1/*
2 * Conditions Of Use
3 *
4 * This software was developed by employees of the National Institute of
5 * Standards and Technology (NIST), an agency of the Federal Government.
6 * Pursuant to title 15 Untied States Code Section 105, works of NIST
7 * employees are not subject to copyright protection in the United States
8 * and are considered to be in the public domain.  As a result, a formal
9 * license is not needed to use the software.
10 *
11 * This software is provided by NIST as a service and is expressly
12 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15 * AND DATA ACCURACY.  NIST does not warrant or make any representations
16 * regarding the use of the software or the results thereof, including but
17 * not limited to the correctness, accuracy, reliability or usefulness of
18 * the software.
19 *
20 * Permission to use this software is contingent upon your acceptance
21 * of the terms of this agreement
22 *
23 * .
24 *
25 */
26/******************************************************************************
27 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).      *
28 ******************************************************************************/
29package gov.nist.javax.sip;
30
31import gov.nist.core.InternalErrorHandler;
32import gov.nist.javax.sip.DialogTimeoutEvent.Reason;
33import gov.nist.javax.sip.address.RouterExt;
34import gov.nist.javax.sip.header.CallID;
35import gov.nist.javax.sip.header.Via;
36import gov.nist.javax.sip.message.SIPMessage;
37import gov.nist.javax.sip.message.SIPRequest;
38import gov.nist.javax.sip.message.SIPResponse;
39import gov.nist.javax.sip.stack.HopImpl;
40import gov.nist.javax.sip.stack.MessageChannel;
41import gov.nist.javax.sip.stack.SIPClientTransaction;
42import gov.nist.javax.sip.stack.SIPDialog;
43import gov.nist.javax.sip.stack.SIPDialogErrorEvent;
44import gov.nist.javax.sip.stack.SIPDialogEventListener;
45import gov.nist.javax.sip.stack.SIPServerTransaction;
46import gov.nist.javax.sip.stack.SIPTransaction;
47import gov.nist.javax.sip.stack.SIPTransactionErrorEvent;
48import gov.nist.javax.sip.stack.SIPTransactionEventListener;
49
50import java.io.IOException;
51import java.text.ParseException;
52import java.util.EventObject;
53import java.util.Iterator;
54import java.util.TooManyListenersException;
55import java.util.concurrent.ConcurrentHashMap;
56
57import javax.sip.ClientTransaction;
58import javax.sip.Dialog;
59import javax.sip.DialogState;
60import javax.sip.InvalidArgumentException;
61import javax.sip.ListeningPoint;
62import javax.sip.ObjectInUseException;
63import javax.sip.RequestEvent;
64import javax.sip.ResponseEvent;
65import javax.sip.ServerTransaction;
66import javax.sip.SipException;
67import javax.sip.SipListener;
68import javax.sip.SipStack;
69import javax.sip.Timeout;
70import javax.sip.TimeoutEvent;
71import javax.sip.Transaction;
72import javax.sip.TransactionAlreadyExistsException;
73import javax.sip.TransactionState;
74import javax.sip.TransactionUnavailableException;
75import javax.sip.address.Hop;
76import javax.sip.header.CallIdHeader;
77import javax.sip.message.Request;
78import javax.sip.message.Response;
79
80/*
81 * Contributions (bug fixes) made by: Daniel J. Martinez Manzano, Hagai Sela.
82 * Bug reports by Shanti Kadiyala, Rhys Ulerich,Victor Hugo
83 */
84/**
85 * Implementation of the JAIN-SIP provider interface.
86 *
87 * @version 1.2 $Revision: 1.82 $ $Date: 2009/11/24 17:16:59 $
88 *
89 * @author M. Ranganathan <br/>
90 *
91 *
92 */
93
94public class SipProviderImpl implements javax.sip.SipProvider, gov.nist.javax.sip.SipProviderExt,
95        SIPTransactionEventListener, SIPDialogEventListener {
96
97    private SipListener sipListener;
98
99    protected SipStackImpl sipStack;
100
101    /*
102     * A set of listening points associated with the provider At most one LP per
103     * transport
104     */
105    private ConcurrentHashMap listeningPoints;
106
107    private EventScanner eventScanner;
108
109    private String address;
110
111    private int port;
112
113    private boolean automaticDialogSupportEnabled ;
114    /**
115     * A string containing the 0.0.0.0 IPv4 ANY address.
116     */
117    private String IN_ADDR_ANY = "0.0.0.0";
118
119    /**
120     * A string containing the ::0 IPv6 ANY address.
121     */
122    private String IN6_ADDR_ANY = "::0";
123
124    private boolean dialogErrorsAutomaticallyHandled = true;
125
126    private SipProviderImpl() {
127
128    }
129
130    /**
131     * Stop processing messages for this provider. Post an empty message to our
132     * message processing queue that signals us to quit.
133     */
134    protected void stop() {
135        // Put an empty event in the queue and post ourselves a message.
136        if (sipStack.isLoggingEnabled())
137            sipStack.getStackLogger().logDebug("Exiting provider");
138        for (Iterator it = listeningPoints.values().iterator(); it.hasNext();) {
139            ListeningPointImpl listeningPoint = (ListeningPointImpl) it.next();
140            listeningPoint.removeSipProvider();
141        }
142        this.eventScanner.stop();
143
144    }
145
146    /*
147     * (non-Javadoc)
148     *
149     * @see javax.sip.SipProvider#getListeningPoint(java.lang.String)
150     */
151    public ListeningPoint getListeningPoint(String transport) {
152        if (transport == null)
153            throw new NullPointerException("Null transport param");
154        return (ListeningPoint) this.listeningPoints.get(transport
155                .toUpperCase());
156    }
157
158    /**
159     * Handle the SIP event - because we have only one listener and we are
160     * already in the context of a separate thread, we dont need to enque the
161     * event and signal another thread.
162     *
163     * @param sipEvent
164     *            is the event to process.
165     *
166     */
167
168    public void handleEvent(EventObject sipEvent, SIPTransaction transaction) {
169        if (sipStack.isLoggingEnabled()) {
170            sipStack.getStackLogger().logDebug(
171                    "handleEvent " + sipEvent + "currentTransaction = "
172                            + transaction + "this.sipListener = "
173                            + this.getSipListener() + "sipEvent.source = "
174                            + sipEvent.getSource());
175            if (sipEvent instanceof RequestEvent) {
176                Dialog dialog = ((RequestEvent) sipEvent).getDialog();
177                if ( sipStack.isLoggingEnabled())  sipStack.getStackLogger().logDebug("Dialog = " + dialog);
178            } else if (sipEvent instanceof ResponseEvent) {
179                Dialog dialog = ((ResponseEvent) sipEvent).getDialog();
180                if (sipStack.isLoggingEnabled() ) sipStack.getStackLogger().logDebug("Dialog = " + dialog);
181            }
182            sipStack.getStackLogger().logStackTrace();
183        }
184
185        EventWrapper eventWrapper = new EventWrapper(sipEvent, transaction);
186
187        if (!sipStack.reEntrantListener) {
188            // Run the event in the context of a single thread.
189            this.eventScanner.addEvent(eventWrapper);
190        } else {
191            // just call the delivery method
192            this.eventScanner.deliverEvent(eventWrapper);
193        }
194    }
195
196    /** Creates a new instance of SipProviderImpl */
197    protected SipProviderImpl(SipStackImpl sipStack) {
198        this.eventScanner = sipStack.getEventScanner(); // for quick access.
199        this.sipStack = sipStack;
200        this.eventScanner.incrementRefcount();
201        this.listeningPoints = new ConcurrentHashMap<String,ListeningPointImpl>();
202        this.automaticDialogSupportEnabled = this.sipStack
203                .isAutomaticDialogSupportEnabled();
204        this.dialogErrorsAutomaticallyHandled = this.sipStack.isAutomaticDialogErrorHandlingEnabled();
205    }
206
207    /*
208     * (non-Javadoc)
209     *
210     * @see java.lang.Object#clone()
211     */
212    protected Object clone() throws java.lang.CloneNotSupportedException {
213        throw new java.lang.CloneNotSupportedException();
214    }
215
216
217    /*
218     * (non-Javadoc)
219     *
220     * @see javax.sip.SipProvider#addSipListener(javax.sip.SipListener)
221     */
222    public void addSipListener(SipListener sipListener)
223            throws TooManyListenersException {
224
225        if (sipStack.sipListener == null) {
226            sipStack.sipListener = sipListener;
227        } else if (sipStack.sipListener != sipListener) {
228            throw new TooManyListenersException(
229                    "Stack already has a listener. Only one listener per stack allowed");
230        }
231
232        if (sipStack.isLoggingEnabled())
233            sipStack.getStackLogger().logDebug("add SipListener " + sipListener);
234        this.sipListener = sipListener;
235
236    }
237
238    /*
239     * This method is deprecated (non-Javadoc)
240     *
241     * @see javax.sip.SipProvider#getListeningPoint()
242     */
243
244    public ListeningPoint getListeningPoint() {
245        if (this.listeningPoints.size() > 0)
246            return (ListeningPoint) this.listeningPoints.values().iterator()
247                    .next();
248        else
249            return null;
250    }
251
252    /*
253     * (non-Javadoc)
254     *
255     * @see javax.sip.SipProvider#getNewCallId()
256     */
257    public CallIdHeader getNewCallId() {
258        String callId = Utils.getInstance().generateCallIdentifier(this.getListeningPoint()
259                .getIPAddress());
260        CallID callid = new CallID();
261        try {
262            callid.setCallId(callId);
263        } catch (java.text.ParseException ex) {
264        }
265        return callid;
266
267    }
268
269    /*
270     * (non-Javadoc)
271     *
272     * @see javax.sip.SipProvider#getNewClientTransaction(javax.sip.message.Request)
273     */
274    public ClientTransaction getNewClientTransaction(Request request)
275            throws TransactionUnavailableException {
276        if (request == null)
277            throw new NullPointerException("null request");
278        if (!sipStack.isAlive())
279            throw new TransactionUnavailableException("Stack is stopped");
280
281        SIPRequest sipRequest = (SIPRequest) request;
282        if (sipRequest.getTransaction() != null)
283            throw new TransactionUnavailableException(
284                    "Transaction already assigned to request");
285        if ( sipRequest.getMethod().equals(Request.ACK)) {
286            throw new TransactionUnavailableException ("Cannot create client transaction for  " + Request.ACK);
287        }
288        // Be kind and assign a via header for this provider if the user is
289        // sloppy
290        if (sipRequest.getTopmostVia() == null) {
291            ListeningPointImpl lp = (ListeningPointImpl) this
292                    .getListeningPoint("udp");
293            Via via = lp.getViaHeader();
294            request.setHeader(via);
295        }
296        // Give the request a quick check to see if all headers are assigned.
297        try {
298            sipRequest.checkHeaders();
299        } catch (ParseException ex) {
300            throw new TransactionUnavailableException(ex.getMessage(), ex);
301        }
302
303        /*
304         * User decided to give us his own via header branch. Lets see if it
305         * results in a clash. If so reject the request.
306         */
307        if (sipRequest.getTopmostVia().getBranch() != null
308                && sipRequest.getTopmostVia().getBranch().startsWith(
309                        SIPConstants.BRANCH_MAGIC_COOKIE)
310                && sipStack.findTransaction((SIPRequest) request, false) != null) {
311            throw new TransactionUnavailableException(
312                    "Transaction already exists!");
313        }
314
315
316
317
318        if (request.getMethod().equalsIgnoreCase(Request.CANCEL)) {
319            SIPClientTransaction ct = (SIPClientTransaction) sipStack
320                    .findCancelTransaction((SIPRequest) request, false);
321            if (ct != null) {
322                ClientTransaction retval = sipStack.createClientTransaction(
323                        (SIPRequest) request, ct.getMessageChannel());
324
325                ((SIPTransaction) retval).addEventListener(this);
326                sipStack.addTransaction((SIPClientTransaction) retval);
327                if (ct.getDialog() != null) {
328                    ((SIPClientTransaction) retval).setDialog((SIPDialog) ct
329                            .getDialog(), sipRequest.getDialogId(false));
330
331                }
332                return retval;
333            }
334
335        }
336        if (sipStack.isLoggingEnabled())
337            sipStack.getStackLogger().logDebug(
338                    "could not find existing transaction for "
339                            + ((SIPRequest) request).getFirstLine()
340                            + " creating a new one ");
341
342        // Could not find a dialog or the route is not set in dialog.
343
344        Hop hop = null;
345        try {
346            hop = sipStack.getNextHop((SIPRequest) request);
347            if (hop == null)
348                throw new TransactionUnavailableException(
349                        "Cannot resolve next hop -- transaction unavailable");
350        } catch (SipException ex) {
351            throw new TransactionUnavailableException(
352                    "Cannot resolve next hop -- transaction unavailable", ex);
353        }
354        String transport = hop.getTransport();
355        ListeningPointImpl listeningPoint = (ListeningPointImpl) this
356                .getListeningPoint(transport);
357
358        String dialogId = sipRequest.getDialogId(false);
359        SIPDialog dialog = sipStack.getDialog(dialogId);
360        if (dialog != null && dialog.getState() == DialogState.TERMINATED) {
361
362            // throw new TransactionUnavailableException
363            // ("Found a terminated dialog -- possible re-use of old tag
364            // parameters");
365            sipStack.removeDialog(dialog);
366
367        }
368
369        // An out of dialog route was found. Assign this to the
370        // client transaction.
371
372        try {
373            // Set the brannch id before you ask for a tx.
374            // If the user has set his own branch Id and the
375            // branch id starts with a valid prefix, then take it.
376            // otherwise, generate one. If branch ID checking has
377            // been requested, set the branch ID.
378            String branchId = null;
379            if (sipRequest.getTopmostVia().getBranch() == null
380                    || !sipRequest.getTopmostVia().getBranch().startsWith(
381                            SIPConstants.BRANCH_MAGIC_COOKIE)
382                            || sipStack.checkBranchId() ) {
383                branchId = Utils.getInstance().generateBranchId();
384
385                sipRequest.getTopmostVia().setBranch(branchId);
386            }
387            Via topmostVia = sipRequest.getTopmostVia();
388
389            //set port and transport if user hasn't already done this.
390            if(topmostVia.getTransport() == null)
391                topmostVia.setTransport(transport);
392
393            if(topmostVia.getPort() == -1)
394                topmostVia.setPort(listeningPoint.getPort());
395            branchId = sipRequest.getTopmostVia().getBranch();
396
397            SIPClientTransaction ct = (SIPClientTransaction) sipStack
398                    .createMessageChannel(sipRequest, listeningPoint
399                            .getMessageProcessor(), hop);
400            if (ct == null)
401                throw new TransactionUnavailableException("Cound not create tx");
402            ct.setNextHop(hop);
403            ct.setOriginalRequest(sipRequest);
404            ct.setBranch(branchId);
405            // if the stack supports dialogs then
406            if (sipStack.isDialogCreated(request.getMethod())) {
407                // create a new dialog to contain this transaction
408                // provided this is necessary.
409                // This could be a re-invite
410                // in which case the dialog is re-used.
411                // (but noticed by Brad Templeton)
412                if (dialog != null)
413                    ct.setDialog(dialog, sipRequest.getDialogId(false));
414                else if (this.isAutomaticDialogSupportEnabled()) {
415                    SIPDialog sipDialog = sipStack.createDialog(ct);
416                    ct.setDialog(sipDialog, sipRequest.getDialogId(false));
417                }
418            } else {
419                if (dialog != null) {
420                    ct.setDialog(dialog, sipRequest.getDialogId(false));
421                }
422
423            }
424
425            // The provider is the event listener for all transactions.
426            ct.addEventListener(this);
427            return (ClientTransaction) ct;
428        } catch (IOException ex) {
429
430            throw new TransactionUnavailableException(
431                    "Could not resolve next hop or listening point unavailable! ",
432                    ex);
433
434        } catch (java.text.ParseException ex) {
435            InternalErrorHandler.handleException(ex);
436            throw new TransactionUnavailableException(
437                    "Unexpected Exception FIXME! ", ex);
438        } catch (InvalidArgumentException ex) {
439            InternalErrorHandler.handleException(ex);
440            throw new TransactionUnavailableException(
441                    "Unexpected Exception FIXME! ", ex);
442        }
443
444    }
445
446    /*
447     * (non-Javadoc)
448     *
449     * @see javax.sip.SipProvider#getNewServerTransaction(javax.sip.message.Request)
450     */
451    public ServerTransaction getNewServerTransaction(Request request)
452            throws TransactionAlreadyExistsException,
453            TransactionUnavailableException {
454
455        if (!sipStack.isAlive())
456            throw new TransactionUnavailableException("Stack is stopped");
457        SIPServerTransaction transaction = null;
458        SIPRequest sipRequest = (SIPRequest) request;
459        try {
460            sipRequest.checkHeaders();
461        } catch (ParseException ex) {
462            throw new TransactionUnavailableException(ex.getMessage(), ex);
463        }
464
465        if ( request.getMethod().equals(Request.ACK)) {
466            if ( sipStack.isLoggingEnabled())
467                sipStack.getStackLogger().logError("Creating server transaction for ACK -- makes no sense!");
468            throw new TransactionUnavailableException("Cannot create Server transaction for ACK ");
469        }
470        /*
471         * Got a notify.
472         */
473        if (sipRequest.getMethod().equals(Request.NOTIFY)
474                && sipRequest.getFromTag() != null
475                && sipRequest.getToTag() == null) {
476
477            SIPClientTransaction ct = sipStack.findSubscribeTransaction(
478                    sipRequest, (ListeningPointImpl) this.getListeningPoint());
479            /* Issue 104 */
480            if (ct == null && ! sipStack.deliverUnsolicitedNotify) {
481                throw new TransactionUnavailableException(
482                        "Cannot find matching Subscription (and gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY not set)");
483            }
484        }
485        if ( !sipStack.acquireSem()) {
486            throw new TransactionUnavailableException(
487            "Transaction not available -- could not acquire stack lock");
488        }
489        try {
490            if (sipStack.isDialogCreated(sipRequest.getMethod())) {
491                if (sipStack.findTransaction((SIPRequest) request, true) != null)
492                    throw new TransactionAlreadyExistsException(
493                    "server transaction already exists!");
494
495                transaction = (SIPServerTransaction) ((SIPRequest) request)
496                .getTransaction();
497                if (transaction == null)
498                    throw new TransactionUnavailableException(
499                    "Transaction not available");
500                if (transaction.getOriginalRequest() == null)
501                    transaction.setOriginalRequest(sipRequest);
502                try {
503                    sipStack.addTransaction(transaction);
504                } catch (IOException ex) {
505                    throw new TransactionUnavailableException(
506                    "Error sending provisional response");
507                }
508                // So I can handle timeouts.
509                transaction.addEventListener(this);
510                if (isAutomaticDialogSupportEnabled()) {
511                    // If automatic dialog support is enabled then
512                    // this tx gets his own dialog.
513                    String dialogId = sipRequest.getDialogId(true);
514                    SIPDialog dialog = sipStack.getDialog(dialogId);
515                    if (dialog == null) {
516                        dialog = sipStack.createDialog(transaction);
517
518                    }
519                    transaction.setDialog(dialog, sipRequest.getDialogId(true));
520                    if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
521                        sipStack.putInMergeTable(transaction, sipRequest);
522                    }
523                    dialog.addRoute(sipRequest);
524                    if (dialog.getRemoteTag() != null
525                            && dialog.getLocalTag() != null) {
526                        this.sipStack.putDialog(dialog);
527                    }
528                }
529
530            } else {
531                if (isAutomaticDialogSupportEnabled()) {
532                    /*
533                     * Under automatic dialog support, dialog is tied into a transaction. You cannot
534                     * create a server tx except for dialog creating transactions. After that, all
535                     * subsequent transactions are created for you by the stack.
536                     */
537                    transaction = (SIPServerTransaction) sipStack.findTransaction(
538                            (SIPRequest) request, true);
539                    if (transaction != null)
540                        throw new TransactionAlreadyExistsException(
541                        "Transaction exists! ");
542                    transaction = (SIPServerTransaction) ((SIPRequest) request)
543                    .getTransaction();
544                    if (transaction == null)
545                        throw new TransactionUnavailableException(
546                        "Transaction not available!");
547                    if (transaction.getOriginalRequest() == null)
548                        transaction.setOriginalRequest(sipRequest);
549                    // Map the transaction.
550                    try {
551                        sipStack.addTransaction(transaction);
552                    } catch (IOException ex) {
553                        throw new TransactionUnavailableException(
554                        "Could not send back provisional response!");
555                    }
556
557                    // If there is a dialog already assigned then just update the
558                    // dialog state.
559                    String dialogId = sipRequest.getDialogId(true);
560                    SIPDialog dialog = sipStack.getDialog(dialogId);
561                    if (dialog != null) {
562                        dialog.addTransaction(transaction);
563                        dialog.addRoute(sipRequest);
564                        transaction.setDialog(dialog, sipRequest.getDialogId(true));
565                    }
566
567                } else {
568                    transaction = (SIPServerTransaction) sipStack.findTransaction(
569                            (SIPRequest) request, true);
570                    if (transaction != null)
571                        throw new TransactionAlreadyExistsException(
572                        "Transaction exists! ");
573                    transaction = (SIPServerTransaction) ((SIPRequest) request)
574                    .getTransaction();
575                    if (transaction != null) {
576                        if (transaction.getOriginalRequest() == null)
577                            transaction.setOriginalRequest(sipRequest);
578                        // Map the transaction.
579                        sipStack.mapTransaction(transaction);
580
581                        // If there is a dialog already assigned then just
582                        // assign the dialog to the transaction.
583                        String dialogId = sipRequest.getDialogId(true);
584                        SIPDialog dialog = sipStack.getDialog(dialogId);
585                        if (dialog != null) {
586                            dialog.addTransaction(transaction);
587                            dialog.addRoute(sipRequest);
588                            transaction.setDialog(dialog, sipRequest
589                                    .getDialogId(true));
590                        }
591
592                        return transaction;
593                    } else {
594                        // tx does not exist so create the tx.
595
596                        MessageChannel mc = (MessageChannel) sipRequest
597                        .getMessageChannel();
598                        transaction = sipStack.createServerTransaction(mc);
599                        if (transaction == null)
600                            throw new TransactionUnavailableException(
601                            "Transaction unavailable -- too many servrer transactions");
602
603                        transaction.setOriginalRequest(sipRequest);
604                        sipStack.mapTransaction(transaction);
605
606                        // If there is a dialog already assigned then just
607                        // assign the dialog to the transaction.
608                        String dialogId = sipRequest.getDialogId(true);
609                        SIPDialog dialog = sipStack.getDialog(dialogId);
610                        if (dialog != null) {
611                            dialog.addTransaction(transaction);
612                            dialog.addRoute(sipRequest);
613                            transaction.setDialog(dialog, sipRequest
614                                    .getDialogId(true));
615                        }
616
617                        return transaction;
618                    }
619                }
620
621            }
622            return transaction;
623        } finally {
624            sipStack.releaseSem();
625        }
626
627    }
628
629    /*
630     * (non-Javadoc)
631     *
632     * @see javax.sip.SipProvider#getSipStack()
633     */
634    public SipStack getSipStack() {
635        return (SipStack) this.sipStack;
636    }
637
638    /*
639     * (non-Javadoc)
640     *
641     * @see javax.sip.SipProvider#removeSipListener(javax.sip.SipListener)
642     */
643    public void removeSipListener(SipListener sipListener) {
644        if (sipListener == this.getSipListener()) {
645            this.sipListener = null;
646        }
647
648        boolean found = false;
649
650        for (Iterator<SipProviderImpl> it = sipStack.getSipProviders(); it.hasNext();) {
651            SipProviderImpl nextProvider = (SipProviderImpl) it.next();
652            if (nextProvider.getSipListener() != null)
653                found = true;
654        }
655        if (!found) {
656            sipStack.sipListener = null;
657        }
658    }
659
660    /*
661     * (non-Javadoc)
662     *
663     * @see javax.sip.SipProvider#sendRequest(javax.sip.message.Request)
664     */
665    public void sendRequest(Request request) throws SipException {
666        if (!sipStack.isAlive())
667            throw new SipException("Stack is stopped.");
668
669        // mranga: added check to ensure we are not sending empty (keepalive)
670        // message.
671        if (((SIPRequest) request).getRequestLine() != null
672                && request.getMethod().equals(Request.ACK)) {
673            Dialog dialog = sipStack.getDialog(((SIPRequest) request)
674                    .getDialogId(false));
675            if (dialog != null && dialog.getState() != null) {
676            	if (sipStack.isLoggingEnabled())
677            		sipStack.getStackLogger().logWarning(
678                        "Dialog exists -- you may want to use Dialog.sendAck() "
679                                + dialog.getState());
680            }
681        }
682        Hop hop = sipStack.getRouter((SIPRequest) request).getNextHop(request);
683        if (hop == null)
684            throw new SipException("could not determine next hop!");
685        SIPRequest sipRequest = (SIPRequest) request;
686        // Check if we have a valid via.
687        // Null request is used to send default proxy keepalive messages.
688        if ((!sipRequest.isNullRequest()) && sipRequest.getTopmostVia() == null)
689            throw new SipException("Invalid SipRequest -- no via header!");
690
691        try {
692            /*
693             * JvB: Via branch should already be OK, dont touch it here? Some
694             * apps forward statelessly, and then it's not set. So set only when
695             * not set already, dont overwrite CANCEL branch here..
696             */
697            if (!sipRequest.isNullRequest()) {
698                Via via = sipRequest.getTopmostVia();
699                String branch = via.getBranch();
700                if (branch == null || branch.length() == 0) {
701                    via.setBranch(sipRequest.getTransactionId());
702                }
703            }
704            MessageChannel messageChannel = null;
705            if (this.listeningPoints.containsKey(hop.getTransport()
706                    .toUpperCase()))
707                messageChannel = sipStack.createRawMessageChannel(
708                        this.getListeningPoint(hop.getTransport()).getIPAddress(),
709                        this.getListeningPoint(hop.getTransport()).getPort(), hop);
710            if (messageChannel != null) {
711                messageChannel.sendMessage((SIPMessage) sipRequest,hop);
712            } else {
713                throw new SipException(
714                        "Could not create a message channel for "
715                                + hop.toString());
716            }
717        } catch (IOException ex) {
718            if (sipStack.isLoggingEnabled()) {
719                sipStack.getStackLogger().logException(ex);
720            }
721
722            throw new SipException(
723                    "IO Exception occured while Sending Request", ex);
724
725        } catch (ParseException ex1) {
726            InternalErrorHandler.handleException(ex1);
727        } finally {
728            if (sipStack.isLoggingEnabled())
729                sipStack.getStackLogger().logDebug(
730                        "done sending " + request.getMethod() + " to hop "
731                                + hop);
732        }
733    }
734
735    /*
736     * (non-Javadoc)
737     *
738     * @see javax.sip.SipProvider#sendResponse(javax.sip.message.Response)
739     */
740    public void sendResponse(Response response) throws SipException {
741        if (!sipStack.isAlive())
742            throw new SipException("Stack is stopped");
743        SIPResponse sipResponse = (SIPResponse) response;
744        Via via = sipResponse.getTopmostVia();
745        if (via == null)
746            throw new SipException("No via header in response!");
747        SIPServerTransaction st = (SIPServerTransaction) sipStack.findTransaction((SIPMessage)response, true);
748        if ( st != null   && st.getState() != TransactionState.TERMINATED && this.isAutomaticDialogSupportEnabled()) {
749            throw new SipException("Transaction exists -- cannot send response statelessly");
750        }
751        String transport = via.getTransport();
752
753        // check to see if Via has "received paramaeter". If so
754        // set the host to the via parameter. Else set it to the
755        // Via host.
756        String host = via.getReceived();
757
758        if (host == null)
759            host = via.getHost();
760
761        // Symmetric nat support
762        int port = via.getRPort();
763        if (port == -1) {
764            port = via.getPort();
765            if (port == -1) {
766                if (transport.equalsIgnoreCase("TLS"))
767                    port = 5061;
768                else
769                    port = 5060;
770            }
771        }
772
773        // for correct management of IPv6 addresses.
774        if (host.indexOf(":") > 0)
775            if (host.indexOf("[") < 0)
776                host = "[" + host + "]";
777
778        Hop hop = sipStack.getAddressResolver().resolveAddress(
779                new HopImpl(host, port, transport));
780
781        try {
782            ListeningPointImpl listeningPoint = (ListeningPointImpl) this
783                    .getListeningPoint(transport);
784            if (listeningPoint == null)
785                throw new SipException(
786                        "whoopsa daisy! no listening point found for transport "
787                                + transport);
788            MessageChannel messageChannel = sipStack.createRawMessageChannel(
789                    this.getListeningPoint(hop.getTransport()).getIPAddress(),
790                    listeningPoint.port, hop);
791            messageChannel.sendMessage(sipResponse);
792        } catch (IOException ex) {
793            throw new SipException(ex.getMessage());
794        }
795    }
796
797    /*
798     * (non-Javadoc)
799     *
800     * @see javax.sip.SipProvider#setListeningPoint(javax.sip.ListeningPoint)
801     */
802    public synchronized void setListeningPoint(ListeningPoint listeningPoint) {
803        if (listeningPoint == null)
804            throw new NullPointerException("Null listening point");
805        ListeningPointImpl lp = (ListeningPointImpl) listeningPoint;
806        lp.sipProvider = this;
807        String transport = lp.getTransport().toUpperCase();
808        this.address = listeningPoint.getIPAddress();
809        this.port = listeningPoint.getPort();
810        // This is the first listening point.
811        this.listeningPoints.clear();
812        this.listeningPoints.put(transport, listeningPoint);
813
814    }
815
816    /*
817     * (non-Javadoc)
818     *
819     * @see javax.sip.SipProvider#getNewDialog(javax.sip.Transaction)
820     */
821
822    public Dialog getNewDialog(Transaction transaction) throws SipException {
823        if (transaction == null)
824            throw new NullPointerException("Null transaction!");
825
826        if (!sipStack.isAlive())
827            throw new SipException("Stack is stopped.");
828
829        if (isAutomaticDialogSupportEnabled())
830            throw new SipException(" Error - AUTOMATIC_DIALOG_SUPPORT is on");
831
832        if (!sipStack.isDialogCreated(transaction.getRequest().getMethod()))
833            throw new SipException("Dialog cannot be created for this method "
834                    + transaction.getRequest().getMethod());
835
836        SIPDialog dialog = null;
837        SIPTransaction sipTransaction = (SIPTransaction) transaction;
838
839        if (transaction instanceof ServerTransaction) {
840            SIPServerTransaction st = (SIPServerTransaction) transaction;
841            Response response = st.getLastResponse();
842            if (response != null) {
843                if (response.getStatusCode() != 100)
844                    throw new SipException(
845                            "Cannot set dialog after response has been sent");
846            }
847            SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
848            String dialogId = sipRequest.getDialogId(true);
849            dialog = sipStack.getDialog(dialogId);
850            if (dialog == null) {
851                dialog = sipStack.createDialog((SIPTransaction) transaction);
852                // create and register the dialog and add the inital route set.
853                dialog.addTransaction(sipTransaction);
854                dialog.addRoute(sipRequest);
855                sipTransaction.setDialog(dialog, null);
856
857            } else {
858                sipTransaction.setDialog(dialog, sipRequest.getDialogId(true));
859            }
860            if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
861                sipStack.putInMergeTable(st, sipRequest);
862            }
863        } else {
864
865            SIPClientTransaction sipClientTx = (SIPClientTransaction) transaction;
866
867            SIPResponse response = sipClientTx.getLastResponse();
868
869            if (response == null) {
870                // A response has not yet been received, then set this up as the
871                // default dialog.
872                SIPRequest request = (SIPRequest) sipClientTx.getRequest();
873
874                String dialogId = request.getDialogId(false);
875                dialog = sipStack.getDialog(dialogId);
876                if (dialog != null) {
877                    throw new SipException("Dialog already exists!");
878                } else {
879                    dialog = sipStack.createDialog(sipTransaction);
880                }
881                sipClientTx.setDialog(dialog, null);
882
883            } else {
884                throw new SipException(
885                        "Cannot call this method after response is received!");
886            }
887        }
888        dialog.addEventListener(this);
889        return dialog;
890
891    }
892
893    /**
894     * Invoked when an error has ocurred with a transaction. Propagate up to the
895     * listeners.
896     *
897     * @param transactionErrorEvent
898     *            Error event.
899     */
900    public void transactionErrorEvent(
901            SIPTransactionErrorEvent transactionErrorEvent) {
902        SIPTransaction transaction = (SIPTransaction) transactionErrorEvent
903                .getSource();
904
905        if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) {
906            // There must be a way to inform the TU here!!
907            if (sipStack.isLoggingEnabled()) {
908                sipStack.getStackLogger().logDebug(
909                        "TransportError occured on " + transaction);
910            }
911            // Treat this like a timeout event. (Suggestion from Christophe).
912            Object errorObject = transactionErrorEvent.getSource();
913            Timeout timeout = Timeout.TRANSACTION;
914            TimeoutEvent ev = null;
915
916            if (errorObject instanceof SIPServerTransaction) {
917                ev = new TimeoutEvent(this, (ServerTransaction) errorObject,
918                        timeout);
919            } else {
920                SIPClientTransaction clientTx = (SIPClientTransaction) errorObject;
921                Hop hop = clientTx.getNextHop();
922                if ( sipStack.getRouter() instanceof RouterExt ) {
923                    ((RouterExt) sipStack.getRouter()).transactionTimeout(hop);
924                }
925                ev = new TimeoutEvent(this, (ClientTransaction) errorObject,
926                        timeout);
927            }
928            // Handling transport error like timeout
929            this.handleEvent(ev, (SIPTransaction) errorObject);
930        } else if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TIMEOUT_ERROR) {
931            // This is a timeout event.
932            Object errorObject = transactionErrorEvent.getSource();
933            Timeout timeout = Timeout.TRANSACTION;
934            TimeoutEvent ev = null;
935
936            if (errorObject instanceof SIPServerTransaction) {
937                ev = new TimeoutEvent(this, (ServerTransaction) errorObject,
938                        timeout);
939            } else {
940                SIPClientTransaction clientTx = (SIPClientTransaction) errorObject;
941                Hop hop = clientTx.getNextHop();
942                if ( sipStack.getRouter() instanceof RouterExt ) {
943                    ((RouterExt) sipStack.getRouter()).transactionTimeout(hop);
944                }
945
946                ev = new TimeoutEvent(this, (ClientTransaction) errorObject,
947                        timeout);
948            }
949            this.handleEvent(ev, (SIPTransaction) errorObject);
950
951        } else if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) {
952            // This is a timeout retransmit event.
953            // We should never get this if retransmit filter is
954            // enabled (ie. in that case the stack should handle.
955            // all retransmits.
956            Object errorObject = transactionErrorEvent.getSource();
957            Transaction tx = (Transaction) errorObject;
958
959            if (tx.getDialog() != null)
960                InternalErrorHandler.handleException("Unexpected event !",
961                        this.sipStack.getStackLogger());
962
963            Timeout timeout = Timeout.RETRANSMIT;
964            TimeoutEvent ev = null;
965
966            if (errorObject instanceof SIPServerTransaction) {
967                ev = new TimeoutEvent(this, (ServerTransaction) errorObject,
968                        timeout);
969            } else {
970                ev = new TimeoutEvent(this, (ClientTransaction) errorObject,
971                        timeout);
972            }
973            this.handleEvent(ev, (SIPTransaction) errorObject);
974        }
975    }
976
977    /*
978     * (non-Javadoc)
979     * @see gov.nist.javax.sip.stack.SIPDialogEventListener#dialogErrorEvent(gov.nist.javax.sip.stack.SIPDialogErrorEvent)
980     */
981    public synchronized void dialogErrorEvent(SIPDialogErrorEvent dialogErrorEvent) {
982        SIPDialog sipDialog = (SIPDialog) dialogErrorEvent.getSource();
983        Reason reason = Reason.AckNotReceived;
984        if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT) {
985        	reason= Reason.AckNotSent;
986        } else if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT) {
987            reason = Reason.ReInviteTimeout;
988        }
989        if (sipStack.isLoggingEnabled()) {
990            sipStack.getStackLogger().logDebug(
991                    "Dialog TimeoutError occured on " + sipDialog);
992        }
993        DialogTimeoutEvent ev = new DialogTimeoutEvent(this, sipDialog, reason);
994        // Handling transport error like timeout
995        this.handleEvent(ev, null);
996    }
997
998    /*
999     * (non-Javadoc)
1000     *
1001     * @see javax.sip.SipProvider#getListeningPoints()
1002     */
1003    public synchronized ListeningPoint[] getListeningPoints() {
1004
1005        ListeningPoint[] retval = new ListeningPointImpl[this.listeningPoints
1006                .size()];
1007        this.listeningPoints.values().toArray(retval);
1008        return retval;
1009    }
1010
1011    /*
1012     * (non-Javadoc)
1013     *
1014     * @see javax.sip.SipProvider#addListeningPoint(javax.sip.ListeningPoint)
1015     */
1016    public synchronized void addListeningPoint(ListeningPoint listeningPoint)
1017            throws ObjectInUseException {
1018        ListeningPointImpl lp = (ListeningPointImpl) listeningPoint;
1019        if (lp.sipProvider != null && lp.sipProvider != this)
1020            throw new ObjectInUseException(
1021                    "Listening point assigned to another provider");
1022        String transport = lp.getTransport().toUpperCase();
1023        if (this.listeningPoints.isEmpty()) {
1024            // first one -- record the IP address/port of the LP
1025
1026            this.address = listeningPoint.getIPAddress();
1027            this.port = listeningPoint.getPort();
1028        } else {
1029            if ((!this.address.equals(listeningPoint.getIPAddress()))
1030                    || this.port != listeningPoint.getPort())
1031                throw new ObjectInUseException(
1032                        "Provider already has different IP Address associated");
1033
1034        }
1035        if (this.listeningPoints.containsKey(transport)
1036                && this.listeningPoints.get(transport) != listeningPoint)
1037            throw new ObjectInUseException(
1038                    "Listening point already assigned for transport!");
1039
1040        // This is for backwards compatibility.
1041        lp.sipProvider = this;
1042
1043        this.listeningPoints.put(transport, lp);
1044
1045    }
1046
1047    /*
1048     * (non-Javadoc)
1049     *
1050     * @see javax.sip.SipProvider#removeListeningPoint(javax.sip.ListeningPoint)
1051     */
1052    public synchronized void removeListeningPoint(ListeningPoint listeningPoint)
1053            throws ObjectInUseException {
1054        ListeningPointImpl lp = (ListeningPointImpl) listeningPoint;
1055        if (lp.messageProcessor.inUse())
1056            throw new ObjectInUseException("Object is in use");
1057        this.listeningPoints.remove(lp.getTransport().toUpperCase());
1058
1059    }
1060
1061    /**
1062     * Remove all the listening points for this sip provider. This is called
1063     * when the stack removes the Provider
1064     */
1065    public synchronized void removeListeningPoints() {
1066        for (Iterator it = this.listeningPoints.values().iterator(); it
1067                .hasNext();) {
1068            ListeningPointImpl lp = (ListeningPointImpl) it.next();
1069            lp.messageProcessor.stop();
1070            it.remove();
1071        }
1072
1073    }
1074
1075    /*
1076     * (non-Javadoc)
1077     *
1078     * @see javax.sip.SipProvider#setAutomaticDialogSupportEnabled(boolean)
1079     */
1080    public void setAutomaticDialogSupportEnabled(
1081            boolean automaticDialogSupportEnabled) {
1082        this.automaticDialogSupportEnabled = automaticDialogSupportEnabled;
1083        if ( this.automaticDialogSupportEnabled ) {
1084            this.dialogErrorsAutomaticallyHandled = true;
1085        }
1086    }
1087
1088    /**
1089     * @return Returns the automaticDialogSupportEnabled.
1090     */
1091    public boolean isAutomaticDialogSupportEnabled() {
1092        return automaticDialogSupportEnabled;
1093    }
1094
1095    /*
1096     * (non-Javadoc)
1097     * @see gov.nist.javax.sip.SipProviderExt#setDialogErrorsAutomaticallyHandled()
1098     */
1099    public void setDialogErrorsAutomaticallyHandled() {
1100        this.dialogErrorsAutomaticallyHandled = true;
1101    }
1102
1103    public boolean isDialogErrorsAutomaticallyHandled() {
1104        return this.dialogErrorsAutomaticallyHandled;
1105    }
1106
1107
1108    /**
1109     * @return the sipListener
1110     */
1111    public SipListener getSipListener() {
1112        return sipListener;
1113    }
1114
1115
1116}
1117