$search
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