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;
22f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo syncimport gov.nist.javax.sip.header.extensions.ReferencesHeader;
23f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo syncimport gov.nist.javax.sip.header.extensions.ReferredByHeader;
24f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo syncimport gov.nist.javax.sip.header.extensions.ReplacesHeader;
259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipProfile;
279329db04f13480ccdff013dcc00cdb96f12a921cWink Savilleimport android.telephony.Rlog;
289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.text.ParseException;
309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.ArrayList;
319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.EventObject;
329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.List;
33cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandbergimport java.util.regex.Pattern;
34cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ClientTransaction;
369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.Dialog;
379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.DialogTerminatedEvent;
389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.InvalidArgumentException;
399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ListeningPoint;
409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.PeerUnavailableException;
419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.RequestEvent;
429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ResponseEvent;
439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.ServerTransaction;
449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipException;
459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipFactory;
469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipProvider;
479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipStack;
489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.Transaction;
499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.TransactionTerminatedEvent;
509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.TransactionState;
519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.address.Address;
529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.address.AddressFactory;
539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.address.SipURI;
549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.CSeqHeader;
559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.CallIdHeader;
569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.ContactHeader;
579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.FromHeader;
589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.Header;
599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.HeaderFactory;
609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.MaxForwardsHeader;
619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.ToHeader;
629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.header.ViaHeader;
639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.Message;
649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.MessageFactory;
659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.Request;
669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.message.Response;
679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/**
699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Helper class for holding SIP stack related classes and for various low-level
709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * SIP tasks like sending messages.
719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */
729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanclass SipHelper {
739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static final String TAG = SipHelper.class.getSimpleName();
749329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    private static final boolean DBG = false;
759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    private static final boolean DBG_PING = false;
769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private SipStack mSipStack;
789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private SipProvider mSipProvider;
799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private AddressFactory mAddressFactory;
809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private HeaderFactory mHeaderFactory;
819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private MessageFactory mMessageFactory;
829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public SipHelper(SipStack sipStack, SipProvider sipProvider)
849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws PeerUnavailableException {
859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mSipStack = sipStack;
869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mSipProvider = sipProvider;
879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        SipFactory sipFactory = SipFactory.getInstance();
899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mAddressFactory = sipFactory.createAddressFactory();
909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mHeaderFactory = sipFactory.createHeaderFactory();
919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mMessageFactory = sipFactory.createMessageFactory();
929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private FromHeader createFromHeader(SipProfile profile, String tag)
959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException {
969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createFromHeader(profile.getSipAddress(), tag);
979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ToHeader createToHeader(SipProfile profile) throws ParseException {
1009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return createToHeader(profile, null);
1019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ToHeader createToHeader(SipProfile profile, String tag)
1049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException {
1059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createToHeader(profile.getSipAddress(), tag);
1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private CallIdHeader createCallIdHeader() {
1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mSipProvider.getNewCallId();
1109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private CSeqHeader createCSeqHeader(String method)
1139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException, InvalidArgumentException {
1149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        long sequence = (long) (Math.random() * 10000);
1159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createCSeqHeader(sequence, method);
1169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private MaxForwardsHeader createMaxForwardsHeader()
1199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws InvalidArgumentException {
1209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createMaxForwardsHeader(70);
1219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private MaxForwardsHeader createMaxForwardsHeader(int max)
1249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws InvalidArgumentException {
1259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createMaxForwardsHeader(max);
1269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ListeningPoint getListeningPoint() throws SipException {
1299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ListeningPoint lp = mSipProvider.getListeningPoint(ListeningPoint.UDP);
1309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (lp == null) lp = mSipProvider.getListeningPoint(ListeningPoint.TCP);
1319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (lp == null) {
1329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ListeningPoint[] lps = mSipProvider.getListeningPoints();
1339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if ((lps != null) && (lps.length > 0)) lp = lps[0];
1349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (lp == null) {
1369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("no listening point is available");
1379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return lp;
1399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private List<ViaHeader> createViaHeaders()
1429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException, SipException {
1439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        List<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(1);
1449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ListeningPoint lp = getListeningPoint();
1459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ViaHeader viaHeader = mHeaderFactory.createViaHeader(lp.getIPAddress(),
1469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                lp.getPort(), lp.getTransport(), null);
1479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        viaHeader.setRPort();
1489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        viaHeaders.add(viaHeader);
1499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return viaHeaders;
1509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ContactHeader createContactHeader(SipProfile profile)
1539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws ParseException, SipException {
1543efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan        return createContactHeader(profile, null, 0);
1553efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    }
1563efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan
1573efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    private ContactHeader createContactHeader(SipProfile profile,
1583efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            String ip, int port) throws ParseException,
1593efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            SipException {
1603efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan        SipURI contactURI = (ip == null)
1613efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan                ? createSipUri(profile.getUserName(), profile.getProtocol(),
1623efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan                        getListeningPoint())
1633efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan                : createSipUri(profile.getUserName(), profile.getProtocol(),
1643efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan                        ip, port);
1659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Address contactAddress = mAddressFactory.createAddress(contactURI);
1679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        contactAddress.setDisplayName(profile.getDisplayName());
1689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return mHeaderFactory.createContactHeader(contactAddress);
1709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private ContactHeader createWildcardContactHeader() {
1739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ContactHeader contactHeader  = mHeaderFactory.createContactHeader();
1749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        contactHeader.setWildCard();
1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return contactHeader;
1769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private SipURI createSipUri(String username, String transport,
1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ListeningPoint lp) throws ParseException {
1803efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan        return createSipUri(username, transport, lp.getIPAddress(), lp.getPort());
1813efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    }
1823efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan
1833efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    private SipURI createSipUri(String username, String transport,
1843efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            String ip, int port) throws ParseException {
1853efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan        SipURI uri = mAddressFactory.createSipURI(username, ip);
1869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
1873efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            uri.setPort(port);
1889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            uri.setTransportParam(transport);
1899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (InvalidArgumentException e) {
1909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new RuntimeException(e);
1919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
1929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return uri;
1939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1958a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    public ClientTransaction sendOptions(SipProfile caller, SipProfile callee,
1968a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            String tag) throws SipException {
1979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
1988a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            Request request = (caller == callee)
1998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    ? createRequest(Request.OPTIONS, caller, tag)
2008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    : createRequest(Request.OPTIONS, caller, callee, tag);
2019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
2039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
2049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            clientTransaction.sendRequest();
2059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
2069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (Exception e) {
2078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            throw new SipException("sendOptions()", e);
2089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
2099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction sendRegister(SipProfile userProfile, String tag,
2129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            int expiry) throws SipException {
2139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
2149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = createRequest(Request.REGISTER, userProfile, tag);
2159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (expiry == 0) {
2169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                // remove all previous registrations by wildcard
2179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                // rfc3261#section-10.2.2
2189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                request.addHeader(createWildcardContactHeader());
2199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            } else {
2209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                request.addHeader(createContactHeader(userProfile));
2219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
2229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            request.addHeader(mHeaderFactory.createExpiresHeader(expiry));
2239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
2259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
2269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            clientTransaction.sendRequest();
2279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
2289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
2299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendRegister()", e);
2309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
2319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private Request createRequest(String requestType, SipProfile userProfile,
2349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            String tag) throws ParseException, SipException {
2359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        FromHeader fromHeader = createFromHeader(userProfile, tag);
2369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ToHeader toHeader = createToHeader(userProfile);
237cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
238cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg        String replaceStr = Pattern.quote(userProfile.getUserName() + "@");
2392e45c0b8f84172a004df4e3a1f50dbf1235474ebChung-yih Wang        SipURI requestURI = mAddressFactory.createSipURI(
240cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg                userProfile.getUriString().replaceFirst(replaceStr, ""));
241cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
2429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        List<ViaHeader> viaHeaders = createViaHeaders();
2439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        CallIdHeader callIdHeader = createCallIdHeader();
2449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        CSeqHeader cSeqHeader = createCSeqHeader(requestType);
2459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        MaxForwardsHeader maxForwards = createMaxForwardsHeader();
2469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request request = mMessageFactory.createRequest(requestURI,
2479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                requestType, callIdHeader, cSeqHeader, fromHeader,
2489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                toHeader, viaHeaders, maxForwards);
2499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Header userAgentHeader = mHeaderFactory.createHeader("User-Agent",
2509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                "SIPAUA/0.1.001");
2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        request.addHeader(userAgentHeader);
2529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return request;
2539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction handleChallenge(ResponseEvent responseEvent,
2569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            AccountManager accountManager) throws SipException {
2579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        AuthenticationHelper authenticationHelper =
2589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                ((SipStackExt) mSipStack).getAuthenticationHelper(
2599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                        accountManager, mHeaderFactory);
2609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ClientTransaction tid = responseEvent.getClientTransaction();
2619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ClientTransaction ct = authenticationHelper.handleChallenge(
2629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                responseEvent.getResponse(), tid, mSipProvider, 5);
2639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville        if (DBG) log("send request with challenge response: "
264e9fe79e34d2c4100cd391bcf21df8bd50d5f3228Hung-ying Tyan                + ct.getRequest());
2659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ct.sendRequest();
2669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return ct;
2679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    private Request createRequest(String requestType, SipProfile caller,
2708a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            SipProfile callee, String tag) throws ParseException, SipException {
2718a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        FromHeader fromHeader = createFromHeader(caller, tag);
2728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        ToHeader toHeader = createToHeader(callee);
2738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        SipURI requestURI = callee.getUri();
2748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        List<ViaHeader> viaHeaders = createViaHeaders();
2758a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        CallIdHeader callIdHeader = createCallIdHeader();
2768a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        CSeqHeader cSeqHeader = createCSeqHeader(requestType);
2778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        MaxForwardsHeader maxForwards = createMaxForwardsHeader();
2788a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2798a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        Request request = mMessageFactory.createRequest(requestURI,
2808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                requestType, callIdHeader, cSeqHeader, fromHeader,
2818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                toHeader, viaHeaders, maxForwards);
2828a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        request.addHeader(createContactHeader(caller));
2848a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        return request;
2858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    }
2868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction sendInvite(SipProfile caller, SipProfile callee,
288f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            String sessionDescription, String tag, ReferredByHeader referredBy,
289f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            String replaces) throws SipException {
2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
2918a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            Request request = createRequest(Request.INVITE, caller, callee, tag);
292f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            if (referredBy != null) request.addHeader(referredBy);
293f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            if (replaces != null) {
294f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                request.addHeader(mHeaderFactory.createHeader(
295f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                        ReplacesHeader.NAME, replaces));
296f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            }
2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            request.setContent(sessionDescription,
2989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mHeaderFactory.createContentTypeHeader(
2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                            "application", "sdp"));
3009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
3019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
3029329db04f13480ccdff013dcc00cdb96f12a921cWink Saville            if (DBG) log("send INVITE: " + request);
3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            clientTransaction.sendRequest();
3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
3059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInvite()", e);
3079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ClientTransaction sendReinvite(Dialog dialog,
3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            String sessionDescription) throws SipException {
3129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
3139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = dialog.createRequest(Request.INVITE);
3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            request.setContent(sessionDescription,
3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mHeaderFactory.createContentTypeHeader(
3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                            "application", "sdp"));
3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
318a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            // Adding rport argument in the request could fix some SIP servers
319a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            // in resolving the initiator's NAT port mapping for relaying the
320a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            // response message from the other end.
321a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang
322a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
323a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            if (viaHeader != null) viaHeader.setRPort();
324a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang
3259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ClientTransaction clientTransaction =
3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mSipProvider.getNewClientTransaction(request);
3279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville            if (DBG) log("send RE-INVITE: " + request);
3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            dialog.sendRequest(clientTransaction);
3299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return clientTransaction;
3309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendReinvite()", e);
3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
33522ecc3df834674605daf86f7edf20169b6ca800brepo sync    public ServerTransaction getServerTransaction(RequestEvent event)
3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ServerTransaction transaction = event.getServerTransaction();
3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (transaction == null) {
3399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return mSipProvider.getNewServerTransaction(request);
3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else {
3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return transaction;
3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /**
3479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     * @param event the INVITE request event
3489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     */
3499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ServerTransaction sendRinging(RequestEvent event, String tag)
3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
3519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
3529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction transaction = getServerTransaction(event);
3549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(Response.RINGING,
3569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    request);
3579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
3599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            toHeader.setTag(tag);
3609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            response.addHeader(toHeader);
3619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville            if (DBG) log("send RINGING: " + response);
3629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            transaction.sendResponse(response);
3639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return transaction;
3649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendRinging()", e);
3669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /**
3709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     * @param event the INVITE request event
3719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     */
3729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public ServerTransaction sendInviteOk(RequestEvent event,
3739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            SipProfile localProfile, String sessionDescription,
3743efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            ServerTransaction inviteTransaction, String externalIp,
3753efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            int externalPort) throws SipException {
3769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
3779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
3789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(Response.OK,
3799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    request);
3803efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan            response.addHeader(createContactHeader(localProfile, externalIp,
3813efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan                    externalPort));
3829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            response.setContent(sessionDescription,
3839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    mHeaderFactory.createContentTypeHeader(
3849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                            "application", "sdp"));
3859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (inviteTransaction == null) {
3879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                inviteTransaction = getServerTransaction(event);
3889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
3899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (inviteTransaction.getState() != TransactionState.COMPLETED) {
3919329db04f13480ccdff013dcc00cdb96f12a921cWink Saville                if (DBG) log("send OK: " + response);
3929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                inviteTransaction.sendResponse(response);
3939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
3949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return inviteTransaction;
3969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
3979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInviteOk()", e);
3989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendInviteBusyHere(RequestEvent event,
4029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction inviteTransaction) throws SipException {
4039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
4049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Request request = event.getRequest();
4059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(
4069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    Response.BUSY_HERE, request);
4079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
408ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan            if (inviteTransaction == null) {
409ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan                inviteTransaction = getServerTransaction(event);
410ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan            }
411ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan
4129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (inviteTransaction.getState() != TransactionState.COMPLETED) {
4139329db04f13480ccdff013dcc00cdb96f12a921cWink Saville                if (DBG) log("send BUSY HERE: " + response);
4149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                inviteTransaction.sendResponse(response);
4159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
4169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
4179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInviteBusyHere()", e);
4189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /**
4229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     * @param event the INVITE ACK request event
4239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     */
4249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendInviteAck(ResponseEvent event, Dialog dialog)
4259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
4269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Response response = event.getResponse();
4279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        long cseq = ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
4289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                .getSeqNumber();
4299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request ack = dialog.createAck(cseq);
4309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville        if (DBG) log("send ACK: " + ack);
4319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        dialog.sendAck(ack);
4329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendBye(Dialog dialog) throws SipException {
4359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request byeRequest = dialog.createRequest(Request.BYE);
4369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville        if (DBG) log("send BYE: " + byeRequest);
4379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        dialog.sendRequest(mSipProvider.getNewClientTransaction(byeRequest));
4389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendCancel(ClientTransaction inviteTransaction)
4419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
4429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        Request cancelRequest = inviteTransaction.createCancel();
4439329db04f13480ccdff013dcc00cdb96f12a921cWink Saville        if (DBG) log("send CANCEL: " + cancelRequest);
4449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        mSipProvider.getNewClientTransaction(cancelRequest).sendRequest();
4459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendResponse(RequestEvent event, int responseCode)
4489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throws SipException {
4499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
4508a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            Request request = event.getRequest();
4519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(
4528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan                    responseCode, request);
4539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville            if (DBG && (!Request.OPTIONS.equals(request.getMethod())
4549329db04f13480ccdff013dcc00cdb96f12a921cWink Saville                    || DBG_PING)) {
4559329db04f13480ccdff013dcc00cdb96f12a921cWink Saville                log("send response: " + response);
4568a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan            }
4579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            getServerTransaction(event).sendResponse(response);
4589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
4599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendResponse()", e);
4609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
463f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync    public void sendReferNotify(Dialog dialog, String content)
464f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            throws SipException {
465f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync        try {
466f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            Request request = dialog.createRequest(Request.NOTIFY);
467f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            request.addHeader(mHeaderFactory.createSubscriptionStateHeader(
468f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                    "active;expires=60"));
469f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            // set content here
470f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            request.setContent(content,
471f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                    mHeaderFactory.createContentTypeHeader(
472f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                            "message", "sipfrag"));
473f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            request.addHeader(mHeaderFactory.createEventHeader(
474f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                    ReferencesHeader.REFER));
4759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville            if (DBG) log("send NOTIFY: " + request);
476f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            dialog.sendRequest(mSipProvider.getNewClientTransaction(request));
477f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync        } catch (ParseException e) {
478f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync            throw new SipException("sendReferNotify()", e);
479f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync        }
480f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync    }
481f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync
4829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public void sendInviteRequestTerminated(Request inviteRequest,
4839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ServerTransaction inviteTransaction) throws SipException {
4849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        try {
4859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Response response = mMessageFactory.createResponse(
4869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    Response.REQUEST_TERMINATED, inviteRequest);
4879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville            if (DBG) log("send response: " + response);
4889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            inviteTransaction.sendResponse(response);
4899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } catch (ParseException e) {
4909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            throw new SipException("sendInviteRequestTerminated()", e);
4919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
4929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
4939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public static String getCallId(EventObject event) {
4959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (event == null) return null;
4969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (event instanceof RequestEvent) {
4979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(((RequestEvent) event).getRequest());
4989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else if (event instanceof ResponseEvent) {
4999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(((ResponseEvent) event).getResponse());
5009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else if (event instanceof DialogTerminatedEvent) {
5019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Dialog dialog = ((DialogTerminatedEvent) event).getDialog();
5029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(((DialogTerminatedEvent) event).getDialog());
5039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else if (event instanceof TransactionTerminatedEvent) {
5049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            TransactionTerminatedEvent e = (TransactionTerminatedEvent) event;
5059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return getCallId(e.isServerTransaction()
5069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    ? e.getServerTransaction()
5079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                    : e.getClientTransaction());
5089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else {
5099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            Object source = event.getSource();
5109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (source instanceof Transaction) {
5119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                return getCallId(((Transaction) source));
5129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            } else if (source instanceof Dialog) {
5139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                return getCallId((Dialog) source);
5149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
5159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
5169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return "";
5179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
5189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
5199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    public static String getCallId(Transaction transaction) {
5209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return ((transaction != null) ? getCallId(transaction.getRequest())
5219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                                      : "");
5229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
5239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
5249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static String getCallId(Message message) {
5259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        CallIdHeader callIdHeader =
5269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                (CallIdHeader) message.getHeader(CallIdHeader.NAME);
5279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return callIdHeader.getCallId();
5289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
5299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
5309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    private static String getCallId(Dialog dialog) {
5319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return dialog.getCallId().getCallId();
5329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
5339329db04f13480ccdff013dcc00cdb96f12a921cWink Saville
5349329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    private void log(String s) {
5359329db04f13480ccdff013dcc00cdb96f12a921cWink Saville        Rlog.d(TAG, s);
5369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    }
5379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
538