001: /*
002: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
003: * Reserved. Use is subject to license terms.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: package gov.nist.siplite;
027:
028: import gov.nist.siplite.message.Request;
029: import gov.nist.siplite.message.Response;
030: import gov.nist.siplite.stack.ClientTransaction;
031: import gov.nist.siplite.stack.Dialog;
032: import gov.nist.siplite.stack.ServerTransaction;
033: import gov.nist.siplite.stack.Transaction;
034:
035: import java.io.IOException;
036: import java.util.Enumeration;
037: import java.util.Vector;
038:
039: import com.sun.midp.log.Logging;
040: import com.sun.midp.log.LogChannels;
041:
042: /**
043: * Event scanner.
044: */
045: public class EventScanner implements Runnable {
046: /** Current SIP stack context. */
047: private SipStack sipStack;
048: /** Vector of pending events. */
049: private Vector pendingEvents;
050: /** Current SIP event listener. */
051: private SipListener sipListener;
052: /** Flag to indicate if event processing is stopped. */
053: private boolean isStopped;
054:
055: /**
056: * Constructor.
057: * @param sipStack the current transaction context
058: */
059: public EventScanner(SipStack sipStack) {
060: this .sipStack = sipStack;
061: this .pendingEvents = new Vector();
062: }
063:
064: /**
065: * Starts the scanning for events.
066: */
067: public void start() {
068: Thread myThread = new Thread(this );
069: myThread.setPriority(Thread.MAX_PRIORITY);
070: myThread.start();
071: }
072:
073: /**
074: * Stops the scanning for events.
075: */
076: public void stop() {
077: synchronized (this .pendingEvents) {
078: this .isStopped = true;
079: this .pendingEvents.notify();
080: }
081: }
082:
083: /**
084: * Adds a new event to be processed.
085: * @param eventWrapper the event filter handler to be added
086: */
087: public void addEvent(EventWrapper eventWrapper) {
088: synchronized (pendingEvents) {
089: pendingEvents.addElement(eventWrapper);
090: pendingEvents.notify();
091: }
092: }
093:
094: /**
095: * Starts the scanner procesing.
096: */
097: public void run() {
098: while (true) {
099: SipEvent sipEvent = null;
100: EventWrapper eventWrapper = null;
101:
102: synchronized (this .pendingEvents) {
103: if (pendingEvents.isEmpty()) {
104: try {
105: pendingEvents.wait();
106: } catch (InterruptedException ex) {
107: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
108: Logging.report(Logging.INFORMATION,
109: LogChannels.LC_JSR180,
110: "Interrupted!");
111: }
112: continue;
113: }
114: }
115:
116: if (this .isStopped) {
117: return;
118: }
119:
120: SipListener sipListener = sipStack.getSipListener();
121: Enumeration iterator = pendingEvents.elements();
122:
123: while (iterator.hasMoreElements()) {
124: eventWrapper = (EventWrapper) iterator
125: .nextElement();
126: sipEvent = eventWrapper.sipEvent;
127:
128: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
129: Logging.report(Logging.INFORMATION,
130: LogChannels.LC_JSR180, "Processing "
131: + sipEvent + "nevents "
132: + pendingEvents.size());
133: }
134:
135: try {
136: if (sipEvent instanceof RequestEvent) {
137: // Check if this request has already created a
138: // transaction
139: Request sipRequest = (Request) ((RequestEvent) sipEvent)
140: .getRequest();
141: // Check if this request has already created a
142: // transaction. If this is a dialog creating
143: // method for which a server transaction
144: // already exists or a method which is not
145: // dialog creating and not within an existing
146: // dialog (special handling for cancel) then
147: // check to see if the listener already
148: // created a transaction to handle this
149: // request and discard the duplicate request
150: // if a transaction already exists. If the
151: // listener chose to handle the request
152: // statelessly, then the listener will see the
153: // retransmission. Note that in both of these
154: // two cases, JAIN SIP will allow you to
155: // handle the request statefully or
156: // statelessly. An example of the latter case
157: // is REGISTER and an example of the former
158: // case is INVITE.
159:
160: /*
161: * The transaction was added to the list
162: * in SIPTransactionStack, so it is not the right
163: * place to check if the transaction already exists.
164: *
165: * IMPL_NOTE: remove the following block of code after
166: * ensuring that it doesn't break anything.
167: */
168:
169: /*
170: if (sipStack.
171: isDialogCreated(sipRequest.getMethod())) {
172: SipProvider sipProvider =
173: (SipProvider)sipEvent.getSource();
174: sipProvider.currentTransaction =
175: (ServerTransaction)
176: eventWrapper.transaction;
177: ServerTransaction tr = (ServerTransaction)
178: sipStack.findTransaction(sipRequest, true);
179: Dialog dialog = sipStack.getDialog
180: (sipRequest.getDialogId(true));
181:
182: if (tr != null && !tr.passToListener()) {
183: if (Logging.REPORT_LEVEL <=
184: Logging.INFORMATION) {
185: Logging.report(Logging.INFORMATION,
186: LogChannels.LC_JSR180,
187: "transaction already exists!");
188: }
189: continue;
190: }
191: } else if (!sipRequest.getMethod()
192: .equals(Request.CANCEL) &&
193: sipStack.getDialog(sipRequest
194: .getDialogId(true))
195: == null) {
196: // not dialog creating and not a cancel.
197: // transaction already processed this message.
198: Transaction tr = sipStack
199: .findTransaction(sipRequest,
200: true);
201: //
202: // Should this be allowed?
203: // SipProvider sipProvider =
204: // (SipProvider) sipEvent.getSource();
205: // sipProvider.currentTransaction =
206: // (ServerTransaction) eventWrapper.transaction;
207: // If transaction already exists bail.
208: if (tr != null) {
209: if (Logging.REPORT_LEVEL <=
210: Logging.INFORMATION) {
211: Logging.report(Logging.INFORMATION,
212: LogChannels.LC_JSR180,
213: "transaction already exists!");
214: }
215: continue;
216: }
217: }
218: */
219:
220: // Processing incoming CANCEL.
221: if (sipRequest.getMethod().equals(
222: Request.CANCEL)) {
223: Transaction tr = sipStack
224: .findTransaction(sipRequest,
225: true);
226: if (tr != null
227: && tr.getState() == Transaction.TERMINATED_STATE) {
228: // If transaction already exists but it is
229: // too late to cancel the transaction then
230: // just respond OK to the CANCEL and bail.
231: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
232: Logging
233: .report(
234: Logging.INFORMATION,
235: LogChannels.LC_JSR180,
236: "Too late to cancel Transaction");
237: }
238:
239: // send OK and just ignore the CANCEL.
240: try {
241: tr
242: .sendMessage(sipRequest
243: .createResponse(Response.OK));
244: } catch (IOException ex) {
245: // Ignore?
246: }
247: continue;
248: }
249: }
250:
251: sipListener
252: .processRequest((RequestEvent) sipEvent);
253: } else if (sipEvent instanceof ResponseEvent) {
254: sipListener
255: .processResponse((ResponseEvent) sipEvent);
256: ClientTransaction ct = ((ResponseEvent) sipEvent)
257: .getClientTransaction();
258: ct.clearEventPending();
259: } else if (sipEvent instanceof TimeoutEvent) {
260: sipListener
261: .processTimeout((TimeoutEvent) sipEvent);
262: // Mark that Timeout event has been processed
263: if (eventWrapper.transaction != null) {
264: if (eventWrapper.transaction instanceof ClientTransaction) {
265: ((ClientTransaction) eventWrapper.transaction)
266: .clearEventPending();
267: }
268: }
269: } else {
270: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
271: Logging.report(Logging.INFORMATION,
272: LogChannels.LC_JSR180,
273: "bad event");
274: }
275: }
276: } catch (Throwable exc) { // ignore
277: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
278: Logging.report(Logging.INFORMATION,
279: LogChannels.LC_JSR180,
280: "Uncaught exception ");
281: }
282: }
283: }
284:
285: pendingEvents.removeAllElements();
286: } // end of Synchronized block
287: } // end While
288: }
289:
290: }
|