Revision: 8642
Author: vladimir.ralev
Date: Tue Nov 24 07:06:32 2009
Log: Recover some lost calls in proxy scenarios
http://code.google.com/p/mobicents/source/detail?r=8642
Modified:
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/core/dispatchers/ResponseDispatcher.java
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/message/SipServletResponseImpl.java
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyBranchImpl.java
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyImpl.java
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyUtils.java
=======================================
---
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/core/dispatchers/ResponseDispatcher.java
Mon Nov 23 23:43:10 2009
+++
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/core/dispatchers/ResponseDispatcher.java
Tue Nov 24 07:06:32 2009
@@ -221,8 +221,6 @@
}
if(session.getProxy()
!= null) {
- // TODO: FIXME: On retrans - we get null transaction from JSIP
thus we lose the info about the
- // proxy
branch. Figure out a way to do the mapping.
// the final Application data is null meaning that the CTX was
null, so it's a retransmission
if(proxyBranch
== null) {
@@ -233,6 +231,15 @@
SIPTransaction tx =
((SipStackImpl)sipProvider.getSipStack()).findTransaction((SIPMessage)
response, false);
if(tx
!= null) {
TransactionApplicationData tad = (TransactionApplicationData)
tx.getApplicationData();
+
if(tad == null) {
+
if(logger.isDebugEnabled()) {
+ logger.debug("Attempting to recover lost transaction app data
for " + branch);
+
}
+ tad = (TransactionApplicationData)
session.getProxy().getTransactionMap().get(branch);
+
if(logger.isDebugEnabled()) {
+ if(tad != null) logger.debug("Sucessfully recovered app data
for " + branch + " " + tad);
+
}
+
}
if(tad != null) {
proxyBranch = tad.getProxyBranch();
logger.debug("A proxy response retransmission was able to
recover the transaction application data");
=======================================
---
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/message/SipServletResponseImpl.java
Fri Nov 20 04:24:28 2009
+++
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/message/SipServletResponseImpl.java
Tue Nov 24 07:06:32 2009
@@ -50,6 +50,7 @@
import javax.sip.header.RequireHeader;
import javax.sip.header.RouteHeader;
import javax.sip.header.SupportedHeader;
+import javax.sip.header.ViaHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
@@ -468,6 +469,19 @@
if(logger.isDebugEnabled()) {
logger.debug("sending response "+ this.message);
}
+ if(originalRequest == null && session.getProxy() !=
null) {
+ String txid = ((ViaHeader)
message.getHeader(ViaHeader.NAME)).getBranch();
+ TransactionApplicationData tad = (TransactionApplicationData)
session.getProxy().getTransactionMap().get(txid);
+ if(logger.isDebugEnabled()) {
+ logger.debug("OTrying to recover lost transaction for proxy: " +
txid);
+ }
+ if(tad != null) {
+ if(logger.isDebugEnabled()) {
+ logger.debug("Recovering lost transaction from the proxy transaction
map is succesful: " + txid);
+ }
+ originalRequest =
(SipServletRequestImpl) tad.getSipServletMessage();
+ }
+ }
//if a response is sent for an initial request, it means that the
application
//acted as an endpoint so a dialog must be created but only for dialog
creating method
if(!Request.CANCEL.equals(originalRequest.getMethod())
=======================================
---
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyBranchImpl.java
Fri Nov 20 04:24:28 2009
+++
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyBranchImpl.java
Tue Nov 24 07:06:32 2009
@@ -142,6 +142,7 @@
*/
public void cancel(String[] protocol, int[] reasonCode, String[]
reasonText) {
if(proxy.getAckReceived()) throw new IllegalStateException("There has
been an ACK received on this branch. Can not cancel.");
+
try {
cancelTimer();
if(this.isStarted() && !canceled && !timedOut &&
@@ -186,6 +187,17 @@
}
catch(Exception e) {
throw new IllegalStateException("Failed canceling proxy
branch", e);
+ } finally {
+ onBranchTerminated();
+ }
+
+ }
+
+ // This will be called when we are sure this branch will not succeed and
we moved on to other branches.
+ public void onBranchTerminated() {
+ if(outgoingRequest != null) {
+ String txid = ((ViaHeader)
outgoingRequest.getMessage().getHeader(ViaHeader.NAME)).getBranch();
+ proxy.getTransactionMap().remove(txid);
}
}
@@ -364,6 +376,10 @@
}
clonedRequest.getTransactionApplicationData().setProxyBranch(this);
clonedRequest.send();
+ String txid = ((ViaHeader)
clonedRequest.getMessage().getHeader(ViaHeader.NAME)).getBranch();
+ if(clonedRequest.getTransactionApplicationData() != null) {
+ proxy.transactionMap.put(txid,
clonedRequest.getTransactionApplicationData());
+ }
}
/**
=======================================
---
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyImpl.java
Tue Nov 24 01:44:57 2009
+++
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyImpl.java
Tue Nov 24 07:06:32 2009
@@ -25,6 +25,7 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
@@ -82,6 +83,8 @@
// clustering : will be recreated when loaded from the cache
private transient ProxyUtils proxyUtils;
+ transient HashMap<String, Object> transactionMap = new HashMap<String,
Object>();
+
private transient Map<URI, ProxyBranch> proxyBranches;
private boolean started;
private boolean ackReceived = false;
@@ -110,6 +113,10 @@
this.outboundInterface =
((MobicentsSipSession)request.getSession()).getOutboundInterface();
this.callerFromHeader = request.getFrom().toString();
this.previousNode = extractPreviousNodeFromRequest(request);
+ String txid = ((ViaHeader)
request.getMessage().getHeader(ViaHeader.NAME)).getBranch();
+ if(originalRequest.getTransactionApplicationData() != null) {
+ this.transactionMap.put(txid,
originalRequest.getTransactionApplicationData());
+ }
}
/*
@@ -553,6 +560,7 @@
if(logger.isDebugEnabled())
logger.debug("Trying new branch in
proxy" );
startNextUntriedBranch();
+ branch.onBranchTerminated();
}
}
}
@@ -572,6 +580,7 @@
{
branch.cancel();
startNextUntriedBranch();
+ branch.onBranchTerminated();
}
}
}
@@ -633,13 +642,18 @@
if(logger.isDebugEnabled())
logger.debug("Proxy branch has NOT timed
out");
-
-
+
//Otherwise proceed with proxying the response
SipServletResponseImpl proxiedResponse =
getProxyUtils().createProxiedResponse(response,
proxyBranch);
- if(proxiedResponse.getRequest() != null) {
+
+ if(proxiedResponse.getMessage() == null) {
+ return;// drop out of order message
+ }
+
+
+ if(originalRequest != null && proxiedResponse.getRequest() !=
null) {
if(logger.isDebugEnabled())
logger.debug("Response was dropped because
getProxyUtils().createProxiedResponse(response, proxyBranch) returned
null");
// non retransmission case
@@ -773,6 +787,10 @@
public void setCallerFromHeader(String initiatorFromHeader) {
this.callerFromHeader = initiatorFromHeader;
}
+
+ public HashMap<String, Object> getTransactionMap() {
+ return transactionMap;
+ }
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
=======================================
---
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyUtils.java
Fri Nov 20 04:24:28 2009
+++
/trunk/servers/sip-servlets/sip-servlets-impl/src/main/java/org/mobicents/servlet/sip/proxy/ProxyUtils.java
Tue Nov 24 07:06:32 2009
@@ -253,7 +253,8 @@
}
SipServletResponseImpl newServletResponseImpl = null;
- if(sipServetResponse.getTransaction() != null) {
+
+ if(sipServetResponse.getTransaction() != null && originalRequest !=
null) {
// non retransmission case
newServletResponseImpl = new
SipServletResponseImpl(clonedResponse,
sipFactoryImpl,