1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/****************************************************************************** 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD). * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/ 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.InternalErrorHandler; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.SipUri; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Contact; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Event; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ReferTo; 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RetryAfter; 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Route; 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.RouteList; 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Server; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.MessageFactoryImpl; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPResponse; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.MessageChannel; 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPClientTransaction; 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPDialog; 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPServerTransaction; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransaction; 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.ServerRequestInterface; 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.ServerResponseInterface; 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.IOException; 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.TimerTask; 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ClientTransaction; 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.DialogState; 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.InvalidArgumentException; 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ObjectInUseException; 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.RequestEvent; 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ResponseEvent; 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ServerTransaction; 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipException; 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipProvider; 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TransactionState; 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CSeqHeader; 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.EventHeader; 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ReferToHeader; 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ServerHeader; 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Request; 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Response; 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Bug fix Contributions by Lamine Brahimi, Andreas Bystrom, Bill Roome, John Martin, Daniel 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Machin Vasquez-Illa, Antonis Karydas, Joe Provino, Bruce Evangelder, Jeroen van Bemmel, Robert 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * S. Rosen. 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * An adapter class from the JAIN implementation objects to the NIST-SIP stack. The primary 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * purpose of this class is to do early rejection of bad messages and deliver meaningful messages 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to the application. This class is essentially a Dialog filter. It is a helper for the UAC Core. 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * It checks for and rejects requests and responses which may be filtered out because of sequence 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * number, Dialog not found, etc. Note that this is not part of the JAIN-SIP spec (it does not 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * implement a JAIN-SIP interface). This is part of the glue that ties together the NIST-SIP stack 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and event model with the JAIN-SIP stack. This is strictly an implementation class. 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.64 $ $Date: 2010/01/14 18:58:30 $ 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangclass DialogFilter implements ServerRequestInterface, ServerResponseInterface { 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected SIPTransaction transactionChannel; 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected ListeningPointImpl listeningPoint; 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private SipStackImpl sipStack; 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public DialogFilter(SipStackImpl sipStack) { 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = sipStack; 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send back a Request Pending response. 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipRequest 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transaction 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void sendRequestPendingResponse(SIPRequest sipRequest, 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction transaction) { 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = sipRequest.createResponse(Response.REQUEST_PENDING); 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (serverHeader != null) { 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(serverHeader); 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RetryAfter retryAfter = new RetryAfter(); 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retryAfter.setRetryAfter(1); 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(retryAfter); 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.INVITE)) { 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransactionPendingAck(transaction); 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(sipResponse); 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Problem sending error response", ex); 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a BAD REQUEST response. 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipRequest 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transaction 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param reasonPhrase 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void sendBadRequestResponse(SIPRequest sipRequest, SIPServerTransaction transaction, 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String reasonPhrase) { 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = sipRequest.createResponse(Response.BAD_REQUEST); 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (reasonPhrase != null) 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setReasonPhrase(reasonPhrase); 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (serverHeader != null) { 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(serverHeader); 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.INVITE)) { 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransactionPendingAck(transaction); 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(sipResponse); 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Problem sending error response", ex); 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send a CALL OR TRANSACTION DOES NOT EXIST response. 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipRequest 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transaction 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void sendCallOrTransactionDoesNotExistResponse(SIPRequest sipRequest, 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction transaction) { 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = sipRequest 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (serverHeader != null) { 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(serverHeader); 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.INVITE)) { 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransactionPendingAck(transaction); 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(sipResponse); 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Problem sending error response", ex); 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send back a LOOP Detected Response. 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipRequest 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transaction 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void sendLoopDetectedResponse(SIPRequest sipRequest, SIPServerTransaction transaction) { 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = sipRequest.createResponse(Response.LOOP_DETECTED); 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (serverHeader != null) { 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(serverHeader); 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransactionPendingAck(transaction); 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(sipResponse); 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Problem sending error response", ex); 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Send back an error Response. 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param sipRequest 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param transaction 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private void sendServerInternalErrorResponse(SIPRequest sipRequest, 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction transaction) { 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug("Sending 500 response for out of sequence message"); 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = sipRequest.createResponse(Response.SERVER_INTERNAL_ERROR); 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setReasonPhrase("Request out of order"); 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (MessageFactoryImpl.getDefaultServerHeader() != null) { 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader(); 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(serverHeader); 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RetryAfter retryAfter = new RetryAfter(); 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retryAfter.setRetryAfter(10); 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipResponse.setHeader(retryAfter); 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransactionPendingAck(transaction); 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(sipResponse); 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Problem sending response", ex); 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Process a request. Check for various conditions in the dialog that can result in the 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * message being dropped. Possibly return errors for these conditions. 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception SIPServerException is thrown when there is an error processing the request. 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel) { 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Generate the wrapper JAIN-SIP object. 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "PROCESSING INCOMING REQUEST " + sipRequest + " transactionChannel = " 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + transactionChannel + " listening point = " 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + listeningPoint.getIPAddress() + ":" + listeningPoint.getPort()); 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (listeningPoint == null) { 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping message: No listening point registered!"); 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipStackImpl sipStack = (SipStackImpl) transactionChannel.getSIPStack(); 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipProviderImpl sipProvider = listeningPoint.getProvider(); 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider == null) { 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("No provider - dropping !!"); 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack == null) 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException("Egads! no sip stack!"); 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Look for the registered SIPListener for the message channel. 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction transaction = (SIPServerTransaction) this.transactionChannel; 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) { 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "transaction state = " + transaction.getState()); 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String dialogId = sipRequest.getDialogId(true); 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPDialog dialog = sipStack.getDialog(dialogId); 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Check if we got this request on the contact address of the dialog If not the dialog 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * does not belong to this request. We check this condition if a contact address has been 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * assigned to the dialog. Forgive the sins of B2BUA's that like to record route ACK's 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null && sipProvider != dialog.getSipProvider()) { 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Contact contact = dialog.getMyContactHeader(); 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (contact != null) { 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipUri contactUri = (SipUri) (contact.getAddress().getURI()); 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String ipAddress = contactUri.getHost(); 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int contactPort = contactUri.getPort(); 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String contactTransport = contactUri.getTransportParam(); 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (contactTransport == null) 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contactTransport = "udp"; 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (contactPort == -1) { 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (contactTransport.equals("udp") || contactTransport.equals("tcp")) 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contactPort = 5060; 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contactPort = 5061; 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check if the dialog contact is the same as the provider on 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // which we got the request. Otherwise, dont assign this 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // dialog to the request. 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ipAddress != null 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (!ipAddress.equals(listeningPoint.getIPAddress()) || contactPort != listeningPoint 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getPort())) { 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "nulling dialog -- listening point mismatch! " + contactPort 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " lp port = " + listeningPoint.getPort()); 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog = null; 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3261 8.2.2.2 Merged requests: If the request has no tag in the To header field, the 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * UAS core MUST check the request against ongoing transactions. If the From tag, Call-ID, 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and CSeq exactly match those associated with an ongoing transaction, but the request 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * does not match that transaction (based on the matching rules in Section 17.2.3), the 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * UAS core SHOULD generate a 482 (Loop Detected) response and pass it to the server 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * transaction. This support is only enabled when the stack has been instructed to 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * function with Automatic Dialog Support. 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider.isAutomaticDialogSupportEnabled() 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled() 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipRequest.getToTag() == null) { 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction sipServerTransaction = sipStack 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .findMergedTransaction(sipRequest); 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipServerTransaction != null) { 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendLoopDetectedResponse(sipRequest, transaction); 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("dialogId = " + dialogId); 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("dialog = " + dialog); 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3261 Section 16.4 If the first value in the Route header field indicates this 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * proxy,the proxy MUST remove that value from the request . 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If the message is being processed 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // by a Proxy, then the proxy will take care of stripping the 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Route header. If the request is being processed by an 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // endpoint, then the stack strips off the route header. 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getHeader(Route.NAME) != null && transaction.getDialog() != null) { 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RouteList routes = sipRequest.getRouteHeaders(); 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Route route = (Route) routes.getFirst(); 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipUri uri = (SipUri) route.getAddress().getURI(); 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int port; 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (uri.getHostPort().hasPort()) { 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = uri.getHostPort().getPort(); 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (listeningPoint.getTransport().equalsIgnoreCase("TLS")) 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = 5061; 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang port = 5060; 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String host = uri.getHost(); 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((host.equals(listeningPoint.getIPAddress()) || host 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .equalsIgnoreCase(listeningPoint.getSentBy())) 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && port == listeningPoint.getPort()) { 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (routes.size() == 1) 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipRequest.removeHeader(Route.NAME); 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang routes.removeFirst(); 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.REFER) && dialog != null 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled()) { 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * An agent responding to a REFER method MUST return a 400 (Bad Request) if the 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * request contained zero or more than one Refer-To header field values. 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ReferToHeader sipHeader = (ReferToHeader) sipRequest.getHeader(ReferTo.NAME); 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipHeader == null) { 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .sendBadRequestResponse(sipRequest, transaction, 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Refer-To header is missing"); 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * A refer cannot be processed until we have either sent or received an ACK. 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction(); 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (lastTransaction != null && sipProvider.isDialogErrorsAutomaticallyHandled()) { 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest(); 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (lastTransaction instanceof SIPServerTransaction) { 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!((SIPDialog) dialog).isAckSeen() 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastRequest.getMethod().equals(Request.INVITE)) { 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendRequestPendingResponse(sipRequest, transaction); 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (lastTransaction instanceof SIPClientTransaction) { 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang long cseqno = lastRequest.getCSeqHeader().getSeqNumber(); 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String method = lastRequest.getMethod(); 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (method.equals(Request.INVITE) && !dialog.isAckSent(cseqno)) { 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendRequestPendingResponse(sipRequest, transaction); 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipRequest.getMethod().equals(Request.UPDATE)) { 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Got an UPDATE method and the user dialog does not exist and the user wants to be a 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * User agent. 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) { 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction); 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipRequest.getMethod().equals(Request.ACK)) { 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null && transaction.isInviteTransaction()) { 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This is an ack for a 3xx-6xx response. Just let the tx laer 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // take care of it. 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx "); 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog); 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog == null) { 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dialog does not exist " + sipRequest.getFirstLine() 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " isServerTransaction = " + true); 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction st = sipStack 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getRetransmissionAlertTransaction(dialogId); 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (st != null && st.isRetransmissionAlertEnabled()) { 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang st.disableRetransmissionAlerts(); 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * JvB: must never drop ACKs that dont match a transaction! One cannot be sure 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * if it isn't an ACK for a 2xx response 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction ackTransaction = sipStack 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .findTransactionPendingAck(sipRequest); 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Found a transaction ( that we generated ) which is waiting for ACK. So ACK 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * it and return. 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ackTransaction != null) { 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Found Tx pending ACK"); 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ackTransaction.setAckSeen(); 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(ackTransaction); 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransactionPendingAck(ackTransaction); 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Problem terminating transaction", ex); 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!dialog.handleAck(transaction)) { 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!dialog.isSequnceNumberValidation()) { 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dialog exists with loose dialog validation " 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getFirstLine() 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " isServerTransaction = " + true + " dialog = " 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + dialog.getDialogId()); 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction st = sipStack 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getRetransmissionAlertTransaction(dialogId); 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (st != null && st.isRetransmissionAlertEnabled()) { 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang st.disableRetransmissionAlerts(); 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping ACK - cannot find a transaction or dialog"); 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction ackTransaction = sipStack 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .findTransactionPendingAck(sipRequest); 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ackTransaction != null) { 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Found Tx pending ACK"); 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ackTransaction.setAckSeen(); 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(ackTransaction); 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransactionPendingAck(ackTransaction); 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Problem terminating transaction", ex); 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.passToListener(); 533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addTransaction(transaction); 534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addRoute(sipRequest); 535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(dialog, dialogId); 536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.INVITE) 537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled()) { 538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.putInMergeTable(transaction, sipRequest); 539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Note that ACK is a pseudo transaction. It is never added to the stack 542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and you do not get transaction terminated events on ACK. 543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.deliverTerminatedEventForAck) { 546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransaction(transaction); 548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.scheduleAckRemoval(); 549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setMapped(true); 554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipRequest.getMethod().equals(Request.PRACK)) { 560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3262: A matching PRACK is defined as one within the same dialog as the 563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response, and whose method, CSeq-num, and response-num in the RAck header field 564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * match, respectively, the method from the CSeq, the sequence number from the CSeq, 565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and the sequence number from the RSeq of the reliable provisional response. 566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog); 570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) { 572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dialog does not exist " + sipRequest.getFirstLine() 575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " isServerTransaction = " + true); 576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug( 582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!"); 583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse notExist = sipRequest 585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); 586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.sendResponse(notExist); 589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SipException e) { 590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("error sending response", e); 591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) { 593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (dialog != null) { 599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!dialog.handlePrack(sipRequest)) { 600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK "); 602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) { 603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransaction(transaction); 610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addTransaction(transaction); 611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addRoute(sipRequest); 612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(dialog, dialogId); 613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Processing PRACK without a DIALOG -- this must be a proxy element"); 621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipRequest.getMethod().equals(Request.BYE)) { 624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check for correct sequence numbering of the BYE 625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null && !dialog.isRequestConsumable(sipRequest)) { 626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " " 629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getCSeq().getSeqNumber()); 630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() 632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && transaction.getState() == TransactionState.TRYING) { 633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendServerInternalErrorResponse(sipRequest, transaction); 635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If the stack knows about the tx, then remove it. 638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) 639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) { 643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Drop bye's with 481 if dialog does not exist. 644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If dialog support is enabled then 645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // there must be a dialog associated with the bye 646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // No dialog could be found and requests on this 647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // provider. Must act like a user agent -- so drop the request. 648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // NOTE: if Automatic dialog support is not enabled, 649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // then it is the application's responsibility to 650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // take care of this error condition possibly. 651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse response = sipRequest 653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); 654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang response.setReasonPhrase("Dialog Not Found"); 655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "dropping request -- automatic dialog " 659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "support enabled and dialog does not exist!"); 660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(response); 662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SipException ex) { 663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Error in sending response", ex); 664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If the stack knows about the tx, then remove it. 666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) { 667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction = null; 670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // note that the transaction may be null (which 676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // happens when no dialog for the bye was found. 677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // and automatic dialog support is disabled (i.e. the app wants 678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to manage its own dialog layer. 679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null && dialog != null) { 680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider == dialog.getSipProvider()) { 682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransaction(transaction); 683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addTransaction(transaction); 684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(dialog, dialogId); 685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "BYE Tx = " + transaction + " isMapped =" 694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + transaction.isTransactionMapped()); 695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipRequest.getMethod().equals(Request.CANCEL)) { 698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction( 700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipRequest, true); 701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = " 704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + transaction + " isMapped = " 705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + transaction.isTransactionMapped()); 706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Processing incoming CANCEL. 709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check if we can process the CANCEL request. 710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.CANCEL)) { 711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If the CANCEL comes in too late, there's not 712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // much that the Listener can do so just do the 713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // default action and avoid bothering the listener. 714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) { 715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If transaction already exists but it is 716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // too late to cancel the transaction then 717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // just respond OK to the CANCEL and bail. 718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Too late to cancel Transaction"); 720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // send OK and just ignore the CANCEL. 721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.sendResponse(sipRequest.createResponse(Response.OK)); 724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ex.getCause() != null && ex.getCause() instanceof IOException) { 726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang st.raiseIOExceptionEvent(); 727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Cancel transaction = " + st); 733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null && st != null && st.getDialog() != null) { 736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Found an invite tx corresponding to the CANCEL. 737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Set up the client tx and pass up to listener. 738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog((SIPDialog) st.getDialog(), dialogId); 739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog = (SIPDialog) st.getDialog(); 740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled() 741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && transaction != null) { 742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Could not find a invite tx corresponding to the CANCEL. 743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Automatic dialog support is enabled so I must behave like 744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // an endpoint on this provider. 745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Send the error response for the cancel. 746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse response = sipRequest 748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); 749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "dropping request -- automatic dialog support " 752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + "enabled and INVITE ST does not exist!"); 753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.sendResponse(response); 756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SipException ex) { 757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) { 760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.releaseSem(); 762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // INVITE was handled statefully so the CANCEL must also be 768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // statefully handled. 769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (st != null) { 770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null) { 772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransaction(transaction); 773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setPassToListener(); 774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setInviteTransaction(st); 775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Dont let the INVITE and CANCEL be concurrently 776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // processed. 777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang st.acquireSem(); 778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang InternalErrorHandler.handleException(ex); 783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipRequest.getMethod().equals(Request.INVITE)) { 786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPTransaction lastTransaction = dialog == null ? null : dialog 787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getInviteTransaction(); 788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3261 Chapter 14. A UAS that receives a second INVITE before it sends the final 791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response to a first INVITE with a lower CSeq sequence number on the same dialog 792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MUST return a 500 (Server Internal Error) response to the second INVITE and MUST 793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * include a Retry-After header field with a randomly chosen value of between 0 and 10 794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * seconds. 795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null && transaction != null && lastTransaction != null 798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber() 799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction instanceof SIPServerTransaction 800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled() 801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && dialog.isSequnceNumberValidation() 802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.isInviteTransaction() 803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.getState() != TransactionState.COMPLETED 804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.getState() != TransactionState.TERMINATED 805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.getState() != TransactionState.CONFIRMED) { 806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Sending 500 response for out of sequence message"); 810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendServerInternalErrorResponse(sipRequest, transaction); 812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that 818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in 819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * progress MUST return a 491 (Request Pending) response to the received INVITE. 820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lastTransaction = (dialog == null ? null : dialog.getLastTransaction()); 822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null 824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled() 825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction != null 826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.isInviteTransaction() 827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction instanceof ClientTransaction 828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.getLastResponse() != null 829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.getLastResponse().getStatusCode() == 200 830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq() 831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getSeqNumber())) { 832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Sending 491 response for client Dialog ACK not sent."); 835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendRequestPendingResponse(sipRequest, transaction); 837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null && lastTransaction != null 841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled() 842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction.isInviteTransaction() 843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && lastTransaction instanceof ServerTransaction && !dialog.isAckSeen()) { 844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Sending 491 response for server Dialog ACK not seen."); 847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendRequestPendingResponse(sipRequest, transaction); 849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Sequence numbers are supposed to be incremented 855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // sequentially within a dialog for RFC 3261 856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Note BYE, CANCEL and ACK is handled above - so no check here. 857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " + transaction); 861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null && transaction != null && !sipRequest.getMethod().equals(Request.BYE) 864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !sipRequest.getMethod().equals(Request.CANCEL) 865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !sipRequest.getMethod().equals(Request.ACK) 866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !sipRequest.getMethod().equals(Request.PRACK)) { 867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!dialog.isRequestConsumable(sipRequest)) { 869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3261: "UAS Behavior" section (12.2.2): If the remote sequence number was 872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not empty, but the sequence number of the request is lower than the remote 873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * sequence number, the request is out of order and MUST be rejected with a 500 874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (Server Internal Error) response. 875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Drop the request 878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping out of sequence message " + dialog.getRemoteSeqNumber() 881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " " + sipRequest.getCSeq()); 882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // send error when stricly higher, ignore when == 885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // (likely still processing, error would interrupt that) 886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber() 888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipProvider.isDialogErrorsAutomaticallyHandled() 889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (transaction.getState() == TransactionState.TRYING || transaction 890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getState() == TransactionState.PROCEEDING)) { 891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sendServerInternalErrorResponse(sipRequest, transaction); 892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider == dialog.getSipProvider()) { 899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.addTransaction(transaction); 900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This will set the remote sequence number. 901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addTransaction(transaction); 902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.addRoute(sipRequest); 903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(dialog, dialogId); 904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (IOException ex) { 907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.raiseIOExceptionEvent(); 908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.removeTransaction(transaction); 909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang RequestEvent sipEvent; 915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipRequest.getMethod() + " transaction.isMapped = " 919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + transaction.isTransactionMapped()); 920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3265: Each event package MUST specify whether forked SUBSCRIBE requests are allowed 924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * to install multiple subscriptions. If such behavior is not allowed, the first potential 925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * dialog- establishing message will create a dialog. All subsequent NOTIFY messages which 926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * correspond to the SUBSCRIBE message (i.e., match "To", "From", "From" header "tag" 927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * parameter, "Call-ID", "CSeq", "Event", and "Event" header "id" parameter) but which do 928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not match the dialog would be rejected with a 481 response. Note that the 200-class 929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * response to the SUBSCRIBE can arrive after a matching NOTIFY has been received; such 930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * responses might not correlate to the same dialog established by the NOTIFY. Except as 931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * required to complete the SUBSCRIBE transaction, such non-matching 200-class responses 932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * are ignored. 933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) { 936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPClientTransaction pendingSubscribeClientTx = sipStack.findSubscribeTransaction( 938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipRequest, listeningPoint); 939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 942600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "PROCESSING NOTIFY DIALOG == null " + pendingSubscribeClientTx); 943600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 944600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 945600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 946600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * RFC 3265: Upon receiving a NOTIFY request, the subscriber should check that it 947600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * matches at least one of its outstanding subscriptions; if not, it MUST return a 948600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * "481 Subscription does not exist" response unless another 400- or -class response 949600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * is more appropriate. 950600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 951600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider.isAutomaticDialogSupportEnabled() && pendingSubscribeClientTx == null 952600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !sipStack.deliverUnsolicitedNotify) { 953600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 954600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This is the case of the UAC receiving a Stray NOTIFY for which it has not 955600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * previously sent out a SUBSCRIBE and for which it does not have an established 956600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * dialog. 957600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 958600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 959600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 960600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 961600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Could not find Subscription for Notify Tx."); 962600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 963600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Response errorResponse = sipRequest 964600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST); 965600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang errorResponse.setReasonPhrase("Subscription does not exist"); 966600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.sendResponse(errorResponse); 967600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 968600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 969600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 970600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 971600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Exception while sending error response statelessly", ex); 972600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 973600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 974600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 975600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 976600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 977600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If the server transaction cannot be found or if it 978600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // aleady has a dialog attached to it then just assign the 979600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // notify to this dialog and pass it up. 980600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (pendingSubscribeClientTx != null) { 981600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The response to the pending subscribe tx can try to create 982600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // a dialog at the same time that the notify is trying to 983600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // create a dialog. Thus we cannot process both at the 984600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // same time. 985600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 986600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setPendingSubscribe(pendingSubscribeClientTx); 987600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The transaction gets assigned to the dialog from the 988600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // outgoing subscribe. First see if anybody claimed the 989600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // default Dialog for the outgoing Subscribe request. 990600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPDialog subscriptionDialog = (SIPDialog) pendingSubscribeClientTx 991600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getDefaultDialog(); 992600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 993600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // TODO -- refactor this. Can probably be written far cleaner. 994600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (subscriptionDialog == null || subscriptionDialog.getDialogId() == null 995600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || !subscriptionDialog.getDialogId().equals(dialogId)) { 996600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Notify came in before you could assign a response to 997600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the subscribe. 998600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // grab the default dialog and assign it to the tags in 999600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the notify. 1000600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (subscriptionDialog != null && subscriptionDialog.getDialogId() == null) { 1001600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang subscriptionDialog.setDialogId(dialogId); 1002600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1003600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1004600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang subscriptionDialog = pendingSubscribeClientTx.getDialog(dialogId); 1005600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1006600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1007600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1008600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "PROCESSING NOTIFY Subscribe DIALOG " + subscriptionDialog); 1009600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1010600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1011600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The user could have createed a dialog before sending out 1012600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the SUBSCRIBE on the subscribe tx. 1013600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (subscriptionDialog == null 1014600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (sipProvider.isAutomaticDialogSupportEnabled() || pendingSubscribeClientTx 1015600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getDefaultDialog() != null)) { 1016600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Event event = (Event) sipRequest.getHeader(EventHeader.NAME); 1017600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isEventForked(event.getEventType())) { 1018600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1019600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang subscriptionDialog = SIPDialog.createFromNOTIFY( 1020600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pendingSubscribeClientTx, transaction); 1021600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1022600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1023600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1024600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1025600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (subscriptionDialog != null) { 1026600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(subscriptionDialog, dialogId); 1027600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang subscriptionDialog.setState(DialogState.CONFIRMED.getValue()); 1028600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.putDialog(subscriptionDialog); 1029600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId); 1030600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!transaction.isTransactionMapped()) { 1031600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.mapTransaction(transaction); 1032600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Let the listener see it if it just got 1033600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // created. 1034600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // otherwise, we have already processed the tx 1035600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // so 1036600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // we dont want the listener to see it. 1037600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setPassToListener(); 1038600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1039600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.addTransaction(transaction); 1040600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 1041600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1042600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1043600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1044600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1045600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The subscription default dialog is our dialog. 1046600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Found a subscrbe dialog for the NOTIFY 1047600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // So map the tx. 1048600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(subscriptionDialog, dialogId); 1049600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog = subscriptionDialog; 1050600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!transaction.isTransactionMapped()) { 1051600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.mapTransaction(transaction); 1052600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Let the listener see it if it just got created. 1053600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // otherwise, we have already processed the tx so 1054600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // we dont want the listener to see it. 1055600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setPassToListener(); 1056600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1057600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack.addTransaction(transaction); 1058600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 1059600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1060600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1061600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.putDialog(subscriptionDialog); 1062600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (pendingSubscribeClientTx != null) { 1063600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang subscriptionDialog.addTransaction(pendingSubscribeClientTx); 1064600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId); 1065600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1066600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1067600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1068600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null 1069600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && ((SIPServerTransaction) transaction).isTransactionMapped()) { 1070600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Shadow transaction has been created and the stack 1071600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // knows 1072600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // about it. 1073600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipEvent = new RequestEvent((SipProvider) sipProvider, 1074600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (ServerTransaction) transaction, subscriptionDialog, 1075600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (Request) sipRequest); 1076600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1077600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Shadow transaction has been created but the stack 1078600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // does 1079600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // not know 1080600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // about it. 1081600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipEvent = new RequestEvent((SipProvider) sipProvider, null, 1082600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang subscriptionDialog, (Request) sipRequest); 1083600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1084600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1085600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1086600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1087600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("could not find subscribe tx"); 1088600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1089600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1090600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Got a notify out of the blue - just pass it up 1091600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // for stateless handling by the application. 1092600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipEvent = new RequestEvent(sipProvider, null, null, (Request) sipRequest); 1093600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1094600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1095600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1096600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1097600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // For a dialog creating event - set the transaction to null. 1098600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The listener can create the dialog if needed. 1099600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction != null 1100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (((SIPServerTransaction) transaction).isTransactionMapped())) { 1101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipEvent = new RequestEvent(sipProvider, (ServerTransaction) transaction, dialog, 1102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (Request) sipRequest); 1103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipEvent = new RequestEvent(sipProvider, null, dialog, (Request) sipRequest); 1105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.handleEvent(sipEvent, transaction); 1108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Process the response. 1113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @exception SIPServerException is thrown when there is an error processing the response 1115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param incomingMessageChannel -- message channel on which the response is received. 1116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void processResponse(SIPResponse response, MessageChannel incomingMessageChannel, 1118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPDialog dialog) { 1119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "PROCESSING INCOMING RESPONSE" + response.encodeMessage()); 1122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (listeningPoint == null) { 1124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 1126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping message: No listening point" + " registered!"); 1127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(response)) { 1131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 1133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 1134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logError( 1135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping response - topmost VIA header does not originate from this stack"); 1136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipProviderImpl sipProvider = listeningPoint.getProvider(); 1141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider == null) { 1142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Dropping message: no provider"); 1144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider.getSipListener() == null) { 1148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("No listener -- dropping response!"); 1150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel; 1155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipStackImpl sipStackImpl = sipProvider.sipStack; 1156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStackImpl.getStackLogger().logDebug("Transaction = " + transaction); 1159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (transaction == null) { 1162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Transaction is null but the dialog is not null. This means that 1163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the transaction has been removed by the stack. 1164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // If the dialog exists, then it may need to retransmit ACK so 1165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // we cannot drop the response. 1166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null) { 1167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (response.getStatusCode() / 100 != 2) { 1168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 1170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 1171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug( 1172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Response is not a final response and dialog is found for response -- dropping response!"); 1173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (dialog.getState() == DialogState.TERMINATED) { 1176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dialog is terminated -- dropping response!"); 1179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean ackAlreadySent = false; 1183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog.isAckSeen() && dialog.getLastAckSent() != null) { 1184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog.getLastAckSent().getCSeq().getSeqNumber() == response 1185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getCSeq().getSeqNumber()) { 1186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the last ack sent corresponded to this 200 1187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ackAlreadySent = true; 1188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // 200 retransmission for the final response. 1191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ackAlreadySent 1192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && response.getCSeq().getMethod().equals(dialog.getMethod())) { 1193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Found the dialog - resend the ACK and 1195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // dont pass up the null transaction 1196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Retransmission of OK detected: Resending last ACK"); 1199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.resendAck(); 1201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SipException ex) { 1203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // What to do here ?? kill the dialog? 1204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("could not resend ack", ex); 1205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "could not find tx, handling statelessly Dialog = " + dialog); 1213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Pass the response up to the application layer to handle 1215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // statelessly. 1216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ResponseEventExt sipEvent = new ResponseEventExt(sipProvider, transaction, dialog, 1218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (Response) response); 1219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) { 1221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPClientTransaction forked = this.sipStack.getForkedTransaction(response 1222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getTransactionId()); 1223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipEvent.setOriginalTransaction(forked); 1224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.handleEvent(sipEvent, transaction); 1227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ResponseEventExt responseEvent = null; 1231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Here if there is an assigned dialog 1233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang responseEvent = new ResponseEventExt(sipProvider, (ClientTransactionExt) transaction, 1234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog, (Response) response); 1235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) { 1236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPClientTransaction forked = this.sipStack.getForkedTransaction(response 1237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getTransactionId()); 1238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang responseEvent.setOriginalTransaction(forked); 1239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Set the Dialog for the response. 1242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null && response.getStatusCode() != 100) { 1243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // set the last response for the dialog. 1244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.setLastResponse(transaction, response); 1245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang transaction.setDialog(dialog, dialog.getDialogId()); 1246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.handleEvent(responseEvent, transaction); 1249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 1253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Just a placeholder. This is called from the stack for message logging. Auxiliary processing 1254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * information can be passed back to be written into the log file. 1255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return auxiliary information that we may have generated during the message processing 1257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * which is retrieved by the message logger. 1258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String getProcessingInfo() { 1260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 1261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 1264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 1265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 1266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse, 1267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * gov.nist.javax.sip.stack.MessageChannel) 1268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 1269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) { 1270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String dialogID = sipResponse.getDialogId(false); 1271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPDialog sipDialog = this.sipStack.getDialog(dialogID); 1272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String method = sipResponse.getCSeq().getMethod(); 1274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "PROCESSING INCOMING RESPONSE: " + sipResponse.encodeMessage()); 1277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(sipResponse)) { 1280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Detected stray response -- dropping"); 1282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (listeningPoint == null) { 1287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping message: No listening point" + " registered!"); 1290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipProviderImpl sipProvider = listeningPoint.getProvider(); 1294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider == null) { 1295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Dropping message: no provider"); 1297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider.getSipListener() == null) { 1302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dropping message: no sipListener registered!"); 1305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel; 1310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This may be a dialog creating method for which the ACK has not yet 1311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // been sent 1312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // but the dialog has already been assigned ( happens this way for 1313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // 3PCC). 1314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog == null && transaction != null) { 1315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog = transaction.getDialog(dialogID); 1316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog != null && sipDialog.getState() == DialogState.TERMINATED) 1317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog = null; 1318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Transaction = " + transaction + " sipDialog = " + sipDialog); 1323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.transactionChannel != null) { 1325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String originalFrom = ((SIPRequest) this.transactionChannel.getRequest()) 1326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getFromTag(); 1327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (originalFrom == null ^ sipResponse.getFrom().getTag() == null) { 1328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); 1330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (originalFrom != null 1333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !originalFrom.equalsIgnoreCase(sipResponse.getFrom().getTag())) { 1334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response"); 1336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isDialogCreated(method) && sipResponse.getStatusCode() != 100 1341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getFrom().getTag() != null && sipResponse.getTo().getTag() != null 1342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipDialog == null) { 1343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipProvider.isAutomaticDialogSupportEnabled()) { 1344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.transactionChannel != null) { 1345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog == null) { 1346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // There could be an existing dialog for this response. 1347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog = sipStack.createDialog( 1348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (SIPClientTransaction) this.transactionChannel, sipResponse); 1349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.transactionChannel.setDialog(sipDialog, sipResponse 1351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getDialogId(false)); 1352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog = this.sipStack.createDialog(sipProvider, sipResponse); 1355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Have a dialog but could not find transaction. 1360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog != null && transaction == null 1361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipDialog.getState() != DialogState.TERMINATED) { 1362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipResponse.getStatusCode() / 100 != 2) { 1363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "status code != 200 ; statusCode = " 1366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipResponse.getStatusCode()); 1367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipDialog.getState() == DialogState.TERMINATED) { 1368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 1369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 1370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Dialog is terminated -- dropping response!"); 1371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Dialog exists but was terminated - just create and send an ACK for the OK. 1373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // It could be late arriving. 1374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipResponse.getStatusCode() / 100 == 2 1375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getCSeq().getMethod().equals(Request.INVITE)) { 1376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Request ackRequest = sipDialog.createAck(sipResponse.getCSeq() 1378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getSeqNumber()); 1379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog.sendAck(ackRequest); 1380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 1381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError("Error creating ack", ex); 1382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 1386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang boolean ackAlreadySent = false; 1387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog.isAckSeen() && sipDialog.getLastAckSent() != null) { 1388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog.getLastAckSent().getCSeq().getSeqNumber() == sipResponse 1389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getCSeq().getSeqNumber() 1390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getDialogId(false).equals( 1391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog.getLastAckSent().getDialogId(false))) { 1392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the last ack sent corresponded to this 200 1393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ackAlreadySent = true; 1394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // 200 retransmission for the final response. 1397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ackAlreadySent 1398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getCSeq().getMethod().equals(sipDialog.getMethod())) { 1399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 1400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Found the dialog - resend the ACK and 1401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // dont pass up the null transaction 1402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("resending ACK"); 1404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog.resendAck(); 1406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 1407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (SipException ex) { 1408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // What to do here ?? kill the dialog? 1409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Pass the response up to the application layer to handle 1414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // statelessly. 1415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 1418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("sending response to TU for processing "); 1419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipDialog != null && sipResponse.getStatusCode() != 100 1421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getTo().getTag() != null) { 1422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog.setLastResponse(transaction, sipResponse); 1423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ResponseEventExt responseEvent = new ResponseEventExt(sipProvider, 1426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang (ClientTransactionExt) transaction, sipDialog, (Response) sipResponse); 1427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipResponse.getCSeq().getMethod().equals(Request.INVITE)) { 1429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ClientTransactionExt originalTx = this.sipStack.getForkedTransaction(sipResponse 1430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getTransactionId()); 1431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang responseEvent.setOriginalTransaction(originalTx); 1432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipProvider.handleEvent(responseEvent, transaction); 1435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 1436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 1437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 1438