Revision: 15870
Author: vladimir.ralev
Date: Sun Dec 19 18:42:21 2010
Log: Update Issue 2282
More testcases and support for early dialog failover testing
http://code.google.com/p/mobicents/source/detail?r=15870
Added:
/trunk/tools/sip-balancer/jar/src/test/java/org/mobicents/tools/sip/balancer/algorithms/EarlyDialogWorstCaseAffinityTest.java
Modified:
/trunk/tools/sip-balancer/jar/src/main/java/org/mobicents/tools/sip/balancer/WorstCaseUdpTestAffinityAlgorithm.java
/trunk/tools/sip-balancer/jar/src/test/java/org/mobicents/tools/sip/balancer/algorithms/WorstCaseAffinityTest.java
=======================================
--- /dev/null
+++
/trunk/tools/sip-balancer/jar/src/test/java/org/mobicents/tools/sip/balancer/algorithms/EarlyDialogWorstCaseAffinityTest.java
Sun Dec 19 18:42:21 2010
@@ -0,0 +1,182 @@
+package org.mobicents.tools.sip.balancer.algorithms;
+
+import java.util.Properties;
+
+import javax.sip.address.SipURI;
+import javax.sip.header.RecordRouteHeader;
+
+import junit.framework.TestCase;
+
+import org.mobicents.tools.sip.balancer.AppServer;
+import org.mobicents.tools.sip.balancer.BalancerRunner;
+import org.mobicents.tools.sip.balancer.EventListener;
+import org.mobicents.tools.sip.balancer.WorstCaseUdpTestAffinityAlgorithm;
+import org.mobicents.tools.sip.balancer.operation.Shootist;
+
+public class EarlyDialogWorstCaseAffinityTest extends TestCase {
+ BalancerRunner balancer;
+ int numNodes = 2;
+ AppServer[] servers = new AppServer[numNodes];
+ Shootist shootist;
+
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ shootist = new Shootist();
+ balancer = new BalancerRunner();
+ Properties properties = new Properties();
+ properties.setProperty("javax.sip.STACK_NAME",
"SipBalancerForwarder");
+ properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT",
"off");
+ // You need 16 for logging traces. 32 for debug + traces.
+ // Your code will limp at 32 but it is best for debugging.
+ properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
+ properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",
+ "logs/sipbalancerforwarderdebug.txt");
+ properties.setProperty("gov.nist.javax.sip.SERVER_LOG",
+ "logs/sipbalancerforwarder.xml");
+ properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE",
"2");
+ properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER",
"true");
+
properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false");
+ properties.setProperty("algorithmClass",
WorstCaseUdpTestAffinityAlgorithm.class.getName());
+ properties.setProperty("host", "127.0.0.1");
+ properties.setProperty("internalPort", "5065");
+ properties.setProperty("externalPort", "5060");
+ properties.setProperty("earlyDialogWorstCase", "true");
+ balancer.start(properties);
+
+
+ for(int q=0;q<servers.length;q++) {
+ servers[q] = new AppServer("node" + q,4060+q);
+ servers[q].start();
+ }
+ Thread.sleep(5000);
+ }
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ shootist.stop();
+ for(int q=0;q<servers.length;q++) {
+ servers[q].stop();
+ }
+ balancer.stop();
+ }
+ static AppServer invite;
+ static AppServer ack;
+ static AppServer bye;
+ public void testInviteAckLandOnDifferentNodes() throws Exception {
+ EventListener failureEventListener = new EventListener() {
+
+ @Override
+ public void uasAfterResponse(int statusCode, AppServer
source) {
+
+ }
+
+ @Override
+ public void uasAfterRequestReceived(String method,
AppServer source) {
+ if(method.equals("INVITE")) invite = source;
+ if(method.equals("ACK")) {
+ ack = source;
+
+ if(ack == invite) TestCase.fail("INVITE and ACK should have landed on
different nodes");
+ }
+ if(method.equals("BYE")) {
+ bye = source;
+
+ if(ack == bye) TestCase.fail("ACK and BYE should have landed on
different nodes");
+ }
+
+
+ }
+
+ @Override
+ public void uacAfterRequestSent(String method,
AppServer source) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void uacAfterResponse(int statusCode, AppServer
source) {
+ // TODO Auto-generated method stub
+
+ }
+ };
+ for(AppServer as:servers)
as.setEventListener(failureEventListener);
+
+ shootist.callerSendsBye = true;
+ shootist.sendInitialInvite();
+ Thread.sleep(11000);
+ if(invite == null) TestCase.fail("INVITE not seen");
+ if(ack == null) TestCase.fail("BYE not seen");
+ }
+
+ AppServer ringingAppServer;
+ AppServer okAppServer;
+ public void testOKRingingLandOnDifferentNodes() throws Exception {
+
+ EventListener failureEventListener = new EventListener() {
+
+ @Override
+ public void uasAfterResponse(int statusCode, AppServer
source) {
+
+
+ }
+
+ @Override
+ public void uasAfterRequestReceived(String method,
AppServer source) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void uacAfterRequestSent(String method,
AppServer source) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void uacAfterResponse(int statusCode, AppServer
source) {
+ if(statusCode == 180) {
+ ringingAppServer = source;
+ } else {
+ okAppServer = source;
+
+ }
+ }
+ };
+ for(AppServer as:servers)
as.setEventListener(failureEventListener);
+ shootist.callerSendsBye = true;
+
+ String fromName = "sender";
+ String fromHost = "sip-servlets.com";
+ SipURI fromAddress =
servers[0].protocolObjects.addressFactory.createSipURI(
+ fromName, fromHost);
+
+ String toUser = "replaces";
+ String toHost = "sip-servlets.com";
+ SipURI toAddress =
servers[0].protocolObjects.addressFactory.createSipURI(
+ toUser, toHost);
+
+ SipURI ruri =
servers[0].protocolObjects.addressFactory.createSipURI(
+ "usera", "127.0.0.1:5033");
+ ruri.setLrParam();
+ SipURI route =
servers[0].protocolObjects.addressFactory.createSipURI(
+ "lbint", "127.0.0.1:5065");
+ route.setParameter("node_host", "127.0.0.1");
+ route.setParameter("node_port", "4060");
+ route.setLrParam();
+ shootist.start();
+ //servers[0].sipListener.sendSipRequest("INVITE", fromAddress,
toAddress, null, null, false);
+ servers[0].sipListener.sendSipRequest("INVITE", fromAddress, toAddress,
null, route, false, null, null, ruri);
+ Thread.sleep(16000);
+
assertTrue(shootist.inviteRequest.getHeader(RecordRouteHeader.NAME).toString().contains("node_host"));
+ assertNotSame(ringingAppServer, okAppServer);
+ assertNotNull(ringingAppServer);
+ assertNotNull(okAppServer);
+ }
+}
=======================================
---
/trunk/tools/sip-balancer/jar/src/main/java/org/mobicents/tools/sip/balancer/WorstCaseUdpTestAffinityAlgorithm.java
Tue Dec 7 17:43:36 2010
+++
/trunk/tools/sip-balancer/jar/src/main/java/org/mobicents/tools/sip/balancer/WorstCaseUdpTestAffinityAlgorithm.java
Sun Dec 19 18:42:21 2010
@@ -14,6 +14,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.sip.ListeningPoint;
import javax.sip.address.SipURI;
import javax.sip.header.RouteHeader;
import javax.sip.header.ViaHeader;
@@ -29,6 +30,7 @@
public class WorstCaseUdpTestAffinityAlgorithm extends
DefaultBalancerAlgorithm {
protected ConcurrentHashMap<String, SIPNode> txToNode = new
ConcurrentHashMap<String, SIPNode>();
protected ConcurrentHashMap<String, Long> txTimestamps = new
ConcurrentHashMap<String, Long>();
+ protected boolean earlyDialogWorstCase = false;
public synchronized SIPNode getNode(String tx) {
return txToNode.get(tx);
}
@@ -38,10 +40,14 @@
}
public SIPNode processAssignedExternalRequest(Request request,
SIPNode assignedNode) {
- String tx =
((ViaHeader)request.getHeader(Via.NAME)).getBranch();
+ ViaHeader via = (ViaHeader) request.getHeader(Via.NAME);
+ String transport = via.getTransport().toLowerCase();
+ String tx = via.getBranch();
SIPNode seenNode = getNode(tx);
if(seenNode != null) return seenNode;
- if(request.getMethod().contains("ACK")) return assignedNode;
+ if(!earlyDialogWorstCase) {
+ if(request.getMethod().contains("ACK")) return
assignedNode;
+ }
RouteHeader route = (RouteHeader)
request.getHeader(RouteHeader.NAME);
SipURI uri = null;
if(route != null) {
@@ -53,7 +59,7 @@
for(SIPNode node:getBalancerContext().nodes) {
if(!node.equals(assignedNode)) {
uri.setHost(node.getIp());
- Integer port = (Integer)
node.getProperties().get("udpPort");
+ Integer port = (Integer)
node.getProperties().get(transport + "Port");
uri.setPort(port);
String callId = ((SIPHeader)
request.getHeader(headerName))
.getValue();
@@ -65,7 +71,7 @@
if(request.getRequestURI().isSipURI()) {
SipURI ruri = (SipURI)
request.getRequestURI();
String rurihostid =
ruri.getHost() + ruri.getPort();
- String originalhostid = assignedNode.getIp() +
assignedNode.getProperties().get("udpPort");
+ String originalhostid = assignedNode.getIp() +
assignedNode.getProperties().get(transport + "Port");
if(rurihostid.equals(originalhostid)) {
ruri.setPort(port);
ruri.setHost(node.getIp());
@@ -103,6 +109,7 @@
public void processExternalResponse(Response response) {
BalancerContext balancerContext = getBalancerContext();
Via via = (Via) response.getHeader(Via.NAME);
+ String transport = via.getTransport().toLowerCase();
String host = via.getHost();
boolean found = false;
for(SIPNode node : BalancerContext.balancerContext.nodes) {
@@ -116,13 +123,40 @@
node = selectNewNode(node, callId);
try {
via.setHost(node.getIp());
- String transportProperty =
via.getTransport().toLowerCase() + "Port";
+ String transportProperty = transport +
"Port";
Integer port = (Integer)
node.getProperties().get(transportProperty);
if(port == null) throw new RuntimeException("No transport found for
node " + node + " " + transportProperty);
via.setPort(port);
} catch (Exception e) {
throw new RuntimeException("Error", e);
}
+
if(!ListeningPoint.UDP.equalsIgnoreCase(transport)) {
+ via.setRPort();
+ }
+ }
+ } else {
+ if(earlyDialogWorstCase) {
+ String callId = ((SIPHeader)
response.getHeader(headerName))
+ .getValue();
+ SIPNode node = callIdMap.get(callId);
+ for(int q=0; q<3; q++) {
+ SIPNode other = selectNewNode(node,
callId);
+ if(other!= null && !other.equals(node))
{
+ node = other; break;
+ }
+ }
+ try {
+ via.setHost(node.getIp());
+ String transportProperty = transport +
"Port";
+ Integer port = (Integer)
node.getProperties().get(transportProperty);
+ if(port == null) throw new RuntimeException("No transport found for
node " + node + " " + transportProperty);
+ via.setPort(port);
+ } catch (Exception e) {
+ throw new RuntimeException("Error", e);
+ }
+
if(!ListeningPoint.UDP.equalsIgnoreCase(transport)) {
+ via.setRPort();
+ }
}
}
}
@@ -227,7 +261,11 @@
this.maxCallIdleTime =
Integer.parseInt(maxTimeInCacheString);
}
logger.info("Call Idle Time is " + this.maxCallIdleTime + " seconds.
Inactive calls will be evicted.");
-
+ String earlyDialogWorstCaseString =
getProperties().getProperty("earlyDialogWorstCase");
+ if(earlyDialogWorstCaseString != null) {
+ earlyDialogWorstCase =
Boolean.parseBoolean(earlyDialogWorstCaseString);
+ }
+ logger.info("Early dialog worst case is " +
this.earlyDialogWorstCase);
final WorstCaseUdpTestAffinityAlgorithm thisAlgorithm = this;
this.cacheEvictionTimer.schedule(new TimerTask() {
=======================================
---
/trunk/tools/sip-balancer/jar/src/test/java/org/mobicents/tools/sip/balancer/algorithms/WorstCaseAffinityTest.java
Sun Nov 7 19:02:46 2010
+++
/trunk/tools/sip-balancer/jar/src/test/java/org/mobicents/tools/sip/balancer/algorithms/WorstCaseAffinityTest.java
Sun Dec 19 18:42:21 2010
@@ -2,6 +2,9 @@
import java.util.Properties;
+import javax.sip.address.SipURI;
+import javax.sip.header.RecordRouteHeader;
+
import junit.framework.TestCase;
import org.mobicents.tools.sip.balancer.AppServer;
@@ -64,6 +67,7 @@
}
static AppServer invite;
static AppServer bye;
+ static AppServer ack;
public void testInviteByeLandOnDifferentNodes() throws Exception {
EventListener failureEventListener = new EventListener() {
@@ -75,10 +79,16 @@
@Override
public void uasAfterRequestReceived(String method,
AppServer source) {
if(method.equals("INVITE")) invite = source;
+ if(method.equals("ACK")) {
+ ack = source;
+
+ if(ack != invite) TestCase.fail("INVITE and ACK should have landed on
same node");
+
+ }
if(method.equals("BYE")) {
bye = source;
- if(bye == invite) TestCase.fail("INVITE and BYE should have landed on
different ndoes");
+ if(bye == invite) TestCase.fail("INVITE and BYE should have landed on
different nodes");
}
@@ -104,4 +114,69 @@
if(invite == null) TestCase.fail("INVITE not seen");
if(bye == null) TestCase.fail("BYE not seen");
}
-}
+
+ AppServer ringingAppServer;
+ AppServer okAppServer;
+ public void testOKRingingLandOnSameNode() throws Exception {
+
+ EventListener failureEventListener = new EventListener() {
+
+ @Override
+ public void uasAfterResponse(int statusCode, AppServer
source) {
+
+
+ }
+
+ @Override
+ public void uasAfterRequestReceived(String method,
AppServer source) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void uacAfterRequestSent(String method,
AppServer source) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void uacAfterResponse(int statusCode, AppServer
source) {
+ if(statusCode == 180) {
+ ringingAppServer = source;
+ } else {
+ okAppServer = source;
+
+ }
+ }
+ };
+ for(AppServer as:servers)
as.setEventListener(failureEventListener);
+ shootist.callerSendsBye = true;
+
+ String fromName = "sender";
+ String fromHost = "sip-servlets.com";
+ SipURI fromAddress =
servers[0].protocolObjects.addressFactory.createSipURI(
+ fromName, fromHost);
+
+ String toUser = "replaces";
+ String toHost = "sip-servlets.com";
+ SipURI toAddress =
servers[0].protocolObjects.addressFactory.createSipURI(
+ toUser, toHost);
+
+ SipURI ruri =
servers[0].protocolObjects.addressFactory.createSipURI(
+ "usera", "127.0.0.1:5033");
+ ruri.setLrParam();
+ SipURI route =
servers[0].protocolObjects.addressFactory.createSipURI(
+ "lbint", "127.0.0.1:5065");
+ route.setParameter("node_host", "127.0.0.1");
+ route.setParameter("node_port", "4060");
+ route.setLrParam();
+ shootist.start();
+ //servers[0].sipListener.sendSipRequest("INVITE", fromAddress,
toAddress, null, null, false);
+ servers[0].sipListener.sendSipRequest("INVITE", fromAddress, toAddress,
null, route, false, null, null, ruri);
+ Thread.sleep(16000);
+
assertTrue(shootist.inviteRequest.getHeader(RecordRouteHeader.NAME).toString().contains("node_host"));
+ assertSame(ringingAppServer, okAppServer);
+ assertNotNull(ringingAppServer);
+ assertNotNull(okAppServer);
+ }
+}