Commit a1f11352 authored by Yann Diorcet's avatar Yann Diorcet

Rework upnp for add/remove mapping callback

parent 16548f4e
......@@ -19,12 +19,26 @@ typedef enum _upnp_igd_event {
UPNP_IGD_EXTERNAL_IPADDRESS_CHANGED = 0,
UPNP_IGD_NAT_ENABLED_CHANGED,
UPNP_IGD_CONNECTION_STATUS_CHANGED,
UPNP_IGD_PORT_MAPPING_ADDED,
UPNP_IGD_PORT_MAPPING_REMOVED,
UPNP_IGD_PORT_MAPPING_ADD_SUCCESS,
UPNP_IGD_PORT_MAPPING_ADD_FAILURE,
UPNP_IGD_PORT_MAPPING_REMOVE_SUCCESS,
UPNP_IGD_PORT_MAPPING_REMOVE_FAILURE,
UPNP_IGD_DEVICE_ADDED = 100,
UPNP_IGD_DEVICE_REMOVED,
} upnp_igd_event;
typedef struct _upnp_igd_port_mapping {
upnp_igd_ip_protocol protocol;
const char* local_host;
int local_port;
const char* remote_host;
int remote_port;
const char* description;
} upnp_igd_port_mapping;
typedef void (*upnp_igd_callback_function)(void *cookie, upnp_igd_event event, void *arg);
typedef void (*upnp_igd_print_function)(void *cookie, upnp_igd_print_level level, const char *fmt, va_list list);
......@@ -36,15 +50,8 @@ const char *upnp_igd_get_external_ipaddress(upnp_igd_context *igd_ctxt);
const char *upnp_igd_get_connection_status(upnp_igd_context *igd_ctxt);
int upnp_igd_get_nat_enabled(upnp_igd_context *igd_ctxt);
int upnp_igd_add_port_mapping(upnp_igd_context *igd_ctxt,
upnp_igd_ip_protocol protocol,
const char* local_host, int local_port,
const char* remote_host, int remote_port,
const char* description);
int upnp_igd_delete_port_mapping(upnp_igd_context *igd_ctxt,
upnp_igd_ip_protocol protocol,
const char* remote_host, int remote_port);
int upnp_igd_add_port_mapping(upnp_igd_context *igd_ctxt, const upnp_igd_port_mapping *mapping);
int upnp_igd_delete_port_mapping(upnp_igd_context *igd_ctxt, const upnp_igd_port_mapping *mapping);
int upnp_refresh(upnp_igd_context *igd_ctxt);
......
......@@ -586,8 +586,10 @@ void upnp_igd_handle_get_var(upnp_igd_context* igd_ctxt, const char *controlURL,
if (strcmp(tmpdevnode->device.services[service].control_url, controlURL) == 0) {
for (variable = 0; variable < IGDVarCount[service]; variable++) {
if (strcmp(IGDVarName[service][variable], varName) == 0) {
strcpy(tmpdevnode->device.services[service].variables[variable], varValue);
upnp_igd_var_updated(igd_ctxt, tmpdevnode, service, variable, varValue);
if(strcmp(tmpdevnode->device.services[service].variables[variable], varValue)) {
strcpy(tmpdevnode->device.services[service].variables[variable], varValue);
upnp_igd_var_updated(igd_ctxt, tmpdevnode, service, variable, varValue);
}
break;
}
}
......@@ -619,13 +621,11 @@ void upnp_igd_handle_get_var(upnp_igd_context* igd_ctxt, const char *controlURL,
void upnp_igd_handle_send_action(upnp_igd_context* igd_ctxt, const char *controlURL, IXML_Document *action, IXML_Document *result) {
upnp_igd_device_node *tmpdevnode;
int service;
IXML_Node *node;
IXML_Element *variable;
IXML_NodeList *variables;
long unsigned int length1;
int j;
char *tmpstate = NULL;
const char *ctmpstate = NULL;
char variable_name[IGD_MAX_VAR_LEN + 3];
ithread_mutex_lock(&igd_ctxt->devices_mutex);
......@@ -648,8 +648,10 @@ void upnp_igd_handle_send_action(upnp_igd_context* igd_ctxt, const char *control
variable = (IXML_Element *) ixmlNodeList_item(variables, 0);
tmpstate = upnp_igd_get_element_value(igd_ctxt, variable);
if (tmpstate) {
strcpy(tmpdevnode->device.services[service].variables[j], tmpstate);
upnp_igd_var_updated(igd_ctxt, tmpdevnode, service, j, tmpdevnode->device.services[service].variables[j]);
if(strcmp(tmpdevnode->device.services[service].variables[j], tmpstate)) {
strcpy(tmpdevnode->device.services[service].variables[j], tmpstate);
upnp_igd_var_updated(igd_ctxt, tmpdevnode, service, j, tmpdevnode->device.services[service].variables[j]);
}
}
if (tmpstate) {
free(tmpstate);
......@@ -660,20 +662,6 @@ void upnp_igd_handle_send_action(upnp_igd_context* igd_ctxt, const char *control
variables = NULL;
}
}
if(igd_ctxt->callback_fct != NULL) {
node = ixmlNode_getFirstChild(&result->n);
if(node && node->nodeType == eELEMENT_NODE) {
variable = (IXML_Element *)node;
ctmpstate = ixmlElement_getTagName(variable);
if(ctmpstate != NULL) {
if(strcmp(ctmpstate, "AddPortMappingResponse") == 0) {
igd_ctxt->callback_fct(igd_ctxt->cookie, UPNP_IGD_PORT_MAPPING_ADDED, NULL);
} else if(strcmp(ctmpstate, "DeletePortMappingResponse") == 0) {
igd_ctxt->callback_fct(igd_ctxt->cookie, UPNP_IGD_PORT_MAPPING_REMOVED, NULL);
}
}
}
}
break;
}
}
......@@ -730,8 +718,10 @@ void upnp_igd_state_update(upnp_igd_context* igd_ctxt, upnp_igd_device_node *dev
variable = (IXML_Element *) ixmlNodeList_item(variables, 0);
tmpstate = upnp_igd_get_element_value(igd_ctxt, variable);
if (tmpstate) {
strcpy(values[j], tmpstate);
upnp_igd_var_updated(igd_ctxt, device_node, service, j, values[j]);
if(strcmp(values[j], tmpstate)) {
strcpy(values[j], tmpstate);
upnp_igd_var_updated(igd_ctxt, device_node, service, j, values[j]);
}
}
if (tmpstate) {
free(tmpstate);
......
#include "mediastreamer2/upnp_igd.h"
#include "upnp_igd_private.h"
#include <stdlib.h>
#include <stdio.h>
typedef struct _upnp_igd_port_mapping_context {
upnp_igd_context *igd_ctxt;
upnp_igd_port_mapping mapping;
} upnp_igd_port_mapping_context;
upnp_igd_port_mapping_context * upnp_igd_port_mapping_context_create(upnp_igd_context *igd_ctxt, const upnp_igd_port_mapping *mapping) {
upnp_igd_port_mapping_context *igd_port_mapping_ctxt = (upnp_igd_port_mapping_context *)malloc(sizeof(upnp_igd_port_mapping_context));
igd_port_mapping_ctxt->igd_ctxt = igd_ctxt;
memcpy(&igd_port_mapping_ctxt->mapping, mapping, sizeof(upnp_igd_port_mapping));
return igd_port_mapping_ctxt;
}
void upnp_igd_port_mapping_context_destroy(upnp_igd_port_mapping_context *igd_port_mapping_ctxt) {
free(igd_port_mapping_ctxt);
}
int upnp_igd_port_mapping_handle_action(upnp_igd_port_mapping_context *igd_port_mapping_ctxt, int errcode, const char *controlURL, IXML_Document *action, IXML_Document *result) {
upnp_igd_device_node *tmpdevnode;
int service;
IXML_Node *node;
const char *ctmpstate = NULL;
upnp_igd_context *igd_ctxt = igd_port_mapping_ctxt->igd_ctxt;
ithread_mutex_lock(&igd_ctxt->devices_mutex);
tmpdevnode = igd_ctxt->devices;
while (tmpdevnode) {
for (service = 0; service < IGD_SERVICE_SERVCOUNT; service++) {
if (strcmp(tmpdevnode->device.services[service].control_url, controlURL) == 0) {
if(igd_ctxt->callback_fct != NULL) {
node = ixmlNode_getFirstChild(&action->n);
if(node && node->nodeType == eELEMENT_NODE) {
ctmpstate = ixmlNode_getLocalName(node);
if(ctmpstate != NULL) {
if(strcmp(ctmpstate, "AddPortMapping") == 0) {
if(errcode == UPNP_E_SUCCESS)
igd_ctxt->callback_fct(igd_ctxt->cookie, UPNP_IGD_PORT_MAPPING_ADD_SUCCESS, &igd_port_mapping_ctxt->mapping);
else
igd_ctxt->callback_fct(igd_ctxt->cookie, UPNP_IGD_PORT_MAPPING_ADD_FAILURE, &igd_port_mapping_ctxt->mapping);
} else if(strcmp(ctmpstate, "DeletePortMapping") == 0) {
if(errcode == UPNP_E_SUCCESS)
igd_ctxt->callback_fct(igd_ctxt->cookie, UPNP_IGD_PORT_MAPPING_REMOVE_SUCCESS, &igd_port_mapping_ctxt->mapping);
else
igd_ctxt->callback_fct(igd_ctxt->cookie, UPNP_IGD_PORT_MAPPING_REMOVE_FAILURE, &igd_port_mapping_ctxt->mapping);
}
}
}
}
break;
}
}
tmpdevnode = tmpdevnode->next;
}
ithread_mutex_unlock(&igd_ctxt->devices_mutex);
return 0;
}
int upnp_igd_port_mapping_callback(Upnp_EventType event_type, void* event, void *cookie) {
int ret = 1;
upnp_igd_port_mapping_context *igd_port_mapping_ctxt = (upnp_igd_port_mapping_context*)cookie;
ret = upnp_igd_callback(event_type, event, igd_port_mapping_ctxt->igd_ctxt);
switch(event_type) {
case UPNP_CONTROL_ACTION_COMPLETE: {
struct Upnp_Action_Complete *a_event = (struct Upnp_Action_Complete *)event;
upnp_igd_port_mapping_handle_action(igd_port_mapping_ctxt, a_event->ErrCode, a_event->CtrlUrl, a_event->ActionRequest, a_event->ActionResult);
}
break;
default:
break;
}
upnp_igd_port_mapping_context_destroy(igd_port_mapping_ctxt);
return ret;
}
/********************************************************************************
* upnp_igd_get_external_ipaddress
......@@ -15,6 +96,7 @@
********************************************************************************/
const char *upnp_igd_get_external_ipaddress(upnp_igd_context* igd_ctxt) {
const char *address = NULL;
ithread_mutex_lock(&igd_ctxt->devices_mutex);
if(igd_ctxt->devices != NULL) {
address = igd_ctxt->devices->device.services[IGD_SERVICE_WANIPCONNECTION].variables[IGD_SERVICE_WANIPCONNECTION_EXTERNAL_IP_ADDRESS];
if(address != NULL) {
......@@ -23,6 +105,7 @@ const char *upnp_igd_get_external_ipaddress(upnp_igd_context* igd_ctxt) {
}
}
}
ithread_mutex_unlock(&igd_ctxt->devices_mutex);
return address;
}
......@@ -39,6 +122,7 @@ const char *upnp_igd_get_external_ipaddress(upnp_igd_context* igd_ctxt) {
********************************************************************************/
const char *upnp_igd_get_connection_status(upnp_igd_context *igd_ctxt) {
const char *status = NULL;
ithread_mutex_lock(&igd_ctxt->devices_mutex);
if(igd_ctxt->devices != NULL) {
status = igd_ctxt->devices->device.services[IGD_SERVICE_WANIPCONNECTION].variables[IGD_SERVICE_WANIPCONNECTION_CONNECTION_STATUS];
if(status != NULL) {
......@@ -47,6 +131,7 @@ const char *upnp_igd_get_connection_status(upnp_igd_context *igd_ctxt) {
}
}
}
ithread_mutex_unlock(&igd_ctxt->devices_mutex);
return status;
}
......@@ -64,6 +149,7 @@ const char *upnp_igd_get_connection_status(upnp_igd_context *igd_ctxt) {
int upnp_igd_get_nat_enabled(upnp_igd_context *igd_ctxt) {
int enabled = 0;
const char *status = NULL;
ithread_mutex_lock(&igd_ctxt->devices_mutex);
if(igd_ctxt->devices != NULL) {
status = igd_ctxt->devices->device.services[IGD_SERVICE_WANIPCONNECTION].variables[IGD_SERVICE_WANIPCONNECTION_NAT_ENABLED];
if(status != NULL) {
......@@ -72,6 +158,7 @@ int upnp_igd_get_nat_enabled(upnp_igd_context *igd_ctxt) {
}
}
}
ithread_mutex_unlock(&igd_ctxt->devices_mutex);
return enabled;
}
......@@ -83,22 +170,14 @@ int upnp_igd_get_nat_enabled(upnp_igd_context *igd_ctxt) {
* Add a port mapping.
*
* Parameters:
* igd_ctxt -- The upnp igd context
* protocol -- The protocol to map (UDP/TCP)
* local_host -- The local host to map
* local_port -- The local port to map
* remote_host -- The remote host to map
* remote_port -- The remote port to map
* description -- The description associated with the mapping
* igd_ctxt -- The upnp igd context
* mapping -- The port mapping to add
*
********************************************************************************/
int upnp_igd_add_port_mapping(upnp_igd_context *igd_ctxt,
upnp_igd_ip_protocol protocol,
const char* local_host, int local_port,
const char* remote_host, int remote_port,
const char* description) {
int upnp_igd_add_port_mapping(upnp_igd_context *igd_ctxt, const upnp_igd_port_mapping *mapping) {
int ret;
char local_port_str[6], remote_port_str[6];
upnp_igd_port_mapping_context * upnp_igd_port_mapping_ctxt = NULL;
const char* variables[]={
"NewProtocol",
"NewInternalClient",
......@@ -110,27 +189,37 @@ int upnp_igd_add_port_mapping(upnp_igd_context *igd_ctxt,
"NewEnabled"
};
const char* values[]={
(protocol == UPNP_IGD_IP_PROTOCOL_UDP)? "UDP": "TCP",
local_host,
NULL,
NULL,
local_port_str,
remote_host,
NULL,
remote_port_str,
description,
NULL,
"0",
"1"
};
if(igd_ctxt->devices == NULL || remote_host == NULL || local_host == NULL) {
return -1;
}
ithread_mutex_lock(&igd_ctxt->devices_mutex);
if(igd_ctxt->devices != NULL && mapping != NULL && mapping->remote_host != NULL && mapping->local_host != NULL) {
/* Set values */
values[0] = (mapping->protocol == UPNP_IGD_IP_PROTOCOL_UDP)? "UDP": "TCP";
values[1] = mapping->local_host;
values[3] = mapping->remote_host;
values[5] = mapping->description;
/* Convert int to str */
snprintf(local_port_str, sizeof(local_port_str)/sizeof(local_port_str[0]), "%d", local_port);
snprintf(remote_port_str, sizeof(remote_port_str)/sizeof(remote_port_str[0]), "%d", remote_port);
/* Convert int to str */
snprintf(local_port_str, sizeof(local_port_str)/sizeof(local_port_str[0]), "%d", mapping->local_port);
snprintf(remote_port_str, sizeof(remote_port_str)/sizeof(remote_port_str[0]), "%d", mapping->remote_port);
ret = upnp_igd_send_action(igd_ctxt, igd_ctxt->devices, IGD_SERVICE_WANIPCONNECTION, "AddPortMapping",
variables, values, sizeof(values)/sizeof(values[0]),
upnp_igd_callback, igd_ctxt);
upnp_igd_port_mapping_ctxt = upnp_igd_port_mapping_context_create(igd_ctxt, mapping);
ret = upnp_igd_send_action(igd_ctxt, igd_ctxt->devices, IGD_SERVICE_WANIPCONNECTION, "AddPortMapping",
variables, values, sizeof(values)/sizeof(values[0]),
upnp_igd_port_mapping_callback, upnp_igd_port_mapping_ctxt);
} else {
ret = 1;
}
ithread_mutex_unlock(&igd_ctxt->devices_mutex);
return ret;
}
......@@ -149,32 +238,38 @@ int upnp_igd_add_port_mapping(upnp_igd_context *igd_ctxt,
* remote_port -- The remote port of map
*
********************************************************************************/
int upnp_igd_delete_port_mapping(upnp_igd_context *igd_ctxt,
upnp_igd_ip_protocol protocol,
const char* remote_host, int remote_port) {
int upnp_igd_delete_port_mapping(upnp_igd_context *igd_ctxt, const upnp_igd_port_mapping *mapping) {
int ret;
char remote_port_str[6];
upnp_igd_port_mapping_context * upnp_igd_port_mapping_ctxt = NULL;
const char* variables[]={
"NewProtocol",
"NewRemoteHost",
"NewExternalPort",
};
const char* values[]={
(protocol == UPNP_IGD_IP_PROTOCOL_UDP)? "UDP": "TCP",
remote_host,
NULL,
NULL,
remote_port_str
};
if(igd_ctxt->devices == NULL) {
return -1;
}
ithread_mutex_lock(&igd_ctxt->devices_mutex);
if(igd_ctxt->devices != NULL && mapping != NULL && mapping->remote_host != NULL) {
/* Set values */
values[0] = (mapping->protocol == UPNP_IGD_IP_PROTOCOL_UDP)? "UDP": "TCP";
values[1] = mapping->remote_host;
/* Convert int to str */
snprintf(remote_port_str, sizeof(remote_port_str)/sizeof(remote_port_str[0]), "%d", remote_port);
/* Convert int to str */
snprintf(remote_port_str, sizeof(remote_port_str)/sizeof(remote_port_str[0]), "%d", mapping->remote_port);
ret = upnp_igd_send_action(igd_ctxt, igd_ctxt->devices, IGD_SERVICE_WANIPCONNECTION, "DeletePortMapping",
variables, values, sizeof(values)/sizeof(values[0]),
upnp_igd_callback, igd_ctxt);
upnp_igd_port_mapping_ctxt = upnp_igd_port_mapping_context_create(igd_ctxt, mapping);
ret = upnp_igd_send_action(igd_ctxt, igd_ctxt->devices, IGD_SERVICE_WANIPCONNECTION, "DeletePortMapping",
variables, values, sizeof(values)/sizeof(values[0]),
upnp_igd_port_mapping_callback, upnp_igd_port_mapping_ctxt);
} else {
ret = -1;
}
ithread_mutex_unlock(&igd_ctxt->devices_mutex);
return ret;
}
#ifndef _UPNP_IGD_UTILS_H__
#define _UPNP_IGD_UTILS_H__
#include "mediastreamer2/upnp_igd.h"
#include "mediastreamer2/upnp_igd.h"
#include <upnp.h>
void upnp_igd_print(upnp_igd_context *uIGD, upnp_igd_print_level level, const char *fmt, ...);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment