vm-buffer.c
Go to the documentation of this file.
00001 /*
00002         Aseba - an event-based framework for distributed robot control
00003         Copyright (C) 2007--2010:
00004                 Stephane Magnenat <stephane at magnenat dot net>
00005                 (http://stephane.magnenat.net)
00006                 and other contributors, see authors.txt for details
00007         
00008         This program is free software: you can redistribute it and/or modify
00009         it under the terms of the GNU Lesser General Public License as published
00010         by the Free Software Foundation, version 3 of the License.
00011         
00012         This program is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU Lesser General Public License for more details.
00016         
00017         You should have received a copy of the GNU Lesser General Public License
00018         along with this program. If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 #include "vm-buffer.h"
00022 #include "../../common/consts.h"
00023 #include "../../common/types.h"
00024 #include <string.h>
00025 #include <assert.h>
00026 
00027 static unsigned char buffer[ASEBA_MAX_INNER_PACKET_SIZE];
00028 static unsigned buffer_pos;
00029 
00030 static void buffer_add(const uint8* data, const uint16 len)
00031 {
00032         uint16 i = 0;
00033         while (i < len)
00034         {
00035                 /* uncomment this to check for buffer overflow in sent packets
00036                 if (buffer_pos >= ASEBA_MAX_INNER_PACKET_SIZE)
00037                 {
00038                         printf("buffer pos %d max size %d\n", buffer_pos, ASEBA_MAX_INNER_PACKET_SIZE);
00039                         abort();
00040                 }*/
00041                 buffer[buffer_pos++] = data[i++];
00042         }
00043 }
00044 
00045 static void buffer_add_uint8(const uint8 value)
00046 {
00047         buffer_add(&value, 1);
00048 }
00049 
00050 static void buffer_add_uint16(const uint16 value)
00051 {
00052         const uint16 temp = bswap16(value);
00053         buffer_add((const unsigned char *) &temp, 2);
00054 }
00055 
00056 static void buffer_add_sint16(const sint16 value)
00057 {
00058         const uint16 temp = bswap16(value);
00059         buffer_add((const unsigned char *) &temp, 2);
00060 }
00061 
00062 static void buffer_add_string(const char* s)
00063 {
00064         uint16 len = strlen(s);
00065         buffer_add_uint8((uint8)len);
00066         while (*s)
00067                 buffer_add_uint8(*s++);
00068 }
00069 
00070 /* implementation of vm hooks */
00071 
00072 void AsebaSendMessage(AsebaVMState *vm, uint16 type, const void *data, uint16 size)
00073 {
00074         uint16 i;
00075 
00076         buffer_pos = 0;
00077         buffer_add_uint16(type);
00078         for (i = 0; i < size; i++)
00079                 buffer_add_uint8(((const unsigned char*)data)[i]);
00080 
00081         AsebaSendBuffer(vm, buffer, buffer_pos);
00082 }
00083 
00084 #ifdef __BIG_ENDIAN__
00085 void AsebaSendMessageWords(AsebaVMState *vm, uint16 type, const uint16* data, uint16 count)
00086 {
00087         uint16 i;
00088         
00089         buffer_pos = 0;
00090         buffer_add_uint16(type);
00091         for (i = 0; i < count; i++)
00092                 buffer_add_uint16(data[i]);
00093         
00094         AsebaSendBuffer(vm, buffer, buffer_pos);
00095 }
00096 #endif
00097 
00098 void AsebaSendVariables(AsebaVMState *vm, uint16 start, uint16 length)
00099 {
00100         uint16 i;
00101 
00102         buffer_pos = 0;
00103         buffer_add_uint16(ASEBA_MESSAGE_VARIABLES);
00104         buffer_add_uint16(start);
00105         for (i = start; i < start + length; i++)
00106                 buffer_add_uint16(vm->variables[i]);
00107 
00108         AsebaSendBuffer(vm, buffer, buffer_pos);
00109 }
00110 
00111 void AsebaSendDescription(AsebaVMState *vm)
00112 {
00113         const AsebaVMDescription *vmDescription = AsebaGetVMDescription(vm);
00114         const AsebaVariableDescription* namedVariables = vmDescription->variables;
00115         const AsebaNativeFunctionDescription* const * nativeFunctionsDescription = AsebaGetNativeFunctionsDescriptions(vm);
00116         const AsebaLocalEventDescription* localEvents = AsebaGetLocalEventsDescriptions(vm);
00117         
00118         uint16 i = 0;
00119         buffer_pos = 0;
00120         
00121         buffer_add_uint16(ASEBA_MESSAGE_DESCRIPTION);
00122 
00123         buffer_add_string(vmDescription->name);
00124         
00125         buffer_add_uint16(ASEBA_PROTOCOL_VERSION);
00126 
00127         buffer_add_uint16(vm->bytecodeSize);
00128         buffer_add_uint16(vm->stackSize);
00129         buffer_add_uint16(vm->variablesSize);
00130 
00131         // compute the number of variables descriptions
00132         for (i = 0; namedVariables[i].size; i++)
00133                 ;
00134         buffer_add_uint16(i);
00135         
00136         // compute the number of local event functions
00137         for (i = 0; localEvents[i].name; i++)
00138                 ;
00139         buffer_add_uint16(i);
00140         
00141         // compute the number of native functions
00142         for (i = 0; nativeFunctionsDescription[i]; i++)
00143                 ;
00144         buffer_add_uint16(i);
00145         
00146         // send buffer
00147         AsebaSendBuffer(vm, buffer, buffer_pos);
00148         
00149         // send named variables description
00150         for (i = 0; namedVariables[i].name; i++)
00151         {
00152                 buffer_pos = 0;
00153                 
00154                 buffer_add_uint16(ASEBA_MESSAGE_NAMED_VARIABLE_DESCRIPTION);
00155                 
00156                 buffer_add_uint16(namedVariables[i].size);
00157                 buffer_add_string(namedVariables[i].name);
00158                 
00159                 // send buffer
00160                 AsebaSendBuffer(vm, buffer, buffer_pos);
00161         }
00162         
00163         // send local events description
00164         for (i = 0; localEvents[i].name; i++)
00165         {
00166                 buffer_pos = 0;
00167                 
00168                 buffer_add_uint16(ASEBA_MESSAGE_LOCAL_EVENT_DESCRIPTION);
00169                 
00170                 buffer_add_string(localEvents[i].name);
00171                 buffer_add_string(localEvents[i].doc);
00172                 
00173                 // send buffer
00174                 AsebaSendBuffer(vm, buffer, buffer_pos);
00175         }
00176         
00177         // send native functions description
00178         for (i = 0; nativeFunctionsDescription[i]; i++)
00179         {
00180                 uint16 j;
00181 
00182                 buffer_pos = 0;
00183                 
00184                 buffer_add_uint16(ASEBA_MESSAGE_NATIVE_FUNCTION_DESCRIPTION);
00185                 
00186                 
00187                 buffer_add_string(nativeFunctionsDescription[i]->name);
00188                 buffer_add_string(nativeFunctionsDescription[i]->doc);
00189                 for (j = 0; nativeFunctionsDescription[i]->arguments[j].size; j++)
00190                         ;
00191                 buffer_add_uint16(j);
00192                 for (j = 0; nativeFunctionsDescription[i]->arguments[j].size; j++)
00193                 {
00194                         buffer_add_sint16(nativeFunctionsDescription[i]->arguments[j].size);
00195                         buffer_add_string(nativeFunctionsDescription[i]->arguments[j].name);
00196                 }
00197                 
00198                 // send buffer
00199                 AsebaSendBuffer(vm, buffer, buffer_pos);
00200         }
00201 }
00202 
00203 void AsebaProcessIncomingEvents(AsebaVMState *vm)
00204 {
00205         uint16 source;
00206         const AsebaVMDescription *desc = AsebaGetVMDescription(vm);
00207         
00208         uint16 amount = AsebaGetBuffer(vm, buffer, ASEBA_MAX_INNER_PACKET_SIZE, &source);
00209 
00210         if (amount > 0)
00211         {
00212                 uint16 type = bswap16(((uint16*)buffer)[0]);
00213                 uint16* payload = (uint16*)(buffer+2);
00214                 uint16 payloadSize = (amount-2)/2;
00215                 if (type < 0x8000)
00216                 {
00217                         // user message, only process if we are not stepping inside an event
00218                         if (AsebaMaskIsClear(vm->flags, ASEBA_VM_STEP_BY_STEP_MASK) || AsebaMaskIsClear(vm->flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00219                         {
00220                                 // by convention. the source begin at variables, address 1
00221                                 // then it's followed by the args
00222                                 uint16 argPos = desc->variables[1].size;
00223                                 uint16 argsSize = desc->variables[2].size;
00224                                 uint16 i;
00225                                 vm->variables[argPos++] = source;
00226                                 for (i = 0; (i < argsSize) && (i < payloadSize); i++)
00227                                         vm->variables[argPos + i] = bswap16(payload[i]);
00228                                 AsebaVMSetupEvent(vm, type);
00229                         }
00230                 }
00231                 else
00232                 {
00233                         // debug message
00234                         AsebaVMDebugMessage(vm, type, payload, payloadSize);
00235                 }
00236         }
00237 }
00238 


aseba
Author(s): Stéphane Magnenat
autogenerated on Thu Jan 2 2014 11:17:17