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