Commit 5f0a6d55 authored by Simon Morlat's avatar Simon Morlat
Browse files

sal is code complete !

parent 40e4b5d4
......@@ -18,8 +18,9 @@ liblinphone_la_SOURCES=\
exevents.c exevents.h \
offeranswer.c offeranswer.h\
sal.c sal.h \
sal_eXosip2.c \
sal_eXosip2.c sal_eXosip2.h\
sal_eXosip2_sdp.c \
sal_eXosip2_presence.c \
misc.c \
address.c \
enum.c enum.h \
......
/*
linphone
Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**
This header files defines the Signaling Abstraction Layer.
The purpose of this layer is too allow experiment different call signaling
protocols and implementations under linphone, for example SIP, JINGLE...
**/
#include "sal.h"
SalMediaDescription *sal_media_description_new(){
return ms_new0(SalMediaDescription,1);
}
void sal_media_description_destroy(SalMediaDescription *md){
int i;
for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++){
ms_list_for_each(md->streams[i].payloads,(void (*)(void *))payload_type_destroy);
ms_list_free(md->streams[i].payloads);
}
ms_free(md);
}
static void assign_string(char **str, const char *arg){
if (*str){
ms_free(*str);
*str=NULL;
}
if (arg)
*str=ms_strdup(arg);
}
void sal_op_set_contact(SalOp *op, const char *contact){
assign_string(&((SalOpBase*)op)->contact,contact);
}
void sal_op_set_route(SalOp *op, const char *route){
assign_string(&((SalOpBase*)op)->route,route);
}
void sal_op_set_from(SalOp *op, const char *from){
assign_string(&((SalOpBase*)op)->from,from);
}
void sal_op_set_to(SalOp *op, const char *to){
assign_string(&((SalOpBase*)op)->to,to);
}
void sal_op_set_user_pointer(SalOp *op, void *up){
((SalOpBase*)op)->user_pointer=up;
}
const char *sal_op_get_from(const SalOp *op){
return ((SalOpBase*)op)->from;
}
const char *sal_op_get_to(const SalOp *op){
return ((SalOpBase*)op)->to;
}
const char *sal_op_get_contact(const SalOp *op){
return ((SalOpBase*)op)->contact;
}
const char *sal_op_get_route(const SalOp *op){
return ((SalOpBase*)op)->route;
}
void *sal_op_get_user_pointer(const SalOp *op){
return ((SalOpBase*)op)->user_pointer;
}
void __sal_op_init(SalOp *b, Sal *sal){
memset(b,0,sizeof(SalOpBase));
((SalOpBase*)b)->root=sal;
}
void __sal_op_free(SalOp *op){
SalOpBase *b=(SalOpBase *)op;
if (b->from) {
ms_free(b->from);
b->from=NULL;
}
if (b->to) {
ms_free(b->to);
b->to=NULL;
}
if (b->route) {
ms_free(b->route);
b->route=NULL;
}
if (b->contact) {
ms_free(b->contact);
b->contact=NULL;
}
if (b->local_media)
sal_media_description_destroy(b->local_media);
if (b->remote_media)
sal_media_description_destroy(b->remote_media);
ms_free(op);
}
......@@ -111,6 +111,7 @@ typedef struct SalOpBase{
char *to;
SalMediaDescription *local_media;
SalMediaDescription *remote_media;
void *user_pointer;
} SalOpBase;
......@@ -160,7 +161,8 @@ 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)(Sal *sal, const char *from, SalPresenceStatus status);
typedef void (*SalOnPresenceChanged)(SalOp *op, SalPresenceStatus status, const char *msg);
typedef void (*SalOnSubscribeReceived)(SalOp *sal, const char *from);
typedef void (*SalOnInternalMsg)(Sal *sal, const char *msg);
typedef struct SalCallbacks{
......@@ -180,6 +182,7 @@ typedef struct SalCallbacks{
SalOnRefer refer_received;
SalOnTextReceived text_received;
SalOnPresenceChanged presence_changed;
SalOnSubscribeReceived subscribe_received;
SalOnInternalMsg internal_message;
}SalCallbacks;
......@@ -206,10 +209,12 @@ void sal_op_set_from(SalOp *op, const char *from);
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);
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);
void *sal_op_get_user_pointer(const SalOp *op);
/*Call API*/
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
......@@ -219,8 +224,18 @@ int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optio
const SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
int sal_call_terminate(SalOp *h);
/*Registration*/
int sal_register(SalOp *op, const char *proxy, const char *from, int expires);
/*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_subscribe_accept(SalOp *op);
int sal_subscribe_decline(SalOp *op);
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message);
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
......
......@@ -17,40 +17,41 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sal.h"
#include <eXosip2/eXosip.h>
#include "sal_eXosip2.h"
#include "offeranswer.h"
extern sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
extern int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
struct Sal{
SalCallbacks callbacks;
int running;
int session_expires;
int automatic_action;
};
struct SalOp{
SalOpBase base;
int cid;
int did;
int tid;
int rid;
int expires;
SalMediaDescription *result;
sdp_message_t *sdp_answer;
eXosip_event_t *pending_auth;
bool_t supports_session_timers;
bool_t sdp_offering;
bool_t reinvite;
};
static SalOp * sal_find_register(Sal *sal, int rid){
const MSList *elem;
SalOp *op;
for(elem=sal->registers;elem!=NULL;elem=elem->next){
op=(SalOp*)elem->data;
if (op->rid==rid) return op;
}
return NULL;
}
static void sal_add_register(Sal *sal, SalOp *op){
sal->registers=ms_list_append(sal->registers,op);
}
static void sal_remove_register(Sal *sal, int rid){
MSList *elem;
SalOp *op;
for(elem=sal->registers;elem!=NULL;elem=elem->next){
op=(SalOp*)elem->data;
if (op->rid==rid) {
sal->registers=ms_list_remove_link(sal->registers,elem);
return;
}
}
}
SalOp * sal_op_new(Sal *sal){
SalOp *op=ms_new(SalOp,1);
__sal_op_init(op,sal);
op->cid=op->did=op->tid=-1;
op->cid=op->did=op->tid=op->rid=op->nid=op->sid-1;
op->supports_session_timers=FALSE;
op->sdp_offering=TRUE;
op->pending_auth=NULL;
......@@ -64,6 +65,9 @@ void sal_op_release(SalOp *op){
sdp_message_free(op->sdp_answer);
if (op->pending_auth)
eXosip_event_free(op->pending_auth);
if( op->rid!=-1){
sal_remove_register(op->base.root,op->rid);
}
__sal_op_free(op);
}
......@@ -107,6 +111,10 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
if (ctx->callbacks.presence_changed==NULL)
ctx->callbacks.presence_changed=(SalOnPresenceChanged)unimplemented_stub;
if (ctx->callbacks.subscribe_received==NULL)
ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
if (ctx->callbacks.text_received==NULL)
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
if (ctx->callbacks.internal_message==NULL)
ctx->callbacks.internal_message=(SalOnInternalMsg)unimplemented_stub;
}
......@@ -805,7 +813,7 @@ static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *ori
}
static void registration_success(Sal *sal, eXosip_event_t *ev){
SalOp *op=(SalOp*)ev->external_reference;
SalOp *op=sal_find_register(sal,ev->rid);
osip_header_t *h=NULL;
bool_t registered;
if (op==NULL){
......@@ -824,7 +832,7 @@ static void registration_success(Sal *sal, eXosip_event_t *ev){
static bool_t registration_failure(Sal *sal, eXosip_event_t *ev){
int status_code=0;
const char *reason=NULL;
SalOp *op=(SalOp*)ev->external_reference;
SalOp *op=sal_find_register(sal,ev->rid);
SalReason sr=SalReasonUnknown;
SalError se=SalErrorUnknown;
......@@ -914,22 +922,23 @@ static bool_t process_event(Sal *sal, eXosip_event_t *ev){
}
break;
case EXOSIP_IN_SUBSCRIPTION_NEW:
ms_message("CALL_SUBSCRIPTION_NEW or UPDATE");
linphone_subscription_new(lc,ev);
ms_message("CALL_SUBSCRIPTION_NEW ");
sal_exosip_subscription_recv(sal,ev);
break;
case EXOSIP_SUBSCRIPTION_UPDATE:
ms_message("CALL_SUBSCRIPTION_UPDATE");
break;
case EXOSIP_SUBSCRIPTION_NOTIFY:
ms_message("CALL_SUBSCRIPTION_NOTIFY");
linphone_notify_recv(lc,ev);
sal_exosip_notify_recv(sal,ev);
break;
case EXOSIP_SUBSCRIPTION_ANSWERED:
ms_message("EXOSIP_SUBSCRIPTION_ANSWERED, ev->sid=%i\n",ev->sid);
linphone_subscription_answered(lc,ev);
sal_exosip_subscription_answered(sal,ev);
break;
case EXOSIP_SUBSCRIPTION_CLOSED:
ms_message("EXOSIP_SUBSCRIPTION_CLOSED\n");
linphone_subscription_closed(lc,ev);
sal_exosip_subscription_closed(sal,ev);
break;
case EXOSIP_CALL_RELEASED:
ms_message("CALL_RELEASED\n");
......@@ -971,20 +980,22 @@ int sal_iterate(Sal *sal){
eXosip_unlock();
}
}
return 0;
}
int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
osip_message_t *msg;
if (h->rid==-1){
eXosip_lock();
h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(op),expires,&msg);
h->rid=eXosip_register_build_initial_register(from,proxy,sal_op_get_contact(h),expires,&msg);
sal_add_register(h->base.root,h);
}else{
eXosip_lock();
eXosip_register_build_register(h->rid,expires,&msg);
}
eXosip_register_send_register(h->rid,msg);
eXosip_unlock();
op->expires=expires;
h->expires=expires;
return 0;
}
......
/*
linphone
Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef sal_exosip2_h
#define sal_exosip2_h
#include "sal.h"
#include <eXosip2/eXosip.h>
sdp_message_t *media_description_to_sdp(const SalMediaDescription *sal);
int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
struct Sal{
SalCallbacks callbacks;
MSList *registers;/*MSList of SalOp */
MSList *out_subscribes;/*MSList of SalOp */
MSList *in_subscribes;/*MSList of SalOp */
int running;
int session_expires;
int automatic_action;
};
struct SalOp{
SalOpBase base;
int cid;
int did;
int tid;
int rid;
int sid;
int nid;
int expires;
SalMediaDescription *result;
sdp_message_t *sdp_answer;
eXosip_event_t *pending_auth;
bool_t supports_session_timers;
bool_t sdp_offering;
bool_t reinvite;
};
void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev);
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);
#endif
/*
linphone
Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sal_eXosip2.h"
static SalOp * sal_find_out_subscribe(Sal *sal, int sid){
const MSList *elem;
SalOp *op;
for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
op=(SalOp*)elem->data;
if (op->sid==sid) return op;
}
return NULL;
}
static void sal_add_out_subscribe(Sal *sal, SalOp *op){
sal->out_subscribes=ms_list_append(sal->out_subscribes,op);
}
static void sal_remove_out_subscribe(Sal *sal, int sid){
MSList *elem;
SalOp *op;
for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){
op=(SalOp*)elem->data;
if (op->sid==sid) {
sal->out_subscribes=ms_list_remove_link(sal->out_subscribes,elem);
return;
}
}
}
static SalOp * sal_find_in_subscribe(Sal *sal, int nid){
const MSList *elem;
SalOp *op;
for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
op=(SalOp*)elem->data;
if (op->nid==nid) return op;
}
return NULL;
}
static void sal_add_in_subscribe(Sal *sal, SalOp *op){
sal->in_subscribes=ms_list_append(sal->in_subscribes,op);
}
static void sal_remove_in_subscribe(Sal *sal, int nid){
MSList *elem;
SalOp *op;
for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
op=(SalOp*)elem->data;
if (op->nid==nid) {
sal->in_subscribes=ms_list_remove_link(sal->in_subscribes,elem);
return;
}
}
}
int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){
osip_message_t *sip=NULL;
if (from)
sal_op_set_from(op,from);
if (to)
sal_op_set_to(op,to);
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);
eXosip_unlock();
return 0;
}
/*presence Subscribe/notify*/
int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
osip_message_t *msg;
if (from)
sal_op_set_from(op,from);
if (to)
sal_op_set_to(op,to);
eXosip_lock();
eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op),
sal_op_get_route(op),"presence",600);
op->sid=eXosip_subscribe_send_initial_request(msg);
eXosip_unlock();
if (op->sid==-1){
osip_message_free(msg);
return -1;
}
sal_add_out_subscribe(op->base.root,op);
return 0;
}
int sal_unsubscribe(SalOp *op){
osip_message_t *msg=NULL;
if (op->did==-1){
ms_error("cannot unsubscribe, no dialog !");
return -1;
}
eXosip_lock();
eXosip_subscribe_build_refresh_request(op->did,&msg);
if (msg){
osip_message_set_expires(msg,"0");
eXosip_subscribe_send_refresh_request(op->did,msg);
}else ms_error("Could not build subscribe refresh request !");
eXosip_unlock();
return 0;
}
int sal_subscribe_accept(SalOp *op){
osip_message_t *msg;
eXosip_lock();
eXosip_insubscription_build_answer(op->tid,202,&msg);
eXosip_insubscription_send_answer(op->tid,202,msg);
eXosip_unlock();
return 0;
}
int sal_subscribe_decline(SalOp *op){
eXosip_lock();
eXosip_insubscription_send_answer(op->tid,401,NULL);
eXosip_unlock();
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];
#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==SalPresenceOnline)
{
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==SalPresenceBusy)
{
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\