sal in progress, near to code complete.

This commit is contained in:
Simon Morlat 2010-02-05 18:42:34 +01:00
parent 9fc1a85d4f
commit fdd99cd205
18 changed files with 735 additions and 1158 deletions

View file

@ -51,7 +51,6 @@ LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *useri
if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1);
if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
obj->works=FALSE;
obj->first_time=TRUE;
return obj;
}
@ -252,7 +251,6 @@ void linphone_core_add_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info)
}
refresh_exosip_auth_info(lc);
/* if the user was prompted, re-allow automatic_action */
if (lc->automatic_action>0) lc->automatic_action--;
}

View file

@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphonecore.h"
#include "private.h"
#include "mediastreamer2/mediastream.h"
static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
if (lc->vtable.show)
@ -37,9 +38,8 @@ static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
}
static void call_received(SalOp *h){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
char *barmesg;
int err;
LinphoneCall *call;
const char *from,*to;
char *tmp;
@ -62,34 +62,34 @@ static void call_received(SalOp *h){
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
else
sal_call_decline(h,SalReasonBusy,NULL);
sal_op_release(op);
sal_op_release(h);
return;
}
if (lc->call!=NULL){/*busy*/
sal_call_decline(h,SalReasonBusy,NULL);
sal_op_release(op);
sal_op_release(h);
return;
}
from=sal_op_get_from(op);
to=sal_op_get_to(op);
from=sal_op_get_from(h);
to=sal_op_get_to(h);
call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),op);
call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),h);
lc->call=call;
sal_call_set_local_media_description(op,call->localdesc);
call->resultdesc=sal_call_get_final_media_description(op);
if (call->resultdesc && sal_media_description_empty(call->resultdesc){
sal_call_decline(op,SalReasonMedia,NULL);
sal_call_set_local_media_description(h,call->localdesc);
call->resultdesc=sal_call_get_final_media_description(h);
if (call->resultdesc && sal_media_description_empty(call->resultdesc)){
sal_call_decline(h,SalReasonMedia,NULL);
linphone_call_destroy(call);
lc->call=NULL;
return;
}
from_parsed=linphone_address_new(sal_op_get_from(op));
from_parsed=linphone_address_new(sal_op_get_from(h));
linphone_address_clean(from_parsed);
tmp=linphone_address_as_string(from_parsed);
linphone_address_destroy(from_parsed);
gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
barmesg=ortp_strdup_printf(_("%s is contacting you"),tmp);
if (lc->vtable.show) lc->vtable.show(lc);
if (lc->vtable.display_status)
lc->vtable.display_status(lc,barmesg);
@ -100,7 +100,7 @@ static void call_received(SalOp *h){
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
}
linphone_call_set_state(call,LCStateRinging);
sal_call_notify_ringing(op);
sal_call_notify_ringing(h);
if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
ms_free(barmesg);
@ -108,7 +108,7 @@ static void call_received(SalOp *h){
}
static void call_ringing(SalOp *h){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneCall *call=lc->call;
SalMediaDescription *md;
if (call==NULL) return;
@ -145,18 +145,18 @@ static void call_ringing(SalOp *h){
}
static void call_accepted(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=lc->call;
if (call==NULL){
ms_warning("No call to accept.");
return 0;
return ;
}
if (sal_op_get_user_pointer(op)!=lc->call){
ms_warning("call_accepted: ignoring.");
return;
}
if (call->state==LCStateAVRunning){
return 0; /*already accepted*/
return ; /*already accepted*/
}
if (lc->audiostream->ticker!=NULL){
/*case where we accepted early media */
@ -176,8 +176,8 @@ static void call_accepted(SalOp *op){
}
}
static void call_ack(SalOp *h){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
static void call_ack(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=lc->call;
if (call==NULL){
ms_warning("No call to be ACK'd");
@ -205,8 +205,9 @@ static void call_ack(SalOp *h){
}
}
static void call_updated(SalOp *){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
static void call_updated(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
linphone_core_stop_media_streams(lc,call);
linphone_core_init_media_streams(lc,call);
if (call->resultdesc)
@ -217,8 +218,8 @@ static void call_updated(SalOp *){
}
}
static void call_terminated(SalOp *h, const char *from){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
static void call_terminated(SalOp *op, const char *from){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
if (sal_op_get_user_pointer(op)!=lc->call){
ms_warning("call_terminated: ignoring.");
return;
@ -236,7 +237,7 @@ static void call_terminated(SalOp *h, const char *from){
LinphoneAddress *addr=linphone_address_new(from);
char *tmp;
linphone_address_clean(addr);
tmp=linphone_address_as_string(from);
tmp=linphone_address_as_string(addr);
lc->vtable.bye_recv(lc,tmp);
ms_free(tmp);
linphone_address_destroy(addr);
@ -246,16 +247,14 @@ static void call_terminated(SalOp *h, const char *from){
}
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
const char *reason="";
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
char *msg486=_("User is busy.");
char *msg480=_("User is temporarily unavailable.");
/*char *retrymsg=_("%s. Retry after %i minute(s).");*/
char *msg600=_("User does not want to be disturbed.");
char *msg603=_("Call declined.");
char* tmpmsg=msg486;
int code;
LinphoneCall *call=lc->call;
if (sal_op_get_user_pointer(op)!=lc->call){
ms_warning("call_failure: ignoring.");
return;
@ -263,10 +262,10 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
if (lc->vtable.show) lc->vtable.show(lc);
if (error==SalErrorNoResponse){
if (lc->vtale.display_status)
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("No response."));
}else if (error==SalErrorProtocol){
if (lc->vtale.display_status)
if (lc->vtable.display_status)
lc->vtable.display_status(lc, details ? details : _("Error."));
}else if (error==SalErrorFailure){
switch(sr){
@ -288,7 +287,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
break;
case SalReasonNotFound:
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg404);
lc->vtable.display_status(lc,_("Not found"));
break;
case SalReasonDoNotDisturb:
if (lc->vtable.display_status)
@ -307,7 +306,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
ring_stop(lc->ringstream);
lc->ringstream=NULL;
}
linphone_core_stop_media_streams(lc);
linphone_core_stop_media_streams(lc,call);
if (call!=NULL) {
linphone_call_destroy(call);
gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
@ -316,41 +315,94 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
}
static void auth_requested(SalOp *h, const char *realm, const char *username){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc);
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc,realm,username);
if (ai && (ai->works || ai->usecount<3)){
SalAuthInfo sai;
sai.username=ai->username;
sai.userid=ai->userid;
sai.realm=ai->realm;
sai.password=ai->passwd;
sal_op_authenticate(h,&sai);
ai->usecount++;
}else{
if (lc->vtable.auth_info_requested)
lc->vtable.auth_info_requested(lc,realm,username);
}
}
static void auth_success(SalOp *h, const char *realm, const char *username){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc,realm,username);
if (ai)
ai->works=TRUE;
}
static void register_success(SalOp *op, bool_t registered){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
char *msg;
gstate_new_state(lc, GSTATE_REG_OK, NULL);
if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op));
else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op));
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg);
ms_free(msg);
}
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),(details!=NULL) ? details : _("no response timeout"));
if (lc->vtable.display_status) lc->vtable.display_status(lc,msg);
gstate_new_state(lc, GSTATE_REG_FAILED, msg);
ms_free(msg);
}
static void vfu_request(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
#ifdef VIDEO_ENABLED
if (lc->videostream)
video_stream_send_vfu(lc->videostream);
#endif
}
static void dtmf_received(SalOp *op, char dtmf){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
if (lc->vtable.dtmf_received != NULL)
lc->vtable.dtmf_received(lc, dtmf);
}
static void refer_received(SalOp *op, SalOp *op, const char *referto){
static void refer_received(Sal *sal, SalOp *op, const char *referto){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
if (lc->vtable.refer_received)
lc->vtable.refer_received(lc,referto);
}
static void text_received(Sal *sal, const char *from, const char *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
linphone_core_text_received(lc,from,msg);
}
static void presence_changed(SalOp *op, SalPresenceStatus status, const char *msg){
static void notify(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
linphone_notify_recv(lc,op,ss,status);
}
static void subscribe_received(SalOp *op, const char *from){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
linphone_subscription_new(lc,op,from);
}
static void internal_message(SalOp *op, const char *msg){
static void subscribe_closed(SalOp *op, const char *from){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
linphone_subscription_closed(lc,op);
}
static void internal_message(Sal *sal, const char *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
if (lc->vtable.show)
lc->vtable.show(lc);
}
SalCallbacks linphone_sal_callbacks={
call_received,
@ -368,8 +420,9 @@ SalCallbacks linphone_sal_callbacks={
dtmf_received,
refer_received,
text_received,
presence_changed,
notify,
subscribe_received,
subscribe_closed,
internal_message
};

View file

@ -24,7 +24,6 @@
#include "linphonecore.h"
#include "private.h"
#include <eXosip2/eXosip.h>
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
LinphoneAddress *parsed_url=NULL;
@ -52,11 +51,10 @@
void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){
const char *identity=linphone_core_get_identity(cr->lc);
osip_message_t *sip=NULL;
eXosip_message_build_request(&sip,"MESSAGE",cr->peer,identity,cr->route);
osip_message_set_content_type(sip,"text/plain");
osip_message_set_body(sip,msg,strlen(msg));
eXosip_message_send_request(sip);
SalOp *op=sal_op_new(cr->lc->sal);
sal_op_set_route(op,cr->route);
sal_text_send(op,identity,cr->peer,msg);
}
bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
@ -69,40 +67,29 @@ void linphone_chat_room_text_received(LinphoneChatRoom *cr, LinphoneCore *lc, co
if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, from, msg);
}
void linphone_core_text_received(LinphoneCore *lc, eXosip_event_t *ev){
void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg){
MSList *elem;
const char *msg;
LinphoneChatRoom *cr=NULL;
char *from;
osip_from_t *from_url=ev->request->from;
osip_body_t *body=NULL;
LinphoneAddress *uri;
LinphoneAddress *addr;
char *cleanfrom;
osip_message_get_body(ev->request,0,&body);
if (body==NULL){
ms_error("Could not get text message from SIP body");
return;
}
msg=body->body;
osip_from_to_str(from_url,&from);
uri=linphone_address_new(from);
osip_free(from);
linphone_address_clean(uri);
addr=linphone_address_new(from);
linphone_address_clean(addr);
for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
cr=(LinphoneChatRoom*)elem->data;
if (linphone_chat_room_matches(cr,uri)){
if (linphone_chat_room_matches(cr,addr)){
break;
}
cr=NULL;
}
from=linphone_address_as_string(uri);
cleanfrom=linphone_address_as_string(addr);
if (cr==NULL){
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,from);
cr=linphone_core_create_chat_room(lc,cleanfrom);
}
linphone_address_destroy(uri);
linphone_chat_room_text_received(cr,lc,from,msg);
ms_free(from);
linphone_address_destroy(addr);
linphone_chat_room_text_received(cr,lc,cleanfrom,msg);
ms_free(cleanfrom);
}

View file

@ -31,9 +31,6 @@
const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
const char *str=NULL;
switch(ss){
case LINPHONE_STATUS_UNKNOWN:
str=_("Unknown");
break;
case LINPHONE_STATUS_ONLINE:
str=_("Online");
break;
@ -67,9 +64,6 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
case LINPHONE_STATUS_PENDING:
str=_("Pending");
break;
case LINPHONE_STATUS_CLOSED:
str=_("Closed");
break;
default:
str=_("Unknown-bug");
}
@ -114,20 +108,20 @@ MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *friend, Linphone
return res;
}
LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid){
LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op){
MSList *elem;
for (elem=l;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
if (lf->nid==nid) return lf;
if (lf->insub==op) return lf;
}
return NULL;
}
LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid){
LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){
MSList *elem;
for (elem=l;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend*)elem->data;
if (lf->sid==sid) return lf;
if (lf->outsub==op) return lf;
}
return NULL;
}
@ -136,30 +130,30 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
char *friend=NULL;
const char *route=NULL;
const char *from=NULL;
osip_message_t *msg=NULL;
LinphoneProxyConfig *cfg;
friend=linphone_address_as_string(fr->uri);
if (fr->proxy!=NULL){
route=fr->proxy->reg_route;
from=fr->proxy->reg_identity;
cfg=linphone_core_lookup_known_proxy(fr->lc,linphone_friend_get_address(fr));
if (cfg!=NULL){
route=linphone_proxy_config_get_route(cfg);
from=linphone_proxy_config_get_identity(cfg);
}else from=linphone_core_get_primary_contact(fr->lc);
if (fr->sid<0){
if (fr->outsub==NULL){
/* people for which we don't have yet an answer should appear as offline */
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr,friend,_("Gone"),"sip-closed.png");
if (fr->lc->vtable.notify_recv)
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr,friend,_("Gone"),"sip-closed.png");
}else{
sal_op_release(fr->outsub);
fr->outsub=NULL;
}
eXosip_lock();
eXosip_subscribe_build_initial_request(&msg,friend,from,route,"presence",600);
eXosip_subscribe_send_initial_request(msg);
eXosip_unlock();
fr->outsub=sal_op_new(fr->lc->sal);
sal_op_set_route(fr->outsub,route);
sal_subscribe_presence(fr->outsub,from,friend);
ms_free(friend);
}
LinphoneFriend * linphone_friend_new(){
LinphoneFriend *obj=ms_new0(LinphoneFriend,1);
obj->out_did=-1;
obj->in_did=-1;
obj->nid=-1;
obj->sid=-1;
obj->pol=LinphoneSPAccept;
obj->status=LINPHONE_STATUS_OFFLINE;
obj->subscribe=TRUE;
@ -214,6 +208,7 @@ int linphone_friend_set_sip_addr(LinphoneFriend *lf, const char *addr){
ms_warning("Invalid friend sip uri: %s",addr);
return -1;
}
linphone_address_clean(fr);
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
lf->uri=fr;
return 0;
@ -240,335 +235,79 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri
return 0;
}
int linphone_friend_set_proxy(LinphoneFriend *fr, struct _LinphoneProxyConfig *cfg){
fr->proxy=cfg;
return 0;
SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){
switch(os){
case LINPHONE_STATUS_OFFLINE:
return SalPresenceOffline;
break;
case LINPHONE_STATUS_ONLINE:
return SalPresenceOnline;
break;
case LINPHONE_STATUS_BUSY:
return SalPresenceBusy;
break;
case LINPHONE_STATUS_BERIGHTBACK:
return SalPresenceBerightback;
break;
case LINPHONE_STATUS_AWAY:
return SalPresenceAway;
break;
case LINPHONE_STATUS_ONTHEPHONE:
return SalPresenceOnthephone;
break;
case LINPHONE_STATUS_OUTTOLUNCH:
return SalPresenceOuttolunch;
break;
case LINPHONE_STATUS_NOT_DISTURB:
return SalPresenceDonotdisturb;
break;
case LINPHONE_STATUS_MOVED:
return SalPresenceMoved;
break;
case LINPHONE_STATUS_ALT_SERVICE:
return SalPresenceAltService;
break;
case LINPHONE_STATUS_PENDING:
return SalPresenceOffline;
break;
default:
return SalPresenceOffline;
break;
}
return SalPresenceOffline;
}
void linphone_friend_set_sid(LinphoneFriend *lf, int sid){
lf->sid=sid;
}
void linphone_friend_set_nid(LinphoneFriend *lf, int nid){
lf->nid=nid;
lf->inc_subscribe_pending=TRUE;
}
void add_presence_body(osip_message_t *notify, LinphoneOnlineStatus online_status)
{
char buf[1000];
#ifdef SUPPORT_MSN
int atom_id = 1000;
#endif
char *contact_info;
osip_contact_t *ct=NULL;
osip_message_get_contact(notify,0,&ct);
osip_contact_to_str(ct,&contact_info);
#ifdef SUPPORT_MSN
if (online_status==LINPHONE_STATUS_ONLINE)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"online\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_BUSY)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"busy\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_BERIGHTBACK)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"berightback\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_AWAY)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_ONTHEPHONE)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"onthephone\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==LINPHONE_STATUS_OUTTOLUNCH)
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"outtolunch\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else
{
sprintf(buf, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence\n\
PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s;user=ip\" priority=\"0.800000\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/xpidf+xml");
#else
if (online_status==LINPHONE_STATUS_ONLINE)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>online</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_BUSY)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>busy</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>busy</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_BERIGHTBACK)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>in-transit</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>be right back</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_AWAY)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>away</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>away</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_ONTHEPHONE)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>on-the-phone</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>on the phone</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==LINPHONE_STATUS_OUTTOLUNCH)
{
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>meal</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>out to lunch</note>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else
{
/* */
sprintf(buf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n%s",
contact_info,
"<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>closed</basic>\n\
<es:activities>\n\
<es:activity>permanent-absence</es:activity>\n\
</es:activities>\n\
</status>\n\
</tuple>\n\
\n</presence>\n");
}
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/pidf+xml");
#endif
osip_free(contact_info);
}
void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os){
void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os){
//printf("Wish to notify %p, lf->nid=%i\n",lf,lf->nid);
if (lf->in_did!=-1){
osip_message_t *msg=NULL;
const char *identity;
if (lf->proxy!=NULL) identity=lf->proxy->reg_identity;
else identity=linphone_core_get_primary_contact(lf->lc);
eXosip_lock();
eXosip_insubscription_build_notify(lf->in_did,ss,0,&msg);
if (msg!=NULL){
osip_message_set_contact(msg,identity);
add_presence_body(msg,os);
eXosip_insubscription_send_request(lf->in_did,msg);
}else ms_error("could not create notify for incoming subscription.");
eXosip_unlock();
if (lf->insub!=NULL){
sal_notify_presence(lf->insub,linphone_online_status_to_sal(os),NULL);
}
}
static void linphone_friend_unsubscribe(LinphoneFriend *lf){
if (lf->out_did!=-1) {
osip_message_t *msg=NULL;
eXosip_lock();
eXosip_subscribe_build_refresh_request(lf->out_did,&msg);
if (msg){
osip_message_set_expires(msg,"0");
eXosip_subscribe_send_refresh_request(lf->out_did,msg);
}else ms_error("Could not build subscribe refresh request !");
eXosip_unlock();
if (lf->outsub!=NULL) {
sal_unsubscribe(lf->outsub);
sal_op_release(lf->outsub);
lf->outsub=NULL;
}
}
void linphone_friend_destroy(LinphoneFriend *lf){
linphone_friend_notify(lf,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
linphone_friend_notify(lf,LINPHONE_STATUS_OFFLINE);
linphone_friend_unsubscribe(lf);
if (lf->insub){
sal_notify_close(lf->insub);
sal_op_release(lf->insub);
}
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
if (lf->info!=NULL) buddy_info_free(lf->info);
ms_free(lf);
}
void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, LinphoneProxyConfig *cfg){
if (lf->proxy==cfg){
lf->proxy=NULL;
}
}
const LinphoneAddress *linphone_friend_get_uri(const LinphoneFriend *lf){
return lf->uri;
}
bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf){
return lf->subscribe;
}
@ -597,21 +336,21 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
if (fr->inc_subscribe_pending){
switch(fr->pol){
case LinphoneSPWait:
linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_PENDING,LINPHONE_STATUS_PENDING);
linphone_friend_notify(fr,LINPHONE_STATUS_PENDING);
break;
case LinphoneSPAccept:
if (fr->lc!=NULL)
{
linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_ACTIVE,fr->lc->presence_mode);
linphone_friend_notify(fr,fr->lc->presence_mode);
}
break;
case LinphoneSPDeny:
linphone_friend_notify(fr,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
linphone_friend_notify(fr,LINPHONE_STATUS_OFFLINE);
break;
}
fr->inc_subscribe_pending=FALSE;
}
if (fr->subscribe && fr->out_did==-1){
if (fr->subscribe && fr->outsub==NULL){
__linphone_friend_do_subscribe(fr);
}
@ -632,6 +371,14 @@ void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf)
{
ms_return_if_fail(lf->lc==NULL);
ms_return_if_fail(lf->uri!=NULL);
if (ms_list_find(lc->friends,lf)!=NULL){
char *tmp=NULL;
const LinphoneAddress *addr=linphone_friend_get_address(lf);
if (addr) tmp=linphone_address_as_string(addr);
ms_warning("Friend %s already in list, ignored.", tmp ? tmp : "unknown");
if (tmp) ms_free(tmp);
return ;
}
lc->friends=ms_list_append(lc->friends,lf);
linphone_friend_apply(lf,lc);
return ;
@ -667,7 +414,7 @@ static bool_t username_match(const char *u1, const char *u2){
return FALSE;
}
LinphoneFriend *linphone_core_get_friend_by_uri(const LinphoneCore *lc, const char *uri){
LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *uri){
LinphoneAddress *puri=linphone_address_new(uri);
const MSList *elem;
const char *username=linphone_address_get_username(puri);
@ -752,10 +499,6 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde
a=lp_config_get_int(config,item,"subscribe",0);
linphone_friend_send_subscribe(lf,a);
a=lp_config_get_int(config,item,"proxy",-1);
if (a!=-1) {
linphone_friend_set_proxy(lf,__index_to_proxy(lc,a));
}
linphone_friend_set_ref_key(lf,lp_config_get_string(config,item,"refkey",NULL));
return lf;
}
@ -779,7 +522,6 @@ const char *__policy_enum_to_str(LinphoneSubscribePolicy pol){
void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf, int index){
char key[50];
char *tmp;
int a;
const char *refkey;
sprintf(key,"friend_%i",index);
@ -798,10 +540,6 @@ void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf,
}
lp_config_set_string(config,key,"pol",__policy_enum_to_str(lf->pol));
lp_config_set_int(config,key,"subscribe",lf->subscribe);
if (lf->proxy!=NULL){
a=ms_list_index(lf->lc->sip_conf.proxies,lf->proxy);
lp_config_set_int(config,key,"proxy",a);
}else lp_config_set_int(config,key,"proxy",-1);
refkey=linphone_friend_get_ref_key(lf);
if (refkey){

View file

@ -650,28 +650,72 @@ static void rtp_config_read(LinphoneCore *lc)
linphone_core_set_nortp_timeout(lc,nortp_timeout);
}
static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, const char *recv_fmtp){
PayloadType *candidate=NULL;
int i;
PayloadType *it;
for(i=0;i<127;++i){
it=rtp_profile_get_payload(prof,i);
if (it!=NULL && strcasecmp(mime_type,it->mime_type)==0
&& (clock_rate==it->clock_rate || clock_rate<=0) ){
if ( (recv_fmtp && it->recv_fmtp && strcasecmp(recv_fmtp,it->recv_fmtp)==0) ||
(recv_fmtp==NULL && it->recv_fmtp==NULL) ){
/*exact match*/
return it;
}else candidate=it;
}
}
return candidate;
}
static PayloadType * get_codec(LpConfig *config, char* type,int index){
static bool_t get_codec(LpConfig *config, char* type, int index, PayloadType **ret){
char codeckey[50];
const char *mime,*fmtp;
int rate,enabled;
PayloadType *pt;
*ret=NULL;
snprintf(codeckey,50,"%s_%i",type,index);
mime=lp_config_get_string(config,codeckey,"mime",NULL);
if (mime==NULL || strlen(mime)==0 ) return NULL;
pt=payload_type_new();
pt->mime_type=ms_strdup(mime);
if (mime==NULL || strlen(mime)==0 ) return FALSE;
rate=lp_config_get_int(config,codeckey,"rate",8000);
pt->clock_rate=rate;
fmtp=lp_config_get_string(config,codeckey,"recv_fmtp",NULL);
if (fmtp) pt->recv_fmtp=ms_strdup(fmtp);
enabled=lp_config_get_int(config,codeckey,"enabled",1);
if (enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
pt=find_payload(&av_profile,mime,rate,fmtp);
if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
//ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate);
return pt;
if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported",
mime,rate,fmtp ? fmtp : "");
*ret=pt;
return TRUE;
}
static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
int i;
for(i=0;i<127;++i){
PayloadType *pt=rtp_profile_get_payload(&av_profile,i);
if (pt){
if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
pt=NULL;
else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED
&& pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
pt=NULL;
}
if (pt && ms_filter_codec_supported(pt->mime_type)){
if (ms_list_find(l,pt)==NULL){
ms_message("Adding new codec %s/%i with fmtp %s",
pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
if (strcasecmp(pt->mime_type,"speex")==0 ||
strcasecmp(pt->mime_type,"MP4V-ES")==0 ||
strcasecmp(pt->mime_type,"H264")==0)
l=ms_list_prepend(l,pt);
else l=ms_list_append(l,pt);
}
}
}
}
return l;
}
static void codecs_config_read(LinphoneCore *lc)
@ -680,23 +724,28 @@ static void codecs_config_read(LinphoneCore *lc)
PayloadType *pt;
MSList *audio_codecs=NULL;
MSList *video_codecs=NULL;
for (i=0;;i++){
pt=get_codec(lc->config,"audio_codec",i);
if (pt==NULL) break;
audio_codecs=ms_list_append(audio_codecs,(void *)pt);
for (i=0;get_codec(lc->config,"audio_codec",i,&pt);i++){
if (pt){
if (!ms_filter_codec_supported(pt->mime_type)){
ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
}else audio_codecs=ms_list_append(audio_codecs,pt);
}
}
for (i=0;;i++){
pt=get_codec(lc->config,"video_codec",i);
if (pt==NULL) break;
video_codecs=ms_list_append(video_codecs,(void *)pt);
audio_codecs=add_missing_codecs(SalAudio,audio_codecs);
for (i=0;get_codec(lc->config,"video_codec",i,&pt);i++){
if (pt){
if (!ms_filter_codec_supported(pt->mime_type)){
ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
}else video_codecs=ms_list_append(video_codecs,(void *)pt);
}
}
video_codecs=add_missing_codecs(SalVideo,video_codecs);
linphone_core_set_audio_codecs(lc,audio_codecs);
linphone_core_set_video_codecs(lc,video_codecs);
linphone_core_setup_local_rtp_profile(lc);
linphone_core_update_allocated_audio_bandwidth(lc);
}
static void video_config_read(LinphoneCore *lc)
{
static void video_config_read(LinphoneCore *lc){
int capture, display, self_view;
int enabled;
const char *str;
@ -868,6 +917,9 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
gstate_new_state(lc, GSTATE_POWER_STARTUP, NULL);
ortp_init();
linphone_core_assign_payload_type(&payload_type_pcmu8000,0,NULL);
linphone_core_assign_payload_type(&payload_type_gsm,3,NULL);
linphone_core_assign_payload_type(&payload_type_pcma8000,8,NULL);
linphone_core_assign_payload_type(&payload_type_lpc1015,115,NULL);
linphone_core_assign_payload_type(&payload_type_speex_nb,110,"vbr=on");
linphone_core_assign_payload_type(&payload_type_speex_wb,111,"vbr=on");
@ -1383,7 +1435,7 @@ static void proxy_update(LinphoneCore *lc, time_t curtime){
}
static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){
LinphoneFriend *lf=linphone_core_get_friend_by_uri(lc,info->sip_uri);
LinphoneFriend *lf=linphone_core_get_friend_by_address(lc,info->sip_uri);
if (lf!=NULL){
lf->info=info;
ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data);
@ -1647,7 +1699,7 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L
static char *get_fixed_contact(LinphoneCore *lc, const char *localip, LinphoneProxyConfig *dest_proxy){
LinphoneAddress *ctt;
if (dest_proxy){
if (dest_proxy && dest_proxy->op){
const char *fixed_contact=sal_op_get_contact(dest_proxy->op);
if (fixed_contact) {
ms_message("Contact has been fixed using proxy to %s",fixed_contact);
@ -3178,10 +3230,6 @@ void codecs_config_uninit(LinphoneCore *lc)
lp_config_set_string(lc->config,key,"recv_fmtp",pt->recv_fmtp);
index++;
}
if (lc->local_profile){
rtp_profile_destroy(lc->local_profile);
lc->local_profile=NULL;
}
}
void ui_config_uninit(LinphoneCore* lc)

View file

@ -139,7 +139,7 @@ typedef enum{
}LinphoneSubscribePolicy;
typedef enum _LinphoneOnlineStatus{
LINPHONE_STATUS_UNKNOWN,
LINPHONE_STATUS_OFFLINE,
LINPHONE_STATUS_ONLINE,
LINPHONE_STATUS_BUSY,
LINPHONE_STATUS_BERIGHTBACK,
@ -149,9 +149,7 @@ typedef enum _LinphoneOnlineStatus{
LINPHONE_STATUS_NOT_DISTURB,
LINPHONE_STATUS_MOVED,
LINPHONE_STATUS_ALT_SERVICE,
LINPHONE_STATUS_OFFLINE,
LINPHONE_STATUS_PENDING,
LINPHONE_STATUS_CLOSED,
LINPHONE_STATUS_END
}LinphoneOnlineStatus;
@ -167,11 +165,10 @@ int linphone_friend_set_sip_addr(LinphoneFriend *fr, const char *uri);
int linphone_friend_set_name(LinphoneFriend *fr, const char *name);
int linphone_friend_send_subscribe(LinphoneFriend *fr, bool_t val);
int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscribePolicy pol);
int linphone_friend_set_proxy(LinphoneFriend *fr, struct _LinphoneProxyConfig *cfg);
void linphone_friend_edit(LinphoneFriend *fr);
void linphone_friend_done(LinphoneFriend *fr);
void linphone_friend_destroy(LinphoneFriend *lf);
const LinphoneAddress *linphone_friend_get_uri(const LinphoneFriend *lf);
const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf);
bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf);
LinphoneSubscribePolicy linphone_friend_get_inc_subscribe_policy(const LinphoneFriend *lf);
LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf);
@ -208,8 +205,8 @@ typedef struct _LinphoneProxyConfig LinphoneProxyConfig;
LinphoneProxyConfig *linphone_proxy_config_new(void);
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr);
void linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
void linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
void linphone_proxy_config_expires(LinphoneProxyConfig *obj, int expires);
void linphone_proxy_config_enable_register(LinphoneProxyConfig *obj, bool_t val);
#define linphone_proxy_config_enableregister linphone_proxy_config_enable_register
@ -638,7 +635,7 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf);
const MSList * linphone_core_get_friend_list(const LinphoneCore *lc);
/* notify all friends that have subscribed */
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os);
LinphoneFriend *linphone_core_get_friend_by_uri(const LinphoneCore *lc, const char *uri);
LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *addr);
LinphoneFriend *linphone_core_get_friend_by_ref_key(const LinphoneCore *lc, const char *key);
/* returns a list of LinphoneCallLog */

