• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Conditions Of Use
3  *
4  * This software was developed by employees of the National Institute of
5  * Standards and Technology (NIST), an agency of the Federal Government.
6  * Pursuant to title 15 Untied States Code Section 105, works of NIST
7  * employees are not subject to copyright protection in the United States
8  * and are considered to be in the public domain.  As a result, a formal
9  * license is not needed to use the software.
10  *
11  * This software is provided by NIST as a service and is expressly
12  * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13  * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15  * AND DATA ACCURACY.  NIST does not warrant or make any representations
16  * regarding the use of the software or the results thereof, including but
17  * not limited to the correctness, accuracy, reliability or usefulness of
18  * the software.
19  *
20  * Permission to use this software is contingent upon your acceptance
21  * of the terms of this agreement
22  *
23  * .
24  *
25  */
26 package gov.nist.javax.sip.stack;
27 
28 import gov.nist.core.InternalErrorHandler;
29 import gov.nist.javax.sip.SIPConstants;
30 import gov.nist.javax.sip.SipProviderImpl;
31 import gov.nist.javax.sip.header.CallID;
32 import gov.nist.javax.sip.header.Event;
33 import gov.nist.javax.sip.header.From;
34 import gov.nist.javax.sip.header.To;
35 import gov.nist.javax.sip.header.Via;
36 import gov.nist.javax.sip.header.ViaList;
37 import gov.nist.javax.sip.message.SIPMessage;
38 import gov.nist.javax.sip.message.SIPRequest;
39 import gov.nist.javax.sip.message.SIPResponse;
40 
41 import java.io.IOException;
42 import java.net.InetAddress;
43 import java.util.Collections;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.Set;
47 import java.util.concurrent.Semaphore;
48 import java.util.concurrent.TimeUnit;
49 import java.util.concurrent.atomic.AtomicBoolean;
50 
51 import javax.net.ssl.SSLPeerUnverifiedException;
52 import javax.sip.Dialog;
53 import javax.sip.IOExceptionEvent;
54 import javax.sip.ServerTransaction;
55 import javax.sip.TransactionState;
56 import javax.sip.message.Request;
57 import javax.sip.message.Response;
58 
59 /*
60  * Modifications for TLS Support added by Daniel J. Martinez Manzano
61  * <dani@dif.um.es> Bug fixes by Jeroen van Bemmel (JvB) and others.
62  */
63 
64 /**
65  * Abstract class to support both client and server transactions. Provides an
66  * encapsulation of a message channel, handles timer events, and creation of the
67  * Via header for a message.
68  *
69  * @author Jeff Keyser
70  * @author M. Ranganathan
71  *
72  *
73  * @version 1.2 $Revision: 1.71 $ $Date: 2009/11/29 04:31:29 $
74  */
75 public abstract class SIPTransaction extends MessageChannel implements
76         javax.sip.Transaction, gov.nist.javax.sip.TransactionExt {
77 
78     protected boolean toListener; // Flag to indicate that the listener gets
79 
80     // to see the event.
81 
82     protected int BASE_TIMER_INTERVAL = SIPTransactionStack.BASE_TIMER_INTERVAL;
83     /**
84      * 5 sec Maximum duration a message will remain in the network
85      */
86     protected int T4 = 5000 / BASE_TIMER_INTERVAL;
87 
88     /**
89      * The maximum retransmit interval for non-INVITE requests and INVITE
90      * responses
91      */
92     protected int T2 = 4000 / BASE_TIMER_INTERVAL;
93     protected int TIMER_I = T4;
94 
95     protected int TIMER_K = T4;
96 
97     protected int TIMER_D = 32000 / BASE_TIMER_INTERVAL;
98 
99     // protected static final int TIMER_C = 3 * 60 * 1000 / BASE_TIMER_INTERVAL;
100 
101     /**
102      * One timer tick.
103      */
104     protected static final int T1 = 1;
105 
106     /**
107      * INVITE request retransmit interval, for UDP only
108      */
109     protected static final int TIMER_A = 1;
110 
111     /**
112      * INVITE transaction timeout timer
113      */
114     protected static final int TIMER_B = 64;
115 
116     protected static final int TIMER_J = 64;
117 
118     protected static final int TIMER_F = 64;
119 
120     protected static final int TIMER_H = 64;
121 
122     // Proposed feature for next release.
123     protected transient Object applicationData;
124 
125     protected SIPResponse lastResponse;
126 
127     // private SIPDialog dialog;
128 
129     protected boolean isMapped;
130 
131     private Semaphore semaphore;
132 
133     protected boolean isSemaphoreAquired;
134 
135     // protected boolean eventPending; // indicate that an event is pending
136     // here.
137 
138     protected String transactionId; // Transaction Id.
139 
140     // Audit tag used by the SIP Stack audit
141     public long auditTag = 0;
142 
143     /**
144      * Initialized but no state assigned.
145      */
146     public static final TransactionState INITIAL_STATE = null;
147 
148     /**
149      * Trying state.
150      */
151     public static final TransactionState TRYING_STATE = TransactionState.TRYING;
152 
153     /**
154      * CALLING State.
155      */
156     public static final TransactionState CALLING_STATE = TransactionState.CALLING;
157 
158     /**
159      * Proceeding state.
160      */
161     public static final TransactionState PROCEEDING_STATE = TransactionState.PROCEEDING;
162 
163     /**
164      * Completed state.
165      */
166     public static final TransactionState COMPLETED_STATE = TransactionState.COMPLETED;
167 
168     /**
169      * Confirmed state.
170      */
171     public static final TransactionState CONFIRMED_STATE = TransactionState.CONFIRMED;
172 
173     /**
174      * Terminated state.
175      */
176     public static final TransactionState TERMINATED_STATE = TransactionState.TERMINATED;
177 
178     /**
179      * Maximum number of ticks between retransmissions.
180      */
181     protected static final int MAXIMUM_RETRANSMISSION_TICK_COUNT = 8;
182 
183     // Parent stack for this transaction
184     protected transient SIPTransactionStack sipStack;
185 
186     // Original request that is being handled by this transaction
187     protected SIPRequest originalRequest;
188 
189     // Underlying channel being used to send messages for this transaction
190     private transient MessageChannel encapsulatedChannel;
191 
192     // Port of peer
193     protected int peerPort;
194 
195     // Address of peer
196     protected InetAddress peerInetAddress;
197 
198     // Address of peer as a string
199     protected String peerAddress;
200 
201     // Protocol of peer
202     protected String peerProtocol;
203 
204     // @@@ hagai - NAT changes
205     // Source port extracted from peer packet
206     protected int peerPacketSourcePort;
207 
208     protected InetAddress peerPacketSourceAddress;
209 
210     protected AtomicBoolean transactionTimerStarted = new AtomicBoolean(false);
211 
212     // Transaction branch ID
213     private String branch;
214 
215     // Method of the Request used to create the transaction.
216     private String method;
217 
218     // Sequence number of request used to create the transaction
219     private long cSeq;
220 
221     // Current transaction state
222     private TransactionState currentState;
223 
224     // Number of ticks the retransmission timer was set to last
225     private transient int retransmissionTimerLastTickCount;
226 
227     // Number of ticks before the message is retransmitted
228     private transient int retransmissionTimerTicksLeft;
229 
230     // Number of ticks before the transaction times out
231     protected int timeoutTimerTicksLeft;
232 
233     // List of event listeners for this transaction
234     private transient Set<SIPTransactionEventListener> eventListeners;
235 
236     // Hang on to these - we clear out the request URI after
237     // transaction goes to final state. Pointers to these are kept around
238     // for transaction matching as long as the transaction is in
239     // the transaction table.
240     protected From from;
241 
242     protected To to;
243 
244     protected Event event;
245 
246     protected CallID callId;
247 
248     // Back ptr to the JAIN layer.
249     // private Object wrapper;
250 
251     // Counter for caching of connections.
252     // Connection lingers for collectionTime
253     // after the Transaction goes to terminated state.
254     protected int collectionTime;
255 
256     protected String toTag;
257 
258     protected String fromTag;
259 
260     private boolean terminatedEventDelivered;
261 
getBranchId()262     public String getBranchId() {
263         return this.branch;
264     }
265 
266     /**
267      * The linger timer is used to remove the transaction from the transaction
268      * table after it goes into terminated state. This allows connection caching
269      * and also takes care of race conditins.
270      *
271      *
272      */
273     class LingerTimer extends SIPStackTimerTask {
274 
LingerTimer()275         public LingerTimer() {
276             SIPTransaction sipTransaction = SIPTransaction.this;
277             if (sipStack.isLoggingEnabled()) {
278                 sipStack.getStackLogger().logDebug("LingerTimer : "
279                         + sipTransaction.getTransactionId());
280             }
281 
282         }
283 
runTask()284         protected void runTask() {
285             SIPTransaction transaction = SIPTransaction.this;
286             // release the connection associated with this transaction.
287             SIPTransactionStack sipStack = transaction.getSIPStack();
288 
289             if (sipStack.isLoggingEnabled()) {
290                 sipStack.getStackLogger().logDebug("LingerTimer: run() : "
291                         + getTransactionId());
292             }
293 
294             if (transaction instanceof SIPClientTransaction) {
295                 sipStack.removeTransaction(transaction);
296                 transaction.close();
297 
298             } else if (transaction instanceof ServerTransaction) {
299                 // Remove it from the set
300                 if (sipStack.isLoggingEnabled())
301                     sipStack.getStackLogger().logDebug("removing" + transaction);
302                 sipStack.removeTransaction(transaction);
303                 if ((!sipStack.cacheServerConnections)
304                         && --transaction.encapsulatedChannel.useCount <= 0) {
305                     // Close the encapsulated socket if stack is configured
306                     transaction.close();
307                 } else {
308                     if (sipStack.isLoggingEnabled()
309                             && (!sipStack.cacheServerConnections)
310                             && transaction.isReliable()) {
311                         int useCount = transaction.encapsulatedChannel.useCount;
312                         sipStack.getStackLogger().logDebug("Use Count = " + useCount);
313                     }
314                 }
315             }
316 
317         }
318     }
319 
320     /**
321      * Transaction constructor.
322      *
323      * @param newParentStack
324      *            Parent stack for this transaction.
325      * @param newEncapsulatedChannel
326      *            Underlying channel for this transaction.
327      */
SIPTransaction(SIPTransactionStack newParentStack, MessageChannel newEncapsulatedChannel)328     protected SIPTransaction(SIPTransactionStack newParentStack,
329             MessageChannel newEncapsulatedChannel) {
330 
331         sipStack = newParentStack;
332         this.semaphore = new Semaphore(1,true);
333 
334         encapsulatedChannel = newEncapsulatedChannel;
335         // Record this to check if the address has changed before sending
336         // message to avoid possible race condition.
337         this.peerPort = newEncapsulatedChannel.getPeerPort();
338         this.peerAddress = newEncapsulatedChannel.getPeerAddress();
339         this.peerInetAddress = newEncapsulatedChannel.getPeerInetAddress();
340         // @@@ hagai
341         this.peerPacketSourcePort = newEncapsulatedChannel
342                 .getPeerPacketSourcePort();
343         this.peerPacketSourceAddress = newEncapsulatedChannel
344                 .getPeerPacketSourceAddress();
345         this.peerProtocol = newEncapsulatedChannel.getPeerProtocol();
346         if (this.isReliable()) {
347                 encapsulatedChannel.useCount++;
348                 if (sipStack.isLoggingEnabled())
349                     sipStack.getStackLogger()
350                             .logDebug("use count for encapsulated channel"
351                                     + this
352                                     + " "
353                                     + encapsulatedChannel.useCount );
354         }
355 
356         this.currentState = null;
357 
358         disableRetransmissionTimer();
359         disableTimeoutTimer();
360         eventListeners = Collections.synchronizedSet(new HashSet<SIPTransactionEventListener>());
361 
362         // Always add the parent stack as a listener
363         // of this transaction
364         addEventListener(newParentStack);
365 
366     }
367 
368     /**
369      * Sets the request message that this transaction handles.
370      *
371      * @param newOriginalRequest
372      *            Request being handled.
373      */
setOriginalRequest(SIPRequest newOriginalRequest)374     public void setOriginalRequest(SIPRequest newOriginalRequest) {
375 
376         // Branch value of topmost Via header
377         String newBranch;
378 
379         if (this.originalRequest != null
380                 && (!this.originalRequest.getTransactionId().equals(
381                         newOriginalRequest.getTransactionId()))) {
382             sipStack.removeTransactionHash(this);
383         }
384         // This will be cleared later.
385 
386         this.originalRequest = newOriginalRequest;
387 
388         // just cache the control information so the
389         // original request can be released later.
390         this.method = newOriginalRequest.getMethod();
391         this.from = (From) newOriginalRequest.getFrom();
392         this.to = (To) newOriginalRequest.getTo();
393         // Save these to avoid concurrent modification exceptions!
394         this.toTag = this.to.getTag();
395         this.fromTag = this.from.getTag();
396         this.callId = (CallID) newOriginalRequest.getCallId();
397         this.cSeq = newOriginalRequest.getCSeq().getSeqNumber();
398         this.event = (Event) newOriginalRequest.getHeader("Event");
399         this.transactionId = newOriginalRequest.getTransactionId();
400 
401         originalRequest.setTransaction(this);
402 
403         // If the message has an explicit branch value set,
404         newBranch = ((Via) newOriginalRequest.getViaHeaders().getFirst())
405                 .getBranch();
406         if (newBranch != null) {
407             if (sipStack.isLoggingEnabled())
408                 sipStack.getStackLogger().logDebug("Setting Branch id : " + newBranch);
409 
410             // Override the default branch with the one
411             // set by the message
412             setBranch(newBranch);
413 
414         } else {
415             if (sipStack.isLoggingEnabled())
416                 sipStack.getStackLogger().logDebug("Branch id is null - compute TID!"
417                         + newOriginalRequest.encode());
418             setBranch(newOriginalRequest.getTransactionId());
419         }
420     }
421 
422     /**
423      * Gets the request being handled by this transaction.
424      *
425      * @return -- the original Request associated with this transaction.
426      */
getOriginalRequest()427     public SIPRequest getOriginalRequest() {
428         return originalRequest;
429     }
430 
431     /**
432      * Get the original request but cast to a Request structure.
433      *
434      * @return the request that generated this transaction.
435      */
getRequest()436     public Request getRequest() {
437         return (Request) originalRequest;
438     }
439 
440     /**
441      * Returns a flag stating whether this transaction is for an INVITE request
442      * or not.
443      *
444      * @return -- true if this is an INVITE request, false if not.
445      */
isInviteTransaction()446     public final boolean isInviteTransaction() {
447         return getMethod().equals(Request.INVITE);
448     }
449 
450     /**
451      * Return true if the transaction corresponds to a CANCEL message.
452      *
453      * @return -- true if the transaciton is a CANCEL transaction.
454      */
isCancelTransaction()455     public final boolean isCancelTransaction() {
456         return getMethod().equals(Request.CANCEL);
457     }
458 
459     /**
460      * Return a flag that states if this is a BYE transaction.
461      *
462      * @return true if the transaciton is a BYE transaction.
463      */
isByeTransaction()464     public final boolean isByeTransaction() {
465         return getMethod().equals(Request.BYE);
466     }
467 
468     /**
469      * Returns the message channel used for transmitting/receiving messages for
470      * this transaction. Made public in support of JAIN dual transaction model.
471      *
472      * @return Encapsulated MessageChannel.
473      *
474      */
getMessageChannel()475     public MessageChannel getMessageChannel() {
476         return encapsulatedChannel;
477     }
478 
479     /**
480      * Sets the Via header branch parameter used to identify this transaction.
481      *
482      * @param newBranch
483      *            New string used as the branch for this transaction.
484      */
setBranch(String newBranch)485     public final void setBranch(String newBranch) {
486         branch = newBranch;
487     }
488 
489     /**
490      * Gets the current setting for the branch parameter of this transaction.
491      *
492      * @return Branch parameter for this transaction.
493      */
getBranch()494     public final String getBranch() {
495         if (this.branch == null) {
496             this.branch = getOriginalRequest().getTopmostVia().getBranch();
497         }
498         return branch;
499     }
500 
501     /**
502      * Get the method of the request used to create this transaction.
503      *
504      * @return the method of the request for the transaction.
505      */
getMethod()506     public final String getMethod() {
507         return this.method;
508     }
509 
510     /**
511      * Get the Sequence number of the request used to create the transaction.
512      *
513      * @return the cseq of the request used to create the transaction.
514      */
getCSeq()515     public final long getCSeq() {
516         return this.cSeq;
517     }
518 
519     /**
520      * Changes the state of this transaction.
521      *
522      * @param newState
523      *            New state of this transaction.
524      */
setState(TransactionState newState)525     public void setState(TransactionState newState) {
526         // PATCH submitted by sribeyron
527         if (currentState == TransactionState.COMPLETED) {
528             if (newState != TransactionState.TERMINATED
529                     && newState != TransactionState.CONFIRMED)
530                 newState = TransactionState.COMPLETED;
531         }
532         if (currentState == TransactionState.CONFIRMED) {
533             if (newState != TransactionState.TERMINATED)
534                 newState = TransactionState.CONFIRMED;
535         }
536         if (currentState != TransactionState.TERMINATED)
537             currentState = newState;
538         else
539             newState = currentState;
540         // END OF PATCH
541         if (sipStack.isLoggingEnabled()) {
542             sipStack.getStackLogger().logDebug("Transaction:setState " + newState
543                     + " " + this + " branchID = " + this.getBranch()
544                     + " isClient = " + (this instanceof SIPClientTransaction));
545             sipStack.getStackLogger().logStackTrace();
546         }
547     }
548 
549     /**
550      * Gets the current state of this transaction.
551      *
552      * @return Current state of this transaction.
553      */
getState()554     public TransactionState getState() {
555         return this.currentState;
556     }
557 
558     /**
559      * Enables retransmission timer events for this transaction to begin in one
560      * tick.
561      */
enableRetransmissionTimer()562     protected final void enableRetransmissionTimer() {
563         enableRetransmissionTimer(1);
564     }
565 
566     /**
567      * Enables retransmission timer events for this transaction to begin after
568      * the number of ticks passed to this routine.
569      *
570      * @param tickCount
571      *            Number of ticks before the next retransmission timer event
572      *            occurs.
573      */
enableRetransmissionTimer(int tickCount)574     protected final void enableRetransmissionTimer(int tickCount) {
575         // For INVITE Client transactions, double interval each time
576         if (isInviteTransaction() && (this instanceof SIPClientTransaction)) {
577             retransmissionTimerTicksLeft = tickCount;
578         } else {
579             // non-INVITE transactions and 3xx-6xx responses are capped at T2
580             retransmissionTimerTicksLeft = Math.min(tickCount,
581                     MAXIMUM_RETRANSMISSION_TICK_COUNT);
582         }
583         retransmissionTimerLastTickCount = retransmissionTimerTicksLeft;
584     }
585 
586     /**
587      * Turns off retransmission events for this transaction.
588      */
disableRetransmissionTimer()589     protected final void disableRetransmissionTimer() {
590         retransmissionTimerTicksLeft = -1;
591     }
592 
593     /**
594      * Enables a timeout event to occur for this transaction after the number of
595      * ticks passed to this method.
596      *
597      * @param tickCount
598      *            Number of ticks before this transaction times out.
599      */
enableTimeoutTimer(int tickCount)600     protected final void enableTimeoutTimer(int tickCount) {
601         if (sipStack.isLoggingEnabled())
602             sipStack.getStackLogger().logDebug("enableTimeoutTimer " + this
603                     + " tickCount " + tickCount + " currentTickCount = "
604                     + timeoutTimerTicksLeft);
605 
606         timeoutTimerTicksLeft = tickCount;
607     }
608 
609     /**
610      * Disabled the timeout timer.
611      */
disableTimeoutTimer()612     protected final void disableTimeoutTimer() {
613         timeoutTimerTicksLeft = -1;
614     }
615 
616     /**
617      * Fired after each timer tick. Checks the retransmission and timeout timers
618      * of this transaction, and fired these events if necessary.
619      */
fireTimer()620     final void fireTimer() {
621         // If the timeout timer is enabled,
622 
623         if (timeoutTimerTicksLeft != -1) {
624             // Count down the timer, and if it has run out,
625             if (--timeoutTimerTicksLeft == 0) {
626                 // Fire the timeout timer
627                 fireTimeoutTimer();
628             }
629         }
630 
631         // If the retransmission timer is enabled,
632         if (retransmissionTimerTicksLeft != -1) {
633             // Count down the timer, and if it has run out,
634             if (--retransmissionTimerTicksLeft == 0) {
635                 // Enable this timer to fire again after
636                 // twice the original time
637                 enableRetransmissionTimer(retransmissionTimerLastTickCount * 2);
638                 // Fire the timeout timer
639                 fireRetransmissionTimer();
640             }
641         }
642     }
643 
644     /**
645      * Tests if this transaction has terminated.
646      *
647      * @return Trus if this transaction is terminated, false if not.
648      */
isTerminated()649     public final boolean isTerminated() {
650         return getState() == TERMINATED_STATE;
651     }
652 
getHost()653     public String getHost() {
654         return encapsulatedChannel.getHost();
655     }
656 
getKey()657     public String getKey() {
658         return encapsulatedChannel.getKey();
659     }
660 
getPort()661     public int getPort() {
662         return encapsulatedChannel.getPort();
663     }
664 
getSIPStack()665     public SIPTransactionStack getSIPStack() {
666         return (SIPTransactionStack) sipStack;
667     }
668 
getPeerAddress()669     public String getPeerAddress() {
670         return this.peerAddress;
671     }
672 
getPeerPort()673     public int getPeerPort() {
674         return this.peerPort;
675     }
676 
677     // @@@ hagai
getPeerPacketSourcePort()678     public int getPeerPacketSourcePort() {
679         return this.peerPacketSourcePort;
680     }
681 
getPeerPacketSourceAddress()682     public InetAddress getPeerPacketSourceAddress() {
683         return this.peerPacketSourceAddress;
684     }
685 
getPeerInetAddress()686     protected InetAddress getPeerInetAddress() {
687         return this.peerInetAddress;
688     }
689 
getPeerProtocol()690     protected String getPeerProtocol() {
691         return this.peerProtocol;
692     }
693 
getTransport()694     public String getTransport() {
695         return encapsulatedChannel.getTransport();
696     }
697 
isReliable()698     public boolean isReliable() {
699         return encapsulatedChannel.isReliable();
700     }
701 
702     /**
703      * Returns the Via header for this channel. Gets the Via header of the
704      * underlying message channel, and adds a branch parameter to it for this
705      * transaction.
706      */
getViaHeader()707     public Via getViaHeader() {
708         // Via header of the encapulated channel
709         Via channelViaHeader;
710 
711         // Add the branch parameter to the underlying
712         // channel's Via header
713         channelViaHeader = super.getViaHeader();
714         try {
715             channelViaHeader.setBranch(branch);
716         } catch (java.text.ParseException ex) {
717         }
718         return channelViaHeader;
719 
720     }
721 
722     /**
723      * Process the message through the transaction and sends it to the SIP peer.
724      *
725      * @param messageToSend
726      *            Message to send to the SIP peer.
727      */
sendMessage(SIPMessage messageToSend)728     public void sendMessage(SIPMessage messageToSend) throws IOException {
729         // Use the peer address, port and transport
730         // that was specified when the transaction was
731         // created. Bug was noted by Bruce Evangelder
732         // soleo communications.
733         try {
734             encapsulatedChannel.sendMessage(messageToSend,
735                     this.peerInetAddress, this.peerPort);
736         } finally {
737             this.startTransactionTimer();
738         }
739     }
740 
741     /**
742      * Parse the byte array as a message, process it through the transaction,
743      * and send it to the SIP peer. This is just a placeholder method -- calling
744      * it will result in an IO exception.
745      *
746      * @param messageBytes
747      *            Bytes of the message to send.
748      * @param receiverAddress
749      *            Address of the target peer.
750      * @param receiverPort
751      *            Network port of the target peer.
752      *
753      * @throws IOException
754      *             If called.
755      */
sendMessage(byte[] messageBytes, InetAddress receiverAddress, int receiverPort, boolean retry)756     protected void sendMessage(byte[] messageBytes,
757             InetAddress receiverAddress, int receiverPort, boolean retry)
758             throws IOException {
759         throw new IOException(
760                 "Cannot send unparsed message through Transaction Channel!");
761     }
762 
763     /**
764      * Adds a new event listener to this transaction.
765      *
766      * @param newListener
767      *            Listener to add.
768      */
addEventListener(SIPTransactionEventListener newListener)769     public void addEventListener(SIPTransactionEventListener newListener) {
770         eventListeners.add(newListener);
771     }
772 
773     /**
774      * Removed an event listener from this transaction.
775      *
776      * @param oldListener
777      *            Listener to remove.
778      */
removeEventListener(SIPTransactionEventListener oldListener)779     public void removeEventListener(SIPTransactionEventListener oldListener) {
780         eventListeners.remove(oldListener);
781     }
782 
783     /**
784      * Creates a SIPTransactionErrorEvent and sends it to all of the listeners
785      * of this transaction. This method also flags the transaction as
786      * terminated.
787      *
788      * @param errorEventID
789      *            ID of the error to raise.
790      */
raiseErrorEvent(int errorEventID)791     protected void raiseErrorEvent(int errorEventID) {
792 
793         // Error event to send to all listeners
794         SIPTransactionErrorEvent newErrorEvent;
795         // Iterator through the list of listeners
796         Iterator<SIPTransactionEventListener> listenerIterator;
797         // Next listener in the list
798         SIPTransactionEventListener nextListener;
799 
800         // Create the error event
801         newErrorEvent = new SIPTransactionErrorEvent(this, errorEventID);
802 
803         // Loop through all listeners of this transaction
804         synchronized (eventListeners) {
805             listenerIterator = eventListeners.iterator();
806             while (listenerIterator.hasNext()) {
807                 // Send the event to the next listener
808                 nextListener = (SIPTransactionEventListener) listenerIterator
809                         .next();
810                 nextListener.transactionErrorEvent(newErrorEvent);
811             }
812         }
813         // Clear the event listeners after propagating the error.
814         // Retransmit notifications are just an alert to the
815         // application (they are not an error).
816         if (errorEventID != SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) {
817             eventListeners.clear();
818 
819             // Errors always terminate a transaction
820             this.setState(TransactionState.TERMINATED);
821 
822             if (this instanceof SIPServerTransaction && this.isByeTransaction()
823                     && this.getDialog() != null)
824                 ((SIPDialog) this.getDialog())
825                         .setState(SIPDialog.TERMINATED_STATE);
826         }
827     }
828 
829     /**
830      * A shortcut way of telling if we are a server transaction.
831      */
isServerTransaction()832     protected boolean isServerTransaction() {
833         return this instanceof SIPServerTransaction;
834     }
835 
836     /**
837      * Gets the dialog object of this Transaction object. This object returns
838      * null if no dialog exists. A dialog only exists for a transaction when a
839      * session is setup between a User Agent Client and a User Agent Server,
840      * either by a 1xx Provisional Response for an early dialog or a 200OK
841      * Response for a committed dialog.
842      *
843      * @return the Dialog Object of this Transaction object.
844      * @see Dialog
845      */
getDialog()846     public abstract Dialog getDialog();
847 
848     /**
849      * set the dialog object.
850      *
851      * @param sipDialog --
852      *            the dialog to set.
853      * @param dialogId --
854      *            the dialog id ot associate with the dialog.s
855      */
setDialog(SIPDialog sipDialog, String dialogId)856     public abstract void setDialog(SIPDialog sipDialog, String dialogId);
857 
858     /**
859      * Returns the current value of the retransmit timer in milliseconds used to
860      * retransmit messages over unreliable transports.
861      *
862      * @return the integer value of the retransmit timer in milliseconds.
863      */
getRetransmitTimer()864     public int getRetransmitTimer() {
865         return SIPTransactionStack.BASE_TIMER_INTERVAL;
866     }
867 
868     /**
869      * Get the host to assign for an outgoing Request via header.
870      */
getViaHost()871     public String getViaHost() {
872         return this.getViaHeader().getHost();
873 
874     }
875 
876     /**
877      * Get the last response. This is used internally by the implementation.
878      * Dont rely on it.
879      *
880      * @return the last response received (for client transactions) or sent (for
881      *         server transactions).
882      */
getLastResponse()883     public SIPResponse getLastResponse() {
884         return this.lastResponse;
885     }
886 
887     /**
888      * Get the JAIN interface response
889      */
getResponse()890     public Response getResponse() {
891         return (Response) this.lastResponse;
892     }
893 
894     /**
895      * Get the transaction Id.
896      */
getTransactionId()897     public String getTransactionId() {
898         return this.transactionId;
899     }
900 
901     /**
902      * Hashcode method for fast hashtable lookup.
903      */
hashCode()904     public int hashCode() {
905         if (this.transactionId == null)
906             return -1;
907         else
908             return this.transactionId.hashCode();
909     }
910 
911     /**
912      * Get the port to assign for the via header of an outgoing message.
913      */
getViaPort()914     public int getViaPort() {
915         return this.getViaHeader().getPort();
916     }
917 
918     /**
919      * A method that can be used to test if an incoming request belongs to this
920      * transction. This does not take the transaction state into account when
921      * doing the check otherwise it is identical to isMessagePartOfTransaction.
922      * This is useful for checking if a CANCEL belongs to this transaction.
923      *
924      * @param requestToTest
925      *            is the request to test.
926      * @return true if the the request belongs to the transaction.
927      *
928      */
doesCancelMatchTransaction(SIPRequest requestToTest)929     public boolean doesCancelMatchTransaction(SIPRequest requestToTest) {
930 
931         // List of Via headers in the message to test
932         ViaList viaHeaders;
933         // Topmost Via header in the list
934         Via topViaHeader;
935         // Branch code in the topmost Via header
936         String messageBranch;
937         // Flags whether the select message is part of this transaction
938         boolean transactionMatches;
939 
940         transactionMatches = false;
941 
942         if (this.getOriginalRequest() == null
943                 || this.getOriginalRequest().getMethod().equals(Request.CANCEL))
944             return false;
945         // Get the topmost Via header and its branch parameter
946         viaHeaders = requestToTest.getViaHeaders();
947         if (viaHeaders != null) {
948 
949             topViaHeader = (Via) viaHeaders.getFirst();
950             messageBranch = topViaHeader.getBranch();
951             if (messageBranch != null) {
952 
953                 // If the branch parameter exists but
954                 // does not start with the magic cookie,
955                 if (!messageBranch.toLowerCase().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) {
956 
957                     // Flags this as old
958                     // (RFC2543-compatible) client
959                     // version
960                     messageBranch = null;
961 
962                 }
963 
964             }
965 
966             // If a new branch parameter exists,
967             if (messageBranch != null && this.getBranch() != null) {
968 
969                 // If the branch equals the branch in
970                 // this message,
971                 if (getBranch().equalsIgnoreCase(messageBranch)
972                         && topViaHeader.getSentBy().equals(
973                                 ((Via) getOriginalRequest().getViaHeaders()
974                                         .getFirst()).getSentBy())) {
975                     transactionMatches = true;
976                     if (sipStack.isLoggingEnabled())
977                         sipStack.getStackLogger().logDebug("returning  true");
978                 }
979 
980             } else {
981                 // If this is an RFC2543-compliant message,
982                 // If RequestURI, To tag, From tag,
983                 // CallID, CSeq number, and top Via
984                 // headers are the same,
985                 if (sipStack.isLoggingEnabled())
986                     sipStack.getStackLogger().logDebug("testing against "
987                             + getOriginalRequest());
988 
989                 if (getOriginalRequest().getRequestURI().equals(
990                         requestToTest.getRequestURI())
991                         && getOriginalRequest().getTo().equals(
992                                 requestToTest.getTo())
993                         && getOriginalRequest().getFrom().equals(
994                                 requestToTest.getFrom())
995                         && getOriginalRequest().getCallId().getCallId().equals(
996                                 requestToTest.getCallId().getCallId())
997                         && getOriginalRequest().getCSeq().getSeqNumber() == requestToTest
998                                 .getCSeq().getSeqNumber()
999                         && topViaHeader.equals(getOriginalRequest()
1000                                 .getViaHeaders().getFirst())) {
1001 
1002                     transactionMatches = true;
1003                 }
1004 
1005             }
1006 
1007         }
1008 
1009         // JvB: Need to pass the CANCEL to the listener! Retransmitted INVITEs
1010         // set it to false
1011         if (transactionMatches) {
1012             this.setPassToListener();
1013         }
1014         return transactionMatches;
1015     }
1016 
1017     /**
1018      * Sets the value of the retransmit timer to the newly supplied timer value.
1019      * The retransmit timer is expressed in milliseconds and its default value
1020      * is 500ms. This method allows the application to change the transaction
1021      * retransmit behavior for different networks. Take the gateway proxy as an
1022      * example. The internal intranet is likely to be reatively uncongested and
1023      * the endpoints will be relatively close. The external network is the
1024      * general Internet. This functionality allows different retransmit times
1025      * for either side.
1026      *
1027      * @param retransmitTimer -
1028      *            the new integer value of the retransmit timer in milliseconds.
1029      */
setRetransmitTimer(int retransmitTimer)1030     public void setRetransmitTimer(int retransmitTimer) {
1031 
1032         if (retransmitTimer <= 0)
1033             throw new IllegalArgumentException(
1034                     "Retransmit timer must be positive!");
1035         if (this.transactionTimerStarted.get())
1036             throw new IllegalStateException(
1037                     "Transaction timer is already started");
1038         BASE_TIMER_INTERVAL = retransmitTimer;
1039         T4 = 5000 / BASE_TIMER_INTERVAL;
1040 
1041         T2 = 4000 / BASE_TIMER_INTERVAL;
1042         TIMER_I = T4;
1043 
1044         TIMER_K = T4;
1045 
1046         TIMER_D = 32000 / BASE_TIMER_INTERVAL;
1047 
1048     }
1049 
1050     /**
1051      * Close the encapsulated channel.
1052      */
close()1053     public void close() {
1054         this.encapsulatedChannel.close();
1055         if (sipStack.isLoggingEnabled())
1056             sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel);
1057 
1058     }
1059 
isSecure()1060     public boolean isSecure() {
1061         return encapsulatedChannel.isSecure();
1062     }
1063 
getMessageProcessor()1064     public MessageProcessor getMessageProcessor() {
1065         return this.encapsulatedChannel.getMessageProcessor();
1066     }
1067 
1068     /**
1069      * Set the application data pointer. This is un-interpreted by the stack.
1070      * This is provided as a conveniant way of keeping book-keeping data for
1071      * applications. Note that null clears the application data pointer
1072      * (releases it).
1073      *
1074      * @param applicationData --
1075      *            application data pointer to set. null clears the applicationd
1076      *            data pointer.
1077      *
1078      */
1079 
setApplicationData(Object applicationData)1080     public void setApplicationData(Object applicationData) {
1081         this.applicationData = applicationData;
1082     }
1083 
1084     /**
1085      * Get the application data associated with this transaction.
1086      *
1087      * @return stored application data.
1088      */
getApplicationData()1089     public Object getApplicationData() {
1090         return this.applicationData;
1091     }
1092 
1093     /**
1094      * Set the encapsuated channel. The peer inet address and port are set equal
1095      * to the message channel.
1096      */
setEncapsulatedChannel(MessageChannel messageChannel)1097     public void setEncapsulatedChannel(MessageChannel messageChannel) {
1098         this.encapsulatedChannel = messageChannel;
1099         this.peerInetAddress = messageChannel.getPeerInetAddress();
1100         this.peerPort = messageChannel.getPeerPort();
1101     }
1102 
1103     /**
1104      * Return the SipProvider for which the transaction is assigned.
1105      *
1106      * @return the SipProvider for the transaction.
1107      */
getSipProvider()1108     public SipProviderImpl getSipProvider() {
1109 
1110         return this.getMessageProcessor().getListeningPoint().getProvider();
1111     }
1112 
1113     /**
1114      * Raise an IO Exception event - this is used for reporting asynchronous IO
1115      * Exceptions that are attributable to this transaction.
1116      *
1117      */
raiseIOExceptionEvent()1118     public void raiseIOExceptionEvent() {
1119         setState(TransactionState.TERMINATED);
1120         String host = getPeerAddress();
1121         int port = getPeerPort();
1122         String transport = getTransport();
1123         IOExceptionEvent exceptionEvent = new IOExceptionEvent(this, host,
1124                 port, transport);
1125         getSipProvider().handleEvent(exceptionEvent, this);
1126     }
1127 
1128     /**
1129      * A given tx can process only a single outstanding event at a time. This
1130      * semaphore gaurds re-entrancy to the transaction.
1131      *
1132      */
acquireSem()1133     public boolean acquireSem() {
1134         boolean retval = false;
1135         try {
1136             if (sipStack.getStackLogger().isLoggingEnabled()) {
1137                 sipStack.getStackLogger().logDebug("acquireSem [[[[" + this);
1138                 sipStack.getStackLogger().logStackTrace();
1139             }
1140             retval = this.semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS);
1141             if ( sipStack.isLoggingEnabled())
1142                 sipStack.getStackLogger().logDebug(
1143                     "acquireSem() returning : " + retval);
1144             return retval;
1145         } catch (Exception ex) {
1146             sipStack.getStackLogger().logError("Unexpected exception acquiring sem",
1147                     ex);
1148             InternalErrorHandler.handleException(ex);
1149             return false;
1150         } finally {
1151             this.isSemaphoreAquired = retval;
1152         }
1153 
1154     }
1155 
1156     /**
1157      * Release the transaction semaphore.
1158      *
1159      */
releaseSem()1160     public void releaseSem() {
1161         try {
1162 
1163             this.toListener = false;
1164             this.semRelease();
1165 
1166         } catch (Exception ex) {
1167             sipStack.getStackLogger().logError("Unexpected exception releasing sem",
1168                     ex);
1169 
1170         }
1171 
1172     }
1173 
semRelease()1174     protected void semRelease() {
1175         try {
1176             if (sipStack.isLoggingEnabled()) {
1177                 sipStack.getStackLogger().logDebug("semRelease ]]]]" + this);
1178                 sipStack.getStackLogger().logStackTrace();
1179             }
1180             this.isSemaphoreAquired = false;
1181             this.semaphore.release();
1182 
1183         } catch (Exception ex) {
1184             sipStack.getStackLogger().logError("Unexpected exception releasing sem",
1185                     ex);
1186 
1187         }
1188     }
1189 
1190     /**
1191      * Set true to pass the request up to the listener. False otherwise.
1192      *
1193      */
1194 
passToListener()1195     public boolean passToListener() {
1196         return toListener;
1197     }
1198 
1199     /**
1200      * Set the passToListener flag to true.
1201      */
setPassToListener()1202     public void setPassToListener() {
1203         if (sipStack.isLoggingEnabled()) {
1204             sipStack.getStackLogger().logDebug("setPassToListener()");
1205         }
1206         this.toListener = true;
1207 
1208     }
1209 
1210     /**
1211      * Flag to test if the terminated event is delivered.
1212      *
1213      * @return
1214      */
testAndSetTransactionTerminatedEvent()1215     protected synchronized boolean testAndSetTransactionTerminatedEvent() {
1216         boolean retval = !this.terminatedEventDelivered;
1217         this.terminatedEventDelivered = true;
1218         return retval;
1219     }
1220 
getCipherSuite()1221     public String getCipherSuite() throws UnsupportedOperationException {
1222         if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1223             if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1224                 return null;
1225             else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1226                 return null;
1227             else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getCipherSuite();
1228         } else throw new UnsupportedOperationException("Not a TLS channel");
1229 
1230     }
1231 
1232 
getLocalCertificates()1233     public java.security.cert.Certificate[] getLocalCertificates() throws UnsupportedOperationException {
1234          if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1235             if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1236                 return null;
1237             else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1238                 return null;
1239             else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getLocalCertificates();
1240         } else throw new UnsupportedOperationException("Not a TLS channel");
1241     }
1242 
1243 
getPeerCertificates()1244     public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
1245         if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1246             if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1247                 return null;
1248             else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1249                 return null;
1250             else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getPeerCertificates();
1251         } else throw new UnsupportedOperationException("Not a TLS channel");
1252 
1253     }
1254 
1255 
1256     /**
1257      * Start the timer that runs the transaction state machine.
1258      *
1259      */
1260 
startTransactionTimer()1261     protected abstract void startTransactionTimer();
1262 
1263     /**
1264      * Tests a message to see if it is part of this transaction.
1265      *
1266      * @return True if the message is part of this transaction, false if not.
1267      */
isMessagePartOfTransaction(SIPMessage messageToTest)1268     public abstract boolean isMessagePartOfTransaction(SIPMessage messageToTest);
1269 
1270     /**
1271      * This method is called when this transaction's retransmission timer has
1272      * fired.
1273      */
fireRetransmissionTimer()1274     protected abstract void fireRetransmissionTimer();
1275 
1276     /**
1277      * This method is called when this transaction's timeout timer has fired.
1278      */
fireTimeoutTimer()1279     protected abstract void fireTimeoutTimer();
1280 
1281 }
1282