/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.mobicents.media.server.testsuite.general.ann; import jain.protocol.ip.mgcp.JainMgcpCommandEvent; import jain.protocol.ip.mgcp.JainMgcpEvent; import jain.protocol.ip.mgcp.JainMgcpResponseEvent; import jain.protocol.ip.mgcp.message.Constants; import jain.protocol.ip.mgcp.message.CreateConnection; import jain.protocol.ip.mgcp.message.CreateConnectionResponse; import jain.protocol.ip.mgcp.message.DeleteConnection; import jain.protocol.ip.mgcp.message.NotificationRequest; import jain.protocol.ip.mgcp.message.Notify; import jain.protocol.ip.mgcp.message.NotifyResponse; import jain.protocol.ip.mgcp.message.parms.ConnectionDescriptor; import jain.protocol.ip.mgcp.message.parms.ConnectionIdentifier; import jain.protocol.ip.mgcp.message.parms.ConnectionMode; import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier; import jain.protocol.ip.mgcp.message.parms.EventName; import jain.protocol.ip.mgcp.message.parms.NotifiedEntity; import jain.protocol.ip.mgcp.message.parms.RequestIdentifier; import jain.protocol.ip.mgcp.message.parms.RequestedAction; import jain.protocol.ip.mgcp.message.parms.RequestedEvent; import jain.protocol.ip.mgcp.message.parms.ReturnCode; import jain.protocol.ip.mgcp.pkg.MgcpEvent; import jain.protocol.ip.mgcp.pkg.PackageName; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Vector; import java.util.logging.Level; import javax.sdp.MediaDescription; import javax.sdp.SdpException; import javax.sdp.SdpParseException; import javax.sdp.SessionDescription; import org.apache.log4j.Logger; import org.mobicents.media.server.testsuite.general.AbstractCall; import org.mobicents.media.server.testsuite.general.AbstractTestCase; import org.mobicents.media.server.testsuite.general.CallState; /** * * @author baranowb */ public class AnnCall extends AbstractCall { protected transient Logger logger = Logger.getLogger(AnnCall.class); private AnnCallState localFlowState = AnnCallState.INITIAL; private String HELLO_WORLD = ""; private ConnectionIdentifier allocatedConnection = null; private RequestIdentifier ri = null; public AnnCall(AbstractTestCase testCase, String fileToPlay) throws IOException { super(testCase); super.endpointName = "/mobicents/media/aap/$"; this.HELLO_WORLD = fileToPlay; } protected void setLocalFlowState(AnnCallState state) { if (this.localFlowState == state) { return; } // FIXME: add more this.localFlowState = state; } public void transactionRxTimedOut(JainMgcpCommandEvent arg0) { } public void transactionTxTimedOut(JainMgcpCommandEvent arg0) { switch (this.localFlowState) { case SENT_CRCX: this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); break; case SENT_ANN: // THis is really bad, ... wech sendDelete(); // If it fails, we dont have means to recover do we? this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); break; case SENT_DLCX: this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); break; } } public void transactionEnded(int arg0) { } public void processMgcpCommandEvent(JainMgcpCommandEvent mgcpCommand) { switch (this.localFlowState) { case SENT_ANN: if (mgcpCommand instanceof Notify) { // here we could do something, instead we respond with 200 and // remove Notify notify = (Notify) mgcpCommand; ReturnCode rc = ReturnCode.Transaction_Executed_Normally; NotifyResponse notifyResponse = new NotifyResponse(this, rc); notifyResponse.setTransactionHandle(notify.getTransactionHandle()); super.provider.sendMgcpEvents(new JainMgcpEvent[] { notifyResponse }); // lets remove us from call maps super.testCase.removeCall(mgcpCommand); super.testCase.removeCall(notify.getRequestIdentifier().toString()); cancelTimeoutHandle(); sendDelete(); //stop(); } break; default: stop(); sendDelete(); } } private String buildResponseHeader(JainMgcpResponseEvent response) { ReturnCode r = response.getReturnCode(); String s = new String(r.getValue() + " " + response.getTransactionHandle() + " " + (r.getComment() == null ? "" : r.getComment()) + " " + this.getMGCPComand(response.getObjectIdentifier()) + "\n"); return s; } private String getMGCPComand(int objectIdentifier) { String cmd = null; switch (objectIdentifier) { case Constants.RESP_CREATE_CONNECTION: cmd = "CRCX"; break; case Constants.RESP_DELETE_CONNECTION: cmd = "DLCX"; break; case Constants.RESP_NOTIFICATION_REQUEST: cmd = "RQNT"; break; default: cmd = "WTF"; break; } return cmd; } public void processMgcpResponseEvent(JainMgcpResponseEvent mgcpResponse) { int code = mgcpResponse.getReturnCode().getValue(); int objId = mgcpResponse.getObjectIdentifier(); super.testCase.removeCall(mgcpResponse); switch (this.localFlowState) { case SENT_CRCX: // here we wait for answer, we need to send 200 to invite if (objId == Constants.RESP_CREATE_CONNECTION) { CreateConnectionResponse ccr = (CreateConnectionResponse) mgcpResponse; if (99 < code && code < 200) { // its provisional } else if (199 < code && code < 300) { try { // its success super.endpointIdentifier = ccr.getSpecificEndpointIdentifier(); this.allocatedConnection = ccr.getConnectionIdentifier(); ConnectionDescriptor cd = ccr.getLocalConnectionDescriptor(); SessionDescription sessionDesc = super.testCase.getSdpFactory().createSessionDescription( cd.toString()); this.connectToPeer(sessionDesc); ri = provider.getUniqueRequestIdentifier(); NotificationRequest notificationRequest = new NotificationRequest(this, super.endpointIdentifier, ri); EventName[] signalRequests = { new EventName(PackageName.Announcement, MgcpEvent.ann .withParm(HELLO_WORLD), null) }; notificationRequest.setSignalRequests(signalRequests); RequestedAction[] actions = new RequestedAction[] { RequestedAction.NotifyImmediately }; RequestedEvent[] requestedEvents = { new RequestedEvent(new EventName(PackageName.Announcement, MgcpEvent.oc, null), actions) }; notificationRequest.setRequestedEvents(requestedEvents); // notificationRequest.setTransactionHandle(mgcpProvider.getUniqueTransactionHandler()); NotifiedEntity notifiedEntity = new NotifiedEntity(super.testCase.getClientTestNodeAddress() .getHostAddress(), super.testCase.getClientTestNodeAddress().getHostAddress(), super.testCase.getCallDisplayInterface().getLocalPort()); notificationRequest.setNotifiedEntity(notifiedEntity); notificationRequest.setTransactionHandle(provider.getUniqueTransactionHandler()); // We dont care // super.testCase.addCall(ri, this); super.testCase.addCall(notificationRequest, this); super.testCase.addCall(ri.toString(), this); super.provider.sendMgcpEvents(new JainMgcpCommandEvent[] { notificationRequest }); // IS this wrong? should we wait unitl notification is // played? super.setState(CallState.ESTABILISHED); this.setLocalFlowState(AnnCallState.SENT_ANN); } catch (Exception ex) { java.util.logging.Logger.getLogger(AnnCall.class.getName()).log(Level.SEVERE, null, ex); this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); } } else { // ADD ERROR this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); // FIXME: add error dump logger.error("FAILED[" + this.localFlowState + "] ON CRCX RESPONSE: " + buildResponseHeader(mgcpResponse)); } } else { // ADD ERROR this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); // FIXME: add error dump logger.error("FAILED[" + this.localFlowState + "] ON RESPONSE: " + buildResponseHeader(mgcpResponse)); } break; case SENT_ANN: if (objId == Constants.RESP_NOTIFICATION_REQUEST) { if (99 < code && code < 200) { // its provisional } else if (199 < code && code < 300) { // its success } else { // its error always? // ADD ERROR this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); // FIXME: add error dump logger.error("FAILED[" + this.localFlowState + "] ON RESPONSE: " + buildResponseHeader(mgcpResponse)); } } else { this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); // FIXME: add error dump logger.error("FAILED[" + this.localFlowState + "] ON CRCX RESPONSE: " + buildResponseHeader(mgcpResponse) + " objId1 = " + objId); } break; case SENT_DLCX: if (objId == Constants.RESP_DELETE_CONNECTION) { if (99 < code && code < 200) { // its provisional } else if (199 < code && code < 300) { // its success stop(); } else { // its error always? // ADD ERROR this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); // FIXME: add error dump logger.error("FAILED[" + this.localFlowState + "] ON DLCX RESPONSE: " + buildResponseHeader(mgcpResponse)); } } else { this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); // FIXME: add error dump logger.error("FAILED[" + this.localFlowState + "] ON CRCX RESPONSE: " + buildResponseHeader(mgcpResponse) + " objId = " + objId); } break; default: logger.error("GOT RESPONSE UNKONWN[" + this.localFlowState + "] ON CRCX RESPONSE: " + buildResponseHeader(mgcpResponse)); } } @Override public void start() { try { super.initSocket(); EndpointIdentifier ei = new EndpointIdentifier(super.endpointName, super.testCase .getServerJbossBindAddress().getHostAddress() + ":" + super.testCase.getCallDisplayInterface().getRemotePort()); CreateConnection crcx = new CreateConnection(this, this.callIdentifier, ei, ConnectionMode.SendOnly); // int localPort = this.datagramChannel.socket().getLocalPort(); int localPort = super.socket.getLocalPort(); String sdp = super.getLocalDescriptor(localPort); //System.err.println(sdp); crcx.setRemoteConnectionDescriptor(new ConnectionDescriptor(sdp)); crcx.setTransactionHandle(this.provider.getUniqueTransactionHandler()); super.testCase.addCall(crcx, this); super.provider.sendMgcpEvents(new JainMgcpEvent[] { crcx }); this.setLocalFlowState(AnnCallState.SENT_CRCX); super.setState(CallState.INITIAL); super.onStart(); } catch (Exception e) { e.printStackTrace(); this.setLocalFlowState(AnnCallState.TERMINATED); super.setState(CallState.IN_ERROR); } } private void cancelTimeoutHandle(){ if(super.getTimeoutHandle() != null ){ super.getTimeoutHandle().cancel(false); } } @Override public void stop() { // if(this.localFlowState != AnnCallState.TERMINATED) // { // sendDelete(); // } cancelTimeoutHandle(); if (ri != null) { super.testCase.removeCall(ri.toString()); } if (this.state == CallState.IN_ERROR || this.state == CallState.TIMED_OUT) { this.setLocalFlowState(AnnCallState.TERMINATED); } else { // FIXME: Should in case of forced stop this indicate error? super.setState(CallState.ENDED); this.setLocalFlowState(AnnCallState.TERMINATED); } super.onStop(); } @Override public void timeOut() { // sometimes its error, for us, we consider this and end of test sendDelete(); } private void sendDelete() { DeleteConnection dlcx = new DeleteConnection(this, super.endpointIdentifier); dlcx.setCallIdentifier(this.callIdentifier); dlcx.setConnectionIdentifier(this.allocatedConnection); dlcx.setTransactionHandle(provider.getUniqueTransactionHandler()); super.testCase.addCall(dlcx, this); // IS this wrong? should we wait unitl notification is played? this.setLocalFlowState(AnnCallState.SENT_DLCX); super.provider.sendMgcpEvents(new JainMgcpCommandEvent[] { dlcx }); } private void connectToPeer(SessionDescription sd) throws SdpParseException, SdpException, UnknownHostException, IOException { String cAddress = sd.getConnection().getAddress(); Vector v = sd.getMediaDescriptions(true); MediaDescription md = (MediaDescription) v.get(0); int port = md.getMedia().getMediaPort(); SocketAddress sa = new InetSocketAddress(InetAddress.getAllByName(cAddress)[0], port); // for now we do that like that this will go away with // rtp socket super.socket.setPeer(InetAddress.getAllByName(cAddress)[0], port); } }