View file

@ -295,152 +295,6 @@ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType
return ret;
}
static PayloadType * find_payload(RtpProfile *prof, PayloadType *pt /*from config*/){
PayloadType *candidate=NULL;
int i;
PayloadType *it;
for(i=0;i<127;++i){
it=rtp_profile_get_payload(prof,i);
if (it!=NULL && strcasecmp(pt->mime_type,it->mime_type)==0
&& (pt->clock_rate==it->clock_rate || pt->clock_rate<=0)
&& payload_type_get_user_data(it)==NULL ){
if ( (pt->recv_fmtp && it->recv_fmtp && strcasecmp(pt->recv_fmtp,it->recv_fmtp)==0) ||
(pt->recv_fmtp==NULL && it->recv_fmtp==NULL) ){
/*exact match*/
return it;
}else candidate=it;
}
}
return candidate;
}
static bool_t check_h264_packmode(PayloadType *payload, MSFilterDesc *desc){
if (payload->recv_fmtp==NULL || strstr(payload->recv_fmtp,"packetization-mode")==0){
/*this is packetization-mode=0 H264, we only support it with a multislicing
enabled version of x264*/
if (strstr(desc->text,"x264") && strstr(desc->text,"multislicing")==0){
/*this is x264 without multisclicing*/
ms_message("Disabling packetization-mode=0 H264 codec because "
"of lack of multislicing support");
return FALSE;
}
}
return TRUE;
}
static MSList *fix_codec_list(RtpProfile *prof, MSList *conflist)
{
MSList *elem;
MSList *newlist=NULL;
PayloadType *payload,*confpayload;
for (elem=conflist;elem!=NULL;elem=ms_list_next(elem))
{
confpayload=(PayloadType*)elem->data;
payload=find_payload(prof,confpayload);
if (payload!=NULL){
if (ms_filter_codec_supported(confpayload->mime_type)){
MSFilterDesc *desc=ms_filter_get_encoder(confpayload->mime_type);
if (strcasecmp(confpayload->mime_type,"H264")==0){
if (!check_h264_packmode(confpayload,desc)){
continue;
}
}
payload_type_set_user_data(payload,(void*)desc->text);
payload_type_set_enable(payload,payload_type_enabled(confpayload));
newlist=ms_list_append(newlist,payload);
}
}
else{
ms_warning("Cannot support %s/%i: does not exist.",confpayload->mime_type,
confpayload->clock_rate);
}
}
return newlist;
}
void linphone_core_setup_local_rtp_profile(LinphoneCore *lc)
{
int i;
MSList *audiopt,*videopt;
PayloadType *payload;
bool_t prepend;
lc->local_profile=rtp_profile_clone_full(&av_profile);
/* first look at the list given by configuration file to see if
it is correct */
audiopt=fix_codec_list(lc->local_profile,lc->codecs_conf.audio_codecs);
videopt=fix_codec_list(lc->local_profile,lc->codecs_conf.video_codecs);
/* now find and add payloads that are not listed in the configuration
codec list */
for (i=0;i<127;i++)
{
payload=rtp_profile_get_payload(lc->local_profile,i);
if (payload!=NULL){
if (payload_type_get_user_data(payload)!=NULL) continue;
/* find a mediastreamer codec for this payload type */
if (ms_filter_codec_supported(payload->mime_type)){
MSFilterDesc *desc=ms_filter_get_encoder(payload->mime_type);
ms_message("Adding new codec %s/%i",payload->mime_type,payload->clock_rate);
payload_type_set_enable(payload,1);
payload_type_set_user_data(payload,(void *)desc->text);
prepend=FALSE;
/* by default, put speex, mpeg4, or h264 on top of list*/
if (strcmp(payload->mime_type,"speex")==0)
prepend=TRUE;
else if (strcmp(payload->mime_type,"MP4V-ES")==0)
prepend=TRUE;
else if (strcasecmp(payload->mime_type,"H264")==0){
if (check_h264_packmode(payload,desc))
prepend=TRUE;
else continue;
}
switch (payload->type){
case PAYLOAD_AUDIO_CONTINUOUS:
case PAYLOAD_AUDIO_PACKETIZED:
if (prepend)
audiopt=ms_list_prepend(audiopt,(void *)payload);
else
audiopt=ms_list_append(audiopt,(void *)payload);
break;
case PAYLOAD_VIDEO:
if (prepend)
videopt=ms_list_prepend(videopt,(void *)payload);
else
videopt=ms_list_append(videopt,(void *)payload);
break;
default:
ms_error("Unsupported rtp media type.");
}
}
}
}
ms_list_for_each(lc->codecs_conf.audio_codecs,(void (*)(void*))payload_type_destroy);
ms_list_for_each(lc->codecs_conf.video_codecs,(void (*)(void *))payload_type_destroy);
ms_list_free(lc->codecs_conf.audio_codecs);
ms_list_free(lc->codecs_conf.video_codecs);
/* set the fixed lists instead:*/
lc->codecs_conf.audio_codecs=audiopt;
lc->codecs_conf.video_codecs=videopt;
linphone_core_update_allocated_audio_bandwidth(lc);
}
int from_2char_without_params(osip_from_t *from,char **str)
{
osip_from_t *tmpfrom=NULL;
osip_from_clone(from,&tmpfrom);
if (tmpfrom!=NULL){
while(!osip_list_eol(&tmpfrom->gen_params,0)){
osip_generic_param_t *param=(osip_generic_param_t*)osip_list_get(&tmpfrom->gen_params,0);
osip_generic_param_free(param);
osip_list_remove(&tmpfrom->gen_params,0);
}
}else return -1;
osip_from_to_str(tmpfrom,str);
osip_from_free(tmpfrom);
return 0;
}
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){
#if !defined(_WIN32_WCE)
FILE *f=popen(command,"r");
@ -619,6 +473,11 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
bool_t got_audio,got_video;
bool_t cone_audio=FALSE,cone_video=FALSE;
struct timeval init,cur;
SalEndpointCandidate *ac,*vc;
ac=&call->localdesc->streams[0].candidates[0];
vc=&call->localdesc->streams[1].candidates[0];
if (parse_stun_server_addr(server,&ss,&ss_len)<0){
ms_error("Fail to parser stun server address: %s",server);
return;
@ -651,20 +510,20 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
usleep(10000);
#endif
if (recvStunResponse(sock1,call->audio_params.natd_addr,
&call->audio_params.natd_port,&id)>0){
if (recvStunResponse(sock1,ac->addr,
&ac->port,&id)>0){
ms_message("STUN test result: local audio port maps to %s:%i",
call->audio_params.natd_addr,
call->audio_params.natd_port);
ac->addr,
ac->port);
if (id==11)
cone_audio=TRUE;
got_audio=TRUE;
}
if (recvStunResponse(sock2,call->video_params.natd_addr,
&call->video_params.natd_port,&id)>0){
if (recvStunResponse(sock2,vc->addr,
&vc->port,&id)>0){
ms_message("STUN test result: local video port maps to %s:%i",
call->video_params.natd_addr,
call->video_params.natd_port);
vc->addr,
vc->port);
if (id==22)
cone_video=TRUE;
got_video=TRUE;
@ -678,7 +537,8 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
}else{
if (!cone_audio) {
ms_warning("NAT is symmetric for audio port");
call->audio_params.natd_port=0;
ac->addr[0]='\0';
ac->port=0;
}
}
if (sock2>=0){
@ -687,7 +547,8 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
}else{
if (!cone_video) {
ms_warning("NAT is symmetric for video port.");
call->video_params.natd_port=0;
vc->addr[0]='\0';
vc->port=0;
}
}
}

View file

@ -18,26 +18,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include <eXosip2/eXosip.h>
#include <osipparser2/osip_message.h>
#include "private.h"
extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol);
void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, int did, int nid){
void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, SalOp *op){
LinphoneFriend *fl=linphone_friend_new_with_addr(subscriber);
if (fl==NULL) return ;
fl->in_did=did;
linphone_friend_set_nid(fl,nid);
fl->insub=op;
linphone_friend_set_inc_subscribe_policy(fl,LinphoneSPAccept);
fl->inc_subscribe_pending=TRUE;
lc->subscribers=ms_list_append(lc->subscribers,(void *)fl);
if (lc->vtable.new_unknown_subscriber!=NULL) {
char *subscriber=linphone_address_as_string(fl->uri);
lc->vtable.new_unknown_subscriber(lc,fl,subscriber);
ms_free(subscriber);
char *tmp=linphone_address_as_string(fl->uri);
lc->vtable.new_unknown_subscriber(lc,fl,tmp);
ms_free(tmp);
}
}
@ -45,167 +42,131 @@ void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf){
linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPDeny);
}
static void __do_notify(void * data, void * user_data){
int *tab=(int*)user_data;
LinphoneFriend *lf=(LinphoneFriend*)data;
linphone_friend_notify(lf,tab[0],tab[1]);
}
void __linphone_core_notify_all_friends(LinphoneCore *lc, int ss, int os){
int tab[2];
tab[0]=ss;
tab[1]=os;
ms_list_for_each2(lc->friends,__do_notify,(void *)tab);
}
void linphone_core_notify_all_friends(LinphoneCore *lc, LinphoneOnlineStatus os){
MSList *elem;
ms_message("Notifying all friends that we are in status %i",os);
__linphone_core_notify_all_friends(lc,EXOSIP_SUBCRSTATE_ACTIVE,os);
for(elem=lc->friends;elem!=NULL;elem=elem->next){
LinphoneFriend *lf=(LinphoneFriend *)elem->data;
if (lf->insub){
linphone_friend_notify(lf,os);
}
}
}
/* check presence state before answering to call; returns TRUE if we can proceed, else answer the appropriate answer
to close the dialog*/
bool_t linphone_core_check_presence(LinphoneCore *lc){
return TRUE;
}
void linphone_subscription_new(LinphoneCore *lc, eXosip_event_t *ev){
void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
LinphoneFriend *lf=NULL;
osip_from_t *from=ev->request->from;
char *tmp;
osip_message_t *msg=NULL;
LinphoneAddress *uri;
osip_from_to_str(ev->request->from,&tmp);
uri=linphone_address_new(tmp);
ms_message("Receiving new subscription from %s.",tmp);
uri=linphone_address_new(from);
linphone_address_clean(uri);
tmp=linphone_address_as_string(uri);
ms_message("Receiving new subscription from %s.",from);
/* check if we answer to this subscription */
if (linphone_find_friend(lc->friends,uri,&lf)!=NULL){
lf->in_did=ev->did;
linphone_friend_set_nid(lf,ev->nid);
eXosip_insubscription_build_answer(ev->tid,202,&msg);
eXosip_insubscription_send_answer(ev->tid,202,msg);
__eXosip_wakeup_event();
lf->insub=op;
lf->inc_subscribe_pending=TRUE;
sal_subscribe_accept(op);
linphone_friend_done(lf); /*this will do all necessary actions */
}else{
/* check if this subscriber is in our black list */
if (linphone_find_friend(lc->subscribers,uri,&lf)){
if (lf->pol==LinphoneSPDeny){
ms_message("Rejecting %s because we already rejected it once.",from);
eXosip_insubscription_send_answer(ev->tid,401,NULL);
sal_subscribe_decline(op);
}
else {
/* else it is in wait for approval state, because otherwise it is in the friend list.*/
ms_message("New subscriber found in friend list, in %s state.",__policy_enum_to_str(lf->pol));
}
}else {
eXosip_insubscription_build_answer(ev->tid,202,&msg);
eXosip_insubscription_send_answer(ev->tid,202,msg);
linphone_core_add_subscriber(lc,tmp,ev->did,ev->nid);
sal_subscribe_accept(op);
linphone_core_add_subscriber(lc,tmp,op);
}
}
osip_free(tmp);
ms_free(tmp);
}
void linphone_notify_recv(LinphoneCore *lc, eXosip_event_t *ev)
{
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus sal_status){
const char *status=_("Gone");
const char *img="sip-closed.png";
char *tmp;
LinphoneFriend *lf;
LinphoneAddress *friend=NULL;
osip_from_t *from=NULL;
osip_body_t *body=NULL;
LinphoneOnlineStatus estatus=LINPHONE_STATUS_UNKNOWN;
ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
if (ev->request!=NULL){
from=ev->request->from;
osip_message_get_body(ev->request,0,&body);
if (body==NULL){
ms_error("No body in NOTIFY");
return;
}
if (strstr(body->body,"pending")!=NULL){
status=_("Waiting for Approval");
img="sip-wfa.png";
estatus=LINPHONE_STATUS_PENDING;
}else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
status=_("Online");
img="sip-online.png";
estatus=LINPHONE_STATUS_ONLINE;
}else if (strstr(body->body,"busy")!=NULL){
status=_("Busy");
img="sip-busy.png";
estatus=LINPHONE_STATUS_BUSY;
}else if (strstr(body->body,"berightback")!=NULL
|| strstr(body->body,"in-transit")!=NULL ){
status=_("Be Right Back");
img="sip-bifm.png";
estatus=LINPHONE_STATUS_BERIGHTBACK;
}else if (strstr(body->body,"away")!=NULL){
status=_("Away");
img="sip-away.png";
estatus=LINPHONE_STATUS_AWAY;
}else if (strstr(body->body,"onthephone")!=NULL
|| strstr(body->body,"on-the-phone")!=NULL){
status=_("On The Phone");
img="sip-otp.png";
estatus=LINPHONE_STATUS_ONTHEPHONE;
}else if (strstr(body->body,"outtolunch")!=NULL
|| strstr(body->body,"meal")!=NULL){
status=_("Out To Lunch");
img="sip-otl.png";
estatus=LINPHONE_STATUS_OUTTOLUNCH;
}else if (strstr(body->body,"closed")!=NULL){
status=_("Closed");
img="sip-away.png";
estatus=LINPHONE_STATUS_CLOSED;
}else{
LinphoneOnlineStatus estatus=LINPHONE_STATUS_OFFLINE;
switch(sal_status){
case SalPresenceOffline:
status=_("Gone");
img="sip-closed.png";
estatus=LINPHONE_STATUS_OFFLINE;
}
ms_message("We are notified that sip:%s@%s has online status %s",from->url->username,from->url->host,status);
break;
case SalPresenceOnline:
status=_("Online");
img="sip-online.png";
estatus=LINPHONE_STATUS_ONLINE;
break;
case SalPresenceBusy:
status=_("Busy");
img="sip-busy.png";
estatus=LINPHONE_STATUS_BUSY;
break;
case SalPresenceBerightback:
status=_("Away");
img="sip-away.png";
estatus=LINPHONE_STATUS_AWAY;
break;
case SalPresenceAway:
status=_("Away");
img="sip-away.png";
estatus=LINPHONE_STATUS_AWAY;
break;
case SalPresenceOnthephone:
status=_("On The Phone");
img="sip-otp.png";
estatus=LINPHONE_STATUS_ONTHEPHONE;
break;
case SalPresenceOuttolunch:
status=_("Out To Lunch");
img="sip-otl.png";
estatus=LINPHONE_STATUS_OUTTOLUNCH;
break;
case SalPresenceDonotdisturb:
status=_("Busy");
img="sip-busy.png";
estatus=LINPHONE_STATUS_BUSY;
break;
case SalPresenceMoved:
case SalPresenceAltService:
status=_("Away");
img="sip-away.png";
estatus=LINPHONE_STATUS_AWAY;
break;
}
lf=linphone_find_friend_by_sid(lc->friends,ev->sid);
lf=linphone_find_friend_by_out_subscribe(lc->friends,op);
if (lf!=NULL){
friend=lf->uri;
tmp=linphone_address_as_string(friend);
lf->status=estatus;
lc->vtable.notify_recv(lc,(LinphoneFriend*)lf,tmp,status,img);
ms_free(tmp);
if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
lf->sid=-1;
lf->out_did=-1;
ms_message("Outgoing subscription terminated by remote.");
}
}else{
ms_message("But this person is not part of our friend list, so we don't care.");
}
if (ss==SalSubscribeTerminated){
sal_op_release(op);
if (lf)
lf->outsub=NULL;
}
}
void linphone_subscription_answered(LinphoneCore *lc, eXosip_event_t *ev){
void linphone_subscription_closed(LinphoneCore *lc, SalOp *op){
LinphoneFriend *lf;
osip_from_t *from=ev->response->to;
char *tmp;
osip_from_to_str(from,&tmp);
LinphoneAddress *uri=linphone_address_new(tmp);
linphone_find_friend(lc->friends,uri,&lf);
lf=linphone_find_friend_by_inc_subscribe(lc->friends,op);
sal_op_release(op);
if (lf!=NULL){
lf->out_did=ev->did;
linphone_friend_set_sid(lf,ev->sid);
lf->insub=NULL;
}else{
ms_warning("Receiving answer for unknown subscribe sip:%s@%s", from->url->username,from->url->host);
}
ms_free(tmp);
}
void linphone_subscription_closed(LinphoneCore *lc,eXosip_event_t *ev){
LinphoneFriend *lf;
osip_from_t *from=ev->request->from;
lf=linphone_find_friend_by_nid(lc->friends,ev->nid);
if (lf!=NULL){
lf->in_did=-1;
linphone_friend_set_nid(lf,-1);
}else{
ms_warning("Receiving unsuscribe for unknown in-subscribtion from sip:%s@%s", from->url->username, from->url->host);
ms_warning("Receiving unsuscribe for unknown in-subscribtion from %s", sal_op_get_from(op));
}
}

View file

@ -99,7 +99,10 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineS
int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os);
void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os);
LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op);
LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op);
int set_lock_file();
int get_lock_file();
@ -107,7 +110,7 @@ int remove_lock_file();
int do_registration(LinphoneCore *lc, bool_t doit);
void check_for_registration(LinphoneCore *lc);
void check_sound_device(LinphoneCore *lc);
void linphone_core_setup_local_rtp_profile(LinphoneCore *lc);
void linphone_core_verify_codecs(LinphoneCore *lc);
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);
@ -135,10 +138,11 @@ static inline void set_string(char **dest, const char *src){
#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0
SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os);
void linphone_process_authentication(LinphoneCore* lc, SalOp *op);
void linphone_authentication_ok(LinphoneCore *lc, SalOp *op);
void linphone_subscription_new(LinphoneCore *lc, SalOp *op);
void linphone_notify_recv(LinphoneCore *lc, SalOp *op);
void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from);
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus status);
void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op);
void linphone_subscription_answered(LinphoneCore *lc, SalOp *op);
@ -164,7 +168,8 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon
int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
/*internal use only */
void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg);
void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
void linphone_core_stop_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
const char * linphone_core_get_identity(LinphoneCore *lc);
@ -206,8 +211,8 @@ struct _LinphoneAuthInfo
char *userid;
char *passwd;
char *ha1;
int usecount;
bool_t works;
bool_t first_time;
};
struct _LinphoneChatRoom{
@ -224,7 +229,6 @@ struct _LinphoneFriend{
SalOp *outsub;
LinphoneSubscribePolicy pol;
LinphoneOnlineStatus status;
struct _LinphoneProxyConfig *proxy;
struct _LinphoneCore *lc;
BuddyInfo *info;
char *refkey;
@ -356,7 +360,6 @@ struct _LinphoneCore
struct _VideoStream *videostream;
struct _VideoStream *previewstream;
RtpTransport *a_rtp,*a_rtcp;
struct _RtpProfile *local_profile;
MSList *bl_reqs;
MSList *subscribers; /* unknown subscribers */
int minutes_away;

View file

@ -20,8 +20,6 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
#include "linphonecore.h"
#include "sipsetup.h"
#include <eXosip2/eXosip.h>
#include <osipparser2/osip_message.h>
#include "lpconfig.h"
#include "private.h"
@ -40,7 +38,6 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
void linphone_proxy_config_init(LinphoneProxyConfig *obj){
memset(obj,0,sizeof(LinphoneProxyConfig));
obj->rid=-1;
obj->expires=3600;
}
@ -72,8 +69,8 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
if (obj->realm!=NULL) ms_free(obj->realm);
if (obj->type!=NULL) ms_free(obj->type);
if (obj->contact_addr!=NULL) ms_free(obj->contact_addr);
if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
if (obj->op) sal_op_release(obj->op);
}
/**
@ -83,79 +80,6 @@ bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){
return obj->registered;
}
void linphone_proxy_config_get_contact(LinphoneProxyConfig *cfg, const char **ip, int *port){
if (cfg->registered){
*ip=cfg->contact_addr;
*port=cfg->contact_port;
}else{
*ip=NULL;
*port=0;
}
}
static void update_contact(LinphoneProxyConfig *cfg, const char *ip, const char *port){
if (cfg->contact_addr){
ms_free(cfg->contact_addr);
}
cfg->contact_addr=ms_strdup(ip);
if (port!=NULL)
cfg->contact_port=atoi(port);
else cfg->contact_port=5060;
}
bool_t linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyConfig *obj, osip_message_t *orig_request, osip_message_t *last_answer){
osip_message_t *msg;
const char *rport,*received;
osip_via_t *via=NULL;
osip_generic_param_t *param=NULL;
osip_contact_t *ctt=NULL;
osip_message_get_via(last_answer,0,&via);
if (!via) return FALSE;
osip_via_param_get_byname(via,"rport",&param);
if (param) rport=param->gvalue;
else return FALSE;
param=NULL;
osip_via_param_get_byname(via,"received",&param);
if (param) received=param->gvalue;
else return FALSE;
osip_message_get_contact(orig_request,0,&ctt);
if (strcmp(ctt->url->host,received)==0){
/*ip address matches, check ports*/
const char *contact_port=ctt->url->port;
const char *via_rport=rport;
if (via_rport==NULL || strlen(via_rport)>0)
via_rport="5060";
if (contact_port==NULL || strlen(contact_port)>0)
contact_port="5060";
if (strcmp(contact_port,via_rport)==0){
ms_message("Register has up to date contact, doing nothing.");
return FALSE;
}else ms_message("ports do not match, need to update the register (%s <> %s)", contact_port,via_rport);
}
eXosip_lock();
msg=NULL;
eXosip_register_build_register(obj->rid,obj->expires,&msg);
if (msg==NULL){
eXosip_unlock();
ms_warning("Fail to create a contact updated register.");
return FALSE;
}
osip_message_get_contact(msg,0,&ctt);
if (ctt->url->host!=NULL){
osip_free(ctt->url->host);
}
ctt->url->host=osip_strdup(received);
if (ctt->url->port!=NULL){
osip_free(ctt->url->port);
}
ctt->url->port=osip_strdup(rport);
eXosip_register_send_register(obj->rid,msg);
eXosip_unlock();
update_contact(obj,received,rport);
ms_message("Resending new register with updated contact %s:%s",received,rport);
return TRUE;
}
/**
* Sets the proxy address
*
@ -165,19 +89,18 @@ bool_t linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyCo
* - hostnames : sip:sip.example.net
**/
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){
int err;
osip_from_t *url;
LinphoneAddress *addr;
if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
obj->reg_proxy=NULL;
if (server_addr!=NULL && strlen(server_addr)>0){
osip_from_init(&url);
err=osip_from_parse(url,server_addr);
if (err==0 && url->url->host!=NULL){
addr=linphone_address_new(server_addr);
if (addr){
obj->reg_proxy=ms_strdup(server_addr);
linphone_address_destroy(addr);
}else{
ms_warning("Could not parse %s",server_addr);
return -1;
}
osip_from_free(url);
}
return 0;
}
@ -191,30 +114,30 @@ int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *
* The REGISTER messages will have from and to set to this identity.
*
**/
void linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
int err=0;
osip_from_t *url=NULL;
int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity){
LinphoneAddress *addr;
if (identity!=NULL && strlen(identity)>0){
osip_from_init(&url);
err=osip_from_parse(url,identity);
if (err<0 || url->url->host==NULL || url->url->username==NULL){
ms_warning("Could not parse %s",identity);
osip_from_free(url);
return;
addr=linphone_address_new(identity);
if (!addr || linphone_address_get_username(addr)==NULL){
ms_warning("Invalid sip identity: %s",identity);
if (addr)
linphone_address_destroy(addr);
return -1;
}else{
if (obj->reg_identity!=NULL) {
ms_free(obj->reg_identity);
obj->reg_identity=NULL;
}
obj->reg_identity=ms_strdup(identity);
if (obj->realm){
ms_free(obj->realm);
}
obj->realm=ms_strdup(linphone_address_get_domain(addr));
linphone_address_destroy(addr);
return 0;
}
} else err=-2;
if (obj->reg_identity!=NULL) {
ms_free(obj->reg_identity);
obj->reg_identity=NULL;
}
if (err==-2) obj->reg_identity=NULL;
else {
obj->reg_identity=ms_strdup(identity);
if (obj->realm)
ms_free(obj->realm);
obj->realm=ms_strdup(url->url->host);
}
if (url) osip_from_free(url);
return -1;
}
const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
@ -226,37 +149,14 @@ const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){
* When a route is set, all outgoing calls will go to the route's destination if this proxy
* is the default one (see linphone_core_set_default_proxy() ).
**/
void linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route)
{
int err;
osip_uri_param_t *lr_param=NULL;
osip_route_t *rt=NULL;
char *tmproute=NULL;
if (route!=NULL && strlen(route)>0){
osip_route_init(&rt);
err=osip_route_parse(rt,route);
if (err<0){
ms_warning("Could not parse %s",route);
osip_route_free(rt);
return ;
}
if (obj->reg_route!=NULL) {
ms_free(obj->reg_route);
obj->reg_route=NULL;
}
/* check if the lr parameter is set , if not add it */
osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
if (lr_param==NULL){
osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
osip_route_to_str(rt,&tmproute);
obj->reg_route=ms_strdup(tmproute);
osip_free(tmproute);
}else obj->reg_route=ms_strdup(route);
}else{
if (obj->reg_route!=NULL) ms_free(obj->reg_route);
if (obj->reg_route!=NULL){
ms_free(obj->reg_route);
obj->reg_route=NULL;
}
obj->reg_route=ms_strdup(route);
return 0;
}
bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){
@ -304,15 +204,10 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
* linphone_proxy_config_done() to commit the changes.
**/
void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
obj->auth_failures=0;
if (obj->reg_sendregister){
/* unregister */
if (obj->registered) {
osip_message_t *msg;
eXosip_lock();
eXosip_register_build_register(obj->rid,0,&msg);
eXosip_register_send_register(obj->rid,msg);
eXosip_unlock();
sal_unregister(obj->op);
obj->registered=FALSE;
}
}
@ -329,13 +224,10 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
if (obj->reg_identity!=NULL) id_str=obj->reg_identity;
else id_str=linphone_core_get_primary_contact(obj->lc);
if (obj->reg_sendregister){
char *ct=NULL;
osip_message_t *msg=NULL;
eXosip_lock();
obj->rid=eXosip_register_build_initial_register(id_str,obj->reg_proxy,NULL,obj->expires,&msg);
eXosip_register_send_register(obj->rid,msg);
eXosip_unlock();
if (ct!=NULL) osip_free(ct);
if (obj->op)
sal_op_release(obj->op);
obj->op=sal_op_new(obj->lc->sal);
sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires);
}
}
@ -484,170 +376,13 @@ void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm
}
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
LinphoneOnlineStatus presence_mode)
{
osip_message_t *pub;
int i;
const char *from=NULL;
char buf[5000];
if (proxy->publish==FALSE) return 0;
if (proxy!=NULL) {
from=linphone_proxy_config_get_identity(proxy);
}
if (from==NULL) from=linphone_core_get_primary_contact(proxy->lc);
if (presence_mode==LINPHONE_STATUS_ONLINE)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>online</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_BUSY
||presence_mode==LINPHONE_STATUS_NOT_DISTURB)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>busy</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>busy</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_BERIGHTBACK)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>in-transit</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>be right back</note>\n\
</tuple>\n\
</presence>",
from,from);
}
else if (presence_mode==LINPHONE_STATUS_AWAY
||presence_mode==LINPHONE_STATUS_MOVED
||presence_mode==LINPHONE_STATUS_ALT_SERVICE)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>away</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>away</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_ONTHEPHONE)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>on-the-phone</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>on the phone</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_OUTTOLUNCH)
{
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>meal</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>out to lunch</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==LINPHONE_STATUS_OFFLINE)
{
/* */
snprintf(buf, 5000, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n%s",
from,
"<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>closed</basic>\n\
<es:activities>\n\
<es:activity>permanent-absence</e:activity>\n\
</es:activities>\n\
</status>\n\
</tuple>\n\
\n</presence>\n");
}
i = eXosip_build_publish(&pub, (char *)from, (char *)from, NULL, "presence", "1800", "application/pidf+xml", buf);
if (i<0)
{
ms_message("Failed to build publish request.");
return -1;
}
eXosip_lock();
i = eXosip_publish(pub, from); /* should update the sip-if-match parameter
from sip-etag from last 200ok of PUBLISH */
eXosip_unlock();
if (i<0)
{
ms_message("Failed to send publish request.");
return -1;
}
return 0;
LinphoneOnlineStatus presence_mode){
int err;
SalOp *op=sal_op_new(proxy->lc->sal);
err=sal_publish(op,linphone_proxy_config_get_identity(proxy),
linphone_proxy_config_get_identity(proxy),linphone_online_status_to_sal(presence_mode));
sal_op_release(op);
return err;
}
@ -657,13 +392,15 @@ entity=\"%s\">\n%s",
**/
int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
if (!linphone_proxy_config_check(lc,cfg)) return -1;
if (ms_list_find(lc->sip_conf.proxies,cfg)!=NULL){
ms_warning("ProxyConfig already entered, ignored.");
return 0;
}
lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg);
linphone_proxy_config_apply(cfg,lc);
return 0;
}
extern void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, LinphoneProxyConfig *cfg);
/**
* Removes a proxy configuration.
*
@ -671,7 +408,6 @@ extern void linphone_friend_check_for_removed_proxy(LinphoneFriend *lf, Linphone
* on a deleted list. For that reason, a removed proxy does NOT need to be freed.
**/
void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){
MSList *elem;
lc->sip_conf.proxies=ms_list_remove(lc->sip_conf.proxies,(void *)cfg);
/* add to the list of destroyed proxies, so that the possible unREGISTER request can succeed authentication */
lc->sip_conf.deleted_proxies=ms_list_append(lc->sip_conf.deleted_proxies,(void *)cfg);
@ -680,11 +416,6 @@ void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cf
if (lc->default_proxy==cfg){
lc->default_proxy=NULL;
}
/* invalidate all references to this proxy in our friend list */
for (elem=lc->friends;elem!=NULL;elem=ms_list_next(elem)){
linphone_friend_check_for_removed_proxy((LinphoneFriend*)elem->data,cfg);
}
}
/**
* Erase all proxies from config.
@ -735,23 +466,6 @@ int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **conf
return pos;
}
static int rid_compare(const void *pcfg,const void *prid){
const LinphoneProxyConfig *cfg=(const LinphoneProxyConfig*)pcfg;
const int *rid=(const int*)prid;
ms_message("cfg= %s, cfg->rid=%i, rid=%i",cfg->reg_proxy, cfg->rid, *rid);
return cfg->rid-(*rid);
}
LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid){
MSList *elem=ms_list_find_custom(lc->sip_conf.proxies,rid_compare, &rid);
if (elem==NULL){
ms_message("linphone_core_get_proxy_config_from_rid: searching in deleted proxies...");
elem=ms_list_find_custom(lc->sip_conf.deleted_proxies,rid_compare, &rid);
}
if (elem==NULL) return NULL;
else return (LinphoneProxyConfig*)elem->data;
}
/**
* Returns an unmodifiable list of entered proxy configurations.
**/
@ -759,47 +473,6 @@ const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){
return lc->sip_conf.proxies;
}
void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, int code, eXosip_event_t *ev){
if (code==403) {
LinphoneProxyConfig *cfg=linphone_core_get_proxy_config_from_rid(lc, ev->rid);
if (cfg){
cfg->auth_failures++;
/*restart a new register so that the user gets a chance to be prompted for a password*/
if (cfg->auth_failures==1){
linphone_proxy_config_register(cfg);
}
}
} else {
//unknown error (possibly timeout)
char *prx_realm=NULL,*www_realm=NULL;
osip_proxy_authenticate_t *prx_auth;
osip_www_authenticate_t *www_auth;
osip_message_t *req=ev->request;
char *username;
username=osip_uri_get_username(req->from->url);
prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&req->proxy_authenticates,0);
www_auth=(osip_proxy_authenticate_t*)osip_list_get(&req->www_authenticates,0);
if (prx_auth!=NULL)
prx_realm=osip_proxy_authenticate_get_realm(prx_auth);
if (www_auth!=NULL)
www_realm=osip_www_authenticate_get_realm(www_auth);
if (prx_realm==NULL && www_realm==NULL){
ms_warning("No realm in the client request.");
return;
}
LinphoneAuthInfo *as=NULL;
/* see if we already have this auth information , not to ask it everytime to the user */
if (prx_realm!=NULL)
as=linphone_core_find_auth_info(lc,prx_realm,username);
if (www_realm!=NULL)
as=linphone_core_find_auth_info(lc,www_realm,username);
if (as) as->first_time=TRUE;
}
}
void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyConfig *obj, int index)
{
char key[50];

View file

@ -99,6 +99,10 @@ void sal_op_set_user_pointer(SalOp *op, void *up){
((SalOpBase*)op)->user_pointer=up;
}
Sal *sal_op_get_sal(const SalOp *op){
return ((SalOpBase*)op)->root;
}
const char *sal_op_get_from(const SalOp *op){
return ((SalOpBase*)op)->from;
}
@ -119,6 +123,10 @@ void *sal_op_get_user_pointer(const SalOp *op){
return ((SalOpBase*)op)->user_pointer;
}
const char *sal_op_get_proxy(const SalOp *op){
return ((SalOpBase*)op)->route;
}
void __sal_op_init(SalOp *b, Sal *sal){
memset(b,0,sizeof(SalOpBase));
((SalOpBase*)b)->root=sal;

View file

@ -82,6 +82,13 @@ typedef enum{
SalProtoRtpSavp
}SalMediaProto;
typedef struct SalEndpointCandidate{
char addr[64];
int port;
}SalEndpointCandidate;
#define SAL_ENDPOINT_CANDIDATE_MAX 2
typedef struct SalStreamDescription{
SalMediaProto proto;
SalStreamType type;
@ -90,6 +97,7 @@ typedef struct SalStreamDescription{
MSList *payloads; //<list of PayloadType
int bandwidth;
int ptime;
SalEndpointCandidate candidates[SAL_ENDPOINT_CANDIDATE_MAX];
} SalStreamDescription;
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
@ -112,7 +120,7 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
/*this structure must be at the first byte of the SalOp structure defined by implementors*/
typedef struct SalOpBase{
Sal *root;
char *route;
char *route; /*or request-uri for REGISTER*/
char *contact;
char *from;
char *to;
@ -154,6 +162,11 @@ typedef enum SalPresenceStatus{
SalPresenceAltService,
}SalPresenceStatus;
typedef enum SalSubscribeState{
SalSubscribeActive,
SalSubscribeTerminated
}SalSubscribeState;
typedef void (*SalOnCallReceived)(SalOp *op);
typedef void (*SalOnCallRinging)(SalOp *op);
typedef void (*SalOnCallAccepted)(SalOp *op);
@ -169,8 +182,9 @@ typedef void (*SalOnVfuRequest)(SalOp *op);
typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
typedef void (*SalOnTextReceived)(Sal *sal, const char *from, const char *msg);
typedef void (*SalOnPresenceChanged)(SalOp *op, SalPresenceStatus status, const char *msg);
typedef void (*SalOnSubscribeReceived)(SalOp *sal, const char *from);
typedef void (*SalOnNotify)(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg);
typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *from);
typedef void (*SalOnSubscribeClosed)(SalOp *salop, const char *from);
typedef void (*SalOnInternalMsg)(Sal *sal, const char *msg);
typedef struct SalCallbacks{
@ -189,8 +203,9 @@ typedef struct SalCallbacks{
SalOnDtmfReceived dtmf_received;
SalOnRefer refer_received;
SalOnTextReceived text_received;
SalOnPresenceChanged presence_changed;
SalOnNotify notify;
SalOnSubscribeReceived subscribe_received;
SalOnSubscribeClosed subscribe_closed;
SalOnInternalMsg internal_message;
}SalCallbacks;
@ -207,11 +222,13 @@ void sal_set_user_agent(Sal *ctx, const char *user_agent);
void sal_masquerade(Sal *ctx, const char *ip);
void sal_use_session_timers(Sal *ctx, int expires);
int sal_iterate(Sal *sal);
MSList * sal_get_pending_auths(Sal *sal);
/*create an operation */
SalOp * sal_op_new(Sal *sal);
/*generic SalOp API, working for all operations */
Sal *sal_op_get_sal(const SalOp *op);
void sal_op_set_contact(SalOp *op, const char *contact);
void sal_op_set_route(SalOp *op, const char *route);
void sal_op_set_from(SalOp *op, const char *from);
@ -219,10 +236,12 @@ void sal_op_set_to(SalOp *op, const char *to);
void sal_op_release(SalOp *h);
void sal_op_authenticate(SalOp *h, const SalAuthInfo *info);
void sal_op_set_user_pointer(SalOp *h, void *up);
int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username);
const char *sal_op_get_from(const SalOp *op);
const char *sal_op_get_to(const SalOp *op);
const char *sal_op_get_contact(const SalOp *op);
const char *sal_op_get_route(const SalOp *op);
const char *sal_op_get_proxy(const SalOp *op);
void *sal_op_get_user_pointer(const SalOp *op);
/*Call API*/
@ -238,16 +257,21 @@ int sal_call_terminate(SalOp *h);
/*Registration*/
int sal_register(SalOp *op, const char *proxy, const char *from, int expires);
int sal_unregister(SalOp *h);
/*Messaging */
int sal_text_send(SalOp *op, const char *from, const char *to, const char *text);
/*presence Subscribe/notify*/
int sal_subscribe_presence(SalOp *op, const char *from, const char *to);
int sal_unsubscribe(SalOp *op);
int sal_subscribe_accept(SalOp *op);
int sal_subscribe_decline(SalOp *op);
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message);
int sal_notify_close(SalOp *op);
/*presence publish */
int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus status);
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)

View file

@ -55,6 +55,39 @@ static void sal_remove_register(Sal *sal, int rid){
}
}
static void sal_add_pending_auth(Sal *sal, SalOp *op){
sal->pending_auths=ms_list_append(sal->pending_auths,op);
}
static void sal_remove_pending_auth(Sal *sal, SalOp *op){
sal->pending_auths=ms_list_remove(sal->pending_auths,op);
}
void sal_exosip_fix_route(SalOp *op){
if (sal_op_get_route(op)!=NULL){
osip_route_t *rt=NULL;
osip_uri_param_t *lr_param=NULL;
osip_route_init(&rt);
if (osip_route_parse(rt,sal_op_get_route(op))<0){
ms_warning("Bad route %s!",sal_op_get_route(op));
sal_op_set_route(op,NULL);
}else{
/* check if the lr parameter is set , if not add it */
osip_uri_uparam_get_byname(rt->url, "lr", &lr_param);
if (lr_param==NULL){
char *tmproute;
osip_uri_uparam_add(rt->url,osip_strdup("lr"),NULL);
osip_route_to_str(rt,&tmproute);
sal_op_set_route(op,tmproute);
osip_free(tmproute);
}
}
osip_route_free(rt);
}
}
SalOp * sal_op_new(Sal *sal){
SalOp *op=ms_new(SalOp,1);
__sal_op_init(op,sal);
@ -78,6 +111,9 @@ void sal_op_release(SalOp *op){
if (op->cid!=-1){
eXosip_call_set_reference(op->cid,NULL);
}
if (op->pending_auth){
sal_remove_pending_auth(op->base.root,op);
}
__sal_op_free(op);
}
@ -174,8 +210,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
if (ctx->callbacks.dtmf_received==NULL)
ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
if (ctx->callbacks.presence_changed==NULL)
ctx->callbacks.presence_changed=(SalOnPresenceChanged)unimplemented_stub;
if (ctx->callbacks.notify==NULL)
ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
if (ctx->callbacks.subscribe_received==NULL)
ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
if (ctx->callbacks.text_received==NULL)
@ -215,6 +251,10 @@ void sal_use_session_timers(Sal *ctx, int expires){
ctx->session_expires=expires;
}
MSList *sal_get_pending_auths(Sal *sal){
return ms_list_copy(sal->pending_auths);
}
static void set_sdp(osip_message_t *sip,sdp_message_t *msg){
int sdplen;
@ -277,7 +317,8 @@ int sal_call(SalOp *h, const char *from, const char *to){
osip_message_t *invite=NULL;
sal_op_set_from(h,from);
sal_op_set_to(h,to);
err=eXosip_call_build_initial_invite(&invite,to,from,h->base.route,"Phone call");
sal_exosip_fix_route(h);
err=eXosip_call_build_initial_invite(&invite,to,from,sal_op_get_route(h),"Phone call");
if (err!=0){
ms_error("Could not create call.");
return -1;
@ -625,6 +666,13 @@ static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **us
return 0;
}
int sal_op_get_auth_requested(SalOp *op, const char **realm, const char **username){
if (op->pending_auth){
return get_auth_data(op->pending_auth,realm,username);
}
return -1;
}
static bool_t process_authentication(Sal *sal, eXosip_event_t *ev){
SalOp *op;
const char *username,*realm;
@ -637,6 +685,7 @@ static bool_t process_authentication(Sal *sal, eXosip_event_t *ev){
if (op->pending_auth!=NULL)
eXosip_event_free(op->pending_auth);
op->pending_auth=ev;
sal_add_pending_auth (sal,op);
sal->callbacks.auth_requested(op,realm,username);
return FALSE;
}
@ -1129,6 +1178,8 @@ int sal_iterate(Sal *sal){
int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
osip_message_t *msg;
sal_op_set_route(h,proxy);
sal_exosip_fix_route(h);
if (h->rid==-1){
eXosip_lock();
h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(h),expires,&msg);
@ -1143,6 +1194,16 @@ int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
return 0;
}
int sal_unregister(SalOp *h){
osip_message_t *msg=NULL;
eXosip_lock();
eXosip_register_build_register(h->rid,0,&msg);
if (msg) eXosip_register_send_register(h->rid,msg);
else ms_warning("Could not build unREGISTER !");
eXosip_unlock();
return 0;
}
SalAddress * sal_address_new(const char *uri){

View file

@ -33,6 +33,7 @@ struct Sal{
MSList *registers;/*MSList of SalOp */
MSList *out_subscribes;/*MSList of SalOp */
MSList *in_subscribes;/*MSList of SalOp */
MSList *pending_auths;/*MSList of SalOp */
int running;
int session_expires;
void *up;
@ -60,5 +61,7 @@ void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev);
void sal_exosip_notify_recv(Sal *sal,eXosip_event_t *ev);
void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev);
void sal_exosip_fix_route(SalOp *op);
#endif

View file

@ -97,6 +97,7 @@ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
sal_op_set_from(op,from);
if (to)
sal_op_set_to(op,to);
sal_exosip_fix_route(op);
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);
@ -142,31 +143,6 @@ int sal_subscribe_decline(SalOp *op){
return 0;
}
static eXosip_ss_status_t sal_presence_to_exosip(SalPresenceStatus s){
switch(s){
case SalPresenceOffline:
return EXOSIP_NOTIFY_CLOSED;
case SalPresenceOnline:
return EXOSIP_NOTIFY_ONLINE;
case SalPresenceBusy:
return EXOSIP_NOTIFY_BUSY;
case SalPresenceBerightback:
return EXOSIP_NOTIFY_BERIGHTBACK;
case SalPresenceAway:
return EXOSIP_NOTIFY_AWAY;
case SalPresenceOnthephone:
return EXOSIP_NOTIFY_ONTHEPHONE;
case SalPresenceOuttolunch:
return EXOSIP_NOTIFY_OUTTOLUNCH;
case SalPresenceDonotdisturb:
return EXOSIP_NOTIFY_BUSY;
case SalPresenceMoved:
case SalPresenceAltService:
default:
return EXOSIP_NOTIFY_AWAY;
}
}
static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status)
{
char buf[1000];
@ -435,14 +411,14 @@ entity=\"%s\">\n%s",
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
osip_message_t *msg;
eXosip_ss_status_t ss;
eXosip_ss_t ss=EXOSIP_SUBCRSTATE_ACTIVE;
if (op->nid==-1){
ms_warning("Cannot notify, subscription was closed.");
return -1;
}
ss=sal_presence_to_exosip(status);
eXosip_lock();
eXosip_insubscription_build_notify(op->did,ss,0,&msg);
eXosip_insubscription_build_notify(op->did,ss,DEACTIVATED,&msg);
if (msg!=NULL){
const char *identity=sal_op_get_contact(op);
if (identity==NULL) identity=sal_op_get_to(op);
@ -454,6 +430,172 @@ int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_
return 0;
}
int sal_notify_close(SalOp *op){
osip_message_t *msg;
eXosip_lock();
eXosip_insubscription_build_notify(op->did,EXOSIP_SUBCRSTATE_TERMINATED,DEACTIVATED,&msg);
if (msg!=NULL){
const char *identity=sal_op_get_contact(op);
if (identity==NULL) identity=sal_op_get_to(op);
osip_message_set_contact(msg,identity);
eXosip_insubscription_send_request(op->did,msg);
}else ms_error("could not create notify for incoming subscription.");
eXosip_unlock();
return 0;
}
int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus presence_mode){
osip_message_t *pub;
int i;
char buf[1024];
if (presence_mode==SalPresenceOnline)
{
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>online</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==SalPresenceBusy
||presence_mode==SalPresenceDonotdisturb)
{
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>busy</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>busy</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==SalPresenceBerightback)
{
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>in-transit</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>be right back</note>\n\
</tuple>\n\
</presence>",
from,from);
}
else if (presence_mode==SalPresenceAway
||presence_mode==SalPresenceMoved)
{
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>away</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>away</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==SalPresenceOnthephone)
{
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>on-the-phone</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>on the phone</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else if (presence_mode==SalPresenceOuttolunch)
{
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>open</basic>\n\
<es:activities>\n\
<es:activity>meal</es:activity>\n\
</es:activities>\n\
</status>\n\
<contact priority=\"0.8\">%s</contact>\n\
<note>out to lunch</note>\n\
</tuple>\n\
</presence>",
from, from);
}
else{
/* offline */
snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n\
xmlns:es=\"urn:ietf:params:xml:ns:pidf:status:rpid-status\"\n\
entity=\"%s\">\n%s",
from,
"<tuple id=\"sg89ae\">\n\
<status>\n\
<basic>closed</basic>\n\
<es:activities>\n\
<es:activity>permanent-absence</e:activity>\n\
</es:activities>\n\
</status>\n\
</tuple>\n\
\n</presence>\n");
}
i = eXosip_build_publish(&pub,from, to, NULL, "presence", "1800", "application/pidf+xml", buf);
if (i<0){
ms_warning("Failed to build publish request.");
return -1;
}
eXosip_lock();
i = eXosip_publish(pub, to); /* should update the sip-if-match parameter
from sip-etag from last 200ok of PUBLISH */
eXosip_unlock();
if (i<0){
ms_message("Failed to send publish request.");
return -1;
}
return 0;
}
void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
SalOp *op=sal_op_new(sal);
char *tmp;
@ -521,7 +663,7 @@ void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
op->did=-1;
ms_message("And outgoing subscription terminated by remote.");
}
sal->callbacks.presence_changed(op,estatus,NULL);
sal->callbacks.notify(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL);
osip_free(tmp);
}
@ -545,3 +687,4 @@ void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev){
op->did=0;
}

View file

@ -153,10 +153,29 @@ static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt)
static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){
const char *mt=desc->type==SAL_AUDIO ? "audio" : "video";
const char *mt=desc->type==SalAudio ? "audio" : "video";
const MSList *elem;
const char *addr;
int port;
if (desc->candidates[0].addr[0]!='\0'){
addr=desc->candidates[0].addr;
port=desc->candidates[0].port;
}else{
addr=desc->addr;
port=desc->port;
}
/*only add a c= line within the stream description if address are differents*/
if (strcmp(addr,sdp_message_c_addr_get(msg, -1, 0))!=0){
bool_t inet6;
if (strchr(addr,':')!=NULL){
inet6=TRUE;
}else inet6=FALSE;
sdp_message_c_connection_add (msg, lineno,
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
osip_strdup (addr), NULL, NULL);
}
sdp_message_m_media_add (msg, osip_strdup (mt),
int_2char (desc->port), NULL,
int_2char (port), NULL,
osip_strdup ("RTP/AVP"));
sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"),
int_2char(desc->bandwidth));
@ -222,12 +241,12 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
mtype = sdp_message_m_media_get(msg, i);
proto = sdp_message_m_proto_get (msg, i);
port = sdp_message_m_port_get(msg, i);
stream->proto=SAL_PROTO_UNKNOWN;
stream->proto=SalProtoUnknown;
if (proto){
if (strcasecmp(proto,"RTP/AVP")==0)
stream->proto=SAL_PROTO_RTP_AVP;
stream->proto=SalProtoRtpAvp;
else if (strcasecmp(proto,"RTP/SAVP")==0){
stream->proto=SAL_PROTO_RTP_SAVP;
stream->proto=SalProtoRtpSavp;
}
}
addr = sdp_message_c_addr_get (msg, i, 0);
@ -235,10 +254,10 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
strncpy(stream->addr,addr,sizeof(stream->addr));
stream->ptime=_sdp_message_get_a_ptime(msg,i);
if (strcasecmp("audio", mtype) == 0){
stream->type=SAL_AUDIO;
stream->type=SalAudio;
}else if (strcasecmp("video", mtype) == 0){
stream->type=SAL_VIDEO;
}else stream->type=SAL_OTHER;
stream->type=SalVideo;
}else stream->type=SalOther;
for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
}

@ -1 +1 @@
Subproject commit a11023fbcc2ba355d40d474cc6b863e29a4960fb
Subproject commit 8dae09b11ee8a0fe29674944b207b5e06fb0f4ed

2
oRTP

@ -1 +1 @@
Subproject commit fd65d84014c4cb3c500952c2f4b42dc4630ac37d
Subproject commit da176d2f439f990012a1bf47b39fb72070dbd580