~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Externals/miniupnpc/src/miniupnpcmodule.c

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

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