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: */
027:
028: package gov.nist.siplite.stack;
029:
030: import java.io.*;
031: import java.util.*;
032:
033: import javax.microedition.io.*;
034:
035: import com.sun.midp.log.LogChannels;
036: import com.sun.midp.log.Logging;
037:
038: import gov.nist.core.*;
039: import gov.nist.siplite.SIPConstants;
040: import gov.nist.siplite.header.*;
041: import gov.nist.siplite.message.*;
042: import gov.nist.siplite.parser.*;
043:
044: /**
045: * This is the UDP Message handler that gets created when a UDP message
046: * needs to be processed. The message is processed by creating a String
047: * Message parser and invoking it on the message read from the UPD socket.
048: * The parsed structure is handed off via a SIP stack request for further
049: * processing. This stack structure isolates the message handling logic
050: * from the mechanics of sending and recieving messages (which could
051: * be either udp or tcp.
052: * Acknowledgement:
053: * Kim Kirby of Keyvoice suggested that duplicate checking should be added
054: * to the stack.
055: *
056: *@see gov.nist.siplite.parser.StringMsgParser
057: *@see gov.nist.siplite.stack.SIPServerRequestInterface
058: *@since v1.0
059: *
060: */
061: public class UDPMessageChannel extends MessageChannel implements
062: ParseExceptionListener, Runnable {
063: /** SIP Stack structure for this channel. */
064: protected SIPMessageStack stack;
065: /** Sender address (from getPeerName()) */
066: private String myAddress;
067: /** Local port number. */
068: private int myPort;
069: /** Remote host address. */
070: private String peerAddress;
071: /** Remote port number. */
072: private int peerPort;
073: /** Remote connection transport. */
074: private String peerProtocol;
075: /* Inbound message transport. */
076: // private String receiverProtocol;
077: /** Raw message contents. */
078: private byte[] msgBytes;
079: /** Input data length. */
080: private int packetLength;
081: /** Datagram connection for transport. */
082: private DatagramConnection datagramConnection;
083: /** Current serevr request message. */
084: private Datagram incomingPacket;
085: /** Pool of duplicate messages. */
086: protected static Hashtable duplicates;
087: /* Current SIP message. */
088: // private Message sipMessage;
089: /** Timestamp of current inbound message. */
090: private long receptionTime;
091:
092: /**
093: * Constructor - takes a datagram packet and a stack structure
094: * Extracts the address of the other from the datagram packet and
095: * stashes away the pointer to the passed stack structure.
096: * @param packet is the UDP Packet that contains the request.
097: * @param sipStack stack is the shared SipStack structure
098: * @param messageProcessor the UDP input message channel
099: */
100: public UDPMessageChannel(Datagram packet, SIPMessageStack sipStack,
101: MessageProcessor messageProcessor) {
102: incomingPacket = packet;
103: stack = sipStack;
104: // format: "protocol://address:port"
105: String address = packet.getAddress();
106:
107: try {
108: int firstColon = address.indexOf("://");
109: int secondColon = address.indexOf(":", firstColon + 1);
110: peerAddress = address
111: .substring(firstColon + 3, secondColon);
112:
113: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
114: Logging.report(Logging.INFORMATION,
115: LogChannels.LC_JSR180,
116: "DEBUG, UDPMessageChannel, UDPMessageChannel(), "
117: + "sender address: " + peerAddress);
118: }
119:
120: String portString = address.substring(secondColon + 1);
121: this .peerPort = Integer.parseInt(portString);
122:
123: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
124: Logging.report(Logging.INFORMATION,
125: LogChannels.LC_JSR180,
126: "DEBUG, UDPMessageChannel, UDPMessageChannel(), "
127: + "sender port: " + peerPort);
128: }
129: } catch (NumberFormatException e) {
130: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
131: Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
132: "DEBUG, UDPMessageChannel, UDPMessageChannel(), "
133: + "exception raised: " + e);
134: }
135:
136: this .peerPort = -1;
137: }
138:
139: packetLength = packet.getLength();
140:
141: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
142: Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
143: "DEBUG, UDPMessageChannel, UDPMessageChannel(), "
144: + "packet length: " + packetLength);
145: }
146:
147: byte[] bytes = packet.getData();
148: msgBytes = new byte[packetLength];
149: for (int i = 0; i < packetLength; i++) {
150: msgBytes[i] = bytes[i];
151: }
152:
153: String msgString = new String(msgBytes, 0, packetLength);
154:
155: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
156: Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
157: "DEBUG, UDPMessageChannel, UDPMessageChannel(), "
158: + " message received: " + msgString.trim());
159: }
160:
161: this .messageProcessor = messageProcessor;
162: // Supports only the single threaded model.
163: this .run();
164: }
165:
166: /**
167: * Constructor. We create one of these when we send out a message.
168: * @param targetAddr internet address of the place where we want to send
169: * messages.
170: * @param port target port (where we want to send the message).
171: * @param sipStack our SIP Stack.
172: * @param processor inbound message processor
173: */
174: public UDPMessageChannel(String targetAddr, int port,
175: SIPMessageStack sipStack, UDPMessageProcessor processor) {
176:
177: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
178: Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
179: "DEBUG, UDPMessageChannel, UDPMessageChannel(), "
180: + "Creating message channel on "
181: + targetAddr + "/" + port);
182: }
183:
184: this .peerPort = port;
185: this .peerAddress = targetAddr;
186: this .myPort = port;
187: this .myAddress = processor.getSIPStack().getHostAddress();
188: this .messageProcessor = processor;
189: this .peerProtocol = "UDP";
190: stack = sipStack;
191: }
192:
193: /**
194: * Runs method specified by runnnable.
195: */
196: public void run() {
197: Message sipMessage = null;
198: // Create a new string message parser to parse the list of messages.
199: // This is a huge performance hit -- need to optimize by pre-create
200: // parser when one is needed....
201: StringMsgParser myParser = new StringMsgParser();
202:
203: try {
204: this .receptionTime = System.currentTimeMillis();
205:
206: sipMessage = myParser.parseSIPMessage(msgBytes);
207: } catch (ParseException ex) {
208: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
209: Logging
210: .report(
211: Logging.ERROR,
212: LogChannels.LC_JSR180,
213: "DEBUG, UDPMessageChannel, run(), "
214: + "Rejecting message during parsing "
215: + "An exception has been raised: "
216: + ex);
217: }
218:
219: // ex.printStackTrace();
220: return;
221: }
222:
223: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
224: Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
225: "DEBUG, UDPMEssageChannel, run(), sipMessage parsed: "
226: + sipMessage.encode());
227: }
228:
229: if (sipMessage == null) {
230: return;
231: }
232:
233: ViaList viaList = sipMessage.getViaHeaders();
234: // For a request first via header tells where the message
235: // is coming from.
236: // For response, just get the port from the packet.
237: // format: address:port
238: String address = incomingPacket.getAddress();
239: try {
240: int firstColon = address.indexOf("://");
241: int secondColon = address.indexOf(":", firstColon + 1);
242: peerAddress = address
243: .substring(firstColon + 3, secondColon);
244:
245: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
246: Logging.report(Logging.INFORMATION,
247: LogChannels.LC_JSR180,
248: "DEBUG, UDPMessageChannel, run(), sender address: "
249: + peerAddress);
250: }
251:
252: String senderPortString = address
253: .substring(secondColon + 1);
254: peerPort = Integer.parseInt(senderPortString);
255:
256: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
257: Logging.report(Logging.INFORMATION,
258: LogChannels.LC_JSR180,
259: "DEBUG, UDPMessageChannel, run(), sender port: "
260: + peerPort);
261: }
262: } catch (NumberFormatException e) {
263: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
264: Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
265: "DEBUG, UDPMessageChannel, run(), "
266: + "exception raised: " + e);
267: }
268: // e.printStackTrace();
269: peerPort = -1;
270: }
271:
272: // Check for the required headers.
273: if (sipMessage.getFromHeader() == null
274: ||
275: // sipMessage.getFromHeader().getTag() == null ||
276: sipMessage.getTo() == null
277: || sipMessage.getCallId() == null
278: || sipMessage.getCSeqHeader() == null
279: || sipMessage.getViaHeaders() == null) {
280: String badmsg = new String(msgBytes);
281:
282: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
283: Logging.report(Logging.INFORMATION,
284: LogChannels.LC_JSR180, "bad message " + badmsg);
285: Logging.report(Logging.INFORMATION,
286: LogChannels.LC_JSR180, ">>> Dropped Bad Msg "
287: + "FromHeader = "
288: + sipMessage.getFromHeader()
289: + "ToHeader = " + sipMessage.getTo()
290: + "CallId = " + sipMessage.getCallId()
291: + "CSeqHeader = "
292: + sipMessage.getCSeqHeader() + "Via = "
293: + sipMessage.getViaHeaders());
294: }
295:
296: stack.logBadMessage(badmsg);
297: return;
298: }
299:
300: // For a request first via header tells where the message
301: // is coming from.
302: // For response, just get the port from the packet.
303: if (sipMessage instanceof Request) {
304: ViaHeader v = (ViaHeader) viaList.first();
305: if (v.hasPort()) {
306: if (sipMessage instanceof Request) {
307: this .peerPort = v.getPort();
308: }
309: } else
310: this .peerPort = SIPConstants.DEFAULT_NONTLS_PORT;
311: this .peerProtocol = v.getTransport();
312: Request sipRequest = (Request) sipMessage;
313: // This is a request - process it.
314: SIPServerRequestInterface sipServerRequest = stack
315: .newSIPServerRequest(sipRequest, this );
316: // Drop it if there is no request returned
317: if (sipServerRequest == null) {
318: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
319: Logging.report(Logging.INFORMATION,
320: LogChannels.LC_JSR180,
321: "Null request interface returned");
322: }
323: return;
324: }
325:
326: int stPort = -1;
327: try {
328: stPort = stack.getPort(this .getTransport());
329: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
330: Logging.report(Logging.INFORMATION,
331: LogChannels.LC_JSR180, "About to process "
332: + sipRequest.getFirstLine() + "/"
333: + sipServerRequest);
334: }
335:
336: sipServerRequest.processRequest(sipRequest, this );
337:
338: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
339: Logging.report(Logging.INFORMATION,
340: LogChannels.LC_JSR180, "Done processing "
341: + sipRequest.getFirstLine() + "/"
342: + sipServerRequest);
343: }
344:
345: // So far so good -- we will commit this message if
346: // all processing is OK.
347: if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) {
348: if (sipServerRequest.getProcessingInfo() == null) {
349: ServerLog.logMessage(sipMessage, sipRequest
350: .getViaHost()
351: + ":" + sipRequest.getViaPort(), stack
352: .getHostAddress()
353: + ":" + stPort, false, new Long(
354: receptionTime).toString());
355: } else {
356: ServerLog.logMessage(sipMessage, sipRequest
357: .getViaHost()
358: + ":" + sipRequest.getViaPort(), stack
359: .getHostAddress()
360: + ":" + stPort, sipServerRequest
361: .getProcessingInfo(), false, new Long(
362: receptionTime).toString());
363: }
364: }
365: } catch (Exception ex) {
366: if (ex instanceof SIPServerException) {
367: handleException((SIPServerException) ex);
368: }
369: }
370: } else {
371: // Handle a SIP Reply message.
372: Response sipResponse = (Response) sipMessage;
373: SIPServerResponseInterface sipServerResponse = stack
374: .newSIPServerResponse(sipResponse, this );
375: try {
376: if (sipServerResponse != null) {
377: sipServerResponse
378: .processResponse(sipResponse, this );
379: // Normal processing of message.
380: } else {
381: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
382: Logging.report(Logging.INFORMATION,
383: LogChannels.LC_JSR180,
384: "null sipServerResponse!");
385: }
386: }
387: } catch (Exception ex) {
388: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
389: Logging.report(Logging.INFORMATION,
390: LogChannels.LC_JSR180, ">>>>>Message = "
391: + new String(msgBytes));
392: }
393:
394: if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) {
395: this .logResponse(sipResponse, receptionTime, ex
396: .getMessage()
397: + "-- Dropped!");
398: }
399:
400: ServerLog.logException(ex);
401: }
402: }
403: }
404:
405: /**
406: * Returns a reply from a pre-constructed reply. This sends the message
407: * back to the entity who caused us to create this channel in the
408: * first place.
409: * @param sipMessage Message string to send.
410: * @throws IOException If there is a problem with sending the
411: * message.
412: */
413: public void sendMessage(Message sipMessage) throws IOException {
414: byte[] msg = sipMessage.encodeAsBytes();
415: sendMessage(msg, peerAddress, peerPort, peerProtocol);
416: }
417:
418: /**
419: * Sends a message to a specified receiver address.
420: * @param msg message string to send.
421: * @param receiverAddress Address of the place to send it to.
422: * @param receiverPort the port to send it to.
423: * @throws IOException If there is trouble sending this message.
424: */
425: protected void sendMessage(byte[] msg, String receiverAddress,
426: int receiverPort) throws IOException {
427: // msg += "\r\n\r\n";
428: // Via is not included in the request so silently drop the reply.
429: if (receiverPort == -1) {
430: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
431: Logging
432: .report(
433: Logging.INFORMATION,
434: LogChannels.LC_JSR180,
435: "DEBUG, UDPMessageChannel, sendMessage(), "
436: + "The message is not sent: the receiverPort=-1");
437: }
438: throw new IOException("Receiver port not set ");
439: }
440: try {
441:
442: /*
443: * Original NIST method for opening the datagram connection
444: * has been replaced by direct calls to instantiate the protocol
445: * handler, in order to pass the security token for use of lower
446: * level transport connection.
447: * Original NIST sequence is :
448: *
449: * //format: "datagram://address:port"
450: * String url = "datagram://"+peerAddress+":"+peerPort;
451: * this.datagramConnection =
452: * (DatagramConnection)Connector.open(url);
453: *
454: */
455:
456: String url = "//" + peerAddress + ":" + peerPort;
457:
458: com.sun.midp.io.j2me.datagram.Protocol conn = new com.sun.midp.io.j2me.datagram.Protocol();
459:
460: this .datagramConnection = (DatagramConnection) conn
461: .openPrim(stack.getSecurityToken(), url,
462: Connector.WRITE, true);
463:
464: // timeouts are ignored for datagrams
465:
466: Datagram reply = datagramConnection.newDatagram(msg,
467: msg.length);
468:
469: datagramConnection.send(reply);
470: String msgString = new String(msg, 0, msg.length);
471:
472: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
473: Logging.report(Logging.INFORMATION,
474: LogChannels.LC_JSR180,
475: "DEBUG, UDPMessageChannel, sendMessage(), "
476: + "Datagram sent on datagram:" + url
477: + ", message sent:\n"
478: + msgString.trim());
479: }
480:
481: datagramConnection.close();
482: } catch (IOException ex) {
483: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
484: Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
485: "toto");
486: Logging
487: .report(
488: Logging.ERROR,
489: LogChannels.LC_JSR180,
490: "DEBUG, UDPMessageChannel, sendMessage(), "
491: + "The message is not sent: exception raised: "
492: + ex);
493: }
494: }
495: }
496:
497: /**
498: * Sends a message to a specified receiver address.
499: * @param msg message string to send.
500: * @param receiverAddress Address of the place to send it to.
501: * @param receiverPort the port to send it to.
502: * @param receiverProtocol protocol to use to send.
503: * @throws IOException If there is trouble sending this message.
504: */
505: protected void sendMessage(byte[] msg, String receiverAddress,
506: int receiverPort, String receiverProtocol)
507: throws IOException {
508: // msg += "\r\n\r\n";
509: // Via is not included in the request so silently drop the reply.
510: if (receiverPort == -1) {
511: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
512: Logging.report(Logging.INFORMATION,
513: LogChannels.LC_JSR180,
514: "DEBUG, UDPMessageChannel, sendMessage(), "
515: + "The message is not sent: "
516: + "the receiverPort=-1");
517: }
518:
519: throw new IOException("Receiver port not set ");
520: }
521:
522: if (Utils.compareToIgnoreCase(receiverProtocol, "UDP") == 0) {
523: try {
524: /*
525: * Original NIST method for opening the datagram connection
526: * has been replaced by direct calls to instantiate the
527: * protocol handler, in order to pass the security token
528: * for use of lower level transport connection.
529: * Original NIST sequence is :
530: *
531: * String url = "datagram://"
532: * + receiverAddress + ":" + receiverPort;
533: * // format: "datagram://address:port"
534: * datagramConnection =
535: * (DatagramConnection)Connector.open(url);
536: *
537: */
538:
539: String url = "//" + receiverAddress + ":"
540: + receiverPort;
541: com.sun.midp.io.j2me.datagram.Protocol conn = new com.sun.midp.io.j2me.datagram.Protocol();
542:
543: datagramConnection = (DatagramConnection) conn
544: .openPrim(stack.getSecurityToken(), url,
545: Connector.WRITE, true);
546: // timeouts are ignored
547: Datagram datagram = datagramConnection.newDatagram(msg,
548: msg.length);
549: datagramConnection.send(datagram);
550: String msgString = new String(msg, 0, msg.length);
551:
552: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
553: Logging.report(Logging.INFORMATION,
554: LogChannels.LC_JSR180,
555: "DEBUG, UDPMessageChannel, sendMessage(), "
556: + " Datagram sent on datagram: "
557: + url + ", message sent:\n"
558: + msgString.trim());
559: }
560:
561: datagramConnection.close();
562: } catch (IOException ex) {
563: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
564: Logging
565: .report(
566: Logging.ERROR,
567: LogChannels.LC_JSR180,
568: "DEBUG, UDPMessageChannel, sendMessage(), "
569: + "The message is not sent: exception raised:"
570: + ex);
571:
572: }
573: }
574: } else {
575: // TCP is not supported
576: throw new IOException("Unsupported protocol");
577: }
578: }
579:
580: /**
581: * Gets the stack pointer.
582: * @return The sip stack for this channel.
583: */
584: public SIPMessageStack getSIPStack() {
585: return stack;
586: }
587:
588: /**
589: * Returns a transport string.
590: * @return the string "udp" in this case.
591: */
592: public String getTransport() {
593: return "udp";
594: }
595:
596: /**
597: * Gets the stack address for the stack that received this message.
598: * @return The stack address for our stack.
599: */
600: public String getHost() {
601: return stack.stackAddress;
602: }
603:
604: /**
605: * Gets the port.
606: * @return Our port (on which we are getting datagram
607: * packets).
608: */
609: public int getPort() {
610: return this .myPort;
611: }
612:
613: /**
614: * Handles an exception - construct a sip reply and send it back to the
615: * caller.
616: * @param ex The exception thrown at us by our
617: * application.
618: */
619: public void handleException(SIPServerException ex) {
620: // Return a parse error message to the client on the other end
621: // if he is still alive.
622: // ex.printStackTrace();
623: int rc = ex.getRC();
624: Request request = (Request) ex.getSIPMessage();
625: Response response;
626: String msgString = ex.getMessage();
627: if (rc != 0) {
628: response = request.createResponse(rc, msgString);
629: // messageFormatter.newResponse(rc,request,msgString);
630: try {
631: sendMessage(response);
632: } catch (IOException ioex) {
633: ServerLog.logException(ioex);
634: }
635: } else {
636: // Assume that the message has already been formatted.
637: try {
638: sendMessage(msgString);
639: } catch (IOException ioex) {
640: ServerLog.logException(ioex);
641: }
642: }
643: }
644:
645: /**
646: * Compares two UDP Message channels for equality.
647: * @param other The other message channel with which to compare oursleves.
648: * @return true if the objects match
649: */
650: public boolean equals(Object other) {
651: if (other == null)
652: return false;
653: boolean retval;
654: if (!this .getClass().equals(other.getClass())) {
655: retval = false;
656: } else {
657: UDPMessageChannel that = (UDPMessageChannel) other;
658: retval = this .peerAddress.equals(that.peerAddress);
659: }
660: return retval;
661: }
662:
663: /**
664: * Gets the key.
665: * @return the key
666: */
667: public String getKey() {
668: return myAddress + ":" + myPort + "/UDP";
669: }
670:
671: /**
672: * Sends the message.
673: * @param msg the message to be processed.
674: * @exception IOException if the send can not be processed
675: */
676: private void sendMessage(String msg) throws IOException {
677: sendMessage(msg.getBytes(), peerAddress, peerPort, peerProtocol);
678: }
679:
680: /**
681: * Sends the message.
682: * @param msg the message to be processed.
683: * @exception IOException if the send can not be processed
684: */
685: private void sendMessage(byte[] msg) throws IOException {
686: sendMessage(msg, peerAddress, peerPort, peerProtocol);
687: }
688:
689: /**
690: * Gets the logical originator of the message (from the top via header).
691: * @return topmost via header sentby field
692: */
693: public String getViaHost() {
694: return this .myAddress;
695: }
696:
697: /**
698: * Gets the logical port of the message orginator (from the top via hdr).
699: * @return the via port from the topmost via header.
700: */
701: public int getViaPort() {
702: return this .myPort;
703: }
704:
705: /**
706: * Checks if the transport is reliable
707: * @return always false
708: */
709: public boolean isReliable() {
710: return false;
711: }
712:
713: /**
714: * Closes the message channel.
715: */
716: public void close() {
717: }
718:
719: /**
720: * Gets the peer address of the machine that sent us this message.
721: * @return a string contianing the ip address or host name of the sender
722: * of the message.
723: */
724: public String getPeerAddress() {
725: return this .peerAddress;
726: }
727:
728: /**
729: * Gets the sender port (the port of the other end that sent me
730: * the message).
731: * @return the remote port number
732: */
733: public int getPeerPort() {
734: return this .peerPort;
735: }
736:
737: /**
738: * Returns true if this is a secure channel.
739: * @return always false
740: */
741: public boolean isSecure() {
742:
743: return false;
744: }
745:
746: /**
747: * This gets called from the parser when a parse error is generated.
748: * The handler is supposed to introspect on the error class and
749: * header name to handle the error appropriately. The error can
750: * be handled by :
751: * <ul>
752: * <li>1. Re-throwing an exception and aborting the parse.
753: * <li>2. Ignoring the header (attach the unparseable header to
754: * the Message being parsed).
755: * <li>3. Re-Parsing the bad header and adding it to the sipMessage
756: * </ul>
757: *
758: * @param ex parse exception being processed.
759: * @param sipMessage sip message being processed.
760: * @param hdrClass header parsing class
761: * @param headerText header/RL/SL text being parsed.
762: * @param messageText message where this header was detected.
763: */
764: public void handleException(ParseException ex, Message sipMessage,
765: Class hdrClass, String headerText, String messageText)
766: throws ParseException {
767:
768: if (Logging.REPORT_LEVEL <= Logging.ERROR) {
769: Logging.report(Logging.ERROR, LogChannels.LC_JSR180, ex
770: .getMessage());
771: }
772:
773: // Log the bad message for later reference.
774: if (hdrClass.equals(FromHeader.clazz)
775: || hdrClass.equals(ToHeader.clazz)
776: || hdrClass.equals(CSeqHeader.clazz)
777: || hdrClass.equals(ViaHeader.clazz)
778: || hdrClass.equals(CallIdHeader.clazz)
779: || hdrClass.equals(RequestLine.clazz)
780: || hdrClass.equals(StatusLine.clazz)) {
781: stack.logBadMessage(messageText);
782: throw ex;
783: } else {
784: sipMessage.addUnparsed(headerText);
785: }
786: }
787: }
|