From: Yann Diorcet Date: Fri, 4 Jan 2013 15:19:13 +0000 (+0100) Subject: Working call with uPnP X-Git-Url: http://sjero.net/git/?p=linphone;a=commitdiff_plain;h=f3805137e6c2f4821450ed6391ebc92a727ec7fd Working call with uPnP --- diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index b3d1a6bb..4eec5be3 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -253,6 +253,12 @@ static void call_received(SalOp *h){ return; } + if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) && (call->upnp_session != NULL)) { + /* Defer ringing until the end of the ICE candidates gathering process. */ + ms_message("Defer ringing to gather uPnP candidates"); + return; + } + linphone_core_notify_incoming_call(lc,call); } @@ -325,6 +331,11 @@ static void call_accepted(SalOp *op){ if (call->ice_session != NULL) { linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op)); } +#ifdef BUILD_UPNP + if (call->upnp_session != NULL) { + linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op)); + } +#endif //BUILD_UPNP md=sal_call_get_final_media_description(op); call->params.has_video &= linphone_core_media_description_contains_video_stream(md); @@ -418,6 +429,7 @@ static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){ } #ifdef BUILD_UPNP if(call->upnp_session != NULL) { + linphone_core_update_upnp_from_remote_media_description(call, rmd); linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session); } #endif @@ -516,6 +528,10 @@ static void call_terminated(SalOp *op, const char *from){ if (lc->vtable.display_status!=NULL) lc->vtable.display_status(lc,_("Call terminated.")); +#ifdef BUILD_UPNP + linphone_call_delete_upnp_session(call); +#endif //BUILD_UPNP + linphone_call_set_state(call, LinphoneCallEnd,"Call ended"); } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 2ab398ba..ec76311a 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -444,7 +444,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr call->op=sal_op_new(lc->sal); sal_op_set_user_pointer(call->op,call); call->core=lc; - linphone_core_get_public_ip(lc,linphone_address_get_domain(to),call->localip); + linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip); linphone_call_init_common(call,from,to); call->params=*params; if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { @@ -491,7 +491,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro } linphone_address_clean(from); - linphone_core_get_public_ip(lc,linphone_address_get_domain(from),call->localip); + linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip); linphone_call_init_common(call, from, to); call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/ linphone_core_init_default_params(lc, &call->params); @@ -524,9 +524,9 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro case LinphonePolicyUseUpnp: #ifdef BUILD_UPNP call->upnp_session = upnp_session_new(call); - if (call->ice_session != NULL) { + if (call->upnp_session != NULL) { linphone_call_init_media_streams(call); - if (linphone_core_update_upnp(call->core,call)<0) { + if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) { /* uPnP port mappings failed, proceed with the call anyway. */ linphone_call_delete_upnp_session(call); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index ddd9eaea..7abce8e9 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1306,7 +1306,7 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact) /*result must be an array of chars at least LINPHONE_IPADDR_SIZE */ -void linphone_core_get_public_ip(LinphoneCore *lc, const char *dest, char *result){ +void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result){ const char *ip; if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){ @@ -1318,6 +1318,7 @@ void linphone_core_get_public_ip(LinphoneCore *lc, const char *dest, char *resul && lc->upnp.state == LinphoneUpnpStateOk) { ip = upnp_igd_get_external_ipaddress(lc->upnp.upnp_igd_ctxt); strncpy(result,ip,LINPHONE_IPADDR_SIZE); + return; } #endif if (linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,dest,result)==0) @@ -1340,7 +1341,7 @@ static void update_primary_contact(LinphoneCore *lc){ ms_error("Could not parse identity contact !"); url=linphone_address_new("sip:unknown@unkwownhost"); } - linphone_core_get_public_ip(lc, NULL, tmp); + linphone_core_get_local_ip(lc, NULL, tmp); if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){ ms_warning("Local loopback network only !"); lc->sip_conf.loopback_only=TRUE; @@ -2268,6 +2269,7 @@ static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphonePr int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){ bool_t ice_ready = FALSE; + bool_t upnp_ready = FALSE; bool_t ping_ready = FALSE; if (call->ice_session != NULL) { @@ -2275,13 +2277,20 @@ int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *c } else { ice_ready = TRUE; } +#ifdef BUILD_UPNP + if (call->upnp_session != NULL) { + if (call->upnp_session->state == LinphoneUpnpStateOk) upnp_ready = TRUE; + } else { + upnp_ready = TRUE; + } +#endif //BUILD_UPNP if (call->ping_op != NULL) { if (call->ping_replied == TRUE) ping_ready = TRUE; } else { ping_ready = TRUE; } - if ((ice_ready == TRUE) && (ping_ready == TRUE)) { + if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) { return linphone_core_start_invite(lc, call); } return 0; @@ -2843,6 +2852,14 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const #if BUILD_UPNP if(call->upnp_session != NULL) { + if ((call->params.has_video) && (call->params.has_video != old_has_video)) { + linphone_call_init_video_stream(call); + video_stream_prepare_video(call->videostream); + if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op))<0) { + /* uPnP update failed, proceed with the call anyway. */ + linphone_call_delete_upnp_session(call); + } else return 0; + } } #endif //BUILD_UPNP @@ -4961,6 +4978,10 @@ static void linphone_core_uninit(LinphoneCore *lc) lc->config = NULL; /* Mark the config as NULL to block further calls */ sip_setup_unregister_all(); +#ifdef BUILD_UPNP + upnp_context_uninit(lc); +#endif + ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy); lc->call_logs=ms_list_free(lc->call_logs); @@ -4973,9 +4994,6 @@ static void linphone_core_uninit(LinphoneCore *lc) #ifdef TUNNEL_ENABLED if (lc->tunnel) linphone_tunnel_destroy(lc->tunnel); #endif -#ifdef BUILD_UPNP - upnp_context_uninit(lc); -#endif } static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){ diff --git a/coreapi/misc.c b/coreapi/misc.c index d7572213..6e49d56a 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1021,14 +1021,15 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size) if (ifp->ifa_addr && ifp->ifa_addr->sa_family == type && (ifp->ifa_flags & UP_FLAG) && !(ifp->ifa_flags & IFF_LOOPBACK)) { - getnameinfo(ifp->ifa_addr, + if(getnameinfo(ifp->ifa_addr, (type == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in), - address, size, NULL, 0, NI_NUMERICHOST); - if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */ - /*ms_message("getifaddrs() found %s",address);*/ - ret++; - break; + address, size, NULL, 0, NI_NUMERICHOST) == 0) { + if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */ + /*ms_message("getifaddrs() found %s",address);*/ + ret++; + break; + } } } } @@ -1099,26 +1100,26 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul } int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ - strcpy(result,type==AF_INET ? "127.0.0.1" : "::1"); + strcpy(result,type==AF_INET ? "127.0.0.1" : "::1"); #ifdef HAVE_GETIFADDRS - if (dest==NULL) { - /*we use getifaddrs for lookup of default interface */ - int found_ifs; - - found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE); - if (found_ifs==1){ - return 0; - }else if (found_ifs<=0){ - /*absolutely no network on this machine */ - return -1; - } - } + if (dest==NULL) { + /*we use getifaddrs for lookup of default interface */ + int found_ifs; + + found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE); + if (found_ifs==1){ + return 0; + }else if (found_ifs<=0){ + /*absolutely no network on this machine */ + return -1; + } + } #endif - /*else use connect to find the best local ip address */ - if (type==AF_INET) - dest="87.98.157.38"; /*a public IP address*/ - else dest="2a00:1450:8002::68"; - return get_local_ip_for_with_connect(type,dest,result); + /*else use connect to find the best local ip address */ + if (type==AF_INET) + dest="87.98.157.38"; /*a public IP address*/ + else dest="2a00:1450:8002::68"; + return get_local_ip_for_with_connect(type,dest,result); } #ifndef WIN32 diff --git a/coreapi/private.h b/coreapi/private.h index e110a03e..d4abf16c 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -206,7 +206,7 @@ int set_lock_file(); int get_lock_file(); int remove_lock_file(); void check_sound_device(LinphoneCore *lc); -void linphone_core_get_public_ip(LinphoneCore *lc, const char *to, char *result); +void linphone_core_get_local_ip(LinphoneCore *lc, const char *to, char *result); bool_t host_has_ipv6_network(); bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret); @@ -593,9 +593,6 @@ int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call); int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call); int linphone_core_get_calls_nb(const LinphoneCore *lc); -void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); -void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); - void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call); void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index ff046f92..82b3b300 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -268,7 +268,7 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){ LCSipTransports tr; LinphoneAddress *contact; - linphone_core_get_public_ip(obj->lc,host,localip); + linphone_core_get_local_ip(obj->lc,host,localip); contact=linphone_address_new(obj->reg_identity); linphone_address_set_domain (contact,localip); linphone_address_set_port_int(contact,linphone_core_get_sip_port(obj->lc)); diff --git a/coreapi/upnp.c b/coreapi/upnp.c index 0de86121..4cb41d7a 100644 --- a/coreapi/upnp.c +++ b/coreapi/upnp.c @@ -53,6 +53,7 @@ UpnpPortBinding *upnp_port_binding_new(); UpnpPortBinding *upnp_port_binding_copy(const UpnpPortBinding *port); bool_t upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2); UpnpPortBinding *upnp_port_binding_retain(UpnpPortBinding *port); +void upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port); void upnp_port_binding_release(UpnpPortBinding *port); MSList *upnp_config_list_port_bindings(struct _LpConfig *lpc); @@ -62,6 +63,7 @@ int upnp_config_remove_port_binding(LinphoneCore *lc, const UpnpPortBinding *por int upnp_context_send_remove_port_binding(LinphoneCore *lc, UpnpPortBinding *port); int upnp_context_send_add_port_binding(LinphoneCore *lc, UpnpPortBinding *port); + /** * uPnP Callbacks */ @@ -74,10 +76,10 @@ void linphone_upnp_igd_print(void *cookie, upnp_igd_print_level level, const cha ortp_level = ORTP_MESSAGE; break; case UPNP_IGD_WARNING: - ortp_level = ORTP_WARNING; + ortp_level = ORTP_DEBUG; // Too verbose otherwise break; case UPNP_IGD_ERROR: - ortp_level = ORTP_ERROR; + ortp_level = ORTP_DEBUG; // Too verbose otherwise break; default: break; @@ -121,11 +123,7 @@ void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) { port_mapping = (UpnpPortBinding*) mapping->cookie; port_mapping->external_port = mapping->remote_port; port_mapping->state = LinphoneUpnpStateOk; - ms_message("uPnP IGD: Added port binding %s|%d->%s:%d", - (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port_mapping->external_port, - port_mapping->local_addr, - port_mapping->local_port); + upnp_port_binding_log(ORTP_MESSAGE, "Added port binding", port_mapping); upnp_config_add_port_binding(lc, port_mapping); upnp_port_binding_release(port_mapping); @@ -135,11 +133,7 @@ void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) { mapping = (upnp_igd_port_mapping *) arg; port_mapping = (UpnpPortBinding*) mapping->cookie; if(upnp_context_send_add_port_binding(lc, port_mapping) != 0) { - ms_error("uPnP IGD: Can't add port binding %s|%d->%s:%d", - (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port_mapping->external_port, - port_mapping->local_addr, - port_mapping->local_port); + upnp_port_binding_log(ORTP_ERROR, "Can't add port binding", port_mapping); } upnp_port_binding_release(port_mapping); @@ -149,10 +143,7 @@ void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) { mapping = (upnp_igd_port_mapping *) arg; port_mapping = (UpnpPortBinding*) mapping->cookie; port_mapping->state = LinphoneUpnpStateIdle; - ms_message("uPnP IGD: Removed port binding %s|%d->%d", - (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port_mapping->external_port, - port_mapping->local_port); + upnp_port_binding_log(ORTP_MESSAGE, "Removed port binding", port_mapping); upnp_config_remove_port_binding(lc, port_mapping); upnp_port_binding_release(port_mapping); @@ -162,10 +153,7 @@ void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) { mapping = (upnp_igd_port_mapping *) arg; port_mapping = (UpnpPortBinding*) mapping->cookie; if(upnp_context_send_remove_port_binding(lc, port_mapping) != 0) { - ms_error("uPnP IGD: Can't remove port binding %s|%d->%d", - (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port_mapping->external_port, - port_mapping->local_port); + upnp_port_binding_log(ORTP_ERROR, "Can't remove port binding", port_mapping); upnp_config_remove_port_binding(lc, port_mapping); } @@ -304,7 +292,7 @@ int upnp_context_send_remove_port_binding(LinphoneCore *lc, UpnpPortBinding *por UpnpContext *lupnp = &lc->upnp; upnp_igd_port_mapping mapping; int ret; - if(port->state == LinphoneUpnpStateIdle) { + if(port->state == LinphoneUpnpStateOk) { port->retry = 0; port->state = LinphoneUpnpStateRemoving; } else if(port->state != LinphoneUpnpStateRemoving) { @@ -332,11 +320,10 @@ int upnp_context_send_remove_port_binding(LinphoneCore *lc, UpnpPortBinding *por * uPnP Core interfaces */ -int upnp_call_process(LinphoneCall *call) { +int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool_t video) { LinphoneCore *lc = call->core; UpnpContext *lupnp = &lc->upnp; int ret = -1; - UpnpState oldState; const char *local_addr, *external_addr; ms_mutex_lock(&lupnp->mutex); @@ -355,34 +342,20 @@ int upnp_call_process(LinphoneCall *call) { strncpy(call->upnp_session->audio->rtcp->local_addr, local_addr, LINPHONE_IPADDR_SIZE); strncpy(call->upnp_session->audio->rtcp->external_addr, external_addr, LINPHONE_IPADDR_SIZE); call->upnp_session->audio->rtcp->local_port = call->audio_port+1; - if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateIdle && call->audiostream != NULL) { + if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateIdle && audio) { // Add audio port binding upnp_context_send_add_port_binding(lc, call->upnp_session->audio->rtp); - } else if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateOk && call->audiostream == NULL) { + } else if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateOk && !audio) { // Remove audio port binding upnp_context_send_remove_port_binding(lc, call->upnp_session->audio->rtp); } - if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateIdle && call->audiostream != NULL) { + if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateIdle && audio) { // Add audio port binding upnp_context_send_add_port_binding(lc, call->upnp_session->audio->rtcp); - } else if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateOk && call->audiostream == NULL) { + } else if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateOk && !audio) { // Remove audio port binding upnp_context_send_remove_port_binding(lc, call->upnp_session->audio->rtcp); } - if((call->upnp_session->audio->rtp->state == LinphoneUpnpStateOk || call->upnp_session->audio->rtp->state == LinphoneUpnpStateIdle) && - (call->upnp_session->audio->rtcp->state == LinphoneUpnpStateOk || call->upnp_session->audio->rtcp->state == LinphoneUpnpStateIdle)) { - call->upnp_session->audio->state = LinphoneUpnpStateOk; - } else if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateAdding || - call->upnp_session->audio->rtp->state == LinphoneUpnpStateRemoving || - call->upnp_session->audio->rtcp->state == LinphoneUpnpStateAdding || - call->upnp_session->audio->rtcp->state == LinphoneUpnpStateRemoving) { - call->upnp_session->audio->state = LinphoneUpnpStatePending; - } else if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateKo || - call->upnp_session->audio->rtp->state == LinphoneUpnpStateKo) { - call->upnp_session->audio->state = LinphoneUpnpStateKo; - } else { - call->upnp_session->audio->state = LinphoneUpnpStateIdle; - } /* * Video part @@ -393,20 +366,82 @@ int upnp_call_process(LinphoneCall *call) { strncpy(call->upnp_session->video->rtcp->local_addr, local_addr, LINPHONE_IPADDR_SIZE); strncpy(call->upnp_session->video->rtcp->external_addr, external_addr, LINPHONE_IPADDR_SIZE); call->upnp_session->video->rtcp->local_port = call->video_port+1; - if(call->upnp_session->video->rtp->state == LinphoneUpnpStateIdle && call->videostream != NULL) { + if(call->upnp_session->video->rtp->state == LinphoneUpnpStateIdle && video) { // Add video port binding upnp_context_send_add_port_binding(lc, call->upnp_session->video->rtp); - } else if(call->upnp_session->video->rtp->state == LinphoneUpnpStateOk && call->videostream == NULL) { + } else if(call->upnp_session->video->rtp->state == LinphoneUpnpStateOk && !video) { // Remove video port binding upnp_context_send_remove_port_binding(lc, call->upnp_session->video->rtp); } - if(call->upnp_session->video->rtcp->state == LinphoneUpnpStateIdle && call->videostream != NULL) { + if(call->upnp_session->video->rtcp->state == LinphoneUpnpStateIdle && video) { // Add video port binding upnp_context_send_add_port_binding(lc, call->upnp_session->video->rtcp); - } else if(call->upnp_session->video->rtcp->state == LinphoneUpnpStateOk && call->videostream == NULL) { + } else if(call->upnp_session->video->rtcp->state == LinphoneUpnpStateOk && !video) { // 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_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md) { + bool_t audio = FALSE; + bool_t video = FALSE; + int i; + const SalStreamDescription *stream; + + for (i = 0; i < md->nstreams; i++) { + stream = &md->streams[i]; + if(stream->type == SalAudio) { + audio = TRUE; + } else if(stream->type == SalVideo) { + video = TRUE; + } + } + + return linphone_core_update_upnp_audio_video(call, audio, video); +} + +int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call) { + return linphone_core_update_upnp_audio_video(call, call->audiostream!=NULL, call->videostream!=NULL); +} + +int upnp_call_process(LinphoneCall *call) { + LinphoneCore *lc = call->core; + UpnpContext *lupnp = &lc->upnp; + int ret = -1; + UpnpState oldState; + + ms_mutex_lock(&lupnp->mutex); + + // Don't handle when the call + if(lupnp->state == LinphoneUpnpStateOk && call->upnp_session != NULL) { + ret = 0; + + /* + * Update Audio state + */ + if((call->upnp_session->audio->rtp->state == LinphoneUpnpStateOk || call->upnp_session->audio->rtp->state == LinphoneUpnpStateIdle) && + (call->upnp_session->audio->rtcp->state == LinphoneUpnpStateOk || call->upnp_session->audio->rtcp->state == LinphoneUpnpStateIdle)) { + call->upnp_session->audio->state = LinphoneUpnpStateOk; + } else if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateAdding || + call->upnp_session->audio->rtp->state == LinphoneUpnpStateRemoving || + call->upnp_session->audio->rtcp->state == LinphoneUpnpStateAdding || + call->upnp_session->audio->rtcp->state == LinphoneUpnpStateRemoving) { + call->upnp_session->audio->state = LinphoneUpnpStatePending; + } else if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateKo || + call->upnp_session->audio->rtp->state == LinphoneUpnpStateKo) { + call->upnp_session->audio->state = LinphoneUpnpStateKo; + } else { + call->upnp_session->audio->state = LinphoneUpnpStateIdle; + } + + /* + * Update Video state + */ if((call->upnp_session->video->rtp->state == LinphoneUpnpStateOk || call->upnp_session->video->rtp->state == LinphoneUpnpStateIdle) && (call->upnp_session->video->rtcp->state == LinphoneUpnpStateOk || call->upnp_session->video->rtcp->state == LinphoneUpnpStateIdle)) { call->upnp_session->video->state = LinphoneUpnpStateOk; @@ -442,18 +477,23 @@ int upnp_call_process(LinphoneCall *call) { /* When change is done proceed update */ if(oldState != LinphoneUpnpStateOk && oldState != LinphoneUpnpStateKo && (call->upnp_session->state == LinphoneUpnpStateOk || call->upnp_session->state == LinphoneUpnpStateKo)) { + if(call->upnp_session->state == LinphoneUpnpStateOk) + ms_message("uPnP IGD: uPnP for Call %p is ok", call); + else + ms_message("uPnP IGD: uPnP for Call %p is ko", call); + switch (call->state) { case LinphoneCallUpdating: - linphone_core_start_update_call(call->core, call); + linphone_core_start_update_call(lc, call); break; case LinphoneCallUpdatedByRemote: - linphone_core_start_accept_call_update(call->core, call); + linphone_core_start_accept_call_update(lc, call); break; case LinphoneCallOutgoingInit: - linphone_core_proceed_with_invite_if_ready(call->core, call, NULL); + linphone_core_proceed_with_invite_if_ready(lc, call, NULL); break; case LinphoneCallIdle: - linphone_core_notify_incoming_call(call->core, call); + linphone_core_notify_incoming_call(lc, call); break; default: break; @@ -465,10 +505,6 @@ int upnp_call_process(LinphoneCall *call) { return ret; } -int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call) { - return upnp_call_process(call); -} - bool_t linphone_core_upnp_hook(void *data) { char key[64]; MSList *port_bindings = NULL; @@ -512,7 +548,7 @@ bool_t linphone_core_upnp_hook(void *data) { (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", port_mapping->external_port, port_mapping->local_port); - lp_config_set_string(lc->config, UPNP_SECTION_NAME, key, ""); + lp_config_set_string(lc->config, UPNP_SECTION_NAME, key, "uPnP"); } if(port_mapping->state == LinphoneUpnpStateRemoving) { snprintf(key, sizeof(key), "%s-%d-%d", @@ -583,6 +619,21 @@ UpnpPortBinding *upnp_port_binding_copy(const UpnpPortBinding *port) { return new_port; } +void upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port) { + if(strlen(port->local_addr)) { + ortp_log(level, "uPnP IGD: %s %s|%d->%s:%d", msg, + (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", + port->external_port, + port->local_addr, + port->local_port); + } else { + ortp_log(level, "uPnP IGD: %s %s|%d->%d", msg, + (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", + port->external_port, + port->local_port); + } +} + bool_t upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2) { return port1->protocol == port2->protocol && port1->local_port == port2->local_port && port1->external_port && port2->external_port; @@ -606,6 +657,7 @@ void upnp_port_binding_release(UpnpPortBinding *port) { ms_mutex_unlock(&port->mutex); } + /* * uPnP Stream */ @@ -617,7 +669,7 @@ UpnpStream* upnp_stream_new() { stream->rtp->protocol = UPNP_IGD_IP_PROTOCOL_UDP; stream->rtcp = upnp_port_binding_new(); stream->rtcp->protocol = UPNP_IGD_IP_PROTOCOL_UDP; - return NULL; + return stream; } void upnp_stream_destroy(UpnpStream* stream) { @@ -636,7 +688,7 @@ UpnpSession* upnp_session_new() { session->state = LinphoneUpnpStateIdle; session->audio = upnp_stream_new(); session->video = upnp_stream_new(); - return NULL; + return session; } void upnp_session_destroy(LinphoneCall* call) { @@ -696,6 +748,7 @@ MSList *upnp_config_list_port_bindings(struct _LpConfig *lpc) { } if(valid) { port = upnp_port_binding_new(); + port->state = LinphoneUpnpStateOk; port->protocol = protocol; port->external_port = external_port; port->local_port = local_port; diff --git a/coreapi/upnp.h b/coreapi/upnp.h index 492b3523..b515d041 100644 --- a/coreapi/upnp.h +++ b/coreapi/upnp.h @@ -72,6 +72,7 @@ typedef struct _UpnpContext { } UpnpContext; void linphone_core_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session); +int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md); int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call); int upnp_call_process(LinphoneCall *call); UpnpSession* upnp_session_new();