aboutsummaryrefslogtreecommitdiff
path: root/external/miniupnpc/miniupnpcmodule.c
diff options
context:
space:
mode:
authorAntonio Juarez <antonio.maria.juarez@live.com>2014-04-09 13:14:35 +0100
committerAntonio Juarez <antonio.maria.juarez@live.com>2014-04-09 13:14:35 +0100
commit9682a15400495ae490543e7e5af242ff5c4c9fa0 (patch)
tree63ba7287d8f679742a244413291d4334fc26b6e6 /external/miniupnpc/miniupnpcmodule.c
parentImprovements in JSON RPC (diff)
downloadmonero-9682a15400495ae490543e7e5af242ff5c4c9fa0.tar.xz
Port mapping with UPnP
Diffstat (limited to 'external/miniupnpc/miniupnpcmodule.c')
-rwxr-xr-xexternal/miniupnpc/miniupnpcmodule.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/external/miniupnpc/miniupnpcmodule.c b/external/miniupnpc/miniupnpcmodule.c
new file mode 100755
index 000000000..4654c9870
--- /dev/null
+++ b/external/miniupnpc/miniupnpcmodule.c
@@ -0,0 +1,545 @@
+/* $Id: miniupnpcmodule.c,v 1.22 2014/01/31 13:18:25 nanard Exp $*/
+/* Project : miniupnp
+ * Author : Thomas BERNARD
+ * website : http://miniupnp.tuxfamily.org/
+ * copyright (c) 2007-2014 Thomas Bernard
+ * This software is subjet to the conditions detailed in the
+ * provided LICENCE file. */
+#include <Python.h>
+#define STATICLIB
+#include "structmember.h"
+#include "miniupnpc.h"
+#include "upnpcommands.h"
+#include "upnperrors.h"
+
+/* for compatibility with Python < 2.4 */
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
+#endif
+
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
+#endif
+
+/* for compatibility with Python < 3.0 */
+#ifndef PyVarObject_HEAD_INIT
+#define PyVarObject_HEAD_INIT(type, size) \
+ PyObject_HEAD_INIT(type) size,
+#endif
+
+#ifndef Py_TYPE
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
+
+typedef struct {
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ struct UPNPDev * devlist;
+ struct UPNPUrls urls;
+ struct IGDdatas data;
+ unsigned int discoverdelay; /* value passed to upnpDiscover() */
+ char lanaddr[40]; /* our ip address on the LAN */
+ char * multicastif;
+ char * minissdpdsocket;
+} UPnPObject;
+
+static PyMemberDef UPnP_members[] = {
+ {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
+ READONLY, "ip address on the LAN"
+ },
+ {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
+ 0/*READWRITE*/, "value in ms used to wait for SSDP responses"
+ },
+ /* T_STRING is allways readonly :( */
+ {"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
+ 0, "IP of the network interface to be used for multicast operations"
+ },
+ {"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
+ 0, "path of the MiniSSDPd unix socket"
+ },
+ {NULL}
+};
+
+static void
+UPnPObject_dealloc(UPnPObject *self)
+{
+ freeUPNPDevlist(self->devlist);
+ FreeUPNPUrls(&self->urls);
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+UPnP_discover(UPnPObject *self)
+{
+ struct UPNPDev * dev;
+ int i;
+ PyObject *res = NULL;
+ if(self->devlist)
+ {
+ freeUPNPDevlist(self->devlist);
+ self->devlist = 0;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
+ 0/* multicast if*/,
+ 0/*minissdpd socket*/,
+ 0/*sameport flag*/,
+ 0/*ip v6*/,
+ 0/*error */);
+ Py_END_ALLOW_THREADS
+ /* Py_RETURN_NONE ??? */
+ for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
+ i++;
+ res = Py_BuildValue("i", i);
+ return res;
+}
+
+static PyObject *
+UPnP_selectigd(UPnPObject *self)
+{
+ int r;
+Py_BEGIN_ALLOW_THREADS
+ r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
+ self->lanaddr, sizeof(self->lanaddr));
+Py_END_ALLOW_THREADS
+ if(r)
+ {
+ return Py_BuildValue("s", self->urls.controlURL);
+ }
+ else
+ {
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
+ return NULL;
+ }
+}
+
+static PyObject *
+UPnP_totalbytesent(UPnPObject *self)
+{
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
+ self->data.CIF.servicetype);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
+}
+
+static PyObject *
+UPnP_totalbytereceived(UPnPObject *self)
+{
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
+ self->data.CIF.servicetype);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
+}
+
+static PyObject *
+UPnP_totalpacketsent(UPnPObject *self)
+{
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
+ self->data.CIF.servicetype);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
+}
+
+static PyObject *
+UPnP_totalpacketreceived(UPnPObject *self)
+{
+ UNSIGNED_INTEGER i;
+Py_BEGIN_ALLOW_THREADS
+ i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
+ self->data.CIF.servicetype);
+Py_END_ALLOW_THREADS
+ return Py_BuildValue("I", i);
+}
+
+static PyObject *
+UPnP_statusinfo(UPnPObject *self)
+{
+ char status[64];
+ char lastconnerror[64];
+ unsigned int uptime = 0;
+ int r;
+ status[0] = '\0';
+ lastconnerror[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
+ r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
+ status, &uptime, lastconnerror);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS) {
+ return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
+ } else {
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, strupnperror(r));
+ return NULL;
+ }
+}
+
+static PyObject *
+UPnP_connectiontype(UPnPObject *self)
+{
+ char connectionType[64];
+ int r;
+ connectionType[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
+ r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
+ self->data.first.servicetype,
+ connectionType);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS) {
+ return Py_BuildValue("s", connectionType);
+ } else {
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, strupnperror(r));
+ return NULL;
+ }
+}
+
+static PyObject *
+UPnP_externalipaddress(UPnPObject *self)
+{
+ char externalIPAddress[40];
+ int r;
+ externalIPAddress[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
+ r = UPNP_GetExternalIPAddress(self->urls.controlURL,
+ self->data.first.servicetype,
+ externalIPAddress);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS) {
+ return Py_BuildValue("s", externalIPAddress);
+ } else {
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, strupnperror(r));
+ return NULL;
+ }
+}
+
+/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
+ * remoteHost)
+ * protocol is 'UDP' or 'TCP' */
+static PyObject *
+UPnP_addportmapping(UPnPObject *self, PyObject *args)
+{
+ char extPort[6];
+ unsigned short ePort;
+ char inPort[6];
+ unsigned short iPort;
+ const char * proto;
+ const char * host;
+ const char * desc;
+ const char * remoteHost;
+ const char * leaseDuration = "0";
+ int r;
+ if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
+ &host, &iPort, &desc, &remoteHost))
+ return NULL;
+Py_BEGIN_ALLOW_THREADS
+ sprintf(extPort, "%hu", ePort);
+ sprintf(inPort, "%hu", iPort);
+ r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
+ extPort, inPort, host, desc, proto,
+ remoteHost, leaseDuration);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS)
+ {
+ Py_RETURN_TRUE;
+ }
+ else
+ {
+ // TODO: RAISE an Exception. See upnpcommands.h for errors codes.
+ // upnperrors.c
+ //Py_RETURN_FALSE;
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, strupnperror(r));
+ return NULL;
+ }
+}
+
+/* DeletePortMapping(extPort, proto, removeHost='')
+ * proto = 'UDP', 'TCP' */
+static PyObject *
+UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
+{
+ char extPort[6];
+ unsigned short ePort;
+ const char * proto;
+ const char * remoteHost = "";
+ int r;
+ if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
+ return NULL;
+Py_BEGIN_ALLOW_THREADS
+ sprintf(extPort, "%hu", ePort);
+ r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
+ extPort, proto, remoteHost);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS) {
+ Py_RETURN_TRUE;
+ } else {
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, strupnperror(r));
+ return NULL;
+ }
+}
+
+static PyObject *
+UPnP_getportmappingnumberofentries(UPnPObject *self)
+{
+ unsigned int n = 0;
+ int r;
+Py_BEGIN_ALLOW_THREADS
+ r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
+ self->data.first.servicetype,
+ &n);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS) {
+ return Py_BuildValue("I", n);
+ } else {
+ /* TODO: have our own exception type ! */
+ PyErr_SetString(PyExc_Exception, strupnperror(r));
+ return NULL;
+ }
+}
+
+/* GetSpecificPortMapping(ePort, proto, remoteHost='')
+ * proto = 'UDP' or 'TCP' */
+static PyObject *
+UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
+{
+ char extPort[6];
+ unsigned short ePort;
+ const char * proto;
+ const char * remoteHost = "";
+ char intClient[40];
+ char intPort[6];
+ unsigned short iPort;
+ char desc[80];
+ char enabled[4];
+ char leaseDuration[16];
+ if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
+ return NULL;
+ extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
+ desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
+Py_BEGIN_ALLOW_THREADS
+ sprintf(extPort, "%hu", ePort);
+ UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
+ self->data.first.servicetype,
+ extPort, proto, remoteHost,
+ intClient, intPort,
+ desc, enabled, leaseDuration);
+Py_END_ALLOW_THREADS
+ if(intClient[0])
+ {
+ iPort = (unsigned short)atoi(intPort);
+ return Py_BuildValue("(s,H,s,O,i)",
+ intClient, iPort, desc,
+ PyBool_FromLong(atoi(enabled)),
+ atoi(leaseDuration));
+ }
+ else
+ {
+ Py_RETURN_NONE;
+ }
+}
+
+/* GetGenericPortMapping(index) */
+static PyObject *
+UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
+{
+ int i, r;
+ char index[8];
+ char intClient[40];
+ char intPort[6];
+ unsigned short iPort;
+ char extPort[6];
+ unsigned short ePort;
+ char protocol[4];
+ char desc[80];
+ char enabled[6];
+ char rHost[64];
+ char duration[16]; /* lease duration */
+ unsigned int dur;
+ if(!PyArg_ParseTuple(args, "i", &i))
+ return NULL;
+Py_BEGIN_ALLOW_THREADS
+ snprintf(index, sizeof(index), "%d", i);
+ rHost[0] = '\0'; enabled[0] = '\0';
+ duration[0] = '\0'; desc[0] = '\0';
+ extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
+ r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
+ self->data.first.servicetype,
+ index,
+ extPort, intClient, intPort,
+ protocol, desc, enabled, rHost,
+ duration);
+Py_END_ALLOW_THREADS
+ if(r==UPNPCOMMAND_SUCCESS)
+ {
+ ePort = (unsigned short)atoi(extPort);
+ iPort = (unsigned short)atoi(intPort);
+ dur = (unsigned int)strtoul(duration, 0, 0);
+ return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
+ ePort, protocol, intClient, iPort,
+ desc, enabled, rHost, dur);
+ }
+ else
+ {
+ Py_RETURN_NONE;
+ }
+}
+
+/* miniupnpc.UPnP object Method Table */
+static PyMethodDef UPnP_methods[] = {
+ {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
+ "discover UPnP IGD devices on the network"
+ },
+ {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
+ "select a valid UPnP IGD among discovered devices"
+ },
+ {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
+ "return the total number of bytes sent by UPnP IGD"
+ },
+ {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
+ "return the total number of bytes received by UPnP IGD"
+ },
+ {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
+ "return the total number of packets sent by UPnP IGD"
+ },
+ {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
+ "return the total number of packets received by UPnP IGD"
+ },
+ {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
+ "return status and uptime"
+ },
+ {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
+ "return IGD WAN connection type"
+ },
+ {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
+ "return external IP address"
+ },
+ {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
+ "add a port mapping"
+ },
+ {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
+ "delete a port mapping"
+ },
+ {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
+ "-- non standard --"
+ },
+ {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
+ "get details about a specific port mapping entry"
+ },
+ {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
+ "get all details about the port mapping at index"
+ },
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject UPnPType = {
+ PyVarObject_HEAD_INIT(NULL,
+ 0) /*ob_size*/
+ "miniupnpc.UPnP", /*tp_name*/
+ sizeof(UPnPObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor)UPnPObject_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "UPnP objects", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ UPnP_methods, /* tp_methods */
+ UPnP_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0,/*(initproc)UPnP_init,*/ /* tp_init */
+ 0, /* tp_alloc */
+#ifndef _WIN32
+ PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
+#else
+ 0,
+#endif
+};
+
+/* module methods */
+static PyMethodDef miniupnpc_methods[] = {
+ {NULL} /* Sentinel */
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "miniupnpc", /* m_name */
+ "miniupnpc module.", /* m_doc */
+ -1, /* m_size */
+ miniupnpc_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+#endif
+
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+
+PyMODINIT_FUNC
+#if PY_MAJOR_VERSION >= 3
+PyInit_miniupnpc(void)
+#else
+initminiupnpc(void)
+#endif
+{
+ PyObject* m;
+
+#ifdef _WIN32
+ UPnPType.tp_new = PyType_GenericNew;
+#endif
+ if (PyType_Ready(&UPnPType) < 0)
+ return;
+
+#if PY_MAJOR_VERSION >= 3
+ m = PyModule_Create(&moduledef);
+#else
+ m = Py_InitModule3("miniupnpc", miniupnpc_methods,
+ "miniupnpc module.");
+#endif
+
+ Py_INCREF(&UPnPType);
+ PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
+
+#if PY_MAJOR_VERSION >= 3
+ return m;
+#endif
+}
+