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 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 */ 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 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 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 */ 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 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 */ 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 */ 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 */ 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 */ 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