Annotation of embedaddon/miniupnpc/miniupnpcmodule.c, revision 1.1.1.1

1.1       misho       1: /* $Id: miniupnpcmodule.c,v 1.18 2011/04/10 11:21:23 nanard Exp $*/
                      2: /* Project : miniupnp
                      3:  * Author : Thomas BERNARD
                      4:  * website : http://miniupnp.tuxfamily.org/
                      5:  * copyright (c) 2007-2009 Thomas Bernard
                      6:  * This software is subjet to the conditions detailed in the
                      7:  * provided LICENCE file. */
                      8: #include <Python.h>
                      9: #define STATICLIB
                     10: #include "structmember.h"
                     11: #include "miniupnpc.h"
                     12: #include "upnpcommands.h"
                     13: #include "upnperrors.h"
                     14: 
                     15: /* for compatibility with Python < 2.4 */
                     16: #ifndef Py_RETURN_NONE
                     17: #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
                     18: #endif
                     19: 
                     20: #ifndef Py_RETURN_TRUE
                     21: #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
                     22: #endif
                     23: 
                     24: #ifndef Py_RETURN_FALSE
                     25: #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
                     26: #endif
                     27: 
                     28: typedef struct {
                     29:     PyObject_HEAD
                     30:     /* Type-specific fields go here. */
                     31:        struct UPNPDev * devlist;
                     32:        struct UPNPUrls urls;
                     33:        struct IGDdatas data;
                     34:        unsigned int discoverdelay;     /* value passed to upnpDiscover() */
                     35:        char lanaddr[40];       /* our ip address on the LAN */
                     36:        char * multicastif;
                     37:        char * minissdpdsocket;
                     38: } UPnPObject;
                     39: 
                     40: static PyMemberDef UPnP_members[] = {
                     41:        {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
                     42:         READONLY, "ip address on the LAN"
                     43:        },
                     44:        {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
                     45:         0/*READWRITE*/, "value in ms used to wait for SSDP responses"
                     46:        },
                     47:        /* T_STRING is allways readonly :( */
                     48:        {"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
                     49:         0, "IP of the network interface to be used for multicast operations"
                     50:        },
                     51:        {"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
                     52:         0, "path of the MiniSSDPd unix socket"
                     53:        },
                     54:        {NULL}
                     55: };
                     56: 
                     57: static void
                     58: UPnPObject_dealloc(UPnPObject *self)
                     59: {
                     60:        freeUPNPDevlist(self->devlist);
                     61:        FreeUPNPUrls(&self->urls);
                     62:        self->ob_type->tp_free((PyObject*)self);
                     63: }
                     64: 
                     65: static PyObject *
                     66: UPnP_discover(UPnPObject *self)
                     67: {
                     68:        struct UPNPDev * dev;
                     69:        int i;
                     70:        PyObject *res = NULL;
                     71:        if(self->devlist)
                     72:        {
                     73:                freeUPNPDevlist(self->devlist);
                     74:                self->devlist = 0;
                     75:        } 
                     76:        Py_BEGIN_ALLOW_THREADS
                     77:        self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
                     78:                                     0/* multicast if*/,
                     79:                                     0/*minissdpd socket*/,
                     80:                                                                 0/*sameport flag*/,
                     81:                                     0/*ip v6*/,
                     82:                                     0/*error */);
                     83:        Py_END_ALLOW_THREADS
                     84:        /* Py_RETURN_NONE ??? */
                     85:        for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
                     86:                i++;
                     87:        res = Py_BuildValue("i", i);
                     88:        return res;
                     89: }
                     90: 
                     91: static PyObject *
                     92: UPnP_selectigd(UPnPObject *self)
                     93: {
                     94:        int r;
                     95: Py_BEGIN_ALLOW_THREADS
                     96:        r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
                     97:                             self->lanaddr, sizeof(self->lanaddr));
                     98: Py_END_ALLOW_THREADS
                     99:        if(r)
                    100:        {
                    101:                return Py_BuildValue("s", self->urls.controlURL);
                    102:        }
                    103:        else
                    104:        {
                    105:                /* TODO: have our own exception type ! */
                    106:                PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
                    107:                return NULL;
                    108:        }
                    109: }
                    110: 
                    111: static PyObject *
                    112: UPnP_totalbytesent(UPnPObject *self)
                    113: {
                    114:        UNSIGNED_INTEGER i;
                    115: Py_BEGIN_ALLOW_THREADS
                    116:        i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
                    117:                                   self->data.CIF.servicetype);
                    118: Py_END_ALLOW_THREADS
                    119:        return Py_BuildValue("I", i);
                    120: }
                    121: 
                    122: static PyObject *
                    123: UPnP_totalbytereceived(UPnPObject *self)
                    124: {
                    125:        UNSIGNED_INTEGER i;
                    126: Py_BEGIN_ALLOW_THREADS
                    127:        i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
                    128:                                           self->data.CIF.servicetype);
                    129: Py_END_ALLOW_THREADS
                    130:        return Py_BuildValue("I", i);
                    131: }
                    132: 
                    133: static PyObject *
                    134: UPnP_totalpacketsent(UPnPObject *self)
                    135: {
                    136:        UNSIGNED_INTEGER i;
                    137: Py_BEGIN_ALLOW_THREADS
                    138:        i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
                    139:                                         self->data.CIF.servicetype);
                    140: Py_END_ALLOW_THREADS
                    141:        return Py_BuildValue("I", i);
                    142: }
                    143: 
                    144: static PyObject *
                    145: UPnP_totalpacketreceived(UPnPObject *self)
                    146: {
                    147:        UNSIGNED_INTEGER i;
                    148: Py_BEGIN_ALLOW_THREADS
                    149:        i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
                    150:                                          self->data.CIF.servicetype);
                    151: Py_END_ALLOW_THREADS
                    152:        return Py_BuildValue("I", i);
                    153: }
                    154: 
                    155: static PyObject *
                    156: UPnP_statusinfo(UPnPObject *self)
                    157: {
                    158:        char status[64];
                    159:        char lastconnerror[64];
                    160:        unsigned int uptime = 0;
                    161:        int r;
                    162:        status[0] = '\0';
                    163:        lastconnerror[0] = '\0';
                    164: Py_BEGIN_ALLOW_THREADS
                    165:        r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
                    166:                           status, &uptime, lastconnerror);
                    167: Py_END_ALLOW_THREADS
                    168:        if(r==UPNPCOMMAND_SUCCESS) {
                    169:                return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
                    170:        } else {
                    171:                /* TODO: have our own exception type ! */
                    172:                PyErr_SetString(PyExc_Exception, strupnperror(r));
                    173:                return NULL;
                    174:        }
                    175: }
                    176: 
                    177: static PyObject *
                    178: UPnP_connectiontype(UPnPObject *self)
                    179: {
                    180:        char connectionType[64];
                    181:        int r;
                    182:        connectionType[0] = '\0';
                    183: Py_BEGIN_ALLOW_THREADS
                    184:        r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
                    185:                                       self->data.first.servicetype,
                    186:                                       connectionType);
                    187: Py_END_ALLOW_THREADS
                    188:        if(r==UPNPCOMMAND_SUCCESS) {
                    189:                return Py_BuildValue("s", connectionType);
                    190:        } else {
                    191:                /* TODO: have our own exception type ! */
                    192:                PyErr_SetString(PyExc_Exception, strupnperror(r));
                    193:                return NULL;
                    194:        }
                    195: }
                    196: 
                    197: static PyObject *
                    198: UPnP_externalipaddress(UPnPObject *self)
                    199: {
                    200:        char externalIPAddress[40];
                    201:        int r;
                    202:        externalIPAddress[0] = '\0';
                    203: Py_BEGIN_ALLOW_THREADS
                    204:        r = UPNP_GetExternalIPAddress(self->urls.controlURL,
                    205:                                      self->data.first.servicetype,
                    206:                                      externalIPAddress);
                    207: Py_END_ALLOW_THREADS
                    208:        if(r==UPNPCOMMAND_SUCCESS) {
                    209:                return Py_BuildValue("s", externalIPAddress);
                    210:        } else {
                    211:                /* TODO: have our own exception type ! */
                    212:                PyErr_SetString(PyExc_Exception, strupnperror(r));
                    213:                return NULL;
                    214:        }
                    215: }
                    216: 
                    217: /* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
                    218:  *                remoteHost) 
                    219:  * protocol is 'UDP' or 'TCP' */
                    220: static PyObject *
                    221: UPnP_addportmapping(UPnPObject *self, PyObject *args)
                    222: {
                    223:        char extPort[6];
                    224:        unsigned short ePort;
                    225:        char inPort[6];
                    226:        unsigned short iPort;
                    227:        const char * proto;
                    228:        const char * host;
                    229:        const char * desc;
                    230:        const char * remoteHost;
                    231:        const char * leaseDuration = "0";
                    232:        int r;
                    233:        if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
                    234:                                             &host, &iPort, &desc, &remoteHost))
                    235:         return NULL;
                    236: Py_BEGIN_ALLOW_THREADS
                    237:        sprintf(extPort, "%hu", ePort);
                    238:        sprintf(inPort, "%hu", iPort);
                    239:        r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
                    240:                                extPort, inPort, host, desc, proto,
                    241:                                remoteHost, leaseDuration);
                    242: Py_END_ALLOW_THREADS
                    243:        if(r==UPNPCOMMAND_SUCCESS)
                    244:        {
                    245:                Py_RETURN_TRUE;
                    246:        }
                    247:        else
                    248:        {
                    249:                // TODO: RAISE an Exception. See upnpcommands.h for errors codes.
                    250:                // upnperrors.c
                    251:                //Py_RETURN_FALSE;
                    252:                /* TODO: have our own exception type ! */
                    253:                PyErr_SetString(PyExc_Exception, strupnperror(r));
                    254:                return NULL;
                    255:        }
                    256: }
                    257: 
                    258: /* DeletePortMapping(extPort, proto, removeHost='')
                    259:  * proto = 'UDP', 'TCP' */
                    260: static PyObject *
                    261: UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
                    262: {
                    263:        char extPort[6];
                    264:        unsigned short ePort;
                    265:        const char * proto;
                    266:        const char * remoteHost = "";
                    267:        int r;
                    268:        if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
                    269:                return NULL;
                    270: Py_BEGIN_ALLOW_THREADS
                    271:        sprintf(extPort, "%hu", ePort);
                    272:        r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
                    273:                                   extPort, proto, remoteHost);
                    274: Py_END_ALLOW_THREADS
                    275:        if(r==UPNPCOMMAND_SUCCESS) {
                    276:                Py_RETURN_TRUE;
                    277:        } else {
                    278:                /* TODO: have our own exception type ! */
                    279:                PyErr_SetString(PyExc_Exception, strupnperror(r));
                    280:                return NULL;
                    281:        }
                    282: }
                    283: 
                    284: static PyObject *
                    285: UPnP_getportmappingnumberofentries(UPnPObject *self)
                    286: {
                    287:        unsigned int n = 0;
                    288:        int r;
                    289: Py_BEGIN_ALLOW_THREADS
                    290:        r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
                    291:                                           self->data.first.servicetype,
                    292:                                                                           &n);
                    293: Py_END_ALLOW_THREADS
                    294:        if(r==UPNPCOMMAND_SUCCESS) {
                    295:                return Py_BuildValue("I", n);
                    296:        } else {
                    297:                /* TODO: have our own exception type ! */
                    298:                PyErr_SetString(PyExc_Exception, strupnperror(r));
                    299:                return NULL;
                    300:        }
                    301: }
                    302: 
                    303: /* GetSpecificPortMapping(ePort, proto) 
                    304:  * proto = 'UDP' or 'TCP' */
                    305: static PyObject *
                    306: UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
                    307: {
                    308:        char extPort[6];
                    309:        unsigned short ePort;
                    310:        const char * proto;
                    311:        char intClient[40];
                    312:        char intPort[6];
                    313:        unsigned short iPort;
                    314:        char desc[80];
                    315:        char enabled[4];
                    316:        char leaseDuration[16];
                    317:        if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
                    318:                return NULL;
                    319:        extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
                    320:        desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
                    321: Py_BEGIN_ALLOW_THREADS
                    322:        sprintf(extPort, "%hu", ePort);
                    323:        UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
                    324:                                         self->data.first.servicetype,
                    325:                                                                         extPort, proto,
                    326:                                                                         intClient, intPort,
                    327:                                         desc, enabled, leaseDuration);
                    328: Py_END_ALLOW_THREADS
                    329:        if(intClient[0])
                    330:        {
                    331:                iPort = (unsigned short)atoi(intPort);
                    332:                return Py_BuildValue("(s,H,s,O,i)",
                    333:                                     intClient, iPort, desc,
                    334:                                     PyBool_FromLong(atoi(enabled)),
                    335:                                     atoi(leaseDuration));
                    336:        }
                    337:        else
                    338:        {
                    339:                Py_RETURN_NONE;
                    340:        }
                    341: }
                    342: 
                    343: /* GetGenericPortMapping(index) */
                    344: static PyObject *
                    345: UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
                    346: {
                    347:        int i, r;
                    348:        char index[8];
                    349:        char intClient[40];
                    350:        char intPort[6];
                    351:        unsigned short iPort;
                    352:        char extPort[6];
                    353:        unsigned short ePort;
                    354:        char protocol[4];
                    355:        char desc[80];
                    356:        char enabled[6];
                    357:        char rHost[64];
                    358:        char duration[16];      /* lease duration */
                    359:        unsigned int dur;
                    360:        if(!PyArg_ParseTuple(args, "i", &i))
                    361:                return NULL;
                    362: Py_BEGIN_ALLOW_THREADS
                    363:        snprintf(index, sizeof(index), "%d", i);
                    364:        rHost[0] = '\0'; enabled[0] = '\0';
                    365:        duration[0] = '\0'; desc[0] = '\0';
                    366:        extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
                    367:        r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
                    368:                                            self->data.first.servicetype,
                    369:                                                                                index,
                    370:                                                                                extPort, intClient, intPort,
                    371:                                                                                protocol, desc, enabled, rHost,
                    372:                                                                                duration);
                    373: Py_END_ALLOW_THREADS
                    374:        if(r==UPNPCOMMAND_SUCCESS)
                    375:        {
                    376:                ePort = (unsigned short)atoi(extPort);
                    377:                iPort = (unsigned short)atoi(intPort);
                    378:                dur = (unsigned int)strtoul(duration, 0, 0);
                    379:                return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
                    380:                                     ePort, protocol, intClient, iPort,
                    381:                                     desc, enabled, rHost, dur);
                    382:        }
                    383:        else
                    384:        {
                    385:                Py_RETURN_NONE;
                    386:        }
                    387: }
                    388: 
                    389: /* miniupnpc.UPnP object Method Table */
                    390: static PyMethodDef UPnP_methods[] = {
                    391:     {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
                    392:      "discover UPnP IGD devices on the network"
                    393:     },
                    394:        {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
                    395:         "select a valid UPnP IGD among discovered devices"
                    396:        },
                    397:        {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
                    398:         "return the total number of bytes sent by UPnP IGD"
                    399:        },
                    400:        {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
                    401:         "return the total number of bytes received by UPnP IGD"
                    402:        },
                    403:        {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
                    404:         "return the total number of packets sent by UPnP IGD"
                    405:        },
                    406:        {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
                    407:         "return the total number of packets received by UPnP IGD"
                    408:        },
                    409:        {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
                    410:         "return status and uptime"
                    411:        },
                    412:        {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
                    413:         "return IGD WAN connection type"
                    414:        },
                    415:        {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
                    416:         "return external IP address"
                    417:        },
                    418:        {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
                    419:         "add a port mapping"
                    420:        },
                    421:        {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
                    422:         "delete a port mapping"
                    423:        },
                    424:        {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
                    425:         "-- non standard --"
                    426:        },
                    427:        {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
                    428:         "get details about a specific port mapping entry"
                    429:        },
                    430:        {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
                    431:         "get all details about the port mapping at index"
                    432:        },
                    433:     {NULL}  /* Sentinel */
                    434: };
                    435: 
                    436: static PyTypeObject UPnPType = {
                    437:     PyObject_HEAD_INIT(NULL)
                    438:     0,                         /*ob_size*/
                    439:     "miniupnpc.UPnP",          /*tp_name*/
                    440:     sizeof(UPnPObject),        /*tp_basicsize*/
                    441:     0,                         /*tp_itemsize*/
                    442:     (destructor)UPnPObject_dealloc,/*tp_dealloc*/
                    443:     0,                         /*tp_print*/
                    444:     0,                         /*tp_getattr*/
                    445:     0,                         /*tp_setattr*/
                    446:     0,                         /*tp_compare*/
                    447:     0,                         /*tp_repr*/
                    448:     0,                         /*tp_as_number*/
                    449:     0,                         /*tp_as_sequence*/
                    450:     0,                         /*tp_as_mapping*/
                    451:     0,                         /*tp_hash */
                    452:     0,                         /*tp_call*/
                    453:     0,                         /*tp_str*/
                    454:     0,                         /*tp_getattro*/
                    455:     0,                         /*tp_setattro*/
                    456:     0,                         /*tp_as_buffer*/
                    457:     Py_TPFLAGS_DEFAULT,        /*tp_flags*/
                    458:     "UPnP objects",            /* tp_doc */
                    459:     0,                            /* tp_traverse */
                    460:     0,                            /* tp_clear */
                    461:     0,                            /* tp_richcompare */
                    462:     0,                            /* tp_weaklistoffset */
                    463:     0,                            /* tp_iter */
                    464:     0,                            /* tp_iternext */
                    465:     UPnP_methods,              /* tp_methods */
                    466:     UPnP_members,              /* tp_members */
                    467:     0,                         /* tp_getset */
                    468:     0,                         /* tp_base */
                    469:     0,                         /* tp_dict */
                    470:     0,                         /* tp_descr_get */
                    471:     0,                         /* tp_descr_set */
                    472:     0,                         /* tp_dictoffset */
                    473:     0,/*(initproc)UPnP_init,*/      /* tp_init */
                    474:     0,                         /* tp_alloc */
                    475: #ifndef WIN32
                    476:     PyType_GenericNew,/*UPnP_new,*/      /* tp_new */
                    477: #else
                    478:     0,
                    479: #endif
                    480: };
                    481: 
                    482: /* module methods */
                    483: static PyMethodDef miniupnpc_methods[] = {
                    484:     {NULL}  /* Sentinel */
                    485: };
                    486: 
                    487: #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
                    488: #define PyMODINIT_FUNC void
                    489: #endif
                    490: PyMODINIT_FUNC
                    491: initminiupnpc(void) 
                    492: {
                    493:     PyObject* m;
                    494: 
                    495: #ifdef WIN32
                    496:     UPnPType.tp_new = PyType_GenericNew;
                    497: #endif
                    498:     if (PyType_Ready(&UPnPType) < 0)
                    499:         return;
                    500: 
                    501:     m = Py_InitModule3("miniupnpc", miniupnpc_methods,
                    502:                        "miniupnpc module.");
                    503: 
                    504:     Py_INCREF(&UPnPType);
                    505:     PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
                    506: }
                    507: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>