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>