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

1.1       misho       1: /* $Id: miniupnpcmodule.c,v 1.38 2021/11/09 18:46:49 nanard Exp $*/
                      2: /* vim: tabstop=4 shiftwidth=4 noexpandtab
                      3:  * Project : miniupnp
                      4:  * Author : Thomas BERNARD
                      5:  * website : https://miniupnp.tuxfamily.org/
                      6:  * copyright (c) 2007-2021 Thomas Bernard
                      7:  * This software is subjet to the conditions detailed in the
                      8:  * provided LICENCE file. */
                      9: #include <Python.h>
                     10: #define MINIUPNP_STATICLIB
                     11: #include <structmember.h>
                     12: #include "miniupnpc.h"
                     13: #include "upnpcommands.h"
                     14: #include "upnperrors.h"
                     15: 
                     16: #ifdef _WIN32
                     17: #include <winsock2.h>
                     18: #endif
                     19: 
                     20: /* for compatibility with Python < 2.4 */
                     21: #ifndef Py_RETURN_NONE
                     22: #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
                     23: #endif
                     24: 
                     25: #ifndef Py_RETURN_TRUE
                     26: #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
                     27: #endif
                     28: 
                     29: #ifndef Py_RETURN_FALSE
                     30: #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
                     31: #endif
                     32: 
                     33: /* for compatibility with Python < 3.0 */
                     34: #ifndef PyVarObject_HEAD_INIT
                     35: #define PyVarObject_HEAD_INIT(type, size) \
                     36:     PyObject_HEAD_INIT(type) size,
                     37: #endif
                     38: 
                     39: #ifndef Py_TYPE
                     40: #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
                     41: #endif
                     42: 
                     43: typedef struct {
                     44:     PyObject_HEAD
                     45:     /* Type-specific fields go here. */
                     46:    struct UPNPDev * devlist;
                     47:    struct UPNPUrls urls;
                     48:    struct IGDdatas data;
                     49:    unsigned int discoverdelay; /* value passed to upnpDiscover() */
                     50:    unsigned int localport;     /* value passed to upnpDiscover() */
                     51:    char lanaddr[40];   /* our ip address on the LAN */
                     52:    char * multicastif;
                     53:    char * minissdpdsocket;
                     54: } UPnPObject;
                     55: 
                     56: static PyMemberDef UPnP_members[] = {
                     57:    {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
                     58:     READONLY, "ip address on the LAN"
                     59:    },
                     60:    {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
                     61:     0/*READWRITE*/, "value in ms used to wait for SSDP responses"
                     62:    },
                     63:    {"localport", T_UINT, offsetof(UPnPObject, localport),
                     64:     0/*READWRITE*/,
                     65:        "If localport is set to UPNP_LOCAL_PORT_SAME(1) "
                     66:        "SSDP packets will be sent from the source port "
                     67:        "1900 (same as destination port), if set to "
                     68:        "UPNP_LOCAL_PORT_ANY(0) system assign a source "
                     69:        "port, any other value will be attempted as the "
                     70:        "source port"
                     71:    },
                     72:    /* T_STRING is always readonly :( */
                     73:    {"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
                     74:     0, "IP of the network interface to be used for multicast operations"
                     75:    },
                     76:    {"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket),
                     77:     0, "path of the MiniSSDPd unix socket"
                     78:    },
                     79:    {NULL}
                     80: };
                     81: 
                     82: 
                     83: static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds)
                     84: {
                     85:    char* multicastif = NULL;
                     86:    char* minissdpdsocket = NULL;
                     87:    static char *kwlist[] = {
                     88:        "multicastif", "minissdpdsocket", "discoverdelay",
                     89:        "localport", NULL
                     90:    };
                     91: 
                     92:    if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist,
                     93:                    &multicastif,
                     94:                    &minissdpdsocket,
                     95:                    &self->discoverdelay,
                     96:                    &self->localport))
                     97:        return -1;
                     98: 
                     99:    if(self->localport>1 &&
                    100:       (self->localport>65534||self->localport<1024)) {
                    101:        PyErr_SetString(PyExc_Exception, "Invalid localport value");
                    102:        return -1;
                    103:    }
                    104:    if(multicastif)
                    105:        self->multicastif = strdup(multicastif);
                    106:    if(minissdpdsocket)
                    107:        self->minissdpdsocket = strdup(minissdpdsocket);
                    108: 
                    109:    return 0;
                    110: }
                    111: 
                    112: static void
                    113: UPnPObject_dealloc(UPnPObject *self)
                    114: {
                    115:    freeUPNPDevlist(self->devlist);
                    116:    FreeUPNPUrls(&self->urls);
                    117:    free(self->multicastif);
                    118:    free(self->minissdpdsocket);
                    119:    Py_TYPE(self)->tp_free((PyObject*)self);
                    120: }
                    121: 
                    122: static PyObject *
                    123: UPnP_discover(UPnPObject *self)
                    124: {
                    125:    int error = 0;
                    126:    PyObject *res = NULL;
                    127: 
                    128:    if(self->devlist)
                    129:    {
                    130:        freeUPNPDevlist(self->devlist);
                    131:        self->devlist = 0;
                    132:    }
                    133:    Py_BEGIN_ALLOW_THREADS
                    134:    self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
                    135:                                 self->multicastif,
                    136:                                 self->minissdpdsocket,
                    137:                                 (int)self->localport,
                    138:                                 0/*ip v6*/,
                    139:                                 2/* TTL */,
                    140:                                 &error);
                    141:    Py_END_ALLOW_THREADS
                    142:    /* Py_RETURN_NONE ??? */
                    143:    if (self->devlist != NULL) {
                    144:        struct UPNPDev * dev;
                    145:        int i = 0;
                    146: 
                    147:        for(dev = self->devlist; dev; dev = dev->pNext)
                    148:            i++;
                    149:        res = Py_BuildValue("i", i);
                    150:        return res;
                    151:    } else {
                    152:        PyErr_SetString(PyExc_Exception, strupnperror(error));
                    153:        return NULL;
                    154:    }
                    155: }
                    156: 
                    157: static PyObject *
                    158: UPnP_selectigd(UPnPObject *self, PyObject *args)
                    159: {
                    160:    const char * rootDescUrl = NULL;
                    161:    int r;
                    162:    if(!PyArg_ParseTuple(args, "|z", &rootDescUrl))
                    163:        return NULL;
                    164: Py_BEGIN_ALLOW_THREADS
                    165:    if (rootDescUrl == NULL) {
                    166:        r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
                    167:                             self->lanaddr, sizeof(self->lanaddr));
                    168:    } else {
                    169:        r = UPNP_GetIGDFromUrl(rootDescUrl, &self->urls, &self->data,
                    170:                               self->lanaddr, sizeof(self->lanaddr));
                    171:    }
                    172: Py_END_ALLOW_THREADS
                    173:    if(r)
                    174:    {
                    175:        return Py_BuildValue("s", self->urls.controlURL);
                    176:    }
                    177:    else
                    178:    {
                    179:        /* TODO: have our own exception type ! */
                    180:        PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
                    181:        return NULL;
                    182:    }
                    183: }
                    184: 
                    185: static PyObject *
                    186: UPnP_totalbytesent(UPnPObject *self)
                    187: {
                    188:    UNSIGNED_INTEGER i;
                    189: Py_BEGIN_ALLOW_THREADS
                    190:    i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
                    191:                               self->data.CIF.servicetype);
                    192: Py_END_ALLOW_THREADS
                    193: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    194:    return Py_BuildValue("I", i);
                    195: #else
                    196:    return Py_BuildValue("i", (int)i);
                    197: #endif
                    198: }
                    199: 
                    200: static PyObject *
                    201: UPnP_totalbytereceived(UPnPObject *self)
                    202: {
                    203:    UNSIGNED_INTEGER i;
                    204: Py_BEGIN_ALLOW_THREADS
                    205:    i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
                    206:                                   self->data.CIF.servicetype);
                    207: Py_END_ALLOW_THREADS
                    208: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    209:    return Py_BuildValue("I", i);
                    210: #else
                    211:    return Py_BuildValue("i", (int)i);
                    212: #endif
                    213: }
                    214: 
                    215: static PyObject *
                    216: UPnP_totalpacketsent(UPnPObject *self)
                    217: {
                    218:    UNSIGNED_INTEGER i;
                    219: Py_BEGIN_ALLOW_THREADS
                    220:    i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
                    221:                                 self->data.CIF.servicetype);
                    222: Py_END_ALLOW_THREADS
                    223: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    224:    return Py_BuildValue("I", i);
                    225: #else
                    226:    return Py_BuildValue("i", (int)i);
                    227: #endif
                    228: }
                    229: 
                    230: static PyObject *
                    231: UPnP_totalpacketreceived(UPnPObject *self)
                    232: {
                    233:    UNSIGNED_INTEGER i;
                    234: Py_BEGIN_ALLOW_THREADS
                    235:    i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
                    236:                                  self->data.CIF.servicetype);
                    237: Py_END_ALLOW_THREADS
                    238: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    239:    return Py_BuildValue("I", i);
                    240: #else
                    241:    return Py_BuildValue("i", (int)i);
                    242: #endif
                    243: }
                    244: 
                    245: static PyObject *
                    246: UPnP_statusinfo(UPnPObject *self)
                    247: {
                    248:    char status[64];
                    249:    char lastconnerror[64];
                    250:    unsigned int uptime = 0;
                    251:    int r;
                    252:    status[0] = '\0';
                    253:    lastconnerror[0] = '\0';
                    254: Py_BEGIN_ALLOW_THREADS
                    255:    r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
                    256:                       status, &uptime, lastconnerror);
                    257: Py_END_ALLOW_THREADS
                    258:    if(r==UPNPCOMMAND_SUCCESS) {
                    259: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    260:        return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
                    261: #else
                    262:        return Py_BuildValue("(s,i,s)", status, (int)uptime, lastconnerror);
                    263: #endif
                    264:    } else {
                    265:        /* TODO: have our own exception type ! */
                    266:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    267:        return NULL;
                    268:    }
                    269: }
                    270: 
                    271: static PyObject *
                    272: UPnP_connectiontype(UPnPObject *self)
                    273: {
                    274:    char connectionType[64];
                    275:    int r;
                    276:    connectionType[0] = '\0';
                    277: Py_BEGIN_ALLOW_THREADS
                    278:    r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
                    279:                                   self->data.first.servicetype,
                    280:                                   connectionType);
                    281: Py_END_ALLOW_THREADS
                    282:    if(r==UPNPCOMMAND_SUCCESS) {
                    283:        return Py_BuildValue("s", connectionType);
                    284:    } else {
                    285:        /* TODO: have our own exception type ! */
                    286:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    287:        return NULL;
                    288:    }
                    289: }
                    290: 
                    291: static PyObject *
                    292: UPnP_externalipaddress(UPnPObject *self)
                    293: {
                    294:    char externalIPAddress[40];
                    295:    int r;
                    296:    externalIPAddress[0] = '\0';
                    297: Py_BEGIN_ALLOW_THREADS
                    298:    r = UPNP_GetExternalIPAddress(self->urls.controlURL,
                    299:                                  self->data.first.servicetype,
                    300:                                  externalIPAddress);
                    301: Py_END_ALLOW_THREADS
                    302:    if(r==UPNPCOMMAND_SUCCESS) {
                    303:        return Py_BuildValue("s", externalIPAddress);
                    304:    } else {
                    305:        /* TODO: have our own exception type ! */
                    306:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    307:        return NULL;
                    308:    }
                    309: }
                    310: 
                    311: /* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
                    312:  *                remoteHost, leaseDuration)
                    313:  * protocol is 'UDP' or 'TCP' */
                    314: static PyObject *
                    315: UPnP_addportmapping(UPnPObject *self, PyObject *args)
                    316: {
                    317:    char extPort[6];
                    318:    unsigned short ePort;
                    319:    char inPort[6];
                    320:    unsigned short iPort;
                    321:    const char * proto;
                    322:    const char * host;
                    323:    const char * desc;
                    324:    const char * remoteHost;
                    325:    unsigned int intLeaseDuration = 0;
                    326:    char strLeaseDuration[12];
                    327:    int r;
                    328: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    329:    if (!PyArg_ParseTuple(args, "HssHzz|I", &ePort, &proto,
                    330:                                         &host, &iPort, &desc, &remoteHost, &intLeaseDuration))
                    331: #else
                    332:    if (!PyArg_ParseTuple(args, "HssHzz|i", &ePort, &proto,
                    333:                                         &host, &iPort, &desc, &remoteHost, (int *)&intLeaseDuration))
                    334: #endif
                    335:         return NULL;
                    336: Py_BEGIN_ALLOW_THREADS
                    337:    sprintf(extPort, "%hu", ePort);
                    338:    sprintf(inPort, "%hu", iPort);
                    339:    sprintf(strLeaseDuration, "%u", intLeaseDuration);
                    340:    r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
                    341:                            extPort, inPort, host, desc, proto,
                    342:                            remoteHost, strLeaseDuration);
                    343: Py_END_ALLOW_THREADS
                    344:    if(r==UPNPCOMMAND_SUCCESS)
                    345:    {
                    346:        Py_RETURN_TRUE;
                    347:    }
                    348:    else
                    349:    {
                    350:        // TODO: RAISE an Exception. See upnpcommands.h for errors codes.
                    351:        // upnperrors.c
                    352:        //Py_RETURN_FALSE;
                    353:        /* TODO: have our own exception type ! */
                    354:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    355:        return NULL;
                    356:    }
                    357: }
                    358: 
                    359: /* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc,
                    360:  *                   remoteHost)
                    361:  * protocol is 'UDP' or 'TCP' */
                    362: static PyObject *
                    363: UPnP_addanyportmapping(UPnPObject *self, PyObject *args)
                    364: {
                    365:    char extPort[6];
                    366:    unsigned short ePort;
                    367:    char inPort[6];
                    368:    unsigned short iPort;
                    369:    char reservedPort[6];
                    370:    const char * proto;
                    371:    const char * host;
                    372:    const char * desc;
                    373:    const char * remoteHost;
                    374:    const char * leaseDuration = "0";
                    375:    int r;
                    376:    if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost))
                    377:         return NULL;
                    378: Py_BEGIN_ALLOW_THREADS
                    379:    sprintf(extPort, "%hu", ePort);
                    380:    sprintf(inPort, "%hu", iPort);
                    381:    r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype,
                    382:                               extPort, inPort, host, desc, proto,
                    383:                               remoteHost, leaseDuration, reservedPort);
                    384: Py_END_ALLOW_THREADS
                    385:    if(r==UPNPCOMMAND_SUCCESS) {
                    386:        return Py_BuildValue("i", atoi(reservedPort));
                    387:    } else {
                    388:        /* TODO: have our own exception type ! */
                    389:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    390:        return NULL;
                    391:    }
                    392: }
                    393: 
                    394: 
                    395: /* DeletePortMapping(extPort, proto, removeHost='')
                    396:  * proto = 'UDP', 'TCP' */
                    397: static PyObject *
                    398: UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
                    399: {
                    400:    char extPort[6];
                    401:    unsigned short ePort;
                    402:    const char * proto;
                    403:    const char * remoteHost = "";
                    404:    int r;
                    405:    if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
                    406:        return NULL;
                    407: Py_BEGIN_ALLOW_THREADS
                    408:    sprintf(extPort, "%hu", ePort);
                    409:    r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
                    410:                               extPort, proto, remoteHost);
                    411: Py_END_ALLOW_THREADS
                    412:    if(r==UPNPCOMMAND_SUCCESS) {
                    413:        Py_RETURN_TRUE;
                    414:    } else {
                    415:        /* TODO: have our own exception type ! */
                    416:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    417:        return NULL;
                    418:    }
                    419: }
                    420: 
                    421: /* DeletePortMappingRange(extPort, proto, removeHost='')
                    422:  * proto = 'UDP', 'TCP' */
                    423: static PyObject *
                    424: UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args)
                    425: {
                    426:    char extPortStart[6];
                    427:    unsigned short ePortStart;
                    428:    char extPortEnd[6];
                    429:    unsigned short ePortEnd;
                    430:    const char * proto;
                    431:    unsigned char manage;
                    432:    char manageStr[6];
                    433:    int r;
                    434:    if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage))
                    435:        return NULL;
                    436: Py_BEGIN_ALLOW_THREADS
                    437:    sprintf(extPortStart, "%hu", ePortStart);
                    438:    sprintf(extPortEnd, "%hu", ePortEnd);
                    439:    sprintf(manageStr, "%hu", (unsigned short)manage);
                    440:    r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype,
                    441:                    extPortStart, extPortEnd, proto, manageStr);
                    442: Py_END_ALLOW_THREADS
                    443:    if(r==UPNPCOMMAND_SUCCESS) {
                    444:        Py_RETURN_TRUE;
                    445:    } else {
                    446:        /* TODO: have our own exception type ! */
                    447:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    448:        return NULL;
                    449:    }
                    450: }
                    451: 
                    452: static PyObject *
                    453: UPnP_getportmappingnumberofentries(UPnPObject *self)
                    454: {
                    455:    unsigned int n = 0;
                    456:    int r;
                    457: Py_BEGIN_ALLOW_THREADS
                    458:    r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
                    459:                                       self->data.first.servicetype,
                    460:                                       &n);
                    461: Py_END_ALLOW_THREADS
                    462:    if(r==UPNPCOMMAND_SUCCESS) {
                    463: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    464:        return Py_BuildValue("I", n);
                    465: #else
                    466:        return Py_BuildValue("i", (int)n);
                    467: #endif
                    468:    } else {
                    469:        /* TODO: have our own exception type ! */
                    470:        PyErr_SetString(PyExc_Exception, strupnperror(r));
                    471:        return NULL;
                    472:    }
                    473: }
                    474: 
                    475: /* GetSpecificPortMapping(ePort, proto, remoteHost='')
                    476:  * proto = 'UDP' or 'TCP' */
                    477: static PyObject *
                    478: UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
                    479: {
                    480:    char extPort[6];
                    481:    unsigned short ePort;
                    482:    const char * proto;
                    483:    const char * remoteHost = "";
                    484:    char intClient[40];
                    485:    char intPort[6];
                    486:    unsigned short iPort;
                    487:    char desc[80];
                    488:    char enabled[4];
                    489:    char leaseDuration[16];
                    490:    if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
                    491:        return NULL;
                    492:    extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
                    493:    desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
                    494: Py_BEGIN_ALLOW_THREADS
                    495:    sprintf(extPort, "%hu", ePort);
                    496:    UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
                    497:                                     self->data.first.servicetype,
                    498:                                     extPort, proto, remoteHost,
                    499:                                     intClient, intPort,
                    500:                                     desc, enabled, leaseDuration);
                    501: Py_END_ALLOW_THREADS
                    502:    if(intClient[0])
                    503:    {
                    504:        iPort = (unsigned short)atoi(intPort);
                    505:        return Py_BuildValue("(s,H,s,O,i)",
                    506:                             intClient, iPort, desc,
                    507:                             PyBool_FromLong(atoi(enabled)),
                    508:                             atoi(leaseDuration));
                    509:    }
                    510:    else
                    511:    {
                    512:        Py_RETURN_NONE;
                    513:    }
                    514: }
                    515: 
                    516: /* GetGenericPortMapping(index) */
                    517: static PyObject *
                    518: UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
                    519: {
                    520:    int i, r;
                    521:    char index[8];
                    522:    char intClient[40];
                    523:    char intPort[6];
                    524:    unsigned short iPort;
                    525:    char extPort[6];
                    526:    unsigned short ePort;
                    527:    char protocol[4];
                    528:    char desc[80];
                    529:    char enabled[6];
                    530:    char rHost[64];
                    531:    char duration[16];  /* lease duration */
                    532:    unsigned int dur;
                    533:    if(!PyArg_ParseTuple(args, "i", &i))
                    534:        return NULL;
                    535: Py_BEGIN_ALLOW_THREADS
                    536:    snprintf(index, sizeof(index), "%d", i);
                    537:    rHost[0] = '\0'; enabled[0] = '\0';
                    538:    duration[0] = '\0'; desc[0] = '\0';
                    539:    extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
                    540:    r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
                    541:                                        self->data.first.servicetype,
                    542:                                        index,
                    543:                                        extPort, intClient, intPort,
                    544:                                        protocol, desc, enabled, rHost,
                    545:                                        duration);
                    546: Py_END_ALLOW_THREADS
                    547:    if(r==UPNPCOMMAND_SUCCESS)
                    548:    {
                    549:        ePort = (unsigned short)atoi(extPort);
                    550:        iPort = (unsigned short)atoi(intPort);
                    551:        dur = (unsigned int)strtoul(duration, 0, 0);
                    552: #if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3)
                    553:        return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
                    554:                             ePort, protocol, intClient, iPort,
                    555:                             desc, enabled, rHost, dur);
                    556: #else
                    557:        return Py_BuildValue("(i,s,(s,i),s,s,s,i)",
                    558:                             (int)ePort, protocol, intClient, (int)iPort,
                    559:                             desc, enabled, rHost, (int)dur);
                    560: #endif
                    561:    }
                    562:    else
                    563:    {
                    564:        Py_RETURN_NONE;
                    565:    }
                    566: }
                    567: 
                    568: /* miniupnpc.UPnP object Method Table */
                    569: static PyMethodDef UPnP_methods[] = {
                    570:     {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
                    571:      "discover UPnP IGD devices on the network"
                    572:     },
                    573:    {"selectigd", (PyCFunction)UPnP_selectigd, METH_VARARGS,
                    574:     "select a valid UPnP IGD among discovered devices"
                    575:    },
                    576:    {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
                    577:     "return the total number of bytes sent by UPnP IGD"
                    578:    },
                    579:    {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
                    580:     "return the total number of bytes received by UPnP IGD"
                    581:    },
                    582:    {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
                    583:     "return the total number of packets sent by UPnP IGD"
                    584:    },
                    585:    {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
                    586:     "return the total number of packets received by UPnP IGD"
                    587:    },
                    588:    {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
                    589:     "return status and uptime"
                    590:    },
                    591:    {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
                    592:     "return IGD WAN connection type"
                    593:    },
                    594:    {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
                    595:     "return external IP address"
                    596:    },
                    597:    {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
                    598:     "add a port mapping"
                    599:    },
                    600:    {"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS,
                    601:     "add a port mapping, IGD to select alternative if necessary"
                    602:    },
                    603:    {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
                    604:     "delete a port mapping"
                    605:    },
                    606:    {"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS,
                    607:     "delete a range of port mappings"
                    608:    },
                    609:    {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
                    610:     "-- non standard --"
                    611:    },
                    612:    {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
                    613:     "get details about a specific port mapping entry"
                    614:    },
                    615:    {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
                    616:     "get all details about the port mapping at index"
                    617:    },
                    618:     {NULL}  /* Sentinel */
                    619: };
                    620: 
                    621: static PyTypeObject UPnPType = {
                    622:     PyVarObject_HEAD_INIT(NULL,
                    623:     0)                         /*ob_size*/
                    624:     "miniupnpc.UPnP",          /*tp_name*/
                    625:     sizeof(UPnPObject),        /*tp_basicsize*/
                    626:     0,                         /*tp_itemsize*/
                    627:     (destructor)UPnPObject_dealloc,/*tp_dealloc*/
                    628:     0,                         /*tp_print*/
                    629:     0,                         /*tp_getattr*/
                    630:     0,                         /*tp_setattr*/
                    631:     0,                         /*tp_compare*/
                    632:     0,                         /*tp_repr*/
                    633:     0,                         /*tp_as_number*/
                    634:     0,                         /*tp_as_sequence*/
                    635:     0,                         /*tp_as_mapping*/
                    636:     0,                         /*tp_hash */
                    637:     0,                         /*tp_call*/
                    638:     0,                         /*tp_str*/
                    639:     0,                         /*tp_getattro*/
                    640:     0,                         /*tp_setattro*/
                    641:     0,                         /*tp_as_buffer*/
                    642:     Py_TPFLAGS_DEFAULT,        /*tp_flags*/
                    643:     "UPnP objects",            /* tp_doc */
                    644:     0,                        /* tp_traverse */
                    645:     0,                        /* tp_clear */
                    646:     0,                        /* tp_richcompare */
                    647:     0,                        /* tp_weaklistoffset */
                    648:     0,                        /* tp_iter */
                    649:     0,                        /* tp_iternext */
                    650:     UPnP_methods,              /* tp_methods */
                    651:     UPnP_members,              /* tp_members */
                    652:     0,                         /* tp_getset */
                    653:     0,                         /* tp_base */
                    654:     0,                         /* tp_dict */
                    655:     0,                         /* tp_descr_get */
                    656:     0,                         /* tp_descr_set */
                    657:     0,                         /* tp_dictoffset */
                    658:     (initproc)UPnP_init,       /* tp_init */
                    659:     0,                         /* tp_alloc */
                    660: #ifndef _WIN32
                    661:     PyType_GenericNew,/*UPnP_new,*/      /* tp_new */
                    662: #else
                    663:     0,                         /* tp_new */
                    664: #endif
                    665:     0,                         /* tp_free */
                    666: };
                    667: 
                    668: /* module methods */
                    669: static PyMethodDef miniupnpc_methods[] = {
                    670:     {NULL}  /* Sentinel */
                    671: };
                    672: 
                    673: #if PY_MAJOR_VERSION >= 3
                    674: static struct PyModuleDef moduledef = {
                    675:     PyModuleDef_HEAD_INIT,
                    676:     "miniupnpc",     /* m_name */
                    677:     "miniupnpc module.",  /* m_doc */
                    678:     -1,                  /* m_size */
                    679:     miniupnpc_methods,    /* m_methods */
                    680:     NULL,                /* m_reload */
                    681:     NULL,                /* m_traverse */
                    682:     NULL,                /* m_clear */
                    683:     NULL,                /* m_free */
                    684: };
                    685: #endif
                    686: 
                    687: #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
                    688: #define PyMODINIT_FUNC void
                    689: #endif
                    690: 
                    691: PyMODINIT_FUNC
                    692: #if PY_MAJOR_VERSION >= 3
                    693: PyInit_miniupnpc(void)
                    694: #else
                    695: initminiupnpc(void)
                    696: #endif
                    697: {
                    698:     PyObject* m;
                    699: 
                    700: #ifdef _WIN32
                    701:     /* initialize Winsock. */
                    702:     WSADATA wsaData;
                    703:     int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
                    704:    if (nResult != 0)
                    705:    {
                    706:        /* error code could be WSASYSNOTREADY WSASYSNOTREADY
                    707:         * WSASYSNOTREADY WSASYSNOTREADY WSASYSNOTREADY */
                    708: #if PY_MAJOR_VERSION >= 3
                    709:         return 0;
                    710: #else
                    711:         return;
                    712: #endif
                    713:    }
                    714: 
                    715:     UPnPType.tp_new = PyType_GenericNew;
                    716: #endif
                    717:     if (PyType_Ready(&UPnPType) < 0)
                    718: #if PY_MAJOR_VERSION >= 3
                    719:         return 0;
                    720: #else
                    721:         return;
                    722: #endif
                    723: 
                    724: #if PY_MAJOR_VERSION >= 3
                    725:     m = PyModule_Create(&moduledef);
                    726: #else
                    727:     m = Py_InitModule3("miniupnpc", miniupnpc_methods,
                    728:                        "miniupnpc module.");
                    729: #endif
                    730: 
                    731:     Py_INCREF(&UPnPType);
                    732:     PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
                    733: 
                    734: #if PY_MAJOR_VERSION >= 3
                    735:     return m;
                    736: #endif
                    737: }
                    738: 

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