Annotation of embedaddon/miniupnpc/miniupnpcmodule.c, revision 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>