001: package examples.tpcc;
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.FileAppender;
010: import org.apache.log4j.Logger;
011: import org.apache.log4j.SimpleLayout;
012:
013: import java.util.*;
014: import java.io.IOException;
015: import java.text.ParseException;
016:
017: /**
018: * The Click to dial third party call controller flow IV application.
019: *
020: * @author Kathleen McCallum
021: *
022: * <pre>
023: * main () -> init()
024: * init()
025: * createSipStack
026: * createInvite() -> First
027: * processResponse()
028: * if (OK) first
029: * ack() first
030: * createInvite() -> second no SDP
031: * else if (OK) second
032: * ack() -> second
033: * ack() -> first
034: * </pre>
035: *
036: *
037: *
038: */
039:
040: public class Controller4 implements SipListener {
041:
042: private static SipProvider sipProvider;
043:
044: private static AddressFactory addressFactory;
045:
046: private static MessageFactory messageFactory;
047:
048: private static HeaderFactory headerFactory;
049:
050: private static SipStack sipStack;
051:
052: private ContactHeader contactHeader;
053:
054: private ListeningPoint udpListeningPoint;
055:
056: protected ClientTransaction inviteFirst;
057:
058: protected ClientTransaction inviteSecond;
059:
060: private String currentState;
061:
062: String transport = "udp";
063:
064: protected static final String usageString = "java "
065: + "examples.ctd.ctdControll \n"
066: + ">>>> is your class path set to the root?";
067:
068: private Dialog firstDialog;
069:
070: private Dialog secondDialog;
071: private static Logger logger = Logger.getLogger(Controller4.class);
072:
073: private String auser = "AGuy";
074:
075: private String aSipAddressDomain = "Afirst.com";
076:
077: private String aDisplayName = "The A first";
078:
079: private String buser = "BGuy";
080:
081: private String bSipAddressDomain = "BSecond.com";
082:
083: private String bDisplayName = "The B second";
084:
085: private String peerHostPortA = "127.0.0.1:5070";
086:
087: private String peerHostPortB = "127.0.0.1:5080";
088:
089: int first = 0, second = 0;
090:
091: private Response secondDialogOK;
092:
093: public void processRequest(RequestEvent requestReceivedEvent) {
094: Request request = requestReceivedEvent.getRequest();
095: ServerTransaction serverTransactionId = requestReceivedEvent
096: .getServerTransaction();
097:
098: logger.info("\n\nRequest " + request.getMethod()
099: + " received at " + sipStack.getStackName()
100: + " with server transaction id " + serverTransactionId);
101:
102: // We are the Controller so the only request we get is the BYE.
103: if (request.getMethod().equals(Request.BYE))
104: processBye(request, serverTransactionId);
105:
106: }
107:
108: public void processBye(Request request,
109: ServerTransaction serverTransactionId) {
110:
111: try {
112: logger.info("Controller4: got a bye .");
113: if (serverTransactionId == null) {
114: logger.info("Controller4: null TID.");
115: return;
116: }
117:
118: logger.info("Create OK para BYE: ");
119: // 1: OK BYE
120: Response ok = messageFactory.createResponse(Response.OK,
121: request);
122: serverTransactionId.sendResponse(ok);
123:
124: // 2do: BYE for the other side (send a new clientTransaction)
125: logger.info("Send BYE in new clientTransaction");
126:
127: Dialog secondBye = (Dialog) (serverTransactionId
128: .getDialog().getApplicationData());
129: Request requestBye = secondBye.createRequest(Request.BYE);
130: ClientTransaction clientTransaction = null;
131: clientTransaction = sipProvider
132: .getNewClientTransaction(requestBye);
133: secondBye.sendRequest(clientTransaction);
134:
135: } catch (Exception ex) {
136: ex.printStackTrace();
137: System.exit(0);
138:
139: }
140: }
141:
142: public synchronized void processResponse(
143: ResponseEvent responseReceivedEvent) {
144: logger.info("Got a response");
145: Response response = (Response) responseReceivedEvent
146: .getResponse();
147: ClientTransaction tid = responseReceivedEvent
148: .getClientTransaction();
149: CSeqHeader cseq = (CSeqHeader) response
150: .getHeader(CSeqHeader.NAME);
151:
152: logger.info("Response received : Status Code = "
153: + response.getStatusCode() + " " + cseq);
154: if (tid == null) {
155: logger.info("Stray response -- dropping ");
156: return;
157: }
158: logger.info("transaction state is " + tid.getState());
159: logger.info("Dialog = " + tid.getDialog());
160: logger.info("Dialog State is " + tid.getDialog().getState());
161:
162: try {
163: if (response.getStatusCode() == Response.OK) {
164: if (cseq.getMethod().equals(Request.INVITE)) {
165: if (currentState.equals("first")) {
166: logger.info("processResponse FIRST");
167: // send ACK
168: this .firstDialog = tid.getDialog();
169: Request ackRequest = firstDialog.createAck(cseq
170: .getSeqNumber());
171: logger.info("Sending ACK firtInvite no media");
172: firstDialog.sendAck(ackRequest);
173:
174: // invite second no SDP
175: // get call-id
176: String callId = ((CallIdHeader) response
177: .getHeader(CallIdHeader.NAME))
178: .getCallId();
179: // Create second Invite
180: second++;
181: currentState = "second";
182: Request requestSecond = this .createInvite(
183: currentState, String.valueOf(second),
184: callId, null, peerHostPortB);
185: inviteSecond = sipProvider
186: .getNewClientTransaction(requestSecond);
187: inviteSecond.sendRequest();
188: logger.info("INVITE second sent:\n"
189: + requestSecond);
190:
191: } else if (currentState.equals("second")) {
192: logger.info("processResponse SECOND");
193: // get offer of second
194: byte[] content = response.getRawContent();
195: ContentTypeHeader cth = (ContentTypeHeader) response
196: .getHeader(ContentTypeHeader.NAME);
197:
198: // reinvite First
199: Request reinvite = firstDialog
200: .createRequest(Request.INVITE);
201: reinvite.removeContent();
202: reinvite.setContent(content, cth);
203:
204: // Re-Invte offer2'
205: ClientTransaction ct = sipProvider
206: .getNewClientTransaction(reinvite);
207: firstDialog.sendRequest(ct);
208: this .secondDialog = tid.getDialog();
209: this .secondDialogOK = response;
210: logger.info("RE-INVITE sent:\n" + reinvite);
211: currentState = "re-invite";
212:
213: } else if (currentState.equals("re-invite")) {
214: logger.info("processResponse re-invite");
215: // send ack
216: CSeqHeader cseq2 = (CSeqHeader) this .secondDialogOK
217: .getHeader(CSeqHeader.NAME);
218: Request ackRequest = secondDialog
219: .createAck(cseq2.getSeqNumber());// secondDialog.createRequest(Request.ACK);
220: logger.info("Sending ACK second "
221: + secondDialog);
222: secondDialog.sendAck(ackRequest);// secondDialog.sendAck(ackRequest);
223:
224: Request ackRequestFirst = this .firstDialog
225: .createAck(cseq.getSeqNumber());
226: ackRequestFirst.setContent(response
227: .getContent(),
228: (ContentTypeHeader) (response
229: .getHeader("Content-Type")));
230:
231: logger.info("Sending ACK first");
232: firstDialog.sendAck(ackRequestFirst);
233:
234: // save the dialog of the other side, for the bye...
235: firstDialog.setApplicationData(secondDialog);
236: secondDialog.setApplicationData(firstDialog);
237:
238: currentState = "fin";
239: }
240: }
241: }
242: } catch (Exception ex) {
243: ex.printStackTrace();
244: System.exit(0);
245: }
246: }
247:
248: public Request createInvite(String headerName, String headerValue,
249: String callerId, String tagVal, String peerHostPort)
250: throws ParseException, InvalidArgumentException {
251:
252: String fromSipAddressDomain = "", toSipAddressDomain = "";
253: String fromDisplayName = "";
254: String toDisplayName = "";
255: String fromVal = "", toVal = "";
256:
257: if (headerName.equals("first")) {
258: fromVal = auser;
259: fromSipAddressDomain = aSipAddressDomain;
260: fromDisplayName = aDisplayName;
261: toVal = buser;
262: toSipAddressDomain = bSipAddressDomain;
263: toDisplayName = bDisplayName;
264: } else if (headerName.equals("second")) {
265: fromVal = buser;
266: fromSipAddressDomain = bSipAddressDomain;
267: fromDisplayName = bDisplayName;
268: toVal = auser;
269: toSipAddressDomain = aSipAddressDomain;
270: toDisplayName = aDisplayName;
271: }
272: logger.info("CreateInvite ");
273:
274: // create >From Header
275: SipURI fromAddress = addressFactory.createSipURI(fromVal,
276: fromSipAddressDomain);
277: Address fromNameAddress = addressFactory
278: .createAddress(fromAddress);
279: fromNameAddress.setDisplayName(fromDisplayName);
280: FromHeader fromHeader = headerFactory.createFromHeader(
281: fromNameAddress, new Integer(
282: (int) (Math.random() * 10000)).toString());
283:
284: // create To Header
285: SipURI toAddress = addressFactory.createSipURI(toVal,
286: toSipAddressDomain);
287: Address toNameAddress = addressFactory.createAddress(toAddress);
288: toNameAddress.setDisplayName(toDisplayName);
289: ToHeader toHeader = headerFactory.createToHeader(toNameAddress,
290: null);
291:
292: // create Request URI
293: SipURI requestURI = addressFactory.createSipURI(toVal,
294: peerHostPort);
295:
296: // Create ViaHeaders
297: ArrayList viaHeaders = new ArrayList();
298: ViaHeader viaHeader = headerFactory.createViaHeader(
299: "127.0.0.1", sipProvider.getListeningPoint(transport)
300: .getPort(), transport, null);
301: viaHeaders.add(viaHeader);
302:
303: // Create a new CallId header
304: CallIdHeader callIdHeader = null;
305: if (callerId == null) {
306: callIdHeader = sipProvider.getNewCallId();
307: } else {
308: callIdHeader = headerFactory.createCallIdHeader(callerId);
309: }
310:
311: // Create a new Cseq header
312: CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(Long
313: .parseLong(headerValue), Request.INVITE);
314:
315: // Create a new MaxForwardsHeader
316: MaxForwardsHeader maxForwards = headerFactory
317: .createMaxForwardsHeader(70);
318:
319: // Create the request.
320: Request request = messageFactory.createRequest(requestURI,
321: Request.INVITE, callIdHeader, cSeqHeader, fromHeader,
322: toHeader, viaHeaders, maxForwards);
323: // Create contact headers
324: String host = "127.0.0.1";
325: SipURI contactUrl = addressFactory.createSipURI(fromVal, host);
326: contactUrl.setPort(udpListeningPoint.getPort());
327:
328: // Create the contact name address.
329: SipURI contactURI = addressFactory.createSipURI(fromVal, host);
330: contactURI.setPort(sipProvider.getListeningPoint(transport)
331: .getPort());
332: Address contactAddress = addressFactory
333: .createAddress(contactURI);
334:
335: // Add the contact address.
336: contactAddress.setDisplayName(fromVal);
337: contactHeader = headerFactory
338: .createContactHeader(contactAddress);
339: request.addHeader(contactHeader);
340:
341: // Allow header. With PUBLISH, to indicate that we'd like to have an
342: // server-sided PA
343: String methods = Request.INVITE + ", " + Request.ACK + ", "
344: + Request.OPTIONS + ", " + Request.CANCEL + ", "
345: + Request.BYE + ", " + Request.INFO + ", "
346: + Request.REFER + ", " + Request.MESSAGE + ", "
347: + Request.NOTIFY + ", " + Request.SUBSCRIBE;
348: AllowHeader allowHeader = headerFactory
349: .createAllowHeader(methods);
350: request.addHeader(allowHeader);
351:
352: return request;
353: }
354:
355: public void init() throws IOException {
356: SipFactory sipFactory = null;
357: sipStack = null;
358: sipFactory = SipFactory.getInstance();
359: sipFactory.setPathName("gov.nist");
360: Properties properties = new Properties();
361: // This one is optional so I remove it, since I will call 2 parts
362: // properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
363: // + transport);
364: properties.setProperty("javax.sip.STACK_NAME", "Controller");
365:
366: properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",
367: "controllerdebug.txt");
368: properties.setProperty("gov.nist.javax.sip.SERVER_LOG",
369: "controllerlog.txt");
370: properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL",
371: "DEBUG");
372: properties.setProperty(
373: "gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
374:
375: logger.addAppender(new ConsoleAppender(new SimpleLayout()));
376: logger.addAppender(new FileAppender(new SimpleLayout(),
377: "controllerconsolelog.txt"));
378:
379: try {
380: sipStack = sipFactory.createSipStack(properties);
381: logger.info("createSipStack " + sipStack);
382:
383: headerFactory = sipFactory.createHeaderFactory();
384: addressFactory = sipFactory.createAddressFactory();
385: messageFactory = sipFactory.createMessageFactory();
386: udpListeningPoint = sipStack.createListeningPoint(
387: "127.0.0.1", 5050, "udp");
388: sipProvider = sipStack.createSipProvider(udpListeningPoint);
389: Controller4 listener = this ;
390: sipProvider.addSipListener(listener);
391:
392: } catch (PeerUnavailableException e) {
393: e.printStackTrace();
394: System.err.println(e.getMessage());
395: System.exit(0);
396: } catch (Exception e) {
397: logger.info("Creating Listener Points");
398: logger.info(e.getMessage());
399: e.printStackTrace();
400: }
401: try {
402: logger.info("ProcessCTD ");
403: first++;
404: this .currentState = "first";
405: Request request = this .createInvite(currentState, String
406: .valueOf(first), null, null, peerHostPortA);
407:
408: // Create ContentTypeHeader, !no media type!
409: ContentTypeHeader contentTypeHeader = headerFactory
410: .createContentTypeHeader("application", "sdp");
411: String sdpData = "v=0\r\n"
412: + "o=4855 13760799956958020 13760799956958020"
413: + " IN IP4 129.6.55.78\r\n"
414: + "s=mysession session\r\n"
415: + "p=+46 8 52018010\r\n"
416: + "c=IN IP4 129.6.55.78\r\n" + "t=0 0\r\n"
417: + "a=rtpmap:0 PCMU/8000\r\n"
418: + "a=rtpmap:4 G723/8000\r\n"
419: + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n";
420: byte[] contents = sdpData.getBytes();
421: request.setContent(contents, contentTypeHeader);
422:
423: // Create the client transaction.
424: inviteFirst = sipProvider.getNewClientTransaction(request);
425: // send the request out.
426: inviteFirst.sendRequest();
427: logger.info("INVITE first sent:\n" + request);
428:
429: } catch (Exception e) {
430: logger.info("Creating call CreateInvite()");
431: logger.info(e.getMessage());
432: e.printStackTrace();
433: }
434: }
435:
436: public static void main(String args[]) throws Exception {
437: new Controller4().init();
438: }
439:
440: public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
441: logger.info("Transaction Time out");
442: }
443:
444: public void processIOException(IOExceptionEvent exceptionEvent) {
445: logger.info("IOException happened for "
446: + exceptionEvent.getHost() + " port = "
447: + exceptionEvent.getPort());
448: }
449:
450: public void processTransactionTerminated(
451: TransactionTerminatedEvent transactionTerminatedEvent) {
452: logger.info("Transaction terminated event recieved");
453: }
454:
455: public void processDialogTerminated(
456: DialogTerminatedEvent dialogTerminatedEvent) {
457: logger.info("dialogTerminatedEvent");
458: }
459: }
|