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: package gov.nist.siplite.stack;
026:
027: import javax.microedition.io.*;
028: import gov.nist.core.*;
029: import java.io.IOException;
030: import java.io.InterruptedIOException;
031:
032: import com.sun.midp.log.Logging;
033: import com.sun.midp.log.LogChannels;
034:
035: /**
036: * Sit in a loop and handle incoming udp datagram messages. For each Datagram
037: * packet, a new UDPMessageChannel is created. (Each UDP message is processed
038: * in its own thread).
039: */
040: public class UDPMessageProcessor extends MessageProcessor implements
041: Runnable {
042: /** Flag indicating the mesage processor is already running. */
043: private boolean running;
044: /** Max datagram size. */
045: protected static final int MAX_DATAGRAM_SIZE = 1500;
046: /** Our stack (that created us). */
047: private SIPMessageStack sipStack;
048: /** Current datagram connection handle. */
049: private DatagramConnection dc = null;
050: /** Inbound message port number. */
051: int port;
052: /** Message processor thread. */
053: private Thread thread;
054:
055: /**
056: * Constructor with initial stack and port number.
057: * @param sipStack pointer to the stack.
058: * @param port for incoming messages
059: */
060: protected UDPMessageProcessor(SIPMessageStack sipStack, int port) {
061: this .sipStack = sipStack;
062: this .port = port;
063: }
064:
065: /**
066: * Starts our processor thread.
067: */
068: synchronized public void start() {
069: /*
070: * Creating datagram connection.
071: */
072: // Create a new datagram socket.
073: /*
074: * Original NIST method for opening the datagram connection
075: * has been replaced by direct calls to instantiate the protocol
076: * handler, in order to pass the security token for use of lower
077: * level transport connection.
078: * Original NIST sequence is :
079: *
080: * dc =
081: * (DatagramConnection)Connector.open("datagram://:"+
082: * sipStack.getPort("udp"));
083: *
084: */
085:
086: if (dc != null) {
087: // the mesage processor is already running
088: return;
089: }
090:
091: com.sun.midp.io.j2me.datagram.Protocol conn = new com.sun.midp.io.j2me.datagram.Protocol();
092:
093: try {
094: // It's incorrect to use sipStack.getPort() to get the port
095: // for listening, because if multiple ports are enabled for
096: // the same transport then this function returns the first one.
097: // So the member 'port' is used.
098: dc = (DatagramConnection) conn.openPrim(sipStack
099: .getSecurityToken(), "//:" + port,
100: Connector.READ_WRITE, true);
101: // timeouts are ignored
102:
103: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
104: Logging.report(Logging.INFORMATION,
105: LogChannels.LC_JSR180,
106: "UDPMessageProcessor, start(), datagram server"
107: + "listener: datagram://:" + port);
108: Logging.report(Logging.INFORMATION,
109: LogChannels.LC_JSR180,
110: "UDPMessageProcessor, start(), datagram size:"
111: + MAX_DATAGRAM_SIZE);
112: }
113: } catch (IOException ioe) {
114: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
115: Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
116: "UDPMessageProcessor, start(), can't"
117: + "create DatagramConnection: "
118: + ioe.getMessage());
119: }
120: }
121:
122: /*
123: * Start a thread to receive data on datagramconnection, dc
124: */
125: if (dc != null) {
126: thread = new Thread(this );
127: thread.start();
128: }
129: }
130:
131: /**
132: * Stops the message processor.
133: */
134: synchronized public void stop() {
135: try {
136: if (dc != null) {
137: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
138: Logging.report(Logging.INFORMATION,
139: LogChannels.LC_JSR180,
140: "UDPMessageProcessor, stop(), "
141: + "The stack is going to stop!");
142: }
143: // interrupt run() infinite loop
144: dc.close();
145: if (thread != null && thread.isAlive()) {
146: try {
147: thread.join();
148: } catch (InterruptedException exc) {
149: // intentionally ignored
150: }
151: thread = null;
152: }
153: // enable start of the processor
154: dc = null;
155: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
156: Logging
157: .report(Logging.INFORMATION,
158: LogChannels.LC_JSR180,
159: "UDPMessageProcessor, stop(), The stack is stopped");
160: }
161: }
162: } catch (IOException ex) {
163: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
164: Logging
165: .report(Logging.INFORMATION,
166: LogChannels.LC_JSR180,
167: "UDPMessageProcessor, stop(), exception raised:");
168: }
169: }
170: }
171:
172: /**
173: * Thread main routine.
174: */
175: public void run() {
176: try {
177: // infinite loop will be broken by stop() function
178: while (true) {
179: Datagram datagram = dc.newDatagram(MAX_DATAGRAM_SIZE);
180:
181: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
182: Logging
183: .report(Logging.INFORMATION,
184: LogChannels.LC_JSR180,
185: "SYSTEM, UDPMessageProcessor, run(), listening!");
186: }
187:
188: dc.receive(datagram);
189:
190: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
191: Logging.report(Logging.INFORMATION,
192: LogChannels.LC_JSR180,
193: "SYSTEM, UDPMessageProcessor, run(), "
194: + "packet revceived!");
195: }
196:
197: // Create synchronous message handler
198: // for this message (UDPMessageChannel.run() will be used
199: // inside UDPMessageChannel constructor)
200: // IMPL_NOTE: execute UDPMessageChannel.run directly
201: // or create a new thread
202: UDPMessageChannel udpMessageChannel = new UDPMessageChannel(
203: datagram, sipStack, this );
204: }
205: } catch (IOException ex) {
206: // intentionally ignored.
207: // can't create new datagram or
208: // recieve exception
209: }
210: }
211:
212: /**
213: * Returns the transport string.
214: * @return the transport string
215: */
216: public String getTransport() {
217: return "udp";
218: }
219:
220: /**
221: * Gets the port from which the UDPMessageProcessor is reading messages
222: * @return Port from which the udp message processor is
223: * reading messages.
224: */
225: public int getPort() {
226: return this .port;
227: }
228:
229: /**
230: * Returns the stack.
231: * @return my sip stack.
232: */
233: public SIPMessageStack getSipStack() {
234: return sipStack;
235: }
236:
237: /**
238: * Create and return new TCPMessageChannel for the given host/port.
239: * @param targetHostPort target host and port number
240: * @return the new message channel
241: */
242: public MessageChannel createMessageChannel(HostPort targetHostPort) {
243: return new UDPMessageChannel(targetHostPort.getHost()
244: .getHostname(), targetHostPort.getPort(), sipStack,
245: this );
246: }
247:
248: /**
249: * Create and return new TCPMessageChannel for the given host/port.
250: * @param host target host
251: * @param port target port
252: * @return the new message channel
253: */
254: public MessageChannel createMessageChannel(String host, int port) {
255: return new UDPMessageChannel(host, port, sipStack, this );
256: }
257:
258: /**
259: * UDP is not a secure protocol.
260: * @return always false
261: */
262: public boolean isSecure() {
263: return false;
264: }
265:
266: /**
267: * Gets the SIP Stack.
268: * @return the sip stack.
269: */
270: public SIPMessageStack getSIPStack() {
271: return sipStack;
272: }
273:
274: }
|