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);
+       }
+}

Reply via email to