• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Conditions Of Use
3  *
4  * This software was developed by employees of the National Institute of
5  * Standards and Technology (NIST), an agency of the Federal Government.
6  * Pursuant to title 15 Untied States Code Section 105, works of NIST
7  * employees are not subject to copyright protection in the United States
8  * and are considered to be in the public domain.  As a result, a formal
9  * license is not needed to use the software.
10  *
11  * This software is provided by NIST as a service and is expressly
12  * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13  * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15  * AND DATA ACCURACY.  NIST does not warrant or make any representations
16  * regarding the use of the software or the results thereof, including but
17  * not limited to the correctness, accuracy, reliability or usefulness of
18  * the software.
19  *
20  * Permission to use this software is contingent upon your acceptance
21  * of the terms of this agreement
22  *
23  * .
24  *
25  */
26 /******************************************************************************
27  * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).      *
28  ******************************************************************************/
29 package gov.nist.javax.sip;
30 
31 import gov.nist.core.InternalErrorHandler;
32 import gov.nist.javax.sip.address.SipUri;
33 import gov.nist.javax.sip.header.Contact;
34 import gov.nist.javax.sip.header.Event;
35 import gov.nist.javax.sip.header.ReferTo;
36 import gov.nist.javax.sip.header.RetryAfter;
37 import gov.nist.javax.sip.header.Route;
38 import gov.nist.javax.sip.header.RouteList;
39 import gov.nist.javax.sip.header.Server;
40 import gov.nist.javax.sip.message.MessageFactoryImpl;
41 import gov.nist.javax.sip.message.SIPRequest;
42 import gov.nist.javax.sip.message.SIPResponse;
43 import gov.nist.javax.sip.stack.MessageChannel;
44 import gov.nist.javax.sip.stack.SIPClientTransaction;
45 import gov.nist.javax.sip.stack.SIPDialog;
46 import gov.nist.javax.sip.stack.SIPServerTransaction;
47 import gov.nist.javax.sip.stack.SIPTransaction;
48 import gov.nist.javax.sip.stack.ServerRequestInterface;
49 import gov.nist.javax.sip.stack.ServerResponseInterface;
50 
51 import java.io.IOException;
52 import java.util.TimerTask;
53 
54 import javax.sip.ClientTransaction;
55 import javax.sip.DialogState;
56 import javax.sip.InvalidArgumentException;
57 import javax.sip.ObjectInUseException;
58 import javax.sip.RequestEvent;
59 import javax.sip.ResponseEvent;
60 import javax.sip.ServerTransaction;
61 import javax.sip.SipException;
62 import javax.sip.SipProvider;
63 import javax.sip.TransactionState;
64 import javax.sip.header.CSeqHeader;
65 import javax.sip.header.EventHeader;
66 import javax.sip.header.ReferToHeader;
67 import javax.sip.header.ServerHeader;
68 import javax.sip.message.Request;
69 import javax.sip.message.Response;
70 
71 /*
72  * Bug fix Contributions by Lamine Brahimi, Andreas Bystrom, Bill Roome, John Martin, Daniel
73  * Machin Vasquez-Illa, Antonis Karydas, Joe Provino, Bruce Evangelder, Jeroen van Bemmel, Robert
74  * S. Rosen.
75  */
76 /**
77  * An adapter class from the JAIN implementation objects to the NIST-SIP stack. The primary
78  * purpose of this class is to do early rejection of bad messages and deliver meaningful messages
79  * to the application. This class is essentially a Dialog filter. It is a helper for the UAC Core.
80  * It checks for and rejects requests and responses which may be filtered out because of sequence
81  * number, Dialog not found, etc. Note that this is not part of the JAIN-SIP spec (it does not
82  * implement a JAIN-SIP interface). This is part of the glue that ties together the NIST-SIP stack
83  * and event model with the JAIN-SIP stack. This is strictly an implementation class.
84  *
85  * @version 1.2 $Revision: 1.64 $ $Date: 2010/01/14 18:58:30 $
86  *
87  * @author M. Ranganathan
88  */
89 class DialogFilter implements ServerRequestInterface, ServerResponseInterface {
90 
91     protected SIPTransaction transactionChannel;
92 
93     protected ListeningPointImpl listeningPoint;
94 
95     private SipStackImpl sipStack;
96 
DialogFilter(SipStackImpl sipStack)97     public DialogFilter(SipStackImpl sipStack) {
98         this.sipStack = sipStack;
99 
100     }
101 
102     /**
103      * Send back a Request Pending response.
104      *
105      * @param sipRequest
106      * @param transaction
107      */
sendRequestPendingResponse(SIPRequest sipRequest, SIPServerTransaction transaction)108     private void sendRequestPendingResponse(SIPRequest sipRequest,
109             SIPServerTransaction transaction) {
110         SIPResponse sipResponse = sipRequest.createResponse(Response.REQUEST_PENDING);
111         ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
112         if (serverHeader != null) {
113             sipResponse.setHeader(serverHeader);
114         }
115         try {
116             RetryAfter retryAfter = new RetryAfter();
117             retryAfter.setRetryAfter(1);
118             sipResponse.setHeader(retryAfter);
119             if (sipRequest.getMethod().equals(Request.INVITE)) {
120                 sipStack.addTransactionPendingAck(transaction);
121             }
122             transaction.sendResponse(sipResponse);
123             transaction.releaseSem();
124         } catch (Exception ex) {
125             sipStack.getStackLogger().logError("Problem sending error response", ex);
126             transaction.releaseSem();
127             sipStack.removeTransaction(transaction);
128         }
129     }
130 
131     /**
132      * Send a BAD REQUEST response.
133      *
134      * @param sipRequest
135      * @param transaction
136      * @param reasonPhrase
137      */
138 
sendBadRequestResponse(SIPRequest sipRequest, SIPServerTransaction transaction, String reasonPhrase)139     private void sendBadRequestResponse(SIPRequest sipRequest, SIPServerTransaction transaction,
140             String reasonPhrase) {
141         SIPResponse sipResponse = sipRequest.createResponse(Response.BAD_REQUEST);
142         if (reasonPhrase != null)
143             sipResponse.setReasonPhrase(reasonPhrase);
144         ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
145         if (serverHeader != null) {
146             sipResponse.setHeader(serverHeader);
147         }
148         try {
149             if (sipRequest.getMethod().equals(Request.INVITE)) {
150                 sipStack.addTransactionPendingAck(transaction);
151             }
152             transaction.sendResponse(sipResponse);
153             transaction.releaseSem();
154         } catch (Exception ex) {
155             sipStack.getStackLogger().logError("Problem sending error response", ex);
156             transaction.releaseSem();
157             sipStack.removeTransaction(transaction);
158 
159         }
160     }
161 
162     /**
163      * Send a CALL OR TRANSACTION DOES NOT EXIST response.
164      *
165      * @param sipRequest
166      * @param transaction
167      */
168 
sendCallOrTransactionDoesNotExistResponse(SIPRequest sipRequest, SIPServerTransaction transaction)169     private void sendCallOrTransactionDoesNotExistResponse(SIPRequest sipRequest,
170             SIPServerTransaction transaction) {
171 
172         SIPResponse sipResponse = sipRequest
173                 .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
174 
175         ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
176         if (serverHeader != null) {
177             sipResponse.setHeader(serverHeader);
178         }
179         try {
180             if (sipRequest.getMethod().equals(Request.INVITE)) {
181                 sipStack.addTransactionPendingAck(transaction);
182             }
183             transaction.sendResponse(sipResponse);
184             transaction.releaseSem();
185         } catch (Exception ex) {
186             sipStack.getStackLogger().logError("Problem sending error response", ex);
187             transaction.releaseSem();
188             sipStack.removeTransaction(transaction);
189 
190         }
191 
192     }
193 
194     /**
195      * Send back a LOOP Detected Response.
196      *
197      * @param sipRequest
198      * @param transaction
199      *
200      */
sendLoopDetectedResponse(SIPRequest sipRequest, SIPServerTransaction transaction)201     private void sendLoopDetectedResponse(SIPRequest sipRequest, SIPServerTransaction transaction) {
202         SIPResponse sipResponse = sipRequest.createResponse(Response.LOOP_DETECTED);
203 
204         ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
205         if (serverHeader != null) {
206             sipResponse.setHeader(serverHeader);
207         }
208         try {
209             sipStack.addTransactionPendingAck(transaction);
210             transaction.sendResponse(sipResponse);
211             transaction.releaseSem();
212         } catch (Exception ex) {
213             sipStack.getStackLogger().logError("Problem sending error response", ex);
214             transaction.releaseSem();
215             sipStack.removeTransaction(transaction);
216 
217         }
218 
219     }
220 
221     /**
222      * Send back an error Response.
223      *
224      * @param sipRequest
225      * @param transaction
226      */
227 
sendServerInternalErrorResponse(SIPRequest sipRequest, SIPServerTransaction transaction)228     private void sendServerInternalErrorResponse(SIPRequest sipRequest,
229             SIPServerTransaction transaction) {
230         if (sipStack.isLoggingEnabled())
231             sipStack.getStackLogger()
232                     .logDebug("Sending 500 response for out of sequence message");
233         SIPResponse sipResponse = sipRequest.createResponse(Response.SERVER_INTERNAL_ERROR);
234         sipResponse.setReasonPhrase("Request out of order");
235         if (MessageFactoryImpl.getDefaultServerHeader() != null) {
236             ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
237             sipResponse.setHeader(serverHeader);
238         }
239 
240         try {
241             RetryAfter retryAfter = new RetryAfter();
242             retryAfter.setRetryAfter(10);
243             sipResponse.setHeader(retryAfter);
244             sipStack.addTransactionPendingAck(transaction);
245             transaction.sendResponse(sipResponse);
246             transaction.releaseSem();
247         } catch (Exception ex) {
248             sipStack.getStackLogger().logError("Problem sending response", ex);
249             transaction.releaseSem();
250             sipStack.removeTransaction(transaction);
251         }
252     }
253 
254     /**
255      * Process a request. Check for various conditions in the dialog that can result in the
256      * message being dropped. Possibly return errors for these conditions.
257      *
258      * @exception SIPServerException is thrown when there is an error processing the request.
259      */
processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel)260     public void processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel) {
261         // Generate the wrapper JAIN-SIP object.
262         if (sipStack.isLoggingEnabled())
263             sipStack.getStackLogger().logDebug(
264                     "PROCESSING INCOMING REQUEST " + sipRequest + " transactionChannel = "
265                             + transactionChannel + " listening point = "
266                             + listeningPoint.getIPAddress() + ":" + listeningPoint.getPort());
267         if (listeningPoint == null) {
268             if (sipStack.isLoggingEnabled())
269                 sipStack.getStackLogger().logDebug(
270                         "Dropping message: No listening point registered!");
271             return;
272         }
273 
274         SipStackImpl sipStack = (SipStackImpl) transactionChannel.getSIPStack();
275 
276         SipProviderImpl sipProvider = listeningPoint.getProvider();
277         if (sipProvider == null) {
278             if (sipStack.isLoggingEnabled())
279                 sipStack.getStackLogger().logDebug("No provider - dropping !!");
280             return;
281         }
282 
283         if (sipStack == null)
284             InternalErrorHandler.handleException("Egads! no sip stack!");
285 
286         // Look for the registered SIPListener for the message channel.
287 
288         SIPServerTransaction transaction = (SIPServerTransaction) this.transactionChannel;
289         if (transaction != null) {
290             if (sipStack.isLoggingEnabled())
291                 sipStack.getStackLogger().logDebug(
292                         "transaction state = " + transaction.getState());
293         }
294         String dialogId = sipRequest.getDialogId(true);
295         SIPDialog dialog = sipStack.getDialog(dialogId);
296         /*
297          * Check if we got this request on the contact address of the dialog If not the dialog
298          * does not belong to this request. We check this condition if a contact address has been
299          * assigned to the dialog. Forgive the sins of B2BUA's that like to record route ACK's
300          */
301         if (dialog != null && sipProvider != dialog.getSipProvider()) {
302             Contact contact = dialog.getMyContactHeader();
303             if (contact != null) {
304                 SipUri contactUri = (SipUri) (contact.getAddress().getURI());
305                 String ipAddress = contactUri.getHost();
306                 int contactPort = contactUri.getPort();
307                 String contactTransport = contactUri.getTransportParam();
308                 if (contactTransport == null)
309                     contactTransport = "udp";
310                 if (contactPort == -1) {
311                     if (contactTransport.equals("udp") || contactTransport.equals("tcp"))
312                         contactPort = 5060;
313                     else
314                         contactPort = 5061;
315                 }
316                 // Check if the dialog contact is the same as the provider on
317                 // which we got the request. Otherwise, dont assign this
318                 // dialog to the request.
319                 if (ipAddress != null
320                         && (!ipAddress.equals(listeningPoint.getIPAddress()) || contactPort != listeningPoint
321                                 .getPort())) {
322                     if (sipStack.isLoggingEnabled()) {
323                         sipStack.getStackLogger().logDebug(
324                                 "nulling dialog -- listening point mismatch!  " + contactPort
325                                         + "  lp port = " + listeningPoint.getPort());
326 
327                     }
328                     dialog = null;
329                 }
330 
331             }
332         }
333 
334         /*
335          * RFC 3261 8.2.2.2 Merged requests: If the request has no tag in the To header field, the
336          * UAS core MUST check the request against ongoing transactions. If the From tag, Call-ID,
337          * and CSeq exactly match those associated with an ongoing transaction, but the request
338          * does not match that transaction (based on the matching rules in Section 17.2.3), the
339          * UAS core SHOULD generate a 482 (Loop Detected) response and pass it to the server
340          * transaction. This support is only enabled when the stack has been instructed to
341          * function with Automatic Dialog Support.
342          */
343         if (sipProvider.isAutomaticDialogSupportEnabled()
344                 && sipProvider.isDialogErrorsAutomaticallyHandled()
345                 && sipRequest.getToTag() == null) {
346             SIPServerTransaction sipServerTransaction = sipStack
347                     .findMergedTransaction(sipRequest);
348             if (sipServerTransaction != null) {
349                 this.sendLoopDetectedResponse(sipRequest, transaction);
350                 return;
351             }
352         }
353 
354         if (sipStack.isLoggingEnabled()) {
355             sipStack.getStackLogger().logDebug("dialogId = " + dialogId);
356             sipStack.getStackLogger().logDebug("dialog = " + dialog);
357         }
358 
359         /*
360          * RFC 3261 Section 16.4 If the first value in the Route header field indicates this
361          * proxy,the proxy MUST remove that value from the request .
362          */
363 
364         // If the message is being processed
365         // by a Proxy, then the proxy will take care of stripping the
366         // Route header. If the request is being processed by an
367         // endpoint, then the stack strips off the route header.
368         if (sipRequest.getHeader(Route.NAME) != null && transaction.getDialog() != null) {
369             RouteList routes = sipRequest.getRouteHeaders();
370             Route route = (Route) routes.getFirst();
371             SipUri uri = (SipUri) route.getAddress().getURI();
372             int port;
373             if (uri.getHostPort().hasPort()) {
374                 port = uri.getHostPort().getPort();
375             } else {
376                 if (listeningPoint.getTransport().equalsIgnoreCase("TLS"))
377                     port = 5061;
378                 else
379                     port = 5060;
380             }
381             String host = uri.getHost();
382             if ((host.equals(listeningPoint.getIPAddress()) || host
383                     .equalsIgnoreCase(listeningPoint.getSentBy()))
384                     && port == listeningPoint.getPort()) {
385                 if (routes.size() == 1)
386                     sipRequest.removeHeader(Route.NAME);
387                 else
388                     routes.removeFirst();
389             }
390         }
391 
392         if (sipRequest.getMethod().equals(Request.REFER) && dialog != null
393                 && sipProvider.isDialogErrorsAutomaticallyHandled()) {
394             /*
395              * An agent responding to a REFER method MUST return a 400 (Bad Request) if the
396              * request contained zero or more than one Refer-To header field values.
397              */
398             ReferToHeader sipHeader = (ReferToHeader) sipRequest.getHeader(ReferTo.NAME);
399             if (sipHeader == null) {
400                 this
401                         .sendBadRequestResponse(sipRequest, transaction,
402                                 "Refer-To header is missing");
403                 return;
404 
405             }
406 
407             /*
408              * A refer cannot be processed until we have either sent or received an ACK.
409              */
410             SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction();
411             if (lastTransaction != null  && sipProvider.isDialogErrorsAutomaticallyHandled()) {
412                 SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest();
413                 if (lastTransaction instanceof SIPServerTransaction) {
414                     if (!((SIPDialog) dialog).isAckSeen()
415                             && lastRequest.getMethod().equals(Request.INVITE)) {
416                         this.sendRequestPendingResponse(sipRequest, transaction);
417                         return;
418                     }
419                 } else if (lastTransaction instanceof SIPClientTransaction) {
420                     long cseqno = lastRequest.getCSeqHeader().getSeqNumber();
421                     String method = lastRequest.getMethod();
422                     if (method.equals(Request.INVITE) && !dialog.isAckSent(cseqno)) {
423                         this.sendRequestPendingResponse(sipRequest, transaction);
424                         return;
425                     }
426                 }
427             }
428 
429         } else if (sipRequest.getMethod().equals(Request.UPDATE)) {
430             /*
431              * Got an UPDATE method and the user dialog does not exist and the user wants to be a
432              * User agent.
433              *
434              */
435             if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
436                 this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction);
437                 return;
438             }
439         } else if (sipRequest.getMethod().equals(Request.ACK)) {
440 
441             if (transaction != null && transaction.isInviteTransaction()) {
442                 // This is an ack for a 3xx-6xx response. Just let the tx laer
443                 // take care of it.
444                 if (sipStack.isLoggingEnabled())
445                     sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx ");
446 
447             } else {
448                 if (sipStack.isLoggingEnabled())
449                     sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog);
450 
451                 if (dialog == null) {
452                     if (sipStack.isLoggingEnabled()) {
453                         sipStack.getStackLogger().logDebug(
454                                 "Dialog does not exist " + sipRequest.getFirstLine()
455                                         + " isServerTransaction = " + true);
456 
457                     }
458                     SIPServerTransaction st = sipStack
459                             .getRetransmissionAlertTransaction(dialogId);
460                     if (st != null && st.isRetransmissionAlertEnabled()) {
461                         st.disableRetransmissionAlerts();
462 
463                     }
464                     /*
465                      * JvB: must never drop ACKs that dont match a transaction! One cannot be sure
466                      * if it isn't an ACK for a 2xx response
467                      *
468                      */
469                     SIPServerTransaction ackTransaction = sipStack
470                             .findTransactionPendingAck(sipRequest);
471                     /*
472                      * Found a transaction ( that we generated ) which is waiting for ACK. So ACK
473                      * it and return.
474                      */
475                     if (ackTransaction != null) {
476                         if (sipStack.isLoggingEnabled())
477                             sipStack.getStackLogger().logDebug("Found Tx pending ACK");
478                         try {
479                             ackTransaction.setAckSeen();
480                             sipStack.removeTransaction(ackTransaction);
481                             sipStack.removeTransactionPendingAck(ackTransaction);
482                         } catch (Exception ex) {
483                             if (sipStack.isLoggingEnabled()) {
484                                 sipStack.getStackLogger().logError(
485                                         "Problem terminating transaction", ex);
486                             }
487                         }
488                         return;
489                     }
490 
491                 } else {
492                     if (!dialog.handleAck(transaction)) {
493                         if (!dialog.isSequnceNumberValidation()) {
494                             if (sipStack.isLoggingEnabled()) {
495                                 sipStack.getStackLogger().logDebug(
496                                         "Dialog exists with loose dialog validation "
497                                                 + sipRequest.getFirstLine()
498                                                 + " isServerTransaction = " + true + " dialog = "
499                                                 + dialog.getDialogId());
500 
501                             }
502                             SIPServerTransaction st = sipStack
503                                     .getRetransmissionAlertTransaction(dialogId);
504                             if (st != null && st.isRetransmissionAlertEnabled()) {
505                                 st.disableRetransmissionAlerts();
506 
507                             }
508                         } else {
509                             if (sipStack.isLoggingEnabled()) {
510                                 sipStack.getStackLogger().logDebug(
511                                         "Dropping ACK - cannot find a transaction or dialog");
512                             }
513                             SIPServerTransaction ackTransaction = sipStack
514                                     .findTransactionPendingAck(sipRequest);
515                             if (ackTransaction != null) {
516                                 if (sipStack.isLoggingEnabled())
517                                     sipStack.getStackLogger().logDebug("Found Tx pending ACK");
518                                 try {
519                                     ackTransaction.setAckSeen();
520                                     sipStack.removeTransaction(ackTransaction);
521                                     sipStack.removeTransactionPendingAck(ackTransaction);
522                                 } catch (Exception ex) {
523                                     if (sipStack.isLoggingEnabled()) {
524                                         sipStack.getStackLogger().logError(
525                                                 "Problem terminating transaction", ex);
526                                     }
527                                 }
528                             }
529                             return;
530                         }
531                     } else {
532                         transaction.passToListener();
533                         dialog.addTransaction(transaction);
534                         dialog.addRoute(sipRequest);
535                         transaction.setDialog(dialog, dialogId);
536                         if (sipRequest.getMethod().equals(Request.INVITE)
537                                 && sipProvider.isDialogErrorsAutomaticallyHandled()) {
538                             sipStack.putInMergeTable(transaction, sipRequest);
539                         }
540                         /*
541                          * Note that ACK is a pseudo transaction. It is never added to the stack
542                          * and you do not get transaction terminated events on ACK.
543                          */
544 
545                         if (sipStack.deliverTerminatedEventForAck) {
546                             try {
547                                 sipStack.addTransaction(transaction);
548                                 transaction.scheduleAckRemoval();
549                             } catch (IOException ex) {
550 
551                             }
552                         } else {
553                             transaction.setMapped(true);
554                         }
555 
556                     }
557                 }
558             }
559         } else if (sipRequest.getMethod().equals(Request.PRACK)) {
560 
561             /*
562              * RFC 3262: A matching PRACK is defined as one within the same dialog as the
563              * response, and whose method, CSeq-num, and response-num in the RAck header field
564              * match, respectively, the method from the CSeq, the sequence number from the CSeq,
565              * and the sequence number from the RSeq of the reliable provisional response.
566              */
567 
568             if (sipStack.isLoggingEnabled())
569                 sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog);
570 
571             if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
572                 if (sipStack.isLoggingEnabled()) {
573                     sipStack.getStackLogger().logDebug(
574                             "Dialog does not exist " + sipRequest.getFirstLine()
575                                     + " isServerTransaction = " + true);
576 
577                 }
578                 if (sipStack.isLoggingEnabled()) {
579                     sipStack
580                             .getStackLogger()
581                             .logDebug(
582                                     "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
583                 }
584                 SIPResponse notExist = sipRequest
585                         .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
586 
587                 try {
588                     sipProvider.sendResponse(notExist);
589                 } catch (SipException e) {
590                     sipStack.getStackLogger().logError("error sending response", e);
591                 }
592                 if (transaction != null) {
593                     sipStack.removeTransaction(transaction);
594                     transaction.releaseSem();
595                 }
596                 return;
597 
598             } else if (dialog != null) {
599                 if (!dialog.handlePrack(sipRequest)) {
600                     if (sipStack.isLoggingEnabled())
601                         sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK ");
602                     if (transaction != null) {
603                         sipStack.removeTransaction(transaction);
604                         transaction.releaseSem();
605                     }
606                     return;
607                 } else {
608                     try {
609                         sipStack.addTransaction(transaction);
610                         dialog.addTransaction(transaction);
611                         dialog.addRoute(sipRequest);
612                         transaction.setDialog(dialog, dialogId);
613                     } catch (Exception ex) {
614                         InternalErrorHandler.handleException(ex);
615                     }
616                 }
617             } else {
618                 if (sipStack.isLoggingEnabled())
619                     sipStack.getStackLogger().logDebug(
620                             "Processing PRACK without a DIALOG -- this must be a proxy element");
621             }
622 
623         } else if (sipRequest.getMethod().equals(Request.BYE)) {
624             // Check for correct sequence numbering of the BYE
625             if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
626                 if (sipStack.isLoggingEnabled())
627                     sipStack.getStackLogger().logDebug(
628                             "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " "
629                                     + sipRequest.getCSeq().getSeqNumber());
630 
631                 if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber()
632                         && transaction.getState() == TransactionState.TRYING) {
633 
634                     this.sendServerInternalErrorResponse(sipRequest, transaction);
635 
636                 }
637                 // If the stack knows about the tx, then remove it.
638                 if (transaction != null)
639                     sipStack.removeTransaction(transaction);
640                 return;
641 
642             } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
643                 // Drop bye's with 481 if dialog does not exist.
644                 // If dialog support is enabled then
645                 // there must be a dialog associated with the bye
646                 // No dialog could be found and requests on this
647                 // provider. Must act like a user agent -- so drop the request.
648                 // NOTE: if Automatic dialog support is not enabled,
649                 // then it is the application's responsibility to
650                 // take care of this error condition possibly.
651 
652                 SIPResponse response = sipRequest
653                         .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
654                 response.setReasonPhrase("Dialog Not Found");
655 
656                 if (sipStack.isLoggingEnabled())
657                     sipStack.getStackLogger().logDebug(
658                             "dropping request -- automatic dialog "
659                                     + "support enabled and dialog does not exist!");
660                 try {
661                     transaction.sendResponse(response);
662                 } catch (SipException ex) {
663                     sipStack.getStackLogger().logError("Error in sending response", ex);
664                 }
665                 // If the stack knows about the tx, then remove it.
666                 if (transaction != null) {
667                     sipStack.removeTransaction(transaction);
668                     transaction.releaseSem();
669                     transaction = null;
670                 }
671                 return;
672 
673             }
674 
675             // note that the transaction may be null (which
676             // happens when no dialog for the bye was found.
677             // and automatic dialog support is disabled (i.e. the app wants
678             // to manage its own dialog layer.
679             if (transaction != null && dialog != null) {
680                 try {
681                     if (sipProvider == dialog.getSipProvider()) {
682                         sipStack.addTransaction(transaction);
683                         dialog.addTransaction(transaction);
684                         transaction.setDialog(dialog, dialogId);
685                     }
686 
687                 } catch (IOException ex) {
688                     InternalErrorHandler.handleException(ex);
689                 }
690             }
691             if (sipStack.isLoggingEnabled()) {
692                 sipStack.getStackLogger().logDebug(
693                         "BYE Tx = " + transaction + " isMapped ="
694                                 + transaction.isTransactionMapped());
695             }
696 
697         } else if (sipRequest.getMethod().equals(Request.CANCEL)) {
698 
699             SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction(
700                     sipRequest, true);
701             if (sipStack.isLoggingEnabled()) {
702                 sipStack.getStackLogger().logDebug(
703                         "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = "
704                                 + transaction + " isMapped = "
705                                 + transaction.isTransactionMapped());
706 
707             }
708             // Processing incoming CANCEL.
709             // Check if we can process the CANCEL request.
710             if (sipRequest.getMethod().equals(Request.CANCEL)) {
711                 // If the CANCEL comes in too late, there's not
712                 // much that the Listener can do so just do the
713                 // default action and avoid bothering the listener.
714                 if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) {
715                     // If transaction already exists but it is
716                     // too late to cancel the transaction then
717                     // just respond OK to the CANCEL and bail.
718                     if (sipStack.isLoggingEnabled())
719                         sipStack.getStackLogger().logDebug("Too late to cancel Transaction");
720                     // send OK and just ignore the CANCEL.
721                     try {
722 
723                         transaction.sendResponse(sipRequest.createResponse(Response.OK));
724                     } catch (Exception ex) {
725                         if (ex.getCause() != null && ex.getCause() instanceof IOException) {
726                             st.raiseIOExceptionEvent();
727                         }
728                     }
729                     return;
730                 }
731                 if (sipStack.isLoggingEnabled())
732                     sipStack.getStackLogger().logDebug("Cancel transaction = " + st);
733 
734             }
735             if (transaction != null && st != null && st.getDialog() != null) {
736                 // Found an invite tx corresponding to the CANCEL.
737                 // Set up the client tx and pass up to listener.
738                 transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
739                 dialog = (SIPDialog) st.getDialog();
740             } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled()
741                     && transaction != null) {
742                 // Could not find a invite tx corresponding to the CANCEL.
743                 // Automatic dialog support is enabled so I must behave like
744                 // an endpoint on this provider.
745                 // Send the error response for the cancel.
746 
747                 SIPResponse response = sipRequest
748                         .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
749                 if (sipStack.isLoggingEnabled()) {
750                     sipStack.getStackLogger().logDebug(
751                             "dropping request -- automatic dialog support "
752                                     + "enabled and INVITE ST does not exist!");
753                 }
754                 try {
755                     sipProvider.sendResponse(response);
756                 } catch (SipException ex) {
757                     InternalErrorHandler.handleException(ex);
758                 }
759                 if (transaction != null) {
760                     sipStack.removeTransaction(transaction);
761                     transaction.releaseSem();
762                 }
763                 return;
764 
765             }
766 
767             // INVITE was handled statefully so the CANCEL must also be
768             // statefully handled.
769             if (st != null) {
770                 try {
771                     if (transaction != null) {
772                         sipStack.addTransaction(transaction);
773                         transaction.setPassToListener();
774                         transaction.setInviteTransaction(st);
775                         // Dont let the INVITE and CANCEL be concurrently
776                         // processed.
777                         st.acquireSem();
778 
779                     }
780 
781                 } catch (Exception ex) {
782                     InternalErrorHandler.handleException(ex);
783                 }
784             }
785         } else if (sipRequest.getMethod().equals(Request.INVITE)) {
786             SIPTransaction lastTransaction = dialog == null ? null : dialog
787                     .getInviteTransaction();
788 
789             /*
790              * RFC 3261 Chapter 14. A UAS that receives a second INVITE before it sends the final
791              * response to a first INVITE with a lower CSeq sequence number on the same dialog
792              * MUST return a 500 (Server Internal Error) response to the second INVITE and MUST
793              * include a Retry-After header field with a randomly chosen value of between 0 and 10
794              * seconds.
795              */
796 
797             if (dialog != null && transaction != null && lastTransaction != null
798                     && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber()
799                     && lastTransaction instanceof SIPServerTransaction
800                     && sipProvider.isDialogErrorsAutomaticallyHandled()
801                     && dialog.isSequnceNumberValidation()
802                     && lastTransaction.isInviteTransaction()
803                     && lastTransaction.getState() != TransactionState.COMPLETED
804                     && lastTransaction.getState() != TransactionState.TERMINATED
805                     && lastTransaction.getState() != TransactionState.CONFIRMED) {
806 
807                 if (sipStack.isLoggingEnabled()) {
808                     sipStack.getStackLogger().logDebug(
809                             "Sending 500 response for out of sequence message");
810                 }
811                 this.sendServerInternalErrorResponse(sipRequest, transaction);
812                 return;
813 
814             }
815 
816             /*
817              * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that
818              * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in
819              * progress MUST return a 491 (Request Pending) response to the received INVITE.
820              */
821             lastTransaction = (dialog == null ? null : dialog.getLastTransaction());
822 
823             if (dialog != null
824                     && sipProvider.isDialogErrorsAutomaticallyHandled()
825                     && lastTransaction != null
826                     && lastTransaction.isInviteTransaction()
827                     && lastTransaction instanceof ClientTransaction
828                     && lastTransaction.getLastResponse() != null
829                     && lastTransaction.getLastResponse().getStatusCode() == 200
830                     && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq()
831                             .getSeqNumber())) {
832                 if (sipStack.isLoggingEnabled()) {
833                     sipStack.getStackLogger().logDebug(
834                             "Sending 491 response for client Dialog ACK not sent.");
835                 }
836                 this.sendRequestPendingResponse(sipRequest, transaction);
837                 return;
838             }
839 
840             if (dialog != null && lastTransaction != null
841                     && sipProvider.isDialogErrorsAutomaticallyHandled()
842                     && lastTransaction.isInviteTransaction()
843                     && lastTransaction instanceof ServerTransaction && !dialog.isAckSeen()) {
844                 if (sipStack.isLoggingEnabled()) {
845                     sipStack.getStackLogger().logDebug(
846                             "Sending 491 response for server Dialog ACK not seen.");
847                 }
848                 this.sendRequestPendingResponse(sipRequest, transaction);
849                 return;
850 
851             }
852         }
853 
854         // Sequence numbers are supposed to be incremented
855         // sequentially within a dialog for RFC 3261
856         // Note BYE, CANCEL and ACK is handled above - so no check here.
857 
858         if (sipStack.isLoggingEnabled()) {
859             sipStack.getStackLogger().logDebug(
860                     "CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " + transaction);
861         }
862 
863         if (dialog != null && transaction != null && !sipRequest.getMethod().equals(Request.BYE)
864                 && !sipRequest.getMethod().equals(Request.CANCEL)
865                 && !sipRequest.getMethod().equals(Request.ACK)
866                 && !sipRequest.getMethod().equals(Request.PRACK)) {
867 
868             if (!dialog.isRequestConsumable(sipRequest)) {
869 
870                 /*
871                  * RFC 3261: "UAS Behavior" section (12.2.2): If the remote sequence number was
872                  * not empty, but the sequence number of the request is lower than the remote
873                  * sequence number, the request is out of order and MUST be rejected with a 500
874                  * (Server Internal Error) response.
875                  */
876 
877                 // Drop the request
878                 if (sipStack.isLoggingEnabled()) {
879                     sipStack.getStackLogger().logDebug(
880                             "Dropping out of sequence message " + dialog.getRemoteSeqNumber()
881                                     + " " + sipRequest.getCSeq());
882                 }
883 
884                 // send error when stricly higher, ignore when ==
885                 // (likely still processing, error would interrupt that)
886 
887                 if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber()
888                         && sipProvider.isDialogErrorsAutomaticallyHandled()
889                         && (transaction.getState() == TransactionState.TRYING || transaction
890                                 .getState() == TransactionState.PROCEEDING)) {
891                     this.sendServerInternalErrorResponse(sipRequest, transaction);
892 
893                 }
894                 return;
895             }
896 
897             try {
898                 if (sipProvider == dialog.getSipProvider()) {
899                     sipStack.addTransaction(transaction);
900                     // This will set the remote sequence number.
901                     dialog.addTransaction(transaction);
902                     dialog.addRoute(sipRequest);
903                     transaction.setDialog(dialog, dialogId);
904 
905                 }
906             } catch (IOException ex) {
907                 transaction.raiseIOExceptionEvent();
908                 sipStack.removeTransaction(transaction);
909                 return;
910             }
911 
912         }
913 
914         RequestEvent sipEvent;
915 
916         if (sipStack.isLoggingEnabled()) {
917             sipStack.getStackLogger().logDebug(
918                     sipRequest.getMethod() + " transaction.isMapped = "
919                             + transaction.isTransactionMapped());
920         }
921 
922         /*
923          * RFC 3265: Each event package MUST specify whether forked SUBSCRIBE requests are allowed
924          * to install multiple subscriptions. If such behavior is not allowed, the first potential
925          * dialog- establishing message will create a dialog. All subsequent NOTIFY messages which
926          * correspond to the SUBSCRIBE message (i.e., match "To", "From", "From" header "tag"
927          * parameter, "Call-ID", "CSeq", "Event", and "Event" header "id" parameter) but which do
928          * not match the dialog would be rejected with a 481 response. Note that the 200-class
929          * response to the SUBSCRIBE can arrive after a matching NOTIFY has been received; such
930          * responses might not correlate to the same dialog established by the NOTIFY. Except as
931          * required to complete the SUBSCRIBE transaction, such non-matching 200-class responses
932          * are ignored.
933          */
934 
935         if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) {
936 
937             SIPClientTransaction pendingSubscribeClientTx = sipStack.findSubscribeTransaction(
938                     sipRequest, listeningPoint);
939 
940             if (sipStack.isLoggingEnabled()) {
941                 sipStack.getStackLogger().logDebug(
942                         "PROCESSING NOTIFY  DIALOG == null " + pendingSubscribeClientTx);
943             }
944 
945             /*
946              * RFC 3265: Upon receiving a NOTIFY request, the subscriber should check that it
947              * matches at least one of its outstanding subscriptions; if not, it MUST return a
948              * "481 Subscription does not exist" response unless another 400- or -class response
949              * is more appropriate.
950              */
951             if (sipProvider.isAutomaticDialogSupportEnabled() && pendingSubscribeClientTx == null
952                     && !sipStack.deliverUnsolicitedNotify) {
953                 /*
954                  * This is the case of the UAC receiving a Stray NOTIFY for which it has not
955                  * previously sent out a SUBSCRIBE and for which it does not have an established
956                  * dialog.
957                  */
958                 try {
959                     if (sipStack.isLoggingEnabled()) {
960                         sipStack.getStackLogger().logDebug(
961                                 "Could not find Subscription for Notify Tx.");
962                     }
963                     Response errorResponse = sipRequest
964                             .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
965                     errorResponse.setReasonPhrase("Subscription does not exist");
966                     sipProvider.sendResponse(errorResponse);
967                     return;
968 
969                 } catch (Exception ex) {
970                     sipStack.getStackLogger().logError(
971                             "Exception while sending error response statelessly", ex);
972                     return;
973                 }
974 
975             }
976 
977             // If the server transaction cannot be found or if it
978             // aleady has a dialog attached to it then just assign the
979             // notify to this dialog and pass it up.
980             if (pendingSubscribeClientTx != null) {
981                 // The response to the pending subscribe tx can try to create
982                 // a dialog at the same time that the notify is trying to
983                 // create a dialog. Thus we cannot process both at the
984                 // same time.
985 
986                 transaction.setPendingSubscribe(pendingSubscribeClientTx);
987                 // The transaction gets assigned to the dialog from the
988                 // outgoing subscribe. First see if anybody claimed the
989                 // default Dialog for the outgoing Subscribe request.
990                 SIPDialog subscriptionDialog = (SIPDialog) pendingSubscribeClientTx
991                         .getDefaultDialog();
992 
993                 // TODO -- refactor this. Can probably be written far cleaner.
994                 if (subscriptionDialog == null || subscriptionDialog.getDialogId() == null
995                         || !subscriptionDialog.getDialogId().equals(dialogId)) {
996                     // Notify came in before you could assign a response to
997                     // the subscribe.
998                     // grab the default dialog and assign it to the tags in
999                     // the notify.
1000                     if (subscriptionDialog != null && subscriptionDialog.getDialogId() == null) {
1001                         subscriptionDialog.setDialogId(dialogId);
1002 
1003                     } else {
1004                         subscriptionDialog = pendingSubscribeClientTx.getDialog(dialogId);
1005                     }
1006                     if (sipStack.isLoggingEnabled()) {
1007                         sipStack.getStackLogger().logDebug(
1008                                 "PROCESSING NOTIFY Subscribe DIALOG " + subscriptionDialog);
1009                     }
1010 
1011                     // The user could have createed a dialog before sending out
1012                     // the SUBSCRIBE on the subscribe tx.
1013                     if (subscriptionDialog == null
1014                             && (sipProvider.isAutomaticDialogSupportEnabled() || pendingSubscribeClientTx
1015                                     .getDefaultDialog() != null)) {
1016                         Event event = (Event) sipRequest.getHeader(EventHeader.NAME);
1017                         if (sipStack.isEventForked(event.getEventType())) {
1018 
1019                             subscriptionDialog = SIPDialog.createFromNOTIFY(
1020                                     pendingSubscribeClientTx, transaction);
1021 
1022                         }
1023 
1024                     }
1025                     if (subscriptionDialog != null) {
1026                         transaction.setDialog(subscriptionDialog, dialogId);
1027                         subscriptionDialog.setState(DialogState.CONFIRMED.getValue());
1028                         sipStack.putDialog(subscriptionDialog);
1029                         pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId);
1030                         if (!transaction.isTransactionMapped()) {
1031                             this.sipStack.mapTransaction(transaction);
1032                             // Let the listener see it if it just got
1033                             // created.
1034                             // otherwise, we have already processed the tx
1035                             // so
1036                             // we dont want the listener to see it.
1037                             transaction.setPassToListener();
1038                             try {
1039                                 this.sipStack.addTransaction(transaction);
1040                             } catch (Exception ex) {
1041                             }
1042                         }
1043                     }
1044                 } else {
1045                     // The subscription default dialog is our dialog.
1046                     // Found a subscrbe dialog for the NOTIFY
1047                     // So map the tx.
1048                     transaction.setDialog(subscriptionDialog, dialogId);
1049                     dialog = subscriptionDialog;
1050                     if (!transaction.isTransactionMapped()) {
1051                         this.sipStack.mapTransaction(transaction);
1052                         // Let the listener see it if it just got created.
1053                         // otherwise, we have already processed the tx so
1054                         // we dont want the listener to see it.
1055                         transaction.setPassToListener();
1056                         try {
1057                             this.sipStack.addTransaction(transaction);
1058                         } catch (Exception ex) {
1059                         }
1060                     }
1061                     sipStack.putDialog(subscriptionDialog);
1062                     if (pendingSubscribeClientTx != null) {
1063                         subscriptionDialog.addTransaction(pendingSubscribeClientTx);
1064                         pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId);
1065 
1066                     }
1067                 }
1068                 if (transaction != null
1069                         && ((SIPServerTransaction) transaction).isTransactionMapped()) {
1070                     // Shadow transaction has been created and the stack
1071                     // knows
1072                     // about it.
1073                     sipEvent = new RequestEvent((SipProvider) sipProvider,
1074                             (ServerTransaction) transaction, subscriptionDialog,
1075                             (Request) sipRequest);
1076                 } else {
1077                     // Shadow transaction has been created but the stack
1078                     // does
1079                     // not know
1080                     // about it.
1081                     sipEvent = new RequestEvent((SipProvider) sipProvider, null,
1082                             subscriptionDialog, (Request) sipRequest);
1083                 }
1084 
1085             } else {
1086                 if (sipStack.isLoggingEnabled()) {
1087                     sipStack.getStackLogger().logDebug("could not find subscribe tx");
1088                 }
1089 
1090                 // Got a notify out of the blue - just pass it up
1091                 // for stateless handling by the application.
1092                 sipEvent = new RequestEvent(sipProvider, null, null, (Request) sipRequest);
1093             }
1094 
1095         } else {
1096 
1097             // For a dialog creating event - set the transaction to null.
1098             // The listener can create the dialog if needed.
1099             if (transaction != null
1100                     && (((SIPServerTransaction) transaction).isTransactionMapped())) {
1101                 sipEvent = new RequestEvent(sipProvider, (ServerTransaction) transaction, dialog,
1102                         (Request) sipRequest);
1103             } else {
1104                 sipEvent = new RequestEvent(sipProvider, null, dialog, (Request) sipRequest);
1105             }
1106         }
1107         sipProvider.handleEvent(sipEvent, transaction);
1108 
1109     }
1110 
1111     /**
1112      * Process the response.
1113      *
1114      * @exception SIPServerException is thrown when there is an error processing the response
1115      * @param incomingMessageChannel -- message channel on which the response is received.
1116      */
processResponse(SIPResponse response, MessageChannel incomingMessageChannel, SIPDialog dialog)1117     public void processResponse(SIPResponse response, MessageChannel incomingMessageChannel,
1118             SIPDialog dialog) {
1119         if (sipStack.isLoggingEnabled()) {
1120             sipStack.getStackLogger().logDebug(
1121                     "PROCESSING INCOMING RESPONSE" + response.encodeMessage());
1122         }
1123         if (listeningPoint == null) {
1124             if (sipStack.isLoggingEnabled())
1125                 sipStack.getStackLogger().logError(
1126                         "Dropping message: No listening point" + " registered!");
1127             return;
1128         }
1129 
1130         if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(response)) {
1131             if (sipStack.isLoggingEnabled()) {
1132                 sipStack
1133                         .getStackLogger()
1134                         .logError(
1135                                 "Dropping response - topmost VIA header does not originate from this stack");
1136             }
1137             return;
1138         }
1139 
1140         SipProviderImpl sipProvider = listeningPoint.getProvider();
1141         if (sipProvider == null) {
1142             if (sipStack.isLoggingEnabled()) {
1143                 sipStack.getStackLogger().logError("Dropping message:  no provider");
1144             }
1145             return;
1146         }
1147         if (sipProvider.getSipListener() == null) {
1148             if (sipStack.isLoggingEnabled()) {
1149                 sipStack.getStackLogger().logError("No listener -- dropping response!");
1150             }
1151             return;
1152         }
1153 
1154         SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel;
1155         SipStackImpl sipStackImpl = sipProvider.sipStack;
1156 
1157         if (sipStack.isLoggingEnabled()) {
1158             sipStackImpl.getStackLogger().logDebug("Transaction = " + transaction);
1159         }
1160 
1161         if (transaction == null) {
1162             // Transaction is null but the dialog is not null. This means that
1163             // the transaction has been removed by the stack.
1164             // If the dialog exists, then it may need to retransmit ACK so
1165             // we cannot drop the response.
1166             if (dialog != null) {
1167                 if (response.getStatusCode() / 100 != 2) {
1168                     if (sipStack.isLoggingEnabled()) {
1169                         sipStack
1170                                 .getStackLogger()
1171                                 .logDebug(
1172                                         "Response is not a final response and dialog is found for response -- dropping response!");
1173                     }
1174                     return;
1175                 } else if (dialog.getState() == DialogState.TERMINATED) {
1176                     if (sipStack.isLoggingEnabled()) {
1177                         sipStack.getStackLogger().logDebug(
1178                                 "Dialog is terminated -- dropping response!");
1179                     }
1180                     return;
1181                 } else {
1182                     boolean ackAlreadySent = false;
1183                     if (dialog.isAckSeen() && dialog.getLastAckSent() != null) {
1184                         if (dialog.getLastAckSent().getCSeq().getSeqNumber() == response
1185                                 .getCSeq().getSeqNumber()) {
1186                             // the last ack sent corresponded to this 200
1187                             ackAlreadySent = true;
1188                         }
1189                     }
1190                     // 200 retransmission for the final response.
1191                     if (ackAlreadySent
1192                             && response.getCSeq().getMethod().equals(dialog.getMethod())) {
1193                         try {
1194                             // Found the dialog - resend the ACK and
1195                             // dont pass up the null transaction
1196                             if (sipStack.isLoggingEnabled()) {
1197                                 sipStack.getStackLogger().logDebug(
1198                                         "Retransmission of OK detected: Resending last ACK");
1199                             }
1200                             dialog.resendAck();
1201                             return;
1202                         } catch (SipException ex) {
1203                             // What to do here ?? kill the dialog?
1204                             sipStack.getStackLogger().logError("could not resend ack", ex);
1205                         }
1206                     }
1207                 }
1208             }
1209 
1210             if (sipStack.isLoggingEnabled()) {
1211                 sipStack.getStackLogger().logDebug(
1212                         "could not find tx, handling statelessly Dialog =  " + dialog);
1213             }
1214             // Pass the response up to the application layer to handle
1215             // statelessly.
1216 
1217             ResponseEventExt sipEvent = new ResponseEventExt(sipProvider, transaction, dialog,
1218                     (Response) response);
1219 
1220             if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) {
1221                 SIPClientTransaction forked = this.sipStack.getForkedTransaction(response
1222                         .getTransactionId());
1223                 sipEvent.setOriginalTransaction(forked);
1224             }
1225 
1226             sipProvider.handleEvent(sipEvent, transaction);
1227             return;
1228         }
1229 
1230         ResponseEventExt responseEvent = null;
1231 
1232         // Here if there is an assigned dialog
1233         responseEvent = new ResponseEventExt(sipProvider, (ClientTransactionExt) transaction,
1234                 dialog, (Response) response);
1235         if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) {
1236             SIPClientTransaction forked = this.sipStack.getForkedTransaction(response
1237                     .getTransactionId());
1238             responseEvent.setOriginalTransaction(forked);
1239         }
1240 
1241         // Set the Dialog for the response.
1242         if (dialog != null && response.getStatusCode() != 100) {
1243             // set the last response for the dialog.
1244             dialog.setLastResponse(transaction, response);
1245             transaction.setDialog(dialog, dialog.getDialogId());
1246         }
1247 
1248         sipProvider.handleEvent(responseEvent, transaction);
1249 
1250     }
1251 
1252     /**
1253      * Just a placeholder. This is called from the stack for message logging. Auxiliary processing
1254      * information can be passed back to be written into the log file.
1255      *
1256      * @return auxiliary information that we may have generated during the message processing
1257      *         which is retrieved by the message logger.
1258      */
getProcessingInfo()1259     public String getProcessingInfo() {
1260         return null;
1261     }
1262 
1263     /*
1264      * (non-Javadoc)
1265      *
1266      * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse,
1267      *      gov.nist.javax.sip.stack.MessageChannel)
1268      */
processResponse(SIPResponse sipResponse, MessageChannel incomingChannel)1269     public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) {
1270         String dialogID = sipResponse.getDialogId(false);
1271         SIPDialog sipDialog = this.sipStack.getDialog(dialogID);
1272 
1273         String method = sipResponse.getCSeq().getMethod();
1274         if (sipStack.isLoggingEnabled()) {
1275             sipStack.getStackLogger().logDebug(
1276                     "PROCESSING INCOMING RESPONSE: " + sipResponse.encodeMessage());
1277         }
1278 
1279         if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(sipResponse)) {
1280             if (sipStack.isLoggingEnabled()) {
1281                 sipStack.getStackLogger().logError("Detected stray response -- dropping");
1282             }
1283             return;
1284         }
1285 
1286         if (listeningPoint == null) {
1287             if (sipStack.isLoggingEnabled())
1288                 sipStack.getStackLogger().logDebug(
1289                         "Dropping message: No listening point" + " registered!");
1290             return;
1291         }
1292 
1293         SipProviderImpl sipProvider = listeningPoint.getProvider();
1294         if (sipProvider == null) {
1295             if (sipStack.isLoggingEnabled()) {
1296                 sipStack.getStackLogger().logDebug("Dropping message:  no provider");
1297             }
1298             return;
1299         }
1300 
1301         if (sipProvider.getSipListener() == null) {
1302             if (sipStack.isLoggingEnabled()) {
1303                 sipStack.getStackLogger().logDebug(
1304                         "Dropping message:  no sipListener registered!");
1305             }
1306             return;
1307         }
1308 
1309         SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel;
1310         // This may be a dialog creating method for which the ACK has not yet
1311         // been sent
1312         // but the dialog has already been assigned ( happens this way for
1313         // 3PCC).
1314         if (sipDialog == null && transaction != null) {
1315             sipDialog = transaction.getDialog(dialogID);
1316             if (sipDialog != null && sipDialog.getState() == DialogState.TERMINATED)
1317                 sipDialog = null;
1318         }
1319 
1320         if (sipStack.isLoggingEnabled())
1321             sipStack.getStackLogger().logDebug(
1322                     "Transaction = " + transaction + " sipDialog = " + sipDialog);
1323 
1324         if (this.transactionChannel != null) {
1325             String originalFrom = ((SIPRequest) this.transactionChannel.getRequest())
1326                     .getFromTag();
1327             if (originalFrom == null ^ sipResponse.getFrom().getTag() == null) {
1328                 if (sipStack.isLoggingEnabled())
1329                     sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
1330                 return;
1331             }
1332             if (originalFrom != null
1333                     && !originalFrom.equalsIgnoreCase(sipResponse.getFrom().getTag())) {
1334                 if (sipStack.isLoggingEnabled())
1335                     sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
1336                 return;
1337             }
1338 
1339         }
1340         if (sipStack.isDialogCreated(method) && sipResponse.getStatusCode() != 100
1341                 && sipResponse.getFrom().getTag() != null && sipResponse.getTo().getTag() != null
1342                 && sipDialog == null) {
1343             if (sipProvider.isAutomaticDialogSupportEnabled()) {
1344                 if (this.transactionChannel != null) {
1345                     if (sipDialog == null) {
1346                         // There could be an existing dialog for this response.
1347                         sipDialog = sipStack.createDialog(
1348                                 (SIPClientTransaction) this.transactionChannel, sipResponse);
1349 
1350                         this.transactionChannel.setDialog(sipDialog, sipResponse
1351                                 .getDialogId(false));
1352                     }
1353                 } else {
1354                     sipDialog = this.sipStack.createDialog(sipProvider, sipResponse);
1355                 }
1356             }
1357 
1358         } else {
1359             // Have a dialog but could not find transaction.
1360             if (sipDialog != null && transaction == null
1361                     && sipDialog.getState() != DialogState.TERMINATED) {
1362                 if (sipResponse.getStatusCode() / 100 != 2) {
1363                     if (sipStack.isLoggingEnabled())
1364                         sipStack.getStackLogger().logDebug(
1365                                 "status code != 200 ; statusCode = "
1366                                         + sipResponse.getStatusCode());
1367                 } else if (sipDialog.getState() == DialogState.TERMINATED) {
1368                     if (sipStack.isLoggingEnabled()) {
1369                         sipStack.getStackLogger().logDebug(
1370                                 "Dialog is terminated -- dropping response!");
1371                     }
1372                     // Dialog exists but was terminated - just create and send an ACK for the OK.
1373                     // It could be late arriving.
1374                     if (sipResponse.getStatusCode() / 100 == 2
1375                             && sipResponse.getCSeq().getMethod().equals(Request.INVITE)) {
1376                         try {
1377                             Request ackRequest = sipDialog.createAck(sipResponse.getCSeq()
1378                                     .getSeqNumber());
1379                             sipDialog.sendAck(ackRequest);
1380                         } catch (Exception ex) {
1381                             sipStack.getStackLogger().logError("Error creating ack", ex);
1382                         }
1383                     }
1384                     return;
1385                 } else {
1386                     boolean ackAlreadySent = false;
1387                     if (sipDialog.isAckSeen() && sipDialog.getLastAckSent() != null) {
1388                         if (sipDialog.getLastAckSent().getCSeq().getSeqNumber() == sipResponse
1389                                 .getCSeq().getSeqNumber()
1390                                 && sipResponse.getDialogId(false).equals(
1391                                         sipDialog.getLastAckSent().getDialogId(false))) {
1392                             // the last ack sent corresponded to this 200
1393                             ackAlreadySent = true;
1394                         }
1395                     }
1396                     // 200 retransmission for the final response.
1397                     if (ackAlreadySent
1398                             && sipResponse.getCSeq().getMethod().equals(sipDialog.getMethod())) {
1399                         try {
1400                             // Found the dialog - resend the ACK and
1401                             // dont pass up the null transaction
1402                             if (sipStack.isLoggingEnabled())
1403                                 sipStack.getStackLogger().logDebug("resending ACK");
1404 
1405                             sipDialog.resendAck();
1406                             return;
1407                         } catch (SipException ex) {
1408                             // What to do here ?? kill the dialog?
1409                         }
1410                     }
1411                 }
1412             }
1413             // Pass the response up to the application layer to handle
1414             // statelessly.
1415 
1416         }
1417         if (sipStack.isLoggingEnabled())
1418             sipStack.getStackLogger().logDebug("sending response to TU for processing ");
1419 
1420         if (sipDialog != null && sipResponse.getStatusCode() != 100
1421                 && sipResponse.getTo().getTag() != null) {
1422             sipDialog.setLastResponse(transaction, sipResponse);
1423         }
1424 
1425         ResponseEventExt responseEvent = new ResponseEventExt(sipProvider,
1426                 (ClientTransactionExt) transaction, sipDialog, (Response) sipResponse);
1427 
1428         if (sipResponse.getCSeq().getMethod().equals(Request.INVITE)) {
1429             ClientTransactionExt originalTx = this.sipStack.getForkedTransaction(sipResponse
1430                     .getTransactionId());
1431             responseEvent.setOriginalTransaction(originalTx);
1432         }
1433 
1434         sipProvider.handleEvent(responseEvent, transaction);
1435 
1436     }
1437 }
1438