001: package test.tck.msgflow.callflows.redirect;
002:
003: import javax.sip.*;
004: import javax.sip.address.*;
005: import javax.sip.header.*;
006: import javax.sip.message.*;
007:
008: import org.apache.log4j.Logger;
009:
010: import test.tck.TestHarness;
011: import test.tck.msgflow.callflows.ProtocolObjects;
012:
013: import java.util.*;
014:
015: import junit.framework.TestCase;
016:
017: /**
018: * This class is a UAC template. Shootist is the guy that shoots and shootme is
019: * the guy that gets shot.
020: *
021: * @author M. Ranganathan
022: */
023:
024: public class Shootist extends TestHarness implements SipListener {
025:
026: private SipProvider sipProvider;
027:
028: private ProtocolObjects protocolObjects;
029:
030: private ContactHeader contactHeader;
031:
032: private ListeningPoint listeningPoint;
033:
034: private ClientTransaction inviteTid;
035:
036: private Dialog dialog;
037:
038: public static final int myPort = 5080;
039:
040: private int peerPort;
041:
042: private String peerHostPort;
043:
044: private int dialogTerminatedCount;
045:
046: private int transctionTerminatedCount;
047:
048: private int transactionCount;
049:
050: private int dialogCount;
051:
052: private boolean byeReceived;
053:
054: private boolean redirectReceived;
055:
056: private SipURI requestURI;
057:
058: private static Logger logger = Logger.getLogger(Shootist.class);
059:
060: public void processRequest(RequestEvent requestReceivedEvent) {
061: Request request = requestReceivedEvent.getRequest();
062: ServerTransaction serverTransactionId = requestReceivedEvent
063: .getServerTransaction();
064:
065: logger.info("\n\nRequest " + request.getMethod()
066: + " received at "
067: + protocolObjects.sipStack.getStackName()
068: + " with server transaction id " + serverTransactionId);
069:
070: // We are the UAC so the only request we get is the BYE.
071: if (request.getMethod().equals(Request.BYE))
072: processBye(request, serverTransactionId);
073:
074: }
075:
076: public void processBye(Request request,
077: ServerTransaction serverTransactionId) {
078: try {
079: logger.info("shootist: got a bye . ServerTxId = "
080: + serverTransactionId);
081: this .byeReceived = true;
082: if (serverTransactionId == null) {
083: logger.info("shootist: null TID.");
084: return;
085: }
086:
087: Dialog dialog = serverTransactionId.getDialog();
088: assertTrue(dialog == this .dialog);
089: logger.info("Dialog State = " + dialog.getState());
090: Response response = protocolObjects.messageFactory
091: .createResponse(200, request);
092: serverTransactionId.sendResponse(response);
093: this .transactionCount++;
094: logger.info("shootist: Sending OK.");
095: logger.info("Dialog State = " + dialog.getState());
096: ViaHeader via = (ViaHeader) request
097: .getHeader(ViaHeader.NAME);
098: if (via.getTransport().equalsIgnoreCase("UDP")) {
099: assertEquals(
100: "Check for Transaction State of Completed",
101: TransactionState.COMPLETED, serverTransactionId
102: .getState());
103: } else {
104: assertEquals(
105: "Check for Transaction State of Completed",
106: TransactionState.TERMINATED,
107: serverTransactionId.getState());
108: }
109: assertEquals("Check for Dialog state of terminated",
110: DialogState.TERMINATED, dialog.getState());
111:
112: } catch (Exception ex) {
113: ex.printStackTrace();
114: System.exit(0);
115:
116: }
117: }
118:
119: public void processResponse(ResponseEvent responseReceivedEvent) {
120: logger.info("Got a response");
121: Response response = (Response) responseReceivedEvent
122: .getResponse();
123: ClientTransaction tid = responseReceivedEvent
124: .getClientTransaction();
125: CSeqHeader cseq = (CSeqHeader) response
126: .getHeader(CSeqHeader.NAME);
127:
128: logger.info("Response received : Status Code = "
129: + response.getStatusCode() + " " + cseq);
130: if (tid == null) {
131: logger.info("Stray response -- dropping ");
132:
133: return;
134: }
135: logger.info("transaction state is " + tid.getState());
136: logger.info("Dialog = " + tid.getDialog());
137: logger.info("Dialog State is " + tid.getDialog().getState());
138:
139: try {
140: if (response.getStatusCode() == Response.OK) {
141: logger.info("response = " + response);
142: if (cseq.getMethod().equals(Request.INVITE)) {
143: Request ackRequest = dialog.createAck(cseq
144: .getSeqNumber());
145: logger.info("Sending ACK");
146: dialog.sendAck(ackRequest);
147: }
148: } else if (response.getStatusCode() == Response.MOVED_TEMPORARILY) {
149: // Dialog dies as soon as you get an error response.
150: assertTrue(tid.getDialog().getState() == DialogState.TERMINATED);
151: assertSame("Dialog Identity should be preserved", tid
152: .getDialog(), this .dialog);
153: this .redirectReceived = true;
154: if (cseq.getMethod().equals(Request.INVITE)) {
155: // lookup the contact header
156: ContactHeader contHdr = (ContactHeader) response
157: .getHeader(ContactHeader.NAME);
158: // we can re-use the from header
159: FromHeader from = ((FromHeader) response
160: .getHeader(FromHeader.NAME));
161: // we use the to-address, but without the tag
162: ToHeader to = (ToHeader) (response
163: .getHeader(ToHeader.NAME)).clone();
164: to.removeParameter("tag");
165: // the call-id can be re-used
166: CallIdHeader callID = ((CallIdHeader) response
167: .getHeader(CallIdHeader.NAME));
168: // we take the next cseq
169: long seqNo = (((CSeqHeader) response
170: .getHeader(CSeqHeader.NAME)).getSeqNumber());
171: logger.info("seqNo = " + seqNo);
172: CSeqHeader cseqNew = protocolObjects.headerFactory
173: .createCSeqHeader(++seqNo, "INVITE");
174: // Create ViaHeaders (either use tcp or udp)
175: ArrayList viaHeaders = new ArrayList();
176: ViaHeader viaHeader = protocolObjects.headerFactory
177: .createViaHeader("127.0.0.1", sipProvider
178: .getListeningPoint(
179: protocolObjects.transport)
180: .getPort(),
181: protocolObjects.transport, null);
182: // add via headers
183: viaHeaders.add(viaHeader);
184: // create max forwards
185: MaxForwardsHeader maxForwardsHeader = protocolObjects.headerFactory
186: .createMaxForwardsHeader(10);
187: // create invite Request
188: SipURI newUri = (SipURI) this .requestURI.clone();
189: newUri.setParameter("redirection", "true");
190:
191: Request invRequest = protocolObjects.messageFactory
192: .createRequest(newUri, "INVITE", callID,
193: cseqNew, from, to, viaHeaders,
194: maxForwardsHeader);
195: // we set the Request URI to the address given
196: SipURI contactURI = protocolObjects.addressFactory
197: .createSipURI(null, this .listeningPoint
198: .getIPAddress());
199:
200: contactURI.setPort(this .listeningPoint.getPort());
201: contactURI
202: .setTransportParam(protocolObjects.transport);
203:
204: Address address = protocolObjects.addressFactory
205: .createAddress(contactURI);
206: ContactHeader contact = protocolObjects.headerFactory
207: .createContactHeader(address);
208: invRequest.addHeader(contact);
209:
210: // the contacat header in the response contains where to redirect
211: // the request to -- which in this case happens to be back to the
212: // same location.
213: ContactHeader chdr = (ContactHeader) response
214: .getHeader(ContactHeader.NAME);
215:
216: SipURI sipUri = (SipURI) chdr.getAddress().getURI();
217: sipUri.setLrParam();
218: RouteHeader routeHeader = protocolObjects.headerFactory
219: .createRouteHeader(chdr.getAddress());
220: invRequest.addHeader(routeHeader);
221:
222: logger.info("Sending INVITE to "
223: + contHdr.getAddress().getURI().toString());
224: inviteTid = sipProvider
225: .getNewClientTransaction(invRequest);
226: this .transactionCount++;
227:
228: logger.info("New TID = " + inviteTid);
229: Thread.sleep(500);
230: inviteTid.sendRequest();
231: // The 100 response could have returned and changed the state of the transaction and hence this test is not valid.
232: // assertEquals("Expected calling state was " + inviteTid.getState(), inviteTid.getState(),TransactionState.CALLING);
233:
234: logger.info("sendReqeust succeeded " + inviteTid);
235: Dialog dialog = inviteTid.getDialog();
236: assertTrue("Stack must allocate a new dialog",
237: dialog != this .dialog);
238: this .dialogCount++;
239: this .dialog = dialog;
240:
241: }
242: }
243: /**
244: * end of modified code
245: */
246: } catch (Exception ex) {
247: ex.printStackTrace();
248: fail("unexpeced exception");
249: }
250:
251: }
252:
253: public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
254:
255: logger.info("Transaction Time out");
256: fail("Unexpected event");
257: }
258:
259: public SipProvider createProvider() throws Exception {
260: logger.info("Shootist: createProvider()");
261: listeningPoint = protocolObjects.sipStack.createListeningPoint(
262: "127.0.0.1", myPort, protocolObjects.transport);
263: this .sipProvider = protocolObjects.sipStack
264: .createSipProvider(listeningPoint);
265: assertTrue(
266: "listening point should be the same as what the provider returns for this transport",
267: listeningPoint == sipProvider
268: .getListeningPoint(protocolObjects.transport));
269: return sipProvider;
270:
271: }
272:
273: public void sendInvite() {
274:
275: try {
276: /**
277: * either use udp or tcp
278: */
279:
280: String fromName = "BigGuy";
281: String fromSipAddress = "here.com";
282: String fromDisplayName = "The Master Blaster";
283:
284: String toSipAddress = "there.com";
285: String toUser = "LittleGuy";
286: String toDisplayName = "The Little Blister";
287:
288: // create >From Header
289: SipURI fromAddress = protocolObjects.addressFactory
290: .createSipURI(fromName, fromSipAddress);
291:
292: Address fromNameAddress = protocolObjects.addressFactory
293: .createAddress(fromAddress);
294: fromNameAddress.setDisplayName(fromDisplayName);
295: FromHeader fromHeader = protocolObjects.headerFactory
296: .createFromHeader(fromNameAddress, "12345");
297:
298: // create To Header
299: SipURI toAddress = protocolObjects.addressFactory
300: .createSipURI(toUser, toSipAddress);
301: Address toNameAddress = protocolObjects.addressFactory
302: .createAddress(toAddress);
303: toNameAddress.setDisplayName(toDisplayName);
304: ToHeader toHeader = protocolObjects.headerFactory
305: .createToHeader(toNameAddress, null);
306:
307: // create Request URI
308: this .requestURI = protocolObjects.addressFactory
309: .createSipURI(toUser, peerHostPort);
310:
311: // Create ViaHeaders
312:
313: ArrayList viaHeaders = new ArrayList();
314: ViaHeader viaHeader = protocolObjects.headerFactory
315: .createViaHeader("127.0.0.1", sipProvider
316: .getListeningPoint(
317: protocolObjects.transport)
318: .getPort(), protocolObjects.transport, null);
319:
320: // add via headers
321: viaHeaders.add(viaHeader);
322:
323: // Create ContentTypeHeader
324: ContentTypeHeader contentTypeHeader = protocolObjects.headerFactory
325: .createContentTypeHeader("application", "sdp");
326:
327: // Create a new CallId header
328: CallIdHeader callIdHeader = sipProvider.getNewCallId();
329: // JvB: Make sure that the implementation matches the messagefactory
330: callIdHeader = protocolObjects.headerFactory
331: .createCallIdHeader(callIdHeader.getCallId());
332:
333: // Create a new Cseq header
334: CSeqHeader cSeqHeader = protocolObjects.headerFactory
335: .createCSeqHeader(1L, Request.INVITE);
336:
337: // Create a new MaxForwardsHeader
338: MaxForwardsHeader maxForwards = protocolObjects.headerFactory
339: .createMaxForwardsHeader(70);
340:
341: // Create the request.
342: Request request = protocolObjects.messageFactory
343: .createRequest(requestURI, Request.INVITE,
344: callIdHeader, cSeqHeader, fromHeader,
345: toHeader, viaHeaders, maxForwards);
346: // Create contact headers
347: String host = "127.0.0.1";
348:
349: SipURI contactUrl = protocolObjects.addressFactory
350: .createSipURI(fromName, host);
351: /**
352: * either use tcp or udp
353: */
354: contactUrl.setPort(listeningPoint.getPort());
355: contactUrl.setTransportParam(protocolObjects.transport);
356:
357: // Create the contact name address.
358:
359: Address contactAddress = protocolObjects.addressFactory
360: .createAddress(contactUrl);
361: contactUrl.setLrParam();
362:
363: // Add the contact address.
364: contactAddress.setDisplayName(fromName);
365:
366: contactHeader = protocolObjects.headerFactory
367: .createContactHeader(contactAddress);
368: request.addHeader(contactHeader);
369:
370: SipURI uri = protocolObjects.addressFactory.createSipURI(
371: null, "127.0.0.1");
372:
373: uri.setLrParam();
374: uri.setTransportParam(protocolObjects.transport);
375: uri.setPort(this .peerPort);
376:
377: Address address = protocolObjects.addressFactory
378: .createAddress(uri);
379: RouteHeader routeHeader = protocolObjects.headerFactory
380: .createRouteHeader(address);
381: request.addHeader(routeHeader);
382:
383: Header callInfoHeader = protocolObjects.headerFactory
384: .createHeader("Call-Info",
385: "<http://www.antd.nist.gov>");
386: request.addHeader(callInfoHeader);
387:
388: // Create the client transaction.
389: inviteTid = sipProvider.getNewClientTransaction(request);
390:
391: this .transactionCount++;
392:
393: //assertTrue(inviteTid.getState() == TransactionState.CALLING);
394:
395: logger.info("client tx = " + inviteTid);
396: this .dialog = inviteTid.getDialog();
397: this .dialogCount++;
398: assertTrue(this .dialog != null);
399: //assertTrue(dialog.getState() == null);
400: // send the request out.
401: inviteTid.sendRequest();
402:
403: } catch (Exception ex) {
404: logger.error(ex.getMessage(), ex);
405: fail("unexpected exception");
406: }
407: }
408:
409: public Shootist(ProtocolObjects protocolObjects) {
410: this .protocolObjects = protocolObjects;
411: this .peerPort = Shootme.myPort;
412: this .peerHostPort = "127.0.0.1:" + peerPort;
413: }
414:
415: public void processIOException(IOExceptionEvent exceptionEvent) {
416: logger.info("IOException happened for "
417: + exceptionEvent.getHost() + " port = "
418: + exceptionEvent.getPort());
419:
420: }
421:
422: public void processTransactionTerminated(
423: TransactionTerminatedEvent transactionTerminatedEvent) {
424: logger.info("Transaction terminated event recieved for "
425: + transactionTerminatedEvent.getClientTransaction());
426: this .transctionTerminatedCount++;
427: }
428:
429: public void processDialogTerminated(
430: DialogTerminatedEvent dialogTerminatedEvent) {
431: this .dialogTerminatedCount++;
432:
433: }
434:
435: public void checkState() {
436: //assertTrue(dialogTerminatedCount == dialogCount);
437: logger.info("byeRecieved = " + this .byeReceived);
438: logger.info("redirectRecieved" + this.redirectReceived);
439: assertTrue(this.byeReceived && this.redirectReceived);
440:
441: }
442: }
|