From 6e666b7491636de4ca5c6af9f80a0f337d6d8f94 Mon Sep 17 00:00:00 2001 From: Yana Stamcheva Date: Tue, 19 Mar 2013 13:51:57 +0000 Subject: [PATCH] Adds implementation for sip response 180 to be retransmitted 3 times. Patch provided by Hristo Terezov on dev (subject: "[jitsi-dev] [PATCH] Added implementation for sip response 180 to be retransmitted 3 times"). --- .../impl/protocol/sip/CallSipImpl.java | 127 +++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java index 507cba688..dd5adf271 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java @@ -19,6 +19,7 @@ import net.java.sip.communicator.service.protocol.media.*; import net.java.sip.communicator.util.*; +import org.jitsi.service.configuration.*; import org.jitsi.service.neomedia.*; /** @@ -49,6 +50,33 @@ public class CallSipImpl * use when creating requests. */ private final SipMessageFactory messageFactory; + + /** + * The name of the property under which the user may specify the number of + * milliseconds for the initial interval for retransmissions of response + * 180. + */ + private static final String RETRANSMITS_RINGING_INTERVAL + = "net.java.sip.communicator.impl.protocol.sip" + + ".RETRANSMITS_RINGING_INTERVAL"; + + /** + * The default amount of time (in milliseconds) for the initial interval for + * retransmissions of response 180. + */ + private static final int DEFAULT_RETRANSMITS_RINGING_INTERVAL = 500; + + /** + * Maximum number of retransmissions that will be sent. + */ + private static final int MAX_RETRANSMISSIONS = 3; + + /** + * The amount of time (in milliseconds) for the initial interval for + * retransmissions of response 180. + */ + private int retransmitsRingingInterval + = DEFAULT_RETRANSMITS_RINGING_INTERVAL; /** * Crates a CallSipImpl instance belonging to sourceProvider and @@ -66,6 +94,10 @@ protected CallSipImpl(OperationSetBasicTelephonySipImpl parentOpSet) //let's add ourselves to the calls repo. we are doing it ourselves just //to make sure that no one ever forgets. parentOpSet.getActiveCallsRepository().addCall(this); + + ConfigurationService cfg = SipActivator.getConfigurationService(); + retransmitsRingingInterval = cfg.getInt(RETRANSMITS_RINGING_INTERVAL, + DEFAULT_RETRANSMITS_RINGING_INTERVAL); } /** @@ -376,7 +408,7 @@ public CallPeerSipImpl processInvite(SipProvider jainSipProvider, { Request invite = serverTran.getRequest(); - CallPeerSipImpl peer = createCallPeerFor(serverTran, jainSipProvider); + final CallPeerSipImpl peer = createCallPeerFor(serverTran, jainSipProvider); //send a ringing response Response response = null; @@ -386,6 +418,32 @@ public CallPeerSipImpl processInvite(SipProvider jainSipProvider, logger.trace("will send ringing response: "); response = messageFactory.createResponse(Response.RINGING, invite); serverTran.sendResponse(response); + + final Timer timer = new Timer(); + CallPeerAdapter stateListener = new CallPeerAdapter() + { + public void peerStateChanged(CallPeerChangeEvent evt) + { + if(!evt.getNewValue().equals(CallPeerState.INCOMING_CALL)) + { + timer.cancel(); + peer.removeCallPeerListener(this); + } + + } + }; + int interval = retransmitsRingingInterval; + int delay = 0; + + for(int i = 0; i < MAX_RETRANSMISSIONS; i++) + { + delay += interval; + timer.schedule(new RingingResponseTask(response, serverTran, + peer, timer, stateListener), delay); + interval *= 2; + } + + peer.addCallPeerListener(stateListener); if (logger.isDebugEnabled()) logger.debug("sent a ringing response: " + response); } @@ -399,6 +457,7 @@ public CallPeerSipImpl processInvite(SipProvider jainSipProvider, return peer; } + /** * Processes an incoming INVITE that is meant to replace an existing @@ -473,4 +532,70 @@ public void setInitialQualityPreferences(QualityPreset qualityPreferences) { this.initialQualityPreferences = qualityPreferences; } + + /** + * Task that will retransmit ringing response + */ + private class RingingResponseTask + extends TimerTask + { + /** + * The response that will be sent + */ + private final Response response; + + /** + * The transaction containing the received request. + */ + private final ServerTransaction serverTran; + + /** + * The peer corresponding to the transaction. + */ + private final CallPeerSipImpl peer; + + /** + * The timer that starts the task. + */ + private final Timer timer; + + /** + * Listener for the state of the peer. + */ + private CallPeerAdapter stateListener; + + /** + * Create ringing response task. + * @param response the response. + * @param serverTran the transaction. + * @param peer the peer. + * @param timer the timer. + * @param stateListener the state listener. + */ + RingingResponseTask(Response response, ServerTransaction serverTran, + CallPeerSipImpl peer, Timer timer, CallPeerAdapter stateListener) + { + this.response = response; + this.serverTran = serverTran; + this.peer = peer; + this.timer = timer; + this.stateListener = stateListener; + } + + /** + * Sends the ringing response. + */ + public void run() + { + try + { + serverTran.sendResponse(response); + } + catch (Exception ex) + { + timer.cancel(); + peer.removeCallPeerListener(stateListener); + } + } + } }