test.tck.msgflow.callflows.recroute.Proxy Maven / Gradle / Ivy
package test.tck.msgflow.callflows.recroute;
import java.util.Hashtable;
import javax.sip.ClientTransaction;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.ListeningPoint;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.TimeoutEvent;
import javax.sip.TransactionState;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.RecordRouteHeader;
import javax.sip.header.RouteHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import org.apache.log4j.Logger;
import test.tck.TestHarness;
import test.tck.msgflow.callflows.ProtocolObjects;
import test.tck.msgflow.callflows.TestAssertion;
/**
* A very simple Record-Routing proxy server.
*
* @author M. Ranganathan
* @author Jeroen van Bemmel
*
*/
public class Proxy extends TestHarness implements SipListener {
// private ServerTransaction st;
private static String host = "127.0.0.1";
private int port = 5070;
private int peerPort;
private SipProvider sipProvider;
private static String unexpectedException = "Unexpected exception";
private static Logger logger = Logger.getLogger("test.tck");
private ProtocolObjects protocolObjects;
private boolean ackSeen;
private boolean inviteSeen;
private boolean byeSeen;
private int infoCount = 0;
public TestAssertion getAssertion() {
return new TestAssertion() {
@Override
public boolean assertCondition() {
return inviteSeen && (infoCount == 2) && byeSeen && ackSeen;
}
};
}
public void checkState() {
TestHarness.assertTrue("INVITE should be seen by proxy", inviteSeen);
TestHarness.assertTrue("Should see two INFO messages", infoCount == 2);
TestHarness.assertTrue("BYE should be seen by proxy", byeSeen);
TestHarness.assertTrue("ACK should be seen by proxy", ackSeen);
}
public void processRequest(RequestEvent requestEvent) {
try {
Request request = requestEvent.getRequest();
SipProvider sipProvider = (SipProvider) requestEvent.getSource();
if (request.getMethod().equals(Request.INVITE)) {
inviteSeen = true;
ListeningPoint lp = sipProvider
.getListeningPoint(protocolObjects.transport);
String host = lp.getIPAddress();
int port = lp.getPort();
ServerTransaction st = null;
if (requestEvent.getServerTransaction() == null) {
st = sipProvider.getNewServerTransaction(request);
}
Request newRequest = (Request) request.clone();
//
// Add a Route: header to 5080
//
SipURI sipUri = protocolObjects.addressFactory.createSipURI(
"UA1", "127.0.0.1");
sipUri.setPort(peerPort);
sipUri.setLrParam();
sipUri.setTransportParam( protocolObjects.transport );
Address address = protocolObjects.addressFactory.createAddress(
"client1", sipUri);
RouteHeader rheader = protocolObjects.headerFactory
.createRouteHeader(address);
newRequest.addFirst(rheader);
//
// Add a Via header + Record-Route
//
ViaHeader viaHeader = protocolObjects.headerFactory
.createViaHeader(host, port, protocolObjects.transport,
null);
newRequest.addFirst(viaHeader);
ClientTransaction ct1 = sipProvider
.getNewClientTransaction(newRequest);
sipUri = protocolObjects.addressFactory.createSipURI("proxy",
"127.0.0.1");
address = protocolObjects.addressFactory.createAddress("proxy",
sipUri);
sipUri.setPort(this.port);
sipUri.setLrParam();
sipUri.setTransportParam(protocolObjects.transport);
RecordRouteHeader recordRoute = protocolObjects.headerFactory
.createRecordRouteHeader(address);
newRequest.addHeader(recordRoute);
ct1.setApplicationData(st);
// Send the request out to the two listening point of the
// client.
ct1.sendRequest();
TestHarness.assertNull(ct1.getDialog());
} else if (request.getMethod().equals(Request.ACK)) {
Request newRequest = (Request) request.clone();
newRequest.removeFirst(RouteHeader.NAME);
ViaHeader viaHeader = protocolObjects.headerFactory
.createViaHeader(host, port, protocolObjects.transport,
null);
newRequest.addFirst(viaHeader);
this.ackSeen = true;
logger.debug("PROXY : sendingAck " + newRequest);
sipProvider.sendRequest(newRequest);
} else {
// Remove the topmost route header
// The route header will make sure it gets to the right place.
logger.debug("proxy: Got a request\n" + request);
if (request.getMethod().equals(Request.BYE)) {
this.byeSeen = true;
}
if (request.getMethod().equals(Request.INFO)) {
this.infoCount++;
}
if (requestEvent.getServerTransaction() == null) {
TestHarness.assertNull("Dialog should be null",
requestEvent.getDialog());
ServerTransaction stx = sipProvider
.getNewServerTransaction(request);
Request newRequest = (Request) request.clone();
newRequest.removeFirst(RouteHeader.NAME);
ViaHeader viaHeader = protocolObjects.headerFactory
.createViaHeader(host, port,
protocolObjects.transport, null);
newRequest.addFirst(viaHeader);
ClientTransaction ctx = sipProvider
.getNewClientTransaction(newRequest);
ctx.setApplicationData(stx);
stx.setApplicationData(ctx);
ctx.sendRequest();
} else {
logger.debug("Saw a retransmission? State = "
+ requestEvent.getServerTransaction().getState());
}
}
} catch (Exception ex) {
ex.printStackTrace();
logger.error("Unexpected error forwarding request", ex);
TestHarness.fail("Unexpected exception forwarding request");
}
}
public void processResponse(ResponseEvent responseEvent) {
try {
Response response = responseEvent.getResponse();
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
logger.debug("ClientTxID = "
+ responseEvent.getClientTransaction()
+ " client tx id "
+ ((ViaHeader) response.getHeader(ViaHeader.NAME))
.getBranch() + " CSeq header = "
+ response.getHeader(CSeqHeader.NAME) + " status code = "
+ response.getStatusCode());
// JvB: stateful proxy MUST NOT forward 100 Trying
if (response.getStatusCode() == 100)
return;
ClientTransaction ct = responseEvent.getClientTransaction();
if (ct != null) {
ServerTransaction st = (ServerTransaction) ct
.getApplicationData();
// Strip the topmost via header
Response newResponse = (Response) response.clone();
newResponse.removeFirst(ViaHeader.NAME);
// The server tx goes to the terminated state.
if ( st.getState() != TransactionState.TERMINATED)
st.sendResponse(newResponse);
TestHarness.assertNull(st.getDialog());
} else {
// Client tx has already terminated but the UA is
// retransmitting
// just forward the response statelessly.
// Strip the topmost via header
Response newResponse = (Response) response.clone();
newResponse.removeFirst(ViaHeader.NAME);
// Send the retransmission statelessly
SipProvider sipProvider = (SipProvider) responseEvent
.getSource();
sipProvider.sendResponse(newResponse);
}
} catch (Exception ex) {
ex.printStackTrace();
TestHarness.fail("unexpected exception",ex);
}
}
public void processTimeout(TimeoutEvent timeoutEvent) {
logger.error("Timeout occured");
fail("unexpected event");
}
public void processIOException(IOExceptionEvent exceptionEvent) {
logger.error("IOException occured");
fail("unexpected exception io exception");
}
public SipProvider createSipProvider() {
try {
ListeningPoint listeningPoint = protocolObjects.sipStack
.createListeningPoint(host, port, protocolObjects.transport);
sipProvider = protocolObjects.sipStack
.createSipProvider(listeningPoint);
sipProvider.setAutomaticDialogSupportEnabled(false);
return sipProvider;
} catch (Exception ex) {
logger.error(unexpectedException, ex);
fail(unexpectedException);
return null;
}
}
public void processTransactionTerminated(
TransactionTerminatedEvent transactionTerminatedEvent) {
logger.debug("Transaction terminated event occured -- cleaning up");
}
public void processDialogTerminated(
DialogTerminatedEvent dialogTerminatedEvent) {
fail("unexpected event");
}
public Proxy(int myPort, int peerPort, ProtocolObjects protocolObjects) {
this.port = myPort;
this.peerPort = peerPort;
this.protocolObjects = protocolObjects;
}
}