1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip; 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.*; 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.*; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.*; 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.*; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.*; 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.ThreadAuditor; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* bug fixes SIPQuest communications and Shu-Lin Chen. */ 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Event Scanner to deliver events to the Listener. 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.41 $ $Date: 2009/11/18 02:35:17 $ 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/> 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangclass EventScanner implements Runnable { 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private boolean isStopped; 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private int refCount; 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // SIPquest: Fix for deadlocks 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private LinkedList pendingEvents = new LinkedList(); 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private int[] eventMutex = { 0 }; 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private SipStackImpl sipStack; 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void incrementRefcount() { 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (eventMutex) { 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.refCount++; 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public EventScanner(SipStackImpl sipStackImpl) { 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.pendingEvents = new LinkedList(); 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Thread myThread = new Thread(this); 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This needs to be set to false else the 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // main thread mysteriously exits. 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myThread.setDaemon(false); 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.sipStack = sipStackImpl; 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myThread.setName("EventScannerThread"); 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang myThread.start(); 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addEvent(EventWrapper eventWrapper) { 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("addEvent " + eventWrapper); 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (this.eventMutex) { 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pendingEvents.add(eventWrapper); 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Add the event into the pending events list 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventMutex.notify(); 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Stop the event scanner. Decrement the reference count and exit the 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * scanner thread if the ref count goes to 0. 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void stop() { 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (eventMutex) { 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.refCount > 0) 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.refCount--; 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.refCount == 0) { 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang isStopped = true; 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventMutex.notify(); 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Brutally stop the event scanner. This does not wait for the refcount to 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * go to 0. 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void forceStop() { 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (this.eventMutex) { 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.isStopped = true; 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.refCount = 0; 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.eventMutex.notify(); 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void deliverEvent(EventWrapper eventWrapper) { 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang EventObject sipEvent = eventWrapper.sipEvent; 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "sipEvent = " + sipEvent + "source = " 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipEvent.getSource()); 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SipListener sipListener = null; 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!(sipEvent instanceof IOExceptionEvent)) { 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener = ((SipProviderImpl) sipEvent.getSource()).getSipListener(); 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener = sipStack.getSipListener(); 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipEvent instanceof RequestEvent) { 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check if this request has already created a 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // transaction 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPRequest sipRequest = (SIPRequest) ((RequestEvent) sipEvent) 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getRequest(); 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "deliverEvent : " 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getFirstLine() 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " transaction " 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + eventWrapper.transaction 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + " sipEvent.serverTx = " 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ((RequestEvent) sipEvent) 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getServerTransaction()); 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Discard the duplicate request if a 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // transaction already exists. If the listener chose 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to handle the request statelessly, then the listener 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // will see the retransmission. 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Note that in both of these two cases, JAIN SIP will allow 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // you to handle the request statefully or statelessly. 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // An example of the latter case is REGISTER and an example 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // of the former case is INVITE. 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction tx = (SIPServerTransaction) sipStack 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .findTransaction(sipRequest, true); 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (tx != null && !tx.passToListener()) { 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: make an exception for a very rare case: some 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // (broken) UACs use 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the same branch parameter for an ACK. Such an ACK should 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // be passed 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to the listener (tx == INVITE ST, terminated upon sending 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // 2xx but 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // lingering to catch retransmitted INVITEs) 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipRequest.getMethod().equals(Request.ACK) 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && tx.isInviteTransaction() && 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ( tx.getLastResponse().getStatusCode()/100 == 2 || 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.isNon2XXAckPassedToListener())) { 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug( 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Detected broken client sending ACK with same branch! Passing..."); 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "transaction already exists! " + tx); 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipStack.findPendingTransaction(sipRequest) != null) { 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "transaction already exists!!"); 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Put it in the pending list so that if a repeat 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // request comes along it will not get assigned a 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // new transaction 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPServerTransaction st = (SIPServerTransaction) eventWrapper.transaction; 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.putPendingTransaction(st); 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Set up a pointer to the transaction. 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipRequest.setTransaction(eventWrapper.transaction); 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Change made by SIPquest 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger() 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logDebug( 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Calling listener " 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getFirstLine()); 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Calling listener " + eventWrapper.transaction); 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null) 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener.processRequest((RequestEvent) sipEvent); 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Done processing Message " 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipRequest.getFirstLine()); 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (eventWrapper.transaction != null) { 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPDialog dialog = (SIPDialog) eventWrapper.transaction 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getDialog(); 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (dialog != null) 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dialog.requestConsumed(); 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We cannot let this thread die under any 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // circumstances. Protect ourselves by logging 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // errors to the console but continue. 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Done processing Message " 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ((SIPRequest) (((RequestEvent) sipEvent) 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getRequest())).getFirstLine()); 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (eventWrapper.transaction != null 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && ((SIPServerTransaction) eventWrapper.transaction) 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .passToListener()) { 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SIPServerTransaction) eventWrapper.transaction) 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .releaseSem(); 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (eventWrapper.transaction != null) 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .removePendingTransaction((SIPServerTransaction) eventWrapper.transaction); 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (eventWrapper.transaction.getOriginalRequest().getMethod() 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .equals(Request.ACK)) { 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Set the tx state to terminated so it is removed from the 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // stack 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // if the user configured to get notification on ACK 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // termination 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventWrapper.transaction 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .setState(TransactionState.TERMINATED); 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipEvent instanceof ResponseEvent) { 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ResponseEvent responseEvent = (ResponseEvent) sipEvent; 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPResponse sipResponse = (SIPResponse) responseEvent 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getResponse(); 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPDialog sipDialog = ((SIPDialog) responseEvent.getDialog()); 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Calling listener for " 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + sipResponse.getFirstLine()); 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null) { 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPTransaction tx = eventWrapper.transaction; 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (tx != null) { 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang tx.setPassToListener(); 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener.processResponse((ResponseEvent) sipEvent); 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the response for a request within a dialog is a 481 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (Call/Transaction Does Not Exist) or a 408 (Request 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Timeout), the UAC SHOULD terminate the dialog. 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ((sipDialog != null && (sipDialog.getState() == null || !sipDialog 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getState().equals(DialogState.TERMINATED))) 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (sipResponse.getStatusCode() == Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST || sipResponse 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStatusCode() == Response.REQUEST_TIMEOUT)) { 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Removing dialog on 408 or 481 response"); 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog.doDeferredDelete(); 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The Client tx disappears after the first 2xx response 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * However, additional 2xx responses may arrive later for 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * example in the following scenario: 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Multiple 2xx responses may arrive at the UAC for a single 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * INVITE request due to a forking proxy. Each response is 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * distinguished by the tag parameter in the To header 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * field, and each represents a distinct dialog, with a 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * distinct dialog identifier. 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If the Listener does not ACK the 200 then we assume he 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * does not care about the dialog and gc the dialog after 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * some time. However, this is really an application bug. 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This garbage collects unacknowledged dialogs. 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipResponse.getCSeq().getMethod() 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .equals(Request.INVITE) 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipDialog != null 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && sipResponse.getStatusCode() == 200) { 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Warning! unacknowledged dialog. " + sipDialog.getState()); 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * If we dont see an ACK in 32 seconds, we want to tear down the dialog. 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipDialog.doDeferredDeleteIfNoAckSent(sipResponse.getCSeq().getSeqNumber()); 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We cannot let this thread die under any 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // circumstances. Protect ourselves by logging 343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // errors to the console but continue. 344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The original request is not needed except for INVITE 347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // transactions -- null the pointers to the transactions so 348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // that state may be released. 349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang SIPClientTransaction ct = (SIPClientTransaction) eventWrapper.transaction; 350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (ct != null 351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && TransactionState.COMPLETED == ct.getState() 352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && ct.getOriginalRequest() != null 353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && !ct.getOriginalRequest().getMethod().equals( 354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Request.INVITE)) { 355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // reduce the state to minimum 356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This assumes that the application will not need 357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // to access the request once the transaction is 358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // completed. 359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ct.clearState(); 360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // mark no longer in the event queue. 362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (eventWrapper.transaction != null 364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && eventWrapper.transaction.passToListener()) { 365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventWrapper.transaction.releaseSem(); 366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipEvent instanceof TimeoutEvent) { 370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Change made by SIPquest 371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check for null as listener could be removed. 373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null) 374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener.processTimeout((TimeoutEvent) sipEvent); 375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We cannot let this thread die under any 377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // circumstances. Protect ourselves by logging 378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // errors to the console but continue. 379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipEvent instanceof DialogTimeoutEvent) { 383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Check for null as listener could be removed. 385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null && sipListener instanceof SipListenerExt) { 386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ((SipListenerExt)sipListener).processDialogTimeout((DialogTimeoutEvent) sipEvent); 387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We cannot let this thread die under any 390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // circumstances. Protect ourselves by logging 391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // errors to the console but continue. 392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipEvent instanceof IOExceptionEvent) { 396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null) 398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener.processIOException((IOExceptionEvent) sipEvent); 399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipEvent instanceof TransactionTerminatedEvent) { 403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "About to deliver transactionTerminatedEvent"); 407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "tx = " 409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ((TransactionTerminatedEvent) sipEvent) 410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getClientTransaction()); 411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "tx = " 413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + ((TransactionTerminatedEvent) sipEvent) 414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getServerTransaction()); 415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null) 418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener 419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .processTransactionTerminated((TransactionTerminatedEvent) sipEvent); 420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (AbstractMethodError ame) { 421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: for backwards compatibility, accept this 422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack 424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .getStackLogger() 425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .logWarning( 426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Unable to call sipListener.processTransactionTerminated"); 427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (sipEvent instanceof DialogTerminatedEvent) { 431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipListener != null) 433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipListener 434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .processDialogTerminated((DialogTerminatedEvent) sipEvent); 435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (AbstractMethodError ame) { 436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // JvB: for backwards compatibility, accept this 437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logWarning( 439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Unable to call sipListener.processDialogTerminated"); 440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception ex) { 441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logException(ex); 442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logFatalError("bad event" + sipEvent); 446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * For the non-re-entrant listener this delivers the events to the listener 452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * from a single queue. If the listener is re-entrant, then the stack just 453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * calls the deliverEvent method above. 454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void run() { 457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Ask the auditor to monitor this thread 459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ThreadAuditor.ThreadHandle threadHandle = sipStack.getThreadAuditor().addCurrentThread(); 460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (true) { 462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang EventWrapper eventWrapper = null; 463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang LinkedList eventsToDeliver; 465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang synchronized (this.eventMutex) { 466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // First, wait for some events to become available. 467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (pendingEvents.isEmpty()) { 468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // There's nothing in the list, check to make sure we 469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // haven't 470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // been stopped. If we have, then let the thread die. 471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (this.isStopped) { 472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Stopped event scanner!!"); 475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // We haven't been stopped, and the event list is indeed 479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // rather empty. Wait for some events to come along. 480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Send a heartbeat to the thread auditor 482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang threadHandle.ping(); 483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Wait for events (with a timeout) 485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventMutex.wait(threadHandle.getPingIntervalInMillisecs()); 486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (InterruptedException ex) { 487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Let the thread die a normal death 488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) 489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug("Interrupted!"); 490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // There are events in the 'pending events list' that need 495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // processing. Hold onto the old 'pending Events' list, but 496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // make a new one for the other methods to operate on. This 497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // tap-dancing is to avoid deadlocks and also to ensure that 498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // the list is not modified while we are iterating over it. 499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventsToDeliver = pendingEvents; 500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang pendingEvents = new LinkedList(); 501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ListIterator iterator = eventsToDeliver.listIterator(); 503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (iterator.hasNext()) { 504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang eventWrapper = (EventWrapper) iterator.next(); 505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logDebug( 507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Processing " + eventWrapper + "nevents " 508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang + eventsToDeliver.size()); 509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang deliverEvent(eventWrapper); 512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (Exception e) { 513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logError( 515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "Unexpected exception caught while delivering event -- carrying on bravely", e); 516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } // end While 520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (sipStack.isLoggingEnabled()) { 522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!this.isStopped) { 523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang sipStack.getStackLogger().logFatalError("Event scanner exited abnormally"); 524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 530