Source Code Cross Referenced for TCPMessageChannel.java in  » 6.0-JDK-Modules » j2me » gov » nist » siplite » stack » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » gov.nist.siplite.stack 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:         * TCPMessageChannel.java
027:         *
028:         * Created on September 3, 2002, 3:47 PM
029:         */
030:
031:        package gov.nist.siplite.stack;
032:
033:        import gov.nist.siplite.header.*;
034:        import gov.nist.siplite.parser.*;
035:        import gov.nist.siplite.message.*;
036:        import gov.nist.siplite.SIPConstants;
037:        import gov.nist.core.*;
038:        import javax.microedition.io.*;
039:        import java.io.*;
040:
041:        import com.sun.midp.log.Logging;
042:        import com.sun.midp.log.LogChannels;
043:
044:        /**
045:         * Handle a TCP stream connection.
046:         *
047:         * @version 1.0
048:         */
049:        public class TCPMessageChannel extends MessageChannel implements 
050:                SIPMessageListener {
051:            /** Stream connection handle. */
052:            private SocketConnection mySock;
053:            /** Message parser handle. */
054:            private PipelinedMsgParser myParser;
055:            /** Input stream for client thread. */
056:            private InputStream myClientInputStream;
057:            /** Output stream for client thread. */
058:            private OutputStream myClientOutputStream;
059:            /** Current SIP message stack. */
060:            private SIPMessageStack stack;
061:            /** Local address. */
062:            private String myAddress;
063:            /** Local port number. */
064:            private int myPort;
065:            /** Remote address. */
066:            private String peerAddress;
067:            /** Remote port number. */
068:            private int peerPort;
069:            /** Remote transport type. */
070:            private String peerProtocol;
071:            /** Indicates channel is shutting down. */
072:            private boolean exitFlag;
073:            /** Number of transaction that uses this channel. */
074:            private int useCounter;
075:
076:            /**
077:             * Constructor - gets called from the SIPMessageStack class with a socket
078:             * on accepting a new client. All the processing of the message is
079:             * done here with the stack being freed up to handle new connections.
080:             * The sock input is the socket that is returned from the accept.
081:             * Global data that is shared by all threads is accessible in the Server
082:             * structure.
083:             * @param sock Socket from which to read and write messages. The socket
084:             * is already connected (was created as a result of an accept).
085:             * @param sipStack Ptr to SIP Stack
086:             * @param msgProcessor handler for TCP message communication
087:             */
088:            protected TCPMessageChannel(SocketConnection sock,
089:                    SIPMessageStack sipStack, TCPMessageProcessor msgProcessor)
090:                    throws IOException {
091:                mySock = sock;
092:                myClientInputStream = sock.openInputStream();
093:                myClientOutputStream = sock.openOutputStream();
094:                stack = sipStack;
095:                messageProcessor = msgProcessor;
096:                // peerAddress will be updated when 
097:                // first Request packet is received
098:                // see processMessage(...)
099:                peerAddress = sock.getAddress();
100:                peerPort = sock.getPort();
101:                myAddress = sock.getLocalAddress();
102:                myPort = sock.getLocalPort();
103:                start();
104:                incrementUseCounter();
105:            }
106:
107:            /**
108:             * Constructor - connects to the given inet address.
109:             * @param targetHostPort inet address to connect to.
110:             * @param sipStack is the sip stack from which we are created.
111:             * @param msgProcessor TCP message processor
112:             * @throws IOException if we cannot connect.
113:             */
114:            protected TCPMessageChannel(HostPort targetHostPort,
115:                    SIPMessageStack sipStack, TCPMessageProcessor msgProcessor)
116:                    throws IOException {
117:                stack = sipStack;
118:                messageProcessor = msgProcessor;
119:                myAddress = sipStack.getHostAddress();
120:                peerAddress = targetHostPort.getHost().getHostname();
121:                peerPort = targetHostPort.getPort();
122:                makeSocket(peerAddress, peerPort);
123:                start();
124:                incrementUseCounter();
125:            }
126:
127:            /**
128:             * Creates a socket connection.
129:             * @param host Host name
130:             * @param port Port number
131:             * @exception IOException if the socket can not be created.
132:             */
133:            private void makeSocket(String host, int port) throws IOException {
134:                if (host == null || host.length() == 0 || port < 0) {
135:                    throw new IOException("Invalid hostname or port number");
136:                }
137:
138:                String name = "//" + host + ":" + port;
139:
140:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
141:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
142:                            "Opening outbound socket connection :" + host + ":"
143:                                    + port);
144:                }
145:
146:                /*
147:                 * Original NIST method for opening the socket connection
148:                 * has been replaced by direct calls to instantiate the protocol 
149:                 * handler, in order to pass the security token for use of lower 
150:                 * level transport connection. 
151:                 * Original NIST sequence is :
152:                 *
153:                 * socket = (SocketConnection)Connector.open(name);
154:                 *
155:                 */
156:                com.sun.midp.io.j2me.socket.Protocol conn = new com.sun.midp.io.j2me.socket.Protocol();
157:                try {
158:                    mySock = (SocketConnection) conn.openPrim(stack
159:                            .getSecurityToken(), name);
160:                } catch (ConnectionNotFoundException ex) {
161:                    throw new IOException("Can't connect to " + name);
162:                }
163:                myClientInputStream = mySock.openInputStream();
164:                myClientOutputStream = mySock.openOutputStream();
165:            }
166:
167:            /**
168:             * Returns "true" as this is a reliable transport.
169:             * @return true if reliable stream transport
170:             */
171:            public boolean isReliable() {
172:                return true;
173:            }
174:
175:            /**
176:             * Closes the message channel.
177:             */
178:            synchronized public void close() {
179:                if (0 != useCounter) {
180:                    useCounter--;
181:                }
182:                if (0 == useCounter) {
183:                    exit();
184:                    if (null != messageProcessor) {
185:                        ((TCPMessageProcessor) messageProcessor)
186:                                .notifyClose(this );
187:                    }
188:                }
189:            }
190:
191:            /**
192:             * Closes the message channel regardless whether it is used or not.
193:             */
194:            synchronized protected void exit() {
195:                useCounter = 0;
196:                exitFlag = true;
197:                shutDownConnection();
198:                // allow gc to collect MP
199:                messageProcessor = null;
200:            }
201:
202:            /**
203:             * Gets my SIP Stack.
204:             * @return The SIP Stack for this message channel.
205:             */
206:            public SIPMessageStack getSIPStack() {
207:                return stack;
208:            }
209:
210:            /**
211:             * Gets the transport string.
212:             * @return "tcp" in this case.
213:             */
214:            public String getTransport() {
215:                return SIPConstants.TRANSPORT_TCP;
216:            }
217:
218:            /**
219:             * Gets the address of the client that sent the data to us.
220:             * @return Address of the client that sent us data
221:             * that resulted in this channel being
222:             * created.
223:             */
224:            public String getPeerAddress() {
225:                return peerAddress;
226:            }
227:
228:            /**
229:             * Sends message to whoever is connected to us.
230:             * Uses the topmost via address to send to.
231:             * @param msg is the message to send.
232:             */
233:            synchronized private void sendMessage(byte[] msg)
234:                    throws IOException {
235:                if (exitFlag) {
236:                    return;
237:                }
238:
239:                if (mySock == null) {
240:                    reConnect();
241:                }
242:
243:                myClientOutputStream.write(msg);
244:            }
245:
246:            /**
247:             * Returns a formatted message to the client.
248:             * We try to re-connect with the peer on the other end if possible.
249:             * @param sipMessage Message to send.
250:             * @throws IOException If there is an error sending the message
251:             */
252:            public void sendMessage(Message sipMessage) throws IOException {
253:                if (sipMessage == null) {
254:                    throw new NullPointerException("null arg!");
255:                }
256:
257:                byte[] msg = sipMessage.encodeAsBytes();
258:                long time = System.currentTimeMillis();
259:
260:                sendMessage(msg);
261:
262:                if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES)) {
263:                    logMessage(sipMessage, peerAddress, peerPort, time);
264:                }
265:            }
266:
267:            /**
268:             * Sends a message to a specified address.
269:             * @param message Pre-formatted message to send.
270:             * @param receiverAddress Address to send it to.
271:             * @param receiverPort Receiver port.
272:             * @throws IOException If there is a problem connecting or sending.
273:             */
274:            public void sendMessage(byte message[], String receiverAddress,
275:                    int receiverPort) throws IOException,
276:                    IllegalArgumentException {
277:                if (message == null || receiverAddress == null) {
278:                    throw new IllegalArgumentException("Null argument");
279:                }
280:
281:                if (!receiverAddress.equals(peerAddress)
282:                        || peerPort != receiverPort) {
283:                    throw new IOException(
284:                            "This channel is bound to different peer");
285:                }
286:
287:                sendMessage(message);
288:            }
289:
290:            /**
291:             * Exception processor for exceptions detected from the application.
292:             * @param ex The exception that was generated.
293:             */
294:            public void handleException(SIPServerException ex) {
295:                // Return a parse error message to the client on the other end
296:                // if he is still alive.
297:                int rc = ex.getRC();
298:                String msgString = ex.getMessage();
299:                if (rc != 0) {
300:                    // Do we have a valid Return code ? --
301:                    // in this case format the message.
302:                    Request request = (Request) ex.getSIPMessage();
303:                    Response response = request.createResponse(rc);
304:                    try {
305:                        sendMessage(response);
306:                    } catch (IOException ioex) {
307:                        if (Logging.REPORT_LEVEL <= Logging.ERROR) {
308:                            Logging.report(Logging.ERROR,
309:                                    LogChannels.LC_JSR180, ioex.getMessage());
310:                        }
311:                    }
312:                } else {
313:                    // Otherwise, message is already formatted --
314:                    // just return it
315:                    try {
316:                        sendMessage(msgString.getBytes());
317:                    } catch (IOException ioex) {
318:                        if (Logging.REPORT_LEVEL <= Logging.ERROR) {
319:                            Logging.report(Logging.ERROR,
320:                                    LogChannels.LC_JSR180, ioex.getMessage());
321:                        }
322:                    }
323:                }
324:            }
325:
326:            /**
327:             * Exception processor for exceptions detected from the parser. (This
328:             * is invoked by the parser when an error is detected).
329:             * @param ex parse exception detected by the parser.
330:             * @param sipMessage message that incurred the error.
331:             * @param hdrClass header parsing class
332:             * @param header header that caused the error.
333:             * @param message descriptive text for exception
334:             * @throws ParseException Thrown if we want to reject the message.
335:             */
336:            public void handleException(ParseException ex, Message sipMessage,
337:                    Class hdrClass, String header, String message)
338:                    throws ParseException {
339:
340:                if (Logging.REPORT_LEVEL <= Logging.ERROR) {
341:                    Logging.report(Logging.ERROR, LogChannels.LC_JSR180, ex
342:                            .getMessage());
343:                }
344:
345:                // Log the bad message for later reference.
346:                if (hdrClass.equals(FromHeader.clazz)
347:                        || hdrClass.equals(ToHeader.clazz)
348:                        || hdrClass.equals(CSeqHeader.clazz)
349:                        || hdrClass.equals(ViaHeader.clazz)
350:                        || hdrClass.equals(CallIdHeader.clazz)
351:                        || hdrClass.equals(RequestLine.clazz)
352:                        || hdrClass.equals(StatusLine.clazz)) {
353:                    stack.logBadMessage(message);
354:                    throw ex;
355:                } else {
356:                    sipMessage.addUnparsed(header);
357:                }
358:
359:            }
360:
361:            /**
362:             * Gets invoked by the parser as a callback on successful message
363:             * parsing (i.e. no parser errors).
364:             * @param sipMessage Mesage to process (this calls the application
365:             * for processing the message).
366:             */
367:            public void processMessage(Message sipMessage) {
368:                if (sipMessage.getFromHeader() == null
369:                        || sipMessage.getTo() == null
370:                        || sipMessage.getCallId() == null
371:                        || sipMessage.getCSeqHeader() == null
372:                        || sipMessage.getViaHeaders() == null) {
373:                    String badmsg = sipMessage.encode();
374:
375:                    if (Logging.REPORT_LEVEL <= Logging.ERROR) {
376:                        ServerLog.logMessage("bad message " + badmsg);
377:                        ServerLog.logMessage(">>> Dropped Bad Msg");
378:                    }
379:
380:                    stack.logBadMessage(badmsg);
381:
382:                    return;
383:                }
384:
385:                ViaList viaList = sipMessage.getViaHeaders();
386:
387:                // For a request
388:                // first via header tells where the message is coming from.
389:                // For response, this has already been recorded in the outgoing
390:                // message.
391:                long receptionTime = 0;
392:
393:                if (sipMessage instanceof  Request) {
394:                    ViaHeader v = (ViaHeader) viaList.first();
395:                    if (v.hasPort()) {
396:                        peerPort = v.getPort();
397:                    } else {
398:                        peerPort = SIPConstants.DEFAULT_NONTLS_PORT;
399:                    }
400:                    peerProtocol = v.getTransport();
401:
402:                    // System.out.println("receiver address = " + receiverAddress);
403:
404:                    // Foreach part of the request header, fetch it and process it
405:                    receptionTime = System.currentTimeMillis();
406:
407:                    // This is a request - process the request.
408:                    Request sipRequest = (Request) sipMessage;
409:
410:                    // Create a new sever side request processor for this
411:                    // message and let it handle the rest.
412:
413:                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
414:                        Logging.report(Logging.INFORMATION,
415:                                LogChannels.LC_JSR180,
416:                                "----Processing Message---");
417:                    }
418:
419:                    SIPServerRequestInterface sipServerRequest = stack
420:                            .newSIPServerRequest(sipRequest, this );
421:                    try {
422:                        sipServerRequest.processRequest(sipRequest, this );
423:
424:                        ServerLog.logMessage(sipMessage, sipRequest
425:                                .getViaHost()
426:                                + ":" + sipRequest.getViaPort(), stack
427:                                .getHostAddress()
428:                                + ":" + stack.getPort(this .getTransport()),
429:                                false, receptionTime);
430:
431:                    } catch (SIPServerException ex) {
432:                        ServerLog.logMessage(sipMessage, sipRequest
433:                                .getViaHost()
434:                                + ":" + sipRequest.getViaPort(), stack
435:                                .getHostAddress()
436:                                + ":" + stack.getPort(this .getTransport()), ex
437:                                .getMessage(), false, receptionTime);
438:                        handleException(ex);
439:                    }
440:                } else {
441:                    // This is a response message - process it.
442:                    Response sipResponse = (Response) sipMessage;
443:                    SIPServerResponseInterface sipServerResponse = stack
444:                            .newSIPServerResponse(sipResponse, this );
445:
446:                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
447:                        Logging
448:                                .report(Logging.INFORMATION,
449:                                        LogChannels.LC_JSR180,
450:                                        "got a response interface "
451:                                                + sipServerResponse);
452:                    }
453:
454:                    try {
455:                        sipServerResponse.processResponse(sipResponse, this );
456:                    } catch (SIPServerException ex) {
457:                        // An error occured processing the message -- just log it.
458:                        ServerLog.logMessage(sipMessage, getPeerAddress()
459:                                .toString()
460:                                + ":" + getPeerPort(), stack.getHostAddress()
461:                                + ":" + stack.getPort(this .getTransport()), ex
462:                                .getMessage(), false, receptionTime);
463:                        // Ignore errors while processing responses??
464:                    }
465:                }
466:            }
467:
468:            /**
469:             * This gets invoked when thread.start is called from the constructor.
470:             * Implements a message loop - reading the tcp connection and processing
471:             * messages until we are done or the other end has closed.
472:             */
473:            private void start() {
474:                // Create a pipelined message parser to read and parse
475:                // messages that we write out to him.
476:                myParser = new PipelinedMsgParser(this , myClientInputStream);
477:                // Enable the flag to parse message content.
478:                // Start running the parser thread.
479:                myParser.processInput();
480:
481:            }
482:
483:            /**
484:             * Increments the number of user of this channel.
485:             */
486:            synchronized protected void incrementUseCounter() {
487:                if (!exitFlag) {
488:                    useCounter++;
489:                }
490:            }
491:
492:            /**
493:             * Called when the pipelined parser cannot read input because the
494:             * other end closed the connection.
495:             */
496:            public void handleIOException() {
497:                if (!exitFlag) {
498:                    shutDownConnection();
499:                }
500:            }
501:
502:            /** 
503:             * Closes all input and output stream and socket.
504:             */
505:            synchronized private void shutDownConnection() {
506:                try {
507:                    if (null != myClientInputStream) {
508:                        myClientInputStream.close();
509:                    }
510:                } catch (IOException ioe) {
511:                    // intentionally ignored
512:                }
513:
514:                try {
515:                    if (null != myClientOutputStream) {
516:                        myClientOutputStream.close();
517:                    }
518:
519:                } catch (IOException ioe) {
520:                    // intentionally ignored
521:                }
522:
523:                try {
524:                    if (null != mySock) {
525:                        mySock.close();
526:                    }
527:                } catch (IOException ioe) {
528:                    // intentionally ignored
529:                }
530:                // null mySock indicates closed connection
531:                // see sendMessage()
532:                mySock = null;
533:            }
534:
535:            /**
536:             * Reconnect to the server.
537:             * @exception IOException if the connection can not be established
538:             */
539:            private void reConnect() throws IOException {
540:                shutDownConnection();
541:                makeSocket(peerAddress, peerPort);
542:                myParser = new PipelinedMsgParser(this , myClientInputStream);
543:                myParser.processInput();
544:            }
545:
546:            /**
547:             * Equals predicate.
548:             * @param other is the other object to compare ourselves to for equals
549:             * @return true if object matches
550:             */
551:            public boolean equals(Object other) {
552:                if (!this .getClass().equals(other.getClass()))
553:                    return false;
554:                else {
555:                    TCPMessageChannel that = (TCPMessageChannel) other;
556:                    if (this .mySock != that.mySock)
557:                        return false;
558:                    else
559:                        return true;
560:                }
561:            }
562:
563:            /**
564:             * Gets an identifying key. This key is used to cache the connection
565:             * and re-use it if necessary.
566:             * @return the identifying key
567:             */
568:            public String getKey() {
569:                return getKey(peerAddress, peerPort, SIPConstants.TRANSPORT_TCP);
570:            }
571:
572:            /**
573:             * Gets the host to assign to outgoing messages.
574:             * @return the host to assign to the via header.
575:             */
576:            public String getViaHost() {
577:                return myAddress;
578:            }
579:
580:            /**
581:             * Gets the port for outgoing messages sent from the channel.
582:             * @return the port to assign to the via header.
583:             */
584:            public int getViaPort() {
585:                return myPort;
586:            }
587:
588:            /**
589:             * Gets the port of the peer to whom we are sending messages.
590:             * @return the peer port.
591:             */
592:            public int getPeerPort() {
593:                return peerPort;
594:            }
595:
596:            /**
597:             * TCP Is not a secure protocol.
598:             * @return always false
599:             */
600:            public boolean isSecure() {
601:                return false;
602:            }
603:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.