mirror of
https://github.com/status-im/miniupnp.git
synced 2025-01-21 19:59:09 +00:00
miniupnpc-libevent: add ability to work on several devices simultaneously
This commit is contained in:
parent
3a3072ee8c
commit
c021d7351f
@ -1,4 +1,4 @@
|
||||
/* $Id: miniupnpc-libevent.c,v 1.17 2014/11/28 13:21:25 nanard Exp $ */
|
||||
/* $Id: miniupnpc-libevent.c,v 1.18 2014/12/01 17:41:11 nanard Exp $ */
|
||||
/* miniupnpc-libevent
|
||||
* Copyright (c) 2008-2014, Thomas BERNARD <miniupnp@free.fr>
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
@ -65,6 +65,9 @@
|
||||
#define debug_printf(...)
|
||||
#endif
|
||||
|
||||
/* compare the begining of a string with a constant string */
|
||||
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
|
||||
|
||||
/* stuctures */
|
||||
|
||||
struct upnp_args {
|
||||
@ -74,7 +77,7 @@ struct upnp_args {
|
||||
|
||||
/* private functions */
|
||||
|
||||
static int upnpc_get_desc(upnpc_t * p, const char * url);
|
||||
static int upnpc_get_desc(upnpc_device_t * p, const char * url);
|
||||
static char * build_url_string(const char * urlbase, const char * root_desc_url, const char * controlurl);
|
||||
|
||||
/* data */
|
||||
@ -89,8 +92,8 @@ static const char * devices_to_search[] = {
|
||||
#ifdef DEBUG
|
||||
static void upnpc_conn_close_cb(struct evhttp_connection * conn, void * data)
|
||||
{
|
||||
upnpc_t * p = (upnpc_t *)data;
|
||||
debug_printf("upnpc_get_desc_conn_close_cb %p %p\n", conn, p);
|
||||
upnpc_device_t * d = (upnpc_device_t *)data;
|
||||
debug_printf("upnpc_get_desc_conn_close_cb %p %p\n", conn, d);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
@ -160,7 +163,7 @@ static void upnpc_send_ssdp_msearch(evutil_socket_t s, short events, upnpc_t * p
|
||||
addr.sin_port = htons(SSDP_PORT);
|
||||
addr.sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
|
||||
n = snprintf(bufr, sizeof(bufr),
|
||||
MSearchMsgFmt, devices_to_search[p->device_index++], mx);
|
||||
MSearchMsgFmt, devices_to_search[p->discover_device_index++], mx);
|
||||
debug_printf("upnpc_send_ssdp_msearch: %s", bufr);
|
||||
n = sendto(s, bufr, n, 0,
|
||||
(struct sockaddr *)&addr, sizeof(struct sockaddr_in));
|
||||
@ -169,19 +172,31 @@ static void upnpc_send_ssdp_msearch(evutil_socket_t s, short events, upnpc_t * p
|
||||
}
|
||||
}
|
||||
|
||||
static int upnpc_set_root_desc_location(upnpc_t * p, const char * location, int locationsize)
|
||||
static int upnpc_set_root_desc_location(upnpc_device_t * d, const char * location, int locationsize)
|
||||
{
|
||||
char * tmp;
|
||||
tmp = realloc(p->root_desc_location, locationsize + 1);
|
||||
tmp = realloc(d->root_desc_location, locationsize + 1);
|
||||
if(tmp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(tmp, location, locationsize);
|
||||
tmp[locationsize] = '\0';
|
||||
p->root_desc_location = tmp;
|
||||
d->root_desc_location = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static upnpc_device_t * upnpc_find_device_with_location(upnpc_t * p, const char * location, int locationsize)
|
||||
{
|
||||
upnpc_device_t * d;
|
||||
for(d = p->devices; d != NULL; d = d->next) {
|
||||
if(d->root_desc_location
|
||||
&& ((int)strlen(d->root_desc_location) == locationsize)
|
||||
&& (0 == memcmp(location, d->root_desc_location, locationsize)))
|
||||
return d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void upnpc_receive_and_parse_ssdp(evutil_socket_t s, short events, upnpc_t * p)
|
||||
{
|
||||
char bufr[2048];
|
||||
@ -190,13 +205,11 @@ static void upnpc_receive_and_parse_ssdp(evutil_socket_t s, short events, upnpc_
|
||||
if(events == EV_TIMEOUT) {
|
||||
/* nothing received ... */
|
||||
debug_printf("upnpc_receive_and_parse_ssdp() TIMEOUT\n");
|
||||
if(p->root_desc_location != NULL) {
|
||||
/* we already have found a device */
|
||||
} else if(!devices_to_search[p->device_index]) {
|
||||
if(!devices_to_search[p->discover_device_index]) {
|
||||
debug_printf("*** NO MORE DEVICES TO SEARCH ***\n");
|
||||
event_del(p->ev_ssdp_recv);
|
||||
/* no device found : report error */
|
||||
p->ready_cb(UPNPC_ERR_NO_DEVICE_FOUND, p->cb_data);
|
||||
p->ready_cb(UPNPC_ERR_NO_DEVICE_FOUND, p, NULL, p->cb_data);
|
||||
} else {
|
||||
/* send another SSDP M-SEARCH packet */
|
||||
if(event_add(p->ev_ssdp_writable, NULL)) {
|
||||
@ -221,11 +234,24 @@ static void upnpc_receive_and_parse_ssdp(evutil_socket_t s, short events, upnpc_
|
||||
debug_printf("location = '%.*s'\n", locationsize, location);
|
||||
debug_printf("st = '%.*s'\n", stsize, st);
|
||||
if(location != NULL) {
|
||||
if(upnpc_set_root_desc_location(p, location, locationsize) < 0) {
|
||||
return;
|
||||
upnpc_device_t * device;
|
||||
device = upnpc_find_device_with_location(p, location, locationsize);
|
||||
if(device) {
|
||||
debug_printf("device already known\n");
|
||||
} else {
|
||||
device = malloc(sizeof(upnpc_device_t));
|
||||
memset(device, 0, sizeof(upnpc_device_t));
|
||||
device->parent = p;
|
||||
device->next = p->devices;
|
||||
p->devices = device;
|
||||
if(upnpc_set_root_desc_location(device, location, locationsize) < 0) {
|
||||
return;
|
||||
}
|
||||
upnpc_get_desc(device, device->root_desc_location);
|
||||
}
|
||||
upnpc_get_desc(p, p->root_desc_location);
|
||||
#if 0
|
||||
event_del(p->ev_ssdp_recv); /* stop receiving SSDP responses */
|
||||
#endif
|
||||
} else {
|
||||
/* or do nothing ? */
|
||||
debug_printf("no location\n");
|
||||
@ -335,18 +361,18 @@ static void upnpc_desc_received(struct evhttp_request * req, void * pvoid)
|
||||
struct evbuffer * input_buffer;
|
||||
struct IGDdatas igd;
|
||||
struct xmlparser parser;
|
||||
upnpc_t * p = (upnpc_t *)pvoid;
|
||||
upnpc_device_t * d = (upnpc_device_t *)pvoid;
|
||||
|
||||
input_buffer = evhttp_request_get_input_buffer(req);
|
||||
len = evbuffer_get_length(input_buffer);
|
||||
data = evbuffer_pullup(input_buffer, len);
|
||||
debug_printf("upnpc_desc_received %d (%d bytes)\n", evhttp_request_get_response_code(req), (int)len);
|
||||
if(evhttp_request_get_response_code(req) != HTTP_OK) {
|
||||
p->ready_cb(evhttp_request_get_response_code(req), p->cb_data);
|
||||
d->parent->ready_cb(evhttp_request_get_response_code(req), d->parent, d, d->parent->cb_data);
|
||||
return;
|
||||
}
|
||||
if(data == NULL) {
|
||||
p->ready_cb(UPNPC_ERR_ROOT_DESC_ERROR, p->cb_data);
|
||||
d->parent->ready_cb(UPNPC_ERR_ROOT_DESC_ERROR, d->parent, d, d->parent->cb_data);
|
||||
return;
|
||||
}
|
||||
debug_printf("%.*s\n", (int)len, (char *)data);
|
||||
@ -363,15 +389,23 @@ static void upnpc_desc_received(struct evhttp_request * req, void * pvoid)
|
||||
#ifdef DEBUG
|
||||
printIGD(&igd);
|
||||
#endif /* DEBUG */
|
||||
p->control_conn_url = build_url_string(igd.urlbase, p->root_desc_location, igd.first.controlurl);
|
||||
p->conn_service_type = strdup(igd.first.servicetype);
|
||||
p->control_cif_url = build_url_string(igd.urlbase, p->root_desc_location, igd.CIF.controlurl);
|
||||
p->cif_service_type = strdup(igd.CIF.servicetype);
|
||||
d->control_conn_url = build_url_string(igd.urlbase, d->root_desc_location, igd.first.controlurl);
|
||||
d->conn_service_type = strdup(igd.first.servicetype);
|
||||
d->control_cif_url = build_url_string(igd.urlbase, d->root_desc_location, igd.CIF.controlurl);
|
||||
d->cif_service_type = strdup(igd.CIF.servicetype);
|
||||
debug_printf("control_conn_url='%s'\n (service_type='%s')\n",
|
||||
p->control_conn_url, p->conn_service_type);
|
||||
d->control_conn_url, d->conn_service_type);
|
||||
debug_printf("control_cif_url='%s'\n (service_type='%s')\n",
|
||||
p->control_cif_url, p->cif_service_type);
|
||||
p->ready_cb(evhttp_request_get_response_code(req), p->cb_data);
|
||||
d->control_cif_url, d->cif_service_type);
|
||||
|
||||
if((d->cif_service_type == NULL)
|
||||
|| (strlen(d->cif_service_type) == 0)
|
||||
|| (!COMPARE(d->cif_service_type, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))) {
|
||||
d->parent->ready_cb(UPNPC_ERR_NOT_IGD, d->parent, d, d->parent->cb_data);
|
||||
} else {
|
||||
d->state |= UPNPC_DEVICE_GETSTATUS;
|
||||
upnpc_get_status_info(d);
|
||||
}
|
||||
}
|
||||
|
||||
static void upnpc_soap_response(struct evhttp_request * req, void * pvoid)
|
||||
@ -379,23 +413,39 @@ static void upnpc_soap_response(struct evhttp_request * req, void * pvoid)
|
||||
size_t len;
|
||||
unsigned char * data;
|
||||
struct evbuffer * input_buffer;
|
||||
upnpc_t * p = (upnpc_t *)pvoid;
|
||||
upnpc_device_t * d = (upnpc_device_t *)pvoid;
|
||||
int code = evhttp_request_get_response_code(req);
|
||||
|
||||
input_buffer = evhttp_request_get_input_buffer(req);
|
||||
len = evbuffer_get_length(input_buffer);
|
||||
data = evbuffer_pullup(input_buffer, len);
|
||||
debug_printf("upnpc_soap_response %d (%d bytes)\n", evhttp_request_get_response_code(req), (int)len);
|
||||
debug_printf("upnpc_soap_response %d (%d bytes)\n", code, (int)len);
|
||||
debug_printf("%.*s\n", (int)len, (char *)data);
|
||||
if(data == NULL)
|
||||
return;
|
||||
|
||||
ClearNameValueList(&p->soap_response_data);
|
||||
ClearNameValueList(&d->soap_response_data);
|
||||
ParseNameValue((char *)data, (int)len,
|
||||
&p->soap_response_data);
|
||||
p->soap_cb(evhttp_request_get_response_code(req), p->cb_data);
|
||||
&d->soap_response_data);
|
||||
if(d->state & UPNPC_DEVICE_READY) {
|
||||
d->parent->soap_cb(code, d->parent, d, d->parent->cb_data);
|
||||
} else if(d->state & UPNPC_DEVICE_GETSTATUS) {
|
||||
const char * connection_status;
|
||||
d->state &= ~UPNPC_DEVICE_GETSTATUS;
|
||||
connection_status = GetValueFromNameValueList(&d->soap_response_data, "NewConnectionStatus");
|
||||
d->state |= UPNPC_DEVICE_READY;
|
||||
if((code == 200) && connection_status && (0 == strcmp("Connected", connection_status))) {
|
||||
d->parent->ready_cb(code, d->parent, d, d->parent->cb_data);
|
||||
d->state |= UPNPC_DEVICE_CONNECTED;
|
||||
event_del(d->parent->ev_ssdp_recv);
|
||||
} else {
|
||||
d->parent->ready_cb(UPNPC_ERR_NOT_CONNECTED, d->parent, d, d->parent->cb_data);
|
||||
}
|
||||
}
|
||||
d->state &= ~UPNPC_DEVICE_SOAP_REQ;
|
||||
}
|
||||
|
||||
static int upnpc_get_desc(upnpc_t * p, const char * url)
|
||||
static int upnpc_get_desc(upnpc_device_t * d, const char * url)
|
||||
{
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
unsigned short port;
|
||||
@ -404,26 +454,26 @@ static int upnpc_get_desc(upnpc_t * p, const char * url)
|
||||
struct evhttp_request * req;
|
||||
struct evkeyvalq * headers;
|
||||
|
||||
if(p->root_desc_location == 0) {
|
||||
/* if(d->root_desc_location == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if(!parseURL(url/*p->root_desc_location*/, hostname, &port,
|
||||
} */
|
||||
if(!parseURL(url/*d->root_desc_location*/, hostname, &port,
|
||||
&path, &scope_id)) {
|
||||
return -1;
|
||||
}
|
||||
if(p->desc_conn == NULL) {
|
||||
p->desc_conn = evhttp_connection_base_new(p->base, NULL, hostname, port);
|
||||
if(d->desc_conn == NULL) {
|
||||
d->desc_conn = evhttp_connection_base_new(d->parent->base, NULL, hostname, port);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
evhttp_connection_set_closecb(p->desc_conn, upnpc_conn_close_cb, p);
|
||||
evhttp_connection_set_closecb(d->desc_conn, upnpc_conn_close_cb, d);
|
||||
#endif /* DEBUG */
|
||||
/*evhttp_connection_set_timeout(p->desc_conn, 600);*/
|
||||
req = evhttp_request_new(upnpc_desc_received/*callback*/, p);
|
||||
req = evhttp_request_new(upnpc_desc_received/*callback*/, d);
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
evhttp_add_header(headers, "Host", hostname);
|
||||
evhttp_add_header(headers, "Connection", "close");
|
||||
/*evhttp_add_header(headers, "User-Agent", "***");*/
|
||||
evhttp_make_request(p->desc_conn, req, EVHTTP_REQ_GET, path);
|
||||
evhttp_make_request(d->desc_conn, req, EVHTTP_REQ_GET, path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -459,7 +509,7 @@ static char * build_url_string(const char * urlbase, const char * root_desc_url,
|
||||
#define SERVICEPREFIX "u"
|
||||
#define SERVICEPREFIX2 'u'
|
||||
|
||||
static int upnpc_send_soap_request(upnpc_t * p, const char * url,
|
||||
static int upnpc_send_soap_request(upnpc_device_t * p, const char * url,
|
||||
const char * service,
|
||||
const char * method,
|
||||
const struct upnp_args * args, int arg_count)
|
||||
@ -525,7 +575,7 @@ static int upnpc_send_soap_request(upnpc_t * p, const char * url,
|
||||
portstr[0] = '\0';
|
||||
snprintf(action, sizeof(action), "\"%s#%s\"", service, method);
|
||||
if(p->soap_conn == NULL) {
|
||||
p->soap_conn = evhttp_connection_base_new(p->base, NULL, hostname, port);
|
||||
p->soap_conn = evhttp_connection_base_new(p->parent->base, NULL, hostname, port);
|
||||
}
|
||||
req = evhttp_request_new(upnpc_soap_response, p);
|
||||
headers = evhttp_request_get_output_headers(req);
|
||||
@ -614,20 +664,34 @@ int upnpc_init(upnpc_t * p, struct event_base * base, const char * multicastif,
|
||||
return UPNPC_OK;
|
||||
}
|
||||
|
||||
static void upnpc_device_finalize(upnpc_device_t * d)
|
||||
{
|
||||
d->state = 0;
|
||||
free(d->root_desc_location);
|
||||
d->root_desc_location = NULL;
|
||||
free(d->control_cif_url);
|
||||
d->control_cif_url = NULL;
|
||||
free(d->cif_service_type);
|
||||
d->cif_service_type = NULL;
|
||||
free(d->control_conn_url);
|
||||
d->control_conn_url = NULL;
|
||||
free(d->conn_service_type);
|
||||
d->conn_service_type = NULL;
|
||||
if(d->desc_conn) {
|
||||
evhttp_connection_free(d->desc_conn);
|
||||
d->desc_conn = NULL;
|
||||
}
|
||||
if(d->soap_conn) {
|
||||
evhttp_connection_free(d->soap_conn);
|
||||
d->soap_conn = NULL;
|
||||
}
|
||||
ClearNameValueList(&d->soap_response_data);
|
||||
}
|
||||
|
||||
int upnpc_finalize(upnpc_t * p)
|
||||
{
|
||||
if(!p) return UPNPC_ERR_INVALID_ARGS;
|
||||
p->device_index = 0;
|
||||
free(p->root_desc_location);
|
||||
p->root_desc_location = NULL;
|
||||
free(p->control_cif_url);
|
||||
p->control_cif_url = NULL;
|
||||
free(p->cif_service_type);
|
||||
p->cif_service_type = NULL;
|
||||
free(p->control_conn_url);
|
||||
p->control_conn_url = NULL;
|
||||
free(p->conn_service_type);
|
||||
p->conn_service_type = NULL;
|
||||
p->discover_device_index = 0;
|
||||
if(p->ssdp_socket >= 0) {
|
||||
close(p->ssdp_socket);
|
||||
p->ssdp_socket = -1;
|
||||
@ -640,33 +704,30 @@ int upnpc_finalize(upnpc_t * p)
|
||||
event_free(p->ev_ssdp_writable);
|
||||
p->ev_ssdp_writable = NULL;
|
||||
}
|
||||
if(p->desc_conn) {
|
||||
evhttp_connection_free(p->desc_conn);
|
||||
p->desc_conn = NULL;
|
||||
while(p->devices != NULL) {
|
||||
upnpc_device_t * d = p->devices;
|
||||
upnpc_device_finalize(d);
|
||||
p->devices = d->next;
|
||||
free(d);
|
||||
}
|
||||
if(p->soap_conn) {
|
||||
evhttp_connection_free(p->soap_conn);
|
||||
p->soap_conn = NULL;
|
||||
}
|
||||
ClearNameValueList(&p->soap_response_data);
|
||||
return UPNPC_OK;
|
||||
}
|
||||
|
||||
int upnpc_get_external_ip_address(upnpc_t * p)
|
||||
int upnpc_get_external_ip_address(upnpc_device_t * p)
|
||||
{
|
||||
return upnpc_send_soap_request(p, p->control_conn_url,
|
||||
p->conn_service_type/*"urn:schemas-upnp-org:service:WANIPConnection:1"*/,
|
||||
"GetExternalIPAddress", NULL, 0);
|
||||
}
|
||||
|
||||
int upnpc_get_link_layer_max_rate(upnpc_t * p)
|
||||
int upnpc_get_link_layer_max_rate(upnpc_device_t * p)
|
||||
{
|
||||
return upnpc_send_soap_request(p, p->control_cif_url,
|
||||
p->cif_service_type/*"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"*/,
|
||||
"GetCommonLinkProperties", NULL, 0);
|
||||
}
|
||||
|
||||
int upnpc_delete_port_mapping(upnpc_t * p,
|
||||
int upnpc_delete_port_mapping(upnpc_device_t * p,
|
||||
const char * remote_host, unsigned short ext_port,
|
||||
const char * proto)
|
||||
{
|
||||
@ -688,7 +749,7 @@ int upnpc_delete_port_mapping(upnpc_t * p,
|
||||
args, 3);
|
||||
}
|
||||
|
||||
int upnpc_add_port_mapping(upnpc_t * p,
|
||||
int upnpc_add_port_mapping(upnpc_device_t * p,
|
||||
const char * remote_host, unsigned short ext_port,
|
||||
unsigned short int_port, const char * int_client,
|
||||
const char * proto, const char * description,
|
||||
@ -726,7 +787,7 @@ int upnpc_add_port_mapping(upnpc_t * p,
|
||||
args, 8);
|
||||
}
|
||||
|
||||
int upnpc_get_status_info(upnpc_t * p)
|
||||
int upnpc_get_status_info(upnpc_device_t * p)
|
||||
{
|
||||
return upnpc_send_soap_request(p, p->control_conn_url,
|
||||
p->conn_service_type/*"urn:schemas-upnp-org:service:WANIPConnection:1"*/,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: miniupnpc-libevent.h,v 1.9 2014/11/25 22:49:19 nanard Exp $ */
|
||||
/* $Id: miniupnpc-libevent.h,v 1.10 2014/12/01 17:41:11 nanard Exp $ */
|
||||
/* miniupnpc-libevent
|
||||
* Copyright (c) 2008-2014, Thomas BERNARD <miniupnp@free.fr>
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
@ -33,15 +33,23 @@ extern "C" {
|
||||
|
||||
#define UPNPC_ERR_NO_DEVICE_FOUND (-100)
|
||||
#define UPNPC_ERR_ROOT_DESC_ERROR (-101)
|
||||
#define UPNPC_ERR_NOT_IGD (-102)
|
||||
#define UPNPC_ERR_NOT_CONNECTED (-103)
|
||||
|
||||
typedef void(* upnpc_callback_fn)(int, void *);
|
||||
/* device->state masks */
|
||||
#define UPNPC_DEVICE_SOAP_REQ (0x0001)
|
||||
#define UPNPC_DEVICE_GETSTATUS (0x0002)
|
||||
#define UPNPC_DEVICE_CONNECTED (0x4000)
|
||||
#define UPNPC_DEVICE_READY (0x8000)
|
||||
|
||||
typedef struct {
|
||||
struct event_base * base;
|
||||
evutil_socket_t ssdp_socket;
|
||||
struct event * ev_ssdp_recv;
|
||||
struct event * ev_ssdp_writable;
|
||||
int device_index;
|
||||
typedef struct upnpc_device upnpc_device_t;
|
||||
typedef struct upnpc upnpc_t;
|
||||
|
||||
typedef void(* upnpc_callback_fn)(int, upnpc_t *, upnpc_device_t *, void *);
|
||||
|
||||
struct upnpc_device {
|
||||
upnpc_t * parent;
|
||||
upnpc_device_t * next;
|
||||
char * root_desc_location;
|
||||
struct evhttp_connection * desc_conn;
|
||||
char * control_cif_url;
|
||||
@ -50,31 +58,41 @@ typedef struct {
|
||||
char * conn_service_type;
|
||||
struct evhttp_connection * soap_conn;
|
||||
struct NameValueParserData soap_response_data;
|
||||
unsigned int state;
|
||||
};
|
||||
|
||||
struct upnpc {
|
||||
struct event_base * base;
|
||||
evutil_socket_t ssdp_socket;
|
||||
struct event * ev_ssdp_recv;
|
||||
struct event * ev_ssdp_writable;
|
||||
int discover_device_index;
|
||||
upnpc_device_t * devices;
|
||||
upnpc_callback_fn ready_cb;
|
||||
upnpc_callback_fn soap_cb;
|
||||
void * cb_data;
|
||||
} upnpc_t;
|
||||
};
|
||||
|
||||
int upnpc_init(upnpc_t * p, struct event_base * base, const char * multicastif,
|
||||
upnpc_callback_fn ready_cb, upnpc_callback_fn soap_cb, void * cb_data);
|
||||
|
||||
int upnpc_finalize(upnpc_t * p);
|
||||
|
||||
int upnpc_get_external_ip_address(upnpc_t * p);
|
||||
int upnpc_get_external_ip_address(upnpc_device_t * p);
|
||||
|
||||
int upnpc_get_link_layer_max_rate(upnpc_t * p);
|
||||
int upnpc_get_link_layer_max_rate(upnpc_device_t * p);
|
||||
|
||||
int upnpc_add_port_mapping(upnpc_t * p,
|
||||
int upnpc_add_port_mapping(upnpc_device_t * p,
|
||||
const char * remote_host, unsigned short ext_port,
|
||||
unsigned short int_port, const char * int_client,
|
||||
const char * proto, const char * description,
|
||||
unsigned int lease_duration);
|
||||
|
||||
int upnpc_delete_port_mapping(upnpc_t * p,
|
||||
int upnpc_delete_port_mapping(upnpc_device_t * p,
|
||||
const char * remote_host, unsigned short ext_port,
|
||||
const char * proto);
|
||||
|
||||
int upnpc_get_status_info(upnpc_t * p);
|
||||
int upnpc_get_status_info(upnpc_device_t * p);
|
||||
|
||||
#ifdef UPNPC_USE_SELECT
|
||||
int upnpc_select_fds(upnpc_t * p, int * nfds, fd_set * readfds, fd_set * writefds);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Id: upnpc-libevent.c,v 1.9 2014/11/25 22:49:19 nanard Exp $ */
|
||||
/* $Id: upnpc-libevent.c,v 1.10 2014/12/01 17:41:11 nanard Exp $ */
|
||||
/* miniupnpc-libevent
|
||||
* Copyright (c) 2008-2014, Thomas BERNARD <miniupnp@free.fr>
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
@ -37,13 +37,14 @@ static void sighandler(int signal)
|
||||
}
|
||||
|
||||
/* ready callback */
|
||||
static void ready(int code, void * data)
|
||||
static void ready(int code, upnpc_t * p, upnpc_device_t * d, void * data)
|
||||
{
|
||||
upnpc_t * p = (upnpc_t *)data;
|
||||
(void)data; (void)p;
|
||||
|
||||
if(code == 200) {
|
||||
printf("READY ! %d\n", code);
|
||||
/* 1st request */
|
||||
upnpc_get_status_info(p);
|
||||
upnpc_get_status_info(d);
|
||||
} else {
|
||||
printf("DISCOVER ERROR : %d\n", code);
|
||||
switch(code) {
|
||||
@ -72,47 +73,50 @@ static enum {
|
||||
} state = EGetStatusInfo;
|
||||
|
||||
/* soap callback */
|
||||
static void soap(int code, void * data)
|
||||
static void soap(int code, upnpc_t * p, upnpc_device_t * d, void * data)
|
||||
{
|
||||
upnpc_t * p = (upnpc_t *)data;
|
||||
(void)data; (void)p;
|
||||
|
||||
printf("SOAP ! %d\n", code);
|
||||
if(code == 200) {
|
||||
switch(state) {
|
||||
case EGetStatusInfo:
|
||||
printf("ConnectionStatus=%s\n", GetValueFromNameValueList(&p->soap_response_data, "NewConnectionStatus"));
|
||||
printf("LastConnectionError=%s\n", GetValueFromNameValueList(&p->soap_response_data, "NewLastConnectionError"));
|
||||
printf("Uptime=%s\n", GetValueFromNameValueList(&p->soap_response_data, "NewUptime"));
|
||||
upnpc_get_external_ip_address(p);
|
||||
printf("ConnectionStatus=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewConnectionStatus"));
|
||||
printf("LastConnectionError=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewLastConnectionError"));
|
||||
printf("Uptime=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewUptime"));
|
||||
upnpc_get_external_ip_address(d);
|
||||
state = EGetExtIp;
|
||||
break;
|
||||
case EGetExtIp:
|
||||
printf("ExternalIpAddress=%s\n", GetValueFromNameValueList(&p->soap_response_data, "NewExternalIPAddress"));
|
||||
upnpc_get_link_layer_max_rate(p);
|
||||
printf("ExternalIpAddress=%s\n", GetValueFromNameValueList(&d->soap_response_data, "NewExternalIPAddress"));
|
||||
upnpc_get_link_layer_max_rate(d);
|
||||
state = EGetMaxRate;
|
||||
break;
|
||||
case EGetMaxRate:
|
||||
printf("DownStream MaxBitRate = %s\t", GetValueFromNameValueList(&p->soap_response_data, "NewLayer1DownstreamMaxBitRate"));
|
||||
upnpc_add_port_mapping(p, NULL, 60001, 60002, local_address, "TCP", "test port mapping", 0);
|
||||
printf("UpStream MaxBitRate = %s\n", GetValueFromNameValueList(&p->soap_response_data, "NewLayer1UpstreamMaxBitRate"));
|
||||
printf("DownStream MaxBitRate = %s\t", GetValueFromNameValueList(&d->soap_response_data, "NewLayer1DownstreamMaxBitRate"));
|
||||
upnpc_add_port_mapping(d, NULL, 60001, 60002, local_address, "TCP", "test port mapping", 0);
|
||||
printf("UpStream MaxBitRate = %s\n", GetValueFromNameValueList(&d->soap_response_data, "NewLayer1UpstreamMaxBitRate"));
|
||||
state = EAddPortMapping;
|
||||
break;
|
||||
case EAddPortMapping:
|
||||
printf("OK!\n");
|
||||
upnpc_delete_port_mapping(p, NULL, 60001, "TCP");
|
||||
upnpc_delete_port_mapping(d, NULL, 60001, "TCP");
|
||||
state = EDeletePortMapping;
|
||||
break;
|
||||
case EDeletePortMapping:
|
||||
printf("OK!\n");
|
||||
state = EFinished;
|
||||
/*default:
|
||||
event_base_loopbreak(base);*/
|
||||
break;
|
||||
default:
|
||||
printf("EFinished : breaking\n");
|
||||
event_base_loopbreak(base);
|
||||
}
|
||||
} else {
|
||||
printf("SOAP error :\n");
|
||||
printf(" faultcode='%s'\n", GetValueFromNameValueList(&p->soap_response_data, "faultcode"));
|
||||
printf(" faultstring='%s'\n", GetValueFromNameValueList(&p->soap_response_data, "faultstring"));
|
||||
printf(" errorCode=%s\n", GetValueFromNameValueList(&p->soap_response_data, "errorCode"));
|
||||
printf(" errorDescription='%s'\n", GetValueFromNameValueList(&p->soap_response_data, "errorDescription"));
|
||||
printf(" faultcode='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "faultcode"));
|
||||
printf(" faultstring='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "faultstring"));
|
||||
printf(" errorCode=%s\n", GetValueFromNameValueList(&d->soap_response_data, "errorCode"));
|
||||
printf(" errorDescription='%s'\n", GetValueFromNameValueList(&d->soap_response_data, "errorDescription"));
|
||||
event_base_loopbreak(base);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user