Source Code Cross Referenced for SipProvider.java in  » 6.0-JDK-Modules » j2me » gov » nist » siplite » 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 
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;
026:
027:        import java.util.*;
028:        import java.io.*;
029:        import javax.microedition.sip.SipException;
030:
031:        import gov.nist.siplite.header.*;
032:        import gov.nist.siplite.message.*;
033:        import gov.nist.siplite.stack.*;
034:        import gov.nist.core.*;
035:        import gov.nist.siplite.address.*;
036:
037:        import com.sun.midp.log.Logging;
038:        import com.sun.midp.log.LogChannels;
039:
040:        /**
041:         * Implementation of the JAIN-SIP provider interface.
042:         *
043:         * @version  JAIN-SIP-1.1
044:         *
045:         * <a href="{@docRoot}/uncopyright.html">
046:         * This code is in the public domain.</a>
047:         *
048:         */
049:        public final class SipProvider implements  SIPTransactionEventListener {
050:            /** Current SIP listener. */
051:            protected SipListener sipListener;
052:            /** Flag to indicate the provider is active. */
053:            protected boolean isActive;
054:            /** Current SIP Stack context. */
055:            protected SipStack sipStack;
056:            /** Current event listening filter. */
057:            protected ListeningPoint listeningPoint;
058:            /** Curent server transactions. */
059:            protected ServerTransaction currentTransaction;
060:            /** Curent event scanner processor. */
061:            private EventScanner eventScanner;
062:
063:            /**
064:             * Stops processing messages for this provider. Post an empty
065:             * message to our message processing queue that signals us to
066:             * quit.
067:             */
068:            protected void stop() {
069:                // Put an empty event in the queue and post ourselves a message.
070:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
071:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
072:                            "Exiting provider");
073:                }
074:
075:                synchronized (this ) {
076:                    listeningPoint.removeSipProvider();
077:                }
078:
079:                this .eventScanner.stop();
080:            }
081:
082:            /**
083:             * Handles the SIP event - because we have only one listener and we are
084:             * already in the context of a separate thread, we dont need to enque
085:             * the event and signal another thread.
086:             *
087:             * @param sipEvent is the event to process.
088:             * @param transaction the current transaction
089:             *
090:             */
091:            public void handleEvent(SipEvent sipEvent, Transaction transaction) {
092:
093:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
094:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
095:                            "handleEvent " + sipEvent + "currentTransaction = "
096:                                    + transaction + "this.sipListener = "
097:                                    + this .sipListener);
098:                }
099:
100:                if (this .sipListener == null)
101:                    return;
102:
103:                EventWrapper eventWrapper = new EventWrapper();
104:                eventWrapper.sipEvent = sipEvent;
105:                eventWrapper.transaction = transaction;
106:
107:                if (transaction != null
108:                        && transaction instanceof  ClientTransaction) {
109:                    ((ClientTransaction) transaction).setEventPending();
110:                }
111:
112:                this .eventScanner.addEvent(eventWrapper);
113:            }
114:
115:            /**
116:             * Creates a new instance of SipProvider.
117:             * @param sipStack the current SIP stack context
118:             */
119:            protected SipProvider(SipStack sipStack) {
120:                this .sipStack = sipStack;
121:                this .eventScanner = sipStack.eventScanner;
122:            }
123:
124:            /**
125:             * Compares to this instance for equivalence.
126:             * @param obj object for comparison
127:             * @return true if the object is the same
128:             */
129:            public boolean equals(Object obj) {
130:                return super .equals(obj);
131:            }
132:
133:            /**
134:             * This method registers the SipListener object to this SipProvider, once
135:             * registered the SIP Listener can send events on the SipProvider and
136:             * recieve events emitted from the SipProvider. As JAIN SIP resticts a
137:             * unicast Listener special case, that is, that one and only one Listener
138:             * may be registered on the SipProvider concurrently.
139:             * <p>
140:             * If an attempt is made to re-register the existing SipListener this
141:             * method returns silently. A previous SipListener must be removed from the
142:             * SipProvider before another SipListener can be registered to
143:             * the SipProvider.
144:             *
145:             * @param sipListener to be registered with the
146:             * Provider.
147:             * @throws TooManyListenersException this exception is thrown when a new
148:             * SipListener attempts to register with the SipProvider when another
149:             * SipListener is already registered with this SipProvider.
150:             *
151:             */
152:            public void addSipListener(SipListener sipListener)
153:                    throws TooManyListenersException {
154:
155:                synchronized (sipStack) {
156:                    Enumeration it = sipStack.getSipProviders();
157:                    while (it.hasMoreElements()) {
158:                        SipProvider provider = (SipProvider) it.nextElement();
159:                        if (provider.sipListener != null
160:                                && provider.sipListener != sipListener)
161:                            throw new TooManyListenersException();
162:                    }
163:                }
164:
165:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
166:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
167:                            "add SipListener " + sipListener);
168:                }
169:
170:                this .sipListener = sipListener;
171:                sipStack.sipListener = sipListener;
172:
173:                synchronized (sipStack) {
174:                    Enumeration it = sipStack.getSipProviders();
175:                    while (it.hasMoreElements()) {
176:                        SipProvider provider = (SipProvider) it.nextElement();
177:                        provider.sipListener = sipListener;
178:                    }
179:                }
180:            }
181:
182:            /**
183:             * Returns the ListeningPoint of this SipProvider.
184:             * A SipProvider has a single Listening Point at any specific point in time.
185:             *
186:             * @see ListeningPoint
187:             * @return the ListeningPoint of this SipProvider
188:             */
189:            public ListeningPoint getListeningPoint() {
190:                return this .listeningPoint;
191:            }
192:
193:            /**
194:             * Returns a unique CallIdHeader for identifying dialogues between two
195:             * SIP applications.
196:             *
197:             * @return new CallId unique within the SIP Stack.
198:             */
199:            public CallIdHeader getNewCallId() {
200:                String callId = SIPUtils.generateCallIdentifier(this 
201:                        .getSipStack().getIPAddress());
202:                CallIdHeader callid = new CallIdHeader();
203:                callid.setCallId(callId);
204:                return callid;
205:
206:            }
207:
208:            /**
209:             * Once an application wants to a send a new request it must first request
210:             * a new client transaction identifier. This method is called by an
211:             * application to create the client transaction befores it sends the Request
212:             * via the SipProvider on that transaction. This methods returns a new
213:             * unique client transaction identifier that can be passed to the stateful
214:             * sendRequest method on the SipProvider and the sendAck/sendBye
215:             * methods on the Dialog in order to send a request.
216:             *
217:             * @param request the new Request message that is to handled
218:             * statefully by the Provider.
219:             * @return a new unique client transation identifier
220:             * @see ClientTransaction
221:             * @since v1.1
222:             */
223:            public ClientTransaction getNewClientTransaction(Request request)
224:                    throws TransactionUnavailableException {
225:                if (request == null) {
226:                    throw new NullPointerException("null request");
227:                }
228:
229:                if (request.getTransaction() != null) {
230:                    throw new TransactionUnavailableException(
231:                            "Transaction already assigned to request");
232:                }
233:
234:                if (request.getMethod().equals(Request.CANCEL)) {
235:                    ClientTransaction ct = (ClientTransaction) sipStack
236:                            .findCancelTransaction(request, false);
237:
238:                    if (ct != null) {
239:                        ClientTransaction retval = sipStack
240:                                .createClientTransaction(ct.getMessageChannel());
241:                        ((Transaction) retval).setOriginalRequest(request);
242:                        ((Transaction) retval).addEventListener(this );
243:                        sipStack.addTransaction((ClientTransaction) retval);
244:                        ((ClientTransaction) retval).setDialog((Dialog) ct
245:                                .getDialog());
246:                        return retval;
247:                    }
248:
249:                }
250:
251:                if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
252:                    Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
253:                            "could not find existing transaction for "
254:                                    + request.getFirstLine());
255:                }
256:
257:                String dialogId = request.getDialogId(false);
258:                Dialog dialog = sipStack.getDialog(dialogId);
259:                // isDialog - is request sends inside dialog
260:                boolean isDialog = false;
261:                if (dialog != null) {
262:                    int dialogState = dialog.getState();
263:                    if (dialogState == Dialog.EARLY_STATE
264:                            || dialogState == Dialog.CONFIRMED_STATE
265:                            || dialogState == Dialog.COMPLETED_STATE) {
266:                        isDialog = true;
267:                    }
268:                }
269:                Enumeration it = sipStack.getRouter().getNextHops(request,
270:                        isDialog);
271:
272:                if (it == null || !it.hasMoreElements()) {
273:                    // could not route the request as out of dialog.
274:                    // maybe the user has no router or the router cannot resolve
275:                    // the route.
276:                    // If this is part of a dialog then use the route from the dialog
277:                    if (dialog != null) {
278:                        try {
279:                            Hop hop = dialog.getNextHop();
280:
281:                            if (hop != null) {
282:                                ClientTransaction ct = null;
283:
284:                                ct = (ClientTransaction) sipStack
285:                                        .createMessageChannel(hop);
286:
287:                                String branchId = SIPUtils.generateBranchId();
288:
289:                                if (request.getTopmostVia() != null) {
290:                                    request.getTopmostVia().setBranch(branchId);
291:                                } else {
292:                                    // Find a message processor to assign this
293:                                    // transaction to.
294:                                    MessageProcessor messageProcessor = this .listeningPoint.messageProcessor;
295:                                    ViaHeader via = messageProcessor
296:                                            .getViaHeader();
297:                                    request.addHeader(via);
298:                                }
299:
300:                                ct.setOriginalRequest(request);
301:                                ct.setBranch(branchId);
302:                                ct.setDialog(dialog);
303:                                ct.addEventListener(this );
304:
305:                                return ct;
306:                            } // end if
307:                        } catch (Exception ex) {
308:                            throw new TransactionUnavailableException(ex
309:                                    .getMessage());
310:                        }
311:                    } else {
312:                        throw new TransactionUnavailableException("no route!");
313:                    }
314:                } else {
315:                    try {
316:                        // An out of dialog route was found. Assign this to the
317:                        // client transaction.
318:                        while (it.hasMoreElements()) {
319:                            Hop hop = (Hop) it.nextElement();
320:
321:                            ClientTransaction ct = null;
322:
323:                            ct = (ClientTransaction) sipStack
324:                                    .createMessageChannel(hop);
325:
326:                            // ClientTransaction ct =
327:                            //   (ClientTransaction) sipStack.createMessageChannel(hop);
328:
329:                            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
330:                                Logging.report(Logging.INFORMATION,
331:                                        LogChannels.LC_JSR180, "hop = " + hop
332:                                                + "ct " + ct);
333:                            }
334:
335:                            if (ct == null)
336:                                continue;
337:
338:                            String branchId = SIPUtils.generateBranchId();
339:
340:                            if (request.getTopmostVia() != null) {
341:                                request.getTopmostVia().setBranch(branchId);
342:                            } else {
343:                                // Find a message processor to assign
344:                                // this transaction to.
345:                                MessageProcessor messageProcessor = listeningPoint.messageProcessor;
346:                                ViaHeader via = messageProcessor.getViaHeader();
347:                                request.addHeader(via);
348:                            }
349:
350:                            ct.setOriginalRequest(request);
351:                            ct.setBranch(branchId);
352:
353:                            if (sipStack.isDialogCreated(request.getMethod())) {
354:                                // create a new dialog to contain this transaction
355:                                // provided this is necessary.
356:                                // This could be a re-invite
357:                                // (noticed by Brad Templeton)
358:
359:                                if (dialog != null) {
360:                                    ct.setDialog(dialog);
361:                                } else {
362:                                    sipStack.createDialog(ct);
363:                                }
364:                            } else {
365:                                ct.setDialog(dialog);
366:                            }
367:
368:                            // The provider is the event listener for all transactions.
369:                            ct.addEventListener(this );
370:                            return (ClientTransaction) ct;
371:                        } // end while()
372:                    } catch (SipException ex) {
373:                        throw new TransactionUnavailableException(ex
374:                                .getMessage());
375:                    }
376:                } // end else
377:
378:                throw new TransactionUnavailableException(
379:                        "Could not create transaction - could not resolve next hop! ");
380:            }
381:
382:            /**
383:             * An application has the responsibility of deciding to respond to a
384:             * Request that does not match an existing server transaction. The method
385:             * is called by an application that decides to respond to an unmatched
386:             * Request statefully. This methods return a new unique server transaction
387:             * identifier that can be passed to the stateful sendResponse methods in
388:             * order to respond to the request.
389:             *
390:             * @param request the initial Request message that the doesn't
391:             * match an existing
392:             * transaction that the application decides to handle statefully.
393:             * @return a new unique server transation identifier
394:             * @throws TransactionAlreadyExistsException if a transaction already exists
395:             * that is already handling this Request. This may happen if the application
396:             * gets retransmits of the same request before the initial transaction is
397:             * allocated.
398:             * @see ServerTransaction
399:             * @since v1.1
400:             */
401:            public ServerTransaction getNewServerTransaction(Request request)
402:                    throws TransactionAlreadyExistsException,
403:                    TransactionUnavailableException {
404:
405:                try {
406:                    ServerTransaction transaction = null;
407:                    Request sipRequest = (Request) request;
408:                    if (sipStack.isDialogCreated(sipRequest.getMethod())) {
409:                        if (sipStack.findTransaction((Request) request, true) != null)
410:                            throw new TransactionAlreadyExistsException(
411:                                    "server transaction already exists!");
412:                        transaction = (ServerTransaction) this .currentTransaction;
413:                        if (transaction == null)
414:                            throw new TransactionUnavailableException(
415:                                    "Transaction not available");
416:                        if (!transaction
417:                                .isMessagePartOfTransaction((Request) request)) {
418:                            throw new TransactionUnavailableException(
419:                                    "Request Mismatch");
420:                        }
421:                        transaction.setOriginalRequest(sipRequest);
422:                        try {
423:                            sipStack.addTransaction(transaction);
424:                        } catch (IOException ex) {
425:                            throw new TransactionUnavailableException(
426:                                    "Error sending provisional response");
427:                        }
428:                        equipADialogForTransaction(transaction, sipRequest);
429:                    } else {
430:                        transaction = (ServerTransaction) sipStack
431:                                .findTransaction((Request) request, true);
432:                        if (transaction != null)
433:                            throw new TransactionAlreadyExistsException(
434:                                    "Transaction exists! ");
435:                        transaction = (ServerTransaction) this .currentTransaction;
436:                        if (transaction == null)
437:                            throw new TransactionUnavailableException(
438:                                    "Transaction not available!");
439:                        if (!transaction
440:                                .isMessagePartOfTransaction((Request) request))
441:                            throw new TransactionUnavailableException(
442:                                    "Request Mismatch");
443:                        transaction.setOriginalRequest(sipRequest);
444:                        // Map the transaction.
445:                        try {
446:                            sipStack.addTransaction(transaction);
447:                        } catch (IOException ex) {
448:                            throw new TransactionUnavailableException(
449:                                    "Could not send back provisional response!");
450:                        }
451:                        String dialogId = sipRequest.getDialogId(true);
452:                        Dialog dialog = sipStack.getDialog(dialogId);
453:                        if (dialog != null) {
454:                            dialog.addTransaction(transaction);
455:                            dialog.addRoute(sipRequest);
456:                        }
457:                    }
458:                    return transaction;
459:                } catch (RuntimeException ex) {
460:                    ex.printStackTrace();
461:                    throw ex;
462:                }
463:            }
464:
465:            /**
466:             * Find or create a dialog with the dialog-id obtained from the request.
467:             * Initializing the dialog's route information.
468:             * Bind the dialog and the transaction to each other.
469:             * @param transaction trasaction for the request
470:             * @param sipRequest request whose tags are the source of dialog-ID
471:             *                   and route information
472:             */
473:            public void equipADialogForTransaction(
474:                    ServerTransaction transaction, Request sipRequest) {
475:                // So I can handle timeouts.
476:                // IMPL_NOTE: do we need it here, or in the calling code?
477:                transaction.addEventListener(this );
478:
479:                String dialogId = sipRequest.getDialogId(true);
480:                Dialog dialog = sipStack.getDialog(dialogId);
481:
482:                if (dialog == null) {
483:                    dialog = sipStack.createDialog(transaction);
484:                }
485:
486:                dialog.setStack(this .sipStack);
487:                dialog.addRoute(sipRequest);
488:
489:                if (dialog.getRemoteTag() != null
490:                        && dialog.getLocalTag() != null) {
491:                    this .sipStack.putDialog(dialog);
492:                }
493:
494:                transaction.setDialog(dialog);
495:            }
496:
497:            /**
498:             * Returns the SipStack that this SipProvider is attached to. A SipProvider
499:             * can only be attached to a single SipStack object which belongs to
500:             * the same SIP stack as the SipProvider.
501:             *
502:             * @see SipStack
503:             * @return the attached SipStack.
504:             */
505:            public SipStack getSipStack() {
506:                return this .sipStack;
507:            }
508:
509:            /**
510:             * Removes the SipListener from this SipProvider. This method returns
511:             * silently if the <var>sipListener</var> argument is not registered
512:             * with the SipProvider.
513:             *
514:             * @param sipListener - the SipListener to be removed from this
515:             * SipProvider
516:             */
517:            public void removeSipListener(SipListener sipListener) {
518:                if (sipListener == this .sipListener) {
519:                    this .sipListener = null;
520:                }
521:            }
522:
523:            /**
524:             * Sends specified Request and returns void i.e.
525:             * no transaction record is associated with this action. This method
526:             * implies that the application is functioning statelessly specific to this
527:             * Request, hence the underlying SipProvider acts statelessly.
528:             * <p>
529:             * Once the Request message has been passed to this method, the SipProvider
530:             * will forget about this Request. No transaction semantics will be
531:             * associated with the Request and no retranmissions will occur on the
532:             * Request by the SipProvider, if these semantics are required it is the
533:             * responsibility of the application not the JAIN SIP Stack.
534:             * <ul>
535:             * <li>Stateless Proxy - A stateless proxy simply forwards every request
536:             *  it receives downstream and discards information about the request
537:             *  message once the message has been forwarded. A stateless proxy does not
538:             *  have any notion of a transaction.
539:             * </ul>
540:             *
541:             * @since v1.1
542:             * @see Request
543:             * @param request - the Request message to send statelessly
544:             * @throws SipException if implementation cannot send request for any reason
545:             */
546:            public void sendRequest(Request request) throws SipException {
547:                // request sends out of dialog
548:                Enumeration it = sipStack.getRouter().getNextHops(request,
549:                        false);
550:                if (it == null || !it.hasMoreElements()) {
551:                    throw new SipException("could not determine next hop!",
552:                            SipException.GENERAL_ERROR);
553:                }
554:
555:                // Will slow down the implementation because it involves
556:                // a search to see if a transaction exists.
557:                // Just to double check adding some assertion
558:                // checking under debug.
559:                Transaction tr = sipStack.findTransaction(request, false);
560:                if (tr != null) {
561:                    throw new SipException(
562:                            "Cannot send: stateless Transaction found!",
563:                            SipException.GENERAL_ERROR);
564:                }
565:
566:                while (it.hasMoreElements()) {
567:                    Hop nextHop = (Hop) it.nextElement();
568:
569:                    Request sipRequest = request;
570:                    String bid = sipRequest.getTransactionId();
571:                    ViaHeader via = sipRequest.getTopmostVia();
572:                    via.setBranch(bid);
573:                    Request newRequest;
574:
575:                    // Do not create a transaction for this request. If it has
576:                    // Mutliple route headers then take the first one off the
577:                    // list and copy into the request URI.
578:                    if (sipRequest.getHeader(Header.ROUTE) != null) {
579:                        newRequest = (Request) sipRequest.clone();
580:                        Enumeration rl = newRequest.getHeaders(Header.ROUTE);
581:                        RouteHeader route = (RouteHeader) rl.nextElement();
582:                        newRequest.setRequestURI(route.getAddress().getURI());
583:                        sipRequest.removeHeader(Header.ROUTE, true);
584:                    } else {
585:                        newRequest = sipRequest;
586:                    }
587:
588:                    MessageChannel messageChannel = sipStack
589:                            .createRawMessageChannel(nextHop);
590:                    try {
591:                        if (messageChannel != null) {
592:                            messageChannel.sendMessage((Message) newRequest);
593:                            return;
594:                        } else {
595:                            throw new SipException(
596:                                    "Could not forward request.",
597:                                    SipException.GENERAL_ERROR);
598:                        }
599:
600:                    } catch (IOException ex) {
601:                        continue;
602:                    }
603:                }
604:            }
605:
606:            /**
607:             * Sends specified {@link Response} and returns void i.e.
608:             * no transaction record is associated with this action. This method implies
609:             * that the application is functioning as either a stateless proxy or a
610:             * stateless User Agent Server.
611:             * <ul>
612:             *  <li> Stateless proxy - A stateless proxy simply forwards every response
613:             *  it receives upstream and discards information about the response message
614:             *  once the message has been forwarded. A stateless proxy does not
615:             *  have any notion of a transaction.
616:             *  <li>Stateless User Agent Server - A stateless UAS does not maintain
617:             *  transaction state. It replies to requests normally, but discards
618:             *  any state that would ordinarily be retained by a UAS after a response
619:             *  has been sent.  If a stateless UAS receives a retransmission of a
620:             *  request, it regenerates the response and resends it, just as if it
621:             *  were replying to the first instance of the request. A UAS cannot be
622:             *  stateless unless the request processing for that method would always
623:             *  result in the same response if the requests are identical. Stateless
624:             *  UASs do not use a transaction layer; they receive requests directly
625:             *  from the transport layer and send responses directly to the transport
626:             *  layer.
627:             * </ul>
628:             *
629:             * @see Response
630:             * @param sipResponse the Response to send statelessly.
631:             * @throws IOException if I/O error occured
632:             * @throws SipException if implementation cannot send response for
633:             * any other reason
634:             * @see Response
635:             * @since v1.1
636:             */
637:            public void sendResponse(Response sipResponse) throws IOException,
638:                    SipException {
639:                ViaHeader via = sipResponse.getTopmostVia();
640:                if (via == null) {
641:                    throw new SipException("No via header in response!",
642:                            SipException.INVALID_MESSAGE);
643:                }
644:
645:                int port = via.getPort();
646:                String transport = via.getTransport();
647:                // check to see if Via has "received paramaeter". If so
648:                // set the host to the via parameter. Else set it to the
649:                // Via host.
650:                String host = via.getReceived();
651:
652:                if (host == null) {
653:                    host = via.getHost();
654:                }
655:
656:                if (port == -1) {
657:                    port = 5060; // IMPL_NOTE: move to SIPConstants
658:                }
659:
660:                Hop hop = new Hop(host + ":" + port + "/" + transport);
661:                MessageChannel messageChannel = sipStack
662:                        .createRawMessageChannel(hop);
663:                messageChannel.sendMessage(sipResponse);
664:            }
665:
666:            /**
667:             * This method sets the listening point of the SipProvider.
668:             * A SipProvider can only have a single listening point at any
669:             * specific time. This method returns
670:             * silently if the same <var>listeningPoint</var> argument is re-set
671:             * on the SipProvider.
672:             * <p>
673:             * JAIN SIP supports recieving messages from
674:             * any port and interface that a server listens on for UDP, on that same
675:             * port and interface for TCP in case a message may need to be sent
676:             * using TCP, rather than UDP, if it is too large. In order to satisfy this
677:             * functionality an application must create two SipProviders and set
678:             * identical listeningPoints except for transport on each SipProvder.
679:             * <p>
680:             * Multiple SipProviders are prohibited to listen on the same
681:             * listening point.
682:             *
683:             * @param listeningPoint of this SipProvider
684:             * @see ListeningPoint
685:             * @since v1.1
686:             */
687:            public void setListeningPoint(ListeningPoint listeningPoint) {
688:                if (listeningPoint == null)
689:                    throw new NullPointerException("Null listening point");
690:                ListeningPoint lp = (ListeningPoint) listeningPoint;
691:                lp.sipProviderImpl = this ;
692:                this .listeningPoint = (ListeningPoint) listeningPoint;
693:
694:            }
695:
696:            /**
697:             * Invoked when an error has ocurred with a transaction.
698:             * Propagate up to the listeners.
699:             *
700:             * @param transactionErrorEvent Error event.
701:             */
702:            public void transactionErrorEvent(
703:                    SIPTransactionErrorEvent transactionErrorEvent) {
704:                Transaction transaction = (Transaction) transactionErrorEvent
705:                        .getSource();
706:
707:                if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) {
708:
709:                    if (Logging.REPORT_LEVEL <= Logging.ERROR) {
710:                        Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
711:                                "TransportError occured on " + transaction);
712:                    }
713:
714:                    //  handle Transport error as timeout.
715:                    Object errorObject = transactionErrorEvent.getSource();
716:                    Timeout timeout = Timeout.TRANSACTION;
717:                    TimeoutEvent ev = null;
718:
719:                    if (errorObject instanceof  ServerTransaction) {
720:                        ev = new TimeoutEvent(this ,
721:                                (ServerTransaction) errorObject);
722:                    } else {
723:                        ev = new TimeoutEvent(this ,
724:                                (ClientTransaction) errorObject, timeout);
725:                    }
726:                    this .handleEvent(ev, (Transaction) errorObject);
727:
728:                } else {
729:                    //  This is a timeout event.
730:                    Object errorObject = transactionErrorEvent.getSource();
731:                    Timeout timeout = Timeout.TRANSACTION;
732:                    TimeoutEvent ev = null;
733:
734:                    if (errorObject instanceof  ServerTransaction) {
735:                        ev = new TimeoutEvent(this ,
736:                                (ServerTransaction) errorObject);
737:                    } else {
738:                        ev = new TimeoutEvent(this ,
739:                                (ClientTransaction) errorObject, timeout);
740:                    }
741:                    this .handleEvent(ev, (Transaction) errorObject);
742:
743:                }
744:            }
745:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.