001: package test.load.concurrency;
002:
003: import java.util.ArrayList;
004: import java.util.Timer;
005: import java.util.TimerTask;
006: import java.util.concurrent.atomic.AtomicInteger;
007:
008: import javax.sip.ClientTransaction;
009: import javax.sip.Dialog;
010: import javax.sip.DialogState;
011: import javax.sip.DialogTerminatedEvent;
012: import javax.sip.IOExceptionEvent;
013: import javax.sip.ListeningPoint;
014: import javax.sip.RequestEvent;
015: import javax.sip.ResponseEvent;
016: import javax.sip.ServerTransaction;
017: import javax.sip.SipListener;
018: import javax.sip.SipProvider;
019: import javax.sip.SipStack;
020: import javax.sip.Transaction;
021: import javax.sip.TransactionTerminatedEvent;
022: import javax.sip.address.Address;
023: import javax.sip.address.AddressFactory;
024: import javax.sip.address.SipURI;
025: import javax.sip.header.CSeqHeader;
026: import javax.sip.header.CallIdHeader;
027: import javax.sip.header.ContactHeader;
028: import javax.sip.header.FromHeader;
029: import javax.sip.header.Header;
030: import javax.sip.header.HeaderFactory;
031: import javax.sip.header.MaxForwardsHeader;
032: import javax.sip.header.RouteHeader;
033: import javax.sip.header.ToHeader;
034: import javax.sip.header.ViaHeader;
035: import javax.sip.message.MessageFactory;
036: import javax.sip.message.Request;
037: import javax.sip.message.Response;
038: import junit.framework.TestCase;
039:
040: /**
041: * This class is a UAC template.
042: *
043: * @author M. Ranganathan
044: */
045:
046: public class Shootist extends TestCase implements SipListener {
047:
048: static AddressFactory addressFactory;
049:
050: static MessageFactory messageFactory;
051:
052: static HeaderFactory headerFactory;
053:
054: static SipStack sipStack;
055:
056: ContactHeader contactHeader;
057:
058: SipProvider[] sipProviders;
059:
060: static String transport;
061:
062: // Starts at -2000, a ramp-up period is required for performance testing.
063: int byeCount = -2000;
064:
065: int ackCount;
066:
067: long start;
068:
069: static int MAXCONCURRENTINVITE = 200;
070: static int NDIALOGS = 1000;
071: static int NBPROVIDERS = 1;
072:
073: AtomicInteger nbConcurrentInvite = new AtomicInteger(0);
074:
075: // Keeps track of successful dialog completion.
076: private static Timer timer;
077:
078: static {
079: timer = new Timer();
080: }
081:
082: class TTask extends TimerTask {
083: Dialog dialog;
084:
085: public TTask(Dialog dialog) {
086: this .dialog = dialog;
087: }
088:
089: public void run() {
090: if (dialog.getState() != DialogState.TERMINATED) {
091: System.out.println("BYE not received for "
092: + this .dialog);
093: System.out.println("State " + this .dialog.getState());
094: System.out.println("dialogId "
095: + this .dialog.getDialogId());
096: Appdata appData = (Appdata) dialog.getApplicationData();
097:
098: System.out.println("ackCount " + appData.ackCount);
099: ((gov.nist.javax.sip.stack.SIPDialog) dialog)
100: .printDebugInfo();
101: System.exit(0);
102: } else {
103: this .dialog = null;
104: }
105: }
106: }
107:
108: class Appdata {
109:
110: protected TTask ttask;
111:
112: protected long startTime;
113:
114: protected long endTime;
115:
116: protected int ackCount;
117:
118: Appdata(Dialog dialog) {
119: ttask = new TTask(dialog);
120: timer.schedule(ttask, 20 * 1000 * NDIALOGS / 100);
121: startTime = System.currentTimeMillis();
122: }
123:
124: public void cancelTimer() {
125: this .ttask.dialog = null;
126: this .ttask.cancel();
127: endTime = System.currentTimeMillis();
128: }
129: }
130:
131: class TestTimer extends TimerTask {
132:
133: private Shootist shootist;
134:
135: public TestTimer(Shootist shootist) {
136: this .shootist = shootist;
137: }
138:
139: public void run() {
140: assertTrue("Missed BYE " + shootist.byeCount,
141: shootist.byeCount >= NDIALOGS);
142: ProtocolObjects.destroy();
143: System.exit(0);
144: }
145:
146: }
147:
148: protected static final String usageString = "java "
149: + "examples.shootist.Shootist \n"
150: + ">>>> is your class path set to the root?";
151:
152: private static void usage() {
153: System.out.println(usageString);
154: System.exit(0);
155:
156: }
157:
158: public void processRequest(RequestEvent requestReceivedEvent) {
159: Request request = requestReceivedEvent.getRequest();
160: ServerTransaction serverTransactionId = requestReceivedEvent
161: .getServerTransaction();
162:
163: // We are the UAC so the only request we get is the BYE.
164: if (request.getMethod().equals(Request.BYE))
165: processBye(request, serverTransactionId);
166:
167: }
168:
169: public void processBye(Request request,
170: ServerTransaction serverTransactionId) {
171: try {
172: if (serverTransactionId == null) {
173: return;
174: }
175: Dialog dialog = serverTransactionId.getDialog();
176: Response response = messageFactory.createResponse(200,
177: request);
178: serverTransactionId.sendResponse(response);
179:
180: Appdata appdata = (Appdata) dialog.getApplicationData();
181: appdata.cancelTimer();
182: int ndialogs = nbConcurrentInvite.decrementAndGet();
183: // System.out.println(nbConcurrentInvite);
184: if (ndialogs > MAXCONCURRENTINVITE)
185: System.out.println("Concurrent invites = " + ndialogs);
186: synchronized (this ) {
187: if (ndialogs < MAXCONCURRENTINVITE / 2)
188: this .notify();
189: }
190: // Synchronization necessary for Multiprocessor machine
191: // noted by Matt Porter.
192: this .byeCount++;
193: // System.out.println("bye count = " + byeCount);
194: if (byeCount == NDIALOGS) {
195: long current = System.currentTimeMillis();
196: float sec = (float) (current - start) / 1000f;
197: System.out.println("Thrupt = "
198: + (float) (NDIALOGS / sec));
199: }
200:
201: // dialog.delete();
202:
203: } catch (Exception ex) {
204: ex.printStackTrace();
205: System.exit(0);
206:
207: }
208: }
209:
210: public void processResponse(ResponseEvent responseReceivedEvent) {
211: Response response = (Response) responseReceivedEvent
212: .getResponse();
213: Transaction tid = responseReceivedEvent.getClientTransaction();
214:
215: if (tid == null) {
216: return;
217: }
218:
219: try {
220: if (response.getStatusCode() == Response.OK
221: && ((CSeqHeader) response
222: .getHeader(CSeqHeader.NAME)).getMethod()
223: .equals(Request.INVITE)) {
224: // Request cancel = inviteTid.createCancel();
225: // ClientTransaction ct =
226: // sipProvider.getNewClientTransaction(cancel);
227: // ct.sendRequest();
228: Dialog dialog = tid.getDialog();
229: if (dialog.getState() != DialogState.TERMINATED) {
230: CSeqHeader cseq = (CSeqHeader) response
231: .getHeader(CSeqHeader.NAME);
232: Request ackRequest = dialog.createAck(cseq
233: .getSeqNumber());
234: dialog.sendAck(ackRequest);
235:
236: Appdata appData = (Appdata) dialog
237: .getApplicationData();
238: if (appData != null)
239: appData.ackCount++;
240: }
241:
242: }
243: } catch (Exception ex) {
244: Dialog dialog = tid.getDialog();
245: System.out.println("Dialog state is " + dialog.getState());
246: ex.printStackTrace();
247: System.exit(0);
248: }
249:
250: }
251:
252: public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
253:
254: System.out.println("Transaction Time out");
255: Request request = null;
256: Transaction transaction = null;
257: if (timeoutEvent.isServerTransaction()) {
258: transaction = timeoutEvent.getServerTransaction();
259: request = ((ServerTransaction) transaction).getRequest();
260: } else {
261: transaction = timeoutEvent.getClientTransaction();
262: request = ((ClientTransaction) transaction).getRequest();
263: }
264: System.out.println("state = " + transaction.getState());
265: System.out.println("dialog = " + transaction.getDialog());
266: System.out.println("dialogState = "
267: + transaction.getDialog().getState());
268: System.out.println("Transaction Time out");
269: System.out.println("Transaction " + transaction);
270: System.out.println("request " + request);
271:
272: fail("Unexpected event: TimeoutEvent ");
273:
274: }
275:
276: public void sendInvite() {
277: try {
278:
279: String fromName = "BigGuy";
280: String fromSipAddress = "here.com";
281: String fromDisplayName = "The Master Blaster";
282:
283: String toSipAddress = "there.com";
284: String toUser = "LittleGuy";
285: String toDisplayName = "The Little Blister";
286:
287: // create >From Header
288: SipURI fromAddress = addressFactory.createSipURI(fromName,
289: fromSipAddress);
290:
291: Address fromNameAddress = addressFactory
292: .createAddress(fromAddress);
293: fromNameAddress.setDisplayName(fromDisplayName);
294:
295: String tag = new Integer((int) (Math.random() * 10000))
296: .toString();
297: FromHeader fromHeader = headerFactory.createFromHeader(
298: fromNameAddress, tag);
299:
300: // create To Header
301: SipURI toAddress = addressFactory.createSipURI(toUser,
302: toSipAddress);
303: Address toNameAddress = addressFactory
304: .createAddress(toAddress);
305: toNameAddress.setDisplayName(toDisplayName);
306: ToHeader toHeader = headerFactory.createToHeader(
307: toNameAddress, null);
308:
309: // create Request URI
310: SipURI requestURI = addressFactory.createSipURI(toUser,
311: toSipAddress);
312:
313: // Create ViaHeaders
314:
315: ArrayList viaHeaders = new ArrayList();
316: SipProvider sipProvider = getNextProvider();
317: int port = sipProvider.getListeningPoint(transport)
318: .getPort();
319: ViaHeader viaHeader = headerFactory.createViaHeader(
320: sipProvider.getListeningPoint(transport)
321: .getIPAddress(), port, transport, null);
322:
323: // add via headers
324: viaHeaders.add(viaHeader);
325:
326: // Create a new CallId header
327: CallIdHeader callIdHeader = sipProvider.getNewCallId();
328:
329: // Create a new Cseq header
330: CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L,
331: Request.INVITE);
332:
333: // Create a new MaxForwardsHeader
334: MaxForwardsHeader maxForwards = headerFactory
335: .createMaxForwardsHeader(70);
336:
337: // Create the request.
338: Request request = messageFactory.createRequest(requestURI,
339: Request.INVITE, callIdHeader, cSeqHeader,
340: fromHeader, toHeader, viaHeaders, maxForwards);
341: // Create contact headers
342: String host = sipProvider.getListeningPoint(transport)
343: .getIPAddress();
344:
345: // Create the contact name address.
346: SipURI contactURI = addressFactory.createSipURI(fromName,
347: host);
348: contactURI.setPort(port);
349: contactURI.setTransportParam(transport);
350:
351: Address contactAddress = addressFactory
352: .createAddress(contactURI);
353:
354: // Add the contact address.
355: contactAddress.setDisplayName(fromName);
356:
357: contactHeader = headerFactory
358: .createContactHeader(contactAddress);
359: request.addHeader(contactHeader);
360:
361: // Add the extension header.
362: Header extensionHeader = headerFactory.createHeader(
363: "My-Header", "my header value");
364: request.addHeader(extensionHeader);
365:
366: Header callInfoHeader = headerFactory.createHeader(
367: "Call-Info", "<http://www.antd.nist.gov>");
368: request.addHeader(callInfoHeader);
369:
370: SipURI myUri = addressFactory.createSipURI(null, host);
371: myUri.setLrParam();
372: myUri.setTransportParam(transport);
373: myUri.setPort(5070);
374: Address address = addressFactory.createAddress(null, myUri);
375: RouteHeader routeHeader = headerFactory
376: .createRouteHeader(address);
377: request.setHeader(routeHeader);
378:
379: // Create the client transaction.
380: ClientTransaction inviteTid = sipProvider
381: .getNewClientTransaction(request);
382:
383: Dialog dialog = inviteTid.getDialog();
384:
385: // Set a pointer to our application data
386: Appdata appdata = new Appdata(dialog);
387: dialog.setApplicationData(appdata);
388: // send the request out.
389: inviteTid.sendRequest();
390:
391: nbConcurrentInvite.incrementAndGet();
392: // System.out.println(nbConcurrentInvite);
393:
394: } catch (Exception ex) {
395: System.out.println(ex.getMessage());
396: ex.printStackTrace();
397: usage();
398: }
399: }
400:
401: int currentProvider = 0;
402:
403: private SipProvider getNextProvider() {
404: synchronized (this ) {
405: currentProvider++;
406: if (currentProvider >= NBPROVIDERS) {
407: currentProvider = 0;
408: }
409: return sipProviders[currentProvider];
410: }
411: }
412:
413: public void createProvider(SipListener listener) throws Exception {
414: sipProviders = new SipProvider[NBPROVIDERS];
415: for (int i = 0; i < NBPROVIDERS; i++) {
416: ListeningPoint listeningPoint = sipStack
417: .createListeningPoint("127.0.0.1", 15060 + i,
418: transport);
419: sipProviders[i] = sipStack
420: .createSipProvider(listeningPoint);
421: sipProviders[i].addSipListener(listener);
422: }
423: }
424:
425: public void processIOException(IOExceptionEvent exceptionEvent) {
426: System.out
427: .println("IOException occured while retransmitting requests:"
428: + exceptionEvent);
429: }
430:
431: public void processTransactionTerminated(
432: TransactionTerminatedEvent transactionTerminatedEvent) {
433: // System.out.println("Transaction Terminated event: " +
434: // transactionTerminatedEvent);
435: }
436:
437: public void processDialogTerminated(
438: DialogTerminatedEvent dialogTerminatedEvent) {
439: // System.out.println("Dialog Terminated event: " +
440: // dialogTerminatedEvent);
441: }
442:
443: public Shootist() {
444: TimerTask testTimer = new TestTimer(this );
445: Shootist.timer.schedule(testTimer, 20000 * NDIALOGS / 100);
446:
447: }
448:
449: public static int getNdialogs() {
450: return NDIALOGS;
451: }
452:
453: public static void main(String args[]) throws Exception {
454: ProtocolObjects.init("shootist", true);
455: NDIALOGS = Integer.parseInt(args[0]);
456: Shootist.addressFactory = ProtocolObjects.addressFactory;
457: Shootist.messageFactory = ProtocolObjects.messageFactory;
458: Shootist.headerFactory = ProtocolObjects.headerFactory;
459: Shootist.sipStack = ProtocolObjects.sipStack;
460: Shootist.transport = ProtocolObjects.transport;
461: final Shootist shootist = new Shootist();
462: shootist.createProvider(shootist);
463:
464: shootist.start = System.currentTimeMillis();
465: while (shootist.byeCount < NDIALOGS) {
466:
467: while (shootist.nbConcurrentInvite.intValue() >= MAXCONCURRENTINVITE) {
468: System.out
469: .println("Waiting for max invite count to go down!");
470: synchronized (shootist) {
471: try {
472: shootist.wait();
473: } catch (Exception ex) {
474: }
475: }
476: }
477:
478: if (shootist.byeCount == 0) {
479: shootist.start = System.currentTimeMillis();
480: }
481:
482: if (transport.equalsIgnoreCase("udp")) {
483: try {
484: Thread.sleep(5);
485: } catch (InterruptedException e) {
486: }
487: }
488:
489: shootist.sendInvite();
490: }
491: }
492: }
|