Return to miniupnpcmodule.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / miniupnpc / src |
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: