/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.sip;

import gov.nist.javax.sip.clientauthutils.AccountManager;
import gov.nist.javax.sip.clientauthutils.UserCredentials;
import gov.nist.javax.sip.header.ProxyAuthenticate;
import gov.nist.javax.sip.header.ReferTo;
import gov.nist.javax.sip.header.SIPHeaderNames;
import gov.nist.javax.sip.header.StatusLine;
import gov.nist.javax.sip.header.WWWAuthenticate;
import gov.nist.javax.sip.header.extensions.ReferredByHeader;
import gov.nist.javax.sip.header.extensions.ReplacesHeader;
import gov.nist.javax.sip.message.SIPMessage;
import gov.nist.javax.sip.message.SIPResponse;

import android.net.sip.ISipSession;
import android.net.sip.ISipSessionListener;
import android.net.sip.SipErrorCode;
import android.net.sip.SipProfile;
import android.net.sip.SipSession;
import android.net.sip.SipSessionAdapter;
import android.text.TextUtils;
import android.telephony.Rlog;

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.EventObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.ObjectInUseException;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.TimeoutEvent;
import javax.sip.Transaction;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderAddress;
import javax.sip.header.MinExpiresHeader;
import javax.sip.header.ReferToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Message;
import javax.sip.message.Request;
import javax.sip.message.Response;


/**
 * Manages {@link ISipSession}'s for a SIP account.
 */
class SipSessionGroup implements SipListener {
    private static final String TAG = "SipSession";
    private static final boolean DBG = false;
    private static final boolean DBG_PING = false;
    private static final String ANONYMOUS = "anonymous";
    // Limit the size of thread pool to 1 for the order issue when the phone is
    // waken up from sleep and there are many packets to be processed in the SIP
    // stack. Note: The default thread pool size in NIST SIP stack is -1 which is
    // unlimited.
    private static final String THREAD_POOL_SIZE = "1";
    private static final int EXPIRY_TIME = 3600; // in seconds
    private static final int CANCEL_CALL_TIMER = 3; // in seconds
    private static final int END_CALL_TIMER = 3; // in seconds
    private static final int KEEPALIVE_TIMEOUT = 5; // in seconds
    private static final int INCALL_KEEPALIVE_INTERVAL = 10; // in seconds
    private static final long WAKE_LOCK_HOLDING_TIME = 500; // in milliseconds

    private static final EventObject DEREGISTER = new EventObject("Deregister");
    private static final EventObject END_CALL = new EventObject("End call");

    private final SipProfile mLocalProfile;
    private final String mPassword;

    private SipStack mSipStack;
    private SipHelper mSipHelper;

    // session that processes INVITE requests
    private SipSessionImpl mCallReceiverSession;
    private String mLocalIp;

    private SipWakeupTimer mWakeupTimer;
    private SipWakeLock mWakeLock;

    // call-id-to-SipSession map
    private Map<String, SipSessionImpl> mSessionMap =
            new HashMap<String, SipSessionImpl>();

    // external address observed from any response
    private String mExternalIp;
    private int mExternalPort;

    /**
     * @param profile the local profile with password crossed out
     * @param password the password of the profile
     * @throws SipException if cannot assign requested address
     */
    public SipSessionGroup(SipProfile profile, String password,
            SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException {
        mLocalProfile = profile;
        mPassword = password;
        mWakeupTimer = timer;
        mWakeLock = wakeLock;
        reset();
    }

    // TODO: remove this method once SipWakeupTimer can better handle variety
    // of timeout values
    void setWakeupTimer(SipWakeupTimer timer) {
        mWakeupTimer = timer;
    }

    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);
        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 void onConnectivityChanged() {
        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");
        }
    }

    synchronized void resetExternalAddress() {
        if (DBG) {
            log("resetExternalAddress: " + mSipStack);
        }
        mExternalIp = null;
        mExternalPort = 0;
    }

    public SipProfile getLocalProfile() {
        return mLocalProfile;
    }

    public String getLocalProfileUri() {
        return mLocalProfile.getUriString();
    }

    private String getStackName() {
        return "stack" + System.currentTimeMillis();
    }

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

    public synchronized boolean isClosed() {
        return (mSipStack == null);
    }

    // For internal use, require listener not to block in callbacks.
    public synchronized void openToReceiveCalls(ISipSessionListener listener) {
        if (mCallReceiverSession == null) {
            mCallReceiverSession = new SipSessionCallReceiverImpl(listener);
        } else {
            mCallReceiverSession.setListener(listener);
        }
    }

    public synchronized void closeToNotReceiveCalls() {
        mCallReceiverSession = null;
    }

    public ISipSession createSession(ISipSessionListener listener) {
        return (isClosed() ? null : new SipSessionImpl(listener));
    }

    synchronized boolean containsSession(String callId) {
        return mSessionMap.containsKey(callId);
    }

    private synchronized SipSessionImpl getSipSession(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 synchronized void addSipSession(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));
            }
        }
    }

    private synchronized void removeSipSession(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));
            }
        }
    }

    @Override
    public void processRequest(final 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);
    }

    @Override
    public void processResponse(ResponseEvent event) {
        process(event);
    }

    @Override
    public void processIOException(IOExceptionEvent event) {
        process(event);
    }

    @Override
    public void processTimeout(TimeoutEvent event) {
        process(event);
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent event) {
        process(event);
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent event) {
        process(event);
    }

    private synchronized void process(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);
        }
    }

    private String extractContent(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 void extractExternalAddress(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 Throwable getRootCause(Throwable exception) {
        Throwable cause = exception.getCause();
        while (cause != null) {
            exception = cause;
            cause = exception.getCause();
        }
        return exception;
    }

    private SipSessionImpl createNewSession(RequestEvent event,
            ISipSessionListener listener, ServerTransaction transaction,
            int newState) throws SipException {
        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 class SipSessionCallReceiverImpl extends SipSessionImpl {
        private static final String SSCRI_TAG = "SipSessionCallReceiverImpl";
        private static final boolean SSCRI_DBG = true;

        public SipSessionCallReceiverImpl(ISipSessionListener listener) {
            super(listener);
        }

        private int processInviteWithReplaces(RequestEvent event,
                ReplacesHeader replaces) {
            String callId = replaces.getCallId();
            SipSessionImpl session = mSessionMap.get(callId);
            if (session == null) {
                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
            }

            Dialog dialog = session.mDialog;
            if (dialog == null) return Response.DECLINE;

            if (!dialog.getLocalTag().equals(replaces.getToTag()) ||
                    !dialog.getRemoteTag().equals(replaces.getFromTag())) {
                // No match is found, returns 481.
                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
            }

            ReferredByHeader referredBy = (ReferredByHeader) event.getRequest()
                    .getHeader(ReferredByHeader.NAME);
            if ((referredBy == null) ||
                    !dialog.getRemoteParty().equals(referredBy.getAddress())) {
                return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
            }
            return Response.OK;
        }

        private void processNewInviteRequest(RequestEvent event)
                throws SipException {
            ReplacesHeader replaces = (ReplacesHeader) event.getRequest()
                    .getHeader(ReplacesHeader.NAME);
            SipSessionImpl newSession = null;
            if (replaces != null) {
                int response = processInviteWithReplaces(event, replaces);
                if (SSCRI_DBG) {
                    log("processNewInviteRequest: " + replaces
                            + " response=" + response);
                }
                if (response == Response.OK) {
                    SipSessionImpl replacedSession =
                            mSessionMap.get(replaces.getCallId());
                    // got INVITE w/ replaces request.
                    newSession = createNewSession(event,
                            replacedSession.mProxy.getListener(),
                            mSipHelper.getServerTransaction(event),
                            SipSession.State.INCOMING_CALL);
                    newSession.mProxy.onCallTransferring(newSession,
                            newSession.mPeerSessionDescription);
                } else {
                    mSipHelper.sendResponse(event, response);
                }
            } else {
                // New Incoming call.
                newSession = createNewSession(event, mProxy,
                        mSipHelper.sendRinging(event, generateTag()),
                        SipSession.State.INCOMING_CALL);
                mProxy.onRinging(newSession, newSession.mPeerProfile,
                        newSession.mPeerSessionDescription);
            }
            if (newSession != null) addSipSession(newSession);
        }

        @Override
        public boolean process(EventObject evt) throws SipException {
            if (isLoggable(this, evt)) log("process: " + this + ": "
                    + SipSession.State.toString(mState) + ": processing "
                    + logEvt(evt));
            if (isRequestEvent(Request.INVITE, evt)) {
                processNewInviteRequest((RequestEvent) evt);
                return true;
            } else if (isRequestEvent(Request.OPTIONS, evt)) {
                mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
                return true;
            } else {
                return false;
            }
        }

        private void log(String s) {
            Rlog.d(SSCRI_TAG, s);
        }
    }

    static interface KeepAliveProcessCallback {
        /** Invoked when the response of keeping alive comes back. */
        void onResponse(boolean portChanged);
        void onError(int errorCode, String description);
    }

    class SipSessionImpl extends ISipSession.Stub {
        private static final String SSI_TAG = "SipSessionImpl";
        private static final boolean SSI_DBG = true;

        SipProfile mPeerProfile;
        SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
        int mState = SipSession.State.READY_TO_CALL;
        RequestEvent mInviteReceived;
        Dialog mDialog;
        ServerTransaction mServerTransaction;
        ClientTransaction mClientTransaction;
        String mPeerSessionDescription;
        boolean mInCall;
        SessionTimer mSessionTimer;
        int mAuthenticationRetryCount;

        private SipKeepAlive mSipKeepAlive;

        private SipSessionImpl mSipSessionImpl;

        // the following three members are used for handling refer request.
        SipSessionImpl mReferSession;
        ReferredByHeader mReferredBy;
        String mReplaces;

        // lightweight timer
        class SessionTimer {
            private boolean mRunning = true;

            void start(final int timeout) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        sleep(timeout);
                        if (mRunning) timeout();
                    }
                }, "SipSessionTimerThread").start();
            }

            synchronized void cancel() {
                mRunning = false;
                this.notify();
            }

            private void timeout() {
                synchronized (SipSessionGroup.this) {
                    onError(SipErrorCode.TIME_OUT, "Session timed out!");
                }
            }

            private synchronized void sleep(int timeout) {
                try {
                    this.wait(timeout * 1000);
                } catch (InterruptedException e) {
                    loge("session timer interrupted!", e);
                }
            }
        }

        public SipSessionImpl(ISipSessionListener listener) {
            setListener(listener);
        }

        SipSessionImpl duplicate() {
            return new SipSessionImpl(mProxy.getListener());
        }

        private void reset() {
            mInCall = false;
            removeSipSession(this);
            mPeerProfile = null;
            mState = SipSession.State.READY_TO_CALL;
            mInviteReceived = null;
            mPeerSessionDescription = null;
            mAuthenticationRetryCount = 0;
            mReferSession = null;
            mReferredBy = null;
            mReplaces = null;

            if (mDialog != null) mDialog.delete();
            mDialog = null;

            try {
                if (mServerTransaction != null) mServerTransaction.terminate();
            } catch (ObjectInUseException e) {
                // ignored
            }
            mServerTransaction = null;

            try {
                if (mClientTransaction != null) mClientTransaction.terminate();
            } catch (ObjectInUseException e) {
                // ignored
            }
            mClientTransaction = null;

            cancelSessionTimer();

            if (mSipSessionImpl != null) {
                mSipSessionImpl.stopKeepAliveProcess();
                mSipSessionImpl = null;
            }
        }

        @Override
        public boolean isInCall() {
            return mInCall;
        }

        @Override
        public String getLocalIp() {
            return mLocalIp;
        }

        @Override
        public SipProfile getLocalProfile() {
            return mLocalProfile;
        }

        @Override
        public SipProfile getPeerProfile() {
            return mPeerProfile;
        }

        @Override
        public String getCallId() {
            return SipHelper.getCallId(getTransaction());
        }

        private Transaction getTransaction() {
            if (mClientTransaction != null) return mClientTransaction;
            if (mServerTransaction != null) return mServerTransaction;
            return null;
        }

        @Override
        public int getState() {
            return mState;
        }

        @Override
        public void setListener(ISipSessionListener listener) {
            mProxy.setListener((listener instanceof SipSessionListenerProxy)
                    ? ((SipSessionListenerProxy) listener).getListener()
                    : listener);
        }

        // process the command in a new thread
        private void doCommandAsync(final EventObject command) {
            new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            processCommand(command);
                        } catch (Throwable e) {
                            loge("command error: " + command + ": "
                                    + mLocalProfile.getUriString(),
                                    getRootCause(e));
                            onError(e);
                        }
                    }
            }, "SipSessionAsyncCmdThread").start();
        }

        @Override
        public void makeCall(SipProfile peerProfile, String sessionDescription,
                int timeout) {
            doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription,
                    timeout));
        }

        @Override
        public void answerCall(String sessionDescription, int timeout) {
            synchronized (SipSessionGroup.this) {
                if (mPeerProfile == null) return;
                doCommandAsync(new MakeCallCommand(mPeerProfile,
                        sessionDescription, timeout));
            }
        }

        @Override
        public void endCall() {
            doCommandAsync(END_CALL);
        }

        @Override
        public void changeCall(String sessionDescription, int timeout) {
            synchronized (SipSessionGroup.this) {
                if (mPeerProfile == null) return;
                doCommandAsync(new MakeCallCommand(mPeerProfile,
                        sessionDescription, timeout));
            }
        }

        @Override
        public void register(int duration) {
            doCommandAsync(new RegisterCommand(duration));
        }

        @Override
        public void unregister() {
            doCommandAsync(DEREGISTER);
        }

        private void processCommand(EventObject command) throws SipException {
            if (isLoggable(command)) log("process cmd: " + command);
            if (!process(command)) {
                onError(SipErrorCode.IN_PROGRESS,
                        "cannot initiate a new transaction to execute: "
                        + command);
            }
        }

        protected String generateTag() {
            // 32-bit randomness
            return String.valueOf((long) (Math.random() * 0x100000000L));
        }

        @Override
        public String toString() {
            try {
                String s = super.toString();
                return s.substring(s.indexOf("@")) + ":"
                        + SipSession.State.toString(mState);
            } catch (Throwable e) {
                return super.toString();
            }
        }

        public boolean process(EventObject evt) throws SipException {
            if (isLoggable(this, evt)) log(" ~~~~~   " + this + ": "
                    + SipSession.State.toString(mState) + ": processing "
                    + logEvt(evt));
            synchronized (SipSessionGroup.this) {
                if (isClosed()) return false;

                if (mSipKeepAlive != null) {
                    // event consumed by keepalive process
                    if (mSipKeepAlive.process(evt)) return true;
                }

                Dialog dialog = null;
                if (evt instanceof RequestEvent) {
                    dialog = ((RequestEvent) evt).getDialog();
                } else if (evt instanceof ResponseEvent) {
                    dialog = ((ResponseEvent) evt).getDialog();
                    extractExternalAddress((ResponseEvent) evt);
                }
                if (dialog != null) mDialog = dialog;

                boolean processed;

                switch (mState) {
                case SipSession.State.REGISTERING:
                case SipSession.State.DEREGISTERING:
                    processed = registeringToReady(evt);
                    break;
                case SipSession.State.READY_TO_CALL:
                    processed = readyForCall(evt);
                    break;
                case SipSession.State.INCOMING_CALL:
                    processed = incomingCall(evt);
                    break;
                case SipSession.State.INCOMING_CALL_ANSWERING:
                    processed = incomingCallToInCall(evt);
                    break;
                case SipSession.State.OUTGOING_CALL:
                case SipSession.State.OUTGOING_CALL_RING_BACK:
                    processed = outgoingCall(evt);
                    break;
                case SipSession.State.OUTGOING_CALL_CANCELING:
                    processed = outgoingCallToReady(evt);
                    break;
                case SipSession.State.IN_CALL:
                    processed = inCall(evt);
                    break;
                case SipSession.State.ENDING_CALL:
                    processed = endingCall(evt);
                    break;
                default:
                    processed = false;
                }
                return (processed || processExceptions(evt));
            }
        }

        private boolean processExceptions(EventObject evt) throws SipException {
            if (isRequestEvent(Request.BYE, evt)) {
                // terminate the call whenever a BYE is received
                mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
                endCallNormally();
                return true;
            } else if (isRequestEvent(Request.CANCEL, evt)) {
                mSipHelper.sendResponse((RequestEvent) evt,
                        Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                return true;
            } else if (evt instanceof TransactionTerminatedEvent) {
                if (isCurrentTransaction((TransactionTerminatedEvent) evt)) {
                    if (evt instanceof TimeoutEvent) {
                        processTimeout((TimeoutEvent) evt);
                    } else {
                        processTransactionTerminated(
                                (TransactionTerminatedEvent) evt);
                    }
                    return true;
                }
            } else if (isRequestEvent(Request.OPTIONS, evt)) {
                mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
                return true;
            } else if (evt instanceof DialogTerminatedEvent) {
                processDialogTerminated((DialogTerminatedEvent) evt);
                return true;
            }
            return false;
        }

        private void processDialogTerminated(DialogTerminatedEvent event) {
            if (mDialog == event.getDialog()) {
                onError(new SipException("dialog terminated"));
            } else {
                if (SSI_DBG) log("not the current dialog; current=" + mDialog
                        + ", terminated=" + event.getDialog());
            }
        }

        private boolean isCurrentTransaction(TransactionTerminatedEvent event) {
            Transaction current = event.isServerTransaction()
                    ? mServerTransaction
                    : mClientTransaction;
            Transaction target = event.isServerTransaction()
                    ? event.getServerTransaction()
                    : event.getClientTransaction();

            if ((current != target) && (mState != SipSession.State.PINGING)) {
                if (SSI_DBG) log("not the current transaction; current="
                        + toString(current) + ", target=" + toString(target));
                return false;
            } else if (current != null) {
                if (SSI_DBG) log("transaction terminated: " + toString(current));
                return true;
            } else {
                // no transaction; shouldn't be here; ignored
                return true;
            }
        }

        private String toString(Transaction transaction) {
            if (transaction == null) return "null";
            Request request = transaction.getRequest();
            Dialog dialog = transaction.getDialog();
            CSeqHeader cseq = (CSeqHeader) request.getHeader(CSeqHeader.NAME);
            return String.format("req=%s,%s,s=%s,ds=%s,", request.getMethod(),
                    cseq.getSeqNumber(), transaction.getState(),
                    ((dialog == null) ? "-" : dialog.getState()));
        }

        private void processTransactionTerminated(
                TransactionTerminatedEvent event) {
            switch (mState) {
                case SipSession.State.IN_CALL:
                case SipSession.State.READY_TO_CALL:
                    if (SSI_DBG) log("Transaction terminated; do nothing");
                    break;
                default:
                    if (SSI_DBG) log("Transaction terminated early: " + this);
                    onError(SipErrorCode.TRANSACTION_TERMINTED,
                            "transaction terminated");
            }
        }

        private void processTimeout(TimeoutEvent event) {
            if (SSI_DBG) log("processing Timeout...");
            switch (mState) {
                case SipSession.State.REGISTERING:
                case SipSession.State.DEREGISTERING:
                    reset();
                    mProxy.onRegistrationTimeout(this);
                    break;
                case SipSession.State.INCOMING_CALL:
                case SipSession.State.INCOMING_CALL_ANSWERING:
                case SipSession.State.OUTGOING_CALL:
                case SipSession.State.OUTGOING_CALL_CANCELING:
                    onError(SipErrorCode.TIME_OUT, event.toString());
                    break;

                default:
                    if (SSI_DBG) log("   do nothing");
                    break;
            }
        }

        private int getExpiryTime(Response response) {
            int time = -1;
            ContactHeader contact = (ContactHeader) response.getHeader(ContactHeader.NAME);
            if (contact != null) {
                time = contact.getExpires();
            }
            ExpiresHeader expires = (ExpiresHeader) response.getHeader(ExpiresHeader.NAME);
            if (expires != null && (time < 0 || time > expires.getExpires())) {
                time = expires.getExpires();
            }
            if (time <= 0) {
                time = EXPIRY_TIME;
            }
            expires = (ExpiresHeader) response.getHeader(MinExpiresHeader.NAME);
            if (expires != null && time < expires.getExpires()) {
                time = expires.getExpires();
            }
            if (SSI_DBG) {
                log("Expiry time = " + time);
            }
            return time;
        }

        private boolean registeringToReady(EventObject evt)
                throws SipException {
            if (expectResponse(Request.REGISTER, evt)) {
                ResponseEvent event = (ResponseEvent) evt;
                Response response = event.getResponse();

                int statusCode = response.getStatusCode();
                switch (statusCode) {
                case Response.OK:
                    int state = mState;
                    onRegistrationDone((state == SipSession.State.REGISTERING)
                            ? getExpiryTime(((ResponseEvent) evt).getResponse())
                            : -1);
                    return true;
                case Response.UNAUTHORIZED:
                case Response.PROXY_AUTHENTICATION_REQUIRED:
                    handleAuthentication(event);
                    return true;
                default:
                    if (statusCode >= 500) {
                        onRegistrationFailed(response);
                        return true;
                    }
                }
            }
            return false;
        }

        private boolean handleAuthentication(ResponseEvent event)
                throws SipException {
            Response response = event.getResponse();
            String nonce = getNonceFromResponse(response);
            if (nonce == null) {
                onError(SipErrorCode.SERVER_ERROR,
                        "server does not provide challenge");
                return false;
            } else if (mAuthenticationRetryCount < 2) {
                mClientTransaction = mSipHelper.handleChallenge(
                        event, getAccountManager());
                mDialog = mClientTransaction.getDialog();
                mAuthenticationRetryCount++;
                if (isLoggable(this, event)) {
                    if (SSI_DBG) log("   authentication retry count="
                            + mAuthenticationRetryCount);
                }
                return true;
            } else {
                if (crossDomainAuthenticationRequired(response)) {
                    onError(SipErrorCode.CROSS_DOMAIN_AUTHENTICATION,
                            getRealmFromResponse(response));
                } else {
                    onError(SipErrorCode.INVALID_CREDENTIALS,
                            "incorrect username or password");
                }
                return false;
            }
        }

        private boolean crossDomainAuthenticationRequired(Response response) {
            String realm = getRealmFromResponse(response);
            if (realm == null) realm = "";
            return !mLocalProfile.getSipDomain().trim().equals(realm.trim());
        }

        private AccountManager getAccountManager() {
            return new AccountManager() {
                @Override
                public UserCredentials getCredentials(ClientTransaction
                        challengedTransaction, String realm) {
                    return new UserCredentials() {
                        @Override
                        public String getUserName() {
                            String username = mLocalProfile.getAuthUserName();
                            return (!TextUtils.isEmpty(username) ? username :
                                    mLocalProfile.getUserName());
                        }

                        @Override
                        public String getPassword() {
                            return mPassword;
                        }

                        @Override
                        public String getSipDomain() {
                            return mLocalProfile.getSipDomain();
                        }
                    };
                }
            };
        }

        private String getRealmFromResponse(Response response) {
            WWWAuthenticate wwwAuth = (WWWAuthenticate)response.getHeader(
                    SIPHeaderNames.WWW_AUTHENTICATE);
            if (wwwAuth != null) return wwwAuth.getRealm();
            ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader(
                    SIPHeaderNames.PROXY_AUTHENTICATE);
            return (proxyAuth == null) ? null : proxyAuth.getRealm();
        }

        private String getNonceFromResponse(Response response) {
            WWWAuthenticate wwwAuth = (WWWAuthenticate)response.getHeader(
                    SIPHeaderNames.WWW_AUTHENTICATE);
            if (wwwAuth != null) return wwwAuth.getNonce();
            ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader(
                    SIPHeaderNames.PROXY_AUTHENTICATE);
            return (proxyAuth == null) ? null : proxyAuth.getNonce();
        }

        private String getResponseString(int statusCode) {
            StatusLine statusLine = new StatusLine();
            statusLine.setStatusCode(statusCode);
            statusLine.setReasonPhrase(SIPResponse.getReasonPhrase(statusCode));
            return statusLine.encode();
        }

        private boolean readyForCall(EventObject evt) throws SipException {
            // expect MakeCallCommand, RegisterCommand, DEREGISTER
            if (evt instanceof MakeCallCommand) {
                mState = SipSession.State.OUTGOING_CALL;
                MakeCallCommand cmd = (MakeCallCommand) evt;
                mPeerProfile = cmd.getPeerProfile();
                if (mReferSession != null) {
                    mSipHelper.sendReferNotify(mReferSession.mDialog,
                            getResponseString(Response.TRYING));
                }
                mClientTransaction = mSipHelper.sendInvite(
                        mLocalProfile, mPeerProfile, cmd.getSessionDescription(),
                        generateTag(), mReferredBy, mReplaces);
                mDialog = mClientTransaction.getDialog();
                addSipSession(this);
                startSessionTimer(cmd.getTimeout());
                mProxy.onCalling(this);
                return true;
            } else if (evt instanceof RegisterCommand) {
                mState = SipSession.State.REGISTERING;
                int duration = ((RegisterCommand) evt).getDuration();
                mClientTransaction = mSipHelper.sendRegister(mLocalProfile,
                        generateTag(), duration);
                mDialog = mClientTransaction.getDialog();
                addSipSession(this);
                mProxy.onRegistering(this);
                return true;
            } else if (DEREGISTER == evt) {
                mState = SipSession.State.DEREGISTERING;
                mClientTransaction = mSipHelper.sendRegister(mLocalProfile,
                        generateTag(), 0);
                mDialog = mClientTransaction.getDialog();
                addSipSession(this);
                mProxy.onRegistering(this);
                return true;
            }
            return false;
        }

        private boolean incomingCall(EventObject evt) throws SipException {
            // expect MakeCallCommand(answering) , END_CALL cmd , Cancel
            if (evt instanceof MakeCallCommand) {
                // answer call
                mState = SipSession.State.INCOMING_CALL_ANSWERING;
                mServerTransaction = mSipHelper.sendInviteOk(mInviteReceived,
                        mLocalProfile,
                        ((MakeCallCommand) evt).getSessionDescription(),
                        mServerTransaction,
                        mExternalIp, mExternalPort);
                startSessionTimer(((MakeCallCommand) evt).getTimeout());
                return true;
            } else if (END_CALL == evt) {
                mSipHelper.sendInviteBusyHere(mInviteReceived,
                        mServerTransaction);
                endCallNormally();
                return true;
            } else if (isRequestEvent(Request.CANCEL, evt)) {
                RequestEvent event = (RequestEvent) evt;
                mSipHelper.sendResponse(event, Response.OK);
                mSipHelper.sendInviteRequestTerminated(
                        mInviteReceived.getRequest(), mServerTransaction);
                endCallNormally();
                return true;
            }
            return false;
        }

        private boolean incomingCallToInCall(EventObject evt) {
            // expect ACK, CANCEL request
            if (isRequestEvent(Request.ACK, evt)) {
                String sdp = extractContent(((RequestEvent) evt).getRequest());
                if (sdp != null) mPeerSessionDescription = sdp;
                if (mPeerSessionDescription == null) {
                    onError(SipErrorCode.CLIENT_ERROR, "peer sdp is empty");
                } else {
                    establishCall(false);
                }
                return true;
            } else if (isRequestEvent(Request.CANCEL, evt)) {
                // http://tools.ietf.org/html/rfc3261#section-9.2
                // Final response has been sent; do nothing here.
                return true;
            }
            return false;
        }

        private boolean outgoingCall(EventObject evt) throws SipException {
            if (expectResponse(Request.INVITE, evt)) {
                ResponseEvent event = (ResponseEvent) evt;
                Response response = event.getResponse();

                int statusCode = response.getStatusCode();
                switch (statusCode) {
                case Response.RINGING:
                case Response.CALL_IS_BEING_FORWARDED:
                case Response.QUEUED:
                case Response.SESSION_PROGRESS:
                    // feedback any provisional responses (except TRYING) as
                    // ring back for better UX
                    if (mState == SipSession.State.OUTGOING_CALL) {
                        mState = SipSession.State.OUTGOING_CALL_RING_BACK;
                        cancelSessionTimer();
                        mProxy.onRingingBack(this);
                    }
                    return true;
                case Response.OK:
                    if (mReferSession != null) {
                        mSipHelper.sendReferNotify(mReferSession.mDialog,
                                getResponseString(Response.OK));
                        // since we don't need to remember the session anymore.
                        mReferSession = null;
                    }
                    mSipHelper.sendInviteAck(event, mDialog);
                    mPeerSessionDescription = extractContent(response);
                    establishCall(true);
                    return true;
                case Response.UNAUTHORIZED:
                case Response.PROXY_AUTHENTICATION_REQUIRED:
                    if (handleAuthentication(event)) {
                        addSipSession(this);
                    }
                    return true;
                case Response.REQUEST_PENDING:
                    // TODO: rfc3261#section-14.1; re-schedule invite
                    return true;
                default:
                    if (mReferSession != null) {
                        mSipHelper.sendReferNotify(mReferSession.mDialog,
                                getResponseString(Response.SERVICE_UNAVAILABLE));
                    }
                    if (statusCode >= 400) {
                        // error: an ack is sent automatically by the stack
                        onError(response);
                        return true;
                    } else if (statusCode >= 300) {
                        // TODO: handle 3xx (redirect)
                    } else {
                        return true;
                    }
                }
                return false;
            } else if (END_CALL == evt) {
                // RFC says that UA should not send out cancel when no
                // response comes back yet. We are cheating for not checking
                // response.
                mState = SipSession.State.OUTGOING_CALL_CANCELING;
                mSipHelper.sendCancel(mClientTransaction);
                startSessionTimer(CANCEL_CALL_TIMER);
                return true;
            } else if (isRequestEvent(Request.INVITE, evt)) {
                // Call self? Send BUSY HERE so server may redirect the call to
                // voice mailbox.
                RequestEvent event = (RequestEvent) evt;
                mSipHelper.sendInviteBusyHere(event,
                        event.getServerTransaction());
                return true;
            }
            return false;
        }

        private boolean outgoingCallToReady(EventObject evt)
                throws SipException {
            if (evt instanceof ResponseEvent) {
                ResponseEvent event = (ResponseEvent) evt;
                Response response = event.getResponse();
                int statusCode = response.getStatusCode();
                if (expectResponse(Request.CANCEL, evt)) {
                    if (statusCode == Response.OK) {
                        // do nothing; wait for REQUEST_TERMINATED
                        return true;
                    }
                } else if (expectResponse(Request.INVITE, evt)) {
                    switch (statusCode) {
                        case Response.OK:
                            outgoingCall(evt); // abort Cancel
                            return true;
                        case Response.REQUEST_TERMINATED:
                            endCallNormally();
                            return true;
                    }
                } else {
                    return false;
                }

                if (statusCode >= 400) {
                    onError(response);
                    return true;
                }
            } else if (evt instanceof TransactionTerminatedEvent) {
                // rfc3261#section-14.1:
                // if re-invite gets timed out, terminate the dialog; but
                // re-invite is not reliable, just let it go and pretend
                // nothing happened.
                onError(new SipException("timed out"));
            }
            return false;
        }

        private boolean processReferRequest(RequestEvent event)
                throws SipException {
            try {
                ReferToHeader referto = (ReferToHeader) event.getRequest()
                        .getHeader(ReferTo.NAME);
                Address address = referto.getAddress();
                SipURI uri = (SipURI) address.getURI();
                String replacesHeader = uri.getHeader(ReplacesHeader.NAME);
                String username = uri.getUser();
                if (username == null) {
                    mSipHelper.sendResponse(event, Response.BAD_REQUEST);
                    return false;
                }
                // send notify accepted
                mSipHelper.sendResponse(event, Response.ACCEPTED);
                SipSessionImpl newSession = createNewSession(event,
                        this.mProxy.getListener(),
                        mSipHelper.getServerTransaction(event),
                        SipSession.State.READY_TO_CALL);
                newSession.mReferSession = this;
                newSession.mReferredBy = (ReferredByHeader) event.getRequest()
                        .getHeader(ReferredByHeader.NAME);
                newSession.mReplaces = replacesHeader;
                newSession.mPeerProfile = createPeerProfile(referto);
                newSession.mProxy.onCallTransferring(newSession,
                        null);
                return true;
            } catch (IllegalArgumentException e) {
                throw new SipException("createPeerProfile()", e);
            }
        }

        private boolean inCall(EventObject evt) throws SipException {
            // expect END_CALL cmd, BYE request, hold call (MakeCallCommand)
            // OK retransmission is handled in SipStack
            if (END_CALL == evt) {
                // rfc3261#section-15.1.1
                mState = SipSession.State.ENDING_CALL;
                mSipHelper.sendBye(mDialog);
                mProxy.onCallEnded(this);
                startSessionTimer(END_CALL_TIMER);
                return true;
            } else if (isRequestEvent(Request.INVITE, evt)) {
                // got Re-INVITE
                mState = SipSession.State.INCOMING_CALL;
                RequestEvent event = mInviteReceived = (RequestEvent) evt;
                mPeerSessionDescription = extractContent(event.getRequest());
                mServerTransaction = null;
                mProxy.onRinging(this, mPeerProfile, mPeerSessionDescription);
                return true;
            } else if (isRequestEvent(Request.BYE, evt)) {
                mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
                endCallNormally();
                return true;
            } else if (isRequestEvent(Request.REFER, evt)) {
                return processReferRequest((RequestEvent) evt);
            } else if (evt instanceof MakeCallCommand) {
                // to change call
                mState = SipSession.State.OUTGOING_CALL;
                mClientTransaction = mSipHelper.sendReinvite(mDialog,
                        ((MakeCallCommand) evt).getSessionDescription());
                startSessionTimer(((MakeCallCommand) evt).getTimeout());
                return true;
            } else if (evt instanceof ResponseEvent) {
                if (expectResponse(Request.NOTIFY, evt)) return true;
            }
            return false;
        }

        private boolean endingCall(EventObject evt) throws SipException {
            if (expectResponse(Request.BYE, evt)) {
                ResponseEvent event = (ResponseEvent) evt;
                Response response = event.getResponse();

                int statusCode = response.getStatusCode();
                switch (statusCode) {
                    case Response.UNAUTHORIZED:
                    case Response.PROXY_AUTHENTICATION_REQUIRED:
                        if (handleAuthentication(event)) {
                            return true;
                        } else {
                            // can't authenticate; pass through to end session
                        }
                }
                cancelSessionTimer();
                reset();
                return true;
            }
            return false;
        }

        // timeout in seconds
        private void startSessionTimer(int timeout) {
            if (timeout > 0) {
                mSessionTimer = new SessionTimer();
                mSessionTimer.start(timeout);
            }
        }

        private void cancelSessionTimer() {
            if (mSessionTimer != null) {
                mSessionTimer.cancel();
                mSessionTimer = null;
            }
        }

        private String createErrorMessage(Response response) {
            return String.format("%s (%d)", response.getReasonPhrase(),
                    response.getStatusCode());
        }

        private void enableKeepAlive() {
            if (mSipSessionImpl != null) {
                mSipSessionImpl.stopKeepAliveProcess();
            } else {
                mSipSessionImpl = duplicate();
            }
            try {
                mSipSessionImpl.startKeepAliveProcess(
                        INCALL_KEEPALIVE_INTERVAL, mPeerProfile, null);
            } catch (SipException e) {
                loge("keepalive cannot be enabled; ignored", e);
                mSipSessionImpl.stopKeepAliveProcess();
            }
        }

        private void establishCall(boolean enableKeepAlive) {
            mState = SipSession.State.IN_CALL;
            cancelSessionTimer();
            if (!mInCall && enableKeepAlive) enableKeepAlive();
            mInCall = true;
            mProxy.onCallEstablished(this, mPeerSessionDescription);
        }

        private void endCallNormally() {
            reset();
            mProxy.onCallEnded(this);
        }

        private void endCallOnError(int errorCode, String message) {
            reset();
            mProxy.onError(this, errorCode, message);
        }

        private void endCallOnBusy() {
            reset();
            mProxy.onCallBusy(this);
        }

        private void onError(int errorCode, String message) {
            cancelSessionTimer();
            switch (mState) {
                case SipSession.State.REGISTERING:
                case SipSession.State.DEREGISTERING:
                    onRegistrationFailed(errorCode, message);
                    break;
                default:
                    endCallOnError(errorCode, message);
            }
        }


        private void onError(Throwable exception) {
            exception = getRootCause(exception);
            onError(getErrorCode(exception), exception.toString());
        }

        private void onError(Response response) {
            int statusCode = response.getStatusCode();
            if (!mInCall && (statusCode == Response.BUSY_HERE)) {
                endCallOnBusy();
            } else {
                onError(getErrorCode(statusCode), createErrorMessage(response));
            }
        }

        private int getErrorCode(int responseStatusCode) {
            switch (responseStatusCode) {
                case Response.TEMPORARILY_UNAVAILABLE:
                case Response.FORBIDDEN:
                case Response.GONE:
                case Response.NOT_FOUND:
                case Response.NOT_ACCEPTABLE:
                case Response.NOT_ACCEPTABLE_HERE:
                    return SipErrorCode.PEER_NOT_REACHABLE;

                case Response.REQUEST_URI_TOO_LONG:
                case Response.ADDRESS_INCOMPLETE:
                case Response.AMBIGUOUS:
                    return SipErrorCode.INVALID_REMOTE_URI;

                case Response.REQUEST_TIMEOUT:
                    return SipErrorCode.TIME_OUT;

                default:
                    if (responseStatusCode < 500) {
                        return SipErrorCode.CLIENT_ERROR;
                    } else {
                        return SipErrorCode.SERVER_ERROR;
                    }
            }
        }

        private int getErrorCode(Throwable exception) {
            String message = exception.getMessage();
            if (exception instanceof UnknownHostException) {
                return SipErrorCode.SERVER_UNREACHABLE;
            } else if (exception instanceof IOException) {
                return SipErrorCode.SOCKET_ERROR;
            } else {
                return SipErrorCode.CLIENT_ERROR;
            }
        }

        private void onRegistrationDone(int duration) {
            reset();
            mProxy.onRegistrationDone(this, duration);
        }

        private void onRegistrationFailed(int errorCode, String message) {
            reset();
            mProxy.onRegistrationFailed(this, errorCode, message);
        }

        private void onRegistrationFailed(Response response) {
            int statusCode = response.getStatusCode();
            onRegistrationFailed(getErrorCode(statusCode),
                    createErrorMessage(response));
        }

        // Notes: SipSessionListener will be replaced by the keepalive process
        // @param interval in seconds
        public void startKeepAliveProcess(int interval,
                KeepAliveProcessCallback callback) throws SipException {
            synchronized (SipSessionGroup.this) {
                startKeepAliveProcess(interval, mLocalProfile, callback);
            }
        }

        // Notes: SipSessionListener will be replaced by the keepalive process
        // @param interval in seconds
        public void startKeepAliveProcess(int interval, SipProfile peerProfile,
                KeepAliveProcessCallback callback) throws SipException {
            synchronized (SipSessionGroup.this) {
                if (mSipKeepAlive != null) {
                    throw new SipException("Cannot create more than one "
                            + "keepalive process in a SipSession");
                }
                mPeerProfile = peerProfile;
                mSipKeepAlive = new SipKeepAlive();
                mProxy.setListener(mSipKeepAlive);
                mSipKeepAlive.start(interval, callback);
            }
        }

        public void stopKeepAliveProcess() {
            synchronized (SipSessionGroup.this) {
                if (mSipKeepAlive != null) {
                    mSipKeepAlive.stop();
                    mSipKeepAlive = null;
                }
            }
        }

        class SipKeepAlive extends SipSessionAdapter implements Runnable {
            private static final String SKA_TAG = "SipKeepAlive";
            private static final boolean SKA_DBG = true;

            private boolean mRunning = false;
            private KeepAliveProcessCallback mCallback;

            private boolean mPortChanged = false;
            private int mRPort = 0;
            private int mInterval; // just for debugging

            // @param interval in seconds
            void start(int interval, KeepAliveProcessCallback callback) {
                if (mRunning) return;
                mRunning = true;
                mInterval = interval;
                mCallback = new KeepAliveProcessCallbackProxy(callback);
                mWakeupTimer.set(interval * 1000, this);
                if (SKA_DBG) {
                    log("start keepalive:"
                            + mLocalProfile.getUriString());
                }

                // No need to run the first time in a separate thread for now
                run();
            }

            // return true if the event is consumed
            boolean process(EventObject evt) {
                if (mRunning && (mState == SipSession.State.PINGING)) {
                    if (evt instanceof ResponseEvent) {
                        if (parseOptionsResult(evt)) {
                            if (mPortChanged) {
                                resetExternalAddress();
                                stop();
                            } else {
                                cancelSessionTimer();
                                removeSipSession(SipSessionImpl.this);
                            }
                            mCallback.onResponse(mPortChanged);
                            return true;
                        }
                    }
                }
                return false;
            }

            // SipSessionAdapter
            // To react to the session timeout event and network error.
            @Override
            public void onError(ISipSession session, int errorCode, String message) {
                stop();
                mCallback.onError(errorCode, message);
            }

            // SipWakeupTimer timeout handler
            // To send out keepalive message.
            @Override
            public void run() {
                synchronized (SipSessionGroup.this) {
                    if (!mRunning) return;

                    if (DBG_PING) {
                        String peerUri = (mPeerProfile == null)
                                ? "null"
                                : mPeerProfile.getUriString();
                        log("keepalive: " + mLocalProfile.getUriString()
                                + " --> " + peerUri + ", interval=" + mInterval);
                    }
                    try {
                        sendKeepAlive();
                    } catch (Throwable t) {
                        if (SKA_DBG) {
                            loge("keepalive error: "
                                    + mLocalProfile.getUriString(), getRootCause(t));
                        }
                        // It's possible that the keepalive process is being stopped
                        // during session.sendKeepAlive() so need to check mRunning
                        // again here.
                        if (mRunning) SipSessionImpl.this.onError(t);
                    }
                }
            }

            void stop() {
                synchronized (SipSessionGroup.this) {
                    if (SKA_DBG) {
                        log("stop keepalive:" + mLocalProfile.getUriString()
                                + ",RPort=" + mRPort);
                    }
                    mRunning = false;
                    mWakeupTimer.cancel(this);
                    reset();
                }
            }

            private void sendKeepAlive() throws SipException {
                synchronized (SipSessionGroup.this) {
                    mState = SipSession.State.PINGING;
                    mClientTransaction = mSipHelper.sendOptions(
                            mLocalProfile, mPeerProfile, generateTag());
                    mDialog = mClientTransaction.getDialog();
                    addSipSession(SipSessionImpl.this);

                    startSessionTimer(KEEPALIVE_TIMEOUT);
                    // when timed out, onError() will be called with SipErrorCode.TIME_OUT
                }
            }

            private boolean parseOptionsResult(EventObject evt) {
                if (expectResponse(Request.OPTIONS, evt)) {
                    ResponseEvent event = (ResponseEvent) evt;
                    int rPort = getRPortFromResponse(event.getResponse());
                    if (rPort != -1) {
                        if (mRPort == 0) mRPort = rPort;
                        if (mRPort != rPort) {
                            mPortChanged = true;
                            if (SKA_DBG) log(String.format(
                                    "rport is changed: %d <> %d", mRPort, rPort));
                            mRPort = rPort;
                        } else {
                            if (SKA_DBG) log("rport is the same: " + rPort);
                        }
                    } else {
                        if (SKA_DBG) log("peer did not respond rport");
                    }
                    return true;
                }
                return false;
            }

            private int getRPortFromResponse(Response response) {
                ViaHeader viaHeader = (ViaHeader)(response.getHeader(
                        SIPHeaderNames.VIA));
                return (viaHeader == null) ? -1 : viaHeader.getRPort();
            }

            private void log(String s) {
                Rlog.d(SKA_TAG, s);
            }
        }

        private void log(String s) {
            Rlog.d(SSI_TAG, s);
        }
    }

    /**
     * @return true if the event is a request event matching the specified
     *      method; false otherwise
     */
    private static boolean isRequestEvent(String method, EventObject event) {
        try {
            if (event instanceof RequestEvent) {
                RequestEvent requestEvent = (RequestEvent) event;
                return method.equals(requestEvent.getRequest().getMethod());
            }
        } catch (Throwable e) {
        }
        return false;
    }

    private static String getCseqMethod(Message message) {
        return ((CSeqHeader) message.getHeader(CSeqHeader.NAME)).getMethod();
    }

    /**
     * @return true if the event is a response event and the CSeqHeader method
     * match the given arguments; false otherwise
     */
    private static boolean expectResponse(
            String expectedMethod, EventObject evt) {
        if (evt instanceof ResponseEvent) {
            ResponseEvent event = (ResponseEvent) evt;
            Response response = event.getResponse();
            return expectedMethod.equalsIgnoreCase(getCseqMethod(response));
        }
        return false;
    }

    private static SipProfile createPeerProfile(HeaderAddress header)
            throws SipException {
        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);
        }
    }

    private static boolean isLoggable(SipSessionImpl s) {
        if (s != null) {
            switch (s.mState) {
                case SipSession.State.PINGING:
                    return DBG_PING;
            }
        }
        return DBG;
    }

    private static boolean isLoggable(EventObject evt) {
        return isLoggable(null, evt);
    }

    private static boolean isLoggable(SipSessionImpl s, 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 String logEvt(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 class RegisterCommand extends EventObject {
        private int mDuration;

        public RegisterCommand(int duration) {
            super(SipSessionGroup.this);
            mDuration = duration;
        }

        public int getDuration() {
            return mDuration;
        }
    }

    private class MakeCallCommand extends EventObject {
        private String mSessionDescription;
        private int mTimeout; // in seconds

        public MakeCallCommand(SipProfile peerProfile,
                String sessionDescription, int timeout) {
            super(peerProfile);
            mSessionDescription = sessionDescription;
            mTimeout = timeout;
        }

        public SipProfile getPeerProfile() {
            return (SipProfile) getSource();
        }

        public String getSessionDescription() {
            return mSessionDescription;
        }

        public int getTimeout() {
            return mTimeout;
        }
    }

    /** Class to help safely run KeepAliveProcessCallback in a different thread. */
    static class KeepAliveProcessCallbackProxy implements KeepAliveProcessCallback {
        private static final String KAPCP_TAG = "KeepAliveProcessCallbackProxy";
        private KeepAliveProcessCallback mCallback;

        KeepAliveProcessCallbackProxy(KeepAliveProcessCallback callback) {
            mCallback = callback;
        }

        private void proxy(Runnable runnable) {
            // One thread for each calling back.
            // Note: Guarantee ordering if the issue becomes important. Currently,
            // the chance of handling two callback events at a time is none.
            new Thread(runnable, "SIP-KeepAliveProcessCallbackThread").start();
        }

        @Override
        public void onResponse(final boolean portChanged) {
            if (mCallback == null) return;
            proxy(new Runnable() {
                @Override
                public void run() {
                    try {
                        mCallback.onResponse(portChanged);
                    } catch (Throwable t) {
                        loge("onResponse", t);
                    }
                }
            });
        }

        @Override
        public void onError(final int errorCode, final String description) {
            if (mCallback == null) return;
            proxy(new Runnable() {
                @Override
                public void run() {
                    try {
                        mCallback.onError(errorCode, description);
                    } catch (Throwable t) {
                        loge("onError", t);
                    }
                }
            });
        }

        private void loge(String s, Throwable t) {
            Rlog.e(KAPCP_TAG, s, t);
        }
    }

    private void log(String s) {
        Rlog.d(TAG, s);
    }

    private void loge(String s, Throwable t) {
        Rlog.e(TAG, s, t);
    }
}
