Navigation



Ignore:
Timestamp:
Dec 16, 2010, 6:56:41 PM (13 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Split interface file in modules

File:
1 edited

Legend:

Unmodified
Added
Removed
  • extensions/dbg_interactive/dbg_interactive.i

    r636 r637  
    4747/* Include standard types & functions used in freeDiameter headers */
    4848%include <stdint.i>
    49 %include <cdata.i>
     49//%include <cdata.i>
    5050%include <cstring.i>
    5151%include <typemaps.i>
    5252
    53 /* Some functions are not available through the wrapper */
    54 %ignore fd_lib_init;
    55 %ignore fd_lib_fini;
    56 /* -- the following functions are better accessed differently, but we leave their definitions just in case
    57 %ignore fd_dict_init;
    58 %ignore fd_dict_fini;
    59 %ignore fd_sess_handler_create_internal;
    60 %ignore fd_sess_handler_destroy;
    61 %ignore fd_sess_new;
    62 %ignore fd_sess_getsid;
    63 %ignore fd_sess_destroy;
    64 %ignore fd_sess_reclaim;
    65 %ignore fd_sess_state_store_internal;
    66 %ignore fd_sess_state_retrieve_internal;
    67 %ignore fd_rtd_init;
    68 %ignore fd_rtd_free;
    69 %ignore fd_rtd_candidate_add;
    70 %ignore fd_rtd_candidate_del;
    71 %ignore fd_rtd_candidate_extract;
    72 %ignore fd_rtd_error_add;
    73 */
    7453
    7554/* Inline functions seems to give problems to SWIG -- just remove the inline definition */
     
    7756%enddef
    7857
     58
    7959/* Make some global-variables read-only (mainly to avoid warnings) */
    8060%immutable fd_g_config;
    8161%immutable peer_state_str;
    8262
    83 
    84 /* Create a generic error handling mechanism so that functions can provoke an exception */
     63/*****************
     64 *  Exceptions  *
     65*****************/
    8566%{
    8667/* This is not thread-safe etc. but it should work /most of the time/. */
     
    128109 ***********************************/
    129110
    130 %apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) };
     111%apply (char *STRING, size_t LENGTH) { ( char * string, size_t len ) }; /* fd_hash */
    131112
     113/* Generic typemap for functions that create something */
    132114%typemap(in, numinputs=0,noblock=1) SWIGTYPE ** OUTPUT (void *temp = NULL) {
    133115        $1 = (void *)&temp;
     
    137119}
    138120
    139 %apply int * OUTPUT { enum dict_object_type * type };
    140 %apply (char *STRING, size_t LENGTH) { (char * sid, size_t len) };
    141 %apply SWIGTYPE ** OUTPUT { struct session ** session };
    142 %apply int * OUTPUT { int * new };
    143 
    144 /* Callbacks defined in python */
     121/* To allow passing callback functions defined in python */
    145122%typemap(in) PyObject *PyCb {
    146123        if (!PyCallable_Check($input)) {
     
    152129
    153130
    154 
    155131/*********************************************************
    156132 Now, create wrappers for (almost) all objects from fD API
     
    160136%include "freeDiameter/freeDiameter.h"
    161137
     138/* Most of the functions from the API are not directly usable "as is".
     139See the specific following files and the dbg_interactive.py.sample file
     140for more usable python-style versions.
     141*/
    162142
     143%include "lists.i"
     144%include "dictionary.i"
     145%include "sessions.i"
     146%include "routing.i"
     147%include "messages.i"
     148%include "dispatch.i"
     149%include "queues.i"
    163150
    164 /**********************************************************/
    165 /* The remaining of this file allows easier manipulation of
    166 the structures and functions of fD by providing wrapper-specific
    167 extensions to the freeDiameter API.
    168 
    169 /****** LISTS *********/
    170 
    171 %extend fd_list {
    172         /* allow a parameter in the constructor, and perform the fd_list_init operation */
    173         fd_list(void * o = NULL) {
    174                 struct fd_list * li;
    175                 li = (struct fd_list *) malloc(sizeof(struct fd_list));
    176                 if (!li) {
    177                         DI_ERROR_MALLOC;
    178                         return NULL;
    179                 }
    180                 fd_list_init(li, o);
    181                 return li;
    182         }
    183         /* Unlink before freeing */
    184         ~fd_list() {
    185                 fd_list_unlink($self);
    186                 free($self);
    187         }
    188         /* For debug, show the values of the list */
    189         void dump() {
    190                 fd_log_debug("list: %p\n", $self);
    191                 fd_log_debug("  - next: %p\n", $self->next);
    192                 fd_log_debug("  - prev: %p\n", $self->prev);
    193                 fd_log_debug("  - head: %p\n", $self->head);
    194                 fd_log_debug("  - o   : %p\n", $self->o);
    195         }
    196 };
    197 
    198 /****** DICTIONARY *********/
    199 
    200 struct dictionary {
    201 };
    202 
    203 %extend dictionary {
    204         dictionary() {
    205                 struct dictionary * r = NULL;
    206                 int ret = fd_dict_init(&r);
    207                 if (ret != 0) {
    208                         DI_ERROR(ret, NULL, NULL);
    209                         return NULL;
    210                 }
    211                 return r;
    212         }
    213         ~dictionary() {
    214                 struct dictionary *d = self;
    215                 int ret = fd_dict_fini(&d);
    216                 if (ret != 0) {
    217                         DI_ERROR(ret, NULL, NULL);
    218                 }
    219                 return;
    220         }
    221         void dump() {
    222                 fd_dict_dump($self);
    223         }
    224         PyObject * vendors_list() {
    225                 uint32_t *list = NULL, *li;
    226                 PyObject * ret;
    227                 SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    228                 ret = PyList_New(0);
    229                 list = fd_dict_get_vendorid_list($self);
    230                 for (li = list; *li != 0; li++) {
    231                         PyList_Append(ret, PyInt_FromLong((long)*li));
    232                 }
    233                 free(list);
    234                 SWIG_PYTHON_THREAD_END_BLOCK;
    235                 return ret;
    236         }
    237         struct dict_object * new_obj(enum dict_object_type type, void * data, struct dict_object * parent = NULL) {
    238                 struct dict_object * obj = NULL;
    239                 int ret = fd_dict_new($self, type, data, parent, &obj);
    240                 if (ret != 0) {
    241                         DI_ERROR(ret, NULL, NULL);
    242                         return NULL;
    243                 }
    244                 return obj;
    245         }
    246         struct dict_object * search(enum dict_object_type type, int criteria, int what_by_val) {
    247                 struct dict_object * obj = NULL;
    248                 int ret = fd_dict_search ( $self, type, criteria, &what_by_val, &obj, ENOENT );
    249                 if (ret != 0) {
    250                         DI_ERROR(ret, NULL, NULL);
    251                         return NULL;
    252                 }
    253                 return obj;
    254         }
    255         struct dict_object * search(enum dict_object_type type, int criteria, char * what_by_string) {
    256                 struct dict_object * obj = NULL;
    257                 int ret = fd_dict_search ( $self, type, criteria, what_by_string, &obj, ENOENT );
    258                 if (ret != 0) {
    259                         DI_ERROR(ret, NULL, NULL);
    260                         return NULL;
    261                 }
    262                 return obj;
    263         }
    264         struct dict_object * search(enum dict_object_type type, int criteria, void * what) {
    265                 struct dict_object * obj = NULL;
    266                 int ret = fd_dict_search ( $self, type, criteria, what, &obj, ENOENT );
    267                 if (ret != 0) {
    268                         DI_ERROR(ret, NULL, NULL);
    269                         return NULL;
    270                 }
    271                 return obj;
    272         }
    273         struct dict_object * error_cmd() {
    274                 struct dict_object * obj = NULL;
    275                 int ret = fd_dict_get_error_cmd ( $self, &obj );
    276                 if (ret != 0) {
    277                         DI_ERROR(ret, NULL, NULL);
    278                         return NULL;
    279                 }
    280                 return obj;
    281         }
    282 }
    283 
    284 struct dict_object {
    285 };
    286 
    287 %extend dict_object {
    288         dict_object() {
    289                 DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be created directly. Use fd_dict_new().");
    290                 return NULL;
    291         }
    292         ~dict_object() {
    293                 DI_ERROR(EINVAL, PyExc_SyntaxError, "dict_object cannot be destroyed directly. Destroy the parent dictionary.");
    294                 return;
    295         }
    296         void dump() {
    297                 fd_dict_dump_object($self);
    298         }
    299         enum dict_object_type gettype() {
    300                 enum dict_object_type t;
    301                 int ret = fd_dict_gettype ( $self, &t);
    302                 if (ret != 0) {
    303                         DI_ERROR(ret, NULL, NULL);
    304                         return 0;
    305                 }
    306                 return t;
    307         }
    308         struct dictionary * getdict() {
    309                 struct dictionary *d;
    310                 int ret = fd_dict_getdict ( $self, &d );
    311                 if (ret != 0) {
    312                         DI_ERROR(ret, NULL, NULL);
    313                         return NULL;
    314                 }
    315                 return d;
    316         }
    317         /* Since casting the pointer requires intelligence, we do it here instead of giving it to SWIG */
    318         PyObject * getval() {
    319                 /* first, get the type */
    320                 enum dict_object_type t;
    321                 int ret = fd_dict_gettype ( $self, &t);
    322                 if (ret != 0) {
    323                         DI_ERROR(ret, NULL, NULL);
    324                         return NULL;
    325                 }
    326                 switch (t) {
    327 %define %GETVAL_CASE(TYPE,STRUCT)
    328                         case TYPE: {
    329                                 PyObject * v = NULL;
    330                                 struct STRUCT * data = NULL;
    331                                 data = malloc(sizeof(struct STRUCT));
    332                                 if (!data) {
    333                                         DI_ERROR_MALLOC;
    334                                         return NULL;
    335                                 }
    336                                 ret = fd_dict_getval($self, data);
    337                                 if (ret != 0) {
    338                                         DI_ERROR(ret, NULL, NULL);
    339                                         free(data);
    340                                         return NULL;
    341                                 }
    342                                 SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    343                                 v = SWIG_NewPointerObj((void *)data, SWIGTYPE_p_##STRUCT, SWIG_POINTER_OWN );
    344                                 Py_XINCREF(v);
    345                                 SWIG_PYTHON_THREAD_END_BLOCK;
    346                                 return v;
    347                         } break
    348 %enddef
    349                         %GETVAL_CASE( DICT_VENDOR,      dict_vendor_data );
    350                         %GETVAL_CASE( DICT_APPLICATION, dict_application_data );
    351                         %GETVAL_CASE( DICT_TYPE,        dict_type_data );
    352                         %GETVAL_CASE( DICT_ENUMVAL,     dict_enumval_data );
    353                         %GETVAL_CASE( DICT_AVP,         dict_avp_data );
    354                         %GETVAL_CASE( DICT_COMMAND,     dict_cmd_data );
    355                         %GETVAL_CASE( DICT_RULE,        dict_rule_data );
    356                         default:
    357                                 DI_ERROR(EINVAL, PyExc_SystemError, "Internal error: Got invalid object type");
    358                 }
    359                 return NULL;
    360         }
    361 }
    362 
    363 
    364 /* The following wrapper leaks memory each time an union avp_value is assigned an octet string.
    365  TODO: fix this leak by better understanding SWIG...
    366    -- the alternative is to uncomment the "free" statements bellow, but then it is easy to
    367    create a segmentation fault by assigning first an integer, then an octetstring.
    368  */
    369 %extend avp_value {
    370         /* The following hack in the proxy file allows assigning the octet string directly like this:
    371         avp_value.os = "blabla"
    372         */
    373         %pythoncode
    374         {
    375     __swig_setmethods__["os"] = _fDpy.avp_value_os_set
    376     if _newclass:os = _swig_property(_fDpy.avp_value_os_get, _fDpy.avp_value_os_set)
    377         }
    378         void os_set(char *STRING, size_t LENGTH) {
    379                 /* free($self->os.data);  -- do not free, in case the previous value was not an OS */
    380                 $self->os.data = malloc(LENGTH);
    381                 if (!$self->os.data) {
    382                         DI_ERROR_MALLOC;
    383                         return;
    384                 }
    385                 memcpy($self->os.data, STRING, LENGTH);
    386                 $self->os.len = LENGTH;
    387         }
    388         void os_set(avp_value_os * os) {
    389                 /* free($self->os.data);  -- do not free, in case the previous value was not an OS */
    390                 $self->os.data = malloc(os->len);
    391                 if (!$self->os.data) {
    392                         DI_ERROR_MALLOC;
    393                         return;
    394                 }
    395                 memcpy($self->os.data, os->data, os->len);
    396                 $self->os.len = os->len;
    397         }
    398 };
    399 
    400 %extend avp_value_os {
    401         void dump() {
    402                 %#define LEN_MAX 20
    403                 int i, n=LEN_MAX;
    404                 if ($self->len < LEN_MAX)
    405                         n = $self->len;
    406                 fd_log_debug("l:%u, v:[", $self->len);
    407                 for (i=0; i < n; i++)
    408                         fd_log_debug("%02.2X", $self->data[i]);
    409                 fd_log_debug("] '%.*s%s'\n", n, $self->data, n == LEN_MAX ? "..." : "");
    410         }
    411 }
    412 
    413 /****** SESSIONS *********/
    414 
    415 %{
    416 /* store the python callback function here */
    417 static PyObject * py_cleanup_cb = NULL;
    418 /* call it (might be called from a different thread than the interpreter, when session times out) */
    419 static void call_the_python_cleanup_callback(session_state * state, char * sid) {
    420         PyObject *result;
    421         if (!py_cleanup_cb)
    422                 return;
    423        
    424         /* Call the function */
    425         SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    426         result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid);
    427         Py_XDECREF(result);
    428         SWIG_PYTHON_THREAD_END_BLOCK;
    429         return;
    430 }
    431 %}
    432 
    433 struct session_handler {
    434 };
    435 
    436 %extend session_handler {
    437         session_handler() {
    438                 DI_ERROR(EINVAL, PyExc_SyntaxError, "a cleanup callback parameter is required.");
    439                 return NULL;
    440         }
    441         session_handler(PyObject * PyCb) {
    442                 struct session_handler * hdl = NULL;
    443                 int ret;
    444                 if (py_cleanup_cb) {
    445                         DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n.");
    446                         return NULL;
    447                 }
    448                 py_cleanup_cb = PyCb;
    449                 Py_XINCREF(py_cleanup_cb);
    450                
    451                 ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback );
    452                 if (ret != 0) {
    453                         DI_ERROR(ret, NULL, NULL);
    454                         return NULL;
    455                 }
    456                 return hdl;
    457         }
    458         ~session_handler() {
    459                 struct session_handler * hdl = self;
    460                 int ret = fd_sess_handler_destroy(&hdl);
    461                 if (ret != 0) {
    462                         DI_ERROR(ret, NULL, NULL);
    463                 }
    464                 /* Now free the callback */
    465                 Py_XDECREF(py_cleanup_cb);
    466                 py_cleanup_cb = NULL;
    467                 return;
    468         }
    469         void dump() {
    470                 fd_sess_dump_hdl(0, $self);
    471         }
    472 }
    473 
    474 struct session {
    475 };
    476 
    477 %extend session {
    478         /* The first two versions create a new session string. The third one allow to use an existing string. */
    479         session() {
    480                 int ret;
    481                 struct session * s = NULL;
    482                 ret = fd_sess_new(&s, fd_g_config->cnf_diamid, "dbg_interactive", sizeof("dbg_interactive"));
    483                 if (ret != 0) {
    484                         DI_ERROR(ret, NULL, NULL);
    485                         return NULL;
    486                 }
    487                 return s;
    488         }
    489         session(char * diamid, char * STRING, size_t LENGTH) {
    490                 int ret;
    491                 struct session * s = NULL;
    492                 ret = fd_sess_new(&s, diamid, STRING, LENGTH);
    493                 if (ret != 0) {
    494                         DI_ERROR(ret, NULL, NULL);
    495                         return NULL;
    496                 }
    497                 return s;
    498         }
    499         session(char * STRING, size_t LENGTH) {
    500                 int ret, n;
    501                 struct session * s = NULL;
    502                 ret = fd_sess_fromsid(STRING, LENGTH, &s, &n);
    503                 if (ret != 0) {
    504                         DI_ERROR(ret, NULL, NULL);
    505                         return NULL;
    506                 }
    507                 /* When defining n as OUTPUT parameter, we get something strange... Use fd_sess_fromsid if you need it */
    508                 #if 0
    509                 if (n) {
    510                         fd_log_debug("A new session has been created\n");
    511                 } else {
    512                         fd_log_debug("A session with same id already existed\n");
    513                 }
    514                 #endif /* 0 */
    515                
    516                 return s;
    517         }
    518         ~session() {
    519                 struct session * s = self;
    520                 int ret = fd_sess_reclaim(&s);
    521                 if (ret != 0) {
    522                         DI_ERROR(ret, NULL, NULL);
    523                 }
    524                 return;
    525         }
    526         char * getsid() {
    527                 int ret;
    528                 char * sid = NULL;
    529                 ret = fd_sess_getsid( $self, &sid);
    530                 if (ret != 0) {
    531                         DI_ERROR(ret, NULL, NULL);
    532                         return NULL;
    533                 }
    534                 return sid;
    535         }
    536         void settimeout(long seconds) {
    537                 struct timespec timeout;
    538                 int ret;
    539                 clock_gettime(CLOCK_REALTIME, &timeout);
    540                 timeout.tv_sec += seconds;
    541                 ret = fd_sess_settimeout( $self, &timeout );
    542                 if (ret != 0) {
    543                         DI_ERROR(ret, NULL, NULL);
    544                 }
    545         }
    546         void dump() {
    547                 fd_sess_dump(0, $self);
    548         }
    549         void store(struct session_handler * handler, PyObject * state) {
    550                 int ret;
    551                 void * store = state;
    552                 Py_XINCREF(state);
    553                 ret = fd_sess_state_store_internal(handler, $self, (void *) &store);
    554                 if (ret != 0) {
    555                         DI_ERROR(ret, NULL, NULL);
    556                 }
    557         }
    558         PyObject *  retrieve(struct session_handler * handler) {
    559                 int ret;
    560                 PyObject * state = NULL;
    561                 ret = fd_sess_state_retrieve_internal(handler, $self, (void *) &state);
    562                 if (ret != 0) {
    563                         DI_ERROR(ret, NULL, NULL);
    564                         return NULL;
    565                 }
    566                 if (state == NULL) {
    567                         Py_INCREF(Py_None);
    568                         return Py_None;
    569                 }
    570                 return state;
    571         }
    572 }       
    573 
    574 /****** ROUTING *********/
    575 
    576 struct rt_data {
    577 };
    578 
    579 %extend rt_data {
    580         rt_data() {
    581                 struct rt_data * r = NULL;
    582                 int ret = fd_rtd_init(&r);
    583                 if (ret != 0) {
    584                         DI_ERROR(ret, NULL, NULL);
    585                         return NULL;
    586                 }
    587                 return r;
    588         }
    589         ~rt_data() {
    590                 struct rt_data *r = self;
    591                 fd_rtd_free(&r);
    592         }
    593         void add(char * peerid, char * realm) {
    594                 int ret = fd_rtd_candidate_add($self, peerid, realm);
    595                 if (ret != 0) {
    596                         DI_ERROR(ret, NULL, NULL);
    597                 }
    598         }
    599         void remove(char * STRING, size_t LENGTH) {
    600                 fd_rtd_candidate_del($self, STRING, LENGTH);
    601         }
    602         void error(char * dest, char * STRING, size_t LENGTH, uint32_t rcode) {
    603                 int ret =  fd_rtd_error_add($self, dest, (uint8_t *)STRING, LENGTH, rcode);
    604                 if (ret != 0) {
    605                         DI_ERROR(ret, NULL, NULL);
    606                 }
    607         }
    608         struct fd_list * extract_li(int score = 0) {
    609                 struct fd_list * li = NULL;
    610                 fd_rtd_candidate_extract($self, &li, score);
    611                 return li;
    612         }
    613         PyObject * extract(int score = 0) {
    614                 struct fd_list * list = NULL, *li;
    615                 PyObject * rl;
    616                 fd_rtd_candidate_extract($self, &list, score);
    617                 rl = PyList_New(0);
    618                 SWIG_PYTHON_THREAD_BEGIN_BLOCK;
    619                 for (li = list->next; li != list; li = li->next) {
    620                         PyList_Append(rl, SWIG_NewPointerObj((void *)li, SWIGTYPE_p_rtd_candidate, 0 ));
    621                 }
    622                 Py_XINCREF(rl);
    623                 SWIG_PYTHON_THREAD_END_BLOCK;
    624                
    625                 return rl;
    626         }
    627 }
    628 
    629 %extend rtd_candidate {
    630         void dump() {
    631                 fd_log_debug("candidate %p\n", $self);
    632                 fd_log_debug("  id : %s\n",  $self->diamid);
    633                 fd_log_debug("  rlm: %s\n", $self->realm);
    634                 fd_log_debug("  sc : %d\n", $self->score);
    635         }
    636 }
    637 
    638 
    639 
    640 /****** MESSAGES *********/
    641 
    642 struct msg {
    643 };
    644 
    645 %extend msg {
    646         msg() {
    647                 DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_COMMAND object parameter (or None) is required.");
    648                 return NULL;
    649         }
    650         msg(struct dict_object * model, int flags = MSGFL_ALLOC_ETEID) {
    651                 struct msg * m = NULL;
    652                 int ret = fd_msg_new( model, flags, &m);
    653                 if (ret != 0) {
    654                         DI_ERROR(ret, NULL, NULL);
    655                 }
    656                 return m;
    657         }
    658         ~msg() {
    659                 int ret = fd_msg_free($self);
    660                 if (ret != 0) {
    661                         DI_ERROR(ret, NULL, NULL);
    662                 }
    663         }
    664         %newobject create_answer;
    665         struct msg * create_answer(struct dictionary * dict = NULL, int flags = 0) {
    666                 /* if dict is not provided, attempt to get it from the request model */
    667                 struct dictionary * d = dict;
    668                 struct msg * m = $self;
    669                 int ret;
    670                 if (!d) {
    671                         struct dict_object * mo = NULL;
    672                         ret = fd_msg_model($self, &mo);
    673                         if (ret != 0) {
    674                                 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
    675                                 return NULL;
    676                         }
    677                         ret = fd_dict_getdict ( mo, &d );
    678                         if (ret != 0) {
    679                                 DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
    680                                 return NULL;
    681                         }
    682                 }
    683                 ret = fd_msg_new_answer_from_req(d, &m, flags);
    684                 if (ret != 0) {
    685                         DI_ERROR(ret, NULL, "Cannot guess the dictionary to use, please provide it as parameter.");
    686                         return NULL;
    687                 }
    688                 return m;
    689         }
    690 }
    691 
    692 struct avp {
    693 };
    694 
    695 %extend avp {
    696         avp() {
    697                 DI_ERROR(EINVAL, PyExc_SyntaxError, "A DICT_AVP object parameter (or None) is required.");
    698                 return NULL;
    699         }
    700         avp(struct dict_object * model, int flags = 0) {
    701                 struct avp * a = NULL;
    702                 int ret = fd_msg_avp_new( model, flags, &a);
    703                 if (ret != 0) {
    704                         DI_ERROR(ret, NULL, NULL);
    705                 }
    706                 return a;
    707         }
    708         ~avp() {
    709                 int ret = fd_msg_free($self);
    710                 if (ret != 0) {
    711                         DI_ERROR(ret, NULL, NULL);
    712                 }
    713         }
    714 }
    715        
    716 
    717 
    718 
    719 %cstring_output_allocate_size(char ** swig_buffer, size_t * swig_len, free(*$1))
    720 %inline %{
    721 int fd_msg_bufferize_py ( struct msg * msg, char ** swig_buffer, size_t * swig_len ) {
    722         return fd_msg_bufferize(msg, (void *)swig_buffer, swig_len);
    723 }
    724 %};
    725 
     151%include "peers.i"
Note: See TracChangeset for help on using the changeset viewer.