1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use
3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of
5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government.
6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST
7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States
8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain.  As a result, a formal
9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software.
10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly
12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY.  NIST does not warrant or make any representations
16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but
17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of
18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software.
19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance
21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement
22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * .
24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/******************************************************************************
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).      *
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ******************************************************************************/
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.InternalErrorHandler;
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.DialogTimeoutEvent.Reason;
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.RouterExt;
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.CallID;
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Via;
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPMessage;
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest;
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPResponse;
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.HopImpl;
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.MessageChannel;
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPClientTransaction;
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPDialog;
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPDialogErrorEvent;
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPDialogEventListener;
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPServerTransaction;
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransaction;
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransactionErrorEvent;
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransactionEventListener;
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.IOException;
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException;
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.EventObject;
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator;
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.TooManyListenersException;
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.ConcurrentHashMap;
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ClientTransaction;
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.Dialog;
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.DialogState;
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.InvalidArgumentException;
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ListeningPoint;
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ObjectInUseException;
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.RequestEvent;
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ResponseEvent;
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ServerTransaction;
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipException;
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipListener;
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipStack;
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.Timeout;
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TimeoutEvent;
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.Transaction;
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TransactionAlreadyExistsException;
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TransactionState;
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TransactionUnavailableException;
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.Hop;
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CallIdHeader;
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Request;
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Response;
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Contributions (bug fixes) made by: Daniel J. Martinez Manzano, Hagai Sela.
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Bug reports by Shanti Kadiyala, Rhys Ulerich,Victor Hugo
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/**
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Implementation of the JAIN-SIP provider interface.
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.82 $ $Date: 2009/11/24 17:16:59 $
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan <br/>
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class SipProviderImpl implements javax.sip.SipProvider, gov.nist.javax.sip.SipProviderExt,
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPTransactionEventListener, SIPDialogEventListener {
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private SipListener sipListener;
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected SipStackImpl sipStack;
100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * A set of listening points associated with the provider At most one LP per
103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * transport
104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private ConcurrentHashMap listeningPoints;
106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private EventScanner eventScanner;
108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private String address;
110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private int port;
112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private boolean automaticDialogSupportEnabled ;
114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * A string containing the 0.0.0.0 IPv4 ANY address.
116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private String IN_ADDR_ANY = "0.0.0.0";
118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * A string containing the ::0 IPv6 ANY address.
121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private String IN6_ADDR_ANY = "::0";
123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private boolean dialogErrorsAutomaticallyHandled = true;
125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private SipProviderImpl() {
127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Stop processing messages for this provider. Post an empty message to our
132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * message processing queue that signals us to quit.
133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void stop() {
135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Put an empty event in the queue and post ourselves a message.
136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled())
137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug("Exiting provider");
138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (Iterator it = listeningPoints.values().iterator(); it.hasNext();) {
139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ListeningPointImpl listeningPoint = (ListeningPointImpl) it.next();
140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            listeningPoint.removeSipProvider();
141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.eventScanner.stop();
143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getListeningPoint(java.lang.String)
150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public ListeningPoint getListeningPoint(String transport) {
152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (transport == null)
153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new NullPointerException("Null transport param");
154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return (ListeningPoint) this.listeningPoints.get(transport
155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .toUpperCase());
156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Handle the SIP event - because we have only one listener and we are
160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * already in the context of a separate thread, we dont need to enque the
161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * event and signal another thread.
162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param sipEvent
164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            is the event to process.
165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void handleEvent(EventObject sipEvent, SIPTransaction transaction) {
169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled()) {
170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug(
171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "handleEvent " + sipEvent + "currentTransaction = "
172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            + transaction + "this.sipListener = "
173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            + this.getSipListener() + "sipEvent.source = "
174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            + sipEvent.getSource());
175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipEvent instanceof RequestEvent) {
176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Dialog dialog = ((RequestEvent) sipEvent).getDialog();
177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ( sipStack.isLoggingEnabled())  sipStack.getStackLogger().logDebug("Dialog = " + dialog);
178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (sipEvent instanceof ResponseEvent) {
179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Dialog dialog = ((ResponseEvent) sipEvent).getDialog();
180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (sipStack.isLoggingEnabled() ) sipStack.getStackLogger().logDebug("Dialog = " + dialog);
181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logStackTrace();
183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        EventWrapper eventWrapper = new EventWrapper(sipEvent, transaction);
186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.reEntrantListener) {
188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Run the event in the context of a single thread.
189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.eventScanner.addEvent(eventWrapper);
190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // just call the delivery method
192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.eventScanner.deliverEvent(eventWrapper);
193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /** Creates a new instance of SipProviderImpl */
197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected SipProviderImpl(SipStackImpl sipStack) {
198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.eventScanner = sipStack.getEventScanner(); // for quick access.
199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.sipStack = sipStack;
200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.eventScanner.incrementRefcount();
201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.listeningPoints = new ConcurrentHashMap<String,ListeningPointImpl>();
202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.automaticDialogSupportEnabled = this.sipStack
203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .isAutomaticDialogSupportEnabled();
204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.dialogErrorsAutomaticallyHandled = this.sipStack.isAutomaticDialogErrorHandlingEnabled();
205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see java.lang.Object#clone()
211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected Object clone() throws java.lang.CloneNotSupportedException {
213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        throw new java.lang.CloneNotSupportedException();
214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#addSipListener(javax.sip.SipListener)
221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void addSipListener(SipListener sipListener)
223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws TooManyListenersException {
224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.sipListener == null) {
226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.sipListener = sipListener;
227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else if (sipStack.sipListener != sipListener) {
228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TooManyListenersException(
229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Stack already has a listener. Only one listener per stack allowed");
230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled())
233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug("add SipListener " + sipListener);
234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.sipListener = sipListener;
235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * This method is deprecated (non-Javadoc)
240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getListeningPoint()
242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public ListeningPoint getListeningPoint() {
245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.listeningPoints.size() > 0)
246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return (ListeningPoint) this.listeningPoints.values().iterator()
247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .next();
248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else
249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return null;
250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getNewCallId()
256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public CallIdHeader getNewCallId() {
258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String callId = Utils.getInstance().generateCallIdentifier(this.getListeningPoint()
259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getIPAddress());
260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        CallID callid = new CallID();
261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            callid.setCallId(callId);
263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (java.text.ParseException ex) {
264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return callid;
266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getNewClientTransaction(javax.sip.message.Request)
273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public ClientTransaction getNewClientTransaction(Request request)
275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws TransactionUnavailableException {
276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (request == null)
277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new NullPointerException("null request");
278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.isAlive())
279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException("Stack is stopped");
280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPRequest sipRequest = (SIPRequest) request;
282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipRequest.getTransaction() != null)
283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Transaction already assigned to request");
285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( sipRequest.getMethod().equals(Request.ACK)) {
286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException ("Cannot create client transaction for  " + Request.ACK);
287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Be kind and assign a via header for this provider if the user is
289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // sloppy
290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipRequest.getTopmostVia() == null) {
291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ListeningPointImpl lp = (ListeningPointImpl) this
292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .getListeningPoint("udp");
293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Via via = lp.getViaHeader();
294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            request.setHeader(via);
295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Give the request a quick check to see if all headers are assigned.
297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipRequest.checkHeaders();
299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(ex.getMessage(), ex);
301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        /*
304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang         * User decided to give us his own via header branch. Lets see if it
305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang         * results in a clash. If so reject the request.
306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang         */
307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipRequest.getTopmostVia().getBranch() != null
308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && sipRequest.getTopmostVia().getBranch().startsWith(
309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        SIPConstants.BRANCH_MAGIC_COOKIE)
310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && sipStack.findTransaction((SIPRequest) request, false) != null) {
311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Transaction already exists!");
313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (request.getMethod().equalsIgnoreCase(Request.CANCEL)) {
319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPClientTransaction ct = (SIPClientTransaction) sipStack
320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .findCancelTransaction((SIPRequest) request, false);
321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (ct != null) {
322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ClientTransaction retval = sipStack.createClientTransaction(
323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        (SIPRequest) request, ct.getMessageChannel());
324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ((SIPTransaction) retval).addEventListener(this);
326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.addTransaction((SIPClientTransaction) retval);
327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (ct.getDialog() != null) {
328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ((SIPClientTransaction) retval).setDialog((SIPDialog) ct
329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            .getDialog(), sipRequest.getDialogId(false));
330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return retval;
333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled())
337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug(
338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "could not find existing transaction for "
339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            + ((SIPRequest) request).getFirstLine()
340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            + " creating a new one ");
341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Could not find a dialog or the route is not set in dialog.
343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Hop hop = null;
345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            hop = sipStack.getNextHop((SIPRequest) request);
347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (hop == null)
348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new TransactionUnavailableException(
349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Cannot resolve next hop -- transaction unavailable");
350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (SipException ex) {
351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Cannot resolve next hop -- transaction unavailable", ex);
353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String transport = hop.getTransport();
355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ListeningPointImpl listeningPoint = (ListeningPointImpl) this
356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getListeningPoint(transport);
357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String dialogId = sipRequest.getDialogId(false);
359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPDialog dialog = sipStack.getDialog(dialogId);
360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (dialog != null && dialog.getState() == DialogState.TERMINATED) {
361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // throw new TransactionUnavailableException
363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // ("Found a terminated dialog -- possible re-use of old tag
364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // parameters");
365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.removeDialog(dialog);
366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // An out of dialog route was found. Assign this to the
370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // client transaction.
371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Set the brannch id before you ask for a tx.
374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // If the user has set his own branch Id and the
375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // branch id starts with a valid prefix, then take it.
376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // otherwise, generate one. If branch ID checking has
377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // been requested, set the branch ID.
378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            String branchId = null;
379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipRequest.getTopmostVia().getBranch() == null
380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    || !sipRequest.getTopmostVia().getBranch().startsWith(
381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            SIPConstants.BRANCH_MAGIC_COOKIE)
382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            || sipStack.checkBranchId() ) {
383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                branchId = Utils.getInstance().generateBranchId();
384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipRequest.getTopmostVia().setBranch(branchId);
386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Via topmostVia = sipRequest.getTopmostVia();
388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            //set port and transport if user hasn't already done this.
390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if(topmostVia.getTransport() == null)
391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                topmostVia.setTransport(transport);
392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if(topmostVia.getPort() == -1)
394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                topmostVia.setPort(listeningPoint.getPort());
395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            branchId = sipRequest.getTopmostVia().getBranch();
396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPClientTransaction ct = (SIPClientTransaction) sipStack
398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .createMessageChannel(sipRequest, listeningPoint
399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            .getMessageProcessor(), hop);
400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (ct == null)
401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new TransactionUnavailableException("Cound not create tx");
402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ct.setNextHop(hop);
403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ct.setOriginalRequest(sipRequest);
404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ct.setBranch(branchId);
405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // if the stack supports dialogs then
406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isDialogCreated(request.getMethod())) {
407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // create a new dialog to contain this transaction
408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // provided this is necessary.
409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // This could be a re-invite
410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // in which case the dialog is re-used.
411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // (but noticed by Brad Templeton)
412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (dialog != null)
413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ct.setDialog(dialog, sipRequest.getDialogId(false));
414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else if (this.isAutomaticDialogSupportEnabled()) {
415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    SIPDialog sipDialog = sipStack.createDialog(ct);
416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ct.setDialog(sipDialog, sipRequest.getDialogId(false));
417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (dialog != null) {
420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ct.setDialog(dialog, sipRequest.getDialogId(false));
421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // The provider is the event listener for all transactions.
426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ct.addEventListener(this);
427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return (ClientTransaction) ct;
428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (IOException ex) {
429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Could not resolve next hop or listening point unavailable! ",
432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ex);
433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (java.text.ParseException ex) {
435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            InternalErrorHandler.handleException(ex);
436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Unexpected Exception FIXME! ", ex);
438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (InvalidArgumentException ex) {
439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            InternalErrorHandler.handleException(ex);
440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Unexpected Exception FIXME! ", ex);
442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getNewServerTransaction(javax.sip.message.Request)
450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public ServerTransaction getNewServerTransaction(Request request)
452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws TransactionAlreadyExistsException,
453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            TransactionUnavailableException {
454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.isAlive())
456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException("Stack is stopped");
457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPServerTransaction transaction = null;
458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPRequest sipRequest = (SIPRequest) request;
459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipRequest.checkHeaders();
461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(ex.getMessage(), ex);
463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( request.getMethod().equals(Request.ACK)) {
466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if ( sipStack.isLoggingEnabled())
467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logError("Creating server transaction for ACK -- makes no sense!");
468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException("Cannot create Server transaction for ACK ");
469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        /*
471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang         * Got a notify.
472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang         */
473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipRequest.getMethod().equals(Request.NOTIFY)
474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && sipRequest.getFromTag() != null
475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && sipRequest.getToTag() == null) {
476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPClientTransaction ct = sipStack.findSubscribeTransaction(
478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipRequest, (ListeningPointImpl) this.getListeningPoint());
479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            /* Issue 104 */
480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (ct == null && ! sipStack.deliverUnsolicitedNotify) {
481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new TransactionUnavailableException(
482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Cannot find matching Subscription (and gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY not set)");
483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( !sipStack.acquireSem()) {
486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new TransactionUnavailableException(
487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            "Transaction not available -- could not acquire stack lock");
488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isDialogCreated(sipRequest.getMethod())) {
491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (sipStack.findTransaction((SIPRequest) request, true) != null)
492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new TransactionAlreadyExistsException(
493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "server transaction already exists!");
494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                transaction = (SIPServerTransaction) ((SIPRequest) request)
496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getTransaction();
497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (transaction == null)
498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new TransactionUnavailableException(
499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Transaction not available");
500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (transaction.getOriginalRequest() == null)
501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction.setOriginalRequest(sipRequest);
502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                try {
503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipStack.addTransaction(transaction);
504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } catch (IOException ex) {
505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new TransactionUnavailableException(
506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Error sending provisional response");
507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // So I can handle timeouts.
509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                transaction.addEventListener(this);
510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isAutomaticDialogSupportEnabled()) {
511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // If automatic dialog support is enabled then
512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // this tx gets his own dialog.
513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String dialogId = sipRequest.getDialogId(true);
514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    SIPDialog dialog = sipStack.getDialog(dialogId);
515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (dialog == null) {
516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        dialog = sipStack.createDialog(transaction);
517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction.setDialog(dialog, sipRequest.getDialogId(true));
520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sipStack.putInMergeTable(transaction, sipRequest);
522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    dialog.addRoute(sipRequest);
524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (dialog.getRemoteTag() != null
525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            && dialog.getLocalTag() != null) {
526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.sipStack.putDialog(dialog);
527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (isAutomaticDialogSupportEnabled()) {
532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    /*
533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                     * Under automatic dialog support, dialog is tied into a transaction. You cannot
534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                     * create a server tx except for dialog creating transactions. After that, all
535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                     * subsequent transactions are created for you by the stack.
536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                     */
537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction = (SIPServerTransaction) sipStack.findTransaction(
538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            (SIPRequest) request, true);
539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (transaction != null)
540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        throw new TransactionAlreadyExistsException(
541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Transaction exists! ");
542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction = (SIPServerTransaction) ((SIPRequest) request)
543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .getTransaction();
544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (transaction == null)
545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        throw new TransactionUnavailableException(
546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Transaction not available!");
547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (transaction.getOriginalRequest() == null)
548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        transaction.setOriginalRequest(sipRequest);
549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // Map the transaction.
550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    try {
551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sipStack.addTransaction(transaction);
552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } catch (IOException ex) {
553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        throw new TransactionUnavailableException(
554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Could not send back provisional response!");
555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // If there is a dialog already assigned then just update the
558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // dialog state.
559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String dialogId = sipRequest.getDialogId(true);
560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    SIPDialog dialog = sipStack.getDialog(dialogId);
561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (dialog != null) {
562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        dialog.addTransaction(transaction);
563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        dialog.addRoute(sipRequest);
564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        transaction.setDialog(dialog, sipRequest.getDialogId(true));
565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction = (SIPServerTransaction) sipStack.findTransaction(
569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            (SIPRequest) request, true);
570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (transaction != null)
571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        throw new TransactionAlreadyExistsException(
572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Transaction exists! ");
573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction = (SIPServerTransaction) ((SIPRequest) request)
574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .getTransaction();
575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (transaction != null) {
576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (transaction.getOriginalRequest() == null)
577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            transaction.setOriginalRequest(sipRequest);
578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        // Map the transaction.
579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sipStack.mapTransaction(transaction);
580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        // If there is a dialog already assigned then just
582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        // assign the dialog to the transaction.
583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        String dialogId = sipRequest.getDialogId(true);
584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        SIPDialog dialog = sipStack.getDialog(dialogId);
585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (dialog != null) {
586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            dialog.addTransaction(transaction);
587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            dialog.addRoute(sipRequest);
588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            transaction.setDialog(dialog, sipRequest
589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                    .getDialogId(true));
590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return transaction;
593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    } else {
594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        // tx does not exist so create the tx.
595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        MessageChannel mc = (MessageChannel) sipRequest
597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        .getMessageChannel();
598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        transaction = sipStack.createServerTransaction(mc);
599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (transaction == null)
600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            throw new TransactionUnavailableException(
601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            "Transaction unavailable -- too many servrer transactions");
602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        transaction.setOriginalRequest(sipRequest);
604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sipStack.mapTransaction(transaction);
605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        // If there is a dialog already assigned then just
607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        // assign the dialog to the transaction.
608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        String dialogId = sipRequest.getDialogId(true);
609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        SIPDialog dialog = sipStack.getDialog(dialogId);
610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        if (dialog != null) {
611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            dialog.addTransaction(transaction);
612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            dialog.addRoute(sipRequest);
613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            transaction.setDialog(dialog, sipRequest
614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                    .getDialogId(true));
615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        return transaction;
618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return transaction;
623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } finally {
624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.releaseSem();
625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getSipStack()
633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public SipStack getSipStack() {
635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return (SipStack) this.sipStack;
636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#removeSipListener(javax.sip.SipListener)
642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void removeSipListener(SipListener sipListener) {
644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipListener == this.getSipListener()) {
645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.sipListener = null;
646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        boolean found = false;
649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (Iterator<SipProviderImpl> it = sipStack.getSipProviders(); it.hasNext();) {
651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SipProviderImpl nextProvider = (SipProviderImpl) it.next();
652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (nextProvider.getSipListener() != null)
653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                found = true;
654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!found) {
656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.sipListener = null;
657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#sendRequest(javax.sip.message.Request)
664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void sendRequest(Request request) throws SipException {
666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.isAlive())
667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Stack is stopped.");
668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // mranga: added check to ensure we are not sending empty (keepalive)
670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // message.
671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (((SIPRequest) request).getRequestLine() != null
672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && request.getMethod().equals(Request.ACK)) {
673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Dialog dialog = sipStack.getDialog(((SIPRequest) request)
674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .getDialogId(false));
675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (dialog != null && dialog.getState() != null) {
676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            	if (sipStack.isLoggingEnabled())
677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            		sipStack.getStackLogger().logWarning(
678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Dialog exists -- you may want to use Dialog.sendAck() "
679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                + dialog.getState());
680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Hop hop = sipStack.getRouter((SIPRequest) request).getNextHop(request);
683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (hop == null)
684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("could not determine next hop!");
685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPRequest sipRequest = (SIPRequest) request;
686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Check if we have a valid via.
687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Null request is used to send default proxy keepalive messages.
688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ((!sipRequest.isNullRequest()) && sipRequest.getTopmostVia() == null)
689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Invalid SipRequest -- no via header!");
690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            /*
693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * JvB: Via branch should already be OK, dont touch it here? Some
694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * apps forward statelessly, and then it's not set. So set only when
695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * not set already, dont overwrite CANCEL branch here..
696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             */
697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (!sipRequest.isNullRequest()) {
698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Via via = sipRequest.getTopmostVia();
699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String branch = via.getBranch();
700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (branch == null || branch.length() == 0) {
701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    via.setBranch(sipRequest.getTransactionId());
702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            MessageChannel messageChannel = null;
705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (this.listeningPoints.containsKey(hop.getTransport()
706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .toUpperCase()))
707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                messageChannel = sipStack.createRawMessageChannel(
708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.getListeningPoint(hop.getTransport()).getIPAddress(),
709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.getListeningPoint(hop.getTransport()).getPort(), hop);
710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (messageChannel != null) {
711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                messageChannel.sendMessage((SIPMessage) sipRequest,hop);
712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new SipException(
714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Could not create a message channel for "
715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                + hop.toString());
716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (IOException ex) {
718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logException(ex);
720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException(
723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "IO Exception occured while Sending Request", ex);
724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex1) {
726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            InternalErrorHandler.handleException(ex1);
727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } finally {
728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled())
729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug(
730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "done sending " + request.getMethod() + " to hop "
731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                + hop);
732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#sendResponse(javax.sip.message.Response)
739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void sendResponse(Response response) throws SipException {
741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.isAlive())
742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Stack is stopped");
743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPResponse sipResponse = (SIPResponse) response;
744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Via via = sipResponse.getTopmostVia();
745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (via == null)
746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("No via header in response!");
747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPServerTransaction st = (SIPServerTransaction) sipStack.findTransaction((SIPMessage)response, true);
748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( st != null   && st.getState() != TransactionState.TERMINATED && this.isAutomaticDialogSupportEnabled()) {
749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Transaction exists -- cannot send response statelessly");
750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String transport = via.getTransport();
752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // check to see if Via has "received paramaeter". If so
754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // set the host to the via parameter. Else set it to the
755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Via host.
756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String host = via.getReceived();
757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (host == null)
759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            host = via.getHost();
760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Symmetric nat support
762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int port = via.getRPort();
763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (port == -1) {
764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            port = via.getPort();
765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (port == -1) {
766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (transport.equalsIgnoreCase("TLS"))
767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    port = 5061;
768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                else
769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    port = 5060;
770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // for correct management of IPv6 addresses.
774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (host.indexOf(":") > 0)
775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (host.indexOf("[") < 0)
776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                host = "[" + host + "]";
777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Hop hop = sipStack.getAddressResolver().resolveAddress(
779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                new HopImpl(host, port, transport));
780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ListeningPointImpl listeningPoint = (ListeningPointImpl) this
783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    .getListeningPoint(transport);
784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (listeningPoint == null)
785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new SipException(
786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "whoopsa daisy! no listening point found for transport "
787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                + transport);
788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            MessageChannel messageChannel = sipStack.createRawMessageChannel(
789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.getListeningPoint(hop.getTransport()).getIPAddress(),
790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    listeningPoint.port, hop);
791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            messageChannel.sendMessage(sipResponse);
792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (IOException ex) {
793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException(ex.getMessage());
794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#setListeningPoint(javax.sip.ListeningPoint)
801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public synchronized void setListeningPoint(ListeningPoint listeningPoint) {
803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (listeningPoint == null)
804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new NullPointerException("Null listening point");
805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ListeningPointImpl lp = (ListeningPointImpl) listeningPoint;
806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        lp.sipProvider = this;
807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String transport = lp.getTransport().toUpperCase();
808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.address = listeningPoint.getIPAddress();
809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.port = listeningPoint.getPort();
810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // This is the first listening point.
811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.listeningPoints.clear();
812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.listeningPoints.put(transport, listeningPoint);
813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getNewDialog(javax.sip.Transaction)
820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Dialog getNewDialog(Transaction transaction) throws SipException {
823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (transaction == null)
824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new NullPointerException("Null transaction!");
825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.isAlive())
827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Stack is stopped.");
828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (isAutomaticDialogSupportEnabled())
830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException(" Error - AUTOMATIC_DIALOG_SUPPORT is on");
831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (!sipStack.isDialogCreated(transaction.getRequest().getMethod()))
833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Dialog cannot be created for this method "
834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    + transaction.getRequest().getMethod());
835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPDialog dialog = null;
837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPTransaction sipTransaction = (SIPTransaction) transaction;
838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (transaction instanceof ServerTransaction) {
840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPServerTransaction st = (SIPServerTransaction) transaction;
841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Response response = st.getLastResponse();
842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (response != null) {
843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (response.getStatusCode() != 100)
844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new SipException(
845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            "Cannot set dialog after response has been sent");
846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            String dialogId = sipRequest.getDialogId(true);
849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            dialog = sipStack.getDialog(dialogId);
850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (dialog == null) {
851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                dialog = sipStack.createDialog((SIPTransaction) transaction);
852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // create and register the dialog and add the inital route set.
853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                dialog.addTransaction(sipTransaction);
854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                dialog.addRoute(sipRequest);
855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipTransaction.setDialog(dialog, null);
856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipTransaction.setDialog(dialog, sipRequest.getDialogId(true));
859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.putInMergeTable(st, sipRequest);
862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPClientTransaction sipClientTx = (SIPClientTransaction) transaction;
866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPResponse response = sipClientTx.getLastResponse();
868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (response == null) {
870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // A response has not yet been received, then set this up as the
871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // default dialog.
872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                SIPRequest request = (SIPRequest) sipClientTx.getRequest();
873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String dialogId = request.getDialogId(false);
875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                dialog = sipStack.getDialog(dialogId);
876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (dialog != null) {
877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    throw new SipException("Dialog already exists!");
878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    dialog = sipStack.createDialog(sipTransaction);
880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipClientTx.setDialog(dialog, null);
882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new SipException(
885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Cannot call this method after response is received!");
886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        dialog.addEventListener(this);
889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return dialog;
890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Invoked when an error has ocurred with a transaction. Propagate up to the
895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * listeners.
896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param transactionErrorEvent
898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Error event.
899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void transactionErrorEvent(
901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPTransactionErrorEvent transactionErrorEvent) {
902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPTransaction transaction = (SIPTransaction) transactionErrorEvent
903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getSource();
904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) {
906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // There must be a way to inform the TU here!!
907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug(
909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "TransportError occured on " + transaction);
910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Treat this like a timeout event. (Suggestion from Christophe).
912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Object errorObject = transactionErrorEvent.getSource();
913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Timeout timeout = Timeout.TRANSACTION;
914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            TimeoutEvent ev = null;
915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (errorObject instanceof SIPServerTransaction) {
917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ev = new TimeoutEvent(this, (ServerTransaction) errorObject,
918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        timeout);
919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                SIPClientTransaction clientTx = (SIPClientTransaction) errorObject;
921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Hop hop = clientTx.getNextHop();
922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ( sipStack.getRouter() instanceof RouterExt ) {
923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ((RouterExt) sipStack.getRouter()).transactionTimeout(hop);
924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ev = new TimeoutEvent(this, (ClientTransaction) errorObject,
926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        timeout);
927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Handling transport error like timeout
929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.handleEvent(ev, (SIPTransaction) errorObject);
930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TIMEOUT_ERROR) {
931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // This is a timeout event.
932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Object errorObject = transactionErrorEvent.getSource();
933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Timeout timeout = Timeout.TRANSACTION;
934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            TimeoutEvent ev = null;
935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (errorObject instanceof SIPServerTransaction) {
937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ev = new TimeoutEvent(this, (ServerTransaction) errorObject,
938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        timeout);
939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                SIPClientTransaction clientTx = (SIPClientTransaction) errorObject;
941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Hop hop = clientTx.getNextHop();
942600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ( sipStack.getRouter() instanceof RouterExt ) {
943600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ((RouterExt) sipStack.getRouter()).transactionTimeout(hop);
944600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
945600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
946600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ev = new TimeoutEvent(this, (ClientTransaction) errorObject,
947600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        timeout);
948600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
949600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.handleEvent(ev, (SIPTransaction) errorObject);
950600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
951600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) {
952600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // This is a timeout retransmit event.
953600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // We should never get this if retransmit filter is
954600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // enabled (ie. in that case the stack should handle.
955600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // all retransmits.
956600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Object errorObject = transactionErrorEvent.getSource();
957600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Transaction tx = (Transaction) errorObject;
958600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
959600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (tx.getDialog() != null)
960600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                InternalErrorHandler.handleException("Unexpected event !",
961600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        this.sipStack.getStackLogger());
962600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
963600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Timeout timeout = Timeout.RETRANSMIT;
964600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            TimeoutEvent ev = null;
965600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
966600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (errorObject instanceof SIPServerTransaction) {
967600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ev = new TimeoutEvent(this, (ServerTransaction) errorObject,
968600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        timeout);
969600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
970600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ev = new TimeoutEvent(this, (ClientTransaction) errorObject,
971600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        timeout);
972600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
973600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.handleEvent(ev, (SIPTransaction) errorObject);
974600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
975600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
976600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
977600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
978600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
979600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see gov.nist.javax.sip.stack.SIPDialogEventListener#dialogErrorEvent(gov.nist.javax.sip.stack.SIPDialogErrorEvent)
980600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
981600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public synchronized void dialogErrorEvent(SIPDialogErrorEvent dialogErrorEvent) {
982600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPDialog sipDialog = (SIPDialog) dialogErrorEvent.getSource();
983600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Reason reason = Reason.AckNotReceived;
984600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT) {
985600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        	reason= Reason.AckNotSent;
986600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else if (dialogErrorEvent.getErrorID() == SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT) {
987600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            reason = Reason.ReInviteTimeout;
988600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
989600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled()) {
990600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug(
991600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Dialog TimeoutError occured on " + sipDialog);
992600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
993600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        DialogTimeoutEvent ev = new DialogTimeoutEvent(this, sipDialog, reason);
994600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Handling transport error like timeout
995600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.handleEvent(ev, null);
996600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
997600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
998600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
999600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
1000600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1001600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#getListeningPoints()
1002600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1003600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public synchronized ListeningPoint[] getListeningPoints() {
1004600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1005600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ListeningPoint[] retval = new ListeningPointImpl[this.listeningPoints
1006600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .size()];
1007600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.listeningPoints.values().toArray(retval);
1008600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval;
1009600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1010600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1011600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
1012600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
1013600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1014600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#addListeningPoint(javax.sip.ListeningPoint)
1015600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1016600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public synchronized void addListeningPoint(ListeningPoint listeningPoint)
1017600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws ObjectInUseException {
1018600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ListeningPointImpl lp = (ListeningPointImpl) listeningPoint;
1019600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (lp.sipProvider != null && lp.sipProvider != this)
1020600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new ObjectInUseException(
1021600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Listening point assigned to another provider");
1022600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String transport = lp.getTransport().toUpperCase();
1023600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.listeningPoints.isEmpty()) {
1024600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // first one -- record the IP address/port of the LP
1025600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1026600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.address = listeningPoint.getIPAddress();
1027600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.port = listeningPoint.getPort();
1028600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
1029600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if ((!this.address.equals(listeningPoint.getIPAddress()))
1030600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    || this.port != listeningPoint.getPort())
1031600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new ObjectInUseException(
1032600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Provider already has different IP Address associated");
1033600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1034600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1035600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.listeningPoints.containsKey(transport)
1036600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && this.listeningPoints.get(transport) != listeningPoint)
1037600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new ObjectInUseException(
1038600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Listening point already assigned for transport!");
1039600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1040600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // This is for backwards compatibility.
1041600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        lp.sipProvider = this;
1042600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1043600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.listeningPoints.put(transport, lp);
1044600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1045600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1046600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1047600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
1048600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
1049600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1050600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#removeListeningPoint(javax.sip.ListeningPoint)
1051600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1052600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public synchronized void removeListeningPoint(ListeningPoint listeningPoint)
1053600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws ObjectInUseException {
1054600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ListeningPointImpl lp = (ListeningPointImpl) listeningPoint;
1055600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (lp.messageProcessor.inUse())
1056600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new ObjectInUseException("Object is in use");
1057600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.listeningPoints.remove(lp.getTransport().toUpperCase());
1058600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1059600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1060600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1061600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1062600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Remove all the listening points for this sip provider. This is called
1063600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * when the stack removes the Provider
1064600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1065600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public synchronized void removeListeningPoints() {
1066600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (Iterator it = this.listeningPoints.values().iterator(); it
1067600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .hasNext();) {
1068600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ListeningPointImpl lp = (ListeningPointImpl) it.next();
1069600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            lp.messageProcessor.stop();
1070600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            it.remove();
1071600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1072600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1073600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1074600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1075600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
1076600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
1077600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1078600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see javax.sip.SipProvider#setAutomaticDialogSupportEnabled(boolean)
1079600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1080600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setAutomaticDialogSupportEnabled(
1081600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            boolean automaticDialogSupportEnabled) {
1082600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.automaticDialogSupportEnabled = automaticDialogSupportEnabled;
1083600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if ( this.automaticDialogSupportEnabled ) {
1084600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.dialogErrorsAutomaticallyHandled = true;
1085600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1086600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1087600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1088600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1089600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return Returns the automaticDialogSupportEnabled.
1090600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1091600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean isAutomaticDialogSupportEnabled() {
1092600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return automaticDialogSupportEnabled;
1093600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1094600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1095600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
1096600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
1097600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see gov.nist.javax.sip.SipProviderExt#setDialogErrorsAutomaticallyHandled()
1098600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1099600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setDialogErrorsAutomaticallyHandled() {
1100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.dialogErrorsAutomaticallyHandled = true;
1101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean isDialogErrorsAutomaticallyHandled() {
1104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.dialogErrorsAutomaticallyHandled;
1105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the sipListener
1110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public SipListener getSipListener() {
1112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return sipListener;
1113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
1117