diff --git a/coreapi/chat.c b/coreapi/chat.c index 357267962..3a41b4c9f 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -33,7 +33,6 @@ cr->lc=lc; cr->peer=linphone_address_as_string(parsed_url); cr->peer_url=parsed_url; - cr->route=ms_strdup(linphone_core_get_route(lc)); lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr); return cr; } @@ -46,11 +45,13 @@ lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr); linphone_address_destroy(cr->peer_url); ms_free(cr->peer); - ms_free(cr->route); + if (cr->op) + sal_op_release(cr->op); } void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){ - const char *identity=linphone_core_get_identity(cr->lc); + const char *route=NULL; + const char *identity=linphone_core_find_best_identity(cr->lc,cr->peer_url,&route); SalOp *op; LinphoneCall *call; if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL) @@ -61,7 +62,12 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){ else { op = sal_op_new(cr->lc->sal); - sal_op_set_route(op,cr->route); + sal_op_set_route(op,route); + if (cr->op!=NULL){ + sal_op_release (cr->op); + cr->op=NULL; + } + cr->op=op; } sal_text_send(op,identity,cr->peer,msg); } diff --git a/coreapi/friend.c b/coreapi/friend.c index 1af7a4cb5..1628d3e5f 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -128,6 +128,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ char *friend=NULL; const char *route=NULL; const char *from=NULL; + const char *fixed_contact=NULL; LinphoneProxyConfig *cfg; friend=linphone_address_as_string(fr->uri); @@ -135,6 +136,12 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ if (cfg!=NULL){ route=linphone_proxy_config_get_route(cfg); from=linphone_proxy_config_get_identity(cfg); + if (cfg->op){ + fixed_contact=sal_op_get_contact(cfg->op); + if (fixed_contact) { + ms_message("Contact for subscribe has been fixed using proxy to %s",fixed_contact); + } + } }else from=linphone_core_get_primary_contact(fr->lc); if (fr->outsub==NULL){ /* people for which we don't have yet an answer should appear as offline */ @@ -149,6 +156,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ } fr->outsub=sal_op_new(fr->lc->sal); sal_op_set_route(fr->outsub,route); + sal_op_set_contact(fr->outsub,fixed_contact); sal_subscribe_presence(fr->outsub,from,friend); fr->subscribe_active=TRUE; ms_free(friend); @@ -367,6 +375,7 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ } ms_message("linphone_friend_apply() done."); lc->bl_refresh=TRUE; + fr->commit=FALSE; } void linphone_friend_edit(LinphoneFriend *fr){ @@ -391,7 +400,8 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf) return ; } lc->friends=ms_list_append(lc->friends,lf); - linphone_friend_apply(lf,lc); + if ( linphone_core_ready(lc)) linphone_friend_apply(lf,lc); + else lf->commit=TRUE; return ; } @@ -404,6 +414,15 @@ void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){ } } +void linphone_core_send_initial_subscribes(LinphoneCore *lc){ + const MSList *elem; + for(elem=lc->friends;elem!=NULL;elem=elem->next){ + LinphoneFriend *f=(LinphoneFriend*)elem->data; + if (f->commit) + linphone_friend_apply(f,lc); + } +} + void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key){ if (lf->refkey!=NULL){ ms_free(lf->refkey); @@ -562,7 +581,7 @@ void linphone_core_write_friends_config(LinphoneCore* lc) { MSList *elem; int i; - if (!lc->ready) return; /*dont write config when reading it !*/ + if (! linphone_core_ready(lc)) return; /*dont write config when reading it !*/ for (elem=lc->friends,i=0; elem!=NULL; elem=ms_list_next(elem),i++){ linphone_friend_write_to_config_file(lc->config,(LinphoneFriend*)elem->data,i); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 775d6712f..b9e7fe518 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -38,7 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /*#define UNSTANDART_GSM_11K 1*/ static const char *liblinphone_version=LIBLINPHONE_VERSION; -static void set_network_reachable(LinphoneCore* lc,bool_t isReachable); +static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime); #include "enum.h" @@ -52,6 +52,7 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val); extern SalCallbacks linphone_sal_callbacks; + void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud) { obj->_func=func; @@ -103,7 +104,7 @@ static void call_logs_write_to_config_file(LinphoneCore *lc){ char *tmp; LpConfig *cfg=lc->config; - if (!lc->ready) return; + if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return; for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){ LinphoneCallLog *cl=(LinphoneCallLog*)elem->data; @@ -996,10 +997,8 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta ui_config_read(lc); if (lc->vtable.display_status) lc->vtable.display_status(lc,_("Ready")); - linphone_core_set_state(lc,LinphoneGlobalOn,"Ready"); lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon; - - lc->ready=TRUE; + linphone_core_set_state(lc,LinphoneGlobalOn,"Ready"); } /** @@ -1529,7 +1528,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ if (new_status){ ms_message("New local ip address is %s",result); } - set_network_reachable(lc,new_status); + set_network_reachable(lc,new_status, curtime); last_status=new_status; } } @@ -1724,6 +1723,12 @@ void linphone_core_iterate(LinphoneCore *lc){ linphone_core_do_plugin_tasks(lc); + if (lc->initial_subscribes_sent==FALSE && lc->netup_time!=0 && + (curtime-lc->netup_time)>3){ + linphone_core_send_initial_subscribes(lc); + lc->initial_subscribes_sent=TRUE; + } + if (one_second_elapsed && lp_config_needs_commit(lc->config)){ lp_config_sync(lc->config); } @@ -1861,6 +1866,17 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L return found_cfg; } +const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to, const char **route){ + LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(lc,to); + if (cfg==NULL) + linphone_core_get_default_proxy (lc,&cfg); + if (cfg!=NULL){ + *route=linphone_proxy_config_get_route(cfg); + return linphone_proxy_config_get_identity (cfg); + } + return linphone_core_get_primary_contact (lc); +} + static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){ LinphoneAddress *ctt; const char *localip=call->localip; @@ -2669,7 +2685,7 @@ bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *dev int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){ MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK); lc->sound_conf.ring_sndcard=card; - if (card && lc->ready) + if (card && linphone_core_ready(lc)) lp_config_set_string(lc->config,"sound","ringer_dev_id",ms_snd_card_get_string_id(card)); return 0; } @@ -2683,7 +2699,7 @@ int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){ int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){ MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK); lc->sound_conf.play_sndcard=card; - if (card && lc->ready) + if (card && linphone_core_ready(lc)) lp_config_set_string(lc->config,"sound","playback_dev_id",ms_snd_card_get_string_id(card)); return 0; } @@ -2697,7 +2713,7 @@ int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){ int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid){ MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_CAPTURE); lc->sound_conf.capt_sndcard=card; - if (card && lc->ready) + if (card && linphone_core_ready(lc)) lp_config_set_string(lc->config,"sound","capture_dev_id",ms_snd_card_get_string_id(card)); return 0; } @@ -2788,7 +2804,7 @@ void linphone_core_set_ring(LinphoneCore *lc,const char *path){ ms_free(lc->sound_conf.local_ring); } lc->sound_conf.local_ring=ms_strdup(path); - if (lc->ready && lc->sound_conf.local_ring) + if ( linphone_core_ready(lc) && lc->sound_conf.local_ring) lp_config_set_string(lc->config,"sound","local_ring",lc->sound_conf.local_ring); } @@ -2852,7 +2868,7 @@ const char * linphone_core_get_ringback(const LinphoneCore *lc){ **/ void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bool_t val){ lc->sound_conf.ec=val; - if (lc->ready) + if ( linphone_core_ready(lc)) lp_config_set_int(lc->config,"sound","echocancellation",val); } @@ -3162,7 +3178,7 @@ int linphone_core_set_video_device(LinphoneCore *lc, const char *id){ if (olddev!=NULL && olddev!=lc->video_conf.device){ toggle_video_preview(lc,FALSE);/*restart the video local preview*/ } - if (lc->ready && lc->video_conf.device){ + if ( linphone_core_ready(lc) && lc->video_conf.device){ vd=ms_web_cam_get_string_id(lc->video_conf.device); if (vd && strstr(vd,"Static picture")!=NULL){ vd=NULL; @@ -3381,7 +3397,7 @@ void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize) toggle_video_preview(lc,FALSE); toggle_video_preview(lc,TRUE); } - if (lc->ready) + if ( linphone_core_ready(lc)) lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize)); } } @@ -3798,7 +3814,7 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); } -static void set_network_reachable(LinphoneCore* lc,bool_t isReachable){ +static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){ ms_message("Network state is now [%s]",isReachable?"UP":"DOWN"); // second get the list of available proxies const MSList *elem=linphone_core_get_proxy_config_list(lc); @@ -3812,6 +3828,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable){ } } } + lc->netup_time=curtime; lc->network_reachable=isReachable; } @@ -3821,7 +3838,7 @@ void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t isReachable) { ms_message("Disabling automatic network state monitoring"); lc->auto_net_state_mon=FALSE; } - set_network_reachable(lc,isReachable); + set_network_reachable(lc,isReachable, ms_time(NULL)); } bool_t linphone_core_is_network_reachabled(LinphoneCore* lc) { diff --git a/coreapi/presence.c b/coreapi/presence.c index 57e764c38..500ce6d7e 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -57,11 +57,24 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ LinphoneFriend *lf=NULL; char *tmp; LinphoneAddress *uri; + LinphoneProxyConfig *cfg; + const char *fixed_contact; uri=linphone_address_new(from); linphone_address_clean(uri); tmp=linphone_address_as_string(uri); ms_message("Receiving new subscription from %s.",from); + + cfg=linphone_core_lookup_known_proxy(lc,uri); + if (cfg!=NULL){ + if (cfg->op){ + fixed_contact=sal_op_get_contact(cfg->op); + if (fixed_contact) { + sal_op_set_contact (op,fixed_contact); + ms_message("Contact for next subscribe answer has been fixed using proxy to %s",fixed_contact); + } + } + } /* check if we answer to this subscription */ if (linphone_find_friend(lc->friends,uri,&lf)!=NULL){ lf->insub=op; diff --git a/coreapi/private.h b/coreapi/private.h index c965bf4ac..9bee983b6 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -166,6 +166,7 @@ void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc); void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCore *lc, const PayloadType *pt); void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call); +void linphone_core_send_initial_subscribes(LinphoneCore *lc); void linphone_core_write_friends_config(LinphoneCore* lc); void linphone_friend_write_to_config_file(struct _LpConfig *config, LinphoneFriend *lf, int index); LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc, int index); @@ -173,6 +174,7 @@ LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc, void linphone_proxy_config_update(LinphoneProxyConfig *cfg); void linphone_proxy_config_get_contact(LinphoneProxyConfig *cfg, const char **ip, int *port); LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri); +const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to, const char **route); int linphone_core_get_local_ip_for(int type, const char *dest, char *result); LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(struct _LpConfig *config, int index); @@ -238,8 +240,8 @@ struct _LinphoneAuthInfo struct _LinphoneChatRoom{ struct _LinphoneCore *lc; char *peer; - char *route; LinphoneAddress *peer_url; + SalOp *op; void * user_data; }; @@ -255,6 +257,7 @@ struct _LinphoneFriend{ bool_t subscribe; bool_t subscribe_active; bool_t inc_subscribe_pending; + bool_t commit; }; @@ -412,9 +415,10 @@ struct _LinphoneCore void *wait_ctx; unsigned long video_window_id; unsigned long preview_window_id; + time_t netup_time; /*time when network went reachable */ bool_t use_files; bool_t apply_nat_settings; - bool_t ready; + bool_t initial_subscribes_sent; bool_t bl_refresh; bool_t preview_finished; bool_t auto_net_state_mon; @@ -433,6 +437,8 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call, bool_t with_video, bool_t only_one_codec); +#define linphone_core_ready(lc) ((lc)->state!=LinphoneGlobalStartup) + #define HOLD_OFF (0) #define HOLD_ON (1) diff --git a/coreapi/proxy.c b/coreapi/proxy.c index c946d988e..aa901cb8d 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -167,10 +167,16 @@ int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route) obj->reg_route=NULL; } if (route!=NULL){ + LinphoneAddress *addr; /*try to prepend 'sip:' */ if (strstr(route,"sip:")==NULL){ obj->reg_route=ms_strdup_printf("sip:%s",route); }else obj->reg_route=ms_strdup(route); + addr=linphone_address_new(obj->reg_route); + if (addr==NULL){ + ms_free(obj->reg_route); + obj->reg_route=NULL; + }else linphone_address_destroy(addr); } return 0; } @@ -694,7 +700,7 @@ void linphone_proxy_config_update(LinphoneProxyConfig *cfg){ if (cfg->type && cfg->ssctx==NULL){ linphone_proxy_config_activate_sip_setup(cfg); } - if (lc->sip_conf.register_only_when_network_is_up || lc->network_reachable) + if (!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable) linphone_proxy_config_register(cfg); if (cfg->publish && cfg->publish_op==NULL){ linphone_proxy_config_send_publish(cfg,lc->presence_mode); diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 0db619d0b..c61ec96ab 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void text_received(Sal *sal, eXosip_event_t *ev); -static void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)){ +void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)){ void *data; while((data=osip_list_get(l,0))!=NULL){ osip_list_remove(l,0); @@ -102,7 +102,7 @@ static SalOp * sal_find_other(Sal *sal, osip_message_t *response){ return NULL; } -static void sal_add_other(Sal *sal, SalOp *op, osip_message_t *request){ +void sal_add_other(Sal *sal, SalOp *op, osip_message_t *request){ osip_call_id_t *callid=osip_message_get_call_id(request); if (callid==NULL) { ms_error("There is no call id in the request !"); diff --git a/coreapi/sal_eXosip2.h b/coreapi/sal_eXosip2.h index 88afb1c21..bfb3d10f2 100644 --- a/coreapi/sal_eXosip2.h +++ b/coreapi/sal_eXosip2.h @@ -66,6 +66,7 @@ struct SalOp{ void sal_remove_out_subscribe(Sal *sal, SalOp *op); void sal_remove_in_subscribe(Sal *sal, SalOp *op); +void sal_add_other(Sal *sal, SalOp *op, osip_message_t *request); void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev); void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev); @@ -76,5 +77,6 @@ void sal_exosip_in_subscription_closed(Sal *sal, eXosip_event_t *ev); SalOp * sal_find_out_subscribe(Sal *sal, int sid); void sal_exosip_fix_route(SalOp *op); +void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*)); #endif diff --git a/coreapi/sal_eXosip2_presence.c b/coreapi/sal_eXosip2_presence.c index bf94edcb3..1e7409f19 100644 --- a/coreapi/sal_eXosip2_presence.c +++ b/coreapi/sal_eXosip2_presence.c @@ -83,9 +83,14 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ eXosip_lock(); eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op), sal_op_get_from(op),sal_op_get_route(op)); - osip_message_set_content_type(sip,"text/plain"); - osip_message_set_body(sip,msg,strlen(msg)); - eXosip_message_send_request(sip); + if (sip!=NULL){ + osip_message_set_content_type(sip,"text/plain"); + osip_message_set_body(sip,msg,strlen(msg)); + sal_add_other(op->base.root,op,sip); + eXosip_message_send_request(sip); + }else{ + ms_error("Could not build MESSAGE request !"); + } eXosip_unlock(); } else @@ -93,22 +98,16 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ /* we are currently in communication with the destination */ eXosip_lock(); //First we generate an INFO message to get the current call_id and a good cseq - eXosip_call_build_info(op->did,&sip); + eXosip_call_build_request(op->did,"MESSAGE",&sip); if(sip == NULL) { ms_warning("could not get a build info to send MESSAGE, maybe no previous call established ?"); - osip_message_free(sip); eXosip_unlock(); return -1; } - //change the sip_message to be a MESSAGE ... - osip_free(osip_message_get_method(sip)); - osip_message_set_method(sip,osip_strdup("MESSAGE")); - osip_free(osip_cseq_get_method(osip_message_get_cseq(sip))); - osip_cseq_set_method(osip_message_get_cseq(sip),osip_strdup("MESSAGE")); osip_message_set_content_type(sip,"text/plain"); osip_message_set_body(sip,msg,strlen(msg)); - eXosip_message_send_request(sip); + eXosip_call_send_request(op->did,sip); eXosip_unlock(); } return 0; @@ -125,6 +124,10 @@ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ eXosip_lock(); eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op), sal_op_get_route(op),"presence",600); + if (op->base.contact){ + _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); + osip_message_set_contact(msg,op->base.contact); + } op->sid=eXosip_subscribe_send_initial_request(msg); eXosip_unlock(); if (op->sid==-1){ @@ -156,6 +159,10 @@ int sal_subscribe_accept(SalOp *op){ osip_message_t *msg; eXosip_lock(); eXosip_insubscription_build_answer(op->tid,202,&msg); + if (op->base.contact){ + _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); + osip_message_set_contact(msg,op->base.contact); + } eXosip_insubscription_send_answer(op->tid,202,msg); eXosip_unlock(); return 0;