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