00001
00021 #include <iostream>
00022 #include <sstream>
00023 #include <list>
00024
00025 #include "urbi/uobject.hh"
00026
00027 #include "urbi/usyncclient.hh"
00028 #include "urbi/uexternal.hh"
00029
00030
00031
00033 namespace urbi
00034 {
00035 UObject* dummyUObject;
00036
00037 STATIC_INSTANCE(UStartlist, objectlist);
00038 STATIC_INSTANCE(UStartlistHub, objecthublist);
00039
00040 UVarTable varmap;
00041 UTable functionmap;
00042 UTable monitormap;
00043 UTable accessmap;
00044 UTable eventmap;
00045 UTable eventendmap;
00046
00047 UTimerTable timermap;
00048 UTimerTable updatemap;
00049
00050 UCallbackAction dispatcher(const UMessage& msg);
00051 UCallbackAction debug(const UMessage& msg);
00052
00053
00054 UVar& cast(UValue& v, UVar*)
00055 {
00056 return (*((UVar*)v.storage));
00057 };
00058
00059
00060 UBinary cast(UValue& v, UBinary*)
00061 {
00062 if (v.type != DATA_BINARY)
00063 return UBinary();
00064 return UBinary(*v.binary);
00065 }
00066
00067
00068 UList cast(UValue& v, UList*)
00069 {
00070 if (v.type != DATA_LIST)
00071 return UList();
00072 return UList(*v.list);
00073 }
00074
00075 UObjectStruct cast(UValue& v, UObjectStruct*)
00076 {
00077 if (v.type != DATA_OBJECT)
00078 return UObjectStruct();
00079 return UObjectStruct(*v.object);
00080 }
00081
00082 const char* cast(UValue &v, const char**)
00083 {
00084 static const char* er = "invalid";
00085 if (v.type != DATA_STRING)
00086 return er;
00087 return v.stringValue->c_str();
00088 }
00089
00090 std::ostream& unarmorAndSend(const char* a);
00091
00092 void uobject_unarmorAndSend(const char* a)
00093 {
00094 unarmorAndSend(a);
00095 }
00096
00097 void send(const char* a)
00098 {
00099 std::ostream& s = getDefaultClient() == 0 ? std::cerr
00100 : ((UAbstractClient*)getDefaultClient())->getStream();
00101 s << a;
00102 }
00103
00104 void send(void* buf, int size)
00105 {
00106 std::ostream& s = getDefaultClient() == 0 ? std::cerr
00107 : ((UAbstractClient*)getDefaultClient())->getStream();
00108 s.rdbuf()->sputn(static_cast<char*> (buf), size);
00109 }
00110
00111
00112
00114 UGenericCallback::UGenericCallback(const std::string& objname,
00115 const std::string& type,
00116 const std::string& name,
00117 int size, UTable& t)
00118 : objname (objname), name (name)
00119 {
00120 nbparam = size;
00121
00122 if (type == "function" || type== "event" || type == "eventend")
00123 {
00124 std::ostringstream oss;
00125 oss << size;
00126 this->name = this->name + "__" + oss.str();
00127 }
00128 t[this->name].push_back(this);
00129
00130 std::cout << "Registering " << type << " " << name << " " << size
00131 << " into " << this->name
00132 << " from " << objname
00133 << std::endl;
00134
00135 if (type == "var")
00136 URBI(()) << "external " << type << " "
00137 << name << " from " << objname << ";";
00138
00139 if (type == "event" || type == "function")
00140 URBI(()) << "external " << type << "(" << size << ") "
00141 << name << " from " << objname << ";";
00142
00143 if (type == "varaccess")
00144 echo("Warning: NotifyAccess facility is not available for modules in "
00145 "remote mode.\n");
00146 };
00147
00149 UGenericCallback::UGenericCallback(const std::string& objname,
00150 const std::string& type,
00151 const std::string& name, UTable& t)
00152 : objname(objname), name(name)
00153 {
00154 t[this->name].push_back(this);
00155 URBI(()) << "external " << type << " " << name << ";";
00156 };
00157
00158 UGenericCallback::~UGenericCallback()
00159 {
00160 };
00161
00162
00163
00165
00166 UTimerCallback::UTimerCallback(const std::string& objname,
00167 ufloat period, UTimerTable& tt)
00168 : period(period),
00169 objname(objname)
00170 {
00171 tt.push_back(this);
00172 lastTimeCalled = -9999999;
00173 std::ostringstream os;
00174 os << "timer"<<tt.size();
00175
00176 std::string cbname = os.str();
00177
00178
00179
00180
00181 new UCallbackvoid0<UTimerCallback> (objname, "event", this,
00182 &UTimerCallback::call,
00183 objname + '.' + cbname, eventmap);
00184
00185 os.str("");
00186 os.clear();
00187 os << "timer_" << objname << ": every(" << period << ") { emit "
00188 << (objname + '.' + cbname) << ";};";
00189 URBI(()) << os.str();
00190 }
00191
00192 UTimerCallback::~UTimerCallback()
00193 {
00194 }
00195
00196
00197
00198
00200 void
00201 UObject::USync(UVar&)
00202 {
00203
00204 }
00205
00206
00208 UObject::UObject(const std::string& s)
00209 : __name(s),
00210 classname(s),
00211 derived(false),
00212 remote (true),
00213 load(s, "load")
00214 {
00215 objecthub = 0;
00216 autogroup = false;
00217
00218 URBI(()) << "class " << __name << "{};";
00219 URBI(()) << "external object " << __name << ";";
00220 period = -1;
00221
00222
00223 load = 1;
00224 }
00225
00227 UObject::UObject(int index)
00228 : derived(false),
00229 remote (true)
00230 {
00231 std::stringstream ss;
00232 ss << "dummy" << index;
00233 __name = ss.str();
00234 classname = __name;
00235 objecthub = 0;
00236 autogroup = false;
00237 period = -1;
00238 }
00239
00240
00243 namespace
00244 {
00245 void
00246 cleanTable(UTable& t, const std::string& name)
00247 {
00248 std::list<UTable::iterator> todelete;
00249 for (UTable::iterator it = t.begin();
00250 it != t.end();
00251 ++it)
00252 {
00253 std::list<UGenericCallback*>& tocheck = (*it).second;
00254 for (std::list<UGenericCallback*>::iterator it2 = tocheck.begin();
00255 it2 != tocheck.end();
00256 )
00257 {
00258 if ((*it2)->objname == name)
00259 {
00260 delete *it2;
00261 it2 = tocheck.erase(it2);
00262 }
00263 else
00264 ++it2;
00265 }
00266
00267 if (tocheck.empty())
00268 todelete.push_back(it);
00269 }
00270
00271 for (std::list<UTable::iterator>::iterator dit = todelete.begin();
00272 dit != todelete.end();
00273 ++dit)
00274 t.erase(*dit);
00275 }
00276 }
00277
00279 void
00280 UObject::clean()
00281 {
00282 cleanTable(monitormap, __name);
00283 cleanTable(accessmap, __name);
00284 cleanTable(functionmap, __name);
00285 cleanTable(eventmap, __name);
00286 cleanTable(eventendmap, __name);
00287
00288 if (objecthub)
00289 objecthub->members.remove(this);
00290 }
00291
00292
00294 UObject::~UObject()
00295 {
00296 clean();
00297 }
00298
00299 void
00300 UObject::UJoinGroup(const std::string& gpname)
00301 {
00302 std::string groupregister = "addgroup " + gpname +" { "+__name+"};";
00303 uobject_unarmorAndSend(groupregister.c_str());
00304 }
00305
00306 void
00307 UObject::USetUpdate(ufloat t)
00308 {
00309 std::ostringstream os;
00310 if (period != -1)
00311 {
00312
00313 os << "stop maintimer_" << __name << ";";
00314 URBI(())<<os.str();
00315 }
00316 period = t;
00317 if (period <= 0)
00318 period = 1;
00319 std::string cbname = __name + ".maintimer";
00320 createUCallback(__name, "event",
00321 this, &UObject::update, cbname, eventmap);
00322 os.str("");
00323 os.clear();
00324 os << "maintimer_" << __name << ": every(" << period << ") "
00325 "{ emit "<<cbname<<";};";
00326 URBI(()) << os.str();
00327 }
00328
00329
00330
00331
00332 UCallbackAction
00333 dispatcher(const UMessage& msg)
00334 {
00335
00336 if (msg.type != MESSAGE_DATA || msg.value->type != DATA_LIST)
00337 {
00338 msg.client.printf("Component Error: "
00339 "unknown message content, type %d\n",
00340 (int) msg.type);
00341 return URBI_CONTINUE;
00342 }
00343
00344 UList& array = *msg.value->list;
00345
00346 if (array.size()<2)
00347 {
00348 msg.client.printf("Component Error: Invalid number "
00349 "of arguments in the server message: %d\n",
00350 array.size());
00351 return URBI_CONTINUE;
00352 }
00353
00354 if (array[0].type != DATA_DOUBLE)
00355 {
00356 msg.client.printf("Component Error: "
00357 "unknown server message type %d\n",
00358 (int) array[0].type);
00359 return URBI_CONTINUE;
00360 }
00361
00362
00363 if ((USystemExternalMessage)(int)array[0] == UEM_ASSIGNVALUE)
00364 {
00365 UVarTable::iterator varmapfind = varmap.find(array[1]);
00366 if (varmapfind != varmap.end())
00367 for (std::list<UVar*>::iterator it = varmapfind->second.begin();
00368 it != varmapfind->second.end();
00369 ++it)
00370 (*it)->__update(array[2]);
00371
00372 UTable::iterator monitormapfind = monitormap.find(array[1]);
00373 for (std::list<UGenericCallback*>::iterator
00374 cbit = monitormapfind->second.begin();
00375 cbit != monitormapfind->second.end();
00376 ++cbit)
00377 {
00378
00379 UList u;
00380 u.array.push_back(new UValue());
00381 u[0].storage = (*cbit)->storage;
00382 (*cbit)->__evalcall(u);
00383 }
00384 }
00385
00386
00387 else if ((USystemExternalMessage)(int)array[0] == UEM_EVALFUNCTION)
00388 {
00389
00390
00391
00392
00393 if (functionmap.find(array[1]) != functionmap.end())
00394 {
00395 std::list<UGenericCallback*> tmpfun = functionmap[array[1]];
00396 std::list<UGenericCallback*>::iterator tmpfunit = tmpfun.begin();
00397 array.setOffset(3);
00398 UValue retval = (*tmpfunit)->__evalcall(array);
00399 array.setOffset(0);
00400 if (retval.type == DATA_VOID)
00401 URBI(()) << "var " << (std::string) array[2];
00402 else
00403 {
00404 URBI(()) << (std::string) array[2] << "=";
00405 getDefaultClient()->send(retval);
00406 }
00407 URBI(()) << ";";
00408 }
00409 else
00410 msg.client.printf("Component Error: %s function unknown.\n",
00411 ((std::string) array[1]).c_str());
00412 }
00413
00414
00415 else if ((USystemExternalMessage)(int)array[0] == UEM_EMITEVENT)
00416 {
00417 if (eventmap.find(array[1]) != eventmap.end())
00418 {
00419 std::list<UGenericCallback*> tmpfun = eventmap[array[1]];
00420 for (std::list<UGenericCallback*>::iterator tmpfunit = tmpfun.begin();
00421 tmpfunit != tmpfun.end();
00422 ++tmpfunit)
00423 {
00424 array.setOffset(2);
00425 (*tmpfunit)->__evalcall(array);
00426 array.setOffset(0);
00427 }
00428 }
00429 }
00430
00431
00432 else if ((USystemExternalMessage)(int)array[0] == UEM_ENDEVENT)
00433 {
00434 if (eventendmap.find(array[1]) != eventendmap.end())
00435 {
00436 std::list<UGenericCallback*> tmpfun = eventendmap[array[1]];
00437 for (std::list<UGenericCallback*>::iterator tmpfunit = tmpfun.begin();
00438 tmpfunit != tmpfun.end();
00439 ++tmpfunit)
00440 {
00441 array.setOffset(2);
00442 (*tmpfunit)->__evalcall(array);
00443 array.setOffset(0);
00444 }
00445 }
00446 }
00447
00448
00449 else if ((USystemExternalMessage)(int)array[0] == UEM_NEW)
00450 {
00451 std::list<baseURBIStarter*>::iterator found = objectlist->end();
00452 for (std::list<baseURBIStarter*>::iterator retr = objectlist->begin();
00453 retr != objectlist->end();
00454 ++retr)
00455 if ((*retr)->name == (std::string)array[2])
00456 if (found != objectlist->end())
00457 msg.client.printf("Double object definition %s\n",
00458 (*retr)->name.c_str());
00459 else
00460 found = retr;
00461
00462 if (found == objectlist->end())
00463 msg.client.printf("Unknown object definition %s\n",
00464 ((std::string) array[2]).c_str());
00465 else
00466 (*found)->copy((std::string) array[1]);
00467
00468 }
00469
00470
00471 else if ((USystemExternalMessage)(int)array[0] == UEM_DELETE)
00472 {
00473 std::list<baseURBIStarter*>::iterator found = objectlist->end();
00474 for (std::list<baseURBIStarter*>::iterator retr = objectlist->begin();
00475 retr != objectlist->end();
00476 ++retr)
00477 if ((*retr)->name == (std::string)array[1])
00478 if (found != objectlist->end())
00479 msg.client.printf("Double object definition %s\n",
00480 (*retr)->name.c_str());
00481 else
00482 found = retr;
00483
00484 if (found == objectlist->end())
00485 msg.client.printf("Unknown object definition %s\n",
00486 ((std::string) array[1]).c_str());
00487 else
00488 {
00489
00490
00491 if (objectlist->size() == 1)
00492 exit(0);
00493 else
00494 {
00495
00496 delete (*found);
00497 }
00498 }
00499 }
00500
00501
00502
00503 else
00504 msg.client.printf("Component Error: "
00505 "unknown server message type number %d\n",
00506 (int)array[0]);
00507
00508 return URBI_CONTINUE;
00509 }
00510
00511
00512
00513
00514
00516 UObjectHub::UObjectHub(const std::string& s) : name(s)
00517 {
00518 }
00519
00521 UObjectHub::~UObjectHub()
00522 {
00523 }
00524
00525 void
00526 UObjectHub::USetUpdate(ufloat t)
00527 {
00528 period = t;
00529
00530 }
00531
00532 int
00533 UObjectHub::updateGlobal()
00534 {
00535 for (UObjectList::iterator it = members.begin();
00536 it != members.end();
00537 ++it)
00538 (*it)->update();
00539 update();
00540 return 0;
00541 }
00542
00543 void
00544 UObjectHub::addMember(UObject* obj)
00545 {
00546 members.push_back(obj);
00547 }
00548
00549 UObjectList*
00550 UObjectHub::getSubClass(const std::string& subclass)
00551 {
00552 UObjectList* res = new UObjectList();
00553 for (UObjectList::iterator it = members.begin();
00554 it != members.end();
00555 ++it)
00556 if ((*it)->classname == subclass)
00557 res->push_back(*it);
00558
00559 return res;
00560 }
00561
00562
00564 UObjectHub*
00565 getUObjectHub(const std::string& name)
00566 {
00567 for (UStartlistHub::iterator retr = objecthublist->begin();
00568 retr != objecthublist->end();
00569 ++retr)
00570 if ((*retr)->name == name)
00571 return (*retr)->getUObjectHub();
00572
00573 return 0;
00574 }
00575
00577 UObject*
00578 getUObject(const std::string& name)
00579 {
00580 for (UStartlist::iterator retr = objectlist->begin();
00581 retr != objectlist->end();
00582 ++retr)
00583 if ((*retr)->name == name)
00584 return (*retr)->getUObject();
00585
00586 return 0;
00587 }
00588
00590 void
00591 echo(const char* format, ...)
00592 {
00593 va_list arg;
00594 va_start(arg, format);
00595 vfprintf(stderr, format, arg);
00596 va_end(arg);
00597 }
00598
00599
00600
00601
00602
00603
00604 UCallbackAction
00605 debug(const UMessage& msg)
00606 {
00607 std::stringstream mesg;
00608 mesg<<msg;
00609 msg.client.printf("DEBUG: got a message : %s\n",
00610 mesg.str().c_str());
00611
00612 return URBI_CONTINUE;
00613 }
00614
00615
00616 void
00617 main(int argc, char* argv[])
00618 {
00619
00620 if (argc!=2)
00621 {
00622 std::cout << "usage:\n"
00623 << argv[0] << " <URBI Server IP>" << std::endl;
00624 exit(0);
00625 }
00626
00627
00628 std::cout << "Running Remote Component '" << argv[0]
00629 << "' on " << argv[1] << std::endl;
00630
00631 new USyncClient(argv[1]);
00632
00633
00634 #ifdef LIBURBIDEBUG
00635 getDefaultClient()->setWildcardCallback( callback (&debug));
00636 #else
00637 getDefaultClient()->setErrorCallback( callback (&debug));
00638 #endif
00639
00640 getDefaultClient()->setCallback(&dispatcher,
00641 externalModuleTag.c_str());
00642
00643 dummyUObject = new UObject (0);
00644 for (UStartlist::iterator retr = objectlist->begin();
00645 retr != objectlist->end();
00646 ++retr)
00647 (*retr)->init((*retr)->name);
00648 }
00649
00650 }