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.MessageFlowHarness;
012: import test.tck.msgflow.callflows.ProtocolObjects;
013:
014: import java.util.*;
015:
016: import junit.framework.TestCase;
017:
018: /**
019: * This class is a UAC template. Shootist is the guy that shoots and shootme is
020: * the guy that gets shot.
021: *
022: * @author M. Ranganathan
023: */
024:
025: public class Shootme extends TestHarness implements SipListener {
026:
027: private ProtocolObjects protocolObjects;
028:
029: private static final String myAddress = "127.0.0.1";
030:
031: public static final int myPort = 5070;
032:
033: protected ServerTransaction inviteTid;
034:
035: private Response okResponse;
036:
037: private Request inviteRequest;
038:
039: private Dialog dialog;
040:
041: private SipProvider sipProvider;
042:
043: private int inviteCount = 0;
044:
045: private int dialogTerminationCount = 0;
046:
047: private int dialogCount;
048:
049: private int byeOkRecieved;
050:
051: private int ackCount;
052:
053: private static Logger logger = Logger.getLogger(Shootme.class);
054:
055: class MyTimerTask extends TimerTask {
056: Shootme shootme;
057:
058: public MyTimerTask(Shootme shootme) {
059: this .shootme = shootme;
060:
061: }
062:
063: public void run() {
064: shootme.sendInviteOK();
065: }
066:
067: }
068:
069: protected static final String usageString = "java "
070: + "examples.shootist.Shootist \n"
071: + ">>>> is your class path set to the root?";
072:
073: public void processRequest(RequestEvent requestEvent) {
074: Request request = requestEvent.getRequest();
075: ServerTransaction serverTransactionId = requestEvent
076: .getServerTransaction();
077:
078: logger.info("\n\nRequest " + request.getMethod()
079: + " received at "
080: + protocolObjects.sipStack.getStackName()
081: + " with server transaction id " + serverTransactionId);
082:
083: if (request.getMethod().equals(Request.INVITE)) {
084: processInvite(requestEvent, serverTransactionId);
085: } else if (request.getMethod().equals(Request.ACK)) {
086: processAck(requestEvent, serverTransactionId);
087: } else {
088: fail("unexpected request recieved");
089: }
090: }
091:
092: public void processResponse(ResponseEvent responseEvent) {
093: if (((CSeqHeader) responseEvent.getResponse().getHeader(
094: CSeqHeader.NAME)).getMethod().equals(Request.BYE))
095: this .byeOkRecieved++;
096: else {
097: fail("unexpected response received");
098: }
099: }
100:
101: /**
102: * Process the ACK request. Send the bye and complete the call flow.
103: */
104: public void processAck(RequestEvent requestEvent,
105: ServerTransaction serverTransaction) {
106: try {
107: this .ackCount++;
108: logger.debug("shootme: got an ACK ");
109: logger.debug("Dialog State = " + dialog.getState()
110: + " sending BYE ");
111: // This check is required because it may be an ACK retransmission
112: // If this is an ACK retransmission, we dont worry about sending BYE
113: // again.
114: if (dialog.getState() == DialogState.CONFIRMED) {
115: Request bye = dialog.createRequest(Request.BYE);
116: ClientTransaction ct = this .sipProvider
117: .getNewClientTransaction(bye);
118: dialog.sendRequest(ct);
119: }
120: } catch (Exception ex) {
121: logger.error("unexpected exception", ex);
122: fail("unexpected exception sending bye");
123: }
124: }
125:
126: /**
127: * Process the invite request.
128: */
129: public void processInvite(RequestEvent requestEvent,
130: ServerTransaction serverTransaction) {
131: SipProvider sipProvider = (SipProvider) requestEvent
132: .getSource();
133: Request request = requestEvent.getRequest();
134: try {
135: this .inviteCount++;
136: logger.info("shootme: got an Invite " + this .inviteCount);
137: assertTrue(request.getHeader(ContactHeader.NAME) != null);
138: Response response = protocolObjects.messageFactory
139: .createResponse(Response.TRYING, request);
140: ToHeader toHeader = (ToHeader) response
141: .getHeader(ToHeader.NAME);
142: /**
143: * We distinguish here after the display header in the Request URI
144: * to manage the different tags
145: */
146: Address address = protocolObjects.addressFactory
147: .createAddress("Shootme <sip:" + myAddress + ":"
148: + myPort + ";transport="
149: + protocolObjects.transport + ">");
150: ServerTransaction st = requestEvent.getServerTransaction();
151:
152: if (st == null) {
153: st = sipProvider.getNewServerTransaction(request);
154: }
155: Dialog dialog = st.getDialog();
156:
157: assertTrue(this .dialog != dialog);
158: this .dialogCount++;
159: this .dialog = dialog;
160:
161: logger.info("Shootme: dialog = " + dialog);
162:
163: st.sendResponse(response);
164: ContactHeader contactHeader = protocolObjects.headerFactory
165: .createContactHeader(address);
166:
167: /**
168: * We distinguish here after the display header in the Request URI
169: * to create a final response
170: */
171: if (((SipURI) (request.getRequestURI()))
172: .getParameter("redirection") == null) {
173: Response moved = protocolObjects.messageFactory
174: .createResponse(Response.MOVED_TEMPORARILY,
175: request);
176: moved.addHeader(contactHeader);
177: toHeader = (ToHeader) moved.getHeader(ToHeader.NAME);
178: toHeader.setTag("4321"); // Application is supposed to set.
179: st.sendResponse(moved);
180: // Check that the stack is assigning the right state to the
181: // dialog.
182: assertTrue("dialog state should be terminated", dialog
183: .getState() == DialogState.TERMINATED);
184:
185: } else {
186: Response ringing = protocolObjects.messageFactory
187: .createResponse(Response.RINGING, request);
188: toHeader = (ToHeader) ringing.getHeader(ToHeader.NAME);
189: toHeader.setTag("5432"); // Application is supposed to set.
190: st.sendResponse(ringing);
191: assertEquals("server tx state should be proceeding", st
192: .getState(), TransactionState.PROCEEDING);
193:
194: this .okResponse = protocolObjects.messageFactory
195: .createResponse(Response.OK, request);
196: toHeader = (ToHeader) okResponse
197: .getHeader(ToHeader.NAME);
198: toHeader.setTag("5432"); // Application is supposed to set.
199: okResponse.addHeader(contactHeader);
200: this .inviteTid = st;
201: // Defer sending the OK to simulate the phone ringing.
202: this .inviteRequest = request;
203:
204: new Timer().schedule(new MyTimerTask(this ), 1000);
205:
206: }
207: } catch (Exception ex) {
208: ex.printStackTrace();
209: fail("Error sending response to INVITE");
210: }
211: }
212:
213: private void sendInviteOK() {
214: try {
215: assertTrue(inviteTid.getState() == TransactionState.PROCEEDING);
216:
217: inviteTid.sendResponse(okResponse);
218: logger.info("Dialog = " + inviteTid.getDialog());
219: logger.info("shootme: Dialog state after response: "
220: + okResponse.getStatusCode() + " "
221: + inviteTid.getDialog().getState());
222:
223: assertEquals("invite tx state should be terminated",
224: inviteTid.getState(), TransactionState.TERMINATED);
225:
226: } catch (SipException ex) {
227: logger.error("unexpected exception", ex);
228: fail("unexpected exception");
229:
230: } catch (InvalidArgumentException ex) {
231: logger.error("unexpceted exception", ex);
232: fail("unexpected exception");
233: }
234: }
235:
236: public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
237: Transaction transaction;
238: if (timeoutEvent.isServerTransaction()) {
239: transaction = timeoutEvent.getServerTransaction();
240: } else {
241: transaction = timeoutEvent.getClientTransaction();
242: }
243: logger.info("state = " + transaction.getState());
244: logger.info("dialog = " + transaction.getDialog());
245: logger.info("dialogState = "
246: + transaction.getDialog().getState());
247: logger.info("Transaction Time out");
248: fail("unexpected timeout occured");
249: }
250:
251: public SipProvider createProvider() throws Exception {
252: ListeningPoint lp = protocolObjects.sipStack
253: .createListeningPoint("127.0.0.1", myPort,
254: protocolObjects.transport);
255: this .sipProvider = protocolObjects.sipStack
256: .createSipProvider(lp);
257: return this .sipProvider;
258: }
259:
260: public Shootme(ProtocolObjects protocolObjects) {
261: this .protocolObjects = protocolObjects;
262: }
263:
264: public void processIOException(IOExceptionEvent exceptionEvent) {
265: logger.info("IOException");
266: fail("unexpected exception");
267:
268: }
269:
270: public void processTransactionTerminated(
271: TransactionTerminatedEvent transactionTerminatedEvent) {
272: logger.info("Transaction terminated event recieved");
273:
274: }
275:
276: public void processDialogTerminated(
277: DialogTerminatedEvent dialogTerminatedEvent) {
278: logger.info("Dialog terminated event recieved dialog = "
279: + dialogTerminatedEvent.getDialog());
280: this .dialogTerminationCount++;
281:
282: }
283:
284: public void checkState() {
285: assertTrue(this .inviteCount == 2 && this .ackCount >= 1
286: && this .byeOkRecieved >= 1);
287:
288: }
289:
290: }
|