PageRenderTime 29ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/ClassMaster2014/barahon/Cultivation_9_UnixSource/minorGems/network/upnp/miniupnpc/miniupnpcmodule.c

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