mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-23 14:18:07 +00:00
Merge branch 'dev_sal'
This commit is contained in:
commit
97e377cf5d
34 changed files with 5318 additions and 2284 deletions
9
NEWS
9
NEWS
|
|
@ -1,9 +1,18 @@
|
|||
linphone-3.3.0 -- ?????????
|
||||
* liblinphone is ported to iphoneOS and Google Android
|
||||
* Internal refactoring of liblinphone (code factorisation, encapsulation
|
||||
of signaling)
|
||||
* enhancements made to presence support (SIP/SIMPLE)
|
||||
|
||||
linphone-3.2.2 -- ?????????
|
||||
* improve bitrate usage of speex codec
|
||||
* allow speex to run with vbr (variable bit rate) mode
|
||||
* add speex/32000 (ultra wide band speex codec)
|
||||
* answer empty SIP INFO requests
|
||||
* reverse order of call logs
|
||||
* optimize video display
|
||||
* manual or automatic network connectivity management (so that REGISTERs
|
||||
are only sent when network is up or refreshed when it comes back)
|
||||
|
||||
linphone-3.2.1 -- October 5, 2009
|
||||
* improve graphics and behaviour of mute button
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ INCLUDES = \
|
|||
|
||||
|
||||
|
||||
bin_PROGRAMS = linphonec sipomatic linphonecsh
|
||||
bin_PROGRAMS = linphonec linphonecsh
|
||||
|
||||
if BUILD_WIN32
|
||||
bin_PROGRAMS += linphoned
|
||||
|
|
|
|||
|
|
@ -1337,7 +1337,7 @@ linphonec_proxy_use(LinphoneCore *lc, int index)
|
|||
static void
|
||||
linphonec_friend_display(LinphoneFriend *fr)
|
||||
{
|
||||
LinphoneAddress *uri=linphone_address_clone(linphone_friend_get_uri(fr));
|
||||
LinphoneAddress *uri=linphone_address_clone(linphone_friend_get_address(fr));
|
||||
char *str;
|
||||
|
||||
linphonec_out("name: %s\n", linphone_address_get_display_name(uri));
|
||||
|
|
@ -1362,7 +1362,7 @@ linphonec_friend_list(LinphoneCore *lc, char *pat)
|
|||
{
|
||||
if ( pat ) {
|
||||
const char *name = linphone_address_get_display_name(
|
||||
linphone_friend_get_uri((LinphoneFriend*)friend->data));
|
||||
linphone_friend_get_address((LinphoneFriend*)friend->data));
|
||||
if (name && ! strstr(name, pat) ) continue;
|
||||
}
|
||||
linphonec_out("****** Friend %i *******\n",n);
|
||||
|
|
@ -1384,7 +1384,7 @@ linphonec_friend_call(LinphoneCore *lc, unsigned int num)
|
|||
if ( n == num )
|
||||
{
|
||||
int ret;
|
||||
addr = linphone_address_as_string(linphone_friend_get_uri((LinphoneFriend*)friend->data));
|
||||
addr = linphone_address_as_string(linphone_friend_get_address((LinphoneFriend*)friend->data));
|
||||
ret=lpc_cmd_call(lc, addr);
|
||||
ms_free(addr);
|
||||
return ret;
|
||||
|
|
@ -1458,17 +1458,16 @@ static int lpc_cmd_register(LinphoneCore *lc, char *args){
|
|||
return 1;
|
||||
}
|
||||
if (passwd[0]!='\0'){
|
||||
osip_from_t *from;
|
||||
LinphoneAddress *from;
|
||||
LinphoneAuthInfo *info;
|
||||
osip_from_init(&from);
|
||||
if (osip_from_parse(from,identity)==0){
|
||||
if ((from=linphone_address_new(identity))!=NULL){
|
||||
char realm[128];
|
||||
snprintf(realm,sizeof(realm)-1,"\"%s\"",from->url->host);
|
||||
info=linphone_auth_info_new(from->url->username,NULL,passwd,NULL,NULL);
|
||||
snprintf(realm,sizeof(realm)-1,"\"%s\"",linphone_address_get_domain(from));
|
||||
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,passwd,NULL,NULL);
|
||||
linphone_core_add_auth_info(lc,info);
|
||||
linphone_address_destroy(from);
|
||||
linphone_auth_info_destroy(info);
|
||||
}
|
||||
osip_from_free(from);
|
||||
}
|
||||
elem=linphone_core_get_proxy_config_list(lc);
|
||||
if (elem) {
|
||||
|
|
@ -1674,7 +1673,8 @@ static void linphonec_codec_list(LinphoneCore *lc){
|
|||
MSList *node;
|
||||
for(node=config->audio_codecs;node!=NULL;node=ms_list_next(node)){
|
||||
pt=(PayloadType*)(node->data);
|
||||
linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, payload_type_enabled(pt) ? "enabled" : "disabled");
|
||||
linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate,
|
||||
linphone_core_payload_type_enabled(lc,pt) ? "enabled" : "disabled");
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,8 +119,7 @@ static void linphonec_display_something (LinphoneCore * lc, const char *somethin
|
|||
static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url);
|
||||
static void linphonec_display_warning (LinphoneCore * lc, const char *something);
|
||||
static void stub () {}
|
||||
static void linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid,
|
||||
const char *from, const char *status, const char *img);
|
||||
static void linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid);
|
||||
static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
|
||||
LinphoneFriend *lf, const char *url);
|
||||
static void linphonec_bye_received(LinphoneCore *lc, const char *from);
|
||||
|
|
@ -283,10 +282,11 @@ linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *usern
|
|||
* Linphone core callback
|
||||
*/
|
||||
static void
|
||||
linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid,
|
||||
const char *from, const char *status, const char *img)
|
||||
linphonec_notify_received(LinphoneCore *lc,LinphoneFriend *fid)
|
||||
{
|
||||
printf("Friend %s is %s\n", from, status);
|
||||
char *tmp=linphone_address_as_string(linphone_friend_get_address(fid));
|
||||
printf("Friend %s is %s\n", tmp, linphone_online_status_to_string(linphone_friend_get_status(fid)));
|
||||
ms_free(tmp);
|
||||
// todo: update Friend list state (unimplemented)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,18 +17,22 @@ lib_LTLIBRARIES=liblinphone.la
|
|||
|
||||
liblinphone_la_SOURCES=\
|
||||
linphonecore.c linphonecore.h private.h\
|
||||
exevents.c exevents.h \
|
||||
offeranswer.c offeranswer.h\
|
||||
sal.c sal.h \
|
||||
sal_eXosip2.c sal_eXosip2.h\
|
||||
sal_eXosip2_sdp.c \
|
||||
sal_eXosip2_presence.c \
|
||||
callbacks.c \
|
||||
misc.c \
|
||||
address.c \
|
||||
enum.c enum.h \
|
||||
sdphandler.c sdphandler.h \
|
||||
presence.c \
|
||||
proxy.c \
|
||||
friend.c \
|
||||
authentication.c \
|
||||
lpconfig.c lpconfig.h \
|
||||
chat.c \
|
||||
general_state.c \
|
||||
general_state.c \
|
||||
sipsetup.c sipsetup.h \
|
||||
siplogin.c
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "linphonecore.h"
|
||||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
#include <eXosip2/eXosip.h>
|
||||
|
||||
/**
|
||||
* @addtogroup linphone_address
|
||||
|
|
@ -31,123 +30,87 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
* Constructs a LinphoneAddress object by parsing the user supplied address,
|
||||
* given as a string.
|
||||
**/
|
||||
LinphoneAddress * linphone_address_new(const char *uri){
|
||||
osip_from_t *from;
|
||||
osip_from_init(&from);
|
||||
if (osip_from_parse(from,uri)!=0){
|
||||
osip_from_free(from);
|
||||
ms_error("Cannot create LinphoneAddress, bad uri [%s]",uri);
|
||||
return NULL;
|
||||
}
|
||||
return from;
|
||||
LinphoneAddress * linphone_address_new(const char *addr){
|
||||
SalAddress *saddr=sal_address_new(addr);
|
||||
if (saddr==NULL) ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr);
|
||||
return saddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones a LinphoneAddress object.
|
||||
**/
|
||||
LinphoneAddress * linphone_address_clone(const LinphoneAddress *uri){
|
||||
osip_from_t *ret=NULL;
|
||||
osip_from_clone(uri,&ret);
|
||||
return ret;
|
||||
LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){
|
||||
return sal_address_clone(addr);
|
||||
}
|
||||
|
||||
#define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
|
||||
|
||||
/**
|
||||
* Returns the address scheme, normally "sip".
|
||||
**/
|
||||
const char *linphone_address_get_scheme(const LinphoneAddress *u){
|
||||
return null_if_empty(u->url->scheme);
|
||||
return sal_address_get_scheme(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name.
|
||||
**/
|
||||
const char *linphone_address_get_display_name(const LinphoneAddress* u){
|
||||
return null_if_empty(u->displayname);
|
||||
return sal_address_get_display_name(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username.
|
||||
**/
|
||||
const char *linphone_address_get_username(const LinphoneAddress *u){
|
||||
return null_if_empty(u->url->username);
|
||||
return sal_address_get_username(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain name.
|
||||
**/
|
||||
const char *linphone_address_get_domain(const LinphoneAddress *u){
|
||||
return null_if_empty(u->url->host);
|
||||
return sal_address_get_domain(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the display name.
|
||||
**/
|
||||
void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
|
||||
if (u->displayname!=NULL){
|
||||
osip_free(u->displayname);
|
||||
u->displayname=NULL;
|
||||
}
|
||||
if (display_name!=NULL)
|
||||
u->displayname=osip_strdup(display_name);
|
||||
sal_address_set_display_name(u,display_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username.
|
||||
**/
|
||||
void linphone_address_set_username(LinphoneAddress *uri, const char *username){
|
||||
if (uri->url->username!=NULL){
|
||||
osip_free(uri->url->username);
|
||||
uri->url->username=NULL;
|
||||
}
|
||||
if (username)
|
||||
uri->url->username=osip_strdup(username);
|
||||
sal_address_set_username(uri,username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the domain.
|
||||
**/
|
||||
void linphone_address_set_domain(LinphoneAddress *uri, const char *host){
|
||||
if (uri->url->host!=NULL){
|
||||
osip_free(uri->url->host);
|
||||
uri->url->host=NULL;
|
||||
}
|
||||
if (host)
|
||||
uri->url->host=osip_strdup(host);
|
||||
sal_address_set_domain(uri,host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port number.
|
||||
**/
|
||||
void linphone_address_set_port(LinphoneAddress *uri, const char *port){
|
||||
if (uri->url->port!=NULL){
|
||||
osip_free(uri->url->port);
|
||||
uri->url->port=NULL;
|
||||
}
|
||||
if (port)
|
||||
uri->url->port=osip_strdup(port);
|
||||
sal_address_set_port(uri,port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the port number.
|
||||
**/
|
||||
void linphone_address_set_port_int(LinphoneAddress *uri, int port){
|
||||
char tmp[12];
|
||||
if (port==5060){
|
||||
/*this is the default, special case to leave the port field blank*/
|
||||
linphone_address_set_port(uri,NULL);
|
||||
return;
|
||||
}
|
||||
snprintf(tmp,sizeof(tmp),"%i",port);
|
||||
linphone_address_set_port(uri,tmp);
|
||||
sal_address_set_port_int(uri,port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes address's tags and uri headers so that it is displayable to the user.
|
||||
**/
|
||||
void linphone_address_clean(LinphoneAddress *uri){
|
||||
osip_generic_param_freelist(&uri->gen_params);
|
||||
sal_address_clean(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -155,11 +118,7 @@ void linphone_address_clean(LinphoneAddress *uri){
|
|||
* The returned char * must be freed by the application. Use ms_free().
|
||||
**/
|
||||
char *linphone_address_as_string(const LinphoneAddress *u){
|
||||
char *tmp,*ret;
|
||||
osip_from_to_str(u,&tmp);
|
||||
ret=ms_strdup(tmp);
|
||||
osip_free(tmp);
|
||||
return ret;
|
||||
return sal_address_as_string(u);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -167,18 +126,14 @@ char *linphone_address_as_string(const LinphoneAddress *u){
|
|||
* The returned char * must be freed by the application. Use ms_free().
|
||||
**/
|
||||
char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
|
||||
char *tmp=NULL,*ret;
|
||||
osip_uri_to_str(u->url,&tmp);
|
||||
ret=ms_strdup(tmp);
|
||||
osip_free(tmp);
|
||||
return ret;
|
||||
return sal_address_as_string_uri_only(u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a LinphoneAddress object.
|
||||
**/
|
||||
void linphone_address_destroy(LinphoneAddress *u){
|
||||
osip_from_free(u);
|
||||
sal_address_destroy(u);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,12 +24,8 @@
|
|||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include <eXosip2/eXosip.h>
|
||||
#include <osipparser2/osip_message.h>
|
||||
#include "lpconfig.h"
|
||||
|
||||
extern LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid);
|
||||
|
||||
/**
|
||||
* @addtogroup authentication
|
||||
* @{
|
||||
|
|
@ -51,7 +47,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;
|
||||
}
|
||||
|
||||
|
|
@ -63,10 +58,28 @@ static LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){
|
|||
if (ai->ha1) obj->ha1=ms_strdup(ai->ha1);
|
||||
if (ai->realm) obj->realm=ms_strdup(ai->realm);
|
||||
obj->works=FALSE;
|
||||
obj->first_time=TRUE;
|
||||
obj->usecount=0;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns username.
|
||||
**/
|
||||
const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i){
|
||||
return i->username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns password.
|
||||
**/
|
||||
const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i){
|
||||
return i->passwd;
|
||||
}
|
||||
|
||||
const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i){
|
||||
return i->userid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
**/
|
||||
|
|
@ -224,21 +237,6 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void refresh_exosip_auth_info(LinphoneCore *lc){
|
||||
MSList *elem;
|
||||
eXosip_lock();
|
||||
eXosip_clear_authentication_info();
|
||||
for (elem=lc->auth_info;elem!=NULL;elem=ms_list_next(elem)){
|
||||
LinphoneAuthInfo *info=(LinphoneAuthInfo*)elem->data;
|
||||
char *userid;
|
||||
if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
|
||||
else userid=info->userid;
|
||||
eXosip_add_authentication_info(info->username,userid,
|
||||
info->passwd,info->ha1,info->realm);
|
||||
}
|
||||
eXosip_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds authentication information to the LinphoneCore.
|
||||
*
|
||||
|
|
@ -247,6 +245,7 @@ static void refresh_exosip_auth_info(LinphoneCore *lc){
|
|||
void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
|
||||
{
|
||||
LinphoneAuthInfo *ai;
|
||||
MSList *elem;
|
||||
|
||||
/* find if we are attempting to modify an existing auth info */
|
||||
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username);
|
||||
|
|
@ -255,10 +254,23 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
|
|||
linphone_auth_info_destroy(ai);
|
||||
}
|
||||
lc->auth_info=ms_list_append(lc->auth_info,linphone_auth_info_clone(info));
|
||||
|
||||
refresh_exosip_auth_info(lc);
|
||||
/* if the user was prompted, re-allow automatic_action */
|
||||
if (lc->automatic_action>0) lc->automatic_action--;
|
||||
/* retry pending authentication operations */
|
||||
for(elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){
|
||||
const char *username,*realm;
|
||||
SalOp *op=(SalOp*)elem->data;
|
||||
LinphoneAuthInfo *ai;
|
||||
sal_op_get_auth_requested(op,&realm,&username);
|
||||
ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
if (ai){
|
||||
SalAuthInfo sai;
|
||||
sai.username=ai->username;
|
||||
sai.userid=ai->userid;
|
||||
sai.realm=ai->realm;
|
||||
sai.password=ai->passwd;
|
||||
sal_op_authenticate(op,&sai);
|
||||
ai->usecount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -267,7 +279,6 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
|
|||
* from the auth_info_requested callback of LinphoneCoreVTable.
|
||||
**/
|
||||
void linphone_core_abort_authentication(LinphoneCore *lc, LinphoneAuthInfo *info){
|
||||
if (lc->automatic_action>0) lc->automatic_action--;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -286,7 +297,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in
|
|||
linphone_auth_info_write_config(lc->config,(LinphoneAuthInfo*)elem->data,i);
|
||||
}
|
||||
linphone_auth_info_write_config(lc->config,NULL,i);
|
||||
refresh_exosip_auth_info(lc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -303,9 +313,6 @@ const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){
|
|||
void linphone_core_clear_all_auth_info(LinphoneCore *lc){
|
||||
MSList *elem;
|
||||
int i;
|
||||
eXosip_lock();
|
||||
eXosip_clear_authentication_info();
|
||||
eXosip_unlock();
|
||||
for(i=0,elem=lc->auth_info;elem!=NULL;elem=ms_list_next(elem),i++){
|
||||
LinphoneAuthInfo *info=(LinphoneAuthInfo*)elem->data;
|
||||
linphone_auth_info_destroy(info);
|
||||
|
|
@ -315,84 +322,6 @@ void linphone_core_clear_all_auth_info(LinphoneCore *lc){
|
|||
lc->auth_info=NULL;
|
||||
}
|
||||
|
||||
void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev){
|
||||
char *prx_realm=NULL,*www_realm=NULL;
|
||||
osip_proxy_authorization_t *prx_auth;
|
||||
osip_authorization_t *www_auth;
|
||||
osip_message_t *msg=ev->request;
|
||||
char *username;
|
||||
LinphoneAuthInfo *as=NULL;
|
||||
|
||||
username=osip_uri_get_username(msg->from->url);
|
||||
osip_message_get_proxy_authorization(msg,0,&prx_auth);
|
||||
osip_message_get_authorization(msg,0,&www_auth);
|
||||
if (prx_auth!=NULL)
|
||||
prx_realm=osip_proxy_authorization_get_realm(prx_auth);
|
||||
if (www_auth!=NULL)
|
||||
www_realm=osip_authorization_get_realm(www_auth);
|
||||
|
||||
if (prx_realm==NULL && www_realm==NULL){
|
||||
ms_message("No authentication info in the request, ignoring");
|
||||
return;
|
||||
}
|
||||
/* see if we already have this auth information , not to ask it everytime to the user */
|
||||
if (prx_realm!=NULL)
|
||||
as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,prx_realm,username);
|
||||
if (www_realm!=NULL)
|
||||
as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,www_realm,username);
|
||||
if (as){
|
||||
ms_message("Authentication for user=%s realm=%s is working.",username,prx_realm ? prx_realm : www_realm);
|
||||
as->works=TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void linphone_core_find_or_ask_for_auth_info(LinphoneCore *lc,const char *username,const char* realm, int tid)
|
||||
{
|
||||
LinphoneAuthInfo *as=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
if ( as==NULL || (as!=NULL && as->works==FALSE && as->first_time==FALSE)){
|
||||
if (lc->vtable.auth_info_requested!=NULL){
|
||||
lc->vtable.auth_info_requested(lc,realm,username);
|
||||
lc->automatic_action++;/*suspends eXosip_automatic_action until the user supplies a password */
|
||||
}
|
||||
}
|
||||
if (as) as->first_time=FALSE;
|
||||
}
|
||||
|
||||
void linphone_process_authentication(LinphoneCore *lc, eXosip_event_t *ev)
|
||||
{
|
||||
char *prx_realm=NULL,*www_realm=NULL;
|
||||
osip_proxy_authenticate_t *prx_auth;
|
||||
osip_www_authenticate_t *www_auth;
|
||||
osip_message_t *resp=ev->response;
|
||||
char *username;
|
||||
|
||||
/*
|
||||
if (strcmp(ev->request->sip_method,"REGISTER")==0) {
|
||||
gstate_new_state(lc, GSTATE_REG_FAILED, "Authentication required");
|
||||
}
|
||||
*/
|
||||
|
||||
username=osip_uri_get_username(resp->from->url);
|
||||
prx_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->proxy_authenticates,0);
|
||||
www_auth=(osip_proxy_authenticate_t*)osip_list_get(&resp->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 server response.");
|
||||
return;
|
||||
}
|
||||
/* see if we already have this auth information , not to ask it everytime to the user */
|
||||
if (prx_realm!=NULL)
|
||||
linphone_core_find_or_ask_for_auth_info(lc,username,prx_realm,ev->tid);
|
||||
if (www_realm!=NULL)
|
||||
linphone_core_find_or_ask_for_auth_info(lc,username,www_realm,ev->tid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
|
|
|||
457
coreapi/callbacks.c
Normal file
457
coreapi/callbacks.c
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
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.h"
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
|
||||
static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
|
||||
if (lc->vtable.show)
|
||||
lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Connected."));
|
||||
call->state=LCStateAVRunning;
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_start_media_streams(lc,call);
|
||||
}
|
||||
|
||||
static void call_received(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
char *barmesg;
|
||||
LinphoneCall *call;
|
||||
const char *from,*to;
|
||||
char *tmp;
|
||||
LinphoneAddress *from_parsed;
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
|
||||
ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
|
||||
if (lc->presence_mode==LINPHONE_STATUS_BUSY)
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
else if (lc->presence_mode==LINPHONE_STATUS_AWAY
|
||||
||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
|
||||
||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
|
||||
||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
|
||||
||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
|
||||
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
|
||||
else
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(h);
|
||||
return;
|
||||
}
|
||||
if (lc->call!=NULL){/*busy*/
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(h);
|
||||
return;
|
||||
}
|
||||
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),h);
|
||||
lc->call=call;
|
||||
sal_call_set_local_media_description(h,call->localdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(h);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
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(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 is contacting you"),tmp);
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
|
||||
/* play the ring */
|
||||
if (lc->sound_conf.ring_sndcard!=NULL){
|
||||
ms_message("Starting local ring...");
|
||||
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(h);
|
||||
linphone_core_init_media_streams(lc,lc->call);
|
||||
if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
|
||||
ms_free(barmesg);
|
||||
ms_free(tmp);
|
||||
}
|
||||
|
||||
static void call_ringing(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneCall *call=lc->call;
|
||||
SalMediaDescription *md;
|
||||
if (call==NULL) return;
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Remote ringing."));
|
||||
md=sal_call_get_final_media_description(h);
|
||||
if (md==NULL){
|
||||
if (lc->ringstream!=NULL) return; /*already ringing !*/
|
||||
if (lc->sound_conf.play_sndcard!=NULL){
|
||||
ms_message("Remote ringing...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
|
||||
}
|
||||
}else{
|
||||
/*accept early media */
|
||||
if (lc->audiostream && lc->audiostream->ticker!=NULL){
|
||||
/*streams already started */
|
||||
ms_message("Early media already started.");
|
||||
return;
|
||||
}
|
||||
sal_media_description_ref(md);
|
||||
call->resultdesc=md;
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Early media."));
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
ms_message("Doing early media...");
|
||||
linphone_core_start_media_streams(lc,call);
|
||||
call->media_pending=TRUE;
|
||||
}
|
||||
call->state=LCStateRinging;
|
||||
}
|
||||
|
||||
static void call_accepted(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 accept.");
|
||||
return ;
|
||||
}
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_accepted: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (call->state==LCStateAVRunning){
|
||||
return ; /*already accepted*/
|
||||
}
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc){
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
call->media_pending=FALSE;
|
||||
}
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
|
||||
linphone_connect_incoming(lc,call);
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
return ;
|
||||
}
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_ack: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (call->media_pending){
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
|
||||
linphone_connect_incoming(lc,call);
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP response received in ACK, need to abort the call");
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
}
|
||||
call->media_pending=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
linphone_connect_incoming(lc,call);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
ms_message("Current call terminated...");
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc,lc->call);
|
||||
lc->vtable.show(lc);
|
||||
lc->vtable.display_status(lc,_("Call terminated."));
|
||||
gstate_new_state(lc, GSTATE_CALL_END, NULL);
|
||||
if (lc->vtable.bye_recv!=NULL){
|
||||
LinphoneAddress *addr=linphone_address_new(from);
|
||||
char *tmp;
|
||||
linphone_address_clean(addr);
|
||||
tmp=linphone_address_as_string(addr);
|
||||
lc->vtable.bye_recv(lc,tmp);
|
||||
ms_free(tmp);
|
||||
linphone_address_destroy(addr);
|
||||
}
|
||||
linphone_call_destroy(lc->call);
|
||||
lc->call=NULL;
|
||||
}
|
||||
|
||||
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){
|
||||
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.");
|
||||
LinphoneCall *call=lc->call;
|
||||
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_failure: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
|
||||
if (error==SalErrorNoResponse){
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("No response."));
|
||||
}else if (error==SalErrorProtocol){
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc, details ? details : _("Error."));
|
||||
}else if (error==SalErrorFailure){
|
||||
switch(sr){
|
||||
case SalReasonDeclined:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg603);
|
||||
break;
|
||||
case SalReasonBusy:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg486);
|
||||
break;
|
||||
case SalReasonRedirect:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Redirected"));
|
||||
break;
|
||||
case SalReasonTemporarilyUnavailable:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg480);
|
||||
break;
|
||||
case SalReasonNotFound:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Not found"));
|
||||
break;
|
||||
case SalReasonDoNotDisturb:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg600);
|
||||
break;
|
||||
case SalReasonMedia:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("No common codecs"));
|
||||
break;
|
||||
default:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Call failed."));
|
||||
}
|
||||
}
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
if (call!=NULL) {
|
||||
linphone_call_destroy(call);
|
||||
gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
|
||||
lc->call=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void auth_requested(SalOp *h, const char *realm, const char *username){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
ms_message("auth_requested() for realm=%s, username=%s",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;
|
||||
ms_message("auth_requested(): authenticating realm=%s, username=%s",realm,username);
|
||||
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=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
if (ai){
|
||||
ms_message("%s/%s authentication works.",realm,username);
|
||||
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);
|
||||
cfg->registered=registered;
|
||||
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(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 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 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);
|
||||
}
|
||||
|
||||
static void ping_reply(SalOp *op){
|
||||
LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op);
|
||||
ms_message("ping reply !");
|
||||
if (call){
|
||||
if (call->state==LCStatePreEstablishing){
|
||||
linphone_core_start_invite(call->core,call,NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SalCallbacks linphone_sal_callbacks={
|
||||
call_received,
|
||||
call_ringing,
|
||||
call_accepted,
|
||||
call_ack,
|
||||
call_updated,
|
||||
call_terminated,
|
||||
call_failure,
|
||||
auth_requested,
|
||||
auth_success,
|
||||
register_success,
|
||||
register_failure,
|
||||
vfu_request,
|
||||
dtmf_received,
|
||||
refer_received,
|
||||
text_received,
|
||||
notify,
|
||||
subscribe_received,
|
||||
subscribe_closed,
|
||||
internal_message,
|
||||
ping_reply
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -24,17 +24,16 @@
|
|||
|
||||
#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;
|
||||
char *route;
|
||||
if (linphone_core_interpret_url(lc,to,&parsed_url,&route)){
|
||||
|
||||
if ((parsed_url=linphone_core_interpret_url(lc,to))!=NULL){
|
||||
LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1);
|
||||
cr->lc=lc;
|
||||
cr->peer=linphone_address_as_string(parsed_url);
|
||||
cr->peer_url=parsed_url;
|
||||
cr->route=route;
|
||||
cr->route=ms_strdup(linphone_core_get_route(lc));
|
||||
lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr);
|
||||
return cr;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -464,7 +464,8 @@ int linphone_set_audio_offer(sdp_context_t *ctx)
|
|||
elem=lc->codecs_conf.audio_codecs;
|
||||
while(elem!=NULL){
|
||||
codec=(PayloadType*) elem->data;
|
||||
if (linphone_core_check_payload_type_usability(lc,codec) && payload_type_enabled(codec)){
|
||||
if (linphone_core_check_payload_type_usability(lc,codec) &&
|
||||
linphone_core_payload_type_enabled(lc,codec)){
|
||||
sdp_payload_init(&payload);
|
||||
payload.a_rtpmap=ortp_strdup_printf("%s/%i/1",codec->mime_type,codec->clock_rate);
|
||||
payload.pt=rtp_profile_get_payload_number_from_rtpmap(lc->local_profile,payload.a_rtpmap);
|
||||
|
|
@ -539,7 +540,8 @@ int linphone_set_video_offer(sdp_context_t *ctx)
|
|||
|
||||
for(elem=lc->codecs_conf.video_codecs;elem!=NULL;elem=ms_list_next(elem)){
|
||||
codec=(PayloadType*) elem->data;
|
||||
if (linphone_core_check_payload_type_usability(lc,codec) && payload_type_enabled(codec)){
|
||||
if (linphone_core_check_payload_type_usability(lc,codec) &&
|
||||
linphone_core_payload_type_enabled(lc,codec)){
|
||||
sdp_payload_t payload;
|
||||
sdp_payload_init(&payload);
|
||||
payload.line=1;
|
||||
|
|
@ -591,7 +593,7 @@ SupportLevel linphone_payload_is_supported(LinphoneCore *lc, sdp_payload_t *payl
|
|||
ms_warning("payload %s is not usable",rtppayload->mime_type);
|
||||
return Unsupported;
|
||||
}
|
||||
if ( !payload_type_enabled(rtppayload)) {
|
||||
if ( !linphone_core_payload_type_enabled(lc,rtppayload)) {
|
||||
ms_warning("payload %s is not enabled.",rtppayload->mime_type);
|
||||
return Unsupported;
|
||||
}
|
||||
|
|
|
|||
451
coreapi/friend.c
451
coreapi/friend.c
|
|
@ -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,34 @@ 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");
|
||||
fr->status=LINPHONE_STATUS_OFFLINE;
|
||||
/*
|
||||
if (fr->lc->vtable.notify_recv)
|
||||
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr);
|
||||
*/
|
||||
}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);
|
||||
fr->subscribe_active=TRUE;
|
||||
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;
|
||||
|
|
@ -175,6 +173,10 @@ LinphoneFriend *linphone_friend_new_with_addr(const char *addr){
|
|||
return fr;
|
||||
}
|
||||
|
||||
bool_t linphone_friend_in_list(const LinphoneFriend *lf){
|
||||
return lf->lc!=NULL;
|
||||
}
|
||||
|
||||
void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char **result){
|
||||
LinphoneAddress *fr=NULL;
|
||||
*result=NULL;
|
||||
|
|
@ -214,6 +216,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 +243,84 @@ 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;
|
||||
lf->subscribe_active=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_friend_close_subscriptions(LinphoneFriend *lf){
|
||||
linphone_friend_unsubscribe(lf);
|
||||
if (lf->insub){
|
||||
sal_notify_close(lf->insub);
|
||||
sal_op_release(lf->insub);
|
||||
lf->insub=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_friend_destroy(LinphoneFriend *lf){
|
||||
linphone_friend_notify(lf,EXOSIP_SUBCRSTATE_TERMINATED,LINPHONE_STATUS_CLOSED);
|
||||
linphone_friend_unsubscribe(lf);
|
||||
|
||||
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){
|
||||
const LinphoneAddress *linphone_friend_get_address(const LinphoneFriend *lf){
|
||||
return lf->uri;
|
||||
}
|
||||
|
||||
|
||||
bool_t linphone_friend_get_send_subscribe(const LinphoneFriend *lf){
|
||||
return lf->subscribe;
|
||||
}
|
||||
|
|
@ -597,22 +349,22 @@ 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->subscribe_active==FALSE){
|
||||
ms_message("Sending a new SUBSCRIBE");
|
||||
__linphone_friend_do_subscribe(fr);
|
||||
}
|
||||
ms_message("linphone_friend_apply() done.");
|
||||
|
|
@ -632,6 +384,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 +427,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 +512,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 +535,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 +553,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){
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
|
||||
#include "linphonecore.h"
|
||||
|
||||
#include "private.h"
|
||||
#if 0
|
||||
static const char *_gstates_text[] = {
|
||||
"GSTATE_POWER_OFF", /* 0 */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -39,109 +39,10 @@ extern "C" {
|
|||
|
||||
struct _MSSndCard;
|
||||
struct _LinphoneCore;
|
||||
|
||||
bool_t payload_type_enabled(struct _PayloadType *pt);
|
||||
void payload_type_set_enable(struct _PayloadType *pt,int value);
|
||||
const char *payload_type_get_description(struct _PayloadType *pt);
|
||||
struct SalOp;
|
||||
|
||||
struct _LpConfig;
|
||||
|
||||
typedef struct sip_config
|
||||
{
|
||||
char *contact;
|
||||
char *guessed_contact;
|
||||
int sip_port;
|
||||
MSList *proxies;
|
||||
MSList *deleted_proxies;
|
||||
int inc_timeout; /*timeout after an un-answered incoming call is rejected*/
|
||||
bool_t use_info;
|
||||
bool_t use_rfc2833; /*force RFC2833 to be sent*/
|
||||
bool_t guess_hostname;
|
||||
bool_t loopback_only;
|
||||
bool_t ipv6_enabled;
|
||||
bool_t sdp_200_ack;
|
||||
bool_t only_one_codec; /*in SDP answers*/
|
||||
bool_t register_only_when_network_is_up;
|
||||
} sip_config_t;
|
||||
|
||||
typedef struct rtp_config
|
||||
{
|
||||
int audio_rtp_port;
|
||||
int video_rtp_port;
|
||||
int audio_jitt_comp; /*jitter compensation*/
|
||||
int video_jitt_comp; /*jitter compensation*/
|
||||
int nortp_timeout;
|
||||
}rtp_config_t;
|
||||
|
||||
|
||||
|
||||
typedef struct net_config
|
||||
{
|
||||
char *nat_address;
|
||||
char *stun_server;
|
||||
char *relay;
|
||||
int download_bw;
|
||||
int upload_bw;
|
||||
int firewall_policy;
|
||||
int mtu;
|
||||
bool_t nat_sdp_only;
|
||||
}net_config_t;
|
||||
|
||||
|
||||
typedef struct sound_config
|
||||
{
|
||||
struct _MSSndCard * ring_sndcard; /* the playback sndcard currently used */
|
||||
struct _MSSndCard * play_sndcard; /* the playback sndcard currently used */
|
||||
struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */
|
||||
const char **cards;
|
||||
int latency; /* latency in samples of the current used sound device */
|
||||
char rec_lev;
|
||||
char play_lev;
|
||||
char ring_lev;
|
||||
char source;
|
||||
char *local_ring;
|
||||
char *remote_ring;
|
||||
bool_t ec;
|
||||
bool_t ea;
|
||||
bool_t agc;
|
||||
} sound_config_t;
|
||||
|
||||
typedef struct codecs_config
|
||||
{
|
||||
MSList *audio_codecs; /* list of audio codecs in order of preference*/
|
||||
MSList *video_codecs; /* for later use*/
|
||||
}codecs_config_t;
|
||||
|
||||
typedef struct video_config{
|
||||
struct _MSWebCam *device;
|
||||
const char **cams;
|
||||
MSVideoSize vsize;
|
||||
bool_t capture;
|
||||
bool_t show_local;
|
||||
bool_t display;
|
||||
bool_t selfview; /*during calls*/
|
||||
}video_config_t;
|
||||
|
||||
typedef struct ui_config
|
||||
{
|
||||
int is_daemon;
|
||||
int is_applet;
|
||||
unsigned int timer_id; /* the timer id for registration */
|
||||
}ui_config_t;
|
||||
|
||||
|
||||
|
||||
typedef struct autoreplier_config
|
||||
{
|
||||
int enabled;
|
||||
int after_seconds; /* accept the call after x seconds*/
|
||||
int max_users; /* maximum number of user that can call simultaneously */
|
||||
int max_rec_time; /* the max time of incoming voice recorded */
|
||||
int max_rec_msg; /* maximum number of recorded messages */
|
||||
const char *message; /* the path of the file to be played */
|
||||
}autoreplier_config_t;
|
||||
|
||||
struct osip_from;
|
||||
|
||||
/**
|
||||
* Object that represents a SIP address.
|
||||
|
|
@ -157,7 +58,7 @@ struct osip_from;
|
|||
* @ingroup linphone_address
|
||||
* @var LinphoneAddress
|
||||
*/
|
||||
typedef struct osip_from LinphoneAddress;
|
||||
typedef struct SalAddress LinphoneAddress;
|
||||
|
||||
LinphoneAddress * linphone_address_new(const char *uri);
|
||||
LinphoneAddress * linphone_address_clone(const LinphoneAddress *uri);
|
||||
|
|
@ -176,8 +77,6 @@ char *linphone_address_as_string(const LinphoneAddress *u);
|
|||
char *linphone_address_as_string_uri_only(const LinphoneAddress *u);
|
||||
void linphone_address_destroy(LinphoneAddress *u);
|
||||
|
||||
struct _LinphoneCore;
|
||||
struct _sdp_context;
|
||||
struct _SipSetupContext;
|
||||
struct _LinphoneCall;
|
||||
|
||||
|
|
@ -240,7 +139,7 @@ typedef enum{
|
|||
}LinphoneSubscribePolicy;
|
||||
|
||||
typedef enum _LinphoneOnlineStatus{
|
||||
LINPHONE_STATUS_UNKNOWN,
|
||||
LINPHONE_STATUS_OFFLINE,
|
||||
LINPHONE_STATUS_ONLINE,
|
||||
LINPHONE_STATUS_BUSY,
|
||||
LINPHONE_STATUS_BERIGHTBACK,
|
||||
|
|
@ -250,29 +149,15 @@ 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;
|
||||
|
||||
const char *linphone_online_status_to_string(LinphoneOnlineStatus ss);
|
||||
|
||||
typedef struct _LinphoneFriend{
|
||||
LinphoneAddress *uri;
|
||||
int in_did;
|
||||
int out_did;
|
||||
int sid;
|
||||
int nid;
|
||||
LinphoneSubscribePolicy pol;
|
||||
LinphoneOnlineStatus status;
|
||||
struct _LinphoneProxyConfig *proxy;
|
||||
struct _LinphoneCore *lc;
|
||||
BuddyInfo *info;
|
||||
char *refkey;
|
||||
bool_t subscribe;
|
||||
bool_t inc_subscribe_pending;
|
||||
}LinphoneFriend;
|
||||
struct _LinphoneFriend;
|
||||
|
||||
typedef struct _LinphoneFriend LinphoneFriend;
|
||||
|
||||
LinphoneFriend * linphone_friend_new();
|
||||
LinphoneFriend *linphone_friend_new_with_addr(const char *addr);
|
||||
|
|
@ -280,21 +165,21 @@ 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);
|
||||
BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf);
|
||||
void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key);
|
||||
const char *linphone_friend_get_ref_key(const LinphoneFriend *lf);
|
||||
#define linphone_friend_in_list(lf) ((lf)->lc!=NULL)
|
||||
bool_t linphone_friend_in_list(const LinphoneFriend *lf);
|
||||
|
||||
#define linphone_friend_url(lf) ((lf)->url)
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup proxies
|
||||
* @{
|
||||
|
|
@ -315,33 +200,12 @@ const char *linphone_friend_get_ref_key(const LinphoneFriend *lf);
|
|||
* The default proxy (see linphone_core_set_default_proxy() ) is the one of the list
|
||||
* that is used by default for calls.
|
||||
**/
|
||||
typedef struct _LinphoneProxyConfig
|
||||
{
|
||||
struct _LinphoneCore *lc;
|
||||
char *reg_proxy;
|
||||
char *reg_identity;
|
||||
char *reg_route;
|
||||
char *realm;
|
||||
int expires;
|
||||
int reg_time;
|
||||
int rid;
|
||||
char *type;
|
||||
struct _SipSetupContext *ssctx;
|
||||
int auth_failures;
|
||||
char *contact_addr; /* our IP address as seen by the proxy, read from via 's received= parameter*/
|
||||
int contact_port; /*our IP port as seen by the proxy, read from via's rport= parameter */
|
||||
char *dial_prefix;
|
||||
bool_t commit;
|
||||
bool_t reg_sendregister;
|
||||
bool_t registered;
|
||||
bool_t publish;
|
||||
bool_t dial_escape_plus;
|
||||
} LinphoneProxyConfig;
|
||||
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
|
||||
|
|
@ -353,18 +217,15 @@ void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char
|
|||
|
||||
bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj);
|
||||
const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg);
|
||||
/** Returns the proxy configured identity as a const char * */
|
||||
#define linphone_proxy_config_get_route(obj) ((obj)->reg_route)
|
||||
/** Returns the proxy configured identity as a const char * */
|
||||
#define linphone_proxy_config_get_identity(obj) ((obj)->reg_identity)
|
||||
#define linphone_proxy_config_publish_enabled(obj) ((obj)->publish)
|
||||
/** Returns the proxy sip address as const char * */
|
||||
#define linphone_proxy_config_get_addr(obj) ((obj)->reg_proxy)
|
||||
/** Returns the 'expire' time of the registration */
|
||||
#define linphone_proxy_config_get_expires(obj) ((obj)->expires)
|
||||
/** Returns TRUE if registration is enabled, FALSE otherwise */
|
||||
#define linphone_proxy_config_register_enabled(obj) ((obj)->reg_sendregister)
|
||||
#define linphone_proxy_config_get_core(obj) ((obj)->lc)
|
||||
|
||||
const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj);
|
||||
const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj);
|
||||
bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj);
|
||||
const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj);
|
||||
int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj);
|
||||
bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj);
|
||||
struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj);
|
||||
|
||||
bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg);
|
||||
const char * linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg);
|
||||
|
||||
|
|
@ -377,6 +238,14 @@ SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg);
|
|||
* normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
|
||||
*/
|
||||
int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len);
|
||||
/*
|
||||
* attached a user data to a proxy config
|
||||
*/
|
||||
void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud);
|
||||
/*
|
||||
* get user data to a proxy config. return null if any
|
||||
*/
|
||||
void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
@ -401,6 +270,8 @@ int linphone_account_creator_test_existence(LinphoneAccountCreator *obj);
|
|||
LinphoneProxyConfig * linphone_account_creator_validate(LinphoneAccountCreator *obj);
|
||||
void linphone_account_creator_destroy(LinphoneAccountCreator *obj);
|
||||
|
||||
struct _LinphoneAuthInfo;
|
||||
|
||||
/**
|
||||
* @ingroup authentication
|
||||
* Object holding authentication information.
|
||||
|
|
@ -425,33 +296,23 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj);
|
|||
* transactions and retry them with authentication headers.
|
||||
*
|
||||
**/
|
||||
typedef struct _LinphoneAuthInfo
|
||||
{
|
||||
char *username;
|
||||
char *realm;
|
||||
char *userid;
|
||||
char *passwd;
|
||||
char *ha1;
|
||||
bool_t works;
|
||||
bool_t first_time;
|
||||
}LinphoneAuthInfo;
|
||||
typedef struct _LinphoneAuthInfo LinphoneAuthInfo;
|
||||
|
||||
LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid,
|
||||
const char *passwd, const char *ha1,const char *realm);
|
||||
void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd);
|
||||
void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username);
|
||||
void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid);
|
||||
|
||||
const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i);
|
||||
const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i);
|
||||
const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i);
|
||||
|
||||
/* you don't need those function*/
|
||||
void linphone_auth_info_destroy(LinphoneAuthInfo *info);
|
||||
LinphoneAuthInfo * linphone_auth_info_new_from_config_file(struct _LpConfig *config, int pos);
|
||||
|
||||
struct _LinphoneChatRoom{
|
||||
struct _LinphoneCore *lc;
|
||||
char *peer;
|
||||
char *route;
|
||||
LinphoneAddress *peer_url;
|
||||
void * user_data;
|
||||
};
|
||||
struct _LinphoneChatRoom;
|
||||
typedef struct _LinphoneChatRoom LinphoneChatRoom;
|
||||
|
||||
LinphoneChatRoom * linphone_core_create_chat_room(struct _LinphoneCore *lc, const char *to);
|
||||
|
|
@ -523,7 +384,7 @@ typedef void (*DisplayQuestionCb)(struct _LinphoneCore *lc, const char *message)
|
|||
/** Callback prototype */
|
||||
typedef void (*LinphoneCoreCbFunc)(struct _LinphoneCore *lc,void * user_data);
|
||||
/** Callback prototype */
|
||||
typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
|
||||
typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid);
|
||||
/** Callback prototype */
|
||||
typedef void (*NewUnknownSubscriberCb)(struct _LinphoneCore *lc, LinphoneFriend *lf, const char *url);
|
||||
/** Callback prototype */
|
||||
|
|
@ -555,10 +416,6 @@ typedef struct _LinphoneVTable
|
|||
AuthInfoRequested auth_info_requested; /**< Ask the application some authentication information */
|
||||
DisplayStatusCb display_status; /**< Callback that notifies various events with human readable text.*/
|
||||
DisplayMessageCb display_message;/**< Callback to display a message to the user */
|
||||
#ifdef VINCENT_MAURY_RSVP
|
||||
/* the yes/no dialog box */
|
||||
DisplayMessageCb display_yes_no;
|
||||
#endif
|
||||
DisplayMessageCb display_warning;/** Callback to display a warning to the user */
|
||||
DisplayUrlCb display_url;
|
||||
DisplayQuestionCb display_question;
|
||||
|
|
@ -595,77 +452,13 @@ typedef enum _LinphoneWaitingState{
|
|||
} LinphoneWaitingState;
|
||||
typedef void * (*LinphoneWaitingCallback)(struct _LinphoneCore *lc, void *context, LinphoneWaitingState ws, const char *purpose, float progress);
|
||||
|
||||
|
||||
typedef struct _LinphoneCore
|
||||
{
|
||||
LinphoneCoreVTable vtable;
|
||||
struct _LpConfig *config;
|
||||
net_config_t net_conf;
|
||||
sip_config_t sip_conf;
|
||||
rtp_config_t rtp_conf;
|
||||
sound_config_t sound_conf;
|
||||
video_config_t video_conf;
|
||||
codecs_config_t codecs_conf;
|
||||
ui_config_t ui_conf;
|
||||
autoreplier_config_t autoreplier_conf;
|
||||
LinphoneProxyConfig *default_proxy;
|
||||
MSList *friends;
|
||||
MSList *auth_info;
|
||||
struct _RingStream *ringstream;
|
||||
LCCallbackObj preview_finished_cb;
|
||||
bool_t preview_finished;
|
||||
struct _LinphoneCall *call; /* the current call, in the future it will be a list of calls (conferencing)*/
|
||||
int rid; /*registration id*/
|
||||
MSList *queued_calls; /* used by the autoreplier */
|
||||
MSList *call_logs;
|
||||
MSList *chatrooms;
|
||||
int max_call_logs;
|
||||
int missed_calls;
|
||||
struct _AudioStream *audiostream; /**/
|
||||
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;
|
||||
LinphoneOnlineStatus presence_mode;
|
||||
LinphoneOnlineStatus prev_mode;
|
||||
char *alt_contact;
|
||||
void *data;
|
||||
ms_mutex_t lock;
|
||||
char *play_file;
|
||||
char *rec_file;
|
||||
time_t prevtime;
|
||||
int dw_audio_bw;
|
||||
int up_audio_bw;
|
||||
int dw_video_bw;
|
||||
int up_video_bw;
|
||||
int audio_bw;
|
||||
int automatic_action;
|
||||
gstate_t gstate_power;
|
||||
gstate_t gstate_reg;
|
||||
gstate_t gstate_call;
|
||||
LinphoneWaitingCallback wait_cb;
|
||||
void *wait_ctx;
|
||||
bool_t use_files;
|
||||
bool_t apply_nat_settings;
|
||||
bool_t ready;
|
||||
bool_t bl_refresh;
|
||||
#ifdef VINCENT_MAURY_RSVP
|
||||
/* QoS parameters*/
|
||||
int rsvp_enable;
|
||||
int rpc_enable;
|
||||
#endif
|
||||
typedef struct _LinphoneCore LinphoneCore;
|
||||
/*set this field to false if application manage network connection state
|
||||
* In case of false, network state must be communicate to linphone core with method linphone_core_
|
||||
*/
|
||||
bool_t auto_net_state_mon;
|
||||
bool_t network_reachable;
|
||||
int down_ptime;
|
||||
} LinphoneCore;
|
||||
|
||||
|
||||
|
||||
/* THE main API */
|
||||
|
||||
|
|
@ -682,8 +475,12 @@ LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
|
|||
/* function to be periodically called in a main loop */
|
||||
void linphone_core_iterate(LinphoneCore *lc);
|
||||
|
||||
LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url);
|
||||
|
||||
int linphone_core_invite(LinphoneCore *lc, const char *url);
|
||||
|
||||
int linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr);
|
||||
|
||||
int linphone_core_refer(LinphoneCore *lc, const char *url);
|
||||
|
||||
bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
|
||||
|
|
@ -742,6 +539,12 @@ const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc);
|
|||
|
||||
int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs);
|
||||
|
||||
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt);
|
||||
|
||||
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable);
|
||||
|
||||
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt);
|
||||
|
||||
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt);
|
||||
|
||||
int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config);
|
||||
|
|
@ -828,6 +631,18 @@ int linphone_core_get_play_level(LinphoneCore *lc);
|
|||
int linphone_core_get_rec_level(LinphoneCore *lc);
|
||||
void linphone_core_set_ring_level(LinphoneCore *lc, int level);
|
||||
void linphone_core_set_play_level(LinphoneCore *lc, int level);
|
||||
/**
|
||||
* Allow to control play level before entering sound card: level in db
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
void linphone_core_set_soft_play_level(LinphoneCore *lc, float level);
|
||||
/**
|
||||
* get play level before entering sound card: level in db
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
float linphone_core_get_soft_play_level(LinphoneCore *lc);
|
||||
void linphone_core_set_rec_level(LinphoneCore *lc, int level);
|
||||
const char * linphone_core_get_ringer_device(LinphoneCore *lc);
|
||||
const char * linphone_core_get_playback_device(LinphoneCore *lc);
|
||||
|
|
@ -852,6 +667,12 @@ void linphone_core_enable_agc(LinphoneCore *lc, bool_t val);
|
|||
bool_t linphone_core_agc_enabled(const LinphoneCore *lc);
|
||||
|
||||
void linphone_core_mute_mic(LinphoneCore *lc, bool_t muted);
|
||||
/**
|
||||
* return mic state.
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
bool_t linphone_core_is_mic_muted(LinphoneCore *lc);
|
||||
|
||||
void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,const char *contact,LinphoneOnlineStatus os);
|
||||
|
||||
|
|
@ -865,7 +686,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 */
|
||||
|
|
@ -927,8 +748,6 @@ void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
|
|||
void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t value);
|
||||
|
||||
|
||||
bool_t linphone_core_is_in_main_thread(LinphoneCore *lc);
|
||||
|
||||
void *linphone_core_get_user_data(LinphoneCore *lc);
|
||||
|
||||
/* returns LpConfig object to read/write to the config file: usefull if you wish to extend
|
||||
|
|
@ -954,21 +773,6 @@ void linphone_core_destroy(LinphoneCore *lc);
|
|||
/*for advanced users:*/
|
||||
void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp);
|
||||
|
||||
/* end of lecacy api */
|
||||
|
||||
/*internal use only */
|
||||
#define linphone_core_lock(lc) ms_mutex_lock(&(lc)->lock)
|
||||
#define linphone_core_unlock(lc) ms_mutex_unlock((&lc)->lock)
|
||||
void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
|
||||
void linphone_core_stop_media_streams(LinphoneCore *lc);
|
||||
const char * linphone_core_get_identity(LinphoneCore *lc);
|
||||
const char * linphone_core_get_route(LinphoneCore *lc);
|
||||
bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAddress **real_parsed_url, char **route);
|
||||
void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);
|
||||
void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses);
|
||||
void linphone_core_stop_waiting(LinphoneCore *lc);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ static void linphone_android_log_handler(OrtpLogLevel lev, const char *fmt, va_l
|
|||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
linphone_core_enable_logs_with_cb(linphone_android_log_handler);
|
||||
#ifdef ANDROID
|
||||
ms_andsnd_register_card(ajvm);
|
||||
#endif /*ANDROID*/
|
||||
jvm=ajvm;
|
||||
|
|
@ -51,7 +50,16 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved)
|
|||
}
|
||||
|
||||
|
||||
|
||||
//LinphoneFactory
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreFactory_setDebugMode(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jboolean isDebug) {
|
||||
if (isDebug) {
|
||||
linphone_core_enable_logs_with_cb(linphone_android_log_handler);
|
||||
} else {
|
||||
linphone_core_disable_logs();
|
||||
}
|
||||
}
|
||||
// LinphoneCore
|
||||
|
||||
class LinphoneCoreData {
|
||||
|
|
@ -150,6 +158,9 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv*
|
|||
const char* userConfig = env->GetStringUTFChars(juserConfig, NULL);
|
||||
const char* factoryConfig = env->GetStringUTFChars(jfactoryConfig, NULL);
|
||||
LinphoneCoreData* ldata = new LinphoneCoreData(env,thiz,jlistener,juserdata);
|
||||
#ifdef ANDROID
|
||||
ms_andsnd_register_card(jvm);
|
||||
#endif /*ANDROID*/
|
||||
jlong nativePtr = (jlong)linphone_core_new( &ldata->vTable
|
||||
,userConfig
|
||||
,factoryConfig
|
||||
|
|
@ -191,8 +202,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig(
|
|||
|
||||
extern "C" int Java_org_linphone_core_LinphoneCoreImpl_addProxyConfig( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jobject jproxyCfg
|
||||
,jlong lc
|
||||
,jlong pc) {
|
||||
LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)pc;
|
||||
linphone_proxy_config_set_user_data(proxy, env->NewGlobalRef(jproxyCfg));
|
||||
|
||||
return linphone_core_add_proxy_config((LinphoneCore*)lc,(LinphoneProxyConfig*)pc);
|
||||
}
|
||||
|
||||
|
|
@ -219,6 +234,12 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_invite( JNIEnv* env
|
|||
linphone_core_invite((LinphoneCore*)lc,uri);
|
||||
env->ReleaseStringUTFChars(juri, uri);
|
||||
}
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_inviteAddress( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jlong to) {
|
||||
linphone_core_invite_address((LinphoneCore*)lc,(LinphoneAddress*)to);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_terminateCall( JNIEnv* env
|
||||
,jobject thiz
|
||||
|
|
@ -268,11 +289,59 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setNetworkStateReachable
|
|||
linphone_core_set_network_reachable((LinphoneCore*)lc,isReachable);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setSoftPlayLevel( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jfloat gain) {
|
||||
linphone_core_set_soft_play_level((LinphoneCore*)lc,gain);
|
||||
}
|
||||
|
||||
extern "C" float Java_org_linphone_core_LinphoneCoreImpl_getSoftPlayLevel( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc) {
|
||||
return linphone_core_get_soft_play_level((LinphoneCore*)lc);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_muteMic( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jboolean isMuted) {
|
||||
linphone_core_mute_mic((LinphoneCore*)lc,isMuted);
|
||||
}
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_interpretUrl( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jstring jurl) {
|
||||
const char* url = env->GetStringUTFChars(jurl, NULL);
|
||||
jlong result = (jlong)linphone_core_interpret_url((LinphoneCore*)lc,url);
|
||||
env->ReleaseStringUTFChars(jurl, url);
|
||||
return result;
|
||||
}
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_sendDtmf( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jchar dtmf) {
|
||||
linphone_core_send_dtmf((LinphoneCore*)lc,dtmf);
|
||||
}
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_clearCallLogs(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc) {
|
||||
linphone_core_clear_call_logs((LinphoneCore*)lc);
|
||||
}
|
||||
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isMicMuted( JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc) {
|
||||
return linphone_core_is_mic_muted((LinphoneCore*)lc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//ProxyConfig
|
||||
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_newLinphoneProxyConfig(JNIEnv* env,jobject thiz) {
|
||||
return (jlong) linphone_proxy_config_new();
|
||||
LinphoneProxyConfig* proxy = linphone_proxy_config_new();
|
||||
return (jlong) proxy;
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_delete(JNIEnv* env,jobject thiz,jlong ptr) {
|
||||
|
|
@ -417,7 +486,7 @@ extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getDomain(JNIEnv*
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toUri(JNIEnv* env
|
||||
extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toString(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
char* uri = linphone_address_as_string((LinphoneAddress*)ptr);
|
||||
|
|
@ -425,6 +494,23 @@ extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toUri(JNIEnv* env
|
|||
ms_free(uri);
|
||||
return juri;
|
||||
}
|
||||
extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toUri(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong ptr) {
|
||||
char* uri = linphone_address_as_string_uri_only((LinphoneAddress*)ptr);
|
||||
jstring juri =env->NewStringUTF(uri);
|
||||
ms_free(uri);
|
||||
return juri;
|
||||
}
|
||||
extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setDisplayName(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong address
|
||||
,jstring jdisplayName) {
|
||||
const char* displayName = env->GetStringUTFChars(jdisplayName, NULL);
|
||||
linphone_address_set_display_name((LinphoneAddress*)address,displayName);
|
||||
env->ReleaseStringUTFChars(jdisplayName, displayName);
|
||||
}
|
||||
|
||||
|
||||
//CallLog
|
||||
extern "C" jlong Java_org_linphone_core_LinphoneCallLogImpl_getFrom(JNIEnv* env
|
||||
|
|
|
|||
214
coreapi/misc.c
214
coreapi/misc.c
|
|
@ -170,21 +170,42 @@ void check_sound_device(LinphoneCore *lc)
|
|||
#define RTP_HDR_SZ 12
|
||||
#define IP4_HDR_SZ 20 /*20 is the minimum, but there may be some options*/
|
||||
|
||||
const char *payload_type_get_description(PayloadType *pt){
|
||||
return _((const char *)pt->user_data);
|
||||
}
|
||||
|
||||
void payload_type_set_enable(PayloadType *pt,int value)
|
||||
static void payload_type_set_enable(PayloadType *pt,int value)
|
||||
{
|
||||
if ((value)!=0) payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED); \
|
||||
else payload_type_unset_flag(pt,PAYLOAD_TYPE_ENABLED);
|
||||
}
|
||||
|
||||
|
||||
bool_t payload_type_enabled(PayloadType *pt) {
|
||||
static bool_t payload_type_enabled(PayloadType *pt) {
|
||||
return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0);
|
||||
}
|
||||
|
||||
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
|
||||
return payload_type_enabled(pt);
|
||||
}
|
||||
ms_error("Getting enablement status of codec not in audio or video list of PayloadType !");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
|
||||
payload_type_set_enable(pt,enabled);
|
||||
return 0;
|
||||
}
|
||||
ms_error("Enabling codec not in audio or video list of PayloadType !");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){
|
||||
if (ms_filter_codec_supported(pt->mime_type)){
|
||||
MSFilterDesc *desc=ms_filter_get_encoder(pt->mime_type);
|
||||
return _(desc->text);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*this function makes a special case for speex/8000.
|
||||
This codec is variable bitrate. The 8kbit/s mode is interesting when having a low upload bandwidth, but its quality
|
||||
is not very good. We 'd better use its 15kbt/s mode when we have enough bandwidth*/
|
||||
|
|
@ -255,6 +276,12 @@ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType
|
|||
case PAYLOAD_AUDIO_PACKETIZED:
|
||||
codec_band=get_audio_payload_bandwidth(lc,pt);
|
||||
ret=bandwidth_is_greater(min_audio_bw*1000,codec_band);
|
||||
/*hack to avoid using uwb codecs when having low bitrate and video*/
|
||||
if (bandwidth_is_greater(199,min_audio_bw)){
|
||||
if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){
|
||||
ret=FALSE;
|
||||
}
|
||||
}
|
||||
//ms_message("Payload %s: %g",pt->mime_type,codec_band);
|
||||
break;
|
||||
case PAYLOAD_VIDEO:
|
||||
|
|
@ -274,152 +301,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");
|
||||
|
|
@ -598,6 +479,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;
|
||||
|
|
@ -630,20 +516,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;
|
||||
|
|
@ -657,7 +543,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){
|
||||
|
|
@ -666,7 +553,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
164
coreapi/offeranswer.c
Normal file
164
coreapi/offeranswer.c
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
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.h"
|
||||
#include "offeranswer.h"
|
||||
|
||||
|
||||
static PayloadType * find_payload_type_best_match(const MSList *l, const PayloadType *refpt){
|
||||
PayloadType *pt;
|
||||
char value[10];
|
||||
const MSList *elem;
|
||||
PayloadType *candidate=NULL;
|
||||
|
||||
for (elem=l;elem!=NULL;elem=elem->next){
|
||||
pt=(PayloadType*)elem->data;
|
||||
if (strcasecmp(pt->mime_type,refpt->mime_type)==0 && pt->clock_rate==refpt->clock_rate){
|
||||
candidate=pt;
|
||||
/*good candidate, check fmtp for H264 */
|
||||
if (strcasecmp(pt->mime_type,"H264")==0){
|
||||
if (pt->recv_fmtp!=NULL && refpt->recv_fmtp!=NULL){
|
||||
int mode1=0,mode2=0;
|
||||
if (fmtp_get_value(pt->recv_fmtp,"packetization-mode",value,sizeof(value))){
|
||||
mode1=atoi(value);
|
||||
}
|
||||
if (fmtp_get_value(refpt->recv_fmtp,"packetization-mode",value,sizeof(value))){
|
||||
mode2=atoi(value);
|
||||
}
|
||||
if (mode1==mode2)
|
||||
break; /*exact match */
|
||||
}
|
||||
}else break;
|
||||
}
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
static MSList *match_payloads(const MSList *local, const MSList *remote){
|
||||
const MSList *e2;
|
||||
MSList *res=NULL;
|
||||
PayloadType *matched;
|
||||
for(e2=remote;e2!=NULL;e2=e2->next){
|
||||
PayloadType *p2=(PayloadType*)e2->data;
|
||||
matched=find_payload_type_best_match(local,p2);
|
||||
if (matched){
|
||||
matched=payload_type_clone(matched);
|
||||
if (p2->recv_fmtp)
|
||||
payload_type_set_send_fmtp(matched,p2->recv_fmtp);
|
||||
res=ms_list_append(res,matched);
|
||||
payload_type_set_number(matched,payload_type_get_number(p2));
|
||||
}else{
|
||||
ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool_t only_telephone_event(const MSList *l){
|
||||
PayloadType *p=(PayloadType*)l->data;
|
||||
if (strcasecmp(p->mime_type,"telephone-event")!=0){
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void initiate_outgoing(const SalStreamDescription *local_offer,
|
||||
const SalStreamDescription *remote_answer,
|
||||
SalStreamDescription *result){
|
||||
if (remote_answer->port!=0)
|
||||
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads);
|
||||
result->proto=local_offer->proto;
|
||||
result->type=local_offer->type;
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
strcpy(result->addr,remote_answer->addr);
|
||||
result->port=remote_answer->port;
|
||||
result->bandwidth=remote_answer->bandwidth;
|
||||
result->ptime=remote_answer->ptime;
|
||||
}else{
|
||||
result->port=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void initiate_incoming(const SalStreamDescription *local_cap,
|
||||
const SalStreamDescription *remote_offer,
|
||||
SalStreamDescription *result){
|
||||
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads);
|
||||
result->proto=local_cap->proto;
|
||||
result->type=local_cap->type;
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
strcpy(result->addr,local_cap->addr);
|
||||
result->port=local_cap->port;
|
||||
result->bandwidth=local_cap->bandwidth;
|
||||
result->ptime=local_cap->ptime;
|
||||
}else{
|
||||
result->port=0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a media description to run the streams with, based on a local offer
|
||||
* and the returned response (remote).
|
||||
**/
|
||||
int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
|
||||
const SalMediaDescription *remote_answer,
|
||||
SalMediaDescription *result){
|
||||
int i,j;
|
||||
const SalStreamDescription *ls,*rs;
|
||||
for(i=0,j=0;i<local_offer->nstreams;++i){
|
||||
ms_message("Processing for stream %i",i);
|
||||
ls=&local_offer->streams[i];
|
||||
rs=sal_media_description_find_stream(remote_answer,ls->proto,ls->type);
|
||||
if (rs) {
|
||||
initiate_outgoing(ls,rs,&result->streams[j]);
|
||||
++j;
|
||||
}
|
||||
else ms_warning("No matching stream for %i",i);
|
||||
}
|
||||
result->nstreams=j;
|
||||
strcpy(result->addr,remote_answer->addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a media description to run the streams with, based on the local capabilities and
|
||||
* and the received offer.
|
||||
* The returned media description is an answer and should be sent to the offerer.
|
||||
**/
|
||||
int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
|
||||
const SalMediaDescription *remote_offer,
|
||||
SalMediaDescription *result){
|
||||
int i,j;
|
||||
const SalStreamDescription *ls,*rs;
|
||||
|
||||
for(i=0,j=0;i<remote_offer->nstreams;++i){
|
||||
rs=&remote_offer->streams[i];
|
||||
ms_message("Processing for stream %i",i);
|
||||
ls=sal_media_description_find_stream(local_capabilities,rs->proto,rs->type);
|
||||
if (ls){
|
||||
initiate_incoming(ls,rs,&result->streams[j]);
|
||||
++j;
|
||||
}
|
||||
}
|
||||
result->nstreams=j;
|
||||
strcpy(result->username, local_capabilities->username);
|
||||
strcpy(result->addr,local_capabilities->addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
47
coreapi/offeranswer.h
Normal file
47
coreapi/offeranswer.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
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 offeranswer_h
|
||||
#define offeranswer_h
|
||||
|
||||
/**
|
||||
This header files defines the SDP offer answer API.
|
||||
It can be used by implementations of SAL directly.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* Returns a media description to run the streams with, based on a local offer
|
||||
* and the returned response (remote).
|
||||
**/
|
||||
int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
|
||||
const SalMediaDescription *remote_answer,
|
||||
SalMediaDescription *result);
|
||||
|
||||
/**
|
||||
* Returns a media description to run the streams with, based on the local capabilities and
|
||||
* and the received offer.
|
||||
* The returned media description is an answer and should be sent to the offerer.
|
||||
**/
|
||||
int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
|
||||
const SalMediaDescription *remote_offer,
|
||||
SalMediaDescription *result);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -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,115 @@ 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);
|
||||
linphone_address_destroy(uri);
|
||||
ms_free(tmp);
|
||||
}
|
||||
|
||||
void linphone_notify_recv(LinphoneCore *lc, eXosip_event_t *ev)
|
||||
{
|
||||
const char *status=_("Gone");
|
||||
const char *img="sip-closed.png";
|
||||
void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, SalPresenceStatus sal_status){
|
||||
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{
|
||||
status=_("Gone");
|
||||
img="sip-closed.png";
|
||||
LinphoneOnlineStatus estatus=LINPHONE_STATUS_OFFLINE;
|
||||
|
||||
switch(sal_status){
|
||||
case SalPresenceOffline:
|
||||
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:
|
||||
estatus=LINPHONE_STATUS_ONLINE;
|
||||
break;
|
||||
case SalPresenceBusy:
|
||||
estatus=LINPHONE_STATUS_BUSY;
|
||||
break;
|
||||
case SalPresenceBerightback:
|
||||
estatus=LINPHONE_STATUS_AWAY;
|
||||
break;
|
||||
case SalPresenceAway:
|
||||
estatus=LINPHONE_STATUS_AWAY;
|
||||
break;
|
||||
case SalPresenceOnthephone:
|
||||
estatus=LINPHONE_STATUS_ONTHEPHONE;
|
||||
break;
|
||||
case SalPresenceOuttolunch:
|
||||
estatus=LINPHONE_STATUS_OUTTOLUNCH;
|
||||
break;
|
||||
case SalPresenceDonotdisturb:
|
||||
estatus=LINPHONE_STATUS_BUSY;
|
||||
break;
|
||||
case SalPresenceMoved:
|
||||
case SalPresenceAltService:
|
||||
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);
|
||||
lf->subscribe_active=TRUE;
|
||||
lc->vtable.notify_recv(lc,(LinphoneFriend*)lf);
|
||||
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;
|
||||
lf->subscribe_active=FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#define _PRIVATE_H
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include <eXosip2/eXosip.h>
|
||||
#include "sal.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
|
|
@ -54,23 +54,9 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _StreamParams
|
||||
{
|
||||
int initialized;
|
||||
int line;
|
||||
int localport;
|
||||
int remoteport;
|
||||
int remotertcpport;
|
||||
int pt;
|
||||
char *relay_session_id;
|
||||
int natd_port;
|
||||
char remoteaddr[LINPHONE_HOSTNAME_SIZE];
|
||||
char natd_addr[LINPHONE_HOSTNAME_SIZE];
|
||||
} StreamParams;
|
||||
|
||||
typedef enum _LCState{
|
||||
LCStateInit,
|
||||
LCStatePreEstablishing,
|
||||
LCStateRinging,
|
||||
LCStateAVRunning
|
||||
}LCState;
|
||||
|
|
@ -79,25 +65,23 @@ typedef enum _LCState{
|
|||
typedef struct _LinphoneCall
|
||||
{
|
||||
struct _LinphoneCore *core;
|
||||
StreamParams audio_params;
|
||||
StreamParams video_params;
|
||||
SalMediaDescription *localdesc;
|
||||
SalMediaDescription *resultdesc;
|
||||
LinphoneCallDir dir;
|
||||
struct _RtpProfile *profile; /*points to the local_profile or to the remote "guessed" profile*/
|
||||
struct _RtpProfile *audio_profile;
|
||||
struct _RtpProfile *video_profile;
|
||||
struct _LinphoneCallLog *log;
|
||||
int cid; /*call id */
|
||||
int did; /*dialog id */
|
||||
int tid; /*last transaction id*/
|
||||
SalOp *op;
|
||||
SalOp *ping_op;
|
||||
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
|
||||
struct _sdp_context *sdpctx;
|
||||
time_t start_time; /*time at which the call was initiated*/
|
||||
time_t media_start_time; /*time at which it was accepted, media streams established*/
|
||||
LCState state;
|
||||
bool_t auth_pending;
|
||||
bool_t supports_session_timers;
|
||||
bool_t media_pending;
|
||||
} LinphoneCall;
|
||||
|
||||
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to);
|
||||
LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, eXosip_event_t *ev);
|
||||
LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op);
|
||||
#define linphone_call_set_state(lcall,st) (lcall)->state=(st)
|
||||
void linphone_call_destroy(struct _LinphoneCall *obj);
|
||||
|
||||
|
|
@ -107,7 +91,7 @@ void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call);
|
|||
void linphone_call_log_destroy(LinphoneCallLog *cl);
|
||||
|
||||
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc);
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos);
|
||||
|
||||
|
|
@ -117,27 +101,26 @@ void linphone_core_refresh_subscribes(LinphoneCore *lc);
|
|||
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os);
|
||||
|
||||
int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
|
||||
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
|
||||
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);
|
||||
|
||||
void linphone_friend_set_sid(LinphoneFriend *lf, int sid);
|
||||
void linphone_friend_set_nid(LinphoneFriend *lf, int nid);
|
||||
void linphone_friend_notify(LinphoneFriend *lf, int ss, LinphoneOnlineStatus os);
|
||||
|
||||
int set_lock_file();
|
||||
int get_lock_file();
|
||||
int remove_lock_file();
|
||||
int do_registration(LinphoneCore *lc, bool_t doit);
|
||||
void check_for_registration(LinphoneCore *lc);
|
||||
char *int2str(int number);
|
||||
int from_2char_without_params(osip_from_t *from,char **str);
|
||||
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);
|
||||
|
||||
static inline int get_min_bandwidth(int dbw, int ubw){
|
||||
if (dbw<0) return ubw;
|
||||
if (ubw<0) return dbw;
|
||||
if (dbw<=0) return ubw;
|
||||
if (ubw<=0) return dbw;
|
||||
return MIN(dbw,ubw);
|
||||
}
|
||||
|
||||
|
|
@ -157,24 +140,18 @@ static inline void set_string(char **dest, const char *src){
|
|||
}
|
||||
|
||||
#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0
|
||||
bool_t linphone_proxy_config_register_again_with_updated_contact(LinphoneProxyConfig *obj, osip_message_t *orig_request, osip_message_t *last_answer);
|
||||
void linphone_process_authentication(LinphoneCore* lc, eXosip_event_t *ev);
|
||||
void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev);
|
||||
void linphone_subscription_new(LinphoneCore *lc, eXosip_event_t *ev);
|
||||
void linphone_notify_recv(LinphoneCore *lc,eXosip_event_t *ev);
|
||||
LinphoneProxyConfig *linphone_core_get_proxy_config_from_rid(LinphoneCore *lc, int rid);
|
||||
void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, int code, eXosip_event_t *ev);
|
||||
|
||||
void linphone_subscription_answered(LinphoneCore *lc, eXosip_event_t *ev);
|
||||
void linphone_subscription_closed(LinphoneCore *lc, eXosip_event_t *ev);
|
||||
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, 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_call_init_media_params(LinphoneCall *call);
|
||||
|
||||
void linphone_set_sdp(osip_message_t *sip, const char *sdp);
|
||||
void linphone_subscription_answered(LinphoneCore *lc, SalOp *op);
|
||||
void linphone_subscription_closed(LinphoneCore *lc, SalOp *op);
|
||||
|
||||
MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *fri, LinphoneFriend **lf);
|
||||
LinphoneFriend *linphone_find_friend_by_nid(MSList *l, int nid);
|
||||
LinphoneFriend *linphone_find_friend_by_sid(MSList *l, int sid);
|
||||
|
||||
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc);
|
||||
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
|
@ -194,4 +171,231 @@ 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);
|
||||
|
||||
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);
|
||||
const char * linphone_core_get_route(LinphoneCore *lc);
|
||||
void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose);
|
||||
void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses);
|
||||
void linphone_core_stop_waiting(LinphoneCore *lc);
|
||||
|
||||
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
|
||||
|
||||
extern SalCallbacks linphone_sal_callbacks;
|
||||
|
||||
|
||||
struct _LinphoneProxyConfig
|
||||
{
|
||||
struct _LinphoneCore *lc;
|
||||
char *reg_proxy;
|
||||
char *reg_identity;
|
||||
char *reg_route;
|
||||
char *realm;
|
||||
int expires;
|
||||
int reg_time;
|
||||
SalOp *op;
|
||||
char *type;
|
||||
struct _SipSetupContext *ssctx;
|
||||
int auth_failures;
|
||||
char *dial_prefix;
|
||||
bool_t commit;
|
||||
bool_t reg_sendregister;
|
||||
bool_t registered;
|
||||
bool_t publish;
|
||||
bool_t dial_escape_plus;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
struct _LinphoneAuthInfo
|
||||
{
|
||||
char *username;
|
||||
char *realm;
|
||||
char *userid;
|
||||
char *passwd;
|
||||
char *ha1;
|
||||
int usecount;
|
||||
bool_t works;
|
||||
};
|
||||
|
||||
struct _LinphoneChatRoom{
|
||||
struct _LinphoneCore *lc;
|
||||
char *peer;
|
||||
char *route;
|
||||
LinphoneAddress *peer_url;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
struct _LinphoneFriend{
|
||||
LinphoneAddress *uri;
|
||||
SalOp *insub;
|
||||
SalOp *outsub;
|
||||
LinphoneSubscribePolicy pol;
|
||||
LinphoneOnlineStatus status;
|
||||
struct _LinphoneCore *lc;
|
||||
BuddyInfo *info;
|
||||
char *refkey;
|
||||
bool_t subscribe;
|
||||
bool_t subscribe_active;
|
||||
bool_t inc_subscribe_pending;
|
||||
};
|
||||
|
||||
typedef struct sip_config
|
||||
{
|
||||
char *contact;
|
||||
char *guessed_contact;
|
||||
int sip_port;
|
||||
MSList *proxies;
|
||||
MSList *deleted_proxies;
|
||||
int inc_timeout; /*timeout after an un-answered incoming call is rejected*/
|
||||
bool_t use_info;
|
||||
bool_t use_rfc2833; /*force RFC2833 to be sent*/
|
||||
bool_t guess_hostname;
|
||||
bool_t loopback_only;
|
||||
bool_t ipv6_enabled;
|
||||
bool_t sdp_200_ack;
|
||||
bool_t only_one_codec; /*in SDP answers*/
|
||||
bool_t register_only_when_network_is_up;
|
||||
bool_t ping_with_options;
|
||||
bool_t auto_net_state_mon;
|
||||
} sip_config_t;
|
||||
|
||||
typedef struct rtp_config
|
||||
{
|
||||
int audio_rtp_port;
|
||||
int video_rtp_port;
|
||||
int audio_jitt_comp; /*jitter compensation*/
|
||||
int video_jitt_comp; /*jitter compensation*/
|
||||
int nortp_timeout;
|
||||
}rtp_config_t;
|
||||
|
||||
|
||||
|
||||
typedef struct net_config
|
||||
{
|
||||
char *nat_address;
|
||||
char *stun_server;
|
||||
char *relay;
|
||||
int download_bw;
|
||||
int upload_bw;
|
||||
int firewall_policy;
|
||||
int mtu;
|
||||
int down_ptime;
|
||||
bool_t nat_sdp_only;
|
||||
}net_config_t;
|
||||
|
||||
|
||||
typedef struct sound_config
|
||||
{
|
||||
struct _MSSndCard * ring_sndcard; /* the playback sndcard currently used */
|
||||
struct _MSSndCard * play_sndcard; /* the playback sndcard currently used */
|
||||
struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */
|
||||
const char **cards;
|
||||
int latency; /* latency in samples of the current used sound device */
|
||||
char rec_lev;
|
||||
char play_lev;
|
||||
char ring_lev;
|
||||
char soft_play_lev;
|
||||
char source;
|
||||
char *local_ring;
|
||||
char *remote_ring;
|
||||
bool_t ec;
|
||||
bool_t ea;
|
||||
bool_t agc;
|
||||
} sound_config_t;
|
||||
|
||||
typedef struct codecs_config
|
||||
{
|
||||
MSList *audio_codecs; /* list of audio codecs in order of preference*/
|
||||
MSList *video_codecs; /* for later use*/
|
||||
}codecs_config_t;
|
||||
|
||||
typedef struct video_config{
|
||||
struct _MSWebCam *device;
|
||||
const char **cams;
|
||||
MSVideoSize vsize;
|
||||
bool_t capture;
|
||||
bool_t show_local;
|
||||
bool_t display;
|
||||
bool_t selfview; /*during calls*/
|
||||
}video_config_t;
|
||||
|
||||
typedef struct ui_config
|
||||
{
|
||||
int is_daemon;
|
||||
int is_applet;
|
||||
unsigned int timer_id; /* the timer id for registration */
|
||||
}ui_config_t;
|
||||
|
||||
|
||||
|
||||
typedef struct autoreplier_config
|
||||
{
|
||||
int enabled;
|
||||
int after_seconds; /* accept the call after x seconds*/
|
||||
int max_users; /* maximum number of user that can call simultaneously */
|
||||
int max_rec_time; /* the max time of incoming voice recorded */
|
||||
int max_rec_msg; /* maximum number of recorded messages */
|
||||
const char *message; /* the path of the file to be played */
|
||||
}autoreplier_config_t;
|
||||
|
||||
|
||||
struct _LinphoneCore
|
||||
{
|
||||
LinphoneCoreVTable vtable;
|
||||
Sal *sal;
|
||||
struct _LpConfig *config;
|
||||
net_config_t net_conf;
|
||||
sip_config_t sip_conf;
|
||||
rtp_config_t rtp_conf;
|
||||
sound_config_t sound_conf;
|
||||
video_config_t video_conf;
|
||||
codecs_config_t codecs_conf;
|
||||
ui_config_t ui_conf;
|
||||
autoreplier_config_t autoreplier_conf;
|
||||
LinphoneProxyConfig *default_proxy;
|
||||
MSList *friends;
|
||||
MSList *auth_info;
|
||||
struct _RingStream *ringstream;
|
||||
LCCallbackObj preview_finished_cb;
|
||||
struct _LinphoneCall *call; /* the current call, in the future it will be a list of calls (conferencing)*/
|
||||
MSList *queued_calls; /* used by the autoreplier */
|
||||
MSList *call_logs;
|
||||
MSList *chatrooms;
|
||||
int max_call_logs;
|
||||
int missed_calls;
|
||||
struct _AudioStream *audiostream; /**/
|
||||
struct _VideoStream *videostream;
|
||||
struct _VideoStream *previewstream;
|
||||
RtpTransport *a_rtp,*a_rtcp;
|
||||
MSList *bl_reqs;
|
||||
MSList *subscribers; /* unknown subscribers */
|
||||
int minutes_away;
|
||||
LinphoneOnlineStatus presence_mode;
|
||||
LinphoneOnlineStatus prev_mode;
|
||||
char *alt_contact;
|
||||
void *data;
|
||||
char *play_file;
|
||||
char *rec_file;
|
||||
time_t prevtime;
|
||||
int dw_audio_bw;
|
||||
int up_audio_bw;
|
||||
int dw_video_bw;
|
||||
int up_video_bw;
|
||||
int audio_bw;
|
||||
gstate_t gstate_power;
|
||||
gstate_t gstate_reg;
|
||||
gstate_t gstate_call;
|
||||
LinphoneWaitingCallback wait_cb;
|
||||
void *wait_ctx;
|
||||
bool_t use_files;
|
||||
bool_t apply_nat_settings;
|
||||
bool_t ready;
|
||||
bool_t bl_refresh;
|
||||
bool_t preview_finished;
|
||||
bool_t auto_net_state_mon;
|
||||
bool_t network_reachable;
|
||||
};
|
||||
|
||||
#endif /* _PRIVATE_H */
|
||||
|
|
|
|||
494
coreapi/proxy.c
494
coreapi/proxy.c
|
|
@ -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",¶m);
|
||||
if (param) rport=param->gvalue;
|
||||
else return FALSE;
|
||||
param=NULL;
|
||||
osip_via_param_get_byname(via,"received",¶m);
|
||||
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,29 @@ 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;
|
||||
char *try=NULL;
|
||||
|
||||
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){
|
||||
obj->reg_proxy=ms_strdup(server_addr);
|
||||
addr=linphone_address_new(server_addr);
|
||||
if (!addr){
|
||||
/*try to prepend 'sip:' */
|
||||
if (strstr(server_addr,"sip:")==NULL){
|
||||
try=ms_strdup_printf("sip:%s",server_addr);
|
||||
addr=linphone_address_new(try);
|
||||
ms_free(try);
|
||||
}
|
||||
}
|
||||
if (addr){
|
||||
obj->reg_proxy=linphone_address_as_string_uri_only(addr);
|
||||
linphone_address_destroy(addr);
|
||||
}else{
|
||||
ms_warning("Could not parse %s",server_addr);
|
||||
return -1;
|
||||
}
|
||||
osip_from_free(url);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -191,30 +125,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 +160,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 +215,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 +235,11 @@ 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_op_set_user_pointer(obj->op,obj);
|
||||
sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +254,7 @@ void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char
|
|||
ms_free(cfg->dial_prefix);
|
||||
cfg->dial_prefix=NULL;
|
||||
}
|
||||
if (prefix) cfg->dial_prefix=ms_strdup(prefix);
|
||||
if (prefix && prefix[0]!='\0') cfg->dial_prefix=ms_strdup(prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -484,172 +388,62 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route set for this proxy configuration.
|
||||
**/
|
||||
const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *obj){
|
||||
return obj->reg_route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SIP identity that belongs to this proxy configuration.
|
||||
*
|
||||
* The SIP identity is a SIP address (Display Name <sip:username@domain> )
|
||||
**/
|
||||
const char *linphone_proxy_config_get_identity(const LinphoneProxyConfig *obj){
|
||||
return obj->reg_identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if PUBLISH request is enabled for this proxy.
|
||||
**/
|
||||
bool_t linphone_proxy_config_publish_enabled(const LinphoneProxyConfig *obj){
|
||||
return obj->publish;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the proxy's SIP address.
|
||||
**/
|
||||
const char *linphone_proxy_config_get_addr(const LinphoneProxyConfig *obj){
|
||||
return obj->reg_proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the duration of registration.
|
||||
**/
|
||||
int linphone_proxy_config_get_expires(const LinphoneProxyConfig *obj){
|
||||
return obj->expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if registration to the proxy is enabled.
|
||||
**/
|
||||
bool_t linphone_proxy_config_register_enabled(const LinphoneProxyConfig *obj){
|
||||
return obj->reg_sendregister;
|
||||
}
|
||||
|
||||
struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig *obj){
|
||||
return obj->lc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a proxy configuration.
|
||||
|
|
@ -657,13 +451,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 +467,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 +475,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 +525,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 +532,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=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,prx_realm,username);
|
||||
if (www_realm!=NULL)
|
||||
as=(LinphoneAuthInfo*)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];
|
||||
|
|
@ -1016,5 +748,13 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj){
|
|||
}
|
||||
}
|
||||
|
||||
void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) {
|
||||
cr->user_data=ud;
|
||||
}
|
||||
|
||||
void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
|
||||
return cr->user_data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
172
coreapi/sal.c
Normal file
172
coreapi/sal.c
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
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(){
|
||||
SalMediaDescription *md=ms_new0(SalMediaDescription,1);
|
||||
md->refcount=1;
|
||||
return md;
|
||||
}
|
||||
|
||||
static 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);
|
||||
md->streams[i].payloads=NULL;
|
||||
}
|
||||
ms_free(md);
|
||||
}
|
||||
|
||||
void sal_media_description_ref(SalMediaDescription *md){
|
||||
md->refcount++;
|
||||
}
|
||||
|
||||
void sal_media_description_unref(SalMediaDescription *md){
|
||||
md->refcount--;
|
||||
if (md->refcount==0){
|
||||
sal_media_description_destroy (md);
|
||||
}
|
||||
}
|
||||
|
||||
const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
|
||||
SalMediaProto proto, SalStreamType type){
|
||||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
const SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->proto==proto && ss->type==type) return ss;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool_t sal_media_description_empty(SalMediaDescription *md){
|
||||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->port!=0) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const char *sal_op_get_proxy(const SalOp *op){
|
||||
return ((SalOpBase*)op)->route;
|
||||
}
|
||||
|
||||
const char *sal_op_get_network_origin(const SalOp *op){
|
||||
return ((SalOpBase*)op)->origin;
|
||||
}
|
||||
|
||||
void __sal_op_init(SalOp *b, Sal *sal){
|
||||
memset(b,0,sizeof(SalOpBase));
|
||||
((SalOpBase*)b)->root=sal;
|
||||
}
|
||||
|
||||
void __sal_op_set_network_origin(SalOp *op, const char *origin){
|
||||
assign_string(&((SalOpBase*)op)->origin,origin);
|
||||
}
|
||||
|
||||
|
||||
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->origin){
|
||||
ms_free(b->origin);
|
||||
b->origin=NULL;
|
||||
}
|
||||
if (b->local_media)
|
||||
sal_media_description_unref(b->local_media);
|
||||
if (b->remote_media)
|
||||
sal_media_description_unref(b->remote_media);
|
||||
ms_free(op);
|
||||
}
|
||||
297
coreapi/sal.h
Normal file
297
coreapi/sal.h
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
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...
|
||||
**/
|
||||
|
||||
#ifndef sal_h
|
||||
#define sal_h
|
||||
|
||||
#include "mediastreamer2/mscommon.h"
|
||||
|
||||
struct Sal;
|
||||
|
||||
typedef struct Sal Sal;
|
||||
|
||||
struct SalOp;
|
||||
|
||||
typedef struct SalOp SalOp;
|
||||
|
||||
struct SalAddress;
|
||||
|
||||
typedef struct SalAddress SalAddress;
|
||||
|
||||
/* Address manipulation API*/
|
||||
SalAddress * sal_address_new(const char *uri);
|
||||
SalAddress * sal_address_clone(const SalAddress *addr);
|
||||
const char *sal_address_get_scheme(const SalAddress *addr);
|
||||
const char *sal_address_get_display_name(const SalAddress* addr);
|
||||
const char *sal_address_get_username(const SalAddress *addr);
|
||||
const char *sal_address_get_domain(const SalAddress *addr);
|
||||
void sal_address_set_display_name(SalAddress *addr, const char *display_name);
|
||||
void sal_address_set_username(SalAddress *addr, const char *username);
|
||||
void sal_address_set_domain(SalAddress *addr, const char *host);
|
||||
void sal_address_set_port(SalAddress *addr, const char *port);
|
||||
void sal_address_set_port_int(SalAddress *uri, int port);
|
||||
void sal_address_clean(SalAddress *addr);
|
||||
char *sal_address_as_string(const SalAddress *u);
|
||||
char *sal_address_as_string_uri_only(const SalAddress *u);
|
||||
void sal_address_destroy(SalAddress *u);
|
||||
|
||||
|
||||
|
||||
|
||||
Sal * sal_init();
|
||||
void sal_uninit(Sal* sal);
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data);
|
||||
void *sal_get_user_pointer(const Sal *sal);
|
||||
|
||||
typedef enum {
|
||||
SalTransportDatagram,
|
||||
SalTransportStream
|
||||
}SalTransport;
|
||||
|
||||
typedef enum {
|
||||
SalAudio,
|
||||
SalVideo,
|
||||
SalOther
|
||||
} SalStreamType;
|
||||
|
||||
typedef enum{
|
||||
SalProtoUnknown,
|
||||
SalProtoRtpAvp,
|
||||
SalProtoRtpSavp
|
||||
}SalMediaProto;
|
||||
|
||||
typedef struct SalEndpointCandidate{
|
||||
char addr[64];
|
||||
int port;
|
||||
}SalEndpointCandidate;
|
||||
|
||||
#define SAL_ENDPOINT_CANDIDATE_MAX 2
|
||||
|
||||
typedef struct SalStreamDescription{
|
||||
SalMediaProto proto;
|
||||
SalStreamType type;
|
||||
char addr[64];
|
||||
int port;
|
||||
MSList *payloads; //<list of PayloadType
|
||||
int bandwidth;
|
||||
int ptime;
|
||||
SalEndpointCandidate candidates[SAL_ENDPOINT_CANDIDATE_MAX];
|
||||
} SalStreamDescription;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
|
||||
|
||||
typedef struct SalMediaDescription{
|
||||
int refcount;
|
||||
char addr[64];
|
||||
char username[64];
|
||||
int nstreams;
|
||||
SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
|
||||
} SalMediaDescription;
|
||||
|
||||
SalMediaDescription *sal_media_description_new();
|
||||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
void sal_media_description_unref(SalMediaDescription *md);
|
||||
bool_t sal_media_description_empty(SalMediaDescription *md);
|
||||
const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
|
||||
SalMediaProto proto, SalStreamType type);
|
||||
|
||||
/*this structure must be at the first byte of the SalOp structure defined by implementors*/
|
||||
typedef struct SalOpBase{
|
||||
Sal *root;
|
||||
char *route; /*or request-uri for REGISTER*/
|
||||
char *contact;
|
||||
char *from;
|
||||
char *to;
|
||||
char *origin;
|
||||
SalMediaDescription *local_media;
|
||||
SalMediaDescription *remote_media;
|
||||
void *user_pointer;
|
||||
} SalOpBase;
|
||||
|
||||
|
||||
typedef enum SalError{
|
||||
SalErrorNoResponse,
|
||||
SalErrorProtocol,
|
||||
SalErrorFailure, /* see SalReason for more details */
|
||||
SalErrorUnknown
|
||||
} SalError;
|
||||
|
||||
typedef enum SalReason{
|
||||
SalReasonDeclined,
|
||||
SalReasonBusy,
|
||||
SalReasonRedirect,
|
||||
SalReasonTemporarilyUnavailable,
|
||||
SalReasonNotFound,
|
||||
SalReasonDoNotDisturb,
|
||||
SalReasonMedia,
|
||||
SalReasonForbidden,
|
||||
SalReasonUnknown
|
||||
}SalReason;
|
||||
|
||||
typedef enum SalPresenceStatus{
|
||||
SalPresenceOffline,
|
||||
SalPresenceOnline,
|
||||
SalPresenceBusy,
|
||||
SalPresenceBerightback,
|
||||
SalPresenceAway,
|
||||
SalPresenceOnthephone,
|
||||
SalPresenceOuttolunch,
|
||||
SalPresenceDonotdisturb,
|
||||
SalPresenceMoved,
|
||||
SalPresenceAltService,
|
||||
}SalPresenceStatus;
|
||||
|
||||
typedef enum SalSubscribeState{
|
||||
SalSubscribeActive,
|
||||
SalSubscribeTerminated
|
||||
}SalSubscribeState;
|
||||
|
||||
typedef void (*SalOnCallReceived)(SalOp *op);
|
||||
typedef void (*SalOnCallRinging)(SalOp *op);
|
||||
typedef void (*SalOnCallAccepted)(SalOp *op);
|
||||
typedef void (*SalOnCallAck)(SalOp *op);
|
||||
typedef void (*SalOnCallUpdated)(SalOp *op);
|
||||
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
|
||||
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnAuthSuccess)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnRegisterSuccess)(SalOp *op, bool_t registered);
|
||||
typedef void (*SalOnRegisterFailure)(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
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 (*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 void (*SalOnPingReply)(SalOp *salop);
|
||||
|
||||
typedef struct SalCallbacks{
|
||||
SalOnCallReceived call_received;
|
||||
SalOnCallRinging call_ringing;
|
||||
SalOnCallAccepted call_accepted;
|
||||
SalOnCallAck call_ack;
|
||||
SalOnCallUpdated call_updated;
|
||||
SalOnCallTerminated call_terminated;
|
||||
SalOnCallFailure call_failure;
|
||||
SalOnAuthRequested auth_requested;
|
||||
SalOnAuthSuccess auth_success;
|
||||
SalOnRegisterSuccess register_success;
|
||||
SalOnRegisterFailure register_failure;
|
||||
SalOnVfuRequest vfu_request;
|
||||
SalOnDtmfReceived dtmf_received;
|
||||
SalOnRefer refer_received;
|
||||
SalOnTextReceived text_received;
|
||||
SalOnNotify notify;
|
||||
SalOnSubscribeReceived subscribe_received;
|
||||
SalOnSubscribeClosed subscribe_closed;
|
||||
SalOnInternalMsg internal_message;
|
||||
SalOnPingReply ping_reply;
|
||||
}SalCallbacks;
|
||||
|
||||
typedef struct SalAuthInfo{
|
||||
char *username;
|
||||
char *userid;
|
||||
char *password;
|
||||
char *realm;
|
||||
}SalAuthInfo;
|
||||
|
||||
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs);
|
||||
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure);
|
||||
void sal_set_user_agent(Sal *ctx, const char *user_agent);
|
||||
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);
|
||||
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);
|
||||
/*for incoming requests, returns the origin of the packet as a sip uri*/
|
||||
const char *sal_op_get_network_origin(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);
|
||||
int sal_call(SalOp *h, const char *from, const char *to);
|
||||
int sal_call_notify_ringing(SalOp *h);
|
||||
int sal_call_accept(SalOp*h);
|
||||
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
|
||||
int sal_refer(SalOp *h, const char *refer_to);
|
||||
int sal_call_send_dtmf(SalOp *h, char dtmf);
|
||||
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);
|
||||
|
||||
|
||||
/*ping: main purpose is to obtain its own contact address behind firewalls*/
|
||||
int sal_ping(SalOp *op, const char *from, const char *to);
|
||||
|
||||
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
|
||||
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
|
||||
|
||||
/*misc*/
|
||||
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen);
|
||||
|
||||
|
||||
/*internal API */
|
||||
void __sal_op_init(SalOp *b, Sal *sal);
|
||||
void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/);
|
||||
void __sal_op_free(SalOp *b);
|
||||
|
||||
|
||||
#endif
|
||||
1559
coreapi/sal_eXosip2.c
Normal file
1559
coreapi/sal_eXosip2.c
Normal file
File diff suppressed because it is too large
Load diff
76
coreapi/sal_eXosip2.h
Normal file
76
coreapi/sal_eXosip2.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 */
|
||||
MSList *pending_auths;/*MSList of SalOp */
|
||||
MSList *other_transactions; /*MSList of SalOp */
|
||||
int running;
|
||||
int session_expires;
|
||||
void *up;
|
||||
};
|
||||
|
||||
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;
|
||||
osip_call_id_t *call_id; /*used for out of calls transaction in order
|
||||
to retrieve the operation when receiving a response*/
|
||||
bool_t supports_session_timers;
|
||||
bool_t sdp_offering;
|
||||
bool_t reinvite;
|
||||
bool_t masquerade_via;
|
||||
};
|
||||
|
||||
void sal_remove_out_subscribe(Sal *sal, SalOp *op);
|
||||
void sal_remove_in_subscribe(Sal *sal, SalOp *op);
|
||||
|
||||
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);
|
||||
|
||||
void sal_exosip_in_subscription_closed(Sal *sal, eXosip_event_t *ev);
|
||||
|
||||
void sal_exosip_fix_route(SalOp *op);
|
||||
|
||||
|
||||
#endif
|
||||
732
coreapi/sal_eXosip2_presence.c
Normal file
732
coreapi/sal_eXosip2_presence.c
Normal file
|
|
@ -0,0 +1,732 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
||||
void sal_remove_out_subscribe(Sal *sal, SalOp *op){
|
||||
sal->out_subscribes=ms_list_remove(sal->out_subscribes,op);
|
||||
}
|
||||
|
||||
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 SalOp * sal_find_in_subscribe_by_call_id(Sal *sal, osip_call_id_t *call_id){
|
||||
const MSList *elem;
|
||||
SalOp *op;
|
||||
for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
|
||||
op=(SalOp*)elem->data;
|
||||
if (op->call_id && osip_call_id_match(op->call_id,call_id)==0)
|
||||
return op;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sal_add_in_subscribe(Sal *sal, SalOp *op, osip_message_t *subs){
|
||||
osip_call_id_clone(subs->call_id,&op->call_id);
|
||||
sal->in_subscribes=ms_list_append(sal->in_subscribes,op);
|
||||
}
|
||||
|
||||
void sal_remove_in_subscribe(Sal *sal, SalOp *op){
|
||||
sal->in_subscribes=ms_list_remove(sal->in_subscribes,op);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
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 ! op->sid=%i, op->did=%i",
|
||||
op->sid,op->did);
|
||||
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 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\
|
||||
<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==SalPresenceBerightback)
|
||||
{
|
||||
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==SalPresenceAway)
|
||||
{
|
||||
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==SalPresenceOnthephone)
|
||||
{
|
||||
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==SalPresenceOuttolunch)
|
||||
{
|
||||
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==SalPresenceOnline)
|
||||
{
|
||||
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==SalPresenceBusy)
|
||||
{
|
||||
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==SalPresenceBerightback)
|
||||
{
|
||||
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==SalPresenceAway)
|
||||
{
|
||||
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==SalPresenceOnthephone)
|
||||
{
|
||||
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==SalPresenceOuttolunch)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
|
||||
osip_message_t *msg;
|
||||
eXosip_ss_t ss=EXOSIP_SUBCRSTATE_ACTIVE;
|
||||
if (op->nid==-1){
|
||||
ms_warning("Cannot notify, subscription was closed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
eXosip_lock();
|
||||
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);
|
||||
osip_message_set_contact(msg,identity);
|
||||
add_presence_body(msg,status);
|
||||
eXosip_insubscription_send_request(op->did,msg);
|
||||
}else ms_error("could not create notify for incoming subscription.");
|
||||
eXosip_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_notify_close(SalOp *op){
|
||||
osip_message_t *msg=NULL;
|
||||
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);
|
||||
add_presence_body(msg,SalPresenceOffline);
|
||||
eXosip_insubscription_send_request(op->did,msg);
|
||||
}else ms_error("sal_notify_close(): could not create notify for incoming subscription"
|
||||
" did=%i, nid=%i",op->did,op->nid);
|
||||
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;
|
||||
}
|
||||
|
||||
static void _sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
|
||||
SalOp *op=sal_op_new(sal);
|
||||
char *tmp;
|
||||
op->did=ev->did;
|
||||
op->tid=ev->tid;
|
||||
op->nid=ev->nid;
|
||||
osip_from_to_str(ev->request->from,&tmp);
|
||||
sal_op_set_from(op,tmp);
|
||||
ms_free(tmp);
|
||||
osip_from_to_str(ev->request->to,&tmp);
|
||||
sal_op_set_to(op,tmp);
|
||||
ms_free(tmp);
|
||||
sal_add_in_subscribe(sal,op,ev->request);
|
||||
sal->callbacks.subscribe_received(op,sal_op_get_from(op));
|
||||
}
|
||||
|
||||
void sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){
|
||||
/*workaround a bug in eXosip: incoming SUBSCRIBES within dialog with expires: 0 are
|
||||
recognized as new incoming subscribes*/
|
||||
SalOp *op=sal_find_in_subscribe_by_call_id(sal,ev->request->call_id);
|
||||
if (op){
|
||||
osip_header_t *h;
|
||||
osip_message_header_get_byname(ev->request,"expires",0,&h);
|
||||
if (h && h->hvalue && atoi(h->hvalue)==0){
|
||||
ms_warning("This susbscribe is not a new one but terminates an old one.");
|
||||
ev->did=op->did;
|
||||
ev->nid=op->nid;
|
||||
sal_exosip_subscription_closed(sal,ev);
|
||||
}else {
|
||||
osip_message_t *msg=NULL;
|
||||
ms_warning("Probably a refresh subscribe");
|
||||
eXosip_lock();
|
||||
eXosip_insubscription_build_answer(ev->tid,202,&msg);
|
||||
eXosip_insubscription_send_answer(ev->tid,202,msg);
|
||||
eXosip_unlock();
|
||||
}
|
||||
}else _sal_exosip_subscription_recv(sal,ev);
|
||||
}
|
||||
|
||||
void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
|
||||
SalOp *op=sal_find_out_subscribe(sal,ev->sid);
|
||||
char *tmp;
|
||||
osip_from_t *from=NULL;
|
||||
osip_body_t *body=NULL;
|
||||
SalPresenceStatus estatus=SalPresenceOffline;
|
||||
|
||||
ms_message("Receiving notify with sid=%i,nid=%i",ev->sid,ev->nid);
|
||||
|
||||
if (op==NULL){
|
||||
ms_error("No operation related to this notify !");
|
||||
return;
|
||||
}
|
||||
if (ev->request==NULL) return;
|
||||
|
||||
from=ev->request->from;
|
||||
osip_message_get_body(ev->request,0,&body);
|
||||
if (body==NULL){
|
||||
ms_error("No body in NOTIFY");
|
||||
return;
|
||||
}
|
||||
osip_from_to_str(from,&tmp);
|
||||
if (strstr(body->body,"pending")!=NULL){
|
||||
estatus=SalPresenceOffline;
|
||||
}else if (strstr(body->body,"busy")!=NULL){
|
||||
estatus=SalPresenceBusy;
|
||||
}else if (strstr(body->body,"berightback")!=NULL
|
||||
|| strstr(body->body,"in-transit")!=NULL ){
|
||||
estatus=SalPresenceBerightback;
|
||||
}else if (strstr(body->body,"away")!=NULL){
|
||||
estatus=SalPresenceAway;
|
||||
}else if (strstr(body->body,"onthephone")!=NULL
|
||||
|| strstr(body->body,"on-the-phone")!=NULL){
|
||||
estatus=SalPresenceOnthephone;
|
||||
}else if (strstr(body->body,"outtolunch")!=NULL
|
||||
|| strstr(body->body,"meal")!=NULL){
|
||||
estatus=SalPresenceOuttolunch;
|
||||
}else if (strstr(body->body,"closed")!=NULL){
|
||||
estatus=SalPresenceOffline;
|
||||
}else if ((strstr(body->body,"online")!=NULL) || (strstr(body->body,"open")!=NULL)) {
|
||||
estatus=SalPresenceOnline;
|
||||
}else{
|
||||
estatus=SalPresenceOffline;
|
||||
}
|
||||
ms_message("We are notified that %s has online status %i",tmp,estatus);
|
||||
if (ev->ss_status==EXOSIP_SUBCRSTATE_TERMINATED) {
|
||||
sal_remove_out_subscribe(sal,op);
|
||||
op->sid=-1;
|
||||
op->did=-1;
|
||||
ms_message("And outgoing subscription terminated by remote.");
|
||||
}
|
||||
sal->callbacks.notify(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL);
|
||||
osip_free(tmp);
|
||||
}
|
||||
|
||||
void sal_exosip_subscription_answered(Sal *sal,eXosip_event_t *ev){
|
||||
SalOp *op=sal_find_out_subscribe(sal,ev->sid);
|
||||
if (op==NULL){
|
||||
ms_error("Subscription answered but no associated op !");
|
||||
return;
|
||||
}
|
||||
op->did=ev->did;
|
||||
}
|
||||
|
||||
void sal_exosip_in_subscription_closed(Sal *sal, eXosip_event_t *ev){
|
||||
SalOp *op=sal_find_in_subscribe(sal,ev->nid);
|
||||
char *tmp;
|
||||
if (op==NULL){
|
||||
ms_error("Incoming subscription closed but no associated op !");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sal_remove_in_subscribe(sal,op);
|
||||
op->nid=-1;
|
||||
op->did=-1;
|
||||
if (ev->request){
|
||||
osip_from_to_str(ev->request->from,&tmp);
|
||||
sal->callbacks.subscribe_closed(op,tmp);
|
||||
osip_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev){
|
||||
SalOp *op=sal_find_out_subscribe(sal,ev->sid);
|
||||
if (op==NULL){
|
||||
ms_error("Subscription closed but no associated op !");
|
||||
return;
|
||||
}
|
||||
sal_remove_out_subscribe(sal,op);
|
||||
op->sid=-1;
|
||||
op->did=-1;
|
||||
sal->callbacks.notify(op,SalSubscribeTerminated, SalPresenceOffline,NULL);
|
||||
}
|
||||
|
||||
|
||||
288
coreapi/sal_eXosip2_sdp.c
Normal file
288
coreapi/sal_eXosip2_sdp.c
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
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 "ortp/b64.h"
|
||||
#include "sal.h"
|
||||
#include <eXosip2/eXosip.h>
|
||||
|
||||
#define keywordcmp(key,b) strncmp(key,b,sizeof(key))
|
||||
|
||||
#ifdef FOR_LATER
|
||||
|
||||
static char *make_relay_session_id(const char *username, const char *relay){
|
||||
/*ideally this should be a hash of the parameters with a random part*/
|
||||
char tmp[128];
|
||||
int s1=(int)random();
|
||||
int s2=(int)random();
|
||||
long long int res=((long long int)s1)<<32 | (long long int) s2;
|
||||
void *src=&res;
|
||||
b64_encode(src, sizeof(long long int), tmp, sizeof(tmp));
|
||||
return osip_strdup(tmp);
|
||||
}
|
||||
|
||||
|
||||
static void add_relay_info(sdp_message_t *sdp, int mline, const char *relay, const char *relay_session_id){
|
||||
|
||||
if (relay) sdp_message_a_attribute_add(sdp, mline,
|
||||
osip_strdup ("relay-addr"),osip_strdup(relay));
|
||||
if (relay_session_id) sdp_message_a_attribute_add(sdp, mline,
|
||||
osip_strdup ("relay-session-id"), osip_strdup(relay_session_id));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static char * int_2char(int a){
|
||||
char *p=osip_malloc(16);
|
||||
snprintf(p,16,"%i",a);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/
|
||||
static const char *sdp_message_a_attr_value_get_with_pt(sdp_message_t *sdp,int pos,int pt,const char *field)
|
||||
{
|
||||
int i,tmppt=0,scanned=0;
|
||||
char *tmp;
|
||||
sdp_attribute_t *attr;
|
||||
for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){
|
||||
if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){
|
||||
int nb = sscanf(attr->a_att_value,"%i %n",&tmppt,&scanned);
|
||||
/* the return value may depend on how %n is interpreted by the libc: see manpage*/
|
||||
if (nb == 1 || nb==2 ){
|
||||
if (pt==tmppt){
|
||||
tmp=attr->a_att_value+scanned;
|
||||
if (strlen(tmp)>0)
|
||||
return tmp;
|
||||
}
|
||||
}else ms_warning("sdp has a strange a= line (%s) nb=%i",attr->a_att_value,nb);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef FOR_LATER
|
||||
/* return the value of attr "field" */
|
||||
static const char *sdp_message_a_attr_value_get(sdp_message_t *sdp,int pos,const char *field)
|
||||
{
|
||||
int i;
|
||||
sdp_attribute_t *attr;
|
||||
for (i=0;(attr=sdp_message_attribute_get(sdp,pos,i))!=NULL;i++){
|
||||
if (keywordcmp(field,attr->a_att_field)==0 && attr->a_att_value!=NULL){
|
||||
return attr->a_att_value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _sdp_message_get_a_ptime(sdp_message_t *sdp, int mline){
|
||||
int i,ret;
|
||||
sdp_attribute_t *attr;
|
||||
for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){
|
||||
if (keywordcmp("ptime",attr->a_att_field)==0){
|
||||
int nb = sscanf(attr->a_att_value,"%i",&ret);
|
||||
/* the return value may depend on how %n is interpreted by the libc: see manpage*/
|
||||
if (nb == 1){
|
||||
return ret;
|
||||
}else ms_warning("sdp has a strange a=ptime line (%s) ",attr->a_att_value);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
||||
{
|
||||
sdp_message_t *local;
|
||||
int inet6;
|
||||
|
||||
sdp_message_init (&local);
|
||||
if (strchr(desc->addr,':')!=NULL){
|
||||
inet6=1;
|
||||
}else inet6=0;
|
||||
sdp_message_v_version_set (local, osip_strdup ("0"));
|
||||
sdp_message_o_origin_set (local, osip_strdup (desc->username),
|
||||
osip_strdup ("123456"), osip_strdup ("654321"),
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr));
|
||||
sdp_message_s_name_set (local, osip_strdup ("A conversation"));
|
||||
sdp_message_c_connection_add (local, -1,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr), NULL, NULL);
|
||||
sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
|
||||
return local;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt)
|
||||
{
|
||||
char attr[256];
|
||||
sdp_message_m_payload_add (msg,line, int_2char (payload_type_get_number(pt)));
|
||||
if (pt->channels>0)
|
||||
snprintf (attr,sizeof(attr),"%i %s/%i/%i", payload_type_get_number(pt),
|
||||
pt->mime_type, pt->clock_rate,pt->channels);
|
||||
else
|
||||
snprintf (attr,sizeof(attr),"%i %s/%i", payload_type_get_number(pt),
|
||||
pt->mime_type, pt->clock_rate);
|
||||
sdp_message_a_attribute_add (msg, line,
|
||||
osip_strdup ("rtpmap"), osip_strdup(attr));
|
||||
|
||||
if (pt->recv_fmtp != NULL)
|
||||
{
|
||||
snprintf (attr,sizeof(attr),"%i %s", payload_type_get_number(pt),pt->recv_fmtp);
|
||||
sdp_message_a_attribute_add (msg, line, osip_strdup ("fmtp"),
|
||||
osip_strdup(attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){
|
||||
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 (port), NULL,
|
||||
osip_strdup ("RTP/AVP"));
|
||||
if (desc->bandwidth>0) sdp_message_b_bandwidth_add (msg, lineno, osip_strdup ("AS"),
|
||||
int_2char(desc->bandwidth));
|
||||
if (desc->ptime>0) sdp_message_a_attribute_add(msg,lineno,osip_strdup("ptime"),
|
||||
int_2char(desc->ptime));
|
||||
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
|
||||
add_payload(msg, lineno, (PayloadType*)elem->data);
|
||||
}
|
||||
}
|
||||
|
||||
sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
|
||||
int i;
|
||||
sdp_message_t *msg=create_generic_sdp(desc);
|
||||
for(i=0;i<desc->nstreams;++i){
|
||||
add_line(msg,i,&desc->streams[i]);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){
|
||||
if (rtpmap==NULL){
|
||||
PayloadType *refpt=rtp_profile_get_payload(&av_profile,payload_type_get_number(pt));
|
||||
if (refpt){
|
||||
pt->mime_type=ms_strdup(refpt->mime_type);
|
||||
pt->clock_rate=refpt->clock_rate;
|
||||
}else{
|
||||
ms_error("payload number %i has no rtpmap and is unknown in AV Profile, ignored.",
|
||||
payload_type_get_number(pt));
|
||||
return -1;
|
||||
}
|
||||
}else{
|
||||
char *mime=ms_strdup(rtpmap);
|
||||
char *p=strchr(mime,'/');
|
||||
if (p){
|
||||
char *chans;
|
||||
*p='\0';
|
||||
p++;
|
||||
chans=strchr(p,'/');
|
||||
if (chans){
|
||||
*chans='\0';
|
||||
chans++;
|
||||
pt->channels=atoi(chans);
|
||||
}else pt->channels=1;
|
||||
pt->clock_rate=atoi(p);
|
||||
}
|
||||
pt->mime_type=mime;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
||||
int i,j;
|
||||
const char *mtype,*proto,*port,*addr,*number;
|
||||
sdp_bandwidth_t *sbw=NULL;
|
||||
|
||||
addr=sdp_message_c_addr_get (msg, -1, 0);
|
||||
if (addr)
|
||||
strncpy(desc->addr,addr,sizeof(desc->addr));
|
||||
/* for each m= line */
|
||||
for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
|
||||
{
|
||||
SalStreamDescription *stream=&desc->streams[i];
|
||||
|
||||
memset(stream,0,sizeof(*stream));
|
||||
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=SalProtoUnknown;
|
||||
if (proto){
|
||||
if (strcasecmp(proto,"RTP/AVP")==0)
|
||||
stream->proto=SalProtoRtpAvp;
|
||||
else if (strcasecmp(proto,"RTP/SAVP")==0){
|
||||
stream->proto=SalProtoRtpSavp;
|
||||
}
|
||||
}
|
||||
addr = sdp_message_c_addr_get (msg, i, 0);
|
||||
if (addr != NULL)
|
||||
strncpy(stream->addr,addr,sizeof(stream->addr));
|
||||
if (port)
|
||||
stream->port=atoi(port);
|
||||
|
||||
stream->ptime=_sdp_message_get_a_ptime(msg,i);
|
||||
if (strcasecmp("audio", mtype) == 0){
|
||||
stream->type=SalAudio;
|
||||
}else if (strcasecmp("video", mtype) == 0){
|
||||
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);
|
||||
}
|
||||
/* for each payload type */
|
||||
for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
|
||||
const char *rtpmap,*fmtp;
|
||||
int ptn=atoi(number);
|
||||
PayloadType *pt=payload_type_new();
|
||||
payload_type_set_number(pt,ptn);
|
||||
/* get the rtpmap associated to this codec, if any */
|
||||
rtpmap=sdp_message_a_attr_value_get_with_pt(msg, i,ptn,"rtpmap");
|
||||
payload_type_fill_from_rtpmap(pt,rtpmap);
|
||||
/* get the fmtp, if any */
|
||||
fmtp=sdp_message_a_attr_value_get_with_pt(msg, i, ptn,"fmtp");
|
||||
payload_type_set_send_fmtp(pt,fmtp);
|
||||
stream->payloads=ms_list_append(stream->payloads,pt);
|
||||
ms_message("Found payload %s/%i fmtp=%s",pt->mime_type,pt->clock_rate,
|
||||
pt->send_fmtp ? pt->send_fmtp : "");
|
||||
}
|
||||
}
|
||||
desc->nstreams=i;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#endif
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static void sip_login_init_instance(SipSetupContext *ctx){
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ typedef struct _status_picture_tab_t{
|
|||
} status_picture_tab_t;
|
||||
|
||||
status_picture_tab_t status_picture_tab[]={
|
||||
{ LINPHONE_STATUS_UNKNOWN, "sip-closed.png" },
|
||||
{ LINPHONE_STATUS_ONLINE, "sip-online.png" },
|
||||
{ LINPHONE_STATUS_BUSY, "sip-busy.png" },
|
||||
{ LINPHONE_STATUS_BERIGHTBACK, "sip-bifm.png" },
|
||||
|
|
@ -51,7 +50,6 @@ status_picture_tab_t status_picture_tab[]={
|
|||
{ LINPHONE_STATUS_ALT_SERVICE, "sip-closed.png" },
|
||||
{ LINPHONE_STATUS_OFFLINE, "sip-away.png" },
|
||||
{ LINPHONE_STATUS_PENDING, "sip-wfa.png" },
|
||||
{ LINPHONE_STATUS_CLOSED, "sip-closed.png" },
|
||||
{ LINPHONE_STATUS_END, NULL },
|
||||
};
|
||||
|
||||
|
|
@ -104,7 +102,7 @@ static void linphone_gtk_set_selection_to_uri_bar(GtkTreeView *treeview){
|
|||
if (gtk_tree_selection_get_selected (select, &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
|
||||
friend=linphone_address_as_string(linphone_friend_get_uri(lf));
|
||||
friend=linphone_address_as_string(linphone_friend_get_address(lf));
|
||||
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),friend);
|
||||
ms_free(friend);
|
||||
}
|
||||
|
|
@ -134,8 +132,7 @@ static GtkWidget * create_presence_menu(){
|
|||
GdkPixbuf *pbuf;
|
||||
status_picture_tab_t *t;
|
||||
for(t=status_picture_tab;t->img!=NULL;++t){
|
||||
if (t->status==LINPHONE_STATUS_UNKNOWN ||
|
||||
t->status==LINPHONE_STATUS_PENDING){
|
||||
if (t->status==LINPHONE_STATUS_PENDING){
|
||||
continue;
|
||||
}
|
||||
menu_item=gtk_image_menu_item_new_with_label(linphone_online_status_to_string(t->status));
|
||||
|
|
@ -309,7 +306,7 @@ void linphone_gtk_show_friends(void){
|
|||
|
||||
for(itf=linphone_core_get_friend_list(core);itf!=NULL;itf=ms_list_next(itf)){
|
||||
LinphoneFriend *lf=(LinphoneFriend*)itf->data;
|
||||
const LinphoneAddress *f_uri=linphone_friend_get_uri(lf);
|
||||
const LinphoneAddress *f_uri=linphone_friend_get_address(lf);
|
||||
char *uri=linphone_address_as_string(f_uri);
|
||||
const char *name=linphone_address_get_display_name(f_uri);
|
||||
const char *display=name;
|
||||
|
|
@ -376,7 +373,7 @@ void linphone_gtk_show_contact(LinphoneFriend *lf){
|
|||
GtkWidget *w=linphone_gtk_create_window("contact");
|
||||
char *uri;
|
||||
const char *name;
|
||||
const LinphoneAddress *f_uri=linphone_friend_get_uri(lf);
|
||||
const LinphoneAddress *f_uri=linphone_friend_get_address(lf);
|
||||
uri=linphone_address_as_string_uri_only(f_uri);
|
||||
name=linphone_address_get_display_name(f_uri);
|
||||
if (uri) {
|
||||
|
|
@ -419,7 +416,7 @@ void linphone_gtk_chat_selected(GtkWidget *item){
|
|||
{
|
||||
char *uri;
|
||||
gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
|
||||
uri=linphone_address_as_string(linphone_friend_get_uri(lf));
|
||||
uri=linphone_address_as_string(linphone_friend_get_address(lf));
|
||||
linphone_gtk_create_chatroom(uri);
|
||||
ms_free(uri);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ static void linphone_gtk_log_file(OrtpLogLevel lev, const char *msg)
|
|||
|
||||
/* lc->config will turn NULL at exit, close the file to flush and
|
||||
return to stop logging */
|
||||
if (lc->config == NULL) {
|
||||
if (linphone_core_get_config(lc) == NULL) {
|
||||
linphone_gtk_log_uninit();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg){
|
|||
LinphoneAddress *from;
|
||||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
int nettype;
|
||||
const char *passwd=NULL;
|
||||
|
||||
|
||||
if (linphone_core_get_download_bandwidth(lc)==512 &&
|
||||
|
|
@ -91,8 +92,9 @@ void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg){
|
|||
if (linphone_address_get_username(from)[0]!='?')
|
||||
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(mw,"login_username")),
|
||||
linphone_address_get_username(from));
|
||||
if (ai) passwd=linphone_auth_info_get_passwd(ai);
|
||||
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(mw,"login_password")),
|
||||
ai!=NULL ? ai->passwd : "");
|
||||
passwd!=NULL ? passwd : "");
|
||||
|
||||
linphone_address_destroy(from);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static GtkWidget *the_ui=NULL;
|
|||
static void linphone_gtk_show(LinphoneCore *lc);
|
||||
static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from);
|
||||
static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from);
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid);
|
||||
static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
|
||||
static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
|
||||
static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
|
||||
|
|
@ -208,7 +208,7 @@ static const char *linphone_gtk_get_factory_config_file(){
|
|||
}
|
||||
|
||||
static void linphone_gtk_init_liblinphone(const char *config_file,
|
||||
const char *factory_config_file) {
|
||||
const char *factory_config_file) {
|
||||
linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
|
||||
the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
|
||||
linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
|
||||
|
|
@ -720,7 +720,8 @@ static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from){
|
|||
|
||||
}
|
||||
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img){
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){
|
||||
linphone_gtk_show_friends();
|
||||
}
|
||||
|
||||
static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ static void linphone_gtk_show_codecs(GtkTreeView *listview, const MSList *codecl
|
|||
gchar *color;
|
||||
const char *params="";
|
||||
struct _PayloadType *pt=(struct _PayloadType *)elem->data;
|
||||
if (payload_type_enabled(pt)) status=_("Enabled");
|
||||
if (linphone_core_payload_type_enabled(linphone_gtk_get_core(),pt)) status=_("Enabled");
|
||||
else status=_("Disabled");
|
||||
if (linphone_core_check_payload_type_usability(linphone_gtk_get_core(),pt)) color="blue";
|
||||
else color="red";
|
||||
|
|
@ -311,7 +311,7 @@ static void linphone_gtk_show_codecs(GtkTreeView *listview, const MSList *codecl
|
|||
CODEC_PARAMS,params,
|
||||
CODEC_PRIVDATA,(gpointer)pt,
|
||||
CODEC_COLOR,(gpointer)color,
|
||||
CODEC_INFO,(gpointer)payload_type_get_description(pt),
|
||||
CODEC_INFO,(gpointer)linphone_core_get_payload_type_description(linphone_gtk_get_core(),pt),
|
||||
-1);
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +433,7 @@ static void linphone_gtk_codec_set_enable(GtkWidget *button, gboolean enabled){
|
|||
if (gtk_tree_selection_get_selected(sel,&mod,&iter)){
|
||||
store=GTK_LIST_STORE(mod);
|
||||
gtk_tree_model_get(mod,&iter,CODEC_PRIVDATA,&pt,-1);
|
||||
payload_type_set_enable(pt,enabled);
|
||||
linphone_core_enable_payload_type(linphone_gtk_get_core(),pt,enabled);
|
||||
gtk_list_store_set(store,&iter,CODEC_STATUS, enabled ? _("Enabled") : _("Disabled"), -1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ AC_CHECK_LIB([eXosip2],[eXosip_get_version],
|
|||
[AC_DEFINE([HAVE_EXOSIP_GET_VERSION],[1],[Defined when eXosip_get_version is available])],
|
||||
[],
|
||||
[-losipparser2 -losip2 ])
|
||||
AC_CHECK_LIB([eXosip2],[eXosip_call_get_reference],
|
||||
[],
|
||||
[AC_MSG_ERROR([Could not find eXosip_call_get_reference() in eXosip2 !])],
|
||||
[-losipparser2 -losip2 ])
|
||||
dnl AC_CHECK_LIB([eXosip2],[eXosip_get_naptr],
|
||||
dnl [AC_DEFINE([HAVE_EXOSIP_NAPTR_SUPPORT],[1],[Defined when eXosip_get_naptr is available])],
|
||||
dnl [],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue