File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpc / src / miniupnpcmodule.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:21:37 2023 UTC (9 months ago) by misho
Branches: miniupnpc, MAIN
CVS tags: v2_2_5p0, HEAD
Version 2.2.5p0

    1: /* $Id: miniupnpcmodule.c,v 1.1.1.1 2023/09/27 11:21:37 misho 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>