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