Merge branch 'master' of git.savannah.nongnu.org:/srv/git/linphone

This commit is contained in:
Jehan Monnier 2010-11-16 08:46:05 +01:00
commit 3d4f548aac
37 changed files with 2407 additions and 504 deletions

View file

@ -70,7 +70,7 @@ LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../../externals/exosip/include \
$(LOCAL_PATH)/../../externals/osip/include
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS += -llog -ldl
LOCAL_STATIC_LIBRARIES := \
libmediastreamer2 \

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([linphone],[3.3.99.7],[linphone-developers@nongnu.org])
AC_INIT([linphone],[3.3.99.9],[linphone-developers@nongnu.org])
AC_CANONICAL_SYSTEM
AC_CONFIG_SRCDIR([coreapi/linphonecore.c])

View file

@ -170,6 +170,12 @@ static LPC_COMMAND commands[] = {
{ "resume", lpc_cmd_resume, "resume a call",
"'resume' : resume the unique call\n"
"'resume <call id>' : hold off the call with given id\n"},
{ "transfer", lpc_cmd_transfer,
"Transfer a call to a specified destination.",
"'transfer <sip-uri>' : transfers the current active call to the destination sip-uri\n"
"'transfer <call id> <sip-uri>': transfers the call with 'id' to the destination sip-uri\n"
"'transfer <call id1> --to-call <call id2>': transfers the call with 'id1' to the destination of call 'id2' (attended transfer)\n"
},
{ "mute", lpc_cmd_mute_mic,
"Mute microphone and suspend voice transmission."},
#ifdef VIDEO_ENABLED
@ -209,11 +215,6 @@ static LPC_COMMAND commands[] = {
"'ipv6 enable' : enable the use of the ipv6 network.\n"
"'ipv6 disable' : do not use ipv6 network."
},
{ "transfer", lpc_cmd_transfer,
"Transfer a call to a specified destination.",
"'transfer <sip-uri>' : transfers the current active call to the destination sip-uri"
"'transfer <call id> <sip-uri>': transfers the call with 'id' to the destination sip-uri"
},
{ "nat", lpc_cmd_nat, "Set nat address",
"'nat' : show nat settings.\n"
"'nat <addr>' : set nat address.\n"
@ -637,10 +638,12 @@ lpc_cmd_transfer(LinphoneCore *lc, char *args)
{
if (args){
LinphoneCall *call;
LinphoneCall *call2;
const char *refer_to=NULL;
char arg1[256]={0};
char arg2[266]={0};
int n=sscanf(args,"%s %s",arg1,arg2);
long id2=0;
int n=sscanf(args,"%s %s %li",arg1,arg2,&id2);
if (n==1 || isalpha(*arg1)){
call=linphone_core_get_current_call(lc);
if (call==NULL && ms_list_size(linphone_core_get_calls(lc))==1){
@ -651,13 +654,24 @@ lpc_cmd_transfer(LinphoneCore *lc, char *args)
linphonec_out("No active call, please specify a call id among the ones listed by 'calls' command.\n");
return 0;
}
}else{
linphone_core_transfer_call(lc, call, refer_to);
}else if (n==2){
long id=atoi(arg1);
refer_to=args+strlen(arg1)+1;
call=linphonec_get_call(id);
if (call==NULL) return 0;
}
linphone_core_transfer_call(lc, call, refer_to);
linphone_core_transfer_call(lc, call, refer_to);
}else if (n==3){
long id=atoi(arg1);
call=linphonec_get_call(id);
call2=linphonec_get_call(id2);
if (call==NULL || call2==NULL) return 0;
if (strcmp(arg2,"--to-call")!=0){
return 0;
}
linphonec_out("Performing attended transfer of call %i to call %i",id,id2);
linphone_core_transfer_call_to_another (lc,call,call2);
}else return 0;
}else{
linphonec_out("Transfer command requires at least one argument\n");
return 0;

View file

@ -110,7 +110,6 @@ static void call_received(SalOp *h){
linphone_address_clean(from_parsed);
tmp=linphone_address_as_string(from_parsed);
linphone_address_destroy(from_parsed);
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
(sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_("."));
if (lc->vtable.show) lc->vtable.show(lc);
@ -146,6 +145,11 @@ static void call_received(SalOp *h){
#endif
ms_free(barmesg);
ms_free(tmp);
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
linphone_core_accept_call(lc,call);
}
}
static void call_ringing(SalOp *h){
@ -343,7 +347,6 @@ static void call_updating(SalOp *op){
linphone_call_set_state (call,prevstate,"Connected (streams running)");
}
}
if (lc->current_call==NULL) linphone_core_start_pending_refered_calls (lc);
}
static void call_terminated(SalOp *op, const char *from){
@ -445,8 +448,10 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
}
linphone_call_stop_media_streams (call);
if (sr!=SalReasonDeclined) linphone_call_set_state(call,LinphoneCallError,msg);
else linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
else{
call->reason=LinphoneReasonDeclined;
linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
}
}
static void auth_requested(SalOp *h, const char *realm, const char *username){
@ -486,7 +491,7 @@ static void register_success(SalOp *op, bool_t registered){
char *msg;
cfg->registered=registered;
linphone_proxy_config_set_error(cfg,LinphoneErrorNone);
linphone_proxy_config_set_error(cfg,LinphoneReasonNone);
linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared ,
registered ? "Registration sucessful" : "Unregistration done");
if (lc->vtable.display_status){
@ -515,9 +520,9 @@ static void register_failure(SalOp *op, SalError error, SalReason reason, const
ms_free(msg);
}
if (error== SalErrorFailure && reason == SalReasonForbidden) {
linphone_proxy_config_set_error(cfg, LinphoneErrorBadCredentials);
linphone_proxy_config_set_error(cfg, LinphoneReasonBadCredentials);
} else if (error == SalErrorNoResponse) {
linphone_proxy_config_set_error(cfg, LinphoneErrorNoResponse);
linphone_proxy_config_set_error(cfg, LinphoneReasonNoResponse);
}
linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details);
}
@ -556,11 +561,15 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
lc->vtable.display_status(lc,msg);
ms_free(msg);
}
if (lc->current_call==NULL) linphone_core_start_pending_refered_calls (lc);
sal_refer_accept(op);
if (call->state!=LinphoneCallPaused){
ms_message("Automatically pausing current call to accept transfer.");
linphone_core_pause_call(lc,call);
}
linphone_core_start_refered_call(lc,call);
sal_call_accept_refer(op);
}else if (lc->vtable.refer_received){
lc->vtable.refer_received(lc,referto);
sal_refer_accept(op);
sal_call_accept_refer(op);
}
}

View file

@ -46,13 +46,13 @@ static void stop(int signum){
/**
* presence state change notification callback
*/
static void notify_presence_recv_updated (struct _LinphoneCore *lc, LinphoneFriend *friend) {
static void notify_presence_recv_updated (LinphoneCore *lc, LinphoneFriend *friend) {
const LinphoneAddress* friend_address = linphone_friend_get_address(friend);
printf("New state state [%s] for user id [%s] \n"
,linphone_online_status_to_string(linphone_friend_get_status(friend))
,linphone_address_as_string (friend_address));
}
static void new_subscription_request (struct _LinphoneCore *lc, LinphoneFriend *friend, const char* url) {
static void new_subscription_request (LinphoneCore *lc, LinphoneFriend *friend, const char* url) {
const LinphoneAddress* friend_address = linphone_friend_get_address(friend);
printf(" [%s] wants to see your status, accepting\n"
,linphone_address_as_string (friend_address));

View file

@ -0,0 +1,194 @@
/*
TutorialBuddyStatus
Copyright (C) 2010 Belledonne Communications SARL
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.
*/
package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
import org.linphone.core.LinphoneFriend;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.OnlineStatus;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.LinphoneFriend.SubscribePolicy;
/**
*
* This program is a _very_ simple usage example of liblinphone,
* demonstrating how to initiate SIP subscriptions and receive notifications
* from a sip uri identity passed from the command line.
* <br>Argument must be like sip:jehan@sip.linphone.org .
* ex budy_list sip:jehan@sip.linphone.org
* <br>Subscription is cleared on SIGINT
*
* Ported from buddy_status.c
*
* @author Guillaume Beraudo
*
*/
public class TutorialBuddyStatus implements LinphoneCoreListener {
private boolean running;
private TutorialNotifier TutorialNotifier;
public TutorialBuddyStatus(TutorialNotifier TutorialNotifier) {
this.TutorialNotifier = TutorialNotifier;
}
public TutorialBuddyStatus() {
this.TutorialNotifier = new TutorialNotifier();
}
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {
write("["+lf.getAddress().getUserName()+"] wants to see your status, accepting");
lf.edit(); // start editing friend
lf.setIncSubscribePolicy(SubscribePolicy.SPAccept); // accept incoming subscription request for this friend
lf.done(); // commit change
try {
// add this new friend to the buddy list
lc.addFriend(lf);
} catch (LinphoneCoreException e) {
write("Error while adding friend [" + lf.getAddress().getUserName() + "] to linphone in the callback");
}
}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {
write("New state [" + lf.getStatus() +"] for user id ["+lf.getAddress().getUserName()+"]");
}
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {}
public void show(LinphoneCore lc) {}
public void byeReceived(LinphoneCore lc, String from) {}
public void authInfoRequested(LinphoneCore lc, String realm, String username) {}
public void displayStatus(LinphoneCore lc, String message) {}
public void displayMessage(LinphoneCore lc, String message) {}
public void displayWarning(LinphoneCore lc, String message) {}
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
if (args.length != 1) {
throw new IllegalArgumentException("Bad number of arguments");
}
// Create tutorial object
TutorialBuddyStatus tutorial = new TutorialBuddyStatus();
try {
// takes sip uri identity from the command line arguments
String userSipAddress = args[1];
tutorial.launchTutorial(userSipAddress);
} catch (Exception e) {
e.printStackTrace();
}
}
public void launchTutorial(String sipAddress) throws LinphoneCoreException {
final LinphoneCoreFactory lcFactory = LinphoneCoreFactory.instance();
// First instantiate the core Linphone object given only a listener.
// The listener will react to events in Linphone core.
LinphoneCore lc = lcFactory.createLinphoneCore(this);
try {
// Create friend object from string address
LinphoneFriend lf = lcFactory.createLinphoneFriend(sipAddress);
if (lf == null) {
write("Could not create friend; weird SIP address?");
return;
}
// configure this friend to emit SUBSCRIBE message after being added to LinphoneCore
lf.enableSubscribes(true);
// accept incoming subscription request for this friend
lf.setIncSubscribePolicy(SubscribePolicy.SPAccept);
try {
// add my friend to the buddy list, initiate SUBSCRIBE message
lc.addFriend(lf);
} catch (LinphoneCoreException e) {
write("Error while adding friend " + lf.getAddress().getUserName() + " to linphone");
return;
}
// set my status to online
lc.setPresenceInfo(0, null, OnlineStatus.Online);
// main loop for receiving notifications and doing background linphonecore work
running = true;
while (running) {
lc.iterate(); // first iterate initiates subscription
try{
Thread.sleep(50);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
}
// change my presence status to offline
lc.setPresenceInfo(0, null, OnlineStatus.Offline);
// just to make sure new status is initiate message is issued
lc.iterate();
lf.edit(); // start editing friend
lf.enableSubscribes(false); // disable subscription for this friend
lf.done(); // commit changes triggering an UNSUBSCRIBE message
lc.iterate(); // just to make sure unsubscribe message is issued
} finally {
write("Shutting down...");
// You need to destroy the LinphoneCore object when no longer used
lc.destroy();
write("Exited");
}
}
public void stopMainLoop() {
running=false;
}
private void write(String s) {
TutorialNotifier.notify(s);
}
}

View file

@ -0,0 +1,147 @@
/*
TutorialChatRoom.java
Copyright (C) 2010 Belledonne Communications SARL
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.
*/
package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
import org.linphone.core.LinphoneFriend;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
/**
* This program is a _very_ simple usage example of liblinphone.
* It demonstrates how to send/receive SIP MESSAGE from a sip uri identity
* passed from the command line.
*
* Argument must be like sip:jehan@sip.linphone.org .
*
* ex chatroom sip:jehan@sip.linphone.org
* just takes a sip-uri as first argument and attempts to call it.
*
* Ported from chatroom.c
*
* @author Guillaume Beraudo
*
*/
public class TutorialChatRoom implements LinphoneCoreListener {
private boolean running;
private TutorialNotifier TutorialNotifier;
public TutorialChatRoom(TutorialNotifier TutorialNotifier) {
this.TutorialNotifier = TutorialNotifier;
}
public TutorialChatRoom() {
this.TutorialNotifier = new TutorialNotifier();
}
public void show(LinphoneCore lc) {}
public void byeReceived(LinphoneCore lc, String from) {}
public void authInfoRequested(LinphoneCore lc, String realm, String username) {}
public void displayStatus(LinphoneCore lc, String message) {}
public void displayMessage(LinphoneCore lc, String message) {}
public void displayWarning(LinphoneCore lc, String message) {}
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {}
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg){}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {
write("Message ["+message+"] received from ["+from.asString()+"]");
}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
// Takes the sip uri identity from the command line arguments
if (args.length != 1) {
throw new IllegalArgumentException("Bad number of arguments");
}
// Create tutorial object
TutorialChatRoom tutorial = new TutorialChatRoom();
try {
String destinationSipAddress = args[1];
tutorial.launchTutorial(destinationSipAddress);
} catch (Exception e) {
e.printStackTrace();
}
}
public void launchTutorial(String destinationSipAddress) throws LinphoneCoreException {
// First instantiate the core Linphone object given only a listener.
// The listener will react to events in Linphone core.
LinphoneCore lc = LinphoneCoreFactory.instance().createLinphoneCore(this);
try {
// Next step is to create a chat room
LinphoneChatRoom chatRoom = lc.createChatRoom(destinationSipAddress);
// Send message
chatRoom.sendMessage("Hello world");
// main loop for receiving notifications and doing background linphonecore work
running = true;
while (running) {
lc.iterate();
try{
Thread.sleep(50);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
}
} finally {
write("Shutting down...");
// You need to destroy the LinphoneCore object when no longer used
lc.destroy();
write("Exited");
}
}
public void stopMainLoop() {
running=false;
}
private void write(String s) {
TutorialNotifier.notify(s);
}
}

View file

@ -0,0 +1,156 @@
/*
TutorialHelloWorld.java
Copyright (C) 2010 Belledonne Communications SARL
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.
*/
package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
import org.linphone.core.LinphoneFriend;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
/**
* This program is a _very_ simple usage example of liblinphone.
* It just takes a sip-uri as first argument and attempts to call it.
*
* Ported from helloworld.c
*
* @author Guillaume Beraudo
*
*/
public class TutorialHelloWorld implements LinphoneCoreListener {
private boolean running;
private TutorialNotifier TutorialNotifier;
public TutorialHelloWorld(TutorialNotifier TutorialNotifier) {
this.TutorialNotifier = TutorialNotifier;
}
public TutorialHelloWorld() {
this.TutorialNotifier = new TutorialNotifier();
}
public void show(LinphoneCore lc) {}
public void byeReceived(LinphoneCore lc, String from) {}
public void authInfoRequested(LinphoneCore lc, String realm, String username) {}
public void displayStatus(LinphoneCore lc, String message) {}
public void displayMessage(LinphoneCore lc, String message) {}
public void displayWarning(LinphoneCore lc, String message) {}
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {}
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
/*
* Call state notification listener
*/
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg){
write("State: " + msg);
if (State.CallEnd.equals(cstate))
running = false;
}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
if (args.length != 1) {
throw new IllegalArgumentException("Bad number of arguments");
}
// Create tutorial object
TutorialHelloWorld helloWorld = new TutorialHelloWorld();
try {
String destinationSipAddress = args[1];
helloWorld.launchTutorial(destinationSipAddress);
} catch (Exception e) {
e.printStackTrace();
}
}
public void launchTutorial(String destinationSipAddress) throws LinphoneCoreException {
// First instantiate the core Linphone object given only a listener.
// The listener will react to events in Linphone core.
LinphoneCore lc = LinphoneCoreFactory.instance().createLinphoneCore(this);
try {
// Send the INVITE message to destination SIP address
LinphoneCall call = lc.invite(destinationSipAddress);
if (call == null) {
write("Could not place call to " + destinationSipAddress);
write("Aborting");
return;
}
write("Call to " + destinationSipAddress + " is in progress...");
// main loop for receiving notifications and doing background linphonecore work
running = true;
while (running) {
lc.iterate();
try{
Thread.sleep(50);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
}
if (!State.CallEnd.equals(call.getState())) {
write("Terminating the call");
lc.terminateCall(call);
}
} finally {
write("Shutting down...");
// You need to destroy the LinphoneCore object when no longer used
lc.destroy();
write("Exited");
}
}
public void stopMainLoop() {
running=false;
}
private void write(String s) {
TutorialNotifier.notify(s);
}
}

View file

@ -0,0 +1,33 @@
/*
TutorialNotifier.java
Copyright (C) 2010 Belledonne Communications SARL
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.
*/
package org.linphone.core.tutorials;
/**
* Notify to the standard output.
* Subclass to define another text output.
*
* @author Guillaume Beraudo
*
*/
public class TutorialNotifier {
public void notify(String s) {
System.out.println(s);
}
}

View file

@ -0,0 +1,170 @@
/*
TutorialRegistration.java
Copyright (C) 2010 Belledonne Communications SARL
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.
*/
package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
import org.linphone.core.LinphoneFriend;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
/**
* This program is a _very_ simple usage example of liblinphone.
* Demonstrating how to initiate a SIP registration from a sip uri identity
* passed from the command line.
*
* First argument must be like sip:jehan@sip.linphone.org, second must be password.
* <br>
* ex registration sip:jehan@sip.linphone.org secret
*
* Ported from registration.c
*
* @author Guillaume Beraudo
*
*/
public class TutorialRegistration implements LinphoneCoreListener {
private boolean running;
private TutorialNotifier TutorialNotifier;
public TutorialRegistration(TutorialNotifier TutorialNotifier) {
this.TutorialNotifier = TutorialNotifier;
}
public TutorialRegistration() {
this.TutorialNotifier = new TutorialNotifier();
}
/*
* Registration state notification listener
*/
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {
write(cfg.getIdentity() + " : "+smessage+"\n");
if (RegistrationState.RegistrationOk.equals(cstate))
running = false;
}
public void show(LinphoneCore lc) {}
public void byeReceived(LinphoneCore lc, String from) {}
public void authInfoRequested(LinphoneCore lc, String realm, String username) {}
public void displayStatus(LinphoneCore lc, String message) {}
public void displayMessage(LinphoneCore lc, String message) {}
public void displayWarning(LinphoneCore lc, String message) {}
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
if (args.length != 2) {
throw new IllegalArgumentException("Bad number of arguments");
}
// Create tutorial object
TutorialRegistration tutorial = new TutorialRegistration();
try {
// takes sip uri identity from the command line arguments
String userSipAddress = args[1];
// takes password from the command line arguments
String userSipPassword = args[2];
tutorial.launchTutorial(userSipAddress, userSipPassword);
} catch (Exception e) {
e.printStackTrace();
}
}
public void launchTutorial(String sipAddress, String password) throws LinphoneCoreException {
final LinphoneCoreFactory lcFactory = LinphoneCoreFactory.instance();
// First instantiate the core Linphone object given only a listener.
// The listener will react to events in Linphone core.
LinphoneCore lc = lcFactory.createLinphoneCore(this);
try {
// Parse identity
LinphoneAddress address = lcFactory.createLinphoneAddress(sipAddress);
String username = address.getUserName();
String domain = address.getDomain();
if (password != null) {
// create authentication structure from identity and add to linphone
lc.addAuthInfo(lcFactory.createAuthInfo(username, password, null));
}
// create proxy config
LinphoneProxyConfig proxyCfg = lcFactory.createProxyConfig(sipAddress, domain, null, true);
lc.addProxyConfig(proxyCfg); // add it to linphone
lc.setDefaultProxyConfig(proxyCfg);
// main loop for receiving notifications and doing background linphonecore work
running = true;
while (running) {
lc.iterate(); // first iterate initiates registration
try{
Thread.sleep(50);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
}
// Automatic unregistration on exit
} finally {
write("Shutting down...");
// You need to destroy the LinphoneCore object when no longer used
lc.destroy();
write("Exited");
}
}
public void stopMainLoop() {
running=false;
}
private void write(String s) {
TutorialNotifier.notify(s);
}
}

View file

@ -161,6 +161,9 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
linphone_core_run_stun_tests(call->core,call);
discover_mtu(lc,linphone_address_get_domain (to));
if (params->referer){
sal_call_set_referer (call->op,params->referer->op);
}
return call;
}
@ -213,7 +216,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){
linphone_core_update_allocated_audio_bandwidth(lc);
if (call->state==LinphoneCallEnd){
status=LinphoneCallSuccess;
if (call->reason==LinphoneReasonDeclined){
status=LinphoneCallDeclined;
}
else status=LinphoneCallSuccess;
}
linphone_call_log_completed(call->log,call, status);
@ -221,7 +227,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){
if (call == lc->current_call){
ms_message("Resetting the current call");
lc->current_call=NULL;
linphone_core_start_pending_refered_calls(lc);
}
if (linphone_core_del_call(lc,call) != 0){
@ -382,6 +387,13 @@ LinphoneCallState linphone_call_get_state(const LinphoneCall *call){
return call->state;
}
/**
* Returns the reason for a call termination (either error or normal termination)
**/
LinphoneReason linphone_call_get_reason(const LinphoneCall *call){
return call->reason;
}
/**
* Get the user_pointer in the LinphoneCall
*
@ -795,7 +807,7 @@ static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_e
recfile,
playcard,
captcard,
send_early_media ? FALSE : linphone_core_echo_cancellation_enabled(lc));
captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc));
post_configure_audio_streams(call);
if (send_early_media) setup_ring_player(lc,call);
audio_stream_set_rtcp_information(call->audiostream, cname, tool);

View file

@ -946,6 +946,14 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
linphone_core_assign_payload_type(&payload_type_ilbc,113,"mode=30");
linphone_core_assign_payload_type(&payload_type_amr,114,"octet-align=1");
#if defined(ANDROID) || defined (__IPHONE_OS_VERSION_MIN_REQUIRED)
/*shorten the DNS lookup time and send more retransmissions on mobiles:
- to workaround potential packet losses
- to avoid hanging for 30 seconds when the network doesn't work despite the phone thinks it does.
*/
_linphone_core_configure_resolver();
#endif
#ifdef ENABLE_NONSTANDARD_GSM
{
PayloadType *pt;
@ -1839,16 +1847,14 @@ const char * linphone_core_get_route(LinphoneCore *lc){
return route;
}
void linphone_core_start_pending_refered_calls(LinphoneCore *lc){
MSList *elem;
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
if (call->refer_pending){
ms_message("Starting new call to refered address %s",call->refer_to);
call->refer_pending=FALSE;
linphone_core_invite(lc,call->refer_to);
break;
}
void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call){
if (call->refer_pending){
LinphoneCallParams *cp=linphone_core_create_default_call_parameters(lc);
cp->referer=call;
ms_message("Starting new call to refered address %s",call->refer_to);
call->refer_pending=FALSE;
linphone_core_invite_with_params(lc,call->refer_to,cp);
linphone_call_params_destroy(cp);
}
}
@ -2143,12 +2149,28 @@ int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char
}
//lc->call=NULL; //Do not do that you will lose the call afterward . . .
real_url=linphone_address_as_string (real_parsed_url);
sal_refer(call->op,real_url);
sal_call_refer(call->op,real_url);
ms_free(real_url);
linphone_address_destroy(real_parsed_url);
return 0;
}
/**
* Transfer a call to destination of another running call. This is used for "attended transfer" scenarios.
* @param lc linphone core object
* @param call a running call you want to transfer
* @param dest a running call whose remote person will receive the transfer
*
* The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately.
* The destination call is a call previously established to introduce the transfered person.
* This method will send a transfer request to the transfered person. The phone of the transfered is then
* expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically
* close the call with us (the 'dest' call).
**/
int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest){
return sal_call_refer_with_replaces (call->op,dest->op);
}
bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
LinphoneCall *call = linphone_core_get_current_call(lc);
if(call != NULL)
@ -2198,6 +2220,7 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
{
LinphoneProxyConfig *cfg=NULL;
const char *contact=NULL;
SalOp *replaced;
if (call==NULL){
//if just one call is present answer the only one ...
@ -2207,16 +2230,27 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
call = (LinphoneCall*)linphone_core_get_calls(lc)->data;
}
if (call->state==LinphoneCallConnected){
/*call already accepted*/
return -1;
}
/* check if this call is supposed to replace an already running one*/
replaced=sal_call_get_replaces(call->op);
if (replaced){
LinphoneCall *rc=(LinphoneCall*)sal_op_get_user_pointer (replaced);
if (rc){
ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.",
call,rc);
linphone_core_terminate_call (lc,rc);
}
}
if (lc->current_call!=NULL && lc->current_call!=call){
ms_warning("Cannot accept this call, there is already one running.");
return -1;
}
if (call->state==LinphoneCallConnected){
/*call already accepted*/
return -1;
}
/*can accept a new call only if others are on hold */
{
MSList *elem;
@ -2306,7 +2340,9 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call)
call = the_call;
}
sal_call_terminate(call->op);
if (call->state==LinphoneCallIncomingReceived){
call->reason=LinphoneReasonDeclined;
}
/*stop ringing*/
if (lc->ringstream!=NULL) {
ring_stop(lc->ringstream);
@ -2394,7 +2430,6 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
lc->current_call=NULL;
if (call->audiostream || call->videostream)
linphone_call_stop_media_streams (call);
linphone_core_start_pending_refered_calls(lc);
return 0;
}
@ -3298,7 +3333,13 @@ unsigned long linphone_core_get_native_video_window_id(const LinphoneCore *lc){
* If not set the core will create its own window.
**/
void linphone_core_set_native_video_window_id(LinphoneCore *lc, unsigned long id){
#ifdef VIDEO_ENABLED
LinphoneCall *call=linphone_core_get_current_call(lc);
lc->video_window_id=id;
if (call!=NULL && call->videostream){
video_stream_set_native_window_id(call->videostream,id);
}
#endif
}
/**
@ -3986,14 +4027,17 @@ LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *l
return p;
}
const char *linphone_error_to_string(LinphoneError err){
const char *linphone_error_to_string(LinphoneReason err){
switch(err){
case LinphoneErrorNone:
case LinphoneReasonNone:
return "No error";
case LinphoneErrorNoResponse:
case LinphoneReasonNoResponse:
return "No response";
case LinphoneErrorBadCredentials:
case LinphoneReasonBadCredentials:
return "Bad credentials";
case LinphoneReasonDeclined:
return "Call declined";
}
return "unknown error";
}

View file

@ -131,7 +131,8 @@ typedef enum _LinphoneCallDir LinphoneCallDir;
typedef enum _LinphoneCallStatus {
LinphoneCallSuccess, /**< The call was sucessful*/
LinphoneCallAborted, /**< The call was aborted */
LinphoneCallMissed /**< The call was missed (unanswered)*/
LinphoneCallMissed, /**< The call was missed (unanswered)*/
LinphoneCallDeclined /**< The call was declined, either locally or by remote end*/
} LinphoneCallStatus;
/**
@ -182,15 +183,16 @@ void linphone_call_params_destroy(LinphoneCallParams *cp);
/**
* Enum describing failure reasons.
**/
enum _LinphoneError{
LinphoneErrorNone,
LinphoneErrorNoResponse, /**<No response received from remote*/
LinphoneErrorBadCredentials /**<Authentication failed due to bad or missing credentials*/
enum _LinphoneReason{
LinphoneReasonNone,
LinphoneReasonNoResponse, /**<No response received from remote*/
LinphoneReasonBadCredentials, /**<Authentication failed due to bad or missing credentials*/
LinphoneReasonDeclined, /**<The call has been declined*/
};
typedef enum _LinphoneError LinphoneError;
typedef enum _LinphoneReason LinphoneReason;
const char *linphone_error_to_string(LinphoneError err);
const char *linphone_reason_to_string(LinphoneReason err);
/**
* The LinphoneCall object represents a call issued or received by the LinphoneCore
@ -200,21 +202,21 @@ typedef struct _LinphoneCall LinphoneCall;
typedef enum _LinphoneCallState{
LinphoneCallIdle,
LinphoneCallIncomingReceived,
LinphoneCallOutgoingInit,
LinphoneCallOutgoingProgress,
LinphoneCallOutgoingRinging,
LinphoneCallOutgoingEarlyMedia,
LinphoneCallConnected,
LinphoneCallStreamsRunning,
LinphoneCallPausing,
LinphoneCallPaused,
LinphoneCallResuming,
LinphoneCallRefered,
LinphoneCallError,
LinphoneCallEnd,
LinphoneCallPausedByRemote,
LinphoneCallUpdatedByRemote /**<used when video is asked by remote */
LinphoneCallIncomingReceived, /**<This is a new incoming call */
LinphoneCallOutgoingInit, /**<An outgoing call is started */
LinphoneCallOutgoingProgress, /**<An outgoing call is in progress */
LinphoneCallOutgoingRinging, /**<An outgoing call is ringing at remote end */
LinphoneCallOutgoingEarlyMedia, /**<An outgoing call is proposed early media */
LinphoneCallConnected, /**<Connected, the call is answered */
LinphoneCallStreamsRunning, /**<The media streams are established and running*/
LinphoneCallPausing, /**<The call is pausing at the initiative of local end */
LinphoneCallPaused, /**< The call is paused, remote end has accepted the pause */
LinphoneCallResuming, /**<The call is being resumed by local end*/
LinphoneCallRefered, /**<The call is being transfered to another party, resulting in a new outgoing call to follow immediately*/
LinphoneCallError, /**<The call encountered an error*/
LinphoneCallEnd, /**<The call ended normally*/
LinphoneCallPausedByRemote, /**<The call is paused by remote end*/
LinphoneCallUpdatedByRemote /**<The call's parameters are updated, used for example when video is asked by remote */
} LinphoneCallState;
const char *linphone_call_state_to_string(LinphoneCallState cs);
@ -236,7 +238,7 @@ const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *
void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled);
bool_t linphone_call_camera_enabled(const LinphoneCall *lc);
int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file);
LinphoneError linphone_call_get_error(const LinphoneCall *call);
LinphoneReason linphone_call_get_reason(const LinphoneCall *call);
const char *linphone_call_get_remote_user_agent(LinphoneCall *call);
void *linphone_call_get_user_pointer(LinphoneCall *call);
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
@ -315,7 +317,7 @@ struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig
bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg);
const char * linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg);
LinphoneError linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg);
LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg);
/* destruction is called automatically when removing the proxy config */
void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg);
@ -591,6 +593,8 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *refer_to);
int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest);
bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
bool_t linphone_core_in_call(const LinphoneCore *lc);

View file

@ -24,6 +24,8 @@ extern "C" void libmsilbc_init();
#endif /*ANDROID*/
extern "C" void ms_andsnd_set_jvm(JavaVM *jvm) ;
extern "C" void ms_andvid_set_jvm(JavaVM *jvm) ;
static JavaVM *jvm=0;
#ifdef ANDROID
@ -45,6 +47,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved)
{
#ifdef ANDROID
ms_andsnd_set_jvm(ajvm);
#ifdef VIDEO_ENABLED
ms_andvid_set_jvm(ajvm);
#endif /*VIDEO_ENABLED*/
#endif /*ANDROID*/
jvm=ajvm;
return JNI_VERSION_1_2;
@ -79,6 +84,9 @@ public:
vTable.global_state_changed = globalStateChange;
vTable.registration_state_changed = registrationStateChange;
vTable.call_state_changed = callStateChange;
vTable.text_received = text_received;
vTable.new_subscription_request = new_subscription_request;
vTable.notify_presence_recv = notify_presence_recv;
listernerClass = (jclass)env->NewGlobalRef(env->GetObjectClass( alistener));
/*displayStatus(LinphoneCore lc,String message);*/
@ -96,12 +104,30 @@ public:
callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));
callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");
/*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/
newSubscriptionRequestId = env->GetMethodID(listernerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");
/*void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);*/
notifyPresenceReceivedId = env->GetMethodID(listernerClass,"notifyPresenceReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;)V");
/*void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message);*/
textReceivedId = env->GetMethodID(listernerClass,"textReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneAddress;Ljava/lang/String;)V");
proxyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"));
proxyCtrId = env->GetMethodID(proxyClass,"<init>", "(J)V");
callClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCallImpl"));
callCtrId = env->GetMethodID(callClass,"<init>", "(J)V");
chatRoomClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatRoomImpl"));
chatRoomCtrId = env->GetMethodID(chatRoomClass,"<init>", "(J)V");
friendClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneFriendImpl"));;
friendCtrId =env->GetMethodID(friendClass,"<init>", "(J)V");
addressClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAddressImpl"));
addressCtrId =env->GetMethodID(addressClass,"<init>", "(J)V");
}
~LinphoneCoreData() {
@ -116,6 +142,8 @@ public:
env->DeleteGlobalRef(callStateClass);
env->DeleteGlobalRef(proxyClass);
env->DeleteGlobalRef(callClass);
env->DeleteGlobalRef(chatRoomClass);
env->DeleteGlobalRef(friendClass);
}
jobject core;
@ -124,6 +152,9 @@ public:
jclass listernerClass;
jmethodID displayStatusId;
jmethodID newSubscriptionRequestId;
jmethodID notifyPresenceReceivedId;
jmethodID textReceivedId;
jclass globalStateClass;
jmethodID globalStateId;
@ -143,6 +174,15 @@ public:
jclass callClass;
jmethodID callCtrId;
jclass chatRoomClass;
jmethodID chatRoomCtrId;
jclass friendClass;
jmethodID friendCtrId;
jclass addressClass;
jmethodID addressCtrId;
LinphoneCoreVTable vTable;
static void showInterfaceCb(LinphoneCore *lc) {
@ -211,6 +251,48 @@ public:
,env->CallStaticObjectMethod(lcData->callStateClass,lcData->callStateFromIntId,(jint)state),
message ? env->NewStringUTF(message) : NULL);
}
static void notify_presence_recv (LinphoneCore *lc, LinphoneFriend *my_friend) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM\n");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
env->CallVoidMethod(lcData->listener
,lcData->notifyPresenceReceivedId
,lcData->core
,env->NewObject(lcData->friendClass,lcData->friendCtrId,(jlong)my_friend));
}
static void new_subscription_request (LinphoneCore *lc, LinphoneFriend *my_friend, const char* url) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM\n");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
env->CallVoidMethod(lcData->listener
,lcData->newSubscriptionRequestId
,lcData->core
,env->NewObject(lcData->friendClass,lcData->friendCtrId,(jlong)my_friend)
,url ? env->NewStringUTF(url) : NULL);
}
static void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM\n");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
env->CallVoidMethod(lcData->listener
,lcData->textReceivedId
,lcData->core
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from)
,message ? env->NewStringUTF(message) : NULL);
}
};
@ -221,8 +303,8 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv*
,jstring jfactoryConfig
,jobject juserdata){
const char* userConfig = env->GetStringUTFChars(juserConfig, NULL);
const char* factoryConfig = env->GetStringUTFChars(jfactoryConfig, NULL);
const char* userConfig = juserConfig?env->GetStringUTFChars(juserConfig, NULL):NULL;
const char* factoryConfig = jfactoryConfig?env->GetStringUTFChars(jfactoryConfig, NULL):NULL;
LinphoneCoreData* ldata = new LinphoneCoreData(env,thiz,jlistener,juserdata);
#ifdef ANDROID
ms_andsnd_set_jvm(jvm);
@ -240,8 +322,8 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv*
//clear existing proxy config
linphone_core_clear_proxy_config((LinphoneCore*) nativePtr);
env->ReleaseStringUTFChars(juserConfig, userConfig);
env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig);
if (userConfig) env->ReleaseStringUTFChars(juserConfig, userConfig);
if (factoryConfig) env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig);
return nativePtr;
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env
@ -456,7 +538,48 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getCurrentCall(JNIEnv*
) {
return (jlong)linphone_core_get_current_call((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addFriend(JNIEnv* env
,jobject thiz
,jlong lc
,jlong aFriend
) {
linphone_core_add_friend((LinphoneCore*)lc,(LinphoneFriend*)aFriend);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPresenceInfo(JNIEnv* env
,jobject thiz
,jlong lc
,jint minute_away
,jstring jalternative_contact
,jint status) {
const char* alternative_contact = env->GetStringUTFChars(jalternative_contact, NULL);
linphone_core_set_presence_info((LinphoneCore*)lc,minute_away,alternative_contact,(LinphoneOnlineStatus)status);
env->ReleaseStringUTFChars(jalternative_contact, alternative_contact);
}
extern "C" long Java_org_linphone_core_LinphoneCoreImpl_createChatRoom(JNIEnv* env
,jobject thiz
,jlong lc
,jstring jto) {
const char* to = env->GetStringUTFChars(jto, NULL);
LinphoneChatRoom* lResult = linphone_core_create_chat_room((LinphoneCore*)lc,to);
env->ReleaseStringUTFChars(jto, to);
return (long)lResult;
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableVideo(JNIEnv* env
,jobject thiz
,jlong lc
,jboolean vcap_enabled
,jboolean display_enabled) {
linphone_core_enable_video((LinphoneCore*)lc, vcap_enabled,display_enabled);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isVideoEnabled(JNIEnv* env
,jobject thiz
,jlong lc) {
return linphone_core_video_enabled((LinphoneCore*)lc);
}
//ProxyConfig
@ -741,6 +864,90 @@ extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getState( JNIEnv* env
return (jint)linphone_call_get_state((LinphoneCall*)ptr);
}
//LinphoneFriend
extern "C" long Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env
,jobject thiz
,jstring jFriendUri) {
LinphoneFriend* lResult;
if (jFriendUri) {
const char* friendUri = env->GetStringUTFChars(jFriendUri, NULL);
lResult= linphone_friend_new_with_addr(friendUri);
env->ReleaseStringUTFChars(jFriendUri, friendUri);
} else {
lResult = linphone_friend_new();
}
return (long)lResult;
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setAddress(JNIEnv* env
,jobject thiz
,jlong ptr
,jlong linphoneAddress) {
linphone_friend_set_addr((LinphoneFriend*)ptr,(LinphoneAddress*)linphoneAddress);
}
extern "C" long Java_org_linphone_core_LinphoneFriendImpl_getAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (long)linphone_friend_get_address((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setIncSubscribePolicy(JNIEnv* env
,jobject thiz
,jlong ptr
,jint policy) {
linphone_friend_set_inc_subscribe_policy((LinphoneFriend*)ptr,(LinphoneSubscribePolicy)policy);
}
extern "C" jint Java_org_linphone_core_LinphoneFriendImpl_getIncSubscribePolicy(JNIEnv* env
,jobject thiz
,jlong ptr) {
return linphone_friend_get_inc_subscribe_policy((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_enableSubscribes(JNIEnv* env
,jobject thiz
,jlong ptr
,jboolean value) {
linphone_friend_enable_subscribes((LinphoneFriend*)ptr,value);
}
extern "C" jboolean Java_org_linphone_core_LinphoneFriendImpl_isSubscribesEnabled(JNIEnv* env
,jobject thiz
,jlong ptr) {
return linphone_friend_subscribes_enabled((LinphoneFriend*)ptr);
}
extern "C" jboolean Java_org_linphone_core_LinphoneFriendImpl_getStatus(JNIEnv* env
,jobject thiz
,jlong ptr) {
return linphone_friend_get_status((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_edit(JNIEnv* env
,jobject thiz
,jlong ptr) {
return linphone_friend_edit((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_done(JNIEnv* env
,jobject thiz
,jlong ptr) {
linphone_friend_done((LinphoneFriend*)ptr);
}
//LinphoneChatRoom
extern "C" long Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (long) linphone_chat_room_get_peer_address((LinphoneChatRoom*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage(JNIEnv* env
,jobject thiz
,jlong ptr
,jstring jmessage) {
const char* message = env->GetStringUTFChars(jmessage, NULL);
linphone_chat_room_send_message((LinphoneChatRoom*)ptr,message);
env->ReleaseStringUTFChars(jmessage, message);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoWindowId(JNIEnv* env
,jobject thiz
,jlong lc
,jobject obj) {
linphone_core_set_native_video_window_id((LinphoneCore*)lc,(unsigned long)obj);
ms_message("linphone_core_set_native_video_window_id() called !!!!!!!");
}

View file

@ -754,14 +754,10 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
}
int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
if (dest==NULL) {
if (type==AF_INET)
dest="87.98.157.38"; /*a public IP address*/
else dest="2a00:1450:8002::68";
}
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
#ifdef HAVE_GETIFADDRS
{
if (dest==NULL) {
/*we use getifaddrs for lookup of default interface */
int found_ifs;
found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE);
@ -774,5 +770,33 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
}
#endif
/*else use connect to find the best local ip address */
if (type==AF_INET)
dest="87.98.157.38"; /*a public IP address*/
else dest="2a00:1450:8002::68";
return get_local_ip_for_with_connect(type,dest,result);
}
#ifndef WIN32
#include <resolv.h>
void _linphone_core_configure_resolver(){
/*bionic declares _res but does not define nor export it !!*/
#ifdef ANDROID
/*timeout and attempts are the same as retrans and retry, but are android specific names.*/
setenv("RES_OPTIONS","timeout:1 attempts:2 retrans:1 retry:2",1);
#else
res_init();
_res.retrans=1; /*retransmit every second*/
_res.retry=2; /*only two times per DNS server*/
#endif
}
#else
void _linphone_core_configure_resolver(){
}
#endif

View file

@ -57,6 +57,7 @@
struct _LinphoneCallParams{
LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */
bool_t has_video;
bool_t pad[3];
};
@ -76,6 +77,7 @@ struct _LinphoneCall
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*/
LinphoneCallState state;
LinphoneReason reason;
int refcnt;
void * user_pointer;
int audio_port;
@ -196,9 +198,9 @@ void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float
void linphone_core_stop_waiting(LinphoneCore *lc);
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
void linphone_core_start_pending_refered_calls(LinphoneCore *lc);
void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call);
extern SalCallbacks linphone_sal_callbacks;
void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneError error);
void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg, LinphoneReason error);
struct _LinphoneProxyConfig
{
@ -223,7 +225,7 @@ struct _LinphoneProxyConfig
bool_t dial_escape_plus;
void* user_data;
time_t deletion_date;
LinphoneError error;
LinphoneReason error;
};
struct _LinphoneAuthInfo
@ -438,6 +440,7 @@ SalMediaDescription *create_local_media_description(LinphoneCore *lc,
LinphoneCall *call, bool_t with_video, bool_t only_one_codec);
#define linphone_core_ready(lc) ((lc)->state!=LinphoneGlobalStartup)
void _linphone_core_configure_resolver();
#define HOLD_OFF (0)
#define HOLD_ON (1)

View file

@ -841,10 +841,12 @@ LinphoneRegistrationState linphone_proxy_config_get_state(const LinphoneProxyCon
}
return NULL;
}
LinphoneError linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg) {
LinphoneReason linphone_proxy_config_get_error(const LinphoneProxyConfig *cfg) {
return cfg->error;
}
void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneError error) {
void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg,LinphoneReason error) {
cfg->error = error;
}

View file

@ -282,8 +282,11 @@ int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optio
int sal_call_hold(SalOp *h, bool_t holdon);
int sal_call_update(SalOp *h);
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
int sal_refer(SalOp *h, const char *refer_to);
int sal_refer_accept(SalOp *h);
int sal_call_refer(SalOp *h, const char *refer_to);
int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h);
int sal_call_accept_refer(SalOp *h);
/*informs this call is consecutive to an incoming refer */
int sal_call_set_referer(SalOp *h, SalOp *refered_call);
/* returns the SalOp of a call that should be replaced by h, if any */
SalOp *sal_call_get_replaces(SalOp *h);
int sal_call_send_dtmf(SalOp *h, char dtmf);

View file

@ -162,6 +162,7 @@ SalOp * sal_op_new(Sal *sal){
op->reinvite=FALSE;
op->call_id=NULL;
op->replaces=NULL;
op->referred_by=NULL;
op->masquerade_via=FALSE;
op->auto_answer_asked=FALSE;
return op;
@ -205,6 +206,9 @@ void sal_op_release(SalOp *op){
if (op->replaces){
ms_free(op->replaces);
}
if (op->referred_by){
ms_free(op->referred_by);
}
__sal_op_free(op);
}
@ -494,6 +498,12 @@ int sal_call(SalOp *h, const char *from, const char *to){
h->sdp_offering=TRUE;
set_sdp_from_desc(invite,h->base.local_media);
}else h->sdp_offering=FALSE;
if (h->replaces){
osip_message_set_header(invite,"Replaces",h->replaces);
if (h->referred_by)
osip_message_set_header(invite,"Referred-By",h->referred_by);
}
eXosip_lock();
err=eXosip_call_send_initial_invite(invite);
eXosip_unlock();
@ -610,6 +620,14 @@ SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
return h->result;
}
int sal_call_set_referer(SalOp *h, SalOp *refered_call){
if (refered_call->replaces)
h->replaces=ms_strdup(refered_call->replaces);
if (refered_call->referred_by)
h->referred_by=ms_strdup(refered_call->referred_by);
return 0;
}
int sal_ping(SalOp *op, const char *from, const char *to){
osip_message_t *options=NULL;
@ -628,7 +646,7 @@ int sal_ping(SalOp *op, const char *from, const char *to){
return -1;
}
int sal_refer_accept(SalOp *op){
int sal_call_accept_refer(SalOp *op){
osip_message_t *msg=NULL;
int err=0;
eXosip_lock();
@ -648,7 +666,7 @@ int sal_refer_accept(SalOp *op){
return err;
}
int sal_refer(SalOp *h, const char *refer_to){
int sal_call_refer(SalOp *h, const char *refer_to){
osip_message_t *msg=NULL;
int err=0;
eXosip_lock();
@ -659,6 +677,24 @@ int sal_refer(SalOp *h, const char *refer_to){
return err;
}
int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h){
osip_message_t *msg=NULL;
char referto[256]={0};
int err=0;
eXosip_lock();
if (eXosip_call_get_referto(other_call_h->did,referto,sizeof(referto)-1)!=0){
ms_error("eXosip_call_get_referto() failed for did=%i",other_call_h->did);
eXosip_unlock();
return -1;
}
eXosip_call_build_refer(h->did,referto, &msg);
osip_message_set_header(msg,"Referred-By",h->base.from);
if (msg) err=eXosip_call_send_request(h->did, msg);
else err=-1;
eXosip_unlock();
return err;
}
SalOp *sal_call_get_replaces(SalOp *h){
if (h->replaces!=NULL){
int cid;
@ -1240,6 +1276,59 @@ static void process_dtmf_relay(Sal *sal, eXosip_event_t *ev){
}
}
static void fill_options_answer(osip_message_t *options){
osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
osip_message_set_accept(options,"application/sdp");
}
static void process_refer(Sal *sal, SalOp *op, eXosip_event_t *ev){
osip_header_t *h=NULL;
osip_message_t *ans=NULL;
ms_message("Receiving REFER request !");
osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
if (h){
osip_from_t *from=NULL;
char *tmp;
osip_from_init(&from);
if (osip_from_parse(from,h->hvalue)==0){
if (op ){
osip_uri_header_t *uh=NULL;
osip_header_t *referred_by=NULL;
osip_uri_header_get_byname(&from->url->url_headers,(char*)"Replaces",&uh);
if (uh!=NULL && uh->gvalue && uh->gvalue[0]!='\0'){
ms_message("Found replaces in Refer-To");
if (op->replaces){
ms_free(op->replaces);
}
op->replaces=ms_strdup(uh->gvalue);
}
osip_message_header_get_byname(ev->request,"Referred-By",0,&referred_by);
if (referred_by && referred_by->hvalue && referred_by->hvalue[0]!='\0'){
if (op->referred_by)
ms_free(op->referred_by);
op->referred_by=ms_strdup(referred_by->hvalue);
}
}
osip_uri_header_freelist(&from->url->url_headers);
osip_from_to_str(from,&tmp);
sal->callbacks.refer_received(sal,op,tmp);
osip_free(tmp);
osip_from_free(from);
}
eXosip_lock();
eXosip_call_build_answer(ev->tid,202,&ans);
if (ans)
eXosip_call_send_answer(ev->tid,202,ans);
eXosip_unlock();
}
else
{
ms_warning("cannot do anything with the refer without destination\n");
}
}
static void call_message_new(Sal *sal, eXosip_event_t *ev){
osip_message_t *ans=NULL;
if (ev->request){
@ -1268,8 +1357,7 @@ static void call_message_new(Sal *sal, eXosip_event_t *ev){
eXosip_call_send_answer(ev->tid,200,ans);
eXosip_unlock();
}
}
if(MSG_IS_MESSAGE(ev->request)){
}else if(MSG_IS_MESSAGE(ev->request)){
/* SIP messages could be received into call */
text_received(sal, ev);
eXosip_lock();
@ -1277,27 +1365,12 @@ static void call_message_new(Sal *sal, eXosip_event_t *ev){
if (ans)
eXosip_call_send_answer(ev->tid,200,ans);
eXosip_unlock();
}
if(MSG_IS_REFER(ev->request)){
osip_header_t *h=NULL;
}else if(MSG_IS_REFER(ev->request)){
SalOp *op=find_op(sal,ev);
ms_message("Receiving REFER request !");
osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
eXosip_lock();
eXosip_call_build_answer(ev->tid,202,&ans);
if (ans)
eXosip_call_send_answer(ev->tid,202,ans);
eXosip_unlock();
if (h){
sal->callbacks.refer_received(sal,op,h->hvalue);
}
else
{
ms_warning("cannot do anything with the refer without destination\n");
}
}
if(MSG_IS_NOTIFY(ev->request)){
process_refer(sal,op,ev);
}else if(MSG_IS_NOTIFY(ev->request)){
osip_header_t *h=NULL;
char *from=NULL;
SalOp *op=find_op(sal,ev);
@ -1314,6 +1387,14 @@ static void call_message_new(Sal *sal, eXosip_event_t *ev){
eXosip_call_send_answer(ev->tid,200,ans);
eXosip_unlock();
osip_free(from);
}else if (MSG_IS_OPTIONS(ev->request)){
eXosip_lock();
eXosip_call_build_answer(ev->tid,200,&ans);
if (ans){
fill_options_answer(ans);
eXosip_call_send_answer(ev->tid,200,ans);
}
eXosip_unlock();
}
}else ms_warning("call_message_new: No request ?");
}
@ -1362,6 +1443,8 @@ static void text_received(Sal *sal, eXosip_event_t *ev){
osip_free(from);
}
static void other_request(Sal *sal, eXosip_event_t *ev){
ms_message("in other_request");
if (ev->request==NULL) return;
@ -1371,8 +1454,7 @@ static void other_request(Sal *sal, eXosip_event_t *ev){
}else if (strcmp(ev->request->sip_method,"OPTIONS")==0){
osip_message_t *options=NULL;
eXosip_options_build_answer(ev->tid,200,&options);
osip_message_set_allow(options,"INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, SUBSCRIBE, NOTIFY, INFO");
osip_message_set_accept(options,"application/sdp");
fill_options_answer(options);
eXosip_options_send_answer(ev->tid,200,options);
}else if (strcmp(ev->request->sip_method,"WAKEUP")==0
&& comes_from_local_if(ev->request)) {
@ -1382,12 +1464,7 @@ static void other_request(Sal *sal, eXosip_event_t *ev){
}else if (strncmp(ev->request->sip_method, "REFER", 5) == 0){
ms_message("Receiving REFER request !");
if (comes_from_local_if(ev->request)) {
osip_header_t *h=NULL;
osip_message_header_get_byname(ev->request,"Refer-To",0,&h);
eXosip_message_send_answer(ev->tid,200,NULL);
if (h){
sal->callbacks.refer_received(sal,NULL,h->hvalue);
}
process_refer(sal,NULL,ev);
}else ms_warning("Ignored REFER not coming from this local loopback interface.");
}else if (strncmp(ev->request->sip_method, "UPDATE", 6) == 0){
inc_update(sal,ev);

View file

@ -57,6 +57,7 @@ struct SalOp{
osip_call_id_t *call_id; /*used for out of calls transaction in order
to retrieve the operation when receiving a response*/
char *replaces;
char *referred_by;
bool_t supports_session_timers;
bool_t sdp_offering;
bool_t reinvite;

View file

@ -20,6 +20,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal_eXosip2.h"
typedef enum {
PIDF = 0,
RFCxxxx = 1,
MSOLDPRES = 2
} presence_type_t;
/*
* REVISIT: this static variable forces every dialog to use the same presence description type depending
* on what is received on a single dialog...
*/
static presence_type_t presence_style = PIDF;
SalOp * sal_find_out_subscribe(Sal *sal, int sid){
const MSList *elem;
@ -175,268 +186,372 @@ int sal_subscribe_decline(SalOp *op){
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;
static void mk_presence_body (const SalPresenceStatus online_status, const char *contact_info,
char *buf, size_t buflen, presence_type_t ptype) {
switch (ptype) {
case RFCxxxx: {
/* definition from http://msdn.microsoft.com/en-us/library/cc246202%28PROT.10%29.aspx */
int atom_id = 1000;
osip_from_t *from=NULL;
from=osip_message_get_from(notify);
osip_uri_to_str(from->url,&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\
if (online_status==SalPresenceOnline)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\
<address uri=\"%s\" 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\
}
else if (online_status == SalPresenceBusy ||
online_status == SalPresenceDonotdisturb)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"inuse\" />\n\
<msnsubstatus substatus=\"busy\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
</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\
}
else if (online_status==SalPresenceBerightback)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\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\
}
else if (online_status == SalPresenceAway ||
online_status == SalPresenceMoved)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\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\
}
else if (online_status==SalPresenceOnthephone)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\
<address uri=\"%s\" 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\
}
else if (online_status==SalPresenceOuttolunch)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\
<address uri=\"%s\" priority=\"0.800000\">\n\
<status status=\"open\" />\n\
<msnsubstatus substatus=\"outtolunch\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence 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\" priority=\"0.800000\">\n\
<status status=\"closed\" />\n\
<msnsubstatus substatus=\"away\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
break;
}
case MSOLDPRES: {
/* Couldn't find schema http://schemas.microsoft.com/2002/09/sip/presence
* so messages format has been taken from Communigate that can send notify
* requests with this schema
*/
int atom_id = 1000;
if (online_status==SalPresenceOnline)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\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 ||
online_status == SalPresenceDonotdisturb)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\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)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\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 ||
online_status == SalPresenceMoved)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\n\
<status status=\"inactive\" />\n\
<msnsubstatus substatus=\"idle\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
else if (online_status==SalPresenceOnthephone)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\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)
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\n\
<presence>\n\
<presentity uri=\"%s;method=SUBSCRIBE\" />\n\
<atom id=\"%i\">\n\
<address uri=\"%s\">\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\
}
else
{
snprintf(buf, buflen, "<?xml version=\"1.0\"?>\n\
<!DOCTYPE presence SYSTEM \"http://schemas.microsoft.com/2002/09/sip/presence\">\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 uri=\"%s\">\n\
<status status=\"closed\" />\n\
<msnsubstatus substatus=\"offline\" />\n\
</address>\n\
</atom>\n\
</presence>", contact_info, atom_id, contact_info);
}
}
break;
}
default: { /* use pidf+xml as default format, rfc4479, rfc4480, rfc3863 */
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify, "application/xpidf+xml");
#else
if (online_status==SalPresenceOnline)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status == SalPresenceBusy ||
online_status == SalPresenceDonotdisturb)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:busy/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==SalPresenceBerightback)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:in-transit/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status == SalPresenceAway ||
online_status == SalPresenceMoved)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:away/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==SalPresenceOnthephone)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"sg89aep\">\n\
<rpid:activities><rpid:on-the-phone/></rpid:activities>\n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else if (online_status==SalPresenceOuttolunch)
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"7777\">\n\
<status><basic>open</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
<dm:person id=\"78787878\">\n\
<rpid:activities><rpid:meal/></rpid:activities>\n\
<rpid:note>Out to lunch</rpid:note> \n\
</dm:person>\n\
</presence>",
contact_info, contact_info);
}
else
{
snprintf(buf, buflen, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \
xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\" \
xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\" \
entity=\"%s\">\n\
<tuple id=\"sg89ae\">\n\
<status><basic>closed</basic></status>\n\
<contact priority=\"0.8\">%s</contact>\n\
</tuple>\n\
</presence>\n", contact_info, contact_info);
}
break;
}
} // switch
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");
}
static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status)
{
char buf[1000];
char *contact_info;
osip_from_t *from=NULL;
from=osip_message_get_from(notify);
osip_uri_to_str(from->url,&contact_info);
mk_presence_body (online_status, contact_info, buf, sizeof (buf), presence_style);
osip_message_set_body(notify, buf, strlen(buf));
osip_message_set_content_type(notify,
presence_style ? "application/xpidf+xml" : "application/pidf+xml");
#endif
osip_free(contact_info);
}
@ -483,137 +598,10 @@ int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus p
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");
}
mk_presence_body (presence_mode, from, buf, sizeof (buf), presence_style);
i = eXosip_build_publish(&pub,from, to, NULL, "presence", "1800", "application/pidf+xml", buf);
i = eXosip_build_publish(&pub,from, to, NULL, "presence", "300",
presence_style ? "application/xpidf+xml" : "application/pidf+xml", buf);
if (i<0){
ms_warning("Failed to build publish request.");
return -1;
@ -627,6 +615,7 @@ int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus p
ms_message("Failed to send publish request.");
return -1;
}
sal_add_other(sal_op_get_sal(op),op,pub);
return 0;
}
@ -698,7 +687,8 @@ void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
}else if (strstr(body->body,"berightback")!=NULL
|| strstr(body->body,"in-transit")!=NULL ){
estatus=SalPresenceBerightback;
}else if (strstr(body->body,"away")!=NULL){
}else if (strstr(body->body,"away")!=NULL
|| strstr(body->body,"idle")){
estatus=SalPresenceAway;
}else if (strstr(body->body,"onthephone")!=NULL
|| strstr(body->body,"on-the-phone")!=NULL){
@ -721,6 +711,15 @@ void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){
ms_message("And outgoing subscription terminated by remote.");
}
sal->callbacks.notify_presence(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL);
/* try to detect presence message style used by server,
* and switch our presence messages to servers style */
if (strstr (body->body, "//IETF//DTD RFCxxxx XPIDF 1.0//EN") != NULL) {
presence_style = RFCxxxx;
} else if (strstr(body->body,"http://schemas.microsoft.com/2002/09/sip/presence")!=NULL) {
presence_style = MSOLDPRES;
}
osip_free(tmp);
}

View file

@ -17,7 +17,16 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* Object that represents a SIP address.
* The LinphoneAddress is an opaque object to represents SIP addresses, ie the content of SIP's 'from' and 'to' headers.
* A SIP address is made of display name, username, domain name, port, and various uri headers (such as tags).
* It looks like 'Alice <sip:alice@example.net>'. The LinphoneAddress has methods to extract and manipulate all parts of the address.
* When some part of the address (for example the username) is empty, the accessor methods return null.
* <br> Can be instanciated using both {@link LinphoneCoreFactory#createLinphoneAddress(String, String, String)} or {@link LinphoneCoreFactory#createLinphoneAddress(String)}
* @author jehanmonnier
*
*/
public interface LinphoneAddress {
/**
* Human display name
@ -58,6 +67,9 @@ public interface LinphoneAddress {
*/
public String asStringUriOnly();
/*must return the same thing as asString()*/
/**
* same as {@link #asString()}
*
* */
public String toString();
}

View file

@ -17,13 +17,51 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* Object holding authentication information.
* In most case, authentication information consists of a username and password. Sometimes, a userid is required by proxy, and realm can be useful to discriminate different SIP domains.
*<br>This object is instanciated using {@link LinphoneCoreFactory#createAuthInfo(String, String, String)}.
*<br>
*Once created and filled, a LinphoneAuthInfo must be added to the LinphoneCore in order to become known and used automatically when needed.
*Use {@link LinphoneCore#addAuthInfo(LinphoneAuthInfo)} for that purpose.
*<br>
*The LinphoneCore object can take the initiative to request authentication information when needed to the application
*through the {@link LinphoneCoreListener#authInfoRequested(LinphoneCore, String, String)} listener.
*<br>
*The application can respond to this information request later using {@link LinphoneCore#addAuthInfo(LinphoneAuthInfo)}.
*This will unblock all pending authentication transactions and retry them with authentication headers.
*
*/
public interface LinphoneAuthInfo {
/**
* get user name
* @return username
*/
String getUsername();
String getPassword();
String getRealm();
/**
* Sets the username.
* @param username
*/
void setUsername(String username);
/**
* get password
* @return password
*/
String getPassword();
/**
* sets password
* @param password
*/
void setPassword(String password);
/**
* get realm
* @return
*/
String getRealm();
/**
* set realm
* @param realm
*/
void setRealm(String realm);
}

View file

@ -20,26 +20,78 @@ package org.linphone.core;
import java.util.Vector;
/**
* Object representing a Call. calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or paased to the application by listener {@link LinphoneCoreListener#callState(LinphoneCore, LinphoneCall, State, String)}
*
*/
public interface LinphoneCall {
/**
* Linphone call states
*
*/
static class State {
static private Vector values = new Vector();
private final int mValue;
private final String mStringValue;
/**
* Idle
*/
public final static State Idle = new State(0,"Idle");
/**
* Incoming call received.
*/
public final static State IncomingReceived = new State(1,"IncomingReceived");
/**
* Outgoing call initialiazed.
*/
public final static State OutgoingInit = new State(2,"OutgoingInit");
/**
* Outgoing call in progress.
*/
public final static State OutgoingProgress = new State(3,"OutgoingProgress");
/**
* Outgoing call ringing.
*/
public final static State OutgoingRinging = new State(4,"OutgoingRinging");
/**
* Outgoing call early media
*/
public final static State OutgoingEarlyMedia = new State(5,"OutgoingEarlyMedia");
/**
* Connected
*/
public final static State Connected = new State(6,"Connected");
/**
* Streams running
*/
public final static State StreamsRunning = new State(7,"StreamsRunning");
/**
* Paussing
*/
public final static State Pausing = new State(8,"Pausing");
/**
* Paused
*/
public final static State Paused = new State(9,"Paused");
/**
* Resuming
*/
public final static State Resuming = new State(10,"Resuming");
/**
* Refered
*/
public final static State Refered = new State(11,"Refered");
/**
* Error
*/
public final static State Error = new State(12,"Error");
/**
* Call end
*/
public final static State CallEnd = new State(13,"CallEnd");
/**
* Paused by remote
*/
public final static State PausedByRemote = new State(14,"PausedByRemote");
private State(int value,String stringValue) {
mValue = value;
@ -69,10 +121,14 @@ public interface LinphoneCall {
*
**/
public LinphoneAddress getRemoteAddress();
/**
* get direction of the call (incoming or outgoing).
* @return CallDirection
*/
public CallDirection getDirection();
/**
* Returns the call log associated to this call.
* get the call log associated to this call.
* @Return LinphoneCallLog
**/
public LinphoneCallLog getCallLog();

View file

@ -17,13 +17,25 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* Call data records object
*
*/
public interface LinphoneCallLog {
/**
* Originator of the call as a LinphoneAddress object.
* @return LinphoneAddress
*/
public LinphoneAddress getFrom();
/**
* Destination of the call as a LinphoneAddress object.
* @return
*/
public LinphoneAddress getTo ();
/**
* The direction of the call
* @return CallDirection
*/
public CallDirection getDirection();
}

View file

@ -0,0 +1,39 @@
/*
LinphoneChatRoom.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
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.
*/
package org.linphone.core;
/**
*
* A chat room is the place where text messages are exchanged.
Can be created by linphone_core_create_chat_room().
*
*/
public interface LinphoneChatRoom {
/**
* get peer address associated to this LinphoneChatRoom
*
* @return LinphoneAddress peer address
*/
LinphoneAddress getPeerAddress();
/**
* send a message to peer member of this chat room.
* @param message to be sent
*/
void sendMessage(String message);
}

View file

@ -21,17 +21,31 @@ package org.linphone.core;
import java.util.Vector;
/**
* Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}.
*
*/
public interface LinphoneCore {
/*
/**
* linphone core states
*/
static public class GlobalState {
static private Vector values = new Vector();
/**
* Off
*/
static public GlobalState GlobalOff = new GlobalState(0,"GlobalOff");
/**
* Startup
*/
static public GlobalState GlobalStartup = new GlobalState(1,"GlobalStartup");
/**
* On
*/
static public GlobalState GlobalOn = new GlobalState(2,"GlobalOn");
/**
* Shutdown
*/
static public GlobalState GlobalShutdown = new GlobalState(3,"GlobalShutdown");
private final int mValue;
@ -54,12 +68,31 @@ public interface LinphoneCore {
return mStringValue;
}
}
/**
* Describes proxy registration states.
*
*/
static public class RegistrationState {
static private Vector values = new Vector();
/**
* None
*/
static public RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone");
/**
* In Progress
*/
static public RegistrationState RegistrationProgress = new RegistrationState(1,"RegistrationProgress");
/**
* Ok
*/
static public RegistrationState RegistrationOk = new RegistrationState(2,"RegistrationOk");
/**
* Cleared
*/
static public RegistrationState RegistrationCleared = new RegistrationState(3,"RegistrationCleared");
/**
* Failed
*/
static public RegistrationState RegistrationFailed = new RegistrationState(4,"RegistrationFailed");
private final int mValue;
private final String mStringValue;
@ -81,8 +114,18 @@ public interface LinphoneCore {
return mStringValue;
}
}
/**
* Signaling transports
*
*/
static public class Transport {
/**
* UDP transport
*/
public final static Transport udp =new Transport("udp");
/**
* TCP transport
*/
public final static Transport tcp =new Transport("tcp");
private final String mStringValue;
@ -94,15 +137,26 @@ public interface LinphoneCore {
}
}
/**
* clear all added proxy config
* clear all added proxy configs
*/
public void clearProxyConfigs();
/**
* Add a proxy configuration. This will start registration on the proxy, if registration is enabled.
* @param proxyCfg
* @throws LinphoneCoreException
*/
public void addProxyConfig(LinphoneProxyConfig proxyCfg) throws LinphoneCoreException;
/**
* Sets the default proxy.
*<br>
* This default proxy must be part of the list of already entered {@link LinphoneProxyConfig}.
* Toggling it as default will make LinphoneCore use the identity associated with the proxy configuration in all incoming and outgoing calls.
* @param proxyCfg
*/
public void setDefaultProxyConfig(LinphoneProxyConfig proxyCfg);
/**
* get he default proxy configuration, that is the one used to determine the current identity.
* @return null if no default proxy config
*/
public LinphoneProxyConfig getDefaultProxyConfig() ;
@ -111,7 +165,11 @@ public interface LinphoneCore {
* clear all the added auth info
*/
void clearAuthInfos();
/**
* Adds authentication information to the LinphoneCore.
* <br>This information will be used during all SIP transacations that require authentication.
* @param info
*/
void addAuthInfo(LinphoneAuthInfo info);
/**
@ -123,13 +181,22 @@ public interface LinphoneCore {
public LinphoneAddress interpretUrl(String destination) throws LinphoneCoreException;
/**
* Starts a call given a destination. Internally calls interpretUrl() then invite(LinphoneAddress).
* Starts a call given a destination. Internally calls {@link #interpretUrl(String)} then {@link #invite(LinphoneAddress)}.
* @param uri
*/
public LinphoneCall invite(String destination)throws LinphoneCoreException;
/**
* Initiates an outgoing call given a destination LinphoneAddress
*<br>The LinphoneAddress can be constructed directly using linphone_address_new(), or created by linphone_core_interpret_url(). The application doesn't own a reference to the returned LinphoneCall object. Use linphone_call_ref() to safely keep the LinphoneCall pointer valid within your application.
* @param to the destination of the call (sip address).
* @return LinphoneCall
* @throws LinphoneCoreException
*/
public LinphoneCall invite(LinphoneAddress to)throws LinphoneCoreException;
/**
* Terminates a call.
* @param aCall to be terminated
*/
public void terminateCall(LinphoneCall aCall);
/**
* Returns The LinphoneCall the current call if one is in call
@ -152,6 +219,17 @@ public interface LinphoneCore {
* @return Returns true if in incoming call is pending, ie waiting for being answered or declined.
*/
public boolean isInComingInvitePending();
/**
* Main loop function. It is crucial that your application call it periodically.
*
* #iterate() performs various backgrounds tasks:
* <li>receiving of SIP messages
* <li> handles timers and timeout
* <li> performs registration to proxies
* <li> authentication retries The application MUST call this function from periodically, in its main loop.
* <br> Be careful that this function must be call from the same thread as other liblinphone methods. In not the case make sure all liblinphone calls are serialized with a mutex.
*/
public void iterate();
/**
* Accept an incoming call.
@ -232,28 +310,86 @@ public interface LinphoneCore {
public void stopDtmf();
/**
*
* remove all call logs
*/
public void clearCallLogs();
/***
* get payload type from mime type an clock rate
*
* return null if not found
*/
public PayloadType findPayloadType(String mime,int clockRate);
/**
* not implemented yet
* @param pt
* @param enable
* @throws LinphoneCoreException
*/
public void enablePayloadType(PayloadType pt, boolean enable) throws LinphoneCoreException;
/**
* Enables or disable echo cancellation.
* @param enable
*/
public void enableEchoCancellation(boolean enable);
/**
* get EC status
* @return true if echo cancellation is enabled.
*/
public boolean isEchoCancellationEnabled();
/**
* not implemented yet
* @param aTransport
*/
public void setSignalingTransport(Transport aTransport);
/**
* not implemented
* @param value
*/
public void enableSpeaker(boolean value);
/**
* not implemented
* @return
*/
public boolean isSpeakerEnabled();
/**
* add a friend to the current buddy list, if subscription attribute is set, a SIP SUBSCRIBE message is sent.
* @param lf LinphoenFriend to add
* @throws LinphoneCoreException
*/
void addFriend(LinphoneFriend lf) throws LinphoneCoreException;
/**
* Set my presence status
* @param minute_away how long in away
* @param status sip uri used to redirect call in state LinphoneStatusMoved
*/
void setPresenceInfo(int minute_away,String alternative_contact, OnlineStatus status);
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
* @param to destination address for messages
*
* @return {@link LinphoneChatRoom} where messaging can take place.
*/
LinphoneChatRoom createChatRoom(String to);
public void setVideoWindow(Object w);
public void setPreviewWindow(Object w);
/**
* Enables video globally.
*
*
* This function does not have any effect during calls. It just indicates #LinphoneCore to
* initiate future calls with video or not. The two boolean parameters indicate in which
* direction video is enabled. Setting both to false disables video entirely.
*
* @param vcap_enabled indicates whether video capture is enabled
* @param display_enabled indicates whether video display should be shown
*
**/
void enableVideo(boolean vcap_enabled, boolean display_enabled);
/**
* Returns TRUE if video is enabled, FALSE otherwise.
*
***/
boolean isVideoEnabled();
}

View file

@ -21,6 +21,7 @@ package org.linphone.core;
abstract public class LinphoneCoreFactory {
private static String factoryName = "org.linphone.core.LinphoneCoreFactoryImpl";
@ -49,9 +50,21 @@ abstract public class LinphoneCoreFactory {
abstract public LinphoneAuthInfo createAuthInfo(String username,String password, String realm);
abstract public LinphoneCore createLinphoneCore(LinphoneCoreListener listener, String userConfig,String factoryConfig,Object userdata) throws LinphoneCoreException;
abstract public LinphoneCore createLinphoneCore(LinphoneCoreListener listener) throws LinphoneCoreException;
/**
* Constructs a LinphoneAddress object
* @param username
* @param domain
* @param displayName
* @return
*/
abstract public LinphoneAddress createLinphoneAddress(String username,String domain,String displayName);
/**
* Constructs a LinphoneAddress object by parsing the user supplied address, given as a string.
* @param address should be like sip:joe@sip.linphone.org
* @return
*/
abstract public LinphoneAddress createLinphoneAddress(String address);
abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException;
@ -62,4 +75,17 @@ abstract public class LinphoneCoreFactory {
abstract public void setDebugMode(boolean enable);
abstract public void setLogHandler(LinphoneLogHandler handler);
/**
* Create a LinphoneFriend, similar to {@link #createLinphoneFriend()} + {@link LinphoneFriend#setAddress(LinphoneAddress)}
* @param friendUri a buddy address, must be a sip uri like sip:joe@sip.linphone.org
* @return a new LinphoneFriend with address initialized
*/
abstract public LinphoneFriend createLinphoneFriend(String friendUri);
/**
* Create a new LinphoneFriend
* @return
*/
abstract public LinphoneFriend createLinphoneFriend();
}

View file

@ -19,15 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
package org.linphone.core;
/**
*
*This interface holds all callbacks that the application should implement. None is mandatory.
*/
public interface LinphoneCoreListener {
/**< Notifies the application that it should show up
* @return */
public void show(LinphoneCore lc);
/**< Notify calls terminated by far end
* @return */
public void byeReceived(LinphoneCore lc,String from);
/**< Ask the application some authentication information
* @return */
public void authInfoRequested(LinphoneCore lc,String realm,String username);
@ -55,5 +55,28 @@ public interface LinphoneCoreListener {
* Registration state notification
* */
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState cstate, String smessage);
/**
* Reports that a new subscription request has been received and wait for a decision.
*Status on this subscription request is notified by changing policy for this friend
*@param lc LinphoneCore
*@param lf LinphoneFriend corresponding to the subscriber
*@param url of the subscriber
*
*/
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url);
/**
* Report status change for a friend previously added to LinphoneCore.
* @param lc LinphoneCore
* @param lf updated LinphoneFriend
*/
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);
/**
* invoked when a new text message is received
* @param lc LinphoneCore
* @param room LinphoneChatRoom involved in this conversation. Can be be created by the framework in case the from is not present in any chat room.
* @param from LinphoneAddress from
* @param message incoming message
*/
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message);
}

View file

@ -0,0 +1,122 @@
/*
LinphoneFriend.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
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.
*/
package org.linphone.core;
import java.util.Vector;
/**
* Represents a buddy, all presence actions like subscription and status change notification are performed on this object
*
*
*/
public interface LinphoneFriend {
/**
* Enum controlling behavior for incoming subscription request.
* Use by {@link LinphoneFriend#setIncSubscribePolicy()}
*
*/
static class SubscribePolicy {
static private Vector values = new Vector();
protected final int mValue;
private final String mStringValue;
/**
* Does not automatically accept an incoming subscription request.
* This policy implies that a decision has to be taken for each incoming subscription request notified by {@link LinphoneCoreListener#newSubscriptionRequest(LinphoneCore, LinphoneFriend, String)}
*/
public final static SubscribePolicy SPWait = new SubscribePolicy(0,"SPWait");
/**
* Rejects incoming subscription request.
*/
public final static SubscribePolicy SPDeny = new SubscribePolicy(1,"SPDeny");
/**
* Automatically accepts a subscription request.
*/
public final static SubscribePolicy SPAccept = new SubscribePolicy(2,"SPAccept");
private SubscribePolicy(int value,String stringValue) {
mValue = value;
values.addElement(this);
mStringValue=stringValue;
}
public static SubscribePolicy fromInt(int value) {
for (int i=0; i<values.size();i++) {
SubscribePolicy policy = (SubscribePolicy) values.elementAt(i);
if (policy.mValue == value) return policy;
}
throw new RuntimeException("Policy not found ["+value+"]");
}
public String toString() {
return mStringValue;
}
}
/**
* Set a {@link LinphoneAddress } for this friend
* @param anAddress
*/
void setAddress(LinphoneAddress anAddress);
/**
* get address of this friend
* @return
*/
LinphoneAddress getAddress();
/**
* Configure incoming subscription policy for this friend.
* @param policy to apply
*/
void setIncSubscribePolicy(SubscribePolicy policy);
/**
* get current subscription policy for this LinphoneFriend
* @return
*/
SubscribePolicy getIncSubscribePolicy();
/**
* Configure LinphoneFriend to subscribe to presence information
* @param enable if true this friend will receive subscription message
*/
void enableSubscribes(boolean enable);
/**
* get subscription flag value
* @return true is subscription is activated for this friend.
*/
boolean isSubscribesEnabled();
/**
* get friend status
* @return
*/
OnlineStatus getStatus();
/**
* Starts editing a friend configuration.
*<br> Because friend configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify friend configuration (such as address or subscription policy and so on).
*Once the modifications are done, then the application must call {@link #done()} to commit the changes.
*/
void edit();
/**
* Commits modification made to the friend configuration.
*/
void done();
/**
* Human readable representation of this friend
* @return
*/
String toString();
}

View file

@ -17,7 +17,11 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* Interface to implement for handling liblinphone log.
* <br> use {@link LinphoneCoreFactory#setLogHandler(LinphoneLogHandler)}
*
*/
public interface LinphoneLogHandler {
public static final int Fatal=1<<4;
public static final int Error=1<<3|Fatal;
@ -25,5 +29,13 @@ public interface LinphoneLogHandler {
public static final int Info=1<<1|Warn;
public static final int Debug=1|Info;
/**
* Method invoked for each traces
* @param loggerName
* @param level
* @param levelString
* @param msg
* @param e
*/
public void log(String loggerName, int level, String levelString, String msg, Throwable e);
}

View file

@ -17,34 +17,62 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods.
* Once created and filled properly the LinphoneProxyConfig can be given to LinphoneCore with {@link LinphoneCore#addProxyConfig(LinphoneProxyConfig)}. This will automatically triggers the registration, if enabled.
*<br>The proxy configuration are persistent to restarts because they are saved in the configuration file. As a consequence, after {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)} there might already be a default proxy that can be examined with {@link LinphoneCore#getDefaultProxyConfig()} .
*
*/
public interface LinphoneProxyConfig {
/**
* Unregister proxy config a enable edition
*Starts editing a proxy configuration.
*Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on).
*Once the modifications are done, then the application must call {@link #done()} to commit the changes.
*/
public void edit();
/**
* Validate proxy config changes. Start registration in case
* Commits modification made to the proxy configuration.
*/
public void done();
/**
* sip user made by sip:username@domain
* Sets the user identity as a SIP address.
* @param identy This identity is normally formed with display name, username and domain, such as: Alice <sip:alice@example.net> The REGISTER messages will have from and to set to this identity.
*/
public void setIdentity(String identity) throws LinphoneCoreException;
/**
* Set proxy uri, like sip:linphone.org:5060
*get the SIP identity that belongs to this proxy configuration.
*
* @return The SIP identity is a SIP address (Display Name <sip:username> )
*/
public String getIdentity();
/**
*Sets the proxy address
* Examples of valid sip proxy address are:
*<li>IP address: sip:87.98.157.38
*<li>IP address with port: sip:87.98.157.38:5062
*<li>hostnames : sip:sip.example.net
* @param proxyUri
* @throws LinphoneCoreException
*/
public void setProxy(String proxyUri) throws LinphoneCoreException;
/**
* get the proxy's SIP address.
*
*/
public String getProxy();
/**
* Enable register for this proxy config.
* Register message is issued after call to {@link #done()}
* @param value
* @throws LinphoneCoreException
*/
*/
public void enableRegister(boolean value) throws LinphoneCoreException;
/**
* @return true if registration to the proxy is enabled.
*/
public boolean registerEnabled();
/**
* normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222
* @param number
@ -52,7 +80,7 @@ public interface LinphoneProxyConfig {
*/
public String normalizePhoneNumber(String number);
/**
* usefull function to automatically add internationnal prefix to e164 phone numbers
* Useful function to automatically add international prefix to e164 phone numbers
* @param prefix
*/
public void setDialPrefix(String prefix);
@ -64,15 +92,25 @@ public interface LinphoneProxyConfig {
public void setDialEscapePlus(boolean value);
/**
* rget domain host name or ip
* get domain host name or ip
* @return may be null
*/
public String getDomain();
public String getIdentity();
public String getProxy();
public boolean registerEnabled();
/**
*
* @return a boolean indicating that the user is successfully registered on the proxy.
*/
public boolean isRegistered();
/**
* Sets a SIP route. When a route is set, all outgoing calls will go to the route's destination if this proxy is the default one (see {@link LinphoneCore#getDefaultProxyConfig()} ).
* @param routeUri ex sip:git.linphone.org
* @throws LinphoneCoreException
*/
public void setRoute(String routeUri) throws LinphoneCoreException;
/**
*
* @return the route set for this proxy configuration.
*/
public String getRoute();
}

View file

@ -0,0 +1,96 @@
/*
OnlineStatus.java
Copyright (C) 2010 Belledonne Communications, Grenoble, France
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.
*/
package org.linphone.core;
import java.util.Vector;
/**
* Enum describing remote friend status
*
*/
public class OnlineStatus {
static private Vector values = new Vector();
/**
* Offline
*/
static public OnlineStatus Offline = new OnlineStatus(0,"Offline");
/**
* Online
*/
static public OnlineStatus Online = new OnlineStatus(1,"Online");
/**
* Busy
*/
static public OnlineStatus Busy = new OnlineStatus(2,"Busy");
/**
* Be Right Back
*/
static public OnlineStatus BeRightBack = new OnlineStatus(3,"BeRightBack");
/**
* Away
*/
static public OnlineStatus Away = new OnlineStatus(4,"Away");
/**
* On The Phone
*/
static public OnlineStatus OnThePhone = new OnlineStatus(5,"OnThePhone");
/**
* Out To Lunch
*/
static public OnlineStatus OutToLunch = new OnlineStatus(6,"OutToLunch ");
/**
* Do Not Disturb
*/
static public OnlineStatus DoNotDisturb = new OnlineStatus(7,"DoNotDisturb");
/**
* Moved in this sate, call can be redirected if an alternate contact address has been set using function {@link LinphoneCore#setPresenceInfo(int, String, OnlineStatus)}
*/
static public OnlineStatus StatusMoved = new OnlineStatus(8,"StatusMoved");
/**
* Using another messaging service
*/
static public OnlineStatus StatusAltService = new OnlineStatus(9,"StatusAltService");
/**
* Pending
*/
static public OnlineStatus Pending = new OnlineStatus(10,"Pending");
protected final int mValue;
private final String mStringValue;
private OnlineStatus(int value,String stringValue) {
mValue = value;
values.addElement(this);
mStringValue=stringValue;
}
public static OnlineStatus fromInt(int value) {
for (int i=0; i<values.size();i++) {
OnlineStatus state = (OnlineStatus) values.elementAt(i);
if (state.mValue == value) return state;
}
throw new RuntimeException("state not found ["+value+"]");
}
public String toString() {
return mStringValue;
}
}

View file

@ -0,0 +1,194 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<!--
@(#)package.html
Copyright (C) 2010 Belledonne Communications, Grenoble, France
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.
-->
</head>
<body bgcolor="white">
Liblinphone is a high level library for bringing SIP video call functionnality into an application. It aims at making easy the integration of the SIP video calls into any applications. All variants of linphone are directly based on it:
<li>linphone (GUI interface)
<li>linphonec (console interface)
<br> Liblinphone is GPL (see COPYING file). Please understand the licencing details before using it!
<br>For any use of this library beyond the rights granted to you by the GPL license, please contact Belledonne Communications (contact@belledonne-communications.com)
<h2>Package Specification</h2>
LibLinphone package is organized in submodules.
<ul>
<li><a href="#proxy">Managing proxies</a>
</ul>
<ul>
<li><a href="#buddy">Managing Buddies and buddy list and presence</a>
</ul>
<ul>
<li><a href="#chat">Chat room and Messaging</a>
</ul>
<h2>Related Documentation</h2>
For overviews, tutorials, examples, guides, and tool documentation, please see:
<ul>
<li><a href="http://www.linphone.org">linphone web site</a>
</ul>
<!-- Put @see and @since tags down here. -->
<h3>
<a name="proxy">Managing proxies</a>
</h3>
User registration is controled by {@link org.linphone.core.LinphoneProxyConfig } settings.
<br> Each {@link org.linphone.core.LinphoneProxyConfig } object can be configured with registration informations
like {@link org.linphone.core.LinphoneProxyConfig#setProxy proxy address } , {@link org.linphone.core.LinphoneProxyConfig#setIdentity user id}, and so on.
<br> A created proxy config using {@link org.linphone.core.LinphoneCoreFactory#createProxyConfig }, once configured, must be added to {@link org.linphone.core.LinphoneCore} using function {@link org.linphone.core.LinphoneCore#addProxyConfig }.
<br> It is recommended to set a default {@link org.linphone.core.LinphoneProxyConfig proxy config } using function {@link org.linphone.core.LinphoneCore#setDefaultProxyConfig }. Once done, if {@link org.linphone.core.LinphoneProxyConfig a proxy config } has been configured with attribute {@link org.linphone.core.LinphoneProxyConfig#enableRegister enable register } , next call to {@link org.linphone.core.LinphoneCore#iterate } triggers a SIP register.
<br> Registration status is reported by {@link org.linphone.core.LinphoneCoreListener#registrationState registration listener}.
<br>
<br> This pseudo code demonstrates basic registration operations:
<br>
<pre>
<code>
LinphoneProxyConfig proxy_cfg;
/*create proxy config*/
proxy_cfg = LinphoneCoreFactory.instance().createProxyConfig();
/*parse identity*/
LinphoneAddress from = LinphoneCoreFactory.instance().createAddress("sip:toto@sip.titi.com");
LinphoneAuthInfo info;
if (password!=NULL){
info=LinphoneCoreFactory.instance().createAuthInfo(from.getUsername(),null,"secret",null,null); /*create authentication structure from identity*/
lc.addAuthInfo(info); /*add authentication info to LinphoneCore*/
}
// configure proxy entries
proxy_cfg.setIdenty(identity); /*set identity with user name and domain*/
String server_addr = from.getDomain(); /*extract domain address from identity*/
proxy_cfg.setProxy(server_addr); /* we assume domain = proxy server address*/
proxy_cfg.enableRegister(true); /*activate registration for this proxy config*/
lc.addProxyConfig(proxy_cfg); /*add proxy config to linphone core*/
lc.setDefaultProxyconfig(proxy_cfg); /*set to default proxy*/
</code>
</pre>
<br>
{@link org.linphone.core.LinphoneCoreListener#registrationState Registration state listener} :
<pre>
<code>
void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState cstate, String message){
System.out.println(New registration state ["+cstate+"] for user id ["+cfg.getUserName()+"] at proxy ["+cfg.getProxy()+"]";
}
</pre>
</code>
<br><b>Authentication:</b>
<br>Most of the time, registration requires {@link org.linphone.core.LinphoneAuthInfo authentication } to succed. {@link org.linphone.core.LinphoneAuthInfo} info must be either added to {@link org.linphone.core.LinphoneCore } using method {@link org.linphone.core.LinphoneCore#addAuthInfo } before {@link org.linphone.core.LinphoneProxyConfig} is added to Linphone core, or on demand from listener {@link org.linphone.core.LinphoneCoreListener#authInfoRequested(LinphoneCore, String, String)} .
<br>
<br><b>Unregistration:</b>
<br> Unregistration or any changes to {@link org.linphone.core.LinphoneProxyConfig} must be first started by a call to function {@link org.linphone.core.LinphoneProxyConfig#edit } and validated by function {@link org.linphone.core.LinphoneProxyConfig#done }
<br> This pseudo code shows how to unregister a user associated to a{@link org.linphone.core.LinphoneProxyConfig}
<pre>
<code>
LinphoneProxyConfig proxy_cfg;
lc.setDefaultProxyConfig(proxy_cfg); /* get default proxy config*/
proxy_cfg.edit(); /*start editing proxy configuration*/
proxy_cfg.enableRegister(false); /*de-activate registration for this proxy config*/
proxy_cfg.done(); /*initiate REGISTER with expire = 0*/
</pre>
</code>
<br>
<br>
<h3>
<a name="buddy">Managing Buddies and buddy list and presence</a>
</h3>
<br>
<b>Buddies and buddy list</b>
<br>Each buddy is represented by a {@link org.linphone.core.LinphoneFriend } object created by function {@link org.linphone.core.LinphoneCoreFactory#createLinphoneFriend()}.
Buddy configuration parameters like {@link org.linphone.core.LinphoneFriend#setAddress(LinphoneAddress) sip uri} or {@link org.linphone.core.LinphoneFriend#setIncSubscribePolicy(LinphoneFriend.SubscribePolicy) status publication} are configurable for each buddy.
<br>Here under a typical buddy creation:
<br>
<pre>
<code>
LinphoneFriend my_friend=LinphoneFactory.instance().createFriend("sip:joe@sip.linphone.org"); /*creates friend object for buddy joe*/
my_friend.enableSubscribes(true); /*configure this friend to emit SUBSCRIBE message after being added to LinphoneCore*/
my_friend.setIncSubscribePolicy(LinphoneFriend.SubscribePolicy.Accept); /* accept Incoming subscription request for this friend*/
</code>
</pre>
{@link LinphoneFriend friends } status changes are reported by {@link org.linphone.core.LinphoneCoreListener#notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf)} .
<pre>
<code>
void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf){
LinphoneAddress friend_address = lf.getAddress();
System.out.println("New state ["+lf.getStatus()+"] for user id ["+friend_address+"] ");
}
</code>
</pre>
<br>Once created a buddy can be added to the buddy list using function {@link org.linphone.core.LinphoneCore#addFriend(LinphoneFriend lf) } . Added friends will be notified about {@link org.linphone.core.LinphoneCore#setPresenceInfo(int minute_away,String alternative_contact, OnlineStatus status) local status changes }
<br>
Any subsequente modifications to {@link org.linphone.core.LinphoneFriend} must be first started by a call to function to {@link org.linphone.core.LinphoneFriend#edit()} and validated by function {@link org.linphone.core.LinphoneFriend#done()}
<pre>
<code>
my_friend.edit(); /* start editing friend */
my_friend.enableSubscribes(true); /*disable subscription for this friend*/
my_friend.done(); /*commit changes triggering an UNSUBSCRIBE message*/
</code>
</pre>
<b> Publishing presence status </b>
<br>Local presence status can be changed using function {@link org.linphone.core.LinphoneCore#setPresenceInfo }.New status is propagated to all friends {@link org.linphone.core.LinphoneCore#addFriend(LinphoneFriend lf) previously added } to LinphoneCore.
<br>
<br>
<b>Handling incoming subscription request</b>
<br> New incoming subscription requests are process according to{@link org.linphone.core.LinphoneFriend#setIncSubscribePolicy(LinphoneFriend.SubscribePolicy) the incoming subscription policy state} for subscription initiated by {@link org.linphone.core.LinphoneCore#addFriend(LinphoneFriend lf) members of the buddy list. }
<br> For incoming request coming from an unknown buddy, the call back {@link org.linphone.core.LinphoneCoreListener#newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)}
<h3>
<a name="chat">Chat room and Messaging</a>
</h3>
<b> Exchanging text messages</b>
<br> Messages are sent using {@link org.linphone.core.LinphoneChatRoom} object. First step is to create a {@link org.linphone.core.LinphoneCore#createChatRoom chat room }
from a peer sip uri.
<pre>
<code>
LinphoneChatRoom chat_room = lc.createChatRoom("sip:joe@sip.linphone.org");
</pre>
</code>
<br>Once created, messages are sent using function {@link org.linphone.core.LinphoneChatRoom#sendMessage } .
<pre>
<code>
chat_room.sendMessage("Hello world"); /*sending message*/
</pre>
</code>
<br>Incoming message are received from {@link org.linphone.core.LinphoneCoreListener#textReceived a listener }
<pre>
<code>
void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message) {
System.out.println("Message ["+message+"] received from ["+from+"] ");
}
</code>
<pre>
</body>
</html>

View file

@ -6,7 +6,7 @@ AC_REQUIRE([LP_CHECK_OSIP2])
case $target_os in
*darwin*)
OSIP_LIBS="$OSIP_LIBS -framework CoreFoundation -framework CoreServices "
OSIP_LIBS="$OSIP_LIBS -framework CoreFoundation "
;;
esac

@ -1 +1 @@
Subproject commit 93ef451fd6da31fd70fd59e6a6ca59cc26a3b287
Subproject commit 7ec60743dfffefc49cc83e47f0eff0ec7928d83a

2
oRTP

@ -1 +1 @@
Subproject commit 461dd13a0aad2a075a075bf618e68443475f7a24
Subproject commit 930fac6f59b13cdd6cbb5f370911a65f98bad7de