mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 03:28:07 +00:00
uPnP in progress
This commit is contained in:
parent
8026b597a7
commit
806203ca0a
9 changed files with 419 additions and 19 deletions
|
|
@ -206,7 +206,7 @@ static LPC_COMMAND commands[] = {
|
|||
{ "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
|
||||
"'autoanswer' \t: show current autoanswer mode\n"
|
||||
"'autoanswer enable'\t: enable autoanswer mode\n"
|
||||
"'autoanswer disable'\t: disable autoanswer mode \n"},
|
||||
"'autoanswer disable'\t: disable autoanswer mode<EFBFBD><EFBFBD>\n"},
|
||||
{ "proxy", lpc_cmd_proxy, "Manage proxies",
|
||||
"'proxy list' : list all proxy setups.\n"
|
||||
"'proxy add' : add a new proxy setup.\n"
|
||||
|
|
@ -896,6 +896,9 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
|
|||
case LinphonePolicyUseIce:
|
||||
linphonec_out("Using ice with stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
|
||||
break;
|
||||
case LinphonePolicyUseUpnp:
|
||||
linphonec_out("Using uPnP IGD protocol\n");
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
|
||||
call->upnp_session = upnp_session_new();
|
||||
call->upnp_session = upnp_session_new(call);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
call->camera_active=params->has_video;
|
||||
|
|
@ -515,6 +515,19 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
case LinphonePolicyUseStun:
|
||||
call->ping_time=linphone_core_run_stun_tests(call->core,call);
|
||||
/* No break to also destroy ice session in this case. */
|
||||
break;
|
||||
case LinphonePolicyUseUpnp:
|
||||
#ifdef BUILD_UPNP
|
||||
call->upnp_session = upnp_session_new(call);
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_call_init_media_streams(call);
|
||||
if (linphone_core_update_upnp(call->core,call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
}
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -663,6 +676,9 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
|
|||
|
||||
static void linphone_call_destroy(LinphoneCall *obj)
|
||||
{
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_delete_upnp_session(obj);
|
||||
#endif //BUILD_UPNP
|
||||
linphone_call_delete_ice_session(obj);
|
||||
if (obj->op!=NULL) {
|
||||
sal_op_release(obj->op);
|
||||
|
|
@ -1674,6 +1690,15 @@ void linphone_call_delete_ice_session(LinphoneCall *call){
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
void linphone_call_delete_upnp_session(LinphoneCall *call){
|
||||
if(call->upnp_session!=NULL) {
|
||||
upnp_session_destroy(call->upnp_session);
|
||||
call->upnp_session=NULL;
|
||||
}
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
|
||||
audio_stream_get_local_rtp_stats (st,&log->local_stats);
|
||||
log->quality=audio_stream_get_average_quality_rating(st);
|
||||
|
|
@ -1984,6 +2009,11 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
|
|||
report_bandwidth(call,as,vs);
|
||||
ms_message("Thread processing load: audio=%f\tvideo=%f",audio_load,video_load);
|
||||
}
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
upnp_call_process(call);
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL) {
|
||||
OrtpEvent *ev;
|
||||
|
|
|
|||
|
|
@ -2005,6 +2005,10 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
}
|
||||
if (call->upnp_session != NULL) {
|
||||
ms_warning("uPnP mapping has not finished yet, proceeded with the call withoutt uPnP anyway.");
|
||||
linphone_call_delete_upnp_session(call);
|
||||
}
|
||||
linphone_core_start_invite(lc,call);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
|
|
@ -2419,7 +2423,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
LinphoneAddress *parsed_url2=NULL;
|
||||
char *real_url=NULL;
|
||||
LinphoneCall *call;
|
||||
bool_t use_ice = FALSE;
|
||||
bool_t defer = FALSE;
|
||||
|
||||
linphone_core_preempt_sound_resources(lc);
|
||||
|
||||
|
|
@ -2472,9 +2476,21 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
} else {
|
||||
use_ice = TRUE;
|
||||
defer = TRUE;
|
||||
}
|
||||
}
|
||||
else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
|
||||
#ifdef BUILD_UPNP
|
||||
linphone_call_init_media_streams(call);
|
||||
call->start_time=time(NULL);
|
||||
if (linphone_core_update_upnp(lc,call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else {
|
||||
defer = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (call->dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
|
||||
/*defer the start of the call after the OPTIONS ping*/
|
||||
|
|
@ -2484,7 +2500,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
sal_op_set_user_pointer(call->ping_op,call);
|
||||
call->start_time=time(NULL);
|
||||
}else{
|
||||
if (use_ice==FALSE) linphone_core_start_invite(lc,call);
|
||||
if (defer==FALSE) linphone_core_start_invite(lc,call);
|
||||
}
|
||||
|
||||
if (real_url!=NULL) ms_free(real_url);
|
||||
|
|
@ -2657,22 +2673,41 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
linphone_call_set_state(call,LinphoneCallUpdating,"Updating call");
|
||||
#ifdef VIDEO_ENABLED
|
||||
bool_t has_video = call->params.has_video;
|
||||
if ((call->ice_session != NULL) && (call->videostream != NULL) && !params->has_video) {
|
||||
ice_session_remove_check_list(call->ice_session, call->videostream->ice_check_list);
|
||||
call->videostream->ice_check_list = NULL;
|
||||
if(call->videostream != NULL && !params->has_video) {
|
||||
if ((call->ice_session != NULL)) {
|
||||
ice_session_remove_check_list(call->ice_session, call->videostream->ice_check_list);
|
||||
call->videostream->ice_check_list = NULL;
|
||||
}
|
||||
}
|
||||
call->params = *params;
|
||||
linphone_call_make_local_media_description(lc, call);
|
||||
if ((call->ice_session != NULL) && !has_video && call->params.has_video) {
|
||||
/* Defer call update until the ICE candidates gathering process has finished. */
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
if (!has_video && call->params.has_video) {
|
||||
if (call->ice_session != NULL) {
|
||||
/* Defer call update until the ICE candidates gathering process has finished. */
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
linphone_call_init_video_stream(call);
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
ms_message("Defer call update to add uPnP port mappings");
|
||||
linphone_call_init_video_stream(call);
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
} else return err;
|
||||
if (linphone_core_update_upnp(lc, call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
#endif
|
||||
err = linphone_core_start_update_call(lc, call);
|
||||
}else{
|
||||
|
|
@ -2789,6 +2824,12 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
linphone_core_start_accept_call_update(lc, call);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,6 +292,7 @@ void linphone_call_stop_audio_stream(LinphoneCall *call);
|
|||
void linphone_call_stop_video_stream(LinphoneCall *call);
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call);
|
||||
void linphone_call_delete_ice_session(LinphoneCall *call);
|
||||
void linphone_call_delete_upnp_session(LinphoneCall *call);
|
||||
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
|
||||
|
||||
const char * linphone_core_get_identity(LinphoneCore *lc);
|
||||
|
|
|
|||
268
coreapi/upnp.c
268
coreapi/upnp.c
|
|
@ -20,6 +20,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "upnp.h"
|
||||
#include "private.h"
|
||||
|
||||
#define UPNP_MAX_RETRY 4
|
||||
|
||||
UpnpPortBinding *upnp_port_binding_new();
|
||||
UpnpPortBinding * upnp_port_binding_retain(UpnpPortBinding *port);
|
||||
void upnp_port_binding_release(UpnpPortBinding *port);
|
||||
|
||||
int upnp_context_send_remove_port_binding(LinphoneCore *lc, UpnpPortBinding *port);
|
||||
int upnp_context_send_add_port_binding(LinphoneCore *lc, UpnpPortBinding *port);
|
||||
|
||||
/* Convert uPnP IGD logs to ortp logs */
|
||||
void linphone_upnp_igd_print(void *cookie, upnp_igd_print_level level, const char *fmt, va_list list) {
|
||||
int ortp_level = ORTP_DEBUG;
|
||||
|
|
@ -42,35 +51,292 @@ void linphone_upnp_igd_print(void *cookie, upnp_igd_print_level level, const cha
|
|||
void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) {
|
||||
LinphoneCore *lc = (LinphoneCore *)cookie;
|
||||
UpnpContext *lupnp = &lc->upnp;
|
||||
upnp_igd_port_mapping *mapping = NULL;
|
||||
UpnpPortBinding *port_mapping = NULL;
|
||||
const char *ip_address = NULL;
|
||||
const char *connection_status = NULL;
|
||||
bool_t nat_enabled = FALSE;
|
||||
|
||||
ms_mutex_lock(&lupnp->mutex);
|
||||
|
||||
switch(event) {
|
||||
case UPNP_IGD_EXTERNAL_IPADDRESS_CHANGED:
|
||||
case UPNP_IGD_NAT_ENABLED_CHANGED:
|
||||
case UPNP_IGD_CONNECTION_STATUS_CHANGED:
|
||||
ip_address = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt);
|
||||
connection_status = upnp_igd_get_connection_status(lupnp->upnp_igd_ctxt);
|
||||
nat_enabled = upnp_igd_get_nat_enabled(lupnp->upnp_igd_ctxt);
|
||||
|
||||
if(ip_address == NULL || connection_status == NULL) {
|
||||
lupnp->state = UPNP_Pending;
|
||||
} else if(strcasecmp(connection_status, "Connected") || !nat_enabled) {
|
||||
lupnp->state = UPNP_Ko;
|
||||
} else {
|
||||
// Emit add port binding
|
||||
// Emit remove old port binding
|
||||
lupnp->state = UPNP_Ok;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UPNP_IGD_PORT_MAPPING_ADD_SUCCESS:
|
||||
mapping = (upnp_igd_port_mapping *) arg;
|
||||
port_mapping = (UpnpPortBinding*) mapping->cookie;
|
||||
port_mapping->remote_port = mapping->remote_port;
|
||||
port_mapping->state = UPNP_Ok;
|
||||
// TODO: SAVE IN CONFIG THE PORT
|
||||
upnp_port_binding_release(port_mapping);
|
||||
break;
|
||||
|
||||
case UPNP_IGD_PORT_MAPPING_ADD_FAILURE:
|
||||
mapping = (upnp_igd_port_mapping *) arg;
|
||||
port_mapping = (UpnpPortBinding*) mapping->cookie;
|
||||
upnp_context_send_add_port_binding(lc, port_mapping);
|
||||
upnp_port_binding_release(port_mapping);
|
||||
break;
|
||||
|
||||
case UPNP_IGD_PORT_MAPPING_REMOVE_SUCCESS:
|
||||
mapping = (upnp_igd_port_mapping *) arg;
|
||||
port_mapping = (UpnpPortBinding*) mapping->cookie;
|
||||
port_mapping->remote_port = -1;
|
||||
port_mapping->state = UPNP_Idle;
|
||||
// TODO: REMOVE FROM CONFIG THE PORT
|
||||
upnp_port_binding_release(port_mapping);
|
||||
break;
|
||||
|
||||
case UPNP_IGD_PORT_MAPPING_REMOVE_FAILURE:
|
||||
mapping = (upnp_igd_port_mapping *) arg;
|
||||
port_mapping = (UpnpPortBinding*) mapping->cookie;
|
||||
upnp_context_send_remove_port_binding(lc, port_mapping);
|
||||
// TODO: REMOVE FROM CONFIG THE PORT (DON'T TRY ANYMORE)
|
||||
upnp_port_binding_release(port_mapping);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ms_mutex_unlock(&lupnp->mutex);
|
||||
}
|
||||
|
||||
int upnp_context_send_add_port_binding(LinphoneCore *lc, UpnpPortBinding *port) {
|
||||
UpnpContext *lupnp = &lc->upnp;
|
||||
upnp_igd_port_mapping mapping;
|
||||
char * local_host = NULL;
|
||||
int ret;
|
||||
if(port->state == UPNP_Idle) {
|
||||
port->remote_port = -1;
|
||||
port->retry = 0;
|
||||
port->state = UPNP_Pending;
|
||||
}
|
||||
if(port->retry >= UPNP_MAX_RETRY) {
|
||||
ret = -1;
|
||||
} else {
|
||||
local_host = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt);
|
||||
mapping.cookie = upnp_port_binding_retain(port);
|
||||
mapping.local_port = port->local_port;
|
||||
mapping.local_host = local_host;
|
||||
mapping.remote_port = rand()%1024 + 1024;
|
||||
mapping.remote_host = "";
|
||||
mapping.description = PACKAGE_NAME;
|
||||
mapping.protocol = port->protocol;
|
||||
|
||||
port->retry++;
|
||||
ret = upnp_igd_add_port_mapping(lupnp->upnp_igd_ctxt, &mapping);
|
||||
if(local_host != NULL) {
|
||||
free(local_host);
|
||||
}
|
||||
}
|
||||
if(ret != 0) {
|
||||
port->state = UPNP_Ko;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int upnp_context_send_remove_port_binding(LinphoneCore *lc, UpnpPortBinding *port) {
|
||||
UpnpContext *lupnp = &lc->upnp;
|
||||
upnp_igd_port_mapping mapping;
|
||||
int ret;
|
||||
if(port->state == UPNP_Idle) {
|
||||
port->retry = 0;
|
||||
port->state = UPNP_Pending;
|
||||
}
|
||||
if(port->retry >= UPNP_MAX_RETRY) {
|
||||
ret = -1;
|
||||
} else {
|
||||
mapping.cookie = upnp_port_binding_retain(port);
|
||||
mapping.remote_port = port->remote_port;
|
||||
mapping.remote_host = "";
|
||||
mapping.protocol = port->protocol;
|
||||
port->retry++;
|
||||
ret = upnp_igd_delete_port_mapping(lupnp->upnp_igd_ctxt, &mapping);
|
||||
}
|
||||
if(ret != 0) {
|
||||
port->state = UPNP_Ko;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int upnp_call_process(LinphoneCall *call) {
|
||||
LinphoneCore *lc = call->core;
|
||||
UpnpContext *lupnp = &lc->upnp;
|
||||
int ret = -1;
|
||||
|
||||
ms_mutex_lock(&lupnp->mutex);
|
||||
// Don't handle when the call
|
||||
if(lupnp->state != UPNP_Ko && call->upnp_session != NULL) {
|
||||
ret = 0;
|
||||
|
||||
/*
|
||||
* Audio part
|
||||
*/
|
||||
call->upnp_session->audio_rtp->local_port = call->audio_port;
|
||||
call->upnp_session->audio_rtcp->local_port = call->audio_port+1;
|
||||
if(call->upnp_session->audio_rtp->state == UPNP_Idle && call->audiostream != NULL) {
|
||||
// Add audio port binding
|
||||
upnp_context_send_add_port_binding(lc, call->upnp_session->audio_rtp);
|
||||
} else if(call->upnp_session->audio_rtp->state == UPNP_Ok && call->audiostream == NULL) {
|
||||
// Remove audio port binding
|
||||
upnp_context_send_remove_port_binding(lc, call->upnp_session->audio_rtp);
|
||||
}
|
||||
if(call->upnp_session->audio_rtcp->state == UPNP_Idle && call->audiostream != NULL) {
|
||||
// Add audio port binding
|
||||
upnp_context_send_add_port_binding(lc, call->upnp_session->audio_rtcp);
|
||||
} else if(call->upnp_session->audio_rtcp->state == UPNP_Ok && call->audiostream == NULL) {
|
||||
// Remove audio port binding
|
||||
upnp_context_send_remove_port_binding(lc, call->upnp_session->audio_rtcp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Video part
|
||||
*/
|
||||
call->upnp_session->video_rtp->local_port = call->video_port;
|
||||
call->upnp_session->video_rtcp->local_port = call->video_port+1;
|
||||
if(call->upnp_session->video_rtp->state == UPNP_Idle && call->videostream != NULL) {
|
||||
// Add video port binding
|
||||
upnp_context_send_add_port_binding(lc, call->upnp_session->video_rtp);
|
||||
} else if(call->upnp_session->video_rtp->state == UPNP_Ok && call->videostream == NULL) {
|
||||
// Remove video port binding
|
||||
upnp_context_send_remove_port_binding(lc, call->upnp_session->video_rtp);
|
||||
}
|
||||
if(call->upnp_session->video_rtcp->state == UPNP_Idle && call->videostream != NULL) {
|
||||
// Add video port binding
|
||||
upnp_context_send_add_port_binding(lc, call->upnp_session->video_rtcp);
|
||||
} else if(call->upnp_session->video_rtcp->state == UPNP_Ok && call->videostream == NULL) {
|
||||
// Remove video port binding
|
||||
upnp_context_send_remove_port_binding(lc, call->upnp_session->video_rtcp);
|
||||
}
|
||||
}
|
||||
ms_mutex_unlock(&lupnp->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call) {
|
||||
return upnp_call_process(call);
|
||||
}
|
||||
|
||||
int upnp_context_init(LinphoneCore *lc) {
|
||||
LCSipTransports transport;
|
||||
UpnpContext *lupnp = &lc->upnp;
|
||||
ms_mutex_init(&lupnp->mutex, NULL);
|
||||
lupnp->state = UPNP_Idle;
|
||||
|
||||
linphone_core_get_sip_transports(lc, &transport);
|
||||
if(transport.udp_port != 0) {
|
||||
lupnp->sip_udp = upnp_port_binding_new();
|
||||
lupnp->sip_udp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
} else {
|
||||
lupnp->sip_udp = NULL;
|
||||
}
|
||||
if(transport.tcp_port != 0) {
|
||||
lupnp->sip_tcp = upnp_port_binding_new();
|
||||
lupnp->sip_tcp->protocol = UPNP_IGD_IP_PROTOCOL_TCP;
|
||||
} else {
|
||||
lupnp->sip_tcp = NULL;
|
||||
}
|
||||
if(transport.tls_port != 0) {
|
||||
lupnp->sip_tls = upnp_port_binding_new();
|
||||
lupnp->sip_tls->protocol = UPNP_IGD_IP_PROTOCOL_TCP;
|
||||
} else {
|
||||
lupnp->sip_tls = NULL;
|
||||
}
|
||||
lupnp->upnp_igd_ctxt = NULL;
|
||||
lupnp->upnp_igd_ctxt = upnp_igd_create(linphone_upnp_igd_callback, linphone_upnp_igd_print, lc);
|
||||
if(lupnp->upnp_igd_ctxt == NULL) {
|
||||
if(lupnp->upnp_igd_ctxt == NULL ) {
|
||||
lupnp->state = UPNP_Ko;
|
||||
ms_error("Can't create uPnP IGD context");
|
||||
return -1;
|
||||
}
|
||||
lupnp->state = UPNP_Pending;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void upnp_context_uninit(LinphoneCore *lc) {
|
||||
// Emit remove port (sip & saved)
|
||||
UpnpContext *lupnp = &lc->upnp;
|
||||
if(lupnp->sip_udp != NULL) {
|
||||
upnp_port_binding_release(lupnp->sip_udp);
|
||||
}
|
||||
if(lupnp->sip_tcp != NULL) {
|
||||
upnp_port_binding_release(lupnp->sip_tcp);
|
||||
}
|
||||
if(lupnp->sip_tls != NULL) {
|
||||
upnp_port_binding_release(lupnp->sip_tls);
|
||||
}
|
||||
if(lupnp->upnp_igd_ctxt != NULL) {
|
||||
upnp_igd_destroy(lupnp->upnp_igd_ctxt);
|
||||
}
|
||||
ms_mutex_destroy(&lupnp->mutex);
|
||||
}
|
||||
|
||||
UpnpPortBinding *upnp_port_binding_new() {
|
||||
UpnpPortBinding *port = NULL;
|
||||
port = ms_new0(UpnpPortBinding,1);
|
||||
ms_mutex_init(&port->mutex, NULL);
|
||||
port->state = UPNP_Idle;
|
||||
port->local_port = -1;
|
||||
port->remote_port = -1;
|
||||
port->ref = 1;
|
||||
return port;
|
||||
}
|
||||
|
||||
UpnpPortBinding *upnp_port_binding_retain(UpnpPortBinding *port) {
|
||||
ms_mutex_lock(&port->mutex);
|
||||
port->ref++;
|
||||
ms_mutex_unlock(&port->mutex);
|
||||
return port;
|
||||
}
|
||||
|
||||
void upnp_port_binding_release(UpnpPortBinding *port) {
|
||||
ms_mutex_lock(&port->mutex);
|
||||
if(--port->ref == 0) {
|
||||
ms_mutex_unlock(&port->mutex);
|
||||
ms_mutex_destroy(&port->mutex);
|
||||
ms_free(port);
|
||||
return;
|
||||
}
|
||||
ms_mutex_unlock(&port->mutex);
|
||||
}
|
||||
|
||||
UpnpSession* upnp_session_new() {
|
||||
UpnpSession *session = ms_new0(UpnpSession,1);
|
||||
session->state = UPNP_Idle;
|
||||
session->audio_rtp = upnp_port_binding_new();
|
||||
session->audio_rtp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
session->audio_rtcp = upnp_port_binding_new();
|
||||
session->audio_rtcp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
session->video_rtp = upnp_port_binding_new();
|
||||
session->video_rtp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
session->video_rtcp = upnp_port_binding_new();
|
||||
session->video_rtcp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void upnp_session_destroy(UpnpSession* session) {
|
||||
upnp_port_binding_release(session->audio_rtp);
|
||||
upnp_port_binding_release(session->audio_rtcp);
|
||||
upnp_port_binding_release(session->video_rtp);
|
||||
upnp_port_binding_release(session->video_rtp);
|
||||
// TODO: send remove
|
||||
ms_free(session);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,15 +23,49 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "mediastreamer2/upnp_igd.h"
|
||||
#include "linphonecore.h"
|
||||
|
||||
typedef struct _UpnpSession {
|
||||
typedef enum {
|
||||
UPNP_Idle,
|
||||
UPNP_Pending,
|
||||
UPNP_Ok,
|
||||
UPNP_Ko,
|
||||
} UpnpState;
|
||||
|
||||
} UpnpSession;
|
||||
typedef struct _UpnpSession UpnpSession;
|
||||
|
||||
typedef struct _UpnpPortBinding {
|
||||
ms_mutex_t mutex;
|
||||
UpnpState state;
|
||||
upnp_igd_ip_protocol protocol;
|
||||
int local_port;
|
||||
int remote_port;
|
||||
int retry;
|
||||
int ref;
|
||||
} UpnpPortBinding;
|
||||
|
||||
struct _UpnpSession {
|
||||
UpnpPortBinding *audio_rtp;
|
||||
UpnpPortBinding *audio_rtcp;
|
||||
UpnpPortBinding *video_rtp;
|
||||
UpnpPortBinding *video_rtcp;
|
||||
UpnpState state;
|
||||
};
|
||||
|
||||
typedef struct _UpnpContext {
|
||||
upnp_igd_context *upnp_igd_ctxt;
|
||||
UpnpPortBinding *sip_tcp;
|
||||
UpnpPortBinding *sip_tls;
|
||||
UpnpPortBinding *sip_udp;
|
||||
UpnpState state;
|
||||
MSList *pending_bindinds;
|
||||
ms_mutex_t mutex;
|
||||
} UpnpContext;
|
||||
|
||||
|
||||
int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call);
|
||||
int upnp_call_process(LinphoneCall *call);
|
||||
UpnpSession* upnp_session_new();
|
||||
void upnp_session_destroy(UpnpSession* session);
|
||||
|
||||
int upnp_context_init(LinphoneCore *lc);
|
||||
void upnp_context_uninit(LinphoneCore *lc);
|
||||
|
||||
|
|
|
|||
|
|
@ -749,6 +749,23 @@
|
|||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="use_upnp">
|
||||
<property name="label" translatable="yes">Behind NAT / Firewall (use uPnP)</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">no_nat</property>
|
||||
<signal name="toggled" handler="linphone_gtk_use_upnp_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox24">
|
||||
<property name="visible">True</property>
|
||||
|
|
|
|||
|
|
@ -236,6 +236,11 @@ void linphone_gtk_use_ice_toggled(GtkWidget *w){
|
|||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseIce);
|
||||
}
|
||||
|
||||
void linphone_gtk_use_upnp_toggled(GtkWidget *w){
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseUpnp);
|
||||
}
|
||||
|
||||
void linphone_gtk_mtu_changed(GtkWidget *w){
|
||||
if (GTK_WIDGET_SENSITIVE(w))
|
||||
linphone_core_set_mtu(linphone_gtk_get_core(),gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)));
|
||||
|
|
@ -1038,6 +1043,9 @@ void linphone_gtk_show_parameters(void){
|
|||
case LinphonePolicyUseIce:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_ice")),TRUE);
|
||||
break;
|
||||
case LinphonePolicyUseUpnp:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_upnp")),TRUE);
|
||||
break;
|
||||
}
|
||||
mtu=linphone_core_get_mtu(lc);
|
||||
if (mtu<=0){
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit a1f113529f506aa178765cf70773db80e5768139
|
||||
Subproject commit 39998cb245606b904a77e093db168057f87bf8b0
|
||||
Loading…
Add table
Reference in a new issue