SipHelper.java revision 8a044dee1690c3dc7b5f467461ce4fa65c565a66
19c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/*
29c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Copyright (C) 2010 The Android Open Source Project
39c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan *
49c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Licensed under the Apache License, Version 2.0 (the "License");
59c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * you may not use this file except in compliance with the License.
69c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * You may obtain a copy of the License at
79c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan *
89c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan *      http://www.apache.org/licenses/LICENSE-2.0
99c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan *
109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Unless required by applicable law or agreed to in writing, software
119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * distributed under the License is distributed on an "AS IS" BASIS,
129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * See the License for the specific language governing permissions and
149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * limitations under the License.
159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */
169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpackage com.android.server.sip;
189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport gov.nist.javax.sip.SipStackExt;
209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport gov.nist.javax.sip.clientauthutils.AccountManager;
219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport gov.nist.javax.sip.clientauthutils.AuthenticationHelper;
229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipProfile;
249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.util.Log;
259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.text.ParseException;
279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.ArrayList;
289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.EventObject;
299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.List;
30cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandbergimport java.util.regex.Pattern;
31cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ClientTransaction;
339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.Dialog;
349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.DialogTerminatedEvent;
359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.InvalidArgumentException;
369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ListeningPoint;
379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.PeerUnavailableException;
389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.RequestEvent;
399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ResponseEvent;
409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ServerTransaction;
419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipException;
429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipFactory;
439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipProvider;
449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipStack;
459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.Transaction;
469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.TransactionAlreadyExistsException;
479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.TransactionTerminatedEvent;
489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.TransactionUnavailableException;
499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.TransactionState;
509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.address.Address;
519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.address.AddressFactory;
529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.address.SipURI;
539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.CSeqHeader;
549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.CallIdHeader;
559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.ContactHeader;
569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.FromHeader;
579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.Header;
589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.HeaderFactory;
599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.MaxForwardsHeader;
609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.ToHeader;
619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.ViaHeader;
629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.Message;
639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.MessageFactory;
649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.Request;
659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.Response;
669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/**
689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Helper class for holding SIP stack related classes and for various low-level
699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * SIP tasks like sending messages.
709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */
719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanclass SipHelper {
729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static final String TAG = SipHelper.class.getSimpleName();
739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static final boolean DEBUG = true;
748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    private static final boolean DEBUG_PING = false;
759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private SipStack mSipStack;
779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private SipProvider mSipProvider;
789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private AddressFactory mAddressFactory;
799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private HeaderFactory mHeaderFactory;
809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private MessageFactory mMessageFactory;
819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public SipHelper(SipStack sipStack, SipProvider sipProvider)
839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws PeerUnavailableException {
849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mSipStack = sipStack;
859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mSipProvider = sipProvider;
869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        SipFactory sipFactory = SipFactory.getInstance();
889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mAddressFactory = sipFactory.createAddressFactory();
899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mHeaderFactory = sipFactory.createHeaderFactory();
909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mMessageFactory = sipFactory.createMessageFactory();
919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private FromHeader createFromHeader(SipProfile profile, String tag)
949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException {
959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createFromHeader(profile.getSipAddress(), tag);
969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ToHeader createToHeader(SipProfile profile) throws ParseException {
999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return createToHeader(profile, null);
1009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ToHeader createToHeader(SipProfile profile, String tag)
1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException {
1049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createToHeader(profile.getSipAddress(), tag);
1059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private CallIdHeader createCallIdHeader() {
1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mSipProvider.getNewCallId();
1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private CSeqHeader createCSeqHeader(String method)
1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException, InvalidArgumentException {
1139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        long sequence = (long) (Math.random() * 10000);
1149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createCSeqHeader(sequence, method);
1159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private MaxForwardsHeader createMaxForwardsHeader()
1189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws InvalidArgumentException {
1199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createMaxForwardsHeader(70);
1209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private MaxForwardsHeader createMaxForwardsHeader(int max)
1239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws InvalidArgumentException {
1249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createMaxForwardsHeader(max);
1259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ListeningPoint getListeningPoint() throws SipException {
1289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ListeningPoint lp = mSipProvider.getListeningPoint(ListeningPoint.UDP);
1299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (lp == null) lp = mSipProvider.getListeningPoint(ListeningPoint.TCP);
1309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (lp == null) {
1319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ListeningPoint[] lps = mSipProvider.getListeningPoints();
1329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if ((lps != null) && (lps.length > 0)) lp = lps[0];
1339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (lp == null) {
1359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("no listening point is available");
1369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return lp;
1389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private List<ViaHeader> createViaHeaders()
1419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException, SipException {
1429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        List<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(1);
1439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ListeningPoint lp = getListeningPoint();
1449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ViaHeader viaHeader = mHeaderFactory.createViaHeader(lp.getIPAddress(),
1459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                lp.getPort(), lp.getTransport(), null);
1469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        viaHeader.setRPort();
1479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        viaHeaders.add(viaHeader);
1489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return viaHeaders;
1499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ContactHeader createContactHeader(SipProfile profile)
1529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException, SipException {
1539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ListeningPoint lp = getListeningPoint();
1549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        SipURI contactURI =
1559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                createSipUri(profile.getUserName(), profile.getProtocol(), lp);
1569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Address contactAddress = mAddressFactory.createAddress(contactURI);
1589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        contactAddress.setDisplayName(profile.getDisplayName());
1599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createContactHeader(contactAddress);
1619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ContactHeader createWildcardContactHeader() {
1649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ContactHeader contactHeader  = mHeaderFactory.createContactHeader();
1659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        contactHeader.setWildCard();
1669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return contactHeader;
1679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private SipURI createSipUri(String username, String transport,
1709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ListeningPoint lp) throws ParseException {
1719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        SipURI uri = mAddressFactory.createSipURI(username, lp.getIPAddress());
1729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
1739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            uri.setPort(lp.getPort());
1749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            uri.setTransportParam(transport);
1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (InvalidArgumentException e) {
1769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new RuntimeException(e);
1779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return uri;
1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    public ClientTransaction sendOptions(SipProfile caller, SipProfile callee,
1828a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            String tag) throws SipException {
1839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
1848a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            Request request = (caller == callee)
1858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    ? createRequest(Request.OPTIONS, caller, tag)
1868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    : createRequest(Request.OPTIONS, caller, callee, tag);
1879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
1899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
1909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            clientTransaction.sendRequest();
1919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
1929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (Exception e) {
1938a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            throw new SipException("sendOptions()", e);
1949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction sendRegister(SipProfile userProfile, String tag,
1989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            int expiry) throws SipException {
1999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
2009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = createRequest(Request.REGISTER, userProfile, tag);
2019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (expiry == 0) {
2029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                // remove all previous registrations by wildcard
2039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                // rfc3261#section-10.2.2
2049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                request.addHeader(createWildcardContactHeader());
2059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            } else {
2069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                request.addHeader(createContactHeader(userProfile));
2079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
2089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            request.addHeader(mHeaderFactory.createExpiresHeader(expiry));
2099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
2119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
2129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            clientTransaction.sendRequest();
2139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
2149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
2159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendRegister()", e);
2169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
2179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private Request createRequest(String requestType, SipProfile userProfile,
2209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            String tag) throws ParseException, SipException {
2219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        FromHeader fromHeader = createFromHeader(userProfile, tag);
2229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ToHeader toHeader = createToHeader(userProfile);
223cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
224cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg        String replaceStr = Pattern.quote(userProfile.getUserName() + "@");
2252e45c0b8f84172a004df4e3a1f50dbf1235474ebChung-yih Wang        SipURI requestURI = mAddressFactory.createSipURI(
226cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg                userProfile.getUriString().replaceFirst(replaceStr, ""));
227cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
2289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        List<ViaHeader> viaHeaders = createViaHeaders();
2299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        CallIdHeader callIdHeader = createCallIdHeader();
2309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        CSeqHeader cSeqHeader = createCSeqHeader(requestType);
2319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        MaxForwardsHeader maxForwards = createMaxForwardsHeader();
2329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request request = mMessageFactory.createRequest(requestURI,
2339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                requestType, callIdHeader, cSeqHeader, fromHeader,
2349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                toHeader, viaHeaders, maxForwards);
2359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Header userAgentHeader = mHeaderFactory.createHeader("User-Agent",
2369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                "SIPAUA/0.1.001");
2379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        request.addHeader(userAgentHeader);
2389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return request;
2399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction handleChallenge(ResponseEvent responseEvent,
2429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            AccountManager accountManager) throws SipException {
2439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        AuthenticationHelper authenticationHelper =
2449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                ((SipStackExt) mSipStack).getAuthenticationHelper(
2459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                        accountManager, mHeaderFactory);
2469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ClientTransaction tid = responseEvent.getClientTransaction();
2479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ClientTransaction ct = authenticationHelper.handleChallenge(
2489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                responseEvent.getResponse(), tid, mSipProvider, 5);
249e9fe79e34d2c4100cd391bcf21df8bd50d5f3228Hung-ying Tyan        if (DEBUG) Log.d(TAG, "send request with challenge response: "
250e9fe79e34d2c4100cd391bcf21df8bd50d5f3228Hung-ying Tyan                + ct.getRequest());
2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ct.sendRequest();
2529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return ct;
2539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    private Request createRequest(String requestType, SipProfile caller,
2568a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            SipProfile callee, String tag) throws ParseException, SipException {
2578a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        FromHeader fromHeader = createFromHeader(caller, tag);
2588a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        ToHeader toHeader = createToHeader(callee);
2598a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        SipURI requestURI = callee.getUri();
2608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        List<ViaHeader> viaHeaders = createViaHeaders();
2618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        CallIdHeader callIdHeader = createCallIdHeader();
2628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        CSeqHeader cSeqHeader = createCSeqHeader(requestType);
2638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        MaxForwardsHeader maxForwards = createMaxForwardsHeader();
2648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        Request request = mMessageFactory.createRequest(requestURI,
2668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                requestType, callIdHeader, cSeqHeader, fromHeader,
2678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                toHeader, viaHeaders, maxForwards);
2688a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        request.addHeader(createContactHeader(caller));
2708a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        return request;
2718a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    }
2728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction sendInvite(SipProfile caller, SipProfile callee,
2749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            String sessionDescription, String tag)
2759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
2769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
2778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            Request request = createRequest(Request.INVITE, caller, callee, tag);
2789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            request.setContent(sessionDescription,
2799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mHeaderFactory.createContentTypeHeader(
2809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                            "application", "sdp"));
2819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
2839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
2849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (DEBUG) Log.d(TAG, "send INVITE: " + request);
2859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            clientTransaction.sendRequest();
2869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
2879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
2889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInvite()", e);
2899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction sendReinvite(Dialog dialog,
2939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            String sessionDescription) throws SipException {
2949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
2959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = dialog.createRequest(Request.INVITE);
2969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            request.setContent(sessionDescription,
2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mHeaderFactory.createContentTypeHeader(
2989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                            "application", "sdp"));
2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
300a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            // Adding rport argument in the request could fix some SIP servers
301a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            // in resolving the initiator's NAT port mapping for relaying the
302a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            // response message from the other end.
303a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang
304a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
305a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            if (viaHeader != null) viaHeader.setRPort();
306a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang
3079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (DEBUG) Log.d(TAG, "send RE-INVITE: " + request);
3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            dialog.sendRequest(clientTransaction);
3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
3129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendReinvite()", e);
3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ServerTransaction getServerTransaction(RequestEvent event)
3189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
3199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ServerTransaction transaction = event.getServerTransaction();
3209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (transaction == null) {
3219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return mSipProvider.getNewServerTransaction(request);
3239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else {
3249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return transaction;
3259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /**
3299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     * @param event the INVITE request event
3309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     */
3319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ServerTransaction sendRinging(RequestEvent event, String tag)
3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
3339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
3349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction transaction = getServerTransaction(event);
3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(Response.RINGING,
3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    request);
3399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            toHeader.setTag(tag);
3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            response.addHeader(toHeader);
3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (DEBUG) Log.d(TAG, "send RINGING: " + response);
3449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            transaction.sendResponse(response);
3459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return transaction;
3469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendRinging()", e);
3489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /**
3529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     * @param event the INVITE request event
3539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     */
3549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ServerTransaction sendInviteOk(RequestEvent event,
3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            SipProfile localProfile, String sessionDescription,
3569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction inviteTransaction)
3579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
3589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
3599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(Response.OK,
3619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    request);
3629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            response.addHeader(createContactHeader(localProfile));
3639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            response.setContent(sessionDescription,
3649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mHeaderFactory.createContentTypeHeader(
3659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                            "application", "sdp"));
3669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (inviteTransaction == null) {
3689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                inviteTransaction = getServerTransaction(event);
3699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
3709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (inviteTransaction.getState() != TransactionState.COMPLETED) {
3729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                if (DEBUG) Log.d(TAG, "send OK: " + response);
3739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                inviteTransaction.sendResponse(response);
3749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
3759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return inviteTransaction;
3779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInviteOk()", e);
3799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendInviteBusyHere(RequestEvent event,
3839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction inviteTransaction) throws SipException {
3849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
3859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(
3879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    Response.BUSY_HERE, request);
3889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
389ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan            if (inviteTransaction == null) {
390ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan                inviteTransaction = getServerTransaction(event);
391ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan            }
392ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan
3939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (inviteTransaction.getState() != TransactionState.COMPLETED) {
3949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                if (DEBUG) Log.d(TAG, "send BUSY HERE: " + response);
3959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                inviteTransaction.sendResponse(response);
3969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
3979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInviteBusyHere()", e);
3999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /**
4039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     * @param event the INVITE ACK request event
4049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     */
4059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendInviteAck(ResponseEvent event, Dialog dialog)
4069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
4079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Response response = event.getResponse();
4089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        long cseq = ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
4099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                .getSeqNumber();
4109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request ack = dialog.createAck(cseq);
4119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (DEBUG) Log.d(TAG, "send ACK: " + ack);
4129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        dialog.sendAck(ack);
4139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendBye(Dialog dialog) throws SipException {
4169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request byeRequest = dialog.createRequest(Request.BYE);
4179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (DEBUG) Log.d(TAG, "send BYE: " + byeRequest);
4189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        dialog.sendRequest(mSipProvider.getNewClientTransaction(byeRequest));
4199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendCancel(ClientTransaction inviteTransaction)
4229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
4239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request cancelRequest = inviteTransaction.createCancel();
4249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (DEBUG) Log.d(TAG, "send CANCEL: " + cancelRequest);
4259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mSipProvider.getNewClientTransaction(cancelRequest).sendRequest();
4269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendResponse(RequestEvent event, int responseCode)
4299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
4309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
4318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            Request request = event.getRequest();
4329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(
4338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    responseCode, request);
4348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            if (DEBUG && (!Request.OPTIONS.equals(request.getMethod())
4358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    || DEBUG_PING)) {
4368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                Log.d(TAG, "send response: " + response);
4378a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            }
4389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            getServerTransaction(event).sendResponse(response);
4399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
4409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendResponse()", e);
4419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendInviteRequestTerminated(Request inviteRequest,
4459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction inviteTransaction) throws SipException {
4469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
4479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(
4489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    Response.REQUEST_TERMINATED, inviteRequest);
4499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (DEBUG) Log.d(TAG, "send response: " + response);
4509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            inviteTransaction.sendResponse(response);
4519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
4529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInviteRequestTerminated()", e);
4539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public static String getCallId(EventObject event) {
4579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (event == null) return null;
4589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (event instanceof RequestEvent) {
4599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(((RequestEvent) event).getRequest());
4609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else if (event instanceof ResponseEvent) {
4619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(((ResponseEvent) event).getResponse());
4629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else if (event instanceof DialogTerminatedEvent) {
4639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Dialog dialog = ((DialogTerminatedEvent) event).getDialog();
4649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(((DialogTerminatedEvent) event).getDialog());
4659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else if (event instanceof TransactionTerminatedEvent) {
4669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            TransactionTerminatedEvent e = (TransactionTerminatedEvent) event;
4679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(e.isServerTransaction()
4689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    ? e.getServerTransaction()
4699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    : e.getClientTransaction());
4709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else {
4719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Object source = event.getSource();
4729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (source instanceof Transaction) {
4739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                return getCallId(((Transaction) source));
4749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            } else if (source instanceof Dialog) {
4759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                return getCallId((Dialog) source);
4769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
4779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return "";
4799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public static String getCallId(Transaction transaction) {
4829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return ((transaction != null) ? getCallId(transaction.getRequest())
4839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                                      : "");
4849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static String getCallId(Message message) {
4879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        CallIdHeader callIdHeader =
4889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                (CallIdHeader) message.getHeader(CallIdHeader.NAME);
4899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return callIdHeader.getCallId();
4909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static String getCallId(Dialog dialog) {
4939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return dialog.getCallId().getCallId();
4949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
496