001: /*
002: * Conditions Of Use
003: *
004: * This software was developed by employees of the National Institute of
005: * Standards and Technology (NIST), and others.
006: * This software is has been contributed to the public domain.
007: * As a result, a formal license is not needed to use the software.
008: *
009: * This software is provided "AS IS."
010: * NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
011: * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
012: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
013: * AND DATA ACCURACY. NIST does not warrant or make any representations
014: * regarding the use of the software or the results thereof, including but
015: * not limited to the correctness, accuracy, reliability or usefulness of
016: * the software.
017: *
018: *
019: */
020: package test.tck.msgflow.callflows.reinvite;
021:
022: import javax.sip.*;
023: import javax.sip.address.*;
024: import javax.sip.header.*;
025: import javax.sip.message.*;
026:
027: import org.apache.log4j.ConsoleAppender;
028: import org.apache.log4j.Logger;
029: import org.apache.log4j.SimpleLayout;
030: import org.apache.log4j.helpers.NullEnumeration;
031:
032: import test.tck.msgflow.callflows.ProtocolObjects;
033:
034: /**
035: * This class is a UAC template.
036: *
037: * @author M. Ranganathan
038: */
039:
040: public class Shootme implements SipListener {
041:
042: private ProtocolObjects protocolObjects;
043:
044: // To run on two machines change these to suit.
045: public static final String myAddress = "127.0.0.1";
046:
047: public static final int myPort = 5070;
048:
049: private ServerTransaction inviteTid;
050:
051: private static Logger logger = Logger.getLogger(Shootme.class);
052:
053: static {
054: if (logger.getAllAppenders().equals(
055: NullEnumeration.getInstance())) {
056:
057: logger.addAppender(new ConsoleAppender(new SimpleLayout()));
058:
059: }
060: }
061:
062: private Dialog dialog;
063:
064: private boolean okRecieved;
065:
066: class ApplicationData {
067: protected int ackCount;
068: }
069:
070: public Shootme(ProtocolObjects protocolObjects) {
071: this .protocolObjects = protocolObjects;
072: }
073:
074: public void processRequest(RequestEvent requestEvent) {
075: Request request = requestEvent.getRequest();
076: ServerTransaction serverTransactionId = requestEvent
077: .getServerTransaction();
078:
079: logger.info("\n\nRequest " + request.getMethod()
080: + " received at "
081: + protocolObjects.sipStack.getStackName()
082: + " with server transaction id " + serverTransactionId);
083:
084: if (request.getMethod().equals(Request.INVITE)) {
085: processInvite(requestEvent, serverTransactionId);
086: } else if (request.getMethod().equals(Request.ACK)) {
087: processAck(requestEvent, serverTransactionId);
088: } else if (request.getMethod().equals(Request.BYE)) {
089: processBye(requestEvent, serverTransactionId);
090: }
091:
092: }
093:
094: /**
095: * Process the ACK request. Send the bye and complete the call flow.
096: */
097: public void processAck(RequestEvent requestEvent,
098: ServerTransaction serverTransaction) {
099: SipProvider sipProvider = (SipProvider) requestEvent
100: .getSource();
101: try {
102: logger.info("shootme: got an ACK "
103: + requestEvent.getRequest());
104:
105: int ackCount = ((ApplicationData) dialog
106: .getApplicationData()).ackCount;
107: if (ackCount == 1) {
108: dialog = inviteTid.getDialog();
109: this .sendReInvite(sipProvider);
110:
111: } else
112: ((ApplicationData) dialog.getApplicationData()).ackCount++;
113: } catch (Exception ex) {
114: String s = "Unexpected error";
115: logger.error(s, ex);
116: ReInviteTest.fail(s);
117: }
118: }
119:
120: /**
121: * Process the invite request.
122: */
123: public void processInvite(RequestEvent requestEvent,
124: ServerTransaction serverTransaction) {
125: SipProvider sipProvider = (SipProvider) requestEvent
126: .getSource();
127: Request request = requestEvent.getRequest();
128: logger.info("Got an INVITE " + request);
129: try {
130: logger.info("shootme: got an Invite sending OK");
131: // logger.info("shootme: " + request);
132: Response response = protocolObjects.messageFactory
133: .createResponse(180, request);
134: ToHeader toHeader = (ToHeader) response
135: .getHeader(ToHeader.NAME);
136: toHeader.setTag("4321");
137: Address address = protocolObjects.addressFactory
138: .createAddress("Shootme <sip:" + myAddress + ":"
139: + myPort + ">");
140: ContactHeader contactHeader = protocolObjects.headerFactory
141: .createContactHeader(address);
142: response.addHeader(contactHeader);
143: ServerTransaction st = requestEvent.getServerTransaction();
144:
145: if (st == null) {
146: st = sipProvider.getNewServerTransaction(request);
147: logger.info("Server transaction created!" + request);
148:
149: logger.info("Dialog = " + st.getDialog());
150: if (st.getDialog().getApplicationData() == null) {
151: st.getDialog().setApplicationData(
152: new ApplicationData());
153: }
154: } else {
155: // If Server transaction is not null, then
156: // this is a re-invite.
157: logger.info("This is a RE INVITE ");
158: ReInviteTest.assertSame("Dialog mismatch ", st
159: .getDialog(), this .dialog);
160: }
161:
162: // Thread.sleep(5000);
163: logger.info("got a server tranasaction " + st);
164: byte[] content = request.getRawContent();
165: if (content != null) {
166: logger.info(" content = " + new String(content));
167: ContentTypeHeader contentTypeHeader = protocolObjects.headerFactory
168: .createContentTypeHeader("application", "sdp");
169: logger.info("response = " + response);
170: response.setContent(content, contentTypeHeader);
171: }
172: dialog = st.getDialog();
173: if (dialog != null) {
174: logger.info("Dialog " + dialog);
175: logger.info("Dialog state " + dialog.getState());
176: }
177: st.sendResponse(response);
178: response = protocolObjects.messageFactory.createResponse(
179: 200, request);
180: toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
181: toHeader.setTag("4321");
182: // Application is supposed to set.
183: response.addHeader(contactHeader);
184: st.sendResponse(response);
185: logger
186: .info("TxState after sendResponse = "
187: + st.getState());
188: this .inviteTid = st;
189: } catch (Exception ex) {
190: String s = "unexpected exception";
191:
192: logger.error(s, ex);
193: ReInviteTest.fail(s);
194: }
195: }
196:
197: public void sendReInvite(SipProvider sipProvider) throws Exception {
198: Request inviteRequest = dialog.createRequest(Request.INVITE);
199: ((SipURI) inviteRequest.getRequestURI())
200: .removeParameter("transport");
201: MaxForwardsHeader mf = protocolObjects.headerFactory
202: .createMaxForwardsHeader(10);
203: inviteRequest.addHeader(mf);
204: ((ViaHeader) inviteRequest.getHeader(ViaHeader.NAME))
205: .setTransport(protocolObjects.transport);
206: Address address = protocolObjects.addressFactory
207: .createAddress("Shootme <sip:" + myAddress + ":"
208: + myPort + ">");
209: ContactHeader contactHeader = protocolObjects.headerFactory
210: .createContactHeader(address);
211: inviteRequest.addHeader(contactHeader);
212: ClientTransaction ct = sipProvider
213: .getNewClientTransaction(inviteRequest);
214: dialog.sendRequest(ct);
215: }
216:
217: /**
218: * Process the bye request.
219: */
220: public void processBye(RequestEvent requestEvent,
221: ServerTransaction serverTransactionId) {
222:
223: SipProvider sipProvider = (SipProvider) requestEvent
224: .getSource();
225: Request request = requestEvent.getRequest();
226: try {
227: logger.info("shootme: got a bye sending OK.");
228: Response response = protocolObjects.messageFactory
229: .createResponse(200, request);
230: if (serverTransactionId != null) {
231: serverTransactionId.sendResponse(response);
232: logger.info("Dialog State is "
233: + serverTransactionId.getDialog().getState());
234: } else {
235: logger.info("null server tx.");
236: // sipProvider.sendResponse(response);
237: }
238:
239: } catch (Exception ex) {
240: String s = "Unexpected exception";
241: logger.error(s, ex);
242: ReInviteTest.fail(s);
243:
244: }
245: }
246:
247: public void processResponse(ResponseEvent responseReceivedEvent) {
248: logger.info("Got a response");
249: Response response = (Response) responseReceivedEvent
250: .getResponse();
251: Transaction tid = responseReceivedEvent.getClientTransaction();
252:
253: logger.info("Response received with client transaction id "
254: + tid + ":\n" + response);
255: try {
256: if (response.getStatusCode() == Response.OK
257: && ((CSeqHeader) response
258: .getHeader(CSeqHeader.NAME)).getMethod()
259: .equals(Request.INVITE)) {
260: this .okRecieved = true;
261: ReInviteTest
262: .assertNotNull(
263: "INVITE 200 response should match a transaction",
264: tid);
265: Dialog dialog = tid.getDialog();
266: CSeqHeader cseq = (CSeqHeader) response
267: .getHeader(CSeqHeader.NAME);
268: Request request = dialog.createAck(cseq.getSeqNumber());
269: dialog.sendAck(request);
270: }
271: if (tid != null) {
272: Dialog dialog = tid.getDialog();
273: logger.info("Dalog State = " + dialog.getState());
274: }
275: } catch (Exception ex) {
276:
277: String s = "Unexpected exception";
278:
279: logger.error(s, ex);
280: ReInviteTest.fail(s);
281: }
282:
283: }
284:
285: public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
286: Transaction transaction;
287: if (timeoutEvent.isServerTransaction()) {
288: transaction = timeoutEvent.getServerTransaction();
289: } else {
290: transaction = timeoutEvent.getClientTransaction();
291: }
292: logger.info("state = " + transaction.getState());
293: logger.info("dialog = " + transaction.getDialog());
294: logger.info("dialogState = "
295: + transaction.getDialog().getState());
296: logger.info("Transaction Time out");
297: }
298:
299: public SipProvider createSipProvider() throws Exception {
300: ListeningPoint lp = protocolObjects.sipStack
301: .createListeningPoint(myAddress, myPort,
302: protocolObjects.transport);
303:
304: SipProvider sipProvider = protocolObjects.sipStack
305: .createSipProvider(lp);
306: return sipProvider;
307: }
308:
309: public static void main(String args[]) throws Exception {
310: logger.addAppender(new ConsoleAppender(new SimpleLayout()));
311: ProtocolObjects protocolObjects = new ProtocolObjects(
312: "shootme", "gov.nist", "udp", true);
313:
314: Shootme shootme = new Shootme(protocolObjects);
315: shootme.createSipProvider().addSipListener(shootme);
316:
317: }
318:
319: public void checkState() {
320: ApplicationData data = (ApplicationData) dialog
321: .getApplicationData();
322: ReInviteTest.assertTrue(data.ackCount == 1);
323: ReInviteTest.assertTrue(okRecieved);
324: }
325:
326: /*
327: * (non-Javadoc)
328: *
329: * @see javax.sip.SipListener#processIOException(javax.sip.IOExceptionEvent)
330: */
331: public void processIOException(IOExceptionEvent exceptionEvent) {
332: logger.error("An IO Exception was detected : "
333: + exceptionEvent.getHost());
334:
335: }
336:
337: /*
338: * (non-Javadoc)
339: *
340: * @see javax.sip.SipListener#processTransactionTerminated(javax.sip.TransactionTerminatedEvent)
341: */
342: public void processTransactionTerminated(
343: TransactionTerminatedEvent transactionTerminatedEvent) {
344: logger.info("Tx terminated event ");
345:
346: }
347:
348: /*
349: * (non-Javadoc)
350: *
351: * @see javax.sip.SipListener#processDialogTerminated(javax.sip.DialogTerminatedEvent)
352: */
353: public void processDialogTerminated(
354: DialogTerminatedEvent dialogTerminatedEvent) {
355: logger.info("Dialog terminated event detected ");
356:
357: }
358:
359: }
|