FileDocCategorySizeDatePackage
SipSessionGroup.javaAPI DocAndroid 5.1 API71691Thu Mar 12 22:22:52 GMT 2015com.android.server.sip

SipSessionGroup

public class SipSessionGroup extends Object implements javax.sip.SipListener
Manages {@link ISipSession}'s for a SIP account.

Fields Summary
private static final String
TAG
private static final boolean
DBG
private static final boolean
DBG_PING
private static final String
ANONYMOUS
private static final String
THREAD_POOL_SIZE
private static final int
EXPIRY_TIME
private static final int
CANCEL_CALL_TIMER
private static final int
END_CALL_TIMER
private static final int
KEEPALIVE_TIMEOUT
private static final int
INCALL_KEEPALIVE_INTERVAL
private static final long
WAKE_LOCK_HOLDING_TIME
private static final EventObject
DEREGISTER
private static final EventObject
END_CALL
private final android.net.sip.SipProfile
mLocalProfile
private final String
mPassword
private javax.sip.SipStack
mSipStack
private SipHelper
mSipHelper
private SipSessionImpl
mCallReceiverSession
private String
mLocalIp
private SipWakeupTimer
mWakeupTimer
private SipWakeLock
mWakeLock
private Map
mSessionMap
private String
mExternalIp
private int
mExternalPort
Constructors Summary
public SipSessionGroup(android.net.sip.SipProfile profile, String password, SipWakeupTimer timer, SipWakeLock wakeLock)

param
profile the local profile with password crossed out
param
password the password of the profile
throws
SipException if cannot assign requested address


                                
        
                  
        mLocalProfile = profile;
        mPassword = password;
        mWakeupTimer = timer;
        mWakeLock = wakeLock;
        reset();
    
Methods Summary
private synchronized voidaddSipSession(com.android.server.sip.SipSessionGroup$SipSessionImpl newSession)

        removeSipSession(newSession);
        String key = newSession.getCallId();
        mSessionMap.put(key, newSession);
        if (isLoggable(newSession)) {
            if (DBG) log("addSipSession: key='" + key + "'");
            for (String k : mSessionMap.keySet()) {
                if (DBG) log("addSipSession:  " + k + ": " + mSessionMap.get(k));
            }
        }
    
public synchronized voidclose()

        if (DBG) log("close: " + mLocalProfile.getUriString());
        onConnectivityChanged();
        mSessionMap.clear();
        closeToNotReceiveCalls();
        if (mSipStack != null) {
            mSipStack.stop();
            mSipStack = null;
            mSipHelper = null;
        }
        resetExternalAddress();
    
public synchronized voidcloseToNotReceiveCalls()

        mCallReceiverSession = null;
    
synchronized booleancontainsSession(java.lang.String callId)

        return mSessionMap.containsKey(callId);
    
private com.android.server.sip.SipSessionGroup$SipSessionImplcreateNewSession(javax.sip.RequestEvent event, android.net.sip.ISipSessionListener listener, javax.sip.ServerTransaction transaction, int newState)

        SipSessionImpl newSession = new SipSessionImpl(listener);
        newSession.mServerTransaction = transaction;
        newSession.mState = newState;
        newSession.mDialog = newSession.mServerTransaction.getDialog();
        newSession.mInviteReceived = event;
        newSession.mPeerProfile = createPeerProfile((HeaderAddress)
                event.getRequest().getHeader(FromHeader.NAME));
        newSession.mPeerSessionDescription =
                extractContent(event.getRequest());
        return newSession;
    
private static android.net.sip.SipProfilecreatePeerProfile(javax.sip.header.HeaderAddress header)

        try {
            Address address = header.getAddress();
            SipURI uri = (SipURI) address.getURI();
            String username = uri.getUser();
            if (username == null) username = ANONYMOUS;
            int port = uri.getPort();
            SipProfile.Builder builder =
                    new SipProfile.Builder(username, uri.getHost())
                    .setDisplayName(address.getDisplayName());
            if (port > 0) builder.setPort(port);
            return builder.build();
        } catch (IllegalArgumentException e) {
            throw new SipException("createPeerProfile()", e);
        } catch (ParseException e) {
            throw new SipException("createPeerProfile()", e);
        }
    
public android.net.sip.ISipSessioncreateSession(android.net.sip.ISipSessionListener listener)

        return (isClosed() ? null : new SipSessionImpl(listener));
    
private static booleanexpectResponse(java.lang.String expectedMethod, java.util.EventObject evt)

return
true if the event is a response event and the CSeqHeader method match the given arguments; false otherwise

        if (evt instanceof ResponseEvent) {
            ResponseEvent event = (ResponseEvent) evt;
            Response response = event.getResponse();
            return expectedMethod.equalsIgnoreCase(getCseqMethod(response));
        }
        return false;
    
private java.lang.StringextractContent(javax.sip.message.Message message)

        // Currently we do not support secure MIME bodies.
        byte[] bytes = message.getRawContent();
        if (bytes != null) {
            try {
                if (message instanceof SIPMessage) {
                    return ((SIPMessage) message).getMessageContent();
                } else {
                    return new String(bytes, "UTF-8");
                }
            } catch (UnsupportedEncodingException e) {
            }
        }
        return null;
    
private voidextractExternalAddress(javax.sip.ResponseEvent evt)

        Response response = evt.getResponse();
        ViaHeader viaHeader = (ViaHeader)(response.getHeader(
                SIPHeaderNames.VIA));
        if (viaHeader == null) return;
        int rport = viaHeader.getRPort();
        String externalIp = viaHeader.getReceived();
        if ((rport > 0) && (externalIp != null)) {
            mExternalIp = externalIp;
            mExternalPort = rport;
            if (DBG) {
                log("extractExternalAddress: external addr " + externalIp + ":" + rport
                        + " on " + mSipStack);
            }
        }
    
private static java.lang.StringgetCseqMethod(javax.sip.message.Message message)

        return ((CSeqHeader) message.getHeader(CSeqHeader.NAME)).getMethod();
    
public android.net.sip.SipProfilegetLocalProfile()

        return mLocalProfile;
    
public java.lang.StringgetLocalProfileUri()

        return mLocalProfile.getUriString();
    
private java.lang.ThrowablegetRootCause(java.lang.Throwable exception)

        Throwable cause = exception.getCause();
        while (cause != null) {
            exception = cause;
            cause = exception.getCause();
        }
        return exception;
    
private synchronized com.android.server.sip.SipSessionGroup$SipSessionImplgetSipSession(java.util.EventObject event)

        String key = SipHelper.getCallId(event);
        SipSessionImpl session = mSessionMap.get(key);
        if ((session != null) && isLoggable(session)) {
            if (DBG) log("getSipSession: event=" + key);
            if (DBG) log("getSipSession: active sessions:");
            for (String k : mSessionMap.keySet()) {
                if (DBG) log("getSipSession: ..." + k + ": " + mSessionMap.get(k));
            }
        }
        return ((session != null) ? session : mCallReceiverSession);
    
private java.lang.StringgetStackName()

        return "stack" + System.currentTimeMillis();
    
public synchronized booleanisClosed()

        return (mSipStack == null);
    
private static booleanisLoggable(com.android.server.sip.SipSessionGroup$SipSessionImpl s)

        if (s != null) {
            switch (s.mState) {
                case SipSession.State.PINGING:
                    return DBG_PING;
            }
        }
        return DBG;
    
private static booleanisLoggable(java.util.EventObject evt)

        return isLoggable(null, evt);
    
private static booleanisLoggable(com.android.server.sip.SipSessionGroup$SipSessionImpl s, java.util.EventObject evt)

        if (!isLoggable(s)) return false;
        if (evt == null) return false;

        if (evt instanceof ResponseEvent) {
            Response response = ((ResponseEvent) evt).getResponse();
            if (Request.OPTIONS.equals(response.getHeader(CSeqHeader.NAME))) {
                return DBG_PING;
            }
            return DBG;
        } else if (evt instanceof RequestEvent) {
            if (isRequestEvent(Request.OPTIONS, evt)) {
                return DBG_PING;
            }
            return DBG;
        }
        return false;
    
private static booleanisRequestEvent(java.lang.String method, java.util.EventObject event)

return
true if the event is a request event matching the specified method; false otherwise

        try {
            if (event instanceof RequestEvent) {
                RequestEvent requestEvent = (RequestEvent) event;
                return method.equals(requestEvent.getRequest().getMethod());
            }
        } catch (Throwable e) {
        }
        return false;
    
private voidlog(java.lang.String s)

        Rlog.d(TAG, s);
    
private static java.lang.StringlogEvt(java.util.EventObject evt)

        if (evt instanceof RequestEvent) {
            return ((RequestEvent) evt).getRequest().toString();
        } else if (evt instanceof ResponseEvent) {
            return ((ResponseEvent) evt).getResponse().toString();
        } else {
            return evt.toString();
        }
    
private voidloge(java.lang.String s, java.lang.Throwable t)

        Rlog.e(TAG, s, t);
    
synchronized voidonConnectivityChanged()

        SipSessionImpl[] ss = mSessionMap.values().toArray(
                    new SipSessionImpl[mSessionMap.size()]);
        // Iterate on the copied array instead of directly on mSessionMap to
        // avoid ConcurrentModificationException being thrown when
        // SipSessionImpl removes itself from mSessionMap in onError() in the
        // following loop.
        for (SipSessionImpl s : ss) {
            s.onError(SipErrorCode.DATA_CONNECTION_LOST,
                    "data connection lost");
        }
    
public synchronized voidopenToReceiveCalls(android.net.sip.ISipSessionListener listener)

        if (mCallReceiverSession == null) {
            mCallReceiverSession = new SipSessionCallReceiverImpl(listener);
        } else {
            mCallReceiverSession.setListener(listener);
        }
    
private synchronized voidprocess(java.util.EventObject event)

        SipSessionImpl session = getSipSession(event);
        try {
            boolean isLoggable = isLoggable(session, event);
            boolean processed = (session != null) && session.process(event);
            if (isLoggable && processed) {
                log("process: event new state after: "
                        + SipSession.State.toString(session.mState));
            }
        } catch (Throwable e) {
            loge("process: error event=" + event, getRootCause(e));
            session.onError(e);
        }
    
public voidprocessDialogTerminated(javax.sip.DialogTerminatedEvent event)

        process(event);
    
public voidprocessIOException(javax.sip.IOExceptionEvent event)

        process(event);
    
public voidprocessRequest(javax.sip.RequestEvent event)

        if (isRequestEvent(Request.INVITE, event)) {
            if (DBG) log("processRequest: mWakeLock.acquire got INVITE, thread:"
                    + Thread.currentThread());
            // Acquire a wake lock and keep it for WAKE_LOCK_HOLDING_TIME;
            // should be large enough to bring up the app.
            mWakeLock.acquire(WAKE_LOCK_HOLDING_TIME);
        }
        process(event);
    
public voidprocessResponse(javax.sip.ResponseEvent event)

        process(event);
    
public voidprocessTimeout(javax.sip.TimeoutEvent event)

        process(event);
    
public voidprocessTransactionTerminated(javax.sip.TransactionTerminatedEvent event)

        process(event);
    
private synchronized voidremoveSipSession(com.android.server.sip.SipSessionGroup$SipSessionImpl session)

        if (session == mCallReceiverSession) return;
        String key = session.getCallId();
        SipSessionImpl s = mSessionMap.remove(key);
        // sanity check
        if ((s != null) && (s != session)) {
            if (DBG) log("removeSession: " + session + " is not associated with key '"
                    + key + "'");
            mSessionMap.put(key, s);
            for (Map.Entry<String, SipSessionImpl> entry
                    : mSessionMap.entrySet()) {
                if (entry.getValue() == s) {
                    key = entry.getKey();
                    mSessionMap.remove(key);
                }
            }
        }

        if ((s != null) && isLoggable(s)) {
            if (DBG) log("removeSession: " + session + " @key '" + key + "'");
            for (String k : mSessionMap.keySet()) {
                if (DBG) log("removeSession:  " + k + ": " + mSessionMap.get(k));
            }
        }
    
synchronized voidreset()

        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);
        mSipStack = SipFactory.getInstance().createSipStack(properties);
        try {
            SipProvider provider = mSipStack.createSipProvider(
                    mSipStack.createListeningPoint(local, port, protocol));
            provider.addSipListener(this);
            mSipHelper = new SipHelper(mSipStack, provider);
        } catch (SipException e) {
            throw e;
        } catch (Exception e) {
            throw new SipException("failed to initialize SIP stack", e);
        }

        if (DBG) log("reset: start stack for " + mLocalProfile.getUriString());
        mSipStack.start();
    
synchronized voidresetExternalAddress()

        if (DBG) {
            log("resetExternalAddress: " + mSipStack);
        }
        mExternalIp = null;
        mExternalPort = 0;
    
voidsetWakeupTimer(SipWakeupTimer timer)

        mWakeupTimer = timer;