How to unregister from SIP in linphone? - iphone

Is there a way to unregister from SIP and re-register when I want in Linphone?
I can't find the unregister function.
Should I destroy the linphone core completely for that?
Or is there a more soft solution?
Currently I am trying to implement it in iOS, but later this will be required for additional platforms.
Thank you.

// Get the default proxyCfg in Linphone
LinphoneProxyConfig* proxyCfg = NULL;
linphone_core_get_default_proxy([LinphoneManager getLc], &proxyCfg);
// To unregister from SIP
linphone_proxy_config_edit(proxyCfg);
linphone_proxy_config_enable_register(proxyCfg, false);
linphone_proxy_config_done(proxyCfg);
// And re-register when want
linphone_proxy_config_edit(proxyCfg);
linphone_proxy_config_enable_register(proxyCfg, true);
linphone_proxy_config_done(proxyCfg);

You may have multiple SIP accounts. First, specify the account you want and get your proxy from getProxyConfigList. Then remove the proxy you want from the core of the linphone via removeProxyConfig method:
private static AuthInfo mAuthInfo;
private static ProxyConfig mProxyConfig;
Core core = LinphoneManager.getCore();
ProxyConfig[] proxyConfigs = core.getProxyConfigList();
if (proxyConfigs.length != 0) {
mProxyConfig = proxyConfigs[0];
mAuthInfo = mProxyConfig.findAuthInfo();
}
if (core != null) {
{
if (mProxyConfig != null) {
core.removeProxyConfig(mProxyConfig);
}
if (mAuthInfo != null) {
core.removeAuthInfo(mAuthInfo);
}
}

there is the way how to unregister using linphone.
Get the LinphoneProxyConfig
LinphoneProxyConfig* proxyCfg = NULL;
linphone_core_get_default_proxy([LinphoneManager getLc], &proxyCfg);
To unregister from SIP
linphone_proxy_config_edit(proxyCfg); /*start editing proxy configuration*/
linphone_proxy_config_enable_publish(proxyCfg, TRUE);
linphone_proxy_config_set_publish_expires(proxyCfg, 0);
linphone_proxy_config_enable_register(proxyCfg,FALSE); /*de-activate registration for this proxy config*/
linphone_proxy_config_done(proxyCfg); /*initiate REGISTER with expire = 0*/
while(linphone_proxy_config_get_state(proxyCfg) != LinphoneRegistrationCleared){
NSLog(#"state = %i",linphone_proxy_config_get_state(proxyCfg));
linphone_core_iterate(lc); /*to make sure we receive call backs before shutting down*/
ms_usleep(100000);
}
But it's works only when app in Foreground. In background if the OS kills your app for any reason, it is killed. There is no notification. You can't catch the SIGKILL signal. Look at the man page for kill.

Unregistration not exactly given. Remove sip extension and then call refresh registers. Now your softphone unregistered from sip
[[NSUserDefaults standardUserDefaults] setObject:#"" forKey:#"username_preference"];
if ([[UIDevice currentDevice] respondsToSelector:#selector(isMultitaskingSupported)]
&& [UIApplication sharedApplication].applicationState == UIApplicationStateBackground
&& [[NSUserDefaults standardUserDefaults] boolForKey:#"disable_autoboot_preference"]) {
// autoboot disabled, doing nothing
return;
} else if ([SipManager instance] == nil) {
[self startApplication:caldelegate];
}
[[LinphoneManager instance] becomeActive];
if (callCenter == nil) {
callCenter = [[CTCallCenter alloc] init];
callCenter.callEventHandler = ^(CTCall* call) {
// post on main thread
[self performSelectorOnMainThread:#selector(handleGSMCallInteration:)
withObject:callCenter
waitUntilDone:YES];
};
}
// check call state at startup
[self handleGSMCallInteration:callCenter];
LinphoneCore* lc = [SipManager getLc];
LinphoneCall* call = linphone_core_get_current_call(lc);
if (call == NULL)
return;
SipManager* instance = [SipManager instance];
if (call == instance->currentCallContextBeforeGoingBackground.call) {
const LinphoneCallParams* params = linphone_call_get_current_params(call);
if (linphone_call_params_video_enabled(params)) {
linphone_call_enable_camera(
call,
instance->currentCallContextBeforeGoingBackground.cameraIsEnabled);
}
instance->currentCallContextBeforeGoingBackground.call = 0;
}

Actually, there is no "unregistration" option for a sip server. The location server will update to the newest register information (including your newest IP address).
If you are talking about how to stop linphone iterate registration, and re-register to the other SIP server. Then follow the #Mun Chun's guide

LinphoneCore *lc = [LinphoneManager getLc];
LinphoneProxyConfig *config = linphone_core_get_default_proxy_config(lc);
linphone_proxy_config_edit(config);
linphone_proxy_config_set_expires(config, 0);
linphone_proxy_config_done(config);

I've worked on Linphone for some months and my function to unregister from SIP was:
- (void)clearProxies {
LinphoneProxyConfig *config = linphone_core_get_default_proxy_config(LC); // Get the default proxy configured.
const LinphoneAuthInfo *ai = linphone_proxy_config_find_auth_info(config);
linphone_core_remove_proxy_config(LC, config); // Remove the selected proxy config.
if (ai) {
linphone_core_remove_auth_info(LC, ai); // Remove the authentication infos.
}
linphone_proxy_config_done(config); // Confirm the actual configuration.
}
You have to clear both proxy config and auth info and confirm the new configuration.

Related

pjsip (pjsua) notification when remote user answers the call

I am trying to make a simple SIP user agent using https://github.com/pjsip/pjproject. I can succesfully connect to a sip server (Twilio) and place calls to PSTN numbers using the pjsua_* interface. This works fine.
What I would like now is to get a notification (through a callback or such) from pjsip when the user that I am calling answers the call.
I am using on_call_state() to get updates on the invite, but this goes through the same states
CALLING -> CONNECTING -> CONFIRMED -> DISCONNCTD
even if the user rejects the call. So I guess I am not looking at the right callback for this.
How can I definitely tell if the user has answered or rejected the call?
for me it is working this way. in on_call_state callback:
pjsua_call_info callInfo;
pjsua_call_get_info(call_id, &callInfo);
pjsip_inv_state state = callInfo.state;
pjsip_status_code statusCode = callInfo.last_status;
switch (state) {
.....
case PJSIP_INV_STATE_CONFIRMED:
// remote party answered the call normally
break;
case PJSIP_INV_STATE_DISCONNECTED:
if (statusCode == PJSIP_SC_BUSY_HERE) {
// rejected
} else {
// finished ok
}
break;
i reject call this way:
pj_status_t state;
int sendCode = PJSIP_SC_DECLINE;
try {
state = pjsua_call_answer((pjsua_call_id) call_id, sendCode, nullptr, nullptr);
} catch (...) {
return -1;
}
return state;

Wifi Direct - GO receives connection request

I have 2 P2P devices (android smartphones). They created a Wifi Direct Group. So, we have a Group owner and a Client. A third device appears, and wants to join the group sending a connection request to the GO. When this happens the GO BroadcastReceiver detects a disconnect. I would like to know if that is a normal behavior or I'm doing something wrong.
This is part of my BroadcastReceiver
else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION
.equals(action)) {
if (manager == null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) intent
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
if (networkInfo.isConnected()) {
// we are connected with the other device, request connection
// info to find group owner IP
} else {
// It's a disconnect
}
} else if ....

how to deal with the block of ftp download request

I am downloading file with ftp protocol. Now, to check the ability of dealing with error, I am simulating happening of some network error. The code to handle the network inputStream is as below:
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
// An NSStream delegate callback that's called when events happen on our
// network stream.
{
#pragma unused(aStream)
assert(aStream == self.networkStream);
switch (eventCode) {
case NSStreamEventOpenCompleted: {
self.connected = YES;
} break;
case NSStreamEventHasBytesAvailable: {
NSInteger bytesRead;
uint8_t buffer[32768];
// Pull some data off the network.
bytesRead = [self.networkStream read:buffer maxLength:sizeof(buffer)];
DLog(#"%#,byteRead:%d",self.urlInput,bytesRead);
if (bytesRead == -1) {
[self _stopReceiveWithStatus:#"Network read error"];
} else if (bytesRead == 0) {
[self _stopReceiveWithStatus:#"success"];
} else {
NSInteger bytesWritten;
NSInteger bytesWrittenSoFar;
bytesWrittenSoFar = 0;
do {
bytesWritten = [self.fileStream write:&buffer[bytesWrittenSoFar] maxLength:bytesRead - bytesWrittenSoFar];
DLog(#"%#,bytesWritten:%d",self.urlInput,bytesWritten);
assert(bytesWritten != 0);
if (bytesWritten == -1) {
[self _stopReceiveWithStatus:#"File write error"];
break;
} else {
bytesWrittenSoFar += bytesWritten;
}
} while (bytesWrittenSoFar != bytesRead);
}
} break;
case NSStreamEventHasSpaceAvailable: {
assert(NO); // should never happen for the output stream
} break;
case NSStreamEventErrorOccurred: {
[self _stopReceiveWithStatus:#"Stream open error"];
} break;
case NSStreamEventEndEncountered: {
assert(NO);
} break;
default: {
assert(NO);
} break;
}
}
If I turn off the wifi manually or turn off my wireless router (Network connection flag is off), a "NSStreamEventErrorOccurred" will be return and the downloading process will be terminated correctly. However, if I turn off the Modem, while keeping the wireless router open (Network connection flag is on). The downloading process stuck at the case "NSStreamEventHasBytesAvailable". Even after I turn on the internet connection , it is still stuck.
I want to know why it is stuck and how can I detect this kind of error. How can I deal with this situation?
First, kudos for considering this and running tests. Many developers assume that "the network connection will always work."
Second, it seems a little odd that you are using NSStream for FTP downloads; you do know that NSURLConnection supports FTP, right? Unless you are doing something really strange you should probably use the built-in URL loading facilities.
In any case, the issue here is that there is in principle no way for an application (or computer) to determine whether there has been a pause in a connection because the connection failed (and should be restarted or canceled) or because it simply is running slowly (in which case patience is required).
I'm a little surprised that an active TCP session is not resumed when your modem is reconnected; that suggests that maybe your ISP's router is dropping the connection when the modem link goes down or that your IP is changing on reconnection, but this isn't important for your question anyway.
TCP sessions will ordinarily eventually get timed out by the OS (or an upstream router) after a period of inactivity, but this might be an unacceptably long time. So the thing you probably need to do is implement a timeout.
What I'd probably do (assuming you stay the course with NSStream as discussed above) is have an NSTimer firing off periodically - maybe every 15 seconds - and have the callback compare the current time to a timestamp that you set on each NSStreamEventHasBytesAvailable event. If the timestamp is too old (say, more than 15 seconds), cancel or restart the download as desired and notify the user.
But again, take a look at just using NSURLConnection.

ilibjingle with the Openfire server - Not able to login

I just installed openfire server in my Suse-Linux EC2 instance and I've configured the openfire server by creating one user named 'balaji' in addition to the admin.
I then installed the ilibjingle code for the iOS platform and I was able to build it. I ran it in the simulator and it worked perfectly for my gmail-id. It logged in, then brought the users from the roster list.
I then modified the code to point to my openfire server IP address and gave the username as 'balaji' (the one I created in openfire) and the appropriate password. I also have a self signed SSL certificate in the openfire server. When I ran this code, it was able to connect, but not able to login (I believe). The ilibjingle code is supposed to go from Connect to Login to LoggedIn to the Roster list. When I ran with my openfire server, it went from Connect to Login, but nothing beyond that.
What could have possibly gone wrong? Should I modify anything in my openfire server to make this work? Here's my iPhone code.
In the rootviewcontroller.mm, I have the following snippet.
-(void) _mainGtalkThread:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//you need to setup name and passwd manuelly here
char *name = "balaji";
char *password = "mypasswd";
[self gtalk_main:(char*)name userpassword:(char*)password];
[pool release];
}
-(int) gtalk_main:(char*)un userpassword:(char*)password
{
// This app has three threads. The main thread will run the XMPP client,
// which will print to the screen in its own thread. A second thread
// will get input from the console, parse it, and pass the appropriate
// message back to the XMPP client's thread. A third thread is used
// by MediaSessionClient as its worker thread.
buzz::Jid jid;
talk_base::InsecureCryptStringImpl pass;
std::string username = un;
if (username.find('#') == std::string::npos) {
username.append("#localhost");
}
jid = buzz::Jid(username);
if (!jid.IsValid() || jid.node() == "") {
printf("Invalid JID. JIDs should be in the form user#domain\n");
return 1;
}
pass.password() = password;
buzz::XmppClientSettings xcs;
xcs.set_user(jid.node());
//xcs.set_resource("call");
xcs.set_host(jid.domain());
xcs.set_pass(talk_base::CryptString(pass));
xcs.set_use_tls(false);
xcs.set_allow_plain(true);
xcs.set_server(talk_base::SocketAddress("50.37.185.206", DEFAULT_PORT));
printf("Logging in as %s with user as %s\n", jid.Str().c_str(), jid.node().c_str());
talk_base::InitializeSSL();
talk_base::Thread athread;
talk_base::ThreadManager::SetCurrent(&athread);
talk_base::Thread* main_thread = talk_base::Thread::Current();
assert(main_thread!=NULL);
XmppPump pump;
//CallClient *client = new CallClient(pump.client());
gtalkClient_ = new gtalkClient(pump.client(), self);
pump.DoLogin(xcs, new XmppSocket(true), NULL);
main_thread->Run();
return 0;
}
and in another file 'gtalkclient.mm', I have the following:
gtalkClient::gtalkClient(buzz::XmppClient* xmpp_client, void * controller) :
xmpp_client_(xmpp_client), controller_(controller), media_engine_(NULL),
media_client_(NULL), call_(NULL), incoming_call_(false), auto_accept_(false),
pmuc_domain_("conference.localhost"), local_renderer_(NULL), remote_renderer_(NULL),
roster_(new RosterMap), portallocator_flags_(0)
{
xmpp_client_->SignalStateChange.connect(this, &gtalkClient::OnStateChange);
}
void gtalkClient::OnStateChange(buzz::XmppEngine::State state)
{
RootViewController * tvc = (RootViewController*)controller_;
switch (state) {
case buzz::XmppEngine::STATE_START:
printf("connecting...");
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"connecting..."];
[tvc reloadTableViewData];
break;
case buzz::XmppEngine::STATE_OPENING:
printf("logging in...");
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"logging in..."];
[tvc reloadTableViewData];
break;
case buzz::XmppEngine::STATE_OPEN:
printf("logged in...");
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"logged in..."];
[tvc reloadTableViewData];
InitPhone();
InitPresence();
// prepare to add roster
[tvc.roster_ removeAllObjects];
break;
case buzz::XmppEngine::STATE_CLOSED:
buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL);
printf("logged out...%s", strerror(error).c_str());
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"logged out..."];
[tvc reloadTableViewData];
Quit();
}
}
I also had the same issue while am running libjingle sample program with my openfire server.Its because newer version of libjingle didn't support the certificates of unknown authorities.
So you need to undo the changes made on xmppsocket.cc on rev65 (when libjingle was updated to version 0.5.6):
This link will help you to see difference between two version
http://code.google.com/p/libjingle/source/diff?spec=svn95&r=65&format=side&path=/trunk/talk/examples/login/xmppsocket.cc&old_path=/trunk/talk/examples/login/xmppsocket.cc&old=30
In this commit, they removed two lines that were allowing certificates of unknown Certificate Authorities.
I got solved the problem by following the above instructions
Or you can follow the below link to get the complete idea.
http://code.google.com/p/libjingle/issues/detail?id=250.

Using GSoap returns EHOSTUNREACH when calling connect() through socket.h

I'm currently building an iPhone app based on Gsoap toolkit to connect to a webservice. Everything works fine except when I try to connect to my service after disconnecting and reconnecting 3g on the device, I get :
SOAP 1.1 fault: SOAP-ENV:Client [no subcode]
"Connection refused"
Detail: connect failed in tcp_connect()
Working through the debugger shows that the error comes from connect() method of socket.h.
I don't really understand, when I launch another app like safari, the device is connected to the Internet. And after loading a web page, my app's connection works fine.
Here is the code I'm using :
//GSoap initialization
struct soap soap;
soap_init(&soap);
soap.connect_timeout = 0;
soap.send_timeout = 0;
soap.recv_timeout = 0;
// objects request & response
// struct types can be foundin soapStub.h
struct _ns1__GetAuthentification requete;
struct _ns1__GetAuthentificationResponse reponse;
// init request
requete.ConnectPass = (char *) [connectPass UTF8String];
requete.Login = (char *) [login UTF8String];
requete.Password = (char *) [password UTF8String];
requete.soap = &soap;
// request callback. returns SOAP_OK if something has been returned
if(soap_call___ns1__GetAuthentification(&soap,NULL,NULL, &requete,&reponse) == SOAP_OK){
//then we build the result
NSLog(#"Yay!");
soap_end(&soap); // remove deserialized data and clean up
soap_done(&soap); // detach the gSOAP environment
return authResult;
}
else {
//NSLog(#"Soap Error : GetAuthentification");
// We try to see if there's any problem. #catch statements are here just to keep note of the concerned
// exceptions for each request. No utility for the code.
#try {
[self processFault:&soap];
}
#catch (MMWrongId * e) {
#throw e;
}
#catch (MMConnectionFailed * e) {
#throw e;
}
#catch (MMGetAuthentificationFault * e) {
#throw e;
}
return nil;
}
Am I missing any particular flag/option?
For those who encounter the same issue, I got a solution. Michael Lasmanis has been a huge help for this one. Here is his answer :
this is one of the reasons i no longer recommend gsoap for iphone new iphone developers. gsoap uses the lower bsd sockets and bypasses the higher level iphone apis. it is the higher level api that manage the state of the internet connectivity which is why if you start safari first, then everything works. the easiest workaround is to use nsurlconnection to open a http connect to a well know site before calling gsoap.