package org.mobicents.tools.sip.balancer.btbua; import gov.nist.javax.sip.DialogTimeoutEvent; import gov.nist.javax.sip.ListeningPointExt; import gov.nist.javax.sip.SipListenerExt; import java.text.ParseException; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import javax.sip.ClientTransaction; import javax.sip.Dialog; import javax.sip.DialogState; import javax.sip.DialogTerminatedEvent; import javax.sip.IOExceptionEvent; import javax.sip.InvalidArgumentException; import javax.sip.ListeningPoint; import javax.sip.RequestEvent; import javax.sip.ResponseEvent; import javax.sip.ServerTransaction; import javax.sip.SipException; import javax.sip.SipFactory; import javax.sip.SipProvider; import javax.sip.TimeoutEvent; import javax.sip.TransactionTerminatedEvent; import javax.sip.address.SipURI; import javax.sip.header.CSeqHeader; import javax.sip.header.ContactHeader; import javax.sip.header.FromHeader; import javax.sip.header.RecordRouteHeader; import javax.sip.header.RouteHeader; import javax.sip.header.ViaHeader; import javax.sip.message.MessageFactory; import javax.sip.message.Request; import javax.sip.message.Response; import org.jboss.netty.channel.MessageEvent; import org.mobicents.tools.heartbeat.api.Node; import org.mobicents.tools.heartbeat.api.Protocol; import org.mobicents.tools.heartbeat.impl.ClientController; import org.mobicents.tools.heartbeat.interfaces.IClientListener; import org.mobicents.tools.sip.balancer.ProtocolObjects; import com.google.gson.JsonObject; public class BackToBackUserAgent implements SipListenerExt, IClientListener { private MessageFactory messageFactory; private ProtocolObjects protocolObjects; private ListeningPoint lp; private SipProvider sp; private Node node; AtomicBoolean stopFlag = new AtomicBoolean(false); protected String balancers; String lbAddress; int lbRMIport; int lbPort; private String transport; private int port; private Dialog incomingDialog,outgoingDialog; private ClientTransaction clientTransaction; private ClientController clientController; private int lbHBPort = 2610; private int heartbeatPort = 2222; private int heartbeatPeriod = 1000; private ExecutorService executor = Executors.newCachedThreadPool(); public BackToBackUserAgent(int port,String transport,String lbAddress,int lbRMI,int lbPort) { this.lbAddress = lbAddress; this.lbRMIport = lbRMI; this.transport=transport; this.port=port; this.lbPort=lbPort; } public void start() { SipFactory sipFactory = null; sipFactory = SipFactory.getInstance(); sipFactory.setPathName("gov.nist"); this.protocolObjects = new ProtocolObjects("backtobackua","gov.nist",transport,true, true, false); try { messageFactory = protocolObjects.messageFactory; lp = protocolObjects.sipStack.createListeningPoint("127.0.0.1", port, transport); sp = protocolObjects.sipStack.createSipProvider(lp); sp.addSipListener(this); protocolObjects.start(); node = new Node("Node", "127.0.0.1"); node.getProperties().put(transport.toLowerCase() + "Port",""+ port); node.getProperties().put("version", "0"); node.getProperties().put(Protocol.SESSION_ID, ""+System.currentTimeMillis()); node.getProperties().put(Protocol.HEARTBEAT_PORT, ""+heartbeatPort); clientController = new ClientController(this, lbAddress, lbHBPort, node, 2000, heartbeatPeriod, executor); clientController.startClient(); } catch (Exception ex) { } } private void replyToRequestEvent(Request event, ServerTransaction st,int status) { try { st.sendResponse(messageFactory.createResponse(status,event)); } catch (Throwable e) { e.printStackTrace(); } } private Dialog getPeerDialog(Dialog original) throws SipException { if (original.getDialogId().equals(incomingDialog.getDialogId())) return outgoingDialog; else return incomingDialog; } private void forwardResponse(ResponseEvent receivedResponse) throws SipException { try { ServerTransaction serverTransaction = (ServerTransaction)receivedResponse.getClientTransaction().getApplicationData(); Request stRequest = serverTransaction.getRequest(); Response newResponse = this.messageFactory.createResponse(receivedResponse.getResponse().getStatusCode(),stRequest); ListeningPoint peerListeningPoint = sp.getListeningPoint(transport); ContactHeader peerContactHeader = ((ListeningPointExt)peerListeningPoint).createContactHeader(); newResponse.setHeader(peerContactHeader); serverTransaction.sendResponse(newResponse); } catch (InvalidArgumentException e) { throw new SipException("invalid response", e); } catch (ParseException e) { throw new SipException("invalid response", e); } } public void processDialogTimeout(DialogTimeoutEvent timeoutEvent) { } public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { } public void processIOException(IOExceptionEvent exceptionEvent) { // TODO Auto-generated method stub } public void processRequest(RequestEvent requestEvent) { try { Request request = requestEvent.getRequest(); if (request.getMethod().equals(Request.INVITE)) { ServerTransaction st=sp.getNewServerTransaction(requestEvent.getRequest()); incomingDialog = st.getDialog(); try { replyToRequestEvent(requestEvent.getRequest(), st, Response.TRYING); Request newRequest = (Request) request.clone(); newRequest.removeHeader(RouteHeader.NAME); newRequest.removeHeader(RecordRouteHeader.NAME); FromHeader fromHeader = (FromHeader) newRequest.getHeader(FromHeader.NAME); fromHeader.setTag(Long.toString(Math.abs(new Random().nextLong()))); ViaHeader viaHeader = ((ListeningPointExt) sp.getListeningPoint(transport)).createViaHeader(); newRequest.setHeader(viaHeader); ContactHeader contactHeader = ((ListeningPointExt) sp.getListeningPoint(transport)).createContactHeader(); newRequest.setHeader(contactHeader); SipURI route = this.protocolObjects.addressFactory.createSipURI("lbint", lbAddress + ":" + lbPort); route.setParameter("node_host", "127.0.0.1"); route.setParameter("node_port", "" + port); route.setLrParam(); RouteHeader routeHeader=(RouteHeader)this.protocolObjects.headerFactory.createRouteHeader(this.protocolObjects.addressFactory.createAddress(route)); newRequest.setHeader(routeHeader); clientTransaction = sp.getNewClientTransaction(newRequest); outgoingDialog=clientTransaction.getDialog(); clientTransaction.setApplicationData(st); clientTransaction.sendRequest(); } catch (Throwable e) { e.printStackTrace(); replyToRequestEvent(request, st, Response.SERVICE_UNAVAILABLE); } } else if (request.getMethod().equals(Request.BYE)) { ServerTransaction st=requestEvent.getServerTransaction(); replyToRequestEvent(requestEvent.getRequest(), st, Response.OK); Dialog peerDialog=getPeerDialog(requestEvent.getDialog()); Request outgoingRequest = peerDialog.createRequest(requestEvent.getRequest().getMethod()); final ClientTransaction ct = sp.getNewClientTransaction(outgoingRequest); peerDialog.sendRequest(ct); } else if( request.getMethod().equals(Request.CANCEL)) { try { final Dialog peerDialog = outgoingDialog; final DialogState peerDialogState = peerDialog.getState(); if (peerDialogState == null || peerDialogState == DialogState.EARLY) { Request cancelRequest=clientTransaction.createCancel(); sp.sendRequest(cancelRequest); } else { clientTransaction=sp.getNewClientTransaction(peerDialog.createRequest(Request.BYE)); clientTransaction.sendRequest(); } } catch (Exception e) { e.printStackTrace(); } } } catch ( Exception ex) { ex.printStackTrace(); } } public void processResponse(ResponseEvent responseEvent) { try { if(responseEvent.getResponse().getStatusCode()>=100 && responseEvent.getResponse().getStatusCode()<200) { if (responseEvent.getResponse().getStatusCode() == Response.TRYING) return; forwardResponse(responseEvent); } else if(responseEvent.getResponse().getStatusCode()>=200 && responseEvent.getResponse().getStatusCode()<300) { final CSeqHeader cseq = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); if (cseq.getMethod().equals(Request.INVITE)) { try { final Request ack = responseEvent.getDialog().createAck(cseq.getSeqNumber()); responseEvent.getDialog().sendAck(ack); } catch (Exception e) { e.printStackTrace(); } } else if (cseq.getMethod().equals(Request.BYE) || cseq.getMethod().equals(Request.CANCEL)) return; forwardResponse(responseEvent); } else forwardResponse(responseEvent); } catch (Exception ex) { ex.printStackTrace(); } } public void processTimeout(TimeoutEvent timeoutEvent) { // TODO Auto-generated method stub } public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { } public void stop() { clientController.stopClient(false); if(protocolObjects != null) protocolObjects.sipStack.stop(); protocolObjects=null; } @Override public void responseReceived(JsonObject json) { // TODO Auto-generated method stub } @Override public void stopRequestReceived(MessageEvent e, JsonObject json) { // TODO Auto-generated method stub } // private void sendKeepAliveToBalancers(ArrayList<Node> info) // { // Thread.currentThread().setContextClassLoader(NodeRegisterRMIStub.class.getClassLoader()); // if(balancers != null) { // for(String balancer:balancers.replaceAll(" ","").split(",")) { // if(balancer.length()<2) continue; // String host; // String port; // int semi = balancer.indexOf(':'); // if(semi>0) { // host = balancer.substring(0, semi); // port = balancer.substring(semi+1); // } else { // host = balancer; // port = "2000"; // } // try { // Registry registry = LocateRegistry.getRegistry(host, Integer.parseInt(port)); // NodeRegisterRMIStub reg=(NodeRegisterRMIStub) registry.lookup("SIPBalancer"); // reg.handlePing(info); // } catch (Exception e) { // e.printStackTrace(); // } // } // // } else { // try { // Registry registry = LocateRegistry.getRegistry(lbAddress, lbRMIport); // NodeRegisterRMIStub reg=(NodeRegisterRMIStub) registry.lookup("SIPBalancer"); // reg.handlePing(info); // } catch (Exception e) { // e.printStackTrace(); // } // } // } // public void sendCleanShutdownToBalancers() { // ArrayList<Node> nodes = new ArrayList<Node>(); // nodes.add(appServerNode); // sendCleanShutdownToBalancers(nodes); // } // public void sendCleanShutdownToBalancers(ArrayList<Node> info) { // Thread.currentThread().setContextClassLoader(NodeRegisterRMIStub.class.getClassLoader()); // try { // Registry registry = LocateRegistry.getRegistry(lbAddress, lbRMIport); // NodeRegisterRMIStub reg=(NodeRegisterRMIStub) registry.lookup("SIPBalancer"); // reg.forceRemoval(info); // stop(); // Thread.sleep(2000); // delay the OK for a while // } catch (Exception e) { // e.printStackTrace(); // } // } }