Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef ASEBA_ASSERT
00022 #define ASEBA_ASSERT
00023 #endif
00024
00025 #include "../../vm/vm.h"
00026 #include "../../vm/natives.h"
00027 #include "../../common/productids.h"
00028 #include "../../common/consts.h"
00029 #include "../../transport/buffer/vm-buffer.h"
00030 #include <dashel/dashel.h>
00031 #include <iostream>
00032 #include <sstream>
00033 #include <valarray>
00034 #include <cassert>
00035 #include <cstring>
00036
00037 extern AsebaVMDescription nodeDescription;
00038
00039 class AsebaNode: public Dashel::Hub
00040 {
00041 private:
00042 AsebaVMState vm;
00043 std::valarray<unsigned short> bytecode;
00044 std::valarray<signed short> stack;
00045 struct Variables
00046 {
00047 sint16 id;
00048 sint16 source;
00049 sint16 args[32];
00050 sint16 productId;
00051 sint16 user[1024];
00052 } variables;
00053 char mutableName[12];
00054
00055 public:
00056
00057 uint16 lastMessageSource;
00058 std::valarray<uint8> lastMessageData;
00059
00060 Dashel::Stream* stream;
00061
00062 public:
00063
00064 AsebaNode()
00065 {
00066
00067 vm.nodeId = 1;
00068
00069 bytecode.resize(512);
00070 vm.bytecode = &bytecode[0];
00071 vm.bytecodeSize = bytecode.size();
00072
00073 stack.resize(64);
00074 vm.stack = &stack[0];
00075 vm.stackSize = stack.size();
00076
00077 vm.variables = reinterpret_cast<sint16 *>(&variables);
00078 vm.variablesSize = sizeof(variables) / sizeof(sint16);
00079 }
00080
00081 void listen(int basePort, int deltaPort)
00082 {
00083 const int port(basePort + deltaPort);
00084 vm.nodeId = 1 + deltaPort;
00085 strncpy(mutableName, "dummynode-0", 12);
00086 mutableName[10] = '0' + deltaPort;
00087 nodeDescription.name = mutableName;
00088
00089
00090 try
00091 {
00092 std::ostringstream oss;
00093 oss << "tcpin:port=" << port;
00094 Dashel::Hub::connect(oss.str());
00095 }
00096 catch (Dashel::DashelException e)
00097 {
00098 std::cerr << "Cannot create listening port " << port << ": " << e.what() << std::endl;
00099 abort();
00100 }
00101
00102
00103 AsebaVMInit(&vm);
00104 }
00105
00106 virtual void connectionCreated(Dashel::Stream *stream)
00107 {
00108 std::string targetName = stream->getTargetName();
00109 if (targetName.substr(0, targetName.find_first_of(':')) == "tcp")
00110 {
00111 std::cerr << this << " : New client connected." << std::endl;
00112 if (this->stream)
00113 {
00114 closeStream(this->stream);
00115 std::cerr << this << " : Disconnected old client." << std::endl;
00116 }
00117 this->stream = stream;
00118 }
00119 }
00120
00121 virtual void connectionClosed(Dashel::Stream *stream, bool abnormal)
00122 {
00123 this->stream = 0;
00124
00125 vm.breakpointsCount = 0;
00126
00127 if (abnormal)
00128 std::cerr << this << " : Client has disconnected unexpectedly." << std::endl;
00129 else
00130 std::cerr << this << " : Client has disconnected properly." << std::endl;
00131 }
00132
00133 virtual void incomingData(Dashel::Stream *stream)
00134 {
00135 uint16 temp;
00136 uint16 len;
00137
00138 stream->read(&temp, 2);
00139 len = bswap16(temp);
00140 stream->read(&temp, 2);
00141 lastMessageSource = bswap16(temp);
00142 lastMessageData.resize(len+2);
00143 stream->read(&lastMessageData[0], lastMessageData.size());
00144
00145 AsebaProcessIncomingEvents(&vm);
00146 }
00147
00148 virtual void applicationStep()
00149 {
00150
00151 AsebaVMRun(&vm, 65535);
00152
00153
00154 if (AsebaMaskIsClear(vm.flags, ASEBA_VM_STEP_BY_STEP_MASK) || AsebaMaskIsClear(vm.flags, ASEBA_VM_EVENT_ACTIVE_MASK))
00155 AsebaVMSetupEvent(&vm, ASEBA_EVENT_LOCAL_EVENTS_START-0);
00156 }
00157 } node;
00158
00159
00160
00161 extern "C" void AsebaPutVmToSleep(AsebaVMState *vm)
00162 {
00163 std::cerr << "Received request to go into sleep" << std::endl;
00164 }
00165
00166 extern "C" void AsebaSendBuffer(AsebaVMState *vm, const uint8* data, uint16 length)
00167 {
00168 Dashel::Stream* stream = node.stream;
00169 if (stream)
00170 {
00171 try
00172 {
00173 uint16 temp;
00174 temp = bswap16(length - 2);
00175 stream->write(&temp, 2);
00176 temp = bswap16(vm->nodeId);
00177 stream->write(&temp, 2);
00178 stream->write(data, length);
00179 stream->flush();
00180 }
00181 catch (Dashel::DashelException e)
00182 {
00183 std::cerr << "Cannot write to socket: " << stream->getFailReason() << std::endl;
00184 }
00185 }
00186 }
00187
00188 extern "C" uint16 AsebaGetBuffer(AsebaVMState *vm, uint8* data, uint16 maxLength, uint16* source)
00189 {
00190 if (node.lastMessageData.size())
00191 {
00192 *source = node.lastMessageSource;
00193 memcpy(data, &node.lastMessageData[0], node.lastMessageData.size());
00194 }
00195 return node.lastMessageData.size();
00196 }
00197
00198 extern AsebaVMDescription nodeDescription;
00199
00200 extern "C" const AsebaVMDescription* AsebaGetVMDescription(AsebaVMState *vm)
00201 {
00202 return &nodeDescription;
00203 }
00204
00205 static AsebaNativeFunctionPointer nativeFunctions[] =
00206 {
00207 ASEBA_NATIVES_STD_FUNCTIONS,
00208 };
00209
00210 static const AsebaNativeFunctionDescription* nativeFunctionsDescriptions[] =
00211 {
00212 ASEBA_NATIVES_STD_DESCRIPTIONS,
00213 0
00214 };
00215
00216 extern "C" const AsebaNativeFunctionDescription * const * AsebaGetNativeFunctionsDescriptions(AsebaVMState *vm)
00217 {
00218 return nativeFunctionsDescriptions;
00219 }
00220
00221 extern "C" void AsebaNativeFunction(AsebaVMState *vm, uint16 id)
00222 {
00223 nativeFunctions[id](vm);
00224 }
00225
00226
00227 static const AsebaLocalEventDescription localEvents[] = {
00228 { "timer", "periodic timer at 50 Hz" },
00229 { NULL, NULL }
00230 };
00231
00232 extern "C" const AsebaLocalEventDescription * AsebaGetLocalEventsDescriptions(AsebaVMState *vm)
00233 {
00234 return localEvents;
00235 }
00236
00237 extern "C" void AsebaWriteBytecode(AsebaVMState *vm)
00238 {
00239 std::cerr << "Received request to write bytecode into flash" << std::endl;
00240 }
00241
00242 extern "C" void AsebaResetIntoBootloader(AsebaVMState *vm)
00243 {
00244 std::cerr << "Received request to reset into bootloader" << std::endl;
00245 }
00246
00247 extern "C" void AsebaAssert(AsebaVMState *vm, AsebaAssertReason reason)
00248 {
00249 std::cerr << "\nFatal error; exception: ";
00250 switch (reason)
00251 {
00252 case ASEBA_ASSERT_UNKNOWN: std::cerr << "undefined"; break;
00253 case ASEBA_ASSERT_UNKNOWN_BINARY_OPERATOR: std::cerr << "unknown binary operator"; break;
00254 case ASEBA_ASSERT_UNKNOWN_BYTECODE: std::cerr << "unknown bytecode"; break;
00255 case ASEBA_ASSERT_STACK_OVERFLOW: std::cerr << "stack overflow"; break;
00256 case ASEBA_ASSERT_STACK_UNDERFLOW: std::cerr << "stack underflow"; break;
00257 case ASEBA_ASSERT_OUT_OF_VARIABLES_BOUNDS: std::cerr << "out of variables bounds"; break;
00258 case ASEBA_ASSERT_OUT_OF_BYTECODE_BOUNDS: std::cerr << "out of bytecode bounds"; break;
00259 case ASEBA_ASSERT_STEP_OUT_OF_RUN: std::cerr << "step out of run"; break;
00260 case ASEBA_ASSERT_BREAKPOINT_OUT_OF_BYTECODE_BOUNDS: std::cerr << "breakpoint out of bytecode bounds"; break;
00261 default: std::cerr << "unknown exception"; break;
00262 }
00263 std::cerr << ".\npc = " << vm->pc << ", sp = " << vm->sp;
00264 abort();
00265 std::cerr << "\nResetting VM" << std::endl;
00266 AsebaVMInit(vm);
00267 }
00268
00269
00270 int main(int argc, char* argv[])
00271 {
00272 const int basePort = ASEBA_DEFAULT_PORT;
00273 int deltaPort = 0;
00274 if (argc > 1)
00275 {
00276 deltaPort = atoi(argv[1]);
00277 if (deltaPort < 0 || deltaPort >= 9)
00278 {
00279 std::cerr << "Usage: " << argv[0] << " [delta port, from 0 to 9]" << std::endl;
00280 return 1;
00281 }
00282 }
00283 node.listen(basePort, deltaPort);
00284 while (node.step(10))
00285 {
00286 node.applicationStep();
00287 }
00288 }