001: package examples.cancel;
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.ConsoleAppender;
009: import org.apache.log4j.Logger;
010: import org.apache.log4j.SimpleLayout;
011:
012: import java.util.*;
013:
014: import junit.framework.TestCase;
015:
016: /**
017: * This class is a UAC template. Shootist is the guy that shoots and shootme is
018: * the guy that gets shot.
019: *
020: * @author M. Ranganathan
021: */
022:
023: public class Shootist extends TestCase implements SipListener {
024:
025: private SipProvider sipProvider;
026:
027: private ContactHeader contactHeader;
028:
029: private ListeningPoint listeningPoint;
030:
031: private static String transport = "udp";
032:
033: private static String host = "127.0.0.1";
034:
035: private static int port = 5060;
036:
037: private static String peerHost = "127.0.0.1";
038:
039: private static int peerPort = 5070;
040:
041: private ClientTransaction inviteTid;
042:
043: private static String unexpectedException = "Unexpected Exception ";
044:
045: private Dialog dialog;
046:
047: public static boolean sendDelayedCancel = false;
048:
049: private boolean cancelSent;
050:
051: private boolean cancelOKReceived;
052:
053: private boolean byeSent;
054:
055: private boolean byeOkReceived;
056:
057: private boolean requestTerminated;
058:
059: private static Logger logger = Logger.getLogger(Shootist.class);
060:
061: public void processRequest(RequestEvent requestReceivedEvent) {
062: Request request = requestReceivedEvent.getRequest();
063: ServerTransaction serverTransactionId = requestReceivedEvent
064: .getServerTransaction();
065:
066: logger.info("\n\nRequest " + request.getMethod()
067: + " received at "
068: + ProtocolObjects.sipStack.getStackName()
069: + " with server transaction id " + serverTransactionId);
070:
071: // We are the UAC so the only request we get is the BYE.
072: SipProvider provider = (SipProvider) requestReceivedEvent
073: .getSource();
074: if (request.getMethod().equals(Request.BYE))
075: processBye(provider, request, serverTransactionId);
076:
077: }
078:
079: public void processBye(SipProvider provider, Request request,
080: ServerTransaction serverTransactionId) {
081: try {
082: logger.info("shootist: got a bye .");
083: /*
084: * if (serverTransactionId == null) { serverTransactionId =
085: * provider.getNewServerTransaction(request); }
086: */
087:
088: Response response = ProtocolObjects.messageFactory
089: .createResponse(200, request);
090: provider.sendResponse(response);
091: // serverTransactionId.sendResponse(response);
092: logger.info("shootist: Sending OK.");
093: if (serverTransactionId != null) {
094: // NULL can happen if the bye arrives late.
095: Dialog dialog = serverTransactionId.getDialog();
096: logger.info("Dialog State = " + dialog.getState());
097: }
098:
099: } catch (Exception ex) {
100: logger.error(unexpectedException, ex);
101: fail(unexpectedException);
102:
103: }
104: }
105:
106: public void processResponse(ResponseEvent responseReceivedEvent) {
107: logger.info("Got a response");
108: Response response = (Response) responseReceivedEvent
109: .getResponse();
110: ClientTransaction tid = responseReceivedEvent
111: .getClientTransaction();
112: CSeqHeader cseq = (CSeqHeader) response
113: .getHeader(CSeqHeader.NAME);
114:
115: logger.info("Response received : Status Code = "
116: + response.getStatusCode() + " " + cseq);
117: if (tid == null) {
118: logger.info("Stray response -- dropping ");
119: return;
120: }
121: logger.info("transaction state is " + tid.getState());
122: logger.info("Dialog = " + tid.getDialog());
123: logger.info("Dialog State is " + tid.getDialog().getState());
124:
125: try {
126: if (response.getStatusCode() == Response.OK) {
127: if (cseq.getMethod().equals(Request.INVITE)) {
128: if (!sendDelayedCancel)
129: fail("Should not see OK for the Invite");
130: // Got the OK for the invite. If Send Cancel was delayed.
131:
132: Request ackRequest = dialog
133: .createRequest(Request.ACK);
134: logger.info("Sending ACK");
135: dialog.sendAck(ackRequest);
136: Request byeRequest = dialog
137: .createRequest(Request.BYE);
138:
139: dialog.sendRequest(sipProvider
140: .getNewClientTransaction(byeRequest));
141: this .byeSent = true;
142: } else if (cseq.getMethod().equals(Request.CANCEL)) {
143: this .cancelOKReceived = true;
144: if (dialog.getState() == DialogState.CONFIRMED) {
145: // oops cancel went in too late. Need to hang up the
146: // dialog.
147: logger
148: .info("Sending BYE -- cancel went in too late !!");
149: Request byeRequest = dialog
150: .createRequest(Request.BYE);
151: ClientTransaction ct = sipProvider
152: .getNewClientTransaction(byeRequest);
153: dialog.sendRequest(ct);
154: assertTrue(dialog.getState().equals(
155: DialogState.TERMINATED));
156:
157: }
158: } else if (cseq.getMethod().equals(Request.BYE)) {
159: this .byeOkReceived = true;
160: }
161: } else if (response.getStatusCode() == Response.RINGING) {
162: // Cancel the invite.
163: if (!cancelSent) {
164: if (!sendDelayedCancel)
165: sendCancel();
166:
167: }
168: } else if (response.getStatusCode() == Response.REQUEST_TERMINATED) {
169: assertTrue(cseq.getMethod().equals(Request.INVITE));
170: this .requestTerminated = true;
171: }
172:
173: } catch (Exception ex) {
174: logger.error(unexpectedException, ex);
175: fail(unexpectedException);
176:
177: }
178:
179: }
180:
181: public void checkState() {
182: if (sendDelayedCancel)
183: assertTrue(byeSent && byeOkReceived);
184: else
185: assertTrue(cancelSent && cancelOKReceived
186: && requestTerminated);
187:
188: }
189:
190: public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
191:
192: logger.info("Transaction Time out");
193: fail("unexpected timeout");
194: }
195:
196: private void sendCancel() {
197: try {
198: logger.info("Sending cancel");
199:
200: Request cancelRequest = inviteTid.createCancel();
201: ClientTransaction cancelTid = sipProvider
202: .getNewClientTransaction(cancelRequest);
203: cancelTid.sendRequest();
204: cancelSent = true;
205: } catch (Exception ex) {
206: ex.printStackTrace();
207: logger.error(unexpectedException, ex);
208: fail(unexpectedException);
209: }
210: }
211:
212: public SipProvider createSipProvider() {
213: try {
214: listeningPoint = ProtocolObjects.sipStack
215: .createListeningPoint(host, port, transport);
216:
217: sipProvider = ProtocolObjects.sipStack
218: .createSipProvider(listeningPoint);
219: return sipProvider;
220: } catch (Exception ex) {
221: logger.error(unexpectedException, ex);
222: fail(unexpectedException);
223: return null;
224: }
225:
226: }
227:
228: public void sendInvite() {
229: try {
230:
231: String fromName = "BigGuy";
232: String fromSipAddress = "here.com";
233: String fromDisplayName = "The Master Blaster";
234:
235: String toSipAddress = "there.com";
236: String toUser = "LittleGuy";
237: String toDisplayName = "The Little Blister";
238:
239: // create >From Header
240: SipURI fromAddress = ProtocolObjects.addressFactory
241: .createSipURI(fromName, fromSipAddress);
242:
243: Address fromNameAddress = ProtocolObjects.addressFactory
244: .createAddress(fromAddress);
245: fromNameAddress.setDisplayName(fromDisplayName);
246: FromHeader fromHeader = ProtocolObjects.headerFactory
247: .createFromHeader(fromNameAddress, "12345");
248:
249: // create To Header
250: SipURI toAddress = ProtocolObjects.addressFactory
251: .createSipURI(toUser, toSipAddress);
252: Address toNameAddress = ProtocolObjects.addressFactory
253: .createAddress(toAddress);
254: toNameAddress.setDisplayName(toDisplayName);
255: ToHeader toHeader = ProtocolObjects.headerFactory
256: .createToHeader(toNameAddress, null);
257:
258: // create Request URI
259: String peerHostPort = peerHost + ":" + peerPort;
260: SipURI requestURI = ProtocolObjects.addressFactory
261: .createSipURI(toUser, peerHostPort);
262:
263: // Create ViaHeaders
264:
265: ArrayList viaHeaders = new ArrayList();
266: ViaHeader viaHeader = ProtocolObjects.headerFactory
267: .createViaHeader(host, sipProvider
268: .getListeningPoint(transport).getPort(),
269: transport, null);
270:
271: // add via headers
272: viaHeaders.add(viaHeader);
273:
274: SipURI sipuri = ProtocolObjects.addressFactory
275: .createSipURI(null, host);
276: sipuri.setPort(peerPort);
277: sipuri.setLrParam();
278:
279: RouteHeader routeHeader = ProtocolObjects.headerFactory
280: .createRouteHeader(ProtocolObjects.addressFactory
281: .createAddress(sipuri));
282:
283: // Create ContentTypeHeader
284: ContentTypeHeader contentTypeHeader = ProtocolObjects.headerFactory
285: .createContentTypeHeader("application", "sdp");
286:
287: // Create a new CallId header
288: CallIdHeader callIdHeader = sipProvider.getNewCallId();
289:
290: // Create a new Cseq header
291: CSeqHeader cSeqHeader = ProtocolObjects.headerFactory
292: .createCSeqHeader(1L, Request.INVITE);
293:
294: // Create a new MaxForwardsHeader
295: MaxForwardsHeader maxForwards = ProtocolObjects.headerFactory
296: .createMaxForwardsHeader(70);
297:
298: // Create the request.
299: Request request = ProtocolObjects.messageFactory
300: .createRequest(requestURI, Request.INVITE,
301: callIdHeader, cSeqHeader, fromHeader,
302: toHeader, viaHeaders, maxForwards);
303: // Create contact headers
304:
305: SipURI contactUrl = ProtocolObjects.addressFactory
306: .createSipURI(fromName, host);
307: contactUrl.setPort(listeningPoint.getPort());
308:
309: // Create the contact name address.
310: SipURI contactURI = ProtocolObjects.addressFactory
311: .createSipURI(fromName, host);
312: contactURI.setPort(sipProvider.getListeningPoint("udp")
313: .getPort());
314:
315: Address contactAddress = ProtocolObjects.addressFactory
316: .createAddress(contactURI);
317:
318: // Add the contact address.
319: contactAddress.setDisplayName(fromName);
320:
321: contactHeader = ProtocolObjects.headerFactory
322: .createContactHeader(contactAddress);
323: request.addHeader(contactHeader);
324:
325: // Dont use the Outbound Proxy. Use Lr instead.
326: request.setHeader(routeHeader);
327:
328: // Add the extension header.
329: Header extensionHeader = ProtocolObjects.headerFactory
330: .createHeader("My-Header", "my header value");
331: request.addHeader(extensionHeader);
332:
333: String sdpData = "v=0\r\n"
334: + "o=4855 13760799956958020 13760799956958020"
335: + " IN IP4 129.6.55.78\r\n"
336: + "s=mysession session\r\n"
337: + "p=+46 8 52018010\r\n"
338: + "c=IN IP4 129.6.55.78\r\n" + "t=0 0\r\n"
339: + "m=audio 6022 RTP/AVP 0 4 18\r\n"
340: + "a=rtpmap:0 PCMU/8000\r\n"
341: + "a=rtpmap:4 G723/8000\r\n"
342: + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n";
343: byte[] contents = sdpData.getBytes();
344:
345: request.setContent(contents, contentTypeHeader);
346:
347: extensionHeader = ProtocolObjects.headerFactory
348: .createHeader("My-Other-Header",
349: "my new header value ");
350: request.addHeader(extensionHeader);
351:
352: Header callInfoHeader = ProtocolObjects.headerFactory
353: .createHeader("Call-Info",
354: "<http://www.antd.nist.gov>");
355: request.addHeader(callInfoHeader);
356:
357: // Create the client transaction.
358: inviteTid = sipProvider.getNewClientTransaction(request);
359:
360: // send the request out.
361: inviteTid.sendRequest();
362:
363: dialog = inviteTid.getDialog();
364:
365: } catch (Exception ex) {
366: logger.error(unexpectedException, ex);
367: fail(unexpectedException);
368:
369: }
370: }
371:
372: public static void main(String args[]) throws Exception {
373:
374: logger.addAppender(new ConsoleAppender(new SimpleLayout()));
375: ProtocolObjects.init("shootist");
376: Shootist shootist = new Shootist();
377: shootist.createSipProvider();
378: shootist.sipProvider.addSipListener(shootist);
379: shootist.sendInvite();
380:
381: }
382:
383: public void processIOException(IOExceptionEvent exceptionEvent) {
384: logger.info("Got an IO Exception");
385: fail("unexpected event");
386:
387: }
388:
389: public void processTransactionTerminated(
390: TransactionTerminatedEvent transactionTerminatedEvent) {
391: logger.info("Got a transaction terminated event");
392:
393: }
394:
395: public void processDialogTerminated(
396: DialogTerminatedEvent dialogTerminatedEvent) {
397: logger.info("Got a dialog terminated event");
398: this.checkState();
399:
400: }
401:
402: }
|