Annotation of embedaddon/miniupnpc/miniupnpcmodule.c, revision 1.1
1.1 ! misho 1: /* $Id: miniupnpcmodule.c,v 1.18 2011/04/10 11:21:23 nanard Exp $*/
! 2: /* Project : miniupnp
! 3: * Author : Thomas BERNARD
! 4: * website : http://miniupnp.tuxfamily.org/
! 5: * copyright (c) 2007-2009 Thomas Bernard
! 6: * This software is subjet to the conditions detailed in the
! 7: * provided LICENCE file. */
! 8: #include <Python.h>
! 9: #define STATICLIB
! 10: #include "structmember.h"
! 11: #include "miniupnpc.h"
! 12: #include "upnpcommands.h"
! 13: #include "upnperrors.h"
! 14:
! 15: /* for compatibility with Python < 2.4 */
! 16: #ifndef Py_RETURN_NONE
! 17: #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
! 18: #endif
! 19:
! 20: #ifndef Py_RETURN_TRUE
! 21: #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
! 22: #endif
! 23:
! 24: #ifndef Py_RETURN_FALSE
! 25: #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
! 26: #endif
! 27:
! 28: typedef struct {
! 29: PyObject_HEAD
! 30: /* Type-specific fields go here. */
! 31: struct UPNPDev * devlist;
! 32: struct UPNPUrls urls;
! 33: struct IGDdatas data;
! 34: unsigned int discoverdelay; /* value passed to upnpDiscover() */
! 35: char lanaddr[40]; /* our ip address on the LAN */
! 36: char * multicastif;
! 37: char * minissdpdsocket;
! 38: } UPnPObject;
! 39:
! 40: static PyMemberDef UPnP_members[] = {
! 41: {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr),
! 42: READONLY, "ip address on the LAN"
! 43: },
! 44: {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay),
! 45: 0/*READWRITE*/, "value in ms used to wait for SSDP responses"
! 46: },
! 47: /* T_STRING is allways readonly :( */
! 48: {"multicastif", T_STRING, offsetof(UPnPObject, multicastif),
! 49: 0, "IP of the network interface to be used for multicast operations"
! 50: },
! 51: {"minissdpdsocket", T_STRING, offsetof(UPnPObject, multicastif),
! 52: 0, "path of the MiniSSDPd unix socket"
! 53: },
! 54: {NULL}
! 55: };
! 56:
! 57: static void
! 58: UPnPObject_dealloc(UPnPObject *self)
! 59: {
! 60: freeUPNPDevlist(self->devlist);
! 61: FreeUPNPUrls(&self->urls);
! 62: self->ob_type->tp_free((PyObject*)self);
! 63: }
! 64:
! 65: static PyObject *
! 66: UPnP_discover(UPnPObject *self)
! 67: {
! 68: struct UPNPDev * dev;
! 69: int i;
! 70: PyObject *res = NULL;
! 71: if(self->devlist)
! 72: {
! 73: freeUPNPDevlist(self->devlist);
! 74: self->devlist = 0;
! 75: }
! 76: Py_BEGIN_ALLOW_THREADS
! 77: self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/,
! 78: 0/* multicast if*/,
! 79: 0/*minissdpd socket*/,
! 80: 0/*sameport flag*/,
! 81: 0/*ip v6*/,
! 82: 0/*error */);
! 83: Py_END_ALLOW_THREADS
! 84: /* Py_RETURN_NONE ??? */
! 85: for(dev = self->devlist, i = 0; dev; dev = dev->pNext)
! 86: i++;
! 87: res = Py_BuildValue("i", i);
! 88: return res;
! 89: }
! 90:
! 91: static PyObject *
! 92: UPnP_selectigd(UPnPObject *self)
! 93: {
! 94: int r;
! 95: Py_BEGIN_ALLOW_THREADS
! 96: r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data,
! 97: self->lanaddr, sizeof(self->lanaddr));
! 98: Py_END_ALLOW_THREADS
! 99: if(r)
! 100: {
! 101: return Py_BuildValue("s", self->urls.controlURL);
! 102: }
! 103: else
! 104: {
! 105: /* TODO: have our own exception type ! */
! 106: PyErr_SetString(PyExc_Exception, "No UPnP device discovered");
! 107: return NULL;
! 108: }
! 109: }
! 110:
! 111: static PyObject *
! 112: UPnP_totalbytesent(UPnPObject *self)
! 113: {
! 114: UNSIGNED_INTEGER i;
! 115: Py_BEGIN_ALLOW_THREADS
! 116: i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF,
! 117: self->data.CIF.servicetype);
! 118: Py_END_ALLOW_THREADS
! 119: return Py_BuildValue("I", i);
! 120: }
! 121:
! 122: static PyObject *
! 123: UPnP_totalbytereceived(UPnPObject *self)
! 124: {
! 125: UNSIGNED_INTEGER i;
! 126: Py_BEGIN_ALLOW_THREADS
! 127: i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF,
! 128: self->data.CIF.servicetype);
! 129: Py_END_ALLOW_THREADS
! 130: return Py_BuildValue("I", i);
! 131: }
! 132:
! 133: static PyObject *
! 134: UPnP_totalpacketsent(UPnPObject *self)
! 135: {
! 136: UNSIGNED_INTEGER i;
! 137: Py_BEGIN_ALLOW_THREADS
! 138: i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF,
! 139: self->data.CIF.servicetype);
! 140: Py_END_ALLOW_THREADS
! 141: return Py_BuildValue("I", i);
! 142: }
! 143:
! 144: static PyObject *
! 145: UPnP_totalpacketreceived(UPnPObject *self)
! 146: {
! 147: UNSIGNED_INTEGER i;
! 148: Py_BEGIN_ALLOW_THREADS
! 149: i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF,
! 150: self->data.CIF.servicetype);
! 151: Py_END_ALLOW_THREADS
! 152: return Py_BuildValue("I", i);
! 153: }
! 154:
! 155: static PyObject *
! 156: UPnP_statusinfo(UPnPObject *self)
! 157: {
! 158: char status[64];
! 159: char lastconnerror[64];
! 160: unsigned int uptime = 0;
! 161: int r;
! 162: status[0] = '\0';
! 163: lastconnerror[0] = '\0';
! 164: Py_BEGIN_ALLOW_THREADS
! 165: r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype,
! 166: status, &uptime, lastconnerror);
! 167: Py_END_ALLOW_THREADS
! 168: if(r==UPNPCOMMAND_SUCCESS) {
! 169: return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror);
! 170: } else {
! 171: /* TODO: have our own exception type ! */
! 172: PyErr_SetString(PyExc_Exception, strupnperror(r));
! 173: return NULL;
! 174: }
! 175: }
! 176:
! 177: static PyObject *
! 178: UPnP_connectiontype(UPnPObject *self)
! 179: {
! 180: char connectionType[64];
! 181: int r;
! 182: connectionType[0] = '\0';
! 183: Py_BEGIN_ALLOW_THREADS
! 184: r = UPNP_GetConnectionTypeInfo(self->urls.controlURL,
! 185: self->data.first.servicetype,
! 186: connectionType);
! 187: Py_END_ALLOW_THREADS
! 188: if(r==UPNPCOMMAND_SUCCESS) {
! 189: return Py_BuildValue("s", connectionType);
! 190: } else {
! 191: /* TODO: have our own exception type ! */
! 192: PyErr_SetString(PyExc_Exception, strupnperror(r));
! 193: return NULL;
! 194: }
! 195: }
! 196:
! 197: static PyObject *
! 198: UPnP_externalipaddress(UPnPObject *self)
! 199: {
! 200: char externalIPAddress[40];
! 201: int r;
! 202: externalIPAddress[0] = '\0';
! 203: Py_BEGIN_ALLOW_THREADS
! 204: r = UPNP_GetExternalIPAddress(self->urls.controlURL,
! 205: self->data.first.servicetype,
! 206: externalIPAddress);
! 207: Py_END_ALLOW_THREADS
! 208: if(r==UPNPCOMMAND_SUCCESS) {
! 209: return Py_BuildValue("s", externalIPAddress);
! 210: } else {
! 211: /* TODO: have our own exception type ! */
! 212: PyErr_SetString(PyExc_Exception, strupnperror(r));
! 213: return NULL;
! 214: }
! 215: }
! 216:
! 217: /* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc,
! 218: * remoteHost)
! 219: * protocol is 'UDP' or 'TCP' */
! 220: static PyObject *
! 221: UPnP_addportmapping(UPnPObject *self, PyObject *args)
! 222: {
! 223: char extPort[6];
! 224: unsigned short ePort;
! 225: char inPort[6];
! 226: unsigned short iPort;
! 227: const char * proto;
! 228: const char * host;
! 229: const char * desc;
! 230: const char * remoteHost;
! 231: const char * leaseDuration = "0";
! 232: int r;
! 233: if (!PyArg_ParseTuple(args, "HssHss", &ePort, &proto,
! 234: &host, &iPort, &desc, &remoteHost))
! 235: return NULL;
! 236: Py_BEGIN_ALLOW_THREADS
! 237: sprintf(extPort, "%hu", ePort);
! 238: sprintf(inPort, "%hu", iPort);
! 239: r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype,
! 240: extPort, inPort, host, desc, proto,
! 241: remoteHost, leaseDuration);
! 242: Py_END_ALLOW_THREADS
! 243: if(r==UPNPCOMMAND_SUCCESS)
! 244: {
! 245: Py_RETURN_TRUE;
! 246: }
! 247: else
! 248: {
! 249: // TODO: RAISE an Exception. See upnpcommands.h for errors codes.
! 250: // upnperrors.c
! 251: //Py_RETURN_FALSE;
! 252: /* TODO: have our own exception type ! */
! 253: PyErr_SetString(PyExc_Exception, strupnperror(r));
! 254: return NULL;
! 255: }
! 256: }
! 257:
! 258: /* DeletePortMapping(extPort, proto, removeHost='')
! 259: * proto = 'UDP', 'TCP' */
! 260: static PyObject *
! 261: UPnP_deleteportmapping(UPnPObject *self, PyObject *args)
! 262: {
! 263: char extPort[6];
! 264: unsigned short ePort;
! 265: const char * proto;
! 266: const char * remoteHost = "";
! 267: int r;
! 268: if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost))
! 269: return NULL;
! 270: Py_BEGIN_ALLOW_THREADS
! 271: sprintf(extPort, "%hu", ePort);
! 272: r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype,
! 273: extPort, proto, remoteHost);
! 274: Py_END_ALLOW_THREADS
! 275: if(r==UPNPCOMMAND_SUCCESS) {
! 276: Py_RETURN_TRUE;
! 277: } else {
! 278: /* TODO: have our own exception type ! */
! 279: PyErr_SetString(PyExc_Exception, strupnperror(r));
! 280: return NULL;
! 281: }
! 282: }
! 283:
! 284: static PyObject *
! 285: UPnP_getportmappingnumberofentries(UPnPObject *self)
! 286: {
! 287: unsigned int n = 0;
! 288: int r;
! 289: Py_BEGIN_ALLOW_THREADS
! 290: r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL,
! 291: self->data.first.servicetype,
! 292: &n);
! 293: Py_END_ALLOW_THREADS
! 294: if(r==UPNPCOMMAND_SUCCESS) {
! 295: return Py_BuildValue("I", n);
! 296: } else {
! 297: /* TODO: have our own exception type ! */
! 298: PyErr_SetString(PyExc_Exception, strupnperror(r));
! 299: return NULL;
! 300: }
! 301: }
! 302:
! 303: /* GetSpecificPortMapping(ePort, proto)
! 304: * proto = 'UDP' or 'TCP' */
! 305: static PyObject *
! 306: UPnP_getspecificportmapping(UPnPObject *self, PyObject *args)
! 307: {
! 308: char extPort[6];
! 309: unsigned short ePort;
! 310: const char * proto;
! 311: char intClient[40];
! 312: char intPort[6];
! 313: unsigned short iPort;
! 314: char desc[80];
! 315: char enabled[4];
! 316: char leaseDuration[16];
! 317: if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto))
! 318: return NULL;
! 319: extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0';
! 320: desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0';
! 321: Py_BEGIN_ALLOW_THREADS
! 322: sprintf(extPort, "%hu", ePort);
! 323: UPNP_GetSpecificPortMappingEntry(self->urls.controlURL,
! 324: self->data.first.servicetype,
! 325: extPort, proto,
! 326: intClient, intPort,
! 327: desc, enabled, leaseDuration);
! 328: Py_END_ALLOW_THREADS
! 329: if(intClient[0])
! 330: {
! 331: iPort = (unsigned short)atoi(intPort);
! 332: return Py_BuildValue("(s,H,s,O,i)",
! 333: intClient, iPort, desc,
! 334: PyBool_FromLong(atoi(enabled)),
! 335: atoi(leaseDuration));
! 336: }
! 337: else
! 338: {
! 339: Py_RETURN_NONE;
! 340: }
! 341: }
! 342:
! 343: /* GetGenericPortMapping(index) */
! 344: static PyObject *
! 345: UPnP_getgenericportmapping(UPnPObject *self, PyObject *args)
! 346: {
! 347: int i, r;
! 348: char index[8];
! 349: char intClient[40];
! 350: char intPort[6];
! 351: unsigned short iPort;
! 352: char extPort[6];
! 353: unsigned short ePort;
! 354: char protocol[4];
! 355: char desc[80];
! 356: char enabled[6];
! 357: char rHost[64];
! 358: char duration[16]; /* lease duration */
! 359: unsigned int dur;
! 360: if(!PyArg_ParseTuple(args, "i", &i))
! 361: return NULL;
! 362: Py_BEGIN_ALLOW_THREADS
! 363: snprintf(index, sizeof(index), "%d", i);
! 364: rHost[0] = '\0'; enabled[0] = '\0';
! 365: duration[0] = '\0'; desc[0] = '\0';
! 366: extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
! 367: r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL,
! 368: self->data.first.servicetype,
! 369: index,
! 370: extPort, intClient, intPort,
! 371: protocol, desc, enabled, rHost,
! 372: duration);
! 373: Py_END_ALLOW_THREADS
! 374: if(r==UPNPCOMMAND_SUCCESS)
! 375: {
! 376: ePort = (unsigned short)atoi(extPort);
! 377: iPort = (unsigned short)atoi(intPort);
! 378: dur = (unsigned int)strtoul(duration, 0, 0);
! 379: return Py_BuildValue("(H,s,(s,H),s,s,s,I)",
! 380: ePort, protocol, intClient, iPort,
! 381: desc, enabled, rHost, dur);
! 382: }
! 383: else
! 384: {
! 385: Py_RETURN_NONE;
! 386: }
! 387: }
! 388:
! 389: /* miniupnpc.UPnP object Method Table */
! 390: static PyMethodDef UPnP_methods[] = {
! 391: {"discover", (PyCFunction)UPnP_discover, METH_NOARGS,
! 392: "discover UPnP IGD devices on the network"
! 393: },
! 394: {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS,
! 395: "select a valid UPnP IGD among discovered devices"
! 396: },
! 397: {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS,
! 398: "return the total number of bytes sent by UPnP IGD"
! 399: },
! 400: {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS,
! 401: "return the total number of bytes received by UPnP IGD"
! 402: },
! 403: {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS,
! 404: "return the total number of packets sent by UPnP IGD"
! 405: },
! 406: {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS,
! 407: "return the total number of packets received by UPnP IGD"
! 408: },
! 409: {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS,
! 410: "return status and uptime"
! 411: },
! 412: {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS,
! 413: "return IGD WAN connection type"
! 414: },
! 415: {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS,
! 416: "return external IP address"
! 417: },
! 418: {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS,
! 419: "add a port mapping"
! 420: },
! 421: {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS,
! 422: "delete a port mapping"
! 423: },
! 424: {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS,
! 425: "-- non standard --"
! 426: },
! 427: {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS,
! 428: "get details about a specific port mapping entry"
! 429: },
! 430: {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS,
! 431: "get all details about the port mapping at index"
! 432: },
! 433: {NULL} /* Sentinel */
! 434: };
! 435:
! 436: static PyTypeObject UPnPType = {
! 437: PyObject_HEAD_INIT(NULL)
! 438: 0, /*ob_size*/
! 439: "miniupnpc.UPnP", /*tp_name*/
! 440: sizeof(UPnPObject), /*tp_basicsize*/
! 441: 0, /*tp_itemsize*/
! 442: (destructor)UPnPObject_dealloc,/*tp_dealloc*/
! 443: 0, /*tp_print*/
! 444: 0, /*tp_getattr*/
! 445: 0, /*tp_setattr*/
! 446: 0, /*tp_compare*/
! 447: 0, /*tp_repr*/
! 448: 0, /*tp_as_number*/
! 449: 0, /*tp_as_sequence*/
! 450: 0, /*tp_as_mapping*/
! 451: 0, /*tp_hash */
! 452: 0, /*tp_call*/
! 453: 0, /*tp_str*/
! 454: 0, /*tp_getattro*/
! 455: 0, /*tp_setattro*/
! 456: 0, /*tp_as_buffer*/
! 457: Py_TPFLAGS_DEFAULT, /*tp_flags*/
! 458: "UPnP objects", /* tp_doc */
! 459: 0, /* tp_traverse */
! 460: 0, /* tp_clear */
! 461: 0, /* tp_richcompare */
! 462: 0, /* tp_weaklistoffset */
! 463: 0, /* tp_iter */
! 464: 0, /* tp_iternext */
! 465: UPnP_methods, /* tp_methods */
! 466: UPnP_members, /* tp_members */
! 467: 0, /* tp_getset */
! 468: 0, /* tp_base */
! 469: 0, /* tp_dict */
! 470: 0, /* tp_descr_get */
! 471: 0, /* tp_descr_set */
! 472: 0, /* tp_dictoffset */
! 473: 0,/*(initproc)UPnP_init,*/ /* tp_init */
! 474: 0, /* tp_alloc */
! 475: #ifndef WIN32
! 476: PyType_GenericNew,/*UPnP_new,*/ /* tp_new */
! 477: #else
! 478: 0,
! 479: #endif
! 480: };
! 481:
! 482: /* module methods */
! 483: static PyMethodDef miniupnpc_methods[] = {
! 484: {NULL} /* Sentinel */
! 485: };
! 486:
! 487: #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
! 488: #define PyMODINIT_FUNC void
! 489: #endif
! 490: PyMODINIT_FUNC
! 491: initminiupnpc(void)
! 492: {
! 493: PyObject* m;
! 494:
! 495: #ifdef WIN32
! 496: UPnPType.tp_new = PyType_GenericNew;
! 497: #endif
! 498: if (PyType_Ready(&UPnPType) < 0)
! 499: return;
! 500:
! 501: m = Py_InitModule3("miniupnpc", miniupnpc_methods,
! 502: "miniupnpc module.");
! 503:
! 504: Py_INCREF(&UPnPType);
! 505: PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType);
! 506: }
! 507:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>