Source Code Cross Referenced for SIPTransactionStack.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) 


0001:        /*
0002:         * Portions Copyright  2000-2007 Sun Microsystems, Inc. All Rights
0003:         * Reserved.  Use is subject to license terms.
0004:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0005:         * 
0006:         * This program is free software; you can redistribute it and/or
0007:         * modify it under the terms of the GNU General Public License version
0008:         * 2 only, as published by the Free Software Foundation.
0009:         * 
0010:         * This program is distributed in the hope that it will be useful, but
0011:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013:         * General Public License version 2 for more details (a copy is
0014:         * included at /legal/license.txt).
0015:         * 
0016:         * You should have received a copy of the GNU General Public License
0017:         * version 2 along with this work; if not, write to the Free Software
0018:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0019:         * 02110-1301 USA
0020:         * 
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0022:         * Clara, CA 95054 or visit www.sun.com if you need additional
0023:         * information or have any questions.
0024:         */
0025:        package gov.nist.siplite.stack;
0026:
0027:        import gov.nist.microedition.sip.SipClientConnectionImpl;
0028:        import gov.nist.siplite.message.*;
0029:        import gov.nist.siplite.header.*;
0030:        import gov.nist.siplite.address.*;
0031:        import gov.nist.core.*;
0032:        import java.util.*;
0033:        import java.io.IOException;
0034:
0035:        import com.sun.midp.log.Logging;
0036:        import com.sun.midp.log.LogChannels;
0037:
0038:        /**
0039:         * Adds a transaction layer to the {@link SIPMessageStack} class. This
0040:         * is done by
0041:         * replacing the normal MessageChannels returned by the base class with
0042:         * transaction-aware MessageChannels that encapsulate the original channels
0043:         * and handle the transaction state machine, retransmissions, etc.
0044:         *
0045:         * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
0046:         *
0047:         * @version JAIN-SIP-1.1
0048:         *
0049:         */
0050:        public abstract class SIPTransactionStack extends SIPMessageStack
0051:                implements  SIPTransactionEventListener {
0052:
0053:            /**
0054:             * Number of milliseconds between timer ticks (500).
0055:             */
0056:            public static final int BASE_TIMER_INTERVAL = 500;
0057:
0058:            /** Collection of current client transactions. */
0059:            private Vector clientTransactions;
0060:            /** Collection or current server transactions. */
0061:            private Vector serverTransactions;
0062:            /** Table of dialogs. */
0063:            private Hashtable dialogTable;
0064:
0065:            /** Max number of server transactions concurrent. */
0066:            protected int transactionTableSize;
0067:
0068:            /**
0069:             * Retransmission filter - indicates the stack will retransmit
0070:             * 200 OK for invite transactions.
0071:             */
0072:            protected boolean retransmissionFilter;
0073:
0074:            /** A set of methods that result in dialog creations. */
0075:            protected Hashtable dialogCreatingMethods;
0076:
0077:            /** Default constructor. */
0078:            protected SIPTransactionStack() {
0079:                super ();
0080:                this .transactionTableSize = -1;
0081:                // a set of methods that result in dialog creation.
0082:                this .dialogCreatingMethods = new Hashtable();
0083:                // Standard set of methods that create dialogs.
0084:                this .dialogCreatingMethods.put(Request.REFER, "");
0085:                this .dialogCreatingMethods.put(Request.INVITE, "");
0086:                this .dialogCreatingMethods.put(Request.SUBSCRIBE, "");
0087:                // Notify may or may not create a dialog. This is handled in
0088:                // the code.
0089:                // this.dialogCreatingMethods.add(Request.NOTIFY);
0090:                // this.dialogCreatingMethods.put(Request.MESSAGE, "");
0091:                // Create the transaction collections
0092:                clientTransactions = new Vector();
0093:                serverTransactions = new Vector();
0094:                // Dialog dable.
0095:                this .dialogTable = new Hashtable();
0096:
0097:                // Start the timer event thread.
0098:                // System.out.println("Starting timeout");
0099:                new Thread(new TransactionScanner()).start();
0100:
0101:            }
0102:
0103:            /**
0104:             * Prints the Dialog creating methods.
0105:             */
0106:            private void printDialogCreatingMethods() {
0107:                System.out.println("PRINTING DIALOGCREATINGMETHODS HASHTABLE");
0108:                Enumeration e = dialogCreatingMethods.keys();
0109:                while (e.hasMoreElements()) {
0110:                    System.out.println(e.nextElement());
0111:                }
0112:                System.out.println("DIALOGCREATINGMETHODS HASHTABLE PRINTED");
0113:            }
0114:
0115:            /**
0116:             * Returns true if extension is supported.
0117:             * @param method the name of the method used for create
0118:             * @return true if extension is supported and false otherwise.
0119:             */
0120:            public boolean isDialogCreated(String method) {
0121:                // printDialogCreatingMethods();
0122:                // System.out.println("CHECKING IF DIALOG HAS BEEN CREATED"
0123:                // + " FOR THE FOLLOWING METHOD"
0124:                // + method.toUpperCase());
0125:                return dialogCreatingMethods.containsKey(method.toUpperCase());
0126:            }
0127:
0128:            /**
0129:             * Returns true if method can change dialog state.
0130:             * @param method the name of the method used for create
0131:             * @return true if extension is supported and false otherwise.
0132:             */
0133:            public boolean allowDialogStateChange(String method) {
0134:                return dialogCreatingMethods.containsKey(method.toUpperCase())
0135:                        || method.equalsIgnoreCase(Request.BYE)
0136:                        || method.equalsIgnoreCase(Request.NOTIFY);
0137:            }
0138:
0139:            /**
0140:             * Adds an extension method.
0141:             * @param extensionMethod -- extension method to support for dialog
0142:             * creation
0143:             */
0144:            public void addExtensionMethod(String extensionMethod) {
0145:                if (!extensionMethod.equals(Request.NOTIFY)) {
0146:                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0147:                        Logging.report(Logging.INFORMATION,
0148:                                LogChannels.LC_JSR180,
0149:                                "NOTIFY Supported Natively");
0150:                    }
0151:                } else {
0152:                    this .dialogCreatingMethods.put(extensionMethod, "");
0153:                }
0154:            }
0155:
0156:            /**
0157:             * Puts a dialog into the dialog table.
0158:             * @param dialog -- dialog to put into the dialog table.
0159:             */
0160:            public void putDialog(Dialog dialog) {
0161:                String dialogId = dialog.getDialogId();
0162:
0163:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0164:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
0165:                            "putDialog dialogId=" + dialogId);
0166:                }
0167:
0168:                // if (this.getDefaultRouteHeader() != null)
0169:                // dialog.addRoute(this.getDefaultRouteHeader(), false);
0170:                dialog.setStack(this );
0171:
0172:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0173:                    // new Exception().printStackTrace();
0174:                }
0175:
0176:                synchronized (dialogTable) {
0177:                    dialogTable.put(dialogId, dialog);
0178:                }
0179:
0180:            }
0181:
0182:            /**
0183:             * Creates a new dialog for requested transaction.
0184:             * @param transaction the requested transaction
0185:             * @return the new Dialog  object
0186:             */
0187:            public synchronized Dialog createDialog(Transaction transaction) {
0188:                Request sipRequest = transaction.getOriginalRequest();
0189:                Dialog retval = new Dialog(transaction);
0190:
0191:                return retval;
0192:            }
0193:
0194:            /**
0195:             * Returns the dialog for a given dialog ID. If compatibility is
0196:             * enabled then we do not assume the presence of tags and hence
0197:             * need to add a flag to indicate whether this is a server or
0198:             * client transaction.
0199:             * @param dialogId is the dialog id to check.
0200:             * @return the Dialog object for the requested id
0201:             */
0202:            public Dialog getDialog(String dialogId) {
0203:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0204:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
0205:                            "Getting dialog for " + dialogId);
0206:                }
0207:
0208:                synchronized (dialogTable) {
0209:                    return (Dialog) dialogTable.get(dialogId);
0210:                }
0211:            }
0212:
0213:            /**
0214:             * Finds a matching client SUBSCRIBE to the incoming notify.
0215:             * NOTIFY requests are matched to such SUBSCRIBE requests if they
0216:             * contain the same "Call-ID", a "ToHeader" header "tag" parameter which
0217:             * matches the "FromHeader" header "tag" parameter of the SUBSCRIBE, and the
0218:             * same "Event" header field. Rules for comparisons of the "Event"
0219:             * headers are described in section 7.2.1. If a matching NOTIFY request
0220:             * contains a "Subscription-State" of "active" or "pending", it creates
0221:             * a new subscription and a new dialog (unless they have already been
0222:             * created by a matching response, as described above).
0223:             *
0224:             * @param notifyMessage the request to be matched
0225:             * @return the new client transaction object
0226:             */
0227:            public ClientTransaction findSubscribeTransaction(
0228:                    Request notifyMessage) {
0229:                synchronized (clientTransactions) {
0230:                    Enumeration it = clientTransactions.elements();
0231:                    String this ToHeaderTag = notifyMessage.getTo().getTag();
0232:                    if (this ToHeaderTag == null)
0233:                        return null;
0234:                    EventHeader eventHdr = (EventHeader) notifyMessage
0235:                            .getHeader(Header.EVENT);
0236:                    if (eventHdr == null)
0237:                        return null;
0238:                    while (it.hasMoreElements()) {
0239:                        ClientTransaction ct = (ClientTransaction) it
0240:                                .nextElement();
0241:                        Request sipRequest = ct.getOriginalRequest();
0242:                        String fromTag = sipRequest.getFromHeader().getTag();
0243:                        EventHeader hisEvent = (EventHeader) sipRequest
0244:                                .getHeader(Header.EVENT);
0245:                        // Event header is mandatory but some slopply clients
0246:                        // dont include it.
0247:                        if (hisEvent == null)
0248:                            continue;
0249:                        if (sipRequest.getMethod().equals(Request.SUBSCRIBE)
0250:                                && Utils.equalsIgnoreCase(fromTag,
0251:                                        this ToHeaderTag)
0252:                                && hisEvent != null
0253:                                && eventHdr.match(hisEvent)
0254:                                && Utils.equalsIgnoreCase(notifyMessage
0255:                                        .getCallId().getCallId(), sipRequest
0256:                                        .getCallId().getCallId()))
0257:                            return ct;
0258:                    }
0259:
0260:                }
0261:                return null;
0262:            }
0263:
0264:            /**
0265:             * Finds the transaction corresponding to a given request.
0266:             * @param sipMessage request for which to retrieve the transaction.
0267:             * @param isServer search the server transaction table if true.
0268:             * @return the transaction object corresponding to the request or null
0269:             * if no such mapping exists.
0270:             */
0271:            public Transaction findTransaction(Message sipMessage,
0272:                    boolean isServer) {
0273:
0274:                if (isServer) {
0275:                    if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0276:                        Logging.report(Logging.INFORMATION,
0277:                                LogChannels.LC_JSR180,
0278:                                "searching server transaction for "
0279:                                        + sipMessage + " size = "
0280:                                        + this .serverTransactions.size());
0281:                    }
0282:
0283:                    synchronized (this .serverTransactions) {
0284:                        Enumeration it = serverTransactions.elements();
0285:                        while (it.hasMoreElements()) {
0286:                            ServerTransaction sipServerTransaction = (ServerTransaction) it
0287:                                    .nextElement();
0288:                            if (sipServerTransaction
0289:                                    .isMessagePartOfTransaction(sipMessage))
0290:                                return sipServerTransaction;
0291:                        }
0292:                    }
0293:                } else {
0294:                    synchronized (this .clientTransactions) {
0295:                        Enumeration it = clientTransactions.elements();
0296:                        while (it.hasMoreElements()) {
0297:                            ClientTransaction clientTransaction = (ClientTransaction) it
0298:                                    .nextElement();
0299:                            if (clientTransaction
0300:                                    .isMessagePartOfTransaction(sipMessage))
0301:                                return clientTransaction;
0302:                        }
0303:                    }
0304:
0305:                }
0306:                return null;
0307:
0308:            }
0309:
0310:            /**
0311:             * Gets the transaction to cancel. Search the server transaction
0312:             * table for a transaction that matches the given transaction.
0313:             * @param cancelRequest the request to be found
0314:             * @param isServer true if this is a server request
0315:             * @return the transaction object requested
0316:             */
0317:            public Transaction findCancelTransaction(Request cancelRequest,
0318:                    boolean isServer) {
0319:
0320:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0321:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
0322:                            "findCancelTransaction request = \n"
0323:                                    + cancelRequest
0324:                                    + "\nfindCancelRequest isServer = "
0325:                                    + isServer);
0326:                }
0327:
0328:                if (isServer) {
0329:                    synchronized (this .serverTransactions) {
0330:                        Enumeration li = this .serverTransactions.elements();
0331:                        while (li.hasMoreElements()) {
0332:                            Transaction transaction = (Transaction) li
0333:                                    .nextElement();
0334:                            Request sipRequest = (Request) (transaction
0335:                                    .getRequest());
0336:                            ServerTransaction sipServerTransaction = (ServerTransaction) transaction;
0337:                            if (sipServerTransaction
0338:                                    .doesCancelMatchTransaction(cancelRequest))
0339:                                return sipServerTransaction;
0340:                        }
0341:                    }
0342:                } else {
0343:                    synchronized (this .clientTransactions) {
0344:                        Enumeration li = this .clientTransactions.elements();
0345:                        while (li.hasMoreElements()) {
0346:                            Transaction transaction = (Transaction) li
0347:                                    .nextElement();
0348:                            Request sipRequest = (Request) (transaction
0349:                                    .getRequest());
0350:
0351:                            ClientTransaction sipClientTransaction = (ClientTransaction) transaction;
0352:                            if (sipClientTransaction
0353:                                    .doesCancelMatchTransaction(cancelRequest))
0354:                                return sipClientTransaction;
0355:
0356:                        }
0357:                    }
0358:                }
0359:                return null;
0360:            }
0361:
0362:            /**
0363:             * Construcor for the stack. Registers the request and response
0364:             * factories for the stack.
0365:             * @param messageFactory User-implemented factory for processing
0366:             * messages.
0367:             */
0368:            protected SIPTransactionStack(SIPStackMessageFactory messageFactory) {
0369:                this ();
0370:                super .sipMessageFactory = messageFactory;
0371:            }
0372:
0373:            /**
0374:             * Thread used to throw timer events for all transactions.
0375:             */
0376:            class TransactionScanner implements  Runnable {
0377:                /**
0378:                 * Main transaction scanner processing loop.
0379:                 */
0380:                public void run() {
0381:
0382:                    // Iterator through all transactions
0383:                    Enumeration transactionIterator;
0384:                    // One transaction in the set
0385:                    Transaction nextTransaction;
0386:
0387:                    // Loop while this stack is running
0388:                    while (isAlive()) {
0389:                        try {
0390:                            // Sleep for one timer "tick"
0391:                            Thread.sleep(BASE_TIMER_INTERVAL);
0392:
0393:                            // System.out.println("clientTransactionTable size " +
0394:                            // clientTransactions.size());
0395:                            // System.out.println("serverTransactionTable size " +
0396:                            // serverTransactions.size());
0397:                            // Check all client transactions
0398:
0399:                            Vector fireList = new Vector();
0400:                            Vector removeList = new Vector();
0401:
0402:                            // Check all server transactions
0403:                            synchronized (serverTransactions) {
0404:                                transactionIterator = serverTransactions
0405:                                        .elements();
0406:                                while (transactionIterator.hasMoreElements()) {
0407:
0408:                                    nextTransaction = (Transaction) transactionIterator
0409:                                            .nextElement();
0410:
0411:                                    // If the transaction has terminated,
0412:                                    if (nextTransaction.isTerminated()) {
0413:                                        // Keep the transaction hanging around
0414:                                        // to catch the incoming ACK.
0415:                                        if (((ServerTransaction) nextTransaction).collectionTime == 0) {
0416:                                            // Remove it from the set
0417:                                            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0418:                                                Logging
0419:                                                        .report(
0420:                                                                Logging.INFORMATION,
0421:                                                                LogChannels.LC_JSR180,
0422:                                                                "removing"
0423:                                                                        + nextTransaction);
0424:                                            }
0425:                                            removeList
0426:                                                    .addElement(nextTransaction);
0427:                                        } else {
0428:                                            ((ServerTransaction) nextTransaction).collectionTime--;
0429:                                        }
0430:                                        // If this transaction has not
0431:                                        // terminated,
0432:                                    } else {
0433:                                        // Add to the fire list -- needs to be moved
0434:                                        // outside the synchronized block to prevent
0435:                                        // deadlock.
0436:                                        fireList.addElement(nextTransaction);
0437:
0438:                                    }
0439:
0440:                                }
0441:                                for (int j = 0; j < removeList.size(); j++) {
0442:                                    serverTransactions.removeElement(removeList
0443:                                            .elementAt(j));
0444:                                }
0445:                            }
0446:
0447:                            removeList = new Vector();
0448:
0449:                            synchronized (clientTransactions) {
0450:                                transactionIterator = clientTransactions
0451:                                        .elements();
0452:                                while (transactionIterator.hasMoreElements()) {
0453:
0454:                                    nextTransaction = (Transaction) transactionIterator
0455:                                            .nextElement();
0456:
0457:                                    // If the transaction has terminated,
0458:                                    // and SipClientConnection instance,
0459:                                    // associated with it has TERMINATED state
0460:                                    boolean removeTransaction = false;
0461:                                    if (nextTransaction.isTerminated()) {
0462:                                        SipClientConnectionImpl conn = (SipClientConnectionImpl) nextTransaction
0463:                                                .getApplicationData();
0464:                                        if (conn == null) { // no connection
0465:                                            removeTransaction = true;
0466:                                        } else if (conn.getState() == SipClientConnectionImpl.TERMINATED) {
0467:                                            removeTransaction = true;
0468:                                        }
0469:                                    }
0470:                                    if (removeTransaction) {
0471:                                        // Remove it from the set
0472:                                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0473:                                            Logging.report(Logging.INFORMATION,
0474:                                                    LogChannels.LC_JSR180,
0475:                                                    "Removing clientTransaction "
0476:                                                            + nextTransaction);
0477:                                        }
0478:
0479:                                        removeList.addElement(nextTransaction);
0480:
0481:                                        // If this transaction has not
0482:                                        // terminated,
0483:                                    } else {
0484:                                        // Add to the fire list -- needs to be moved
0485:                                        // outside the synchronized block to prevent
0486:                                        // deadlock.
0487:                                        fireList.addElement(nextTransaction);
0488:
0489:                                    }
0490:                                }
0491:                                for (int j = 0; j < removeList.size(); j++) {
0492:                                    clientTransactions.removeElement(removeList
0493:                                            .elementAt(j));
0494:                                }
0495:                            }
0496:                            removeList = new Vector();
0497:
0498:                            synchronized (dialogTable) {
0499:                                Enumeration values = dialogTable.elements();
0500:                                while (values.hasMoreElements()) {
0501:                                    Dialog d = (Dialog) values.nextElement();
0502:                                    // System.out.println("dialogState = " +
0503:                                    // d.getState() +
0504:                                    // " isServer = " + d.isServer());
0505:                                    if (d.getState() == Dialog.TERMINATED_STATE) {
0506:                                        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0507:                                            String dialogId = d.getDialogId();
0508:                                            Logging.report(Logging.INFORMATION,
0509:                                                    LogChannels.LC_JSR180,
0510:                                                    "Removing Dialog "
0511:                                                            + dialogId);
0512:                                        }
0513:
0514:                                        removeList.addElement(d);
0515:                                    }
0516:
0517:                                    if (d.isServer() && (!d.ackSeen)
0518:                                            && d.isInviteDialog()) {
0519:                                        Transaction transaction = d
0520:                                                .getLastTransaction();
0521:                                        // If stack is managing the transaction
0522:                                        // then retransmit the last response.
0523:                                        if (transaction.getState() == Transaction.TERMINATED_STATE
0524:                                                && transaction instanceof  ServerTransaction
0525:                                                && ((ServerTransaction) transaction).isMapped) {
0526:                                            Response response = transaction
0527:                                                    .getLastResponse();
0528:                                            // Retransmit to 200 until ack received.
0529:                                            if (response.getStatusCode() == 200) {
0530:                                                try {
0531:                                                    if (d
0532:                                                            .toRetransmitFinalResponse())
0533:                                                        transaction
0534:                                                                .sendMessage(response);
0535:                                                } catch (IOException ex) {
0536:                                                    /* Will eventully time out */
0537:                                                    d
0538:                                                            .setState(Dialog.TERMINATED_STATE);
0539:                                                } finally {
0540:                                                    // Need to fire the timer so
0541:                                                    // transaction will eventually
0542:                                                    // time out whether or not
0543:                                                    // the IOException occurs
0544:                                                    fireList
0545:                                                            .addElement(transaction);
0546:                                                }
0547:                                            }
0548:                                        }
0549:                                    }
0550:
0551:                                }
0552:                                for (int j = 0; j < removeList.size(); j++) {
0553:                                    Dialog d = (Dialog) removeList.elementAt(j);
0554:                                    dialogTable.remove(d.getDialogId());
0555:                                }
0556:                            }
0557:
0558:                            for (int i = 0; i < fireList.size(); i++) {
0559:                                nextTransaction = (Transaction) fireList
0560:                                        .elementAt(i);
0561:                                nextTransaction.fireTimer();
0562:                            }
0563:
0564:                        } catch (Exception e) {
0565:                            e.printStackTrace();
0566:                            // Ignore
0567:                        }
0568:
0569:                    }
0570:
0571:                }
0572:            }
0573:
0574:            /**
0575:             * Creates or terminates a dialog if a subscription matching the given
0576:             * NOTIFY request exists. To create a dialog a list of transactions
0577:             * is searched for the matching transaction and then the corresponding
0578:             * SipClientConnection is notified. To terminate a dialog a list of
0579:             * dialogs is searched for the existing subscription that matches
0580:             * the given NOTIFY request.
0581:             * @param requestReceived NOTIFY request that may create or terminate
0582:             * a dialog.
0583:             */
0584:            private void createOrTerminateDialog(Request requestReceived) {
0585:                // System.out.println(">>> NOTIFY: Scanning dialogs...");
0586:
0587:                synchronized (dialogTable) {
0588:                    Enumeration e = dialogTable.elements();
0589:
0590:                    while (e.hasMoreElements()) {
0591:                        Dialog nextDialog = (Dialog) e.nextElement();
0592:                        Subscription s = nextDialog.subscriptionList
0593:                                .getMatchingSubscription(requestReceived);
0594:
0595:                        if (s != null) {
0596:                            SubscriptionStateHeader ssh = (SubscriptionStateHeader) requestReceived
0597:                                    .getHeader(Header.SUBSCRIPTION_STATE);
0598:
0599:                            if (ssh != null && ssh.isTerminated()) {
0600:                                nextDialog.subscriptionList
0601:                                        .removeSubscription(s);
0602:                            } else {
0603:                                nextDialog.setState(Dialog.CONFIRMED_STATE);
0604:                            }
0605:
0606:                            return;
0607:                        }
0608:                    }
0609:                }
0610:
0611:                // System.out.println(">>> NOTIFY: Scanning transactions...");
0612:
0613:                // Iterator through all client transactions
0614:                Enumeration transactionIterator;
0615:                ClientTransaction currClientTransaction = null;
0616:
0617:                // Loop through all client transactions
0618:                synchronized (clientTransactions) {
0619:                    transactionIterator = clientTransactions.elements();
0620:                    currClientTransaction = null;
0621:
0622:                    String receivedToTag = requestReceived.getToTag();
0623:                    CallIdHeader receivedCid = requestReceived.getCallId();
0624:                    EventHeader receivedEvent = (EventHeader) requestReceived
0625:                            .getHeader(Header.EVENT);
0626:
0627:                    while (transactionIterator.hasMoreElements()) {
0628:                        currClientTransaction = (ClientTransaction) transactionIterator
0629:                                .nextElement();
0630:                        Request request = currClientTransaction.getRequest();
0631:                        String method = request.getMethod();
0632:                        String fromTag = request.getFromHeaderTag();
0633:                        CallIdHeader cid = request.getCallId();
0634:                        EventHeader hEvent = (EventHeader) request
0635:                                .getHeader(Header.EVENT);
0636:                        boolean isSameEvent = (hEvent != null)
0637:                                && hEvent.match(receivedEvent);
0638:
0639:                        if (((method.equals(Request.SUBSCRIBE) && isSameEvent) || method
0640:                                .equals(Request.REFER))
0641:                                && fromTag != null
0642:                                && fromTag.equals(receivedToTag)
0643:                                && cid != null
0644:                                && cid.equals(receivedCid)) {
0645:
0646:                            SipClientConnectionImpl sipClientConnection = (SipClientConnectionImpl) currClientTransaction
0647:                                    .getApplicationData();
0648:
0649:                            if (sipClientConnection != null) {
0650:                                sipClientConnection
0651:                                        .handleMatchingNotify(requestReceived);
0652:                            } else {
0653:                                if (Logging.REPORT_LEVEL <= Logging.WARNING) {
0654:                                    Logging
0655:                                            .report(
0656:                                                    Logging.WARNING,
0657:                                                    LogChannels.LC_JSR180,
0658:                                                    "SIPTransactionStack.createOrTerminateDialog(): "
0659:                                                            + "Cannot find SCC for the given NOTIFY.");
0660:                                }
0661:                            }
0662:
0663:                            break;
0664:                        }
0665:                    }
0666:                }
0667:            }
0668:
0669:            /**
0670:             * Handles a new SIP request.
0671:             * It finds a server transaction to handle
0672:             * this message. If none exists, it creates a new transaction.
0673:             * @param requestReceived Request to handle.
0674:             * @param requestMessageChannel Channel that received message.
0675:             * @return A server transaction.
0676:             */
0677:            protected SIPServerRequestInterface newSIPServerRequest(
0678:                    Request requestReceived,
0679:                    MessageChannel requestMessageChannel) {
0680:
0681:                try {
0682:                    // Iterator through all server transactions
0683:                    Enumeration transactionIterator;
0684:                    // Next transaction in the set
0685:                    ServerTransaction nextTransaction;
0686:                    // Transaction to handle this request
0687:                    ServerTransaction currentTransaction = null;
0688:
0689:                    if (requestReceived.getMethod().equals(Request.NOTIFY)) {
0690:                        createOrTerminateDialog(requestReceived);
0691:                    }
0692:
0693:                    // Loop through all server transactions
0694:                    synchronized (serverTransactions) {
0695:                        transactionIterator = serverTransactions.elements();
0696:                        currentTransaction = null;
0697:                        while (transactionIterator.hasMoreElements()
0698:                                && currentTransaction == null) {
0699:
0700:                            nextTransaction = (ServerTransaction) transactionIterator
0701:                                    .nextElement();
0702:
0703:                            // If this transaction should handle this request,
0704:                            if (!nextTransaction.isTerminated()
0705:                                    && nextTransaction
0706:                                            .isMessagePartOfTransaction(requestReceived)) {
0707:                                // Mark this transaction as the one
0708:                                // to handle this message
0709:                                currentTransaction = nextTransaction;
0710:                            }
0711:                        }
0712:
0713:                        // If no transaction exists to handle this message
0714:                        if (currentTransaction == null) {
0715:                            currentTransaction = createServerTransaction(requestMessageChannel);
0716:                            currentTransaction
0717:                                    .setOriginalRequest(requestReceived);
0718:                            if (!isDialogCreated(requestReceived.getMethod())) {
0719:                                /*
0720:                                 * IMPL_NOTE: remove the following block of code
0721:                                 *       after ensuring that it doesn't break anything.
0722:                                 */
0723:
0724:                                /*
0725:                                // Dialog is not created - can we find the state?
0726:                                // If so, then create a transaction and add it.
0727:                                String dialogId = requestReceived.getDialogId(true);
0728:                                Dialog dialog = getDialog(dialogId);
0729:                                // Sequence numbers are supposed to increment.
0730:                                // avoid processing old sequence numbers and
0731:                                // delivering the same request up to the
0732:                                // application if the request has already been seen.
0733:                                // Special handling applies to ACK processing.
0734:                                if (dialog != null &&
0735:                                    (requestReceived.getMethod().equals(Request.ACK)
0736:                                        || requestReceived.getCSeqHeader()
0737:                                            .getSequenceNumber() >
0738:                                                dialog.getRemoteSequenceNumber())) {
0739:                                    // Found a dialog.
0740:                                    if (Logging.REPORT_LEVEL <=
0741:                                            Logging.INFORMATION) {
0742:                                        Logging.report(Logging.INFORMATION,
0743:                                            LogChannels.LC_JSR180,
0744:                                            "adding server transaction " +
0745:                                            currentTransaction);
0746:                                    }
0747:
0748:                                    serverTransactions.addElement(currentTransaction);
0749:                                    currentTransaction.isMapped = true;
0750:                                }
0751:                                 */
0752:
0753:                                // Server transactions must always be added
0754:                                // to the corresponding vector.
0755:                                serverTransactions
0756:                                        .addElement(currentTransaction);
0757:                                currentTransaction.isMapped = true;
0758:                            } else {
0759:                                // Create the transaction but dont map it.
0760:                                String dialogId = requestReceived
0761:                                        .getDialogId(true);
0762:                                Dialog dialog = getDialog(dialogId);
0763:                                // This is a dialog creating request that is
0764:                                // part of an existing dialog
0765:                                // (eg. re-Invite). Re-invites get a non null
0766:                                // server transaction Id (unlike the original
0767:                                // invite).
0768:                                if (dialog != null
0769:                                        && requestReceived.getCSeqHeader()
0770:                                                .getSequenceNumber() > dialog
0771:                                                .getRemoteSequenceNumber()) {
0772:                                    try {
0773:                                        currentTransaction.map();
0774:                                    } catch (IOException ex) {
0775:                                        /* Ignore */
0776:                                    }
0777:                                }
0778:
0779:                                serverTransactions
0780:                                        .addElement(currentTransaction);
0781:                                currentTransaction.toListener = true;
0782:                            }
0783:                        }
0784:                        // attach to request
0785:                        requestReceived.setTransaction(currentTransaction);
0786:
0787:                        // Set ths transaction's encapsulated request
0788:                        // interface from the superclass
0789:                        currentTransaction.setRequestInterface(super 
0790:                                .newSIPServerRequest(requestReceived,
0791:                                        currentTransaction));
0792:
0793:                        return currentTransaction;
0794:                    }
0795:                } catch (RuntimeException ex) {
0796:                    ex.printStackTrace();
0797:                    throw ex;
0798:                }
0799:
0800:            }
0801:
0802:            /**
0803:             * Handles a new SIP response.
0804:             * It finds a client transaction to handle
0805:             * this message. If none exists, it sends the message directly to the
0806:             * superclass.
0807:             * @param responseReceived Response to handle.
0808:             * @param responseMessageChannel Channel that received message.
0809:             * @return A client transaction.
0810:             */
0811:            SIPServerResponseInterface newSIPServerResponse(
0812:                    Response responseReceived,
0813:                    MessageChannel responseMessageChannel) {
0814:                // System.out.println("response = " + responseReceived.encode());
0815:                // Iterator through all client transactions
0816:                Enumeration transactionIterator;
0817:                // Next transaction in the set
0818:                ClientTransaction nextTransaction;
0819:                // Transaction to handle this request
0820:                ClientTransaction currentTransaction;
0821:
0822:                // Loop through all client transactions
0823:                synchronized (clientTransactions) {
0824:                    transactionIterator = clientTransactions.elements();
0825:                    currentTransaction = null;
0826:                    int i = -1;
0827:                    while (transactionIterator.hasMoreElements()
0828:                            && currentTransaction == null) {
0829:                        i++;
0830:                        nextTransaction = (ClientTransaction) transactionIterator
0831:                                .nextElement();
0832:                        // If this transaction should handle this request,
0833:                        if (nextTransaction
0834:                                .isMessageTransOrMult(responseReceived)) {
0835:                            if (nextTransaction
0836:                                    .isMultipleResponse(responseReceived)) {
0837:                                // RFC 3261, 13.2.2.4:
0838:                                // Multiple 2xx responses may arrive at the UAC for
0839:                                // a single INVITE request due to a forking proxy.
0840:                                // create a new client transaction
0841:                                currentTransaction = nextTransaction
0842:                                        .cloneWithNewLastResponse(responseReceived);
0843:                                currentTransaction
0844:                                        .setState(Transaction.PROCEEDING_STATE);
0845:                                currentTransaction
0846:                                        .setApplicationData(nextTransaction
0847:                                                .getApplicationData());
0848:                                Dialog dialog = new Dialog(currentTransaction);
0849:                                dialog.setDialogId(responseReceived
0850:                                        .getDialogId(false));
0851:                                dialog
0852:                                        .setRemoteTag(responseReceived
0853:                                                .getToTag());
0854:                                dialog.setStack(this );
0855:                                putDialog(dialog);
0856:                                currentTransaction.setDialog(dialog);
0857:                                // change from old to new transaction
0858:                                clientTransactions.setElementAt(
0859:                                        currentTransaction, i);
0860:                            } else { // not multiple response
0861:                                // Mark this transaction as the one to
0862:                                // handle this message
0863:                                currentTransaction = nextTransaction;
0864:                            }
0865:
0866:                        }
0867:                    }
0868:                }
0869:                // If no transaction exists to handle this message,
0870:                if (currentTransaction == null) {
0871:                    // Pass the message directly to the TU
0872:                    return super .newSIPServerResponse(responseReceived,
0873:                            responseMessageChannel);
0874:                }
0875:                // Set ths transaction's encapsulated response interface
0876:                // from the superclass
0877:                currentTransaction.setResponseInterface(super 
0878:                        .newSIPServerResponse(responseReceived,
0879:                                currentTransaction));
0880:                return currentTransaction;
0881:            }
0882:
0883:            /**
0884:             * Creates a client transaction to handle a new request.
0885:             * Gets the real
0886:             * message channel from the superclass, and then creates a new client
0887:             * transaction wrapped around this channel.
0888:             * @param nextHop Hop to create a channel to contact.
0889:             * @return the requested message channel
0890:             */
0891:            public MessageChannel createMessageChannel(Hop nextHop) {
0892:                synchronized (clientTransactions) {
0893:                    // New client transaction to return
0894:                    Transaction returnChannel;
0895:
0896:                    // Create a new client transaction around the
0897:                    // superclass' message channel
0898:                    MessageChannel mc = super .createMessageChannel(nextHop);
0899:                    if (mc == null)
0900:                        return null;
0901:                    returnChannel = createClientTransaction(mc);
0902:                    clientTransactions.addElement(returnChannel);
0903:                    ((ClientTransaction) returnChannel).setViaPort(nextHop
0904:                            .getPort());
0905:                    ((ClientTransaction) returnChannel).setViaHost(nextHop
0906:                            .getHost());
0907:                    return returnChannel;
0908:                }
0909:            }
0910:
0911:            /**
0912:             * Creates a client transaction from a raw channel.
0913:             * @param rawChannel is the transport channel to encapsulate.
0914:             * @return the requested message channel
0915:             */
0916:            public MessageChannel createMessageChannel(MessageChannel rawChannel) {
0917:                synchronized (clientTransactions) {
0918:                    // New client transaction to return
0919:                    Transaction returnChannel = createClientTransaction(rawChannel);
0920:                    clientTransactions.addElement(returnChannel);
0921:                    ((ClientTransaction) returnChannel).setViaPort(rawChannel
0922:                            .getViaPort());
0923:                    ((ClientTransaction) returnChannel).setViaHost(rawChannel
0924:                            .getHost());
0925:                    return returnChannel;
0926:                }
0927:            }
0928:
0929:            /**
0930:             * Creates a client transaction from a raw channel.
0931:             * @param transaction the requested transaction
0932:             * @return the requested message channel
0933:             */
0934:            public MessageChannel createMessageChannel(Transaction transaction) {
0935:                synchronized (clientTransactions) {
0936:                    // New client transaction to return
0937:                    Transaction returnChannel = createClientTransaction(transaction
0938:                            .getMessageChannel());
0939:                    clientTransactions.addElement(returnChannel);
0940:                    ((ClientTransaction) returnChannel).setViaPort(transaction
0941:                            .getViaPort());
0942:                    ((ClientTransaction) returnChannel).setViaHost(transaction
0943:                            .getViaHost());
0944:                    return returnChannel;
0945:                }
0946:            }
0947:
0948:            /**
0949:             * Creates a client transaction that encapsulates a MessageChannel.
0950:             * Useful for implementations that want to subclass the standard
0951:             * @param encapsulatedMessageChannel
0952:             * Message channel of the transport layer.
0953:             * @return the requested client transaction
0954:             */
0955:            public ClientTransaction createClientTransaction(
0956:                    MessageChannel encapsulatedMessageChannel) {
0957:
0958:                return new ClientTransaction(this , encapsulatedMessageChannel);
0959:
0960:            }
0961:
0962:            /**
0963:             * Creates a server transaction that encapsulates a MessageChannel.
0964:             * Useful for implementations that want to subclass the standard
0965:             * @param encapsulatedMessageChannel
0966:             * Message channel of the transport layer.
0967:             * @return the requested server transaction
0968:             */
0969:            public ServerTransaction createServerTransaction(
0970:                    MessageChannel encapsulatedMessageChannel) {
0971:
0972:                return new ServerTransaction(this , encapsulatedMessageChannel);
0973:            }
0974:
0975:            /**
0976:             * Creates a raw message channel. A raw message channel has no
0977:             * transaction wrapper.
0978:             * @param hop hop for which to create the raw message channel.
0979:             * @return the requested message channel
0980:             */
0981:            public MessageChannel createRawMessageChannel(Hop hop) {
0982:                return super .createMessageChannel(hop);
0983:            }
0984:
0985:            /**
0986:             * Adds a new client transaction to the set of existing transactions.
0987:             * @param clientTransaction -- client transaction to add to the set.
0988:             */
0989:            public void addTransaction(ClientTransaction clientTransaction) {
0990:                synchronized (clientTransactions) {
0991:                    clientTransactions.addElement(clientTransaction);
0992:                }
0993:            }
0994:
0995:            /**
0996:             * Adds a new client transaction to the set of existing transactions.
0997:             * @param serverTransaction -- server transaction to add to the set.
0998:             */
0999:            public void addTransaction(ServerTransaction serverTransaction)
1000:                    throws IOException {
1001:                synchronized (serverTransactions) {
1002:                    this.serverTransactions.addElement(serverTransaction);
1003:                }
1004:            }
1005:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.