summaryrefslogtreecommitdiffstats
path: root/voip
diff options
context:
space:
mode:
authorChia-chi Yeh <chiachi@android.com>2012-04-04 13:04:26 -0700
committerChia-chi Yeh <chiachi@android.com>2012-04-04 13:04:26 -0700
commit2dd9134c6b2da47f4816bc0f72a0e4924aca4f84 (patch)
treeb3d716a395d4085f84a929f27fa243c3d9bbe30e /voip
parent54e1553df69350130df5e4518abf14a9a64931bb (diff)
downloadframeworks_base-2dd9134c6b2da47f4816bc0f72a0e4924aca4f84.zip
frameworks_base-2dd9134c6b2da47f4816bc0f72a0e4924aca4f84.tar.gz
frameworks_base-2dd9134c6b2da47f4816bc0f72a0e4924aca4f84.tar.bz2
SIP: push the logic of finding local address down to SipSessionGroup.
This allows different accounts binding on different IP addresses, such as one on IPv4 and another on IPv6. Bug: 4169057 Change-Id: I0bb36669394c281330091673fa338adea8f782cd
Diffstat (limited to 'voip')
-rw-r--r--voip/java/com/android/server/sip/SipService.java44
-rw-r--r--voip/java/com/android/server/sip/SipSessionGroup.java105
2 files changed, 60 insertions, 89 deletions
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 97afc81..a477fd1 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -453,9 +453,8 @@ public final class SipService extends ISipService.Stub {
public SipSessionGroupExt(SipProfile localProfile,
PendingIntent incomingCallPendingIntent,
ISipSessionListener listener) throws SipException {
- String password = localProfile.getPassword();
- SipProfile p = duplicate(localProfile);
- mSipGroup = createSipSessionGroup(mLocalIp, p, password);
+ mSipGroup = new SipSessionGroup(duplicate(localProfile),
+ localProfile.getPassword(), mTimer, mMyWakeLock);
mIncomingCallPendingIntent = incomingCallPendingIntent;
mAutoRegistration.setListener(listener);
}
@@ -478,27 +477,6 @@ public final class SipService extends ISipService.Stub {
mSipGroup.setWakeupTimer(timer);
}
- // network connectivity is tricky because network can be disconnected
- // at any instant so need to deal with exceptions carefully even when
- // you think you are connected
- private SipSessionGroup createSipSessionGroup(String localIp,
- SipProfile localProfile, String password) throws SipException {
- try {
- return new SipSessionGroup(localIp, localProfile, password,
- mTimer, mMyWakeLock);
- } catch (IOException e) {
- // network disconnected
- Log.w(TAG, "createSipSessionGroup(): network disconnected?");
- if (localIp != null) {
- return createSipSessionGroup(null, localProfile, password);
- } else {
- // recursive
- Log.wtf(TAG, "impossible! recursive!");
- throw new RuntimeException("createSipSessionGroup");
- }
- }
- }
-
private SipProfile duplicate(SipProfile p) {
try {
return new SipProfile.Builder(p).setPassword("*").build();
@@ -530,7 +508,7 @@ public final class SipService extends ISipService.Stub {
throws SipException {
mSipGroup.onConnectivityChanged();
if (connected) {
- resetGroup(mLocalIp);
+ mSipGroup.reset();
if (mOpenedToReceiveCalls) openToReceiveCalls();
} else {
// close mSipGroup but remember mOpenedToReceiveCalls
@@ -541,22 +519,6 @@ public final class SipService extends ISipService.Stub {
}
}
- private void resetGroup(String localIp) throws SipException {
- try {
- mSipGroup.reset(localIp);
- } catch (IOException e) {
- // network disconnected
- Log.w(TAG, "resetGroup(): network disconnected?");
- if (localIp != null) {
- resetGroup(null); // reset w/o local IP
- } else {
- // recursive
- Log.wtf(TAG, "impossible!");
- throw new RuntimeException("resetGroup");
- }
- }
- }
-
public void close() {
mOpenedToReceiveCalls = false;
mSipGroup.close();
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 877a0a4..6acd456 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -40,6 +40,7 @@ import android.util.Log;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramSocket;
+import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.Collection;
@@ -47,13 +48,11 @@ import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-import java.util.TooManyListenersException;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
-import javax.sip.InvalidArgumentException;
import javax.sip.ListeningPoint;
import javax.sip.ObjectInUseException;
import javax.sip.RequestEvent;
@@ -132,18 +131,17 @@ class SipSessionGroup implements SipListener {
private int mExternalPort;
/**
- * @param myself the local profile with password crossed out
+ * @param profile the local profile with password crossed out
* @param password the password of the profile
* @throws IOException if cannot assign requested address
*/
- public SipSessionGroup(String localIp, SipProfile myself, String password,
- SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException,
- IOException {
- mLocalProfile = myself;
+ public SipSessionGroup(SipProfile profile, String password,
+ SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException {
+ mLocalProfile = profile;
mPassword = password;
mWakeupTimer = timer;
mWakeLock = wakeLock;
- reset(localIp);
+ reset();
}
// TODO: remove this method once SipWakeupTimer can better handle variety
@@ -152,43 +150,64 @@ class SipSessionGroup implements SipListener {
mWakeupTimer = timer;
}
- synchronized void reset(String localIp) throws SipException, IOException {
- mLocalIp = localIp;
- if (localIp == null) return;
-
- SipProfile myself = mLocalProfile;
- SipFactory sipFactory = SipFactory.getInstance();
+ synchronized void reset() throws SipException {
Properties properties = new Properties();
+
+ String protocol = mLocalProfile.getProtocol();
+ int port = mLocalProfile.getPort();
+ String server = mLocalProfile.getProxyAddress();
+
+ if (!TextUtils.isEmpty(server)) {
+ properties.setProperty("javax.sip.OUTBOUND_PROXY",
+ server + ':' + port + '/' + protocol);
+ } else {
+ server = mLocalProfile.getSipDomain();
+ }
+ if (server.startsWith("[") && server.endsWith("]")) {
+ server = server.substring(1, server.length() - 1);
+ }
+
+ String local = null;
+ try {
+ for (InetAddress remote : InetAddress.getAllByName(server)) {
+ DatagramSocket socket = new DatagramSocket();
+ socket.connect(remote, port);
+ if (socket.isConnected()) {
+ local = socket.getLocalAddress().getHostAddress();
+ port = socket.getLocalPort();
+ socket.close();
+ break;
+ }
+ socket.close();
+ }
+ } catch (Exception e) {
+ // ignore.
+ }
+ if (local == null) {
+ // We are unable to reach the server. Just bail out.
+ return;
+ }
+
+ close();
+ mLocalIp = local;
+
properties.setProperty("javax.sip.STACK_NAME", getStackName());
properties.setProperty(
"gov.nist.javax.sip.THREAD_POOL_SIZE", THREAD_POOL_SIZE);
- String outboundProxy = myself.getProxyAddress();
- if (!TextUtils.isEmpty(outboundProxy)) {
- Log.v(TAG, "outboundProxy is " + outboundProxy);
- properties.setProperty("javax.sip.OUTBOUND_PROXY", outboundProxy
- + ":" + myself.getPort() + "/" + myself.getProtocol());
- }
- SipStack stack = mSipStack = sipFactory.createSipStack(properties);
-
+ mSipStack = SipFactory.getInstance().createSipStack(properties);
try {
- SipProvider provider = stack.createSipProvider(
- stack.createListeningPoint(localIp, allocateLocalPort(),
- myself.getProtocol()));
+ SipProvider provider = mSipStack.createSipProvider(
+ mSipStack.createListeningPoint(local, port, protocol));
provider.addSipListener(this);
- mSipHelper = new SipHelper(stack, provider);
- } catch (InvalidArgumentException e) {
- throw new IOException(e.getMessage());
- } catch (TooManyListenersException e) {
- // must never happen
- throw new SipException("SipSessionGroup constructor", e);
+ mSipHelper = new SipHelper(mSipStack, provider);
+ } catch (SipException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SipException("failed to initialize SIP stack", e);
}
- Log.d(TAG, " start stack for " + myself.getUriString());
- stack.start();
-
- mCallReceiverSession = null;
- mSessionMap.clear();
- resetExternalAddress();
+ Log.d(TAG, " start stack for " + mLocalProfile.getUriString());
+ mSipStack.start();
}
synchronized void onConnectivityChanged() {
@@ -234,6 +253,7 @@ class SipSessionGroup implements SipListener {
mSipStack = null;
mSipHelper = null;
}
+ resetExternalAddress();
}
public synchronized boolean isClosed() {
@@ -257,17 +277,6 @@ class SipSessionGroup implements SipListener {
return (isClosed() ? null : new SipSessionImpl(listener));
}
- private static int allocateLocalPort() throws SipException {
- try {
- DatagramSocket s = new DatagramSocket();
- int localPort = s.getLocalPort();
- s.close();
- return localPort;
- } catch (IOException e) {
- throw new SipException("allocateLocalPort()", e);
- }
- }
-
synchronized boolean containsSession(String callId) {
return mSessionMap.containsKey(callId);
}