00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "simlpy/interpreter_hooks.h"
00032 #include "parsers.h"
00033 #include "PydtnBundle.h"
00034 #include "WrapNode.h"
00035 #include "simlpy/Clock.h"
00036
00037 #include <iostream>
00038 #include <sstream>
00039 #include <netinet/in.h>
00040
00041 #include "simlpy/SimulationException.h"
00042
00045
00046 static PyObject* create_PydtnBundle( DTN::Bundle* b );
00047
00067 static PyObject*
00068 PydtnBundle_new( PyTypeObject* type, PyObject* args, PyObject* kwds )
00069 {
00070 if ( 0 == kwds )
00071 {
00072 PyErr_SetString(PyExc_TypeError,"expected keyword arguments");
00073 return 0;
00074 }
00075 static char* kwlist[] = { "src",
00076 "dest",
00077 "data",
00078 "lifetime",
00079 "app",
00080 "isData",
00081 "isACK",
00082 "isNoACK",
00083 "isBcast",
00084 "isCustodial",
00085 0};
00086 PyObject* srcObj;
00087 PyObject* destObj;
00088 char* data = "";
00089 PyObject* lifetime = 0;
00090 char* app = "";
00091 char isData = 1;
00092 char isACK = 0;
00093 char isNoACK = 0;
00094 char isBcast = 0;
00095 char isCustodial = 1;
00096 if ( ! PyArg_ParseTupleAndKeywords( args, kwds, "OO|sOsbbbbb", kwlist,
00097 &srcObj, &destObj,
00098 &data, &lifetime, &app,
00099 &isData,
00100 &isACK,
00101 &isNoACK,
00102 &isBcast,
00103 &isCustodial ) )
00104 {
00105 return 0;
00106 }
00107
00108 WrapNode* src = 0;
00109 WrapNode* dest = 0;
00110 Time lt;
00111 uint32_t seq;
00112 try
00113 {
00114 src = parse_node( srcObj );
00115 dest = parse_node( destObj );
00116 if ( ( 0 == lifetime ) || ( Py_None == lifetime ) )
00117 {
00118
00119 lt = src->bundleLifetime();
00120 }
00121 else
00122 {
00123 lt = parse_time( lifetime );
00124 }
00125 seq = src->node().nextSeq();
00126 }
00127 catch ( ... )
00128 {
00129 return 0;
00130 }
00131 lt += Clock::time();
00132
00133 DTN::Bundle::BundleType t = 0;
00134 if ( isData ) t |= DTN::Bundle::kData;
00135 if ( isACK ) t |= DTN::Bundle::kACK;
00136 if ( isNoACK ) t |= DTN::Bundle::kNoACK;
00137 if ( isCustodial ) t |= DTN::Bundle::kCustodial;
00138 if ( isBcast ) t |= DTN::Bundle::kBcast;
00139
00140 DTN::ByteString udata;
00141 DTN::ByteString uapp;
00142
00143 for ( unsigned int i = 0 ; i < ::strlen(data) ; ++i )
00144 {
00145 udata += data[i];
00146 }
00147 for ( unsigned int i = 0 ; i < ::strlen(app) ; ++i )
00148 {
00149 uapp += app[i];
00150 }
00151
00152 DTN::Bundle* b = new DTN::Bundle( seq,
00153 src->addr(),
00154 dest->addr(),
00155 udata,
00156 Clock::time().tv,
00157 lt.tv,
00158 t,
00159 uapp );
00160 return create_PydtnBundle(b);
00161 }
00162
00165 static void
00166 PydtnBundle_dealloc( PydtnBundle* self )
00167 {
00168 if ( 0 != self->b ) delete self->b;
00169 self->ob_type->tp_free((PyObject*)self);
00170 }
00171
00175 static PyObject*
00176 PydtnBundle_repr( PyObject* self )
00177 {
00178 if ( 0 == self ) return 0;
00179 DTN::Bundle* b = ((PydtnBundle*)self)->b;
00180 std::stringstream r;
00181 r << "{";
00182 r << " 'source' : '" << stringify(b->source()) << "'," ;
00183 r << " 'seqNum' : " << ::ntohl(b->seqNum()) << "," ;
00184 r << " 'destination' : '" << stringify(b->destination()) << "'," ;
00185 r << " 'size' : " << b->size() << "," ;
00186 r << " 'custodian' : '" << stringify(b->custodian()) << "'," ;
00187 r << " 'send' : '" << stringify(b->send()) << "'," ;
00188 r << " 'recv' : '" << stringify(b->recv()) << "'," ;
00189 r << " 'created' : " << b->created() << "," ;
00190 r << " 'expiry' : " << b->expiry() << "," ;
00191 r << " 'app' : '" << stringify(b->app()) << "'," ;
00192 r << " 'hopCount' : " << b->hopCount() << "," ;
00193 r << " 'expired' : '" << ( b->expired() ? "True" : "False" ) << "'," ;
00194 r << " 'isData' : '" << ( (b->type() & DTN::Bundle::kData) ?
00195 "True" : "False" ) << "'," ;
00196 r << " 'isACK' : '" << ( (b->type() & DTN::Bundle::kACK) ?
00197 "True" : "False" ) << "'," ;
00198 r << " 'isNoACK' : '" << ( (b->type() & DTN::Bundle::kNoACK) ?
00199 "True" : "False" ) << "'," ;
00200 r << " 'isCustodial' : '" << ( (b->type() & DTN::Bundle::kCustodial) ?
00201 "True" : "False" ) << "'," ;
00202 r << " 'isBcast' : '" << ( (b->type() & DTN::Bundle::kBcast) ?
00203 "True" : "False" ) << "'," ;
00204 r << " 'payload' : '" << stringify(b->payload()) << "' ";
00205 r << "}";
00206 return construct_string(r.str());
00207 }
00208
00212 static PyObject*
00213 PydtnBundle_size( PydtnBundle* self )
00214 {
00215 if ( 0 == self ) return 0;
00216 if ( 0 == self->b ) return 0;
00217 return construct_ulong( self->b->size() );
00218 }
00219
00223 static PyObject*
00224 PydtnBundle_seqNum( PydtnBundle* self )
00225 {
00226 if ( 0 == self ) return 0;
00227 if ( 0 == self->b ) return 0;
00228 return construct_ulong( ::ntohl(self->b->seqNum()) );
00229 }
00230
00234 static PyObject*
00235 PydtnBundle_source( PydtnBundle* self )
00236 {
00237 if ( 0 == self ) return 0;
00238 if ( 0 == self->b ) return 0;
00239 return construct_string(stringify(self->b->source()));
00240 }
00241
00245 static PyObject*
00246 PydtnBundle_destination( PydtnBundle* self )
00247 {
00248 if ( 0 == self ) return 0;
00249 if ( 0 == self->b ) return 0;
00250 return construct_string(stringify(self->b->destination()));
00251 }
00252
00256 static PyObject*
00257 PydtnBundle_custodian( PydtnBundle* self )
00258 {
00259 if ( 0 == self ) return 0;
00260 if ( 0 == self->b ) return 0;
00261 return construct_string(stringify(self->b->custodian()));
00262 }
00263
00267 static PyObject*
00268 PydtnBundle_send( PydtnBundle* self )
00269 {
00270 if ( 0 == self ) return 0;
00271 if ( 0 == self->b ) return 0;
00272 return construct_string(stringify(self->b->send()));
00273 }
00274
00278 static PyObject*
00279 PydtnBundle_recv( PydtnBundle* self )
00280 {
00281 if ( 0 == self ) return 0;
00282 if ( 0 == self->b ) return 0;
00283 return construct_string(stringify(self->b->recv()));
00284 }
00285
00289 static PyObject*
00290 PydtnBundle_payload( PydtnBundle* self )
00291 {
00292 if ( 0 == self ) return 0;
00293 if ( 0 == self->b ) return 0;
00294 return construct_string(stringify(self->b->payload()));
00295 }
00296
00300 static PyObject*
00301 PydtnBundle_created( PydtnBundle* self )
00302 {
00303 if ( 0 == self ) return 0;
00304 if ( 0 == self->b ) return 0;
00305 return construct_time(self->b->created());
00306 }
00307
00311 static PyObject*
00312 PydtnBundle_expiry( PydtnBundle* self )
00313 {
00314 if ( 0 == self ) return 0;
00315 if ( 0 == self->b ) return 0;
00316 return construct_time(self->b->expiry());
00317 }
00318
00322 static PyObject*
00323 PydtnBundle_app( PydtnBundle* self )
00324 {
00325 if ( 0 == self ) return 0;
00326 if ( 0 == self->b ) return 0;
00327 return construct_string(stringify(self->b->app()));
00328 }
00329
00333 static PyObject*
00334 PydtnBundle_hopCount( PydtnBundle* self )
00335 {
00336 if ( 0 == self ) return 0;
00337 if ( 0 == self->b ) return 0;
00338 return construct_ulong( self->b->hopCount() );
00339 }
00340
00344 static PyObject*
00345 PydtnBundle_expired( PydtnBundle* self )
00346 {
00347 if ( 0 == self ) return 0;
00348 if ( 0 == self->b ) return 0;
00349 return construct_boolean( self->b->expired() );
00350 }
00351
00355 static PyObject*
00356 PydtnBundle_isData( PydtnBundle* self )
00357 {
00358 if ( 0 == self ) return 0;
00359 if ( 0 == self->b ) return 0;
00360 return construct_boolean( DTN::Bundle::kData & self->b->type() );
00361 }
00362
00366 static PyObject*
00367 PydtnBundle_isACK( PydtnBundle* self )
00368 {
00369 if ( 0 == self ) return 0;
00370 if ( 0 == self->b ) return 0;
00371 return construct_boolean( DTN::Bundle::kACK & self->b->type() );
00372 }
00373
00377 static PyObject*
00378 PydtnBundle_isNoACK( PydtnBundle* self )
00379 {
00380 if ( 0 == self ) return 0;
00381 if ( 0 == self->b ) return 0;
00382 return construct_boolean( DTN::Bundle::kNoACK & self->b->type() );
00383 }
00384
00388 static PyObject*
00389 PydtnBundle_isCustodial( PydtnBundle* self )
00390 {
00391 if ( 0 == self ) return 0;
00392 if ( 0 == self->b ) return 0;
00393 return construct_boolean( DTN::Bundle::kCustodial & self->b->type() );
00394 }
00395
00399 static PyObject*
00400 PydtnBundle_isBcast( PydtnBundle* self )
00401 {
00402 if ( 0 == self ) return 0;
00403 if ( 0 == self->b ) return 0;
00404 return construct_boolean( DTN::Bundle::kBcast & self->b->type() );
00405 }
00406
00408 static char PydtnBundle_doc[] = "Python-accessible version of a bundle.\n\
00409 \n\
00410 This is a non-modifiable version of a bundle. Bundles may be\n\
00411 created by the backend and passed to python, or they may be\n\
00412 created in python with the following syntax:\n\
00413 \n\
00414 b = pydtn.Bundle( **kwargs )\n\
00415 \n\
00416 where **kwargs includes the following (defaults in brackets):\n\
00417 \n\
00418 src = <source node>\n\
00419 dest = <destination node>\n\
00420 data = <payload data string> [\"\"]\n\
00421 lifetime = <bundle lifetime> [src.get('bundle_lifetime')]\n\
00422 app = <application identifier [\"\"]\n\
00423 isData = <boolean> [True]\n\
00424 isACK = <boolean> [False]\n\
00425 isNoACK = <boolean> [False]\n\
00426 isBcast = <boolean> [False]\n\
00427 isCustodial = <boolean> [True]\n\
00428 \n";
00429
00431 static PyMethodDef PydtnBundle_methods[] =
00432 {
00433 { "size", (PyCFunction)PydtnBundle_size, METH_NOARGS,
00434 "returns the total size of the bundle" },
00435 { "seqNum", (PyCFunction)PydtnBundle_seqNum, METH_NOARGS,
00436 "returns the bundle sequence number from the source" },
00437 { "source", (PyCFunction)PydtnBundle_source, METH_NOARGS,
00438 "returns the bundle's source address" },
00439 { "destination", (PyCFunction)PydtnBundle_destination, METH_NOARGS,
00440 "returns the bundle's destination address" },
00441 { "custodian", (PyCFunction)PydtnBundle_custodian, METH_NOARGS,
00442 "returns the address of the current custodian" },
00443 { "send", (PyCFunction)PydtnBundle_send, METH_NOARGS,
00444 "returns the address of the last-hop sender" },
00445 { "recv", (PyCFunction)PydtnBundle_recv, METH_NOARGS,
00446 "returns the address of the last-hop receiver" },
00447 { "payload", (PyCFunction)PydtnBundle_payload, METH_NOARGS,
00448 "returns the bundle payload (ie, the actual data)" },
00449 { "created", (PyCFunction)PydtnBundle_created, METH_NOARGS,
00450 "returns the time at which the bundle was created" },
00451 { "expiry", (PyCFunction)PydtnBundle_expiry, METH_NOARGS,
00452 "returns the time at which the bundle will expire" },
00453 { "app", (PyCFunction)PydtnBundle_app, METH_NOARGS,
00454 "returns the application identifier" },
00455 { "hopCount", (PyCFunction)PydtnBundle_hopCount, METH_NOARGS,
00456 "returns the number of hops the bundle has taken in the network" },
00457 { "expired", (PyCFunction)PydtnBundle_expired, METH_NOARGS,
00458 "(boolean) Has the bundle expired?" },
00459 { "isData", (PyCFunction)PydtnBundle_isData, METH_NOARGS,
00460 "(boolean) Is this a data bundle?" },
00461 { "isACK", (PyCFunction)PydtnBundle_isACK, METH_NOARGS,
00462 "(boolean) Is this an acknowledgment?" },
00463 { "isNoACK", (PyCFunction)PydtnBundle_isNoACK, METH_NOARGS,
00464 "(boolean) Should the destination avoid generating an ACK?" },
00465 { "isCustodial", (PyCFunction)PydtnBundle_isCustodial, METH_NOARGS,
00466 "(boolean) Does this bundle want custody transfer?" },
00467 { "isBcast", (PyCFunction)PydtnBundle_isBcast, METH_NOARGS,
00468 "(boolean) Is this a broadcast bundle?" },
00469 {0}
00470 };
00471
00474 static PyMemberDef PydtnBundle_members[] =
00475 {
00476 {0}
00477 };
00478
00482 static PyTypeObject PydtnBundleType = {
00483 PyObject_HEAD_INIT(0)
00484 0,
00485 "pydtn.Bundle",
00486 sizeof(PydtnBundle),
00487 0,
00488 (destructor)PydtnBundle_dealloc,
00489 0,
00490 0,
00491 0,
00492 0,
00493 PydtnBundle_repr,
00494 0,
00495 0,
00496 0,
00497 0,
00498 0,
00499 0,
00500 0,
00501 0,
00502 0,
00503 Py_TPFLAGS_DEFAULT,
00504 PydtnBundle_doc,
00505 0,
00506 0,
00507 0,
00508 0,
00509 0,
00510 0,
00511 PydtnBundle_methods,
00512 PydtnBundle_members,
00513 0,
00514 0,
00515 0,
00516 0,
00517 0,
00518 0,
00519 0,
00520 0,
00521 PydtnBundle_new,
00522 };
00523
00530 static PyObject*
00531 create_PydtnBundle( DTN::Bundle* b )
00532 {
00533 if ( 0 == b )
00534 {
00535 std::cerr << "Null pointer passed to pydtn.Bundle creator" << std::endl;
00536 return 0;
00537 }
00538 PydtnBundle* self =
00539 (PydtnBundle*)PydtnBundleType.tp_alloc(&PydtnBundleType,0);
00540 if ( 0 == self )
00541 {
00542 std::cerr << "Could not allocate a new pydtn.Bundle" << std::endl;
00543 return 0;
00544 }
00545 self->b = b;
00546 Py_INCREF(self);
00547 return (PyObject*)self;
00548 }
00549
00550 void
00551 addType_PydtnBundle( PyObject* m )
00552 {
00553 if ( 0 == m ) return;
00554 if ( PyType_Ready(&PydtnBundleType) < 0 ) return;
00555 Py_INCREF(&PydtnBundleType);
00556 PyModule_AddObject(m,"Bundle",(PyObject*)&PydtnBundleType);
00557 }
00558
00559 PyObject*
00560 PydtnBundle_wrapBundle( const DTN::Bundle& b )
00561 {
00562 return create_PydtnBundle( b.clone() );
00563 }
00564
00565 int
00566 PydtnBundle_Check( PyObject* o )
00567 {
00568 if ( 0 == o ) return 0;
00569 return PyObject_TypeCheck(o,&PydtnBundleType);
00570 }
00571
00572