001: package test.tck.msgflow.callflows.recroute;
002:
003: import java.util.Hashtable;
004:
005: import javax.sip.ClientTransaction;
006: import javax.sip.DialogTerminatedEvent;
007: import javax.sip.IOExceptionEvent;
008: import javax.sip.ListeningPoint;
009: import javax.sip.RequestEvent;
010: import javax.sip.ResponseEvent;
011: import javax.sip.ServerTransaction;
012: import javax.sip.SipListener;
013: import javax.sip.SipProvider;
014: import javax.sip.TimeoutEvent;
015: import javax.sip.TransactionState;
016: import javax.sip.TransactionTerminatedEvent;
017: import javax.sip.address.Address;
018: import javax.sip.address.SipURI;
019: import javax.sip.header.CSeqHeader;
020: import javax.sip.header.RecordRouteHeader;
021: import javax.sip.header.RouteHeader;
022: import javax.sip.header.ViaHeader;
023: import javax.sip.message.Request;
024: import javax.sip.message.Response;
025:
026: import org.apache.log4j.Logger;
027:
028: import test.tck.TestHarness;
029: import test.tck.msgflow.callflows.ProtocolObjects;
030:
031: /**
032: * A very simple Record-Routing proxy server.
033: *
034: * @author M. Ranganathan
035: * @author Jeroen van Bemmel
036: *
037: */
038: public class Proxy extends TestHarness implements SipListener {
039:
040: // private ServerTransaction st;
041:
042: private static String host = "127.0.0.1";
043:
044: private int port = 5070;
045:
046: private SipProvider sipProvider;
047:
048: private static String unexpectedException = "Unexpected exception";
049:
050: private static Logger logger = Logger.getLogger("test.tck");
051:
052: private ProtocolObjects protocolObjects;
053:
054: private boolean ackSeen;
055:
056: private boolean inviteSeen;
057:
058: private boolean byeSeen;
059:
060: private int infoCount = 0;
061:
062: public void checkState() {
063: TestHarness.assertTrue("INVITE should be seen by proxy",
064: inviteSeen);
065: TestHarness.assertTrue("Should see two INFO messages",
066: infoCount == 2);
067: TestHarness.assertTrue("BYE should be seen by proxy", byeSeen);
068: TestHarness.assertTrue("ACK should be seen by proxy", ackSeen);
069: }
070:
071: public void processRequest(RequestEvent requestEvent) {
072: try {
073: Request request = requestEvent.getRequest();
074: SipProvider sipProvider = (SipProvider) requestEvent
075: .getSource();
076: if (request.getMethod().equals(Request.INVITE)) {
077: inviteSeen = true;
078:
079: ListeningPoint lp = sipProvider
080: .getListeningPoint(protocolObjects.transport);
081: String host = lp.getIPAddress();
082: int port = lp.getPort();
083:
084: ServerTransaction st = null;
085: if (requestEvent.getServerTransaction() == null) {
086: st = sipProvider.getNewServerTransaction(request);
087: }
088: Request newRequest = (Request) request.clone();
089:
090: //
091: // Add a Route: header to 5080
092: //
093: SipURI sipUri = protocolObjects.addressFactory
094: .createSipURI("UA1", "127.0.0.1");
095: sipUri.setPort(5080);
096: sipUri.setLrParam();
097: Address address = protocolObjects.addressFactory
098: .createAddress("client1", sipUri);
099: RouteHeader rheader = protocolObjects.headerFactory
100: .createRouteHeader(address);
101: newRequest.addFirst(rheader);
102:
103: //
104: // Add a Via header + Record-Route
105: //
106: ViaHeader viaHeader = protocolObjects.headerFactory
107: .createViaHeader(host, port,
108: protocolObjects.transport, null);
109: newRequest.addFirst(viaHeader);
110:
111: ClientTransaction ct1 = sipProvider
112: .getNewClientTransaction(newRequest);
113:
114: sipUri = protocolObjects.addressFactory.createSipURI(
115: "proxy", "127.0.0.1");
116: address = protocolObjects.addressFactory.createAddress(
117: "proxy", sipUri);
118: sipUri.setPort(5070);
119: sipUri.setLrParam();
120: sipUri.setTransportParam(protocolObjects.transport);
121:
122: RecordRouteHeader recordRoute = protocolObjects.headerFactory
123: .createRecordRouteHeader(address);
124: newRequest.addHeader(recordRoute);
125: ct1.setApplicationData(st);
126:
127: // Send the request out to the two listening point of the
128: // client.
129: ct1.sendRequest();
130:
131: TestHarness.assertNull(ct1.getDialog());
132: } else if (request.getMethod().equals(Request.ACK)) {
133: Request newRequest = (Request) request.clone();
134: newRequest.removeFirst(RouteHeader.NAME);
135: ViaHeader viaHeader = protocolObjects.headerFactory
136: .createViaHeader(host, port,
137: protocolObjects.transport, null);
138: newRequest.addFirst(viaHeader);
139: this .ackSeen = true;
140: logger.debug("PROXY : sendingAck " + newRequest);
141: sipProvider.sendRequest(newRequest);
142: } else {
143: // Remove the topmost route header
144: // The route header will make sure it gets to the right place.
145: logger.debug("proxy: Got a request\n" + request);
146: if (request.getMethod().equals(Request.BYE)) {
147: this .byeSeen = true;
148: }
149: if (request.getMethod().equals(Request.INFO)) {
150: this .infoCount++;
151: }
152:
153: if (requestEvent.getServerTransaction() == null) {
154: TestHarness.assertNull("Dialog should be null",
155: requestEvent.getDialog());
156: ServerTransaction stx = sipProvider
157: .getNewServerTransaction(request);
158: Request newRequest = (Request) request.clone();
159: newRequest.removeFirst(RouteHeader.NAME);
160: ViaHeader viaHeader = protocolObjects.headerFactory
161: .createViaHeader(host, port,
162: protocolObjects.transport, null);
163: newRequest.addFirst(viaHeader);
164:
165: ClientTransaction ctx = sipProvider
166: .getNewClientTransaction(newRequest);
167: ctx.setApplicationData(stx);
168: stx.setApplicationData(ctx);
169: ctx.sendRequest();
170: } else {
171: logger.debug("Saw a retransmission? State = "
172: + requestEvent.getServerTransaction()
173: .getState());
174: }
175: }
176:
177: } catch (Exception ex) {
178: ex.printStackTrace();
179: logger.error("Unexpected error forwarding request", ex);
180: TestHarness.fail("Unexpected exception forwarding request");
181: }
182:
183: }
184:
185: public void processResponse(ResponseEvent responseEvent) {
186: try {
187: Response response = responseEvent.getResponse();
188: CSeqHeader cseq = (CSeqHeader) response
189: .getHeader(CSeqHeader.NAME);
190: logger.debug("ClientTxID = "
191: + responseEvent.getClientTransaction()
192: + " client tx id "
193: + ((ViaHeader) response.getHeader(ViaHeader.NAME))
194: .getBranch() + " CSeq header = "
195: + response.getHeader(CSeqHeader.NAME)
196: + " status code = " + response.getStatusCode());
197:
198: // JvB: stateful proxy MUST NOT forward 100 Trying
199: if (response.getStatusCode() == 100)
200: return;
201:
202: ClientTransaction ct = responseEvent.getClientTransaction();
203: if (ct != null) {
204: ServerTransaction st = (ServerTransaction) ct
205: .getApplicationData();
206:
207: // Strip the topmost via header
208: Response newResponse = (Response) response.clone();
209: newResponse.removeFirst(ViaHeader.NAME);
210: // The server tx goes to the terminated state.
211: if (st.getState() != TransactionState.TERMINATED)
212: st.sendResponse(newResponse);
213:
214: TestHarness.assertNull(st.getDialog());
215: } else {
216: // Client tx has already terminated but the UA is
217: // retransmitting
218: // just forward the response statelessly.
219: // Strip the topmost via header
220:
221: Response newResponse = (Response) response.clone();
222: newResponse.removeFirst(ViaHeader.NAME);
223: // Send the retransmission statelessly
224: SipProvider sipProvider = (SipProvider) responseEvent
225: .getSource();
226: sipProvider.sendResponse(newResponse);
227: }
228:
229: } catch (Exception ex) {
230: ex.printStackTrace();
231: TestHarness.fail("unexpected exception", ex);
232: }
233: }
234:
235: public void processTimeout(TimeoutEvent timeoutEvent) {
236: logger.error("Timeout occured");
237: fail("unexpected event");
238: }
239:
240: public void processIOException(IOExceptionEvent exceptionEvent) {
241: logger.error("IOException occured");
242: fail("unexpected exception io exception");
243: }
244:
245: public SipProvider createSipProvider() {
246: try {
247: ListeningPoint listeningPoint = protocolObjects.sipStack
248: .createListeningPoint(host, port,
249: protocolObjects.transport);
250:
251: sipProvider = protocolObjects.sipStack
252: .createSipProvider(listeningPoint);
253: sipProvider.setAutomaticDialogSupportEnabled(false);
254: return sipProvider;
255: } catch (Exception ex) {
256: logger.error(unexpectedException, ex);
257: fail(unexpectedException);
258: return null;
259: }
260:
261: }
262:
263: public void processTransactionTerminated(
264: TransactionTerminatedEvent transactionTerminatedEvent) {
265: logger
266: .debug("Transaction terminated event occured -- cleaning up");
267: }
268:
269: public void processDialogTerminated(
270: DialogTerminatedEvent dialogTerminatedEvent) {
271: fail("unexpected event");
272: }
273:
274: public Proxy(int myPort, ProtocolObjects protocolObjects) {
275: this.port = myPort;
276: this.protocolObjects = protocolObjects;
277: }
278:
279: }
|