miniupnpcmodule.c 20 KB

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