Source Code Cross Referenced for ClientTransaction.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:        package gov.nist.siplite.stack;
026:
027:        import gov.nist.siplite.message.*;
028:        import gov.nist.siplite.header.*;
029:        import gov.nist.siplite.*;
030:        import gov.nist.siplite.address.*;
031:        import gov.nist.core.*;
032:        import java.util.*;
033:
034:        import java.io.IOException;
035:        import javax.microedition.sip.SipException;
036:
037:        import com.sun.midp.log.Logging;
038:        import com.sun.midp.log.LogChannels;
039:
040:        /**
041:         * Represents a client transaction.
042:         *
043:         * @version JAIN-SIP-1.1
044:         *
045:         * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
046:         *
047:         * <pre>
048:         *
049:         * Implements the following state machines. (FromHeader RFC 3261)
050:         *
051:         * |INVITE from TU
052:         * Timer A fires |INVITE sent
053:         * Reset A, V Timer B fires
054:         * INVITE sent +-----------+ or Transport Err.
055:         * +---------| |---------------+inform TU
056:         * | | Calling | |
057:         * +-------->| |-------------->|
058:         * +-----------+ 2xx |
059:         * | | 2xx to TU |
060:         * | |1xx |
061:         * 300-699 +---------------+ |1xx to TU |
062:         * ACK sent | | |
063:         * resp. to TU | 1xx V |
064:         * | 1xx to TU -----------+ |
065:         * | +---------| | |
066:         * | | |Proceeding |-------------->|
067:         * | +-------->| | 2xx |
068:         * | +-----------+ 2xx to TU |
069:         * | 300-699 | |
070:         * | ACK sent, | |
071:         * | resp. to TU| |
072:         * | | | NOTE:
073:         * | 300-699 V |
074:         * | ACK sent +-----------+Transport Err. | transitions
075:         * | +---------| |Inform TU | labeled with
076:         * | | | Completed |-------------->| the event
077:         * | +-------->| | | over the action
078:         * | +-----------+ | to take
079:         * | ^ | |
080:         * | | | Timer D fires |
081:         * +--------------+ | - |
082:         * | |
083:         * V |
084:         * +-----------+ |
085:         * | | |
086:         * | Terminated|<--------------+
087:         * | |
088:         * +-----------+
089:         *
090:         * Figure 5: INVITE client transaction
091:         *
092:         *
093:         * |Request from TU
094:         * |send request
095:         * Timer E V
096:         * send request +-----------+
097:         * +---------| |-------------------+
098:         * | | Trying | Timer F |
099:         * +-------->| | or Transport Err.|
100:         * +-----------+ inform TU |
101:         * 200-699 | | |
102:         * resp. to TU | |1xx |
103:         * +---------------+ |resp. to TU |
104:         * | | |
105:         * | Timer E V Timer F |
106:         * | send req +-----------+ or Transport Err. |
107:         * | +---------| | inform TU |
108:         * | | |Proceeding |------------------>|
109:         * | +-------->| |-----+ |
110:         * | +-----------+ |1xx |
111:         * | | ^ |resp to TU |
112:         * | 200-699 | +--------+ |
113:         * | resp. to TU | |
114:         * | | |
115:         * | V |
116:         * | +-----------+ |
117:         * | | | |
118:         * | | Completed | |
119:         * | | | |
120:         * | +-----------+ |
121:         * | ^ | |
122:         * | | | Timer K |
123:         * +--------------+ | - |
124:         * | |
125:         * V |
126:         * NOTE: +-----------+ |
127:         * | | |
128:         * transitions | Terminated|<------------------+
129:         * labeled with | |
130:         * the event +-----------+
131:         * over the action
132:         * to take
133:         *
134:         * Figure 6: non-INVITE client transaction
135:         * </pre>
136:         */
137:        public class ClientTransaction extends Transaction implements 
138:                SIPServerResponseInterface {
139:            /** Last request. */
140:            private Request lastRequest;
141:            /** Flag indicating events are pending. */
142:            private boolean eventPending;
143:            /** Via port number. */
144:            private int viaPort;
145:            /** Via host. */
146:            private String viaHost;
147:            /** Real ResponseInterface to pass messages to. */
148:            private SIPServerResponseInterface respondTo;
149:
150:            /**
151:             * Creates a new client transaction.
152:             *
153:             * @param newSIPMessageStack Transaction stack this transaction
154:             * belongs to.
155:             * @param newChannelToHeaderUse Channel to encapsulate.
156:             */
157:            protected ClientTransaction(SIPTransactionStack newSIPMessageStack,
158:                    MessageChannel newChannelToHeaderUse) {
159:                super (newSIPMessageStack, newChannelToHeaderUse);
160:                setBranch(SIPUtils.generateBranchId());
161:
162:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
163:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
164:                            "Creating clientTransaction " + this );
165:                    // new Exception().printStackTrace();
166:                }
167:            }
168:
169:            /**
170:             * Sets the real ResponseInterface this transaction encapsulates.
171:             *
172:             * @param newRespondToHeader ResponseInterface to send messages to.
173:             */
174:            public void setResponseInterface(
175:                    SIPServerResponseInterface newRespondToHeader) {
176:                respondTo = newRespondToHeader;
177:            }
178:
179:            /**
180:             * Gets the processing information.
181:             * @return processing information
182:             */
183:            public String getProcessingInfo() {
184:                return respondTo.getProcessingInfo();
185:            }
186:
187:            /**
188:             * Returns this transaction.
189:             * @return request channel transaction
190:             */
191:            public MessageChannel getRequestChannel() {
192:                return this ;
193:            }
194:
195:            /**
196:             * Deterines if the message is a part of this transaction.
197:             *
198:             * @param messageToHeaderTest Message to check if it is part of this
199:             * transaction.
200:             *
201:             * @return True if the message is part of this transaction,
202:             * false if not.
203:             */
204:            public boolean isMessagePartOfTransaction(
205:                    Message messageToHeaderTest) {
206:                return isMessageTransOrMult(messageToHeaderTest, false);
207:            }
208:
209:            /**
210:             * Deterines if the message is a part of this transaction or it is
211:             * multiple 2xx response.
212:             *
213:             * @param messageToHeaderTest Message to check if it is part of this
214:             * transaction.
215:             *
216:             * @return True if the message is part of this transaction,
217:             * false if not.
218:             */
219:            public boolean isMessageTransOrMult(Message messageToHeaderTest) {
220:                return isMessageTransOrMult(messageToHeaderTest, true);
221:            }
222:
223:            /**
224:             * Deterines if the message is a part of this transaction or it is
225:             * multiple 2xx response.
226:             *
227:             * @param messageToHeaderTest Message to check if it is part of this
228:             * transaction.
229:             * @param checkMultResponse flag of checking multiple 2xx response
230:             *
231:             * @return True if the message is part of this transaction,
232:             * false if not.
233:             */
234:            private boolean isMessageTransOrMult(Message messageToHeaderTest,
235:                    boolean checkMultResponse) {
236:
237:                // List of Via headers in the message to test
238:                ViaList viaHeaders = messageToHeaderTest.getViaHeaders();
239:                // Flags whether the select message is part of this transaction
240:                boolean transactionMatches;
241:                String messageBranch = ((ViaHeader) viaHeaders.getFirst())
242:                        .getBranch();
243:                boolean rfc3261Compliant = (getBranch() != null)
244:                        && (messageBranch != null)
245:                        && getBranch().startsWith(
246:                                SIPConstants.GENERAL_BRANCH_MAGIC_COOKIE)
247:                        && messageBranch
248:                                .startsWith(SIPConstants.GENERAL_BRANCH_MAGIC_COOKIE);
249:
250:                /**
251:                 * if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
252:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
253:                 *         "--------- TEST ------------");
254:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
255:                 *         " testing " + this.getOriginalRequest());
256:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
257:                 *         "Against " + messageToHeaderTest);
258:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
259:                 *         "isTerminated = " + isTerminated());
260:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
261:                 *         "messageBranch = " + messageBranch);
262:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
263:                 *         "viaList = " + messageToHeaderTest.getViaHeaders());
264:                 *     Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
265:                 *        "myBranch = " + getBranch());
266:                 * }
267:                 */
268:
269:                transactionMatches = false;
270:                // Response 2xx should be processed even in TERMINATED state
271:                // RFC 3261, 13.2.2.4:
272:                // Multiple 2xx responses may arrive at the UAC for a single INVITE
273:                // request due to a forking proxy.
274:                boolean isResponse = messageToHeaderTest instanceof  Response;
275:                if (!isTerminated()
276:                        || (checkMultResponse && isTerminated() && isResponse
277:                                && isInviteTransaction() && (((Response) messageToHeaderTest)
278:                                .getStatusCode() / 100 == 2))) {
279:                    if (rfc3261Compliant) {
280:                        if (viaHeaders != null) {
281:                            // If the branch parameter is the
282:                            // same as this transaction and the method is the same,
283:                            if (getBranch().equals(
284:                                    ((ViaHeader) viaHeaders.getFirst())
285:                                            .getBranch())) {
286:                                transactionMatches = getOriginalRequest()
287:                                        .getCSeqHeader().getMethod().equals(
288:                                                messageToHeaderTest
289:                                                        .getCSeqHeader()
290:                                                        .getMethod());
291:
292:                            }
293:                        }
294:                    } else {
295:                        transactionMatches = getOriginalRequest()
296:                                .getTransactionId().equals(
297:                                        messageToHeaderTest.getTransactionId());
298:
299:                    }
300:
301:                }
302:                return transactionMatches;
303:
304:            }
305:
306:            /**
307:             * Deterines if the response is multiple (RFC 3261, 13.2.2.4).
308:             *
309:             * @param response response for checking
310:             * transaction.
311:             *
312:             * @return True if the input response has 2xx status, the current
313:             * transaction has TERMINATED state and the To tag is not same as
314:             * To tag of current transaction. This method doesn't compare other
315:             * members, it should be use with method isMessageTransOrMult
316:             * together .
317:             */
318:            public boolean isMultipleResponse(Response response) {
319:                boolean returnValue = false;
320:                if ((response.getStatusCode() / 100 == 2) && isTerminated()) {
321:                    Response lastResponse = getLastResponse();
322:                    if (lastResponse != null) {
323:                        String newTag = response.getToTag();
324:                        returnValue = !newTag.equals(lastResponse.getToTag());
325:                    }
326:                }
327:                return returnValue;
328:            }
329:
330:            /**
331:             * Sends a request message through this transaction and
332:             * onto the client.
333:             *
334:             * @param messageToHeaderSend Request to process and send.
335:             */
336:            public void sendMessage(Message messageToHeaderSend)
337:                    throws IOException {
338:
339:                // Message typecast as a request
340:                Request transactionRequest;
341:
342:                transactionRequest = (Request) messageToHeaderSend;
343:
344:                // Set the branch id for the top via header.
345:                ViaHeader topVia = (ViaHeader) transactionRequest
346:                        .getViaHeaders().getFirst();
347:                // Tack on a branch identifier to match responses.
348:
349:                topVia.setBranch(getBranch());
350:
351:                // If this is the first request for this transaction,
352:                if (getState() == INITIAL_STATE) {
353:                    // Save this request as the one this transaction
354:                    // is handling
355:                    setOriginalRequest(transactionRequest);
356:
357:                    // Change to trying/calling state
358:                    if (transactionRequest.getMethod().equals(Request.INVITE)) {
359:                        setState(CALLING_STATE);
360:                    } else if (transactionRequest.getMethod().equals(
361:                            Request.ACK)) {
362:                        // Acks are never retransmitted.
363:                        setState(TERMINATED_STATE);
364:                    } else {
365:                        setState(TRYING_STATE);
366:                    }
367:
368:                    if (!isReliable()) {
369:                        enableRetransmissionTimer();
370:                    }
371:
372:                    if (isInviteTransaction()) {
373:                        enableTimeoutTimer(TIMER_B);
374:                    } else {
375:                        enableTimeoutTimer(TIMER_F);
376:                    }
377:
378:                } else if (getState() == PROCEEDING_STATE
379:                        || getState() == CALLING_STATE) {
380:
381:                    // If this is a TU-generated ACK request,
382:                    if (transactionRequest.getMethod().equals(Request.ACK)) {
383:                        // Send directly to the underlying
384:                        // transport and close this transaction
385:                        setState(TERMINATED_STATE);
386:                        getMessageChannel().sendMessage(transactionRequest);
387:                        return;
388:
389:                    }
390:
391:                }
392:
393:                try {
394:                    // Send the message to the server
395:                    lastRequest = transactionRequest;
396:                    getMessageChannel().sendMessage(transactionRequest);
397:                } catch (IOException e) {
398:                    setState(TERMINATED_STATE);
399:                    throw e;
400:                }
401:            }
402:
403:            /**
404:             * Processes a new response message through this transaction.
405:             * If necessary, this message will also be passed onto the TU.
406:             *
407:             * @param transactionResponse Response to process.
408:             * @param sourceChannel Channel that received this message.
409:             */
410:            public synchronized void processResponse(
411:                    Response transactionResponse, MessageChannel sourceChannel)
412:                    throws SIPServerException {
413:
414:                // Log the incoming response in our log file.
415:                if (ServerLog.needsLogging(ServerLog.TRACE_MESSAGES))
416:                    this .logResponse(transactionResponse, System
417:                            .currentTimeMillis(), "normal processing");
418:
419:                int statusGroup = transactionResponse.getStatusCode() / 100;
420:
421:                // Ignore 1xx
422:                if (getState() == COMPLETED_STATE && statusGroup == 1) {
423:                    return;
424:                    // This block is against RFC 3261 17.1.1.2, figure 5 and
425:                    // 17.1.4, figure 6
426:                    /*
427:                    } else if (PROCEEDING_STATE == this.getState()
428:                    && transactionResponse.getStatusCode() == 100) {
429:                        // Ignore 100 if received after 180
430:                        return;
431:                     */
432:                } else {
433:                    // IMPL_NOTE: investigate if this flag may be completely removed.
434:                    while (eventPending) {
435:                        try {
436:                            // Wait for clearEventPending() call.
437:                            wait();
438:                        } catch (InterruptedException e) {
439:                            // intentionally ignored
440:                            // wait for clearEventPending() call
441:                        }
442:                    }
443:                }
444:
445:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
446:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
447:                            "processing " + transactionResponse.getFirstLine()
448:                                    + "current state = " + getState());
449:                }
450:
451:                this .lastResponse = transactionResponse;
452:
453:                if ((dialog != null) && (statusGroup < 3)) {
454:                    // add the route before you process the response.
455:                    dialog.addRoute(transactionResponse);
456:                }
457:
458:                String method = transactionResponse.getCSeqHeader().getMethod();
459:
460:                if (dialog != null) {
461:                    boolean added = false;
462:                    SIPTransactionStack sipStackImpl = (SIPTransactionStack) getSIPStack();
463:
464:                    // A tag just got assigned or changed.
465:                    if (dialog.getRemoteTag() == null
466:                            && transactionResponse.getTo().getTag() != null) {
467:
468:                        // Dont assign tag on provisional response
469:                        if (transactionResponse.getStatusCode() != 100) {
470:                            dialog.setRemoteTag(transactionResponse.getToTag());
471:                        }
472:
473:                        String dialogId = transactionResponse
474:                                .getDialogId(false);
475:                        dialog.setDialogId(dialogId);
476:
477:                        if (sipStackImpl.isDialogCreated(method)
478:                                && transactionResponse.getStatusCode() != 100) {
479:                            sipStackImpl.putDialog(dialog);
480:                            if (statusGroup == 1) {
481:                                dialog.setState(Dialog.EARLY_STATE);
482:                            } else if (statusGroup == 2) {
483:                                dialog.setState(Dialog.CONFIRMED_STATE);
484:                            }
485:                            added = true;
486:                        }
487:
488:                    } else if (dialog.getRemoteTag() != null
489:                            && transactionResponse.getToTag() != null
490:                            && !dialog.getRemoteTag().equals(
491:                                    transactionResponse.getToTag())) {
492:                        dialog.setRemoteTag(transactionResponse.getToTag());
493:                        String dialogId = transactionResponse
494:                                .getDialogId(false);
495:                        dialog.setDialogId(dialogId);
496:
497:                        if (sipStackImpl.isDialogCreated(method)) {
498:                            sipStackImpl.putDialog(dialog);
499:                            added = true;
500:                        }
501:                    }
502:
503:                    if (sipStackImpl.isDialogCreated(method)) {
504:                        // Make a final tag assignment.
505:                        if (transactionResponse.getToTag() != null
506:                                && statusGroup == 2) {
507:                            // This is a dialog creating method (such as INVITE).
508:                            // 2xx response -- set the state to the confirmed
509:                            // state.
510:                            dialog.setRemoteTag(transactionResponse.getToTag());
511:                            dialog.setState(Dialog.CONFIRMED_STATE);
512:                        } else if ((transactionResponse.getStatusCode() == 487
513:                                || statusGroup == 5 || statusGroup == 6)
514:                                && (dialog.getState() == -1 || dialog
515:                                        .getState() == Dialog.EARLY_STATE)) {
516:                            // Invite transaction generated an error.
517:                            dialog.setState(Dialog.TERMINATED_STATE);
518:                        }
519:                    }
520:
521:                    // 200 OK for a bye so terminate the dialog.
522:                    if (transactionResponse.getCSeqHeader().getMethod().equals(
523:                            Request.BYE)
524:                            && transactionResponse.getStatusCode() == 200) {
525:                        dialog.setState(Dialog.TERMINATED_STATE);
526:                    }
527:                }
528:
529:                try {
530:                    if (isInviteTransaction()) {
531:                        inviteClientTransaction(transactionResponse,
532:                                sourceChannel);
533:                    } else {
534:                        nonInviteClientTransaction(transactionResponse,
535:                                sourceChannel);
536:                    }
537:                } catch (IOException ex) {
538:                    setState(TERMINATED_STATE);
539:                    raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
540:                }
541:            }
542:
543:            /**
544:             * Implements the state machine for invite client transactions.
545:             * @param transactionResponse -- transaction response received.
546:             * @param sourceChannel - source channel on which the response was received.
547:             * <pre>
548:             *
549:             * |Request from TU
550:             * |send request
551:             * Timer E V
552:             * send request +-----------+
553:             * +---------| |-------------------+
554:             * | | Trying | Timer F |
555:             * +-------->| | or Transport Err.|
556:             * +-----------+ inform TU |
557:             * 200-699 | | |
558:             * resp. to TU | |1xx |
559:             * +---------------+ |resp. to TU |
560:             * | | |
561:             * | Timer E V Timer F |
562:             * | send req +-----------+ or Transport Err. |
563:             * | +---------| | inform TU |
564:             * | | |Proceeding |------------------>|
565:             * | +-------->| |-----+ |
566:             * | +-----------+ |1xx |
567:             * | | ^ |resp to TU |
568:             * | 200-699 | +--------+ |
569:             * | resp. to TU | |
570:             * | | |
571:             * | V |
572:             * | +-----------+ |
573:             * | | | |
574:             * | | Completed | |
575:             * | | | |
576:             * | +-----------+ |
577:             * | ^ | |
578:             * | | | Timer K |
579:             * +--------------+ | - |
580:             * | |
581:             * V |
582:             * NOTE: +-----------+ |
583:             * | | |
584:             * transitions | Terminated|<------------------+
585:             * labeled with | |
586:             * the event +-----------+
587:             * over the action
588:             * to take
589:             *
590:             * Figure 6: non-INVITE client transaction
591:             */
592:            private void nonInviteClientTransaction(
593:                    Response transactionResponse, MessageChannel sourceChannel)
594:                    throws IOException, SIPServerException {
595:                int currentState = getState();
596:
597:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
598:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
599:                            "nonInviteClientTransaction "
600:                                    + transactionResponse.getFirstLine());
601:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
602:                            "currentState = " + currentState);
603:                }
604:
605:                int statusCode = transactionResponse.getStatusCode();
606:                if (currentState == TRYING_STATE) {
607:                    if (statusCode / 100 == 1) {
608:                        // Response to TU, RFC 3261, 17.1.4, figure 6
609:                        respondTo.processResponse(transactionResponse, this );
610:                        setState(PROCEEDING_STATE);
611:                        enableRetransmissionTimer(MAXIMUM_RETRANSMISSION_TICK_COUNT);
612:                        enableTimeoutTimer(TIMER_F);
613:                    } else if (200 <= statusCode && statusCode <= 699) {
614:                        // Send the response up to the TU.
615:                        respondTo.processResponse(transactionResponse, this );
616:                        if (!isReliable()) {
617:                            setState(COMPLETED_STATE);
618:                            enableTimeoutTimer(TIMER_K);
619:                        } else {
620:                            setState(TERMINATED_STATE);
621:                        }
622:                    }
623:                } else if (currentState == PROCEEDING_STATE
624:                        && 200 <= statusCode && statusCode <= 699) {
625:
626:                    respondTo.processResponse(transactionResponse, this );
627:
628:                    disableRetransmissionTimer();
629:                    disableTimeoutTimer();
630:                    if (!isReliable()) {
631:                        setState(COMPLETED_STATE);
632:                        enableTimeoutTimer(TIMER_K);
633:                    } else {
634:                        setState(TERMINATED_STATE);
635:                    }
636:                } else if (currentState == PROCEEDING_STATE
637:                        && statusCode / 100 == 1) {
638:                    // Response to TU, RFC 3261, 17.1.4, figure 6
639:                    respondTo.processResponse(transactionResponse, this );
640:                }
641:            }
642:
643:            /**
644:             * Implements the state machine for invite client transactions.
645:             * @param transactionResponse -- transaction response received.
646:             * @param sourceChannel - source channel on which the response was received.
647:             * <pre>
648:             *
649:             * |INVITE from TU
650:             * Timer A fires |INVITE sent
651:             * Reset A, V Timer B fires
652:             * INVITE sent +-----------+ or Transport Err.
653:             * +---------| |---------------+inform TU
654:             * | | Calling | |
655:             * +-------->| |-------------->|
656:             * +-----------+ 2xx |
657:             * | | 2xx to TU |
658:             * | |1xx |
659:             * 300-699 +---------------+ |1xx to TU |
660:             * ACK sent | | |
661:             * resp. to TU | 1xx V |
662:             * | 1xx to TU -----------+ |
663:             * | +---------| | |
664:             * | | |Proceeding |-------------->|
665:             * | +-------->| | 2xx |
666:             * | +-----------+ 2xx to TU |
667:             * | 300-699 | |
668:             * | ACK sent, | |
669:             * | resp. to TU| |
670:             * | | | NOTE:
671:             * | 300-699 V |
672:             * | ACK sent +-----------+Transport Err. | transitions
673:             * | +---------| |Inform TU | labeled with
674:             * | | | Completed |-------------->| the event
675:             * | +-------->| | | over the action
676:             * | +-----------+ | to take
677:             * | ^ | |
678:             * | | | Timer D fires |
679:             * +--------------+ | - |
680:             * | |
681:             * V |
682:             * +-----------+ |
683:             * | | |
684:             * | Terminated|<--------------+
685:             * | |
686:             * +-----------+
687:             * </pre>
688:             */
689:            private void inviteClientTransaction(Response transactionResponse,
690:                    MessageChannel sourceChannel) throws IOException,
691:                    SIPServerException {
692:                int statusCode = transactionResponse.getStatusCode();
693:                int currentState = getState();
694:
695:                if (currentState == TERMINATED_STATE) {
696:                    // Do nothing in the terminated state.
697:                    return;
698:                } else if (currentState == CALLING_STATE) {
699:                    if (statusCode / 100 == 2) {
700:                        // 200 responses are always seen by TU.
701:                        respondTo.processResponse(transactionResponse, this );
702:                        disableRetransmissionTimer();
703:                        disableTimeoutTimer();
704:                        setState(TERMINATED_STATE);
705:                    } else if (statusCode / 100 == 1) {
706:                        disableRetransmissionTimer();
707:                        disableTimeoutTimer();
708:                        respondTo.processResponse(transactionResponse, this );
709:                        setState(PROCEEDING_STATE);
710:                    } else if (300 <= statusCode && statusCode <= 699) {
711:                        // When in either the "Calling" or "Proceeding" states,
712:                        // reception of response with status code from 300-699
713:                        // MUST cause the client transaction to
714:                        // transition to "Completed".
715:                        // The client transaction MUST pass the received response up to
716:                        // the TU, and the client transaction MUST generate an
717:                        // ACK request.
718:
719:                        respondTo.processResponse(transactionResponse, this );
720:
721:                        // Send back an ACK request
722:                        try {
723:                            sendMessage((Request) createAck());
724:                        } catch (SipException ex) {
725:                            InternalErrorHandler.handleException(ex);
726:                        }
727:                        if (!isReliable()) {
728:                            setState(COMPLETED_STATE);
729:                            enableTimeoutTimer(TIMER_D);
730:                        } else {
731:                            // Proceed immediately to the TERMINATED state.
732:                            setState(TERMINATED_STATE);
733:                        }
734:                    }
735:                } else if (currentState == PROCEEDING_STATE) {
736:                    if (statusCode / 100 == 1) {
737:                        respondTo.processResponse(transactionResponse, this );
738:                    } else if (statusCode / 100 == 2) {
739:                        setState(TERMINATED_STATE);
740:                        respondTo.processResponse(transactionResponse, this );
741:                    } else if (300 <= statusCode && statusCode <= 699) {
742:                        respondTo.processResponse(transactionResponse, this );
743:                        // Send back an ACK request
744:                        try {
745:                            sendMessage((Request) createAck());
746:                        } catch (SipException ex) {
747:                            InternalErrorHandler.handleException(ex);
748:                        }
749:                        if (!isReliable()) {
750:                            setState(COMPLETED_STATE);
751:                            enableTimeoutTimer(TIMER_D);
752:                        } else {
753:                            setState(TERMINATED_STATE);
754:                        }
755:                    }
756:                } else if (currentState == COMPLETED_STATE) {
757:                    if (300 <= statusCode && statusCode <= 699) {
758:                        // Send back an ACK request
759:                        try {
760:                            sendMessage((Request) createAck());
761:                        } catch (SipException ex) {
762:                            InternalErrorHandler.handleException(ex);
763:                        }
764:                    }
765:
766:                }
767:
768:            }
769:
770:            /**
771:             * Sends specified {@link gov.nist.siplite.message.Request} on a unique
772:             * client transaction identifier. This method implies that the application
773:             * is functioning as either a User Agent Client or a Stateful proxy, hence
774:             * the underlying SipProvider acts statefully.
775:             * <p>
776:             * JAIN SIP defines a retransmission utility specific to user agent
777:             * behaviour and the default retransmission behaviour for each method.
778:             * <p>
779:             * When an application wishes to send a message, it creates a Request
780:             * message passes that Request to this method, this method returns the
781:             * cleintTransactionId generated by the SipProvider. The Request message
782:             * gets sent via the ListeningPoint that this SipProvider is attached to.
783:             * <ul>
784:             * <li>User Agent Client - must not send a BYE on a confirmed INVITE until
785:             * it has received an ACK for its 2xx response or until the server
786:             * transaction times out.
787:             * </ul>
788:             *
789:             * @throws IOException if an I/O error occured
790:             * @throws SipException if implementation cannot send request for any
791:             * other reason
792:             */
793:            public void sendRequest() throws IOException, SipException {
794:                Request sipRequest = getOriginalRequest();
795:                sendMessage(sipRequest);
796:            }
797:
798:            /**
799:             * Called by the transaction stack when a retransmission timer
800:             * fires.
801:             */
802:            protected void fireRetransmissionTimer() {
803:                boolean noSend = false;
804:                try {
805:                    // Resend the last request sent
806:                    // System.out.println("fireRetransmissionTimer ");
807:                    if (this .getState() == -1) {
808:                        noSend = true;
809:                    } else {
810:                        MessageProcessor mp = this .getMessageProcessor();
811:                        if (mp == null) {
812:                            noSend = true;
813:                        } else if (mp.toExit()) {
814:                            noSend = true;
815:                        }
816:                    }
817:                    int currentState = this .getState();
818:                    if (!noSend
819:                            && (currentState == CALLING_STATE || currentState == TRYING_STATE)) {
820:                        getMessageChannel().sendMessage(lastRequest);
821:                    }
822:                } catch (IOException e) {
823:                    raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
824:                }
825:            }
826:
827:            /**
828:             * Called by the transaction stack when a timeout timer fires.
829:             */
830:            protected void fireTimeoutTimer() {
831:                Dialog dialogImpl = this .getDialog();
832:                if (getState() == CALLING_STATE || getState() == TRYING_STATE
833:                        || getState() == PROCEEDING_STATE) {
834:                    // Timeout occured. If this is asociated with a transaction
835:                    // creation then kill the dialog.
836:                    if (dialogImpl != null) {
837:                        if (((SIPTransactionStack) getSIPStack())
838:                                .isDialogCreated(this .getOriginalRequest()
839:                                        .getMethod())) {
840:                            // terminate the enclosing dialog.
841:                            dialogImpl.setState(Dialog.TERMINATED_STATE);
842:                        } else if (getOriginalRequest().getMethod().equals(
843:                                Request.BYE)) {
844:                            // Terminate the associated dialog on BYE Timeout.
845:                            dialogImpl.setState(Dialog.TERMINATED_STATE);
846:                        }
847:                    }
848:                }
849:                if (getState() != COMPLETED_STATE) {
850:                    raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
851:                } else {
852:                    setState(TERMINATED_STATE);
853:                }
854:            }
855:
856:            /**
857:             * Creates a new Cancel message from the Request associated with this client
858:             * transaction. The CANCEL request, is used to cancel the previous request
859:             * sent by this client transaction. Specifically, it asks the UAS to cease
860:             * processing the request and to generate an error response to that request.
861:             *
862:             * @return a cancel request generated from the original request.
863:             * @throws SipException if the request cannot be cancelled.
864:             */
865:            public Request createCancel() throws SipException {
866:                Request originalRequest = getOriginalRequest();
867:                return originalRequest.createCancelRequest();
868:            }
869:
870:            /**
871:             * Creates an ACK request for this transaction
872:             *
873:             * @return an ack request generated from the original request.
874:             * @throws SipException if transaction is in the wrong state to be acked.
875:             */
876:            public Request createAck() throws SipException {
877:                Request originalRequest = getOriginalRequest();
878:                int statusCode = 0;
879:
880:                if (originalRequest.getMethod().equals(Request.ACK)) {
881:                    throw new SipException("Cannot ACK an ACK!",
882:                            SipException.INVALID_OPERATION);
883:                } else if (lastResponse == null) {
884:                    throw new SipException("bad Transaction state",
885:                            SipException.INVALID_STATE);
886:                } else {
887:                    statusCode = lastResponse.getStatusCode();
888:                    if (statusCode < 200) {
889:                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
890:                            Logging.report(Logging.INFORMATION,
891:                                    LogChannels.LC_JSR180, "lastResponse = "
892:                                            + lastResponse);
893:                        }
894:
895:                        throw new SipException(
896:                                "Cannot ACK a provisional response!",
897:                                SipException.INVALID_OPERATION);
898:                    }
899:                }
900:
901:                Request ackRequest = originalRequest
902:                        .createAckRequest((ToHeader) lastResponse.getTo());
903:
904:                // Automatic ACK at transaction layer
905:                if (300 <= statusCode && statusCode <= 699) {
906:                    ViaHeader topmostVia = originalRequest.getTopmostVia();
907:                    if (topmostVia != null) {
908:                        ackRequest.setHeader(topmostVia);
909:                    }
910:                    return ackRequest;
911:                }
912:
913:                // Pull the record route headers from the last reesponse.
914:                buildRouteSet(ackRequest);
915:                return ackRequest;
916:
917:            }
918:
919:            /**
920:             * Sets the port of the recipient.
921:             * @param port the new via port
922:             */
923:            protected void setViaPort(int port) {
924:                this .viaPort = port;
925:            }
926:
927:            /**
928:             * Sets the port of the recipient.
929:             * @param host the new via host
930:             */
931:            protected void setViaHost(String host) {
932:                this .viaHost = host;
933:            }
934:
935:            /**
936:             * Gets the port of the recipient.
937:             * @return the via port
938:             */
939:            public int getViaPort() {
940:                return this .viaPort;
941:            }
942:
943:            /**
944:             * Gets the host of the recipient.
945:             * @return the via host
946:             */
947:            public String getViaHost() {
948:                return this .viaHost;
949:            }
950:
951:            /**
952:             * Gets the via header for an outgoing request.
953:             * @return the via header reader
954:             */
955:            public ViaHeader getOutgoingViaHeader() {
956:                return this .getMessageProcessor().getViaHeader();
957:            }
958:
959:            /**
960:             * Checks if connection is secure.
961:             * @return true if connection is secure.
962:             */
963:            public boolean isSecure() {
964:                return encapsulatedChannel.isSecure();
965:            }
966:
967:            /**
968:             * Clears the event pending flag.
969:             */
970:            public synchronized void clearEventPending() {
971:                eventPending = false;
972:                notify();
973:            }
974:
975:            /**
976:             * Sets the event pending flag.
977:             */
978:            public synchronized void setEventPending() {
979:                eventPending = true;
980:            }
981:
982:            /**
983:             * Create a new client transaction based on current.
984:             * Field lastResponse is filled by input parameter.
985:             * @param lastResponse last response
986:             * @return new instance of client transaction.
987:             */
988:            public ClientTransaction cloneWithNewLastResponse(
989:                    Response lastResponse) {
990:                ClientTransaction clientTransaction = new ClientTransaction(
991:                        (SIPTransactionStack) getSIPStack(),
992:                        getMessageChannel());
993:                clientTransaction.lastResponse = lastResponse;
994:                clientTransaction.setOriginalRequest(getOriginalRequest());
995:                return clientTransaction;
996:            }
997:
998:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.