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;
}
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)
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);
}
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);
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 */
}
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);
}
ms_message("linphone_friend_apply() done.");
lc->bl_refresh=TRUE;
+ fr->commit=FALSE;
}
void linphone_friend_edit(LinphoneFriend *fr){
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 ;
}
}
}
+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);
{
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);
}
/*#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"
extern SalCallbacks linphone_sal_callbacks;
+
void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud)
{
obj->_func=func;
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;
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");
}
/**
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;
}
}
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);
}
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;
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;
}
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;
}
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;
}
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);
}
**/
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);
}
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;
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));
}
}
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);
}
}
}
+ lc->netup_time=curtime;
lc->network_reachable=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) {
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;
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);
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);
struct _LinphoneChatRoom{
struct _LinphoneCore *lc;
char *peer;
- char *route;
LinphoneAddress *peer_url;
+ SalOp *op;
void * user_data;
};
bool_t subscribe;
bool_t subscribe_active;
bool_t inc_subscribe_pending;
+ bool_t commit;
};
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;
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)
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;
}
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);
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);
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 !");
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);
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
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
/* 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;
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){
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;