PydtnBundle.cc

00001 // Copyright 2008 Michael Marsh, University of Maryland.
00002 //
00003 // This file is part of pydtn.
00004 //
00005 // pydtn is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // pydtn is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // The views and conclusions contained in the software and documentation
00019 // are those of the authors and should not be interpreted as representing
00020 // official policies, either expressed or implied, of the University
00021 // of Maryland.
00022 //
00023 // pydtn extends and embeds the Python interpreter, which is
00024 // Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025 // and is released under the PSF License Agreement.
00026 //
00027 // RANLUX random number generation uses the Boost library,
00028 // Copyright 1994-2006 by various authors (details in individual files),
00029 // which is released under the Boost Software License, Version 1.0.
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          // get the lifetime from src
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} // sentinel
00470 };
00471 
00474 static PyMemberDef PydtnBundle_members[] =
00475 {
00476    {0} // sentinel
00477 };
00478 
00482 static PyTypeObject PydtnBundleType = {
00483    PyObject_HEAD_INIT(0)
00484    0,                               // ob_size
00485    "pydtn.Bundle",                  // tp_name
00486    sizeof(PydtnBundle),             // tp_basicsize
00487    0,                               // tp_itemsize
00488    (destructor)PydtnBundle_dealloc, // tp_dealloc
00489    0,                               // tp_print
00490    0,                               // tp_getattr
00491    0,                               // tp_setattr
00492    0,                               // tp_compare
00493    PydtnBundle_repr,                // tp_repr
00494    0,                               // tp_as_number
00495    0,                               // tp_as_sequence
00496    0,                               // tp_as_mapping
00497    0,                               // tp_hash
00498    0,                               // tp_call
00499    0,                               // tp_str
00500    0,                               // tp_getattro
00501    0,                               // tp_setattro
00502    0,                               // tp_as_buffer
00503    Py_TPFLAGS_DEFAULT,              // tp_flags
00504    PydtnBundle_doc,                 // tp_doc
00505    0,                               // tp_traverse
00506    0,                               // tp_clear
00507    0,                               // tp_richcompare
00508    0,                               // tp_weaklistoffset
00509    0,                               // tp_iter
00510    0,                               // tp_iternext
00511    PydtnBundle_methods,             // tp_methods
00512    PydtnBundle_members,             // tp_members
00513    0,                               // tp_getset
00514    0,                               // tp_base
00515    0,                               // tp_dict
00516    0,                               // tp_descr_get
00517    0,                               // tp_descr_set
00518    0,                               // tp_dictoffset
00519    0,                               // tp_init
00520    0,                               // tp_alloc
00521    PydtnBundle_new,                 // tp_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 

Generated on Mon Mar 24 11:15:46 2008 for Pydtn Simulator by  doxygen 1.5.4