PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/jain-sip-ha/jboss-5/src/test/java/org/mobicents/ha/javax/sip/B2BUAEarlyDialogRecoveryOn1xxTest.java

http://mobicents.googlecode.com/
Java | 1654 lines | 1142 code | 241 blank | 271 comment | 113 complexity | 676a8cc10b749149eb8f77f75ecd3808 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.mobicents.ha.javax.sip;
  23. import gov.nist.javax.sip.stack.SIPDialog;
  24. import java.io.ByteArrayInputStream;
  25. import java.io.ByteArrayOutputStream;
  26. import java.io.IOException;
  27. import java.io.ObjectInputStream;
  28. import java.io.ObjectOutputStream;
  29. import java.text.ParseException;
  30. import java.util.ArrayList;
  31. import java.util.Collection;
  32. import java.util.Iterator;
  33. import java.util.Properties;
  34. import java.util.Timer;
  35. import java.util.TimerTask;
  36. import java.util.logging.FileHandler;
  37. import java.util.logging.Handler;
  38. import java.util.logging.Level;
  39. import java.util.logging.Logger;
  40. import java.util.logging.SimpleFormatter;
  41. import javax.sip.ClientTransaction;
  42. import javax.sip.Dialog;
  43. import javax.sip.DialogState;
  44. import javax.sip.DialogTerminatedEvent;
  45. import javax.sip.IOExceptionEvent;
  46. import javax.sip.InvalidArgumentException;
  47. import javax.sip.ListeningPoint;
  48. import javax.sip.PeerUnavailableException;
  49. import javax.sip.RequestEvent;
  50. import javax.sip.ResponseEvent;
  51. import javax.sip.ServerTransaction;
  52. import javax.sip.SipException;
  53. import javax.sip.SipFactory;
  54. import javax.sip.SipListener;
  55. import javax.sip.SipProvider;
  56. import javax.sip.SipStack;
  57. import javax.sip.Transaction;
  58. import javax.sip.TransactionState;
  59. import javax.sip.TransactionTerminatedEvent;
  60. import javax.sip.address.Address;
  61. import javax.sip.address.AddressFactory;
  62. import javax.sip.address.SipURI;
  63. import javax.sip.header.CSeqHeader;
  64. import javax.sip.header.CallIdHeader;
  65. import javax.sip.header.ContactHeader;
  66. import javax.sip.header.ContentTypeHeader;
  67. import javax.sip.header.EventHeader;
  68. import javax.sip.header.ExpiresHeader;
  69. import javax.sip.header.FromHeader;
  70. import javax.sip.header.Header;
  71. import javax.sip.header.HeaderFactory;
  72. import javax.sip.header.MaxForwardsHeader;
  73. import javax.sip.header.SubscriptionStateHeader;
  74. import javax.sip.header.ToHeader;
  75. import javax.sip.header.ViaHeader;
  76. import javax.sip.message.MessageFactory;
  77. import javax.sip.message.Request;
  78. import javax.sip.message.Response;
  79. import junit.framework.TestCase;
  80. import org.mobicents.tools.sip.balancer.BalancerRunner;
  81. /**
  82. * This test aims to test Mobicents Jain Sip Early Dialog failover recovery.
  83. *
  84. * @author <A HREF="mailto:jean.deruelle@gmail.com">Jean Deruelle</A>
  85. *
  86. */
  87. public class B2BUAEarlyDialogRecoveryOn1xxTest extends TestCase {
  88. public static final String IP_ADDRESS = "192.168.0.10";
  89. public static final int BALANCER_PORT = 5060;
  90. private static AddressFactory addressFactory;
  91. private static MessageFactory messageFactory;
  92. private static HeaderFactory headerFactory;
  93. Shootist shootist;
  94. Shootme shootme;
  95. SimpleB2BUA b2buaNode1;
  96. SimpleB2BUA b2buaNode2;
  97. BalancerRunner balancer;
  98. boolean stopNodeOnReinvite = false;
  99. class Shootme implements SipListener {
  100. private SipStack sipStack;
  101. private static final String myAddress = IP_ADDRESS;
  102. private String stackName;
  103. public int myPort = 5090;
  104. protected ServerTransaction inviteTid;
  105. private Response okResponse;
  106. private Request inviteRequest;
  107. private Dialog dialog;
  108. public boolean callerSendsBye = true;
  109. private SipProvider sipProvider;
  110. private boolean byeTaskRunning;
  111. private boolean secondReinviteSent;
  112. private boolean firstReinviteSent;
  113. private boolean firstTxComplete;
  114. private boolean firstReInviteComplete;
  115. private boolean secondReInviteComplete;
  116. private boolean byeReceived;
  117. private boolean subscribeTxComplete;
  118. private boolean notifyTxComplete;
  119. public Shootme(String stackName, int myPort, boolean callerSendsBye) {
  120. this.stackName = stackName;
  121. this.myPort = myPort;
  122. this.callerSendsBye = callerSendsBye;
  123. System.setProperty("jgroups.bind_addr", IP_ADDRESS);
  124. System.setProperty("java.net.preferIPv4Stack", "true");
  125. }
  126. class ByeTask extends TimerTask {
  127. Dialog dialog;
  128. public ByeTask(Dialog dialog) {
  129. this.dialog = dialog;
  130. }
  131. public void run () {
  132. try {
  133. Request byeRequest = this.dialog.createRequest(Request.BYE);
  134. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  135. dialog.sendRequest(ct);
  136. } catch (Exception ex) {
  137. ex.printStackTrace();
  138. fail("Unexpected exception ");
  139. }
  140. }
  141. }
  142. class MyTimerTask extends TimerTask {
  143. Shootme shootme;
  144. public MyTimerTask(Shootme shootme) {
  145. this.shootme = shootme;
  146. }
  147. public void run() {
  148. shootme.sendInviteOK();
  149. }
  150. }
  151. protected static final String usageString = "java "
  152. + "examples.shootist.Shootist \n"
  153. + ">>>> is your class path set to the root?";
  154. private static final long TIMEOUT = 10000;
  155. public void processRequest(RequestEvent requestEvent) {
  156. Request request = requestEvent.getRequest();
  157. ServerTransaction serverTransactionId = requestEvent
  158. .getServerTransaction();
  159. System.out.println("\n\nRequest " + request.getMethod()
  160. + " received at " + sipStack.getStackName()
  161. + " with server transaction id " + serverTransactionId);
  162. if (request.getMethod().equals(Request.INVITE)) {
  163. processInvite(requestEvent, serverTransactionId);
  164. } else if (request.getMethod().equals(Request.ACK)) {
  165. processAck(requestEvent, serverTransactionId);
  166. } else if (request.getMethod().equals(Request.BYE)) {
  167. processBye(requestEvent, serverTransactionId);
  168. } else if (request.getMethod().equals(Request.SUBSCRIBE)) {
  169. processSubscribe(requestEvent, serverTransactionId);
  170. } else if (request.getMethod().equals(Request.CANCEL)) {
  171. processCancel(requestEvent, serverTransactionId);
  172. } else {
  173. try {
  174. serverTransactionId.sendResponse( messageFactory.createResponse( 202, request ) );
  175. // send one back
  176. SipProvider prov = (SipProvider) requestEvent.getSource();
  177. Request refer = requestEvent.getDialog().createRequest("REFER");
  178. requestEvent.getDialog().sendRequest( prov.getNewClientTransaction(refer) );
  179. } catch (SipException e) {
  180. // TODO Auto-generated catch block
  181. e.printStackTrace();
  182. } catch (InvalidArgumentException e) {
  183. // TODO Auto-generated catch block
  184. e.printStackTrace();
  185. } catch (ParseException e) {
  186. // TODO Auto-generated catch block
  187. e.printStackTrace();
  188. }
  189. }
  190. }
  191. public void processResponse(ResponseEvent responseEvent) {
  192. Dialog dialog = responseEvent.getDialog();
  193. CSeqHeader cSeqHeader = (CSeqHeader)responseEvent.getResponse().getHeader(CSeqHeader.NAME);
  194. try {
  195. if(stopNodeOnReinvite && responseEvent.getResponse().getStatusCode() == Response.RINGING) {
  196. // stop the sip stack w/o stopping the cache
  197. b2buaNode2.stopPingBalancer();
  198. b2buaNode2.stop(false);
  199. }
  200. if(responseEvent.getResponse().getStatusCode() >= 200 && cSeqHeader.getMethod().equalsIgnoreCase(Request.INVITE)) {
  201. Request ackRequest = dialog.createAck(cSeqHeader.getSeqNumber());
  202. int port = 5080;
  203. if(firstReinviteSent) {
  204. port = 5081;
  205. firstReinviteSent = false;
  206. firstReInviteComplete = true;
  207. }
  208. if(secondReinviteSent) {
  209. secondReInviteComplete = true;
  210. }
  211. System.out.println("Sending ACK");
  212. ((SipURI)ackRequest.getRequestURI()).setPort(port);
  213. dialog.sendAck(ackRequest);
  214. // if(!secondReinviteSent) {
  215. // Thread.sleep(2000);
  216. // Request request = dialog.createRequest("INVITE");
  217. // ((SipURI)request.getRequestURI()).setPort(5080);
  218. // final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  219. // dialog.sendRequest(ct);
  220. // secondReinviteSent = true;
  221. // }
  222. } else if(responseEvent.getResponse().getStatusCode() >= 200 && cSeqHeader.getMethod().equalsIgnoreCase(Request.NOTIFY)) {
  223. notifyTxComplete = true;
  224. Thread.sleep(5000);
  225. Request request = dialog.createRequest("INVITE");
  226. ((SipURI)request.getRequestURI()).setPort(5081);
  227. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  228. firstReinviteSent = true;
  229. dialog.sendRequest(ct);
  230. }
  231. } catch (SipException e) {
  232. // TODO Auto-generated catch block
  233. e.printStackTrace();
  234. } catch (InvalidArgumentException e) {
  235. // TODO Auto-generated catch block
  236. e.printStackTrace();
  237. } catch (InterruptedException e) {
  238. // TODO Auto-generated catch block
  239. e.printStackTrace();
  240. }
  241. }
  242. /**
  243. * Process the ACK request. Send the bye and complete the call flow.
  244. */
  245. public void processAck(RequestEvent requestEvent,
  246. ServerTransaction serverTransaction) {
  247. try {
  248. Dialog dialog = serverTransaction.getDialog();
  249. System.out.println("shootme: got an ACK! ");
  250. System.out.println("Dialog State = " + dialog.getState());
  251. firstTxComplete = true;
  252. // used in basic reinvite
  253. if(!firstReinviteSent && !((FromHeader)requestEvent.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  254. Thread.sleep(5000);
  255. Request request = dialog.createRequest("INVITE");
  256. ((SipURI)request.getRequestURI()).setPort(5081);
  257. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  258. firstReinviteSent = true;
  259. dialog.sendRequest(ct);
  260. }
  261. } catch (Exception ex) {
  262. ex.printStackTrace();
  263. }
  264. }
  265. /**
  266. * Process the invite request.
  267. */
  268. public void processInvite(RequestEvent requestEvent,
  269. ServerTransaction serverTransaction) {
  270. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  271. Request request = requestEvent.getRequest();
  272. try {
  273. System.out.println("shootme: got an Invite sending Trying");
  274. // System.out.println("shootme: " + request);
  275. Response response = messageFactory.createResponse(Response.RINGING,
  276. request);
  277. ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
  278. toHeader.setTag("4321"); // Application is supposed to set.
  279. ServerTransaction st = requestEvent.getServerTransaction();
  280. if (st == null) {
  281. st = sipProvider.getNewServerTransaction(request);
  282. }
  283. dialog = st.getDialog();
  284. st.sendResponse(response);
  285. Thread.sleep(3000);
  286. this.okResponse = messageFactory.createResponse(Response.OK,
  287. request);
  288. Address address = addressFactory.createAddress("Shootme <sip:"
  289. + myAddress + ":" + myPort + ">");
  290. ContactHeader contactHeader = headerFactory
  291. .createContactHeader(address);
  292. response.addHeader(contactHeader);
  293. toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME);
  294. toHeader.setTag("4321"); // Application is supposed to set.
  295. okResponse.addHeader(contactHeader);
  296. this.inviteTid = st;
  297. // Defer sending the OK to simulate the phone ringing.
  298. // Answered in 1 second ( this guy is fast at taking calls)
  299. this.inviteRequest = request;
  300. sendInviteOK();
  301. } catch (Exception ex) {
  302. ex.printStackTrace();
  303. System.exit(0);
  304. }
  305. }
  306. private void sendInviteOK() {
  307. try {
  308. if (inviteTid.getState() != TransactionState.COMPLETED) {
  309. System.out.println("shootme: Dialog state before 200: "
  310. + inviteTid.getDialog().getState());
  311. inviteTid.sendResponse(okResponse);
  312. System.out.println("shootme: Dialog state after 200: "
  313. + inviteTid.getDialog().getState());
  314. }
  315. } catch (SipException ex) {
  316. ex.printStackTrace();
  317. } catch (InvalidArgumentException ex) {
  318. ex.printStackTrace();
  319. }
  320. }
  321. /**
  322. * Process the bye request.
  323. */
  324. public void processBye(RequestEvent requestEvent,
  325. ServerTransaction serverTransactionId) {
  326. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  327. Request request = requestEvent.getRequest();
  328. Dialog dialog = requestEvent.getDialog();
  329. System.out.println("local party = " + dialog.getLocalParty());
  330. try {
  331. System.out.println("shootme: got a bye sending OK.");
  332. Response response = messageFactory.createResponse(200, request);
  333. serverTransactionId.sendResponse(response);
  334. System.out.println("Dialog State is "
  335. + serverTransactionId.getDialog().getState());
  336. byeReceived = true;
  337. } catch (Exception ex) {
  338. ex.printStackTrace();
  339. System.exit(0);
  340. }
  341. }
  342. /**
  343. * Process the bye request.
  344. */
  345. public void processSubscribe(RequestEvent requestEvent,
  346. ServerTransaction serverTransactionId) {
  347. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  348. Request request = requestEvent.getRequest();
  349. Dialog dialog = requestEvent.getDialog();
  350. try {
  351. ServerTransaction st = requestEvent.getServerTransaction();
  352. if (st == null) {
  353. st = sipProvider.getNewServerTransaction(request);
  354. }
  355. System.out.println("shootme: got a subscribe sending OK.");
  356. Response response = messageFactory.createResponse(200, request);
  357. response.addHeader(headerFactory.createHeader(ExpiresHeader.NAME, "3600"));
  358. st.sendResponse(response);
  359. System.out.println("Dialog State is "
  360. + st.getDialog().getState());
  361. subscribeTxComplete = true;
  362. Thread.sleep(5000);
  363. Request notify = st.getDialog().createRequest(Request.NOTIFY);
  364. notify.addHeader(headerFactory.createHeader(SubscriptionStateHeader.NAME, SubscriptionStateHeader.ACTIVE));
  365. notify.addHeader(headerFactory.createHeader(EventHeader.NAME, "presence"));
  366. ((SipURI)notify.getRequestURI()).setUser(null);
  367. ((SipURI)notify.getRequestURI()).setHost(IP_ADDRESS);
  368. ((SipURI)notify.getRequestURI()).setPort(5080);
  369. st.getDialog().sendRequest(sipProvider.getNewClientTransaction(notify));
  370. } catch (Exception ex) {
  371. ex.printStackTrace();
  372. System.exit(0);
  373. }
  374. }
  375. public void processCancel(RequestEvent requestEvent,
  376. ServerTransaction serverTransactionId) {
  377. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  378. Request request = requestEvent.getRequest();
  379. try {
  380. System.out.println("shootme: got a cancel.");
  381. if (serverTransactionId == null) {
  382. System.out.println("shootme: null tid.");
  383. return;
  384. }
  385. Response response = messageFactory.createResponse(200, request);
  386. serverTransactionId.sendResponse(response);
  387. if (dialog.getState() != DialogState.CONFIRMED) {
  388. response = messageFactory.createResponse(
  389. Response.REQUEST_TERMINATED, inviteRequest);
  390. inviteTid.sendResponse(response);
  391. }
  392. } catch (Exception ex) {
  393. ex.printStackTrace();
  394. System.exit(0);
  395. }
  396. }
  397. public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
  398. Transaction transaction;
  399. if (timeoutEvent.isServerTransaction()) {
  400. transaction = timeoutEvent.getServerTransaction();
  401. } else {
  402. transaction = timeoutEvent.getClientTransaction();
  403. }
  404. System.out.println("state = " + transaction.getState());
  405. System.out.println("dialog = " + transaction.getDialog());
  406. System.out.println("dialogState = "
  407. + transaction.getDialog().getState());
  408. System.out.println("Transaction Time out");
  409. }
  410. public void init() {
  411. SipFactory sipFactory = null;
  412. sipStack = null;
  413. sipFactory = SipFactory.getInstance();
  414. sipFactory.setPathName("gov.nist");
  415. Properties properties = new Properties();
  416. properties.setProperty("javax.sip.STACK_NAME", stackName);
  417. String transport = "udp";
  418. String peerHostPort = IP_ADDRESS + ":" + BALANCER_PORT;
  419. properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
  420. + transport);
  421. // You need 16 for logging traces. 32 for debug + traces.
  422. // Your code will limp at 32 but it is best for debugging.
  423. properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
  424. properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "logs/" +
  425. stackName + "debug.txt");
  426. properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "logs/" +
  427. stackName + "log.xml");
  428. try {
  429. // Create SipStack object
  430. sipStack = sipFactory.createSipStack(properties);
  431. System.out.println("sipStack = " + sipStack);
  432. } catch (PeerUnavailableException e) {
  433. // could not find
  434. // gov.nist.jain.protocol.ip.sip.SipStackImpl
  435. // in the classpath
  436. e.printStackTrace();
  437. System.err.println(e.getMessage());
  438. if (e.getCause() != null)
  439. e.getCause().printStackTrace();
  440. System.exit(0);
  441. }
  442. try {
  443. headerFactory = sipFactory.createHeaderFactory();
  444. addressFactory = sipFactory.createAddressFactory();
  445. messageFactory = sipFactory.createMessageFactory();
  446. ListeningPoint lp = sipStack.createListeningPoint(myAddress,
  447. myPort, ListeningPoint.UDP);
  448. Shootme listener = this;
  449. sipProvider = sipStack.createSipProvider(lp);
  450. System.out.println("udp provider " + sipProvider);
  451. sipProvider.addSipListener(listener);
  452. // if(dialogs != null) {
  453. // Collection<Dialog> serializedDialogs = simulateDialogSerialization(dialogs);
  454. // for (Dialog dialog : serializedDialogs) {
  455. // ((SIPDialog)dialog).setSipProvider((SipProviderImpl)sipProvider);
  456. // ((SipStackImpl)sipStack).putDialog((SIPDialog)dialog);
  457. // }
  458. // this.dialog = (SIPDialog)serializedDialogs.iterator().next();
  459. // }
  460. sipStack.start();
  461. if(!callerSendsBye && this.dialog != null) {
  462. try {
  463. Request byeRequest = this.dialog.createRequest(Request.BYE);
  464. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  465. System.out.println("sending BYE " + byeRequest);
  466. dialog.sendRequest(ct);
  467. } catch (Exception ex) {
  468. ex.printStackTrace();
  469. fail("Unexpected exception ");
  470. }
  471. }
  472. } catch (Exception ex) {
  473. System.out.println(ex.getMessage());
  474. ex.printStackTrace();
  475. fail("Unexpected exception");
  476. }
  477. }
  478. private Collection<Dialog> simulateDialogSerialization(
  479. Collection<Dialog> dialogs) {
  480. Collection<Dialog> serializedDialogs = new ArrayList<Dialog>();
  481. for (Dialog dialog : dialogs) {
  482. try{
  483. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  484. ObjectOutputStream out = new ObjectOutputStream(baos);
  485. out.writeObject(dialog);
  486. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  487. ObjectInputStream in =new ObjectInputStream(bais);
  488. SIPDialog serializedDialog = (SIPDialog)in.readObject();
  489. serializedDialogs.add(serializedDialog);
  490. out.close();
  491. in.close();
  492. baos.close();
  493. bais.close();
  494. } catch (IOException e) {
  495. e.printStackTrace();
  496. } catch (ClassNotFoundException e) {
  497. e.printStackTrace();
  498. }
  499. }
  500. return serializedDialogs;
  501. }
  502. public void processIOException(IOExceptionEvent exceptionEvent) {
  503. System.out.println("IOException");
  504. }
  505. public void processTransactionTerminated(
  506. TransactionTerminatedEvent transactionTerminatedEvent) {
  507. if (transactionTerminatedEvent.isServerTransaction())
  508. System.out.println("Transaction terminated event recieved"
  509. + transactionTerminatedEvent.getServerTransaction());
  510. else
  511. System.out.println("Transaction terminated "
  512. + transactionTerminatedEvent.getClientTransaction());
  513. }
  514. public void processDialogTerminated(
  515. DialogTerminatedEvent dialogTerminatedEvent) {
  516. System.out.println("Dialog terminated event recieved");
  517. Dialog d = dialogTerminatedEvent.getDialog();
  518. System.out.println("Local Party = " + d.getLocalParty());
  519. }
  520. public void stop() {
  521. stopSipStack(sipStack, this);
  522. }
  523. public void checkState(boolean reinviteSubsNotify) {
  524. if(reinviteSubsNotify) {
  525. if(firstTxComplete && subscribeTxComplete && notifyTxComplete && firstReInviteComplete && secondReInviteComplete && byeReceived) {
  526. System.out.println("shootme state OK " );
  527. } else {
  528. fail("firstTxComplete " + firstTxComplete + " && subscribeTxComplete " + subscribeTxComplete + " && notifyComplete " + notifyTxComplete + " && firstReInviteComplete " + firstReInviteComplete + "&& secondReInviteComplete " + secondReInviteComplete + " && byeReceived " + byeReceived);
  529. }
  530. } else {
  531. if(firstTxComplete && firstReInviteComplete && byeReceived) {
  532. System.out.println("shootme state OK " );
  533. } else {
  534. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && byeReceived " + byeReceived);
  535. }
  536. }
  537. }
  538. }
  539. class Shootist implements SipListener {
  540. private SipProvider sipProvider;
  541. private SipStack sipStack;
  542. private ContactHeader contactHeader;
  543. private ListeningPoint udpListeningPoint;
  544. private ClientTransaction inviteTid;
  545. private Dialog dialog;
  546. private boolean byeTaskRunning;
  547. public boolean callerSendsBye = true;
  548. private static final String myAddress = IP_ADDRESS;
  549. public int myPort = 5050;
  550. private boolean sendSubscribe ;
  551. private boolean firstTxComplete;
  552. private boolean firstReInviteComplete;
  553. private boolean secondReInviteComplete;
  554. private boolean thirdReInviteComplete;
  555. private boolean okToByeReceived;
  556. // Save the created ACK request, to respond to retransmitted 2xx
  557. private Request ackRequest;
  558. private boolean notifyTxComplete;
  559. private boolean subscribeTxComplete;
  560. private String stackName;
  561. private boolean failoverOn1xx;
  562. private boolean failoverOn2xx;
  563. class ByeTask extends TimerTask {
  564. Dialog dialog;
  565. public ByeTask(Dialog dialog) {
  566. this.dialog = dialog;
  567. }
  568. public void run () {
  569. try {
  570. Request byeRequest = this.dialog.createRequest(Request.BYE);
  571. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  572. dialog.sendRequest(ct);
  573. } catch (Exception ex) {
  574. ex.printStackTrace();
  575. fail("Unexpected exception ");
  576. }
  577. }
  578. }
  579. public Shootist(String stackName, boolean callerSendsBye) {
  580. this.callerSendsBye = callerSendsBye;
  581. this.stackName = stackName;
  582. }
  583. public void processRequest(RequestEvent requestReceivedEvent) {
  584. Request request = requestReceivedEvent.getRequest();
  585. ServerTransaction serverTransactionId = requestReceivedEvent
  586. .getServerTransaction();
  587. System.out.println("\n\nRequest " + request.getMethod()
  588. + " received at " + sipStack.getStackName()
  589. + " with server transaction id " + serverTransactionId);
  590. // We are the UAC so the only request we get is the BYE.
  591. if (request.getMethod().equals(Request.BYE))
  592. processBye(request, serverTransactionId);
  593. else if(request.getMethod().equals(Request.NOTIFY)) {
  594. try {
  595. serverTransactionId.sendResponse( messageFactory.createResponse(200,request) );
  596. notifyTxComplete = true;
  597. } catch (Exception e) {
  598. e.printStackTrace();
  599. fail("Unxepcted exception ");
  600. }
  601. } else {
  602. if(!request.getMethod().equals(Request.ACK)) {
  603. // not used in basic reinvite
  604. if(((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber() == 1 && ((ToHeader)request.getHeader(ToHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  605. try {
  606. serverTransactionId.sendResponse( messageFactory.createResponse(202,request) );
  607. } catch (Exception e) {
  608. e.printStackTrace();
  609. fail("Unxepcted exception ");
  610. }
  611. } else {
  612. processInvite(requestReceivedEvent, serverTransactionId);
  613. }
  614. } else {
  615. if(request.getMethod().equals(Request.ACK)) {
  616. long cseq = ((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber();
  617. switch ((int) cseq) {
  618. case 1:
  619. firstReInviteComplete = true;
  620. // not used in basic reinvite
  621. if(sendSubscribe) {
  622. try {
  623. Request subscribe = requestReceivedEvent.getDialog().createRequest(Request.SUBSCRIBE);
  624. requestReceivedEvent.getDialog().sendRequest(sipProvider.getNewClientTransaction(subscribe));
  625. } catch (SipException e) {
  626. // TODO Auto-generated catch block
  627. e.printStackTrace();
  628. fail("Unxepcted exception ");
  629. }
  630. }
  631. break;
  632. case 2:
  633. secondReInviteComplete = true;
  634. break;
  635. case 3:
  636. secondReInviteComplete = true;
  637. break;
  638. case 4:
  639. thirdReInviteComplete = true;
  640. break;
  641. default:
  642. break;
  643. }
  644. }
  645. }
  646. }
  647. }
  648. /**
  649. * Process the invite request.
  650. */
  651. public void processInvite(RequestEvent requestEvent,
  652. ServerTransaction serverTransaction) {
  653. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  654. Request request = requestEvent.getRequest();
  655. if(!((ToHeader)requestEvent.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI().toString().contains("ReInvite") && !((FromHeader)requestEvent.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("LittleGuy")) {
  656. throw new IllegalStateException("The From and To Headers are reversed !!!!");
  657. }
  658. try {
  659. if(failoverOn2xx || failoverOn1xx) {
  660. //restart the sip stack
  661. try {
  662. b2buaNode1.initStack(IP_ADDRESS, ListeningPoint.UDP);
  663. b2buaNode1.pingBalancer();
  664. } catch (Exception e) {
  665. e.printStackTrace();
  666. }
  667. }
  668. System.out.println("shootme: got an Invite sending Trying");
  669. // System.out.println("shootme: " + request);
  670. Response response = messageFactory.createResponse(Response.RINGING,
  671. request);
  672. ServerTransaction st = requestEvent.getServerTransaction();
  673. if (st == null) {
  674. st = sipProvider.getNewServerTransaction(request);
  675. }
  676. dialog = st.getDialog();
  677. st.sendResponse(response);
  678. Thread.sleep(3000);
  679. Response okResponse = messageFactory.createResponse(Response.OK,
  680. request);
  681. Address address = addressFactory.createAddress("Shootme <sip:"
  682. + myAddress + ":" + myPort + ">");
  683. ContactHeader contactHeader = headerFactory
  684. .createContactHeader(address);
  685. response.addHeader(contactHeader);
  686. okResponse.addHeader(contactHeader);
  687. // this.inviteTid = st;
  688. // Defer sending the OK to simulate the phone ringing.
  689. // Answered in 1 second ( this guy is fast at taking calls)
  690. // this.inviteRequest = request;
  691. if (inviteTid.getState() != TransactionState.COMPLETED) {
  692. System.out.println("shootme: Dialog state before 200: "
  693. + inviteTid.getDialog().getState());
  694. st.sendResponse(okResponse);
  695. System.out.println("shootme: Dialog state after 200: "
  696. + inviteTid.getDialog().getState());
  697. }
  698. } catch (Exception ex) {
  699. ex.printStackTrace();
  700. System.exit(0);
  701. }
  702. }
  703. public void processBye(Request request,
  704. ServerTransaction serverTransactionId) {
  705. try {
  706. System.out.println("shootist: got a bye .");
  707. if (serverTransactionId == null) {
  708. System.out.println("shootist: null TID.");
  709. return;
  710. }
  711. Dialog dialog = serverTransactionId.getDialog();
  712. System.out.println("Dialog State = " + dialog.getState());
  713. Response response = messageFactory.createResponse(200, request);
  714. serverTransactionId.sendResponse(response);
  715. System.out.println("shootist: Sending OK.");
  716. System.out.println("Dialog State = " + dialog.getState());
  717. } catch (Exception ex) {
  718. fail("Unexpected exception");
  719. }
  720. }
  721. public void processResponse(ResponseEvent responseReceivedEvent) {
  722. System.out.println("Got a response");
  723. Response response = (Response) responseReceivedEvent.getResponse();
  724. ClientTransaction tid = responseReceivedEvent.getClientTransaction();
  725. CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
  726. System.out.println("Response received : Status Code = "
  727. + response.getStatusCode() + " " + cseq);
  728. if(cseq.getMethod().equalsIgnoreCase(Request.SUBSCRIBE)) {
  729. subscribeTxComplete = true;
  730. return;
  731. }
  732. if (tid == null) {
  733. // RFC3261: MUST respond to every 2xx
  734. if (ackRequest!=null && dialog!=null) {
  735. System.out.println("re-sending ACK");
  736. try {
  737. dialog.sendAck(ackRequest);
  738. } catch (SipException se) {
  739. se.printStackTrace();
  740. fail("Unxpected exception ");
  741. }
  742. }
  743. return;
  744. }
  745. // If the caller is supposed to send the bye
  746. if ( callerSendsBye && !byeTaskRunning) {
  747. byeTaskRunning = true;
  748. new Timer().schedule(new ByeTask(dialog), 50000) ;
  749. }
  750. System.out.println("transaction state is " + tid.getState());
  751. System.out.println("Dialog = " + tid.getDialog());
  752. System.out.println("Dialog State is " + tid.getDialog().getState());
  753. assertSame("Checking dialog identity",tid.getDialog(), this.dialog);
  754. try {
  755. if(failoverOn1xx && response.getStatusCode() == Response.RINGING) {
  756. // stop the sip stack w/o stopping the cache
  757. b2buaNode1.stopPingBalancer();
  758. b2buaNode1.stop(false);
  759. }
  760. if (response.getStatusCode() == Response.OK) {
  761. if (cseq.getMethod().equals(Request.INVITE)) {
  762. System.out.println("Dialog after 200 OK " + dialog);
  763. System.out.println("Dialog State after 200 OK " + dialog.getState());
  764. Request ackRequest = dialog.createAck(cseq.getSeqNumber());
  765. if (failoverOn2xx) {
  766. // stop the sip stack w/o stopping the cache
  767. b2buaNode1.stopPingBalancer();
  768. b2buaNode1.stop(false);
  769. ((SipURI)ackRequest.getRequestURI()).setPort(5081);
  770. }
  771. System.out.println("Sending " + ackRequest);
  772. dialog.sendAck(ackRequest);
  773. firstTxComplete = true;
  774. // JvB: test REFER, reported bug in tag handling
  775. // Request referRequest = dialog.createRequest("REFER");
  776. // //simulating a balancer that will forward the request to the recovery node
  777. // SipURI referRequestURI = addressFactory.createSipURI(null, "127.0.0.1:5080");
  778. // referRequest.setRequestURI(referRequestURI);
  779. // dialog.sendRequest( sipProvider.getNewClientTransaction(referRequest));
  780. //
  781. } else if (cseq.getMethod().equals(Request.CANCEL)) {
  782. if (dialog.getState() == DialogState.CONFIRMED) {
  783. // oops cancel went in too late. Need to hang up the
  784. // dialog.
  785. System.out
  786. .println("Sending BYE -- cancel went in too late !!");
  787. Request byeRequest = dialog.createRequest(Request.BYE);
  788. ClientTransaction ct = sipProvider
  789. .getNewClientTransaction(byeRequest);
  790. dialog.sendRequest(ct);
  791. }
  792. } else if (cseq.getMethod().equals(Request.BYE)) {
  793. okToByeReceived = true;
  794. }
  795. }
  796. } catch (Exception ex) {
  797. ex.printStackTrace();
  798. System.exit(0);
  799. }
  800. }
  801. public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
  802. System.out.println("Transaction Time out");
  803. }
  804. public void sendCancel() {
  805. try {
  806. System.out.println("Sending cancel");
  807. Request cancelRequest = inviteTid.createCancel();
  808. ClientTransaction cancelTid = sipProvider
  809. .getNewClientTransaction(cancelRequest);
  810. cancelTid.sendRequest();
  811. } catch (Exception ex) {
  812. ex.printStackTrace();
  813. }
  814. }
  815. public void init(String from) {
  816. SipFactory sipFactory = null;
  817. sipStack = null;
  818. sipFactory = SipFactory.getInstance();
  819. sipFactory.setPathName("gov.nist");
  820. Properties properties = new Properties();
  821. // If you want to try TCP transport change the following to
  822. String transport = "udp";
  823. String peerHostPort = IP_ADDRESS + ":" + BALANCER_PORT;
  824. properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
  825. + transport);
  826. // If you want to use UDP then uncomment this.
  827. properties.setProperty("javax.sip.STACK_NAME", stackName);
  828. // The following properties are specific to nist-sip
  829. // and are not necessarily part of any other jain-sip
  830. // implementation.
  831. // You can set a max message size for tcp transport to
  832. // guard against denial of service attack.
  833. properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",
  834. "logs/shootistdebug.txt");
  835. properties.setProperty("gov.nist.javax.sip.SERVER_LOG",
  836. "logs/shootistlog.xml");
  837. // Drop the client connection after we are done with the transaction.
  838. properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS",
  839. "false");
  840. // Set to 0 (or NONE) in your production code for max speed.
  841. // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for debug + traces.
  842. // Your code will limp at 32 but it is best for debugging.
  843. properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
  844. try {
  845. // Create SipStack object
  846. sipStack = sipFactory.createSipStack(properties);
  847. System.out.println("createSipStack " + sipStack);
  848. } catch (PeerUnavailableException e) {
  849. // could not find
  850. // gov.nist.jain.protocol.ip.sip.SipStackImpl
  851. // in the classpath
  852. e.printStackTrace();
  853. System.err.println(e.getMessage());
  854. System.exit(0);
  855. }
  856. try {
  857. headerFactory = sipFactory.createHeaderFactory();
  858. addressFactory = sipFactory.createAddressFactory();
  859. messageFactory = sipFactory.createMessageFactory();
  860. udpListeningPoint = sipStack.createListeningPoint(IP_ADDRESS, myPort, "udp");
  861. sipProvider = sipStack.createSipProvider(udpListeningPoint);
  862. Shootist listener = this;
  863. sipProvider.addSipListener(listener);
  864. String fromName = from;
  865. String fromSipAddress = "here.com";
  866. String fromDisplayName = "The Master Blaster";
  867. String toSipAddress = "there.com";
  868. String toUser = "LittleGuy";
  869. String toDisplayName = "The Little Blister";
  870. // create >From Header
  871. SipURI fromAddress = addressFactory.createSipURI(fromName,
  872. fromSipAddress);
  873. Address fromNameAddress = addressFactory.createAddress(fromAddress);
  874. fromNameAddress.setDisplayName(fromDisplayName);
  875. FromHeader fromHeader = headerFactory.createFromHeader(
  876. fromNameAddress, "12345");
  877. // create To Header
  878. SipURI toAddress = addressFactory
  879. .createSipURI(toUser, toSipAddress);
  880. Address toNameAddress = addressFactory.createAddress(toAddress);
  881. toNameAddress.setDisplayName(toDisplayName);
  882. ToHeader toHeader = headerFactory.createToHeader(toNameAddress,
  883. null);
  884. // create Request URI
  885. SipURI requestURI = addressFactory.createSipURI(toUser,
  886. IP_ADDRESS + ":" + 5080);
  887. // Create ViaHeaders
  888. ArrayList viaHeaders = new ArrayList();
  889. String ipAddress = udpListeningPoint.getIPAddress();
  890. ViaHeader viaHeader = headerFactory.createViaHeader(ipAddress,
  891. sipProvider.getListeningPoint(transport).getPort(),
  892. transport, null);
  893. // add via headers
  894. viaHeaders.add(viaHeader);
  895. // Create ContentTypeHeader
  896. ContentTypeHeader contentTypeHeader = headerFactory
  897. .createContentTypeHeader("application", "sdp");
  898. // Create a new CallId header
  899. CallIdHeader callIdHeader = sipProvider.getNewCallId();
  900. // Create a new Cseq header
  901. CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L,
  902. Request.INVITE);
  903. // Create a new MaxForwardsHeader
  904. MaxForwardsHeader maxForwards = headerFactory
  905. .createMaxForwardsHeader(70);
  906. // Create the request.
  907. Request request = messageFactory.createRequest(requestURI,
  908. Request.INVITE, callIdHeader, cSeqHeader, fromHeader,
  909. toHeader, viaHeaders, maxForwards);
  910. // Create contact headers
  911. String host = IP_ADDRESS;
  912. SipURI contactUrl = addressFactory.createSipURI(fromName, host);
  913. contactUrl.setPort(udpListeningPoint.getPort());
  914. contactUrl.setLrParam();
  915. // Create the contact name address.
  916. SipURI contactURI = addressFactory.createSipURI(fromName, host);
  917. contactURI.setPort(sipProvider.getListeningPoint(transport)
  918. .getPort());
  919. Address contactAddress = addressFactory.createAddress(contactURI);
  920. // Add the contact address.
  921. contactAddress.setDisplayName(fromName);
  922. contactHeader = headerFactory.createContactHeader(contactAddress);
  923. request.addHeader(contactHeader);
  924. // You can add extension headers of your own making
  925. // to the outgoing SIP request.
  926. // Add the extension header.
  927. Header extensionHeader = headerFactory.createHeader("My-Header",
  928. "my header value");
  929. request.addHeader(extensionHeader);
  930. String sdpData = "v=0\r\n"
  931. + "o=4855 13760799956958020 13760799956958020"
  932. + " IN IP4 129.6.55.78\r\n" + "s=mysession session\r\n"
  933. + "p=+46 8 52018010\r\n" + "c=IN IP4 129.6.55.78\r\n"
  934. + "t=0 0\r\n" + "m=audio 6022 RTP/AVP 0 4 18\r\n"
  935. + "a=rtpmap:0 PCMU/8000\r\n" + "a=rtpmap:4 G723/8000\r\n"
  936. + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n";
  937. byte[] contents = sdpData.getBytes();
  938. request.setContent(contents, contentTypeHeader);
  939. // You can add as many extension headers as you
  940. // want.
  941. extensionHeader = headerFactory.createHeader("My-Other-Header",
  942. "my new header value ");
  943. request.addHeader(extensionHeader);
  944. Header callInfoHeader = headerFactory.createHeader("Call-Info",
  945. "<http://www.antd.nist.gov>");
  946. request.addHeader(callInfoHeader);
  947. // Create the client transaction.
  948. inviteTid = sipProvider.getNewClientTransaction(request);
  949. // send the request out.
  950. inviteTid.sendRequest();
  951. dialog = inviteTid.getDialog();
  952. } catch (Exception ex) {
  953. System.out.println(ex.getMessage());
  954. ex.printStackTrace();
  955. fail("Unxpected exception ");
  956. }
  957. }
  958. public void processIOException(IOExceptionEvent exceptionEvent) {
  959. System.out.println("IOException happened for "
  960. + exceptionEvent.getHost() + " port = "
  961. + exceptionEvent.getPort());
  962. }
  963. public void processTransactionTerminated(
  964. TransactionTerminatedEvent transactionTerminatedEvent) {
  965. System.out.println("Transaction terminated event recieved");
  966. }
  967. public void processDialogTerminated(
  968. DialogTerminatedEvent dialogTerminatedEvent) {
  969. System.out.println("dialogTerminatedEvent");
  970. }
  971. public void stop() {
  972. stopSipStack(sipStack, this);
  973. }
  974. public void checkState(boolean reinviteSubsNotify) {
  975. if(reinviteSubsNotify) {
  976. if(firstTxComplete && firstReInviteComplete && subscribeTxComplete && notifyTxComplete && secondReInviteComplete && thirdReInviteComplete && okToByeReceived) {
  977. System.out.println("shootist state OK " );
  978. } else {
  979. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && subscribeTxComplete " + subscribeTxComplete + " && notifyComplete " + notifyTxComplete + "&& secondReInviteComplete " + secondReInviteComplete + "&& thirdReInviteComplete " + thirdReInviteComplete + " && okToByeReceived " + okToByeReceived);
  980. }
  981. } else {
  982. if(firstTxComplete && firstReInviteComplete && okToByeReceived) {
  983. System.out.println("shootist state OK " );
  984. } else {
  985. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && okToByeReceived " + okToByeReceived);
  986. }
  987. }
  988. }
  989. public void setSendSubscribe(boolean b) {
  990. sendSubscribe = b;
  991. }
  992. /**
  993. * @param failoverOn2xx the failoverOn2xx to set
  994. */
  995. public void setFailoverOn2xx(boolean failoverOn2xx) {
  996. this.failoverOn2xx = failoverOn2xx;
  997. }
  998. /**
  999. * @return the failoverOn2xx
  1000. */
  1001. public boolean isFailoverOn2xx() {
  1002. return failoverOn2xx;
  1003. }
  1004. /**
  1005. * @param failoverOn1xx the failoverOn1xx to set
  1006. */
  1007. public void setFailoverOn1xx(boolean failoverOn1xx) {
  1008. this.failoverOn1xx = failoverOn1xx;
  1009. }
  1010. /**
  1011. * @return the failoverOn1xx
  1012. */
  1013. public boolean isFailoverOn1xx() {
  1014. return failoverOn1xx;
  1015. }
  1016. }
  1017. public static void stopSipStack(SipStack sipStack, SipListener listener) {
  1018. Iterator<SipProvider> sipProviderIterator = sipStack.getSipProviders();
  1019. try{
  1020. while (sipProviderIterator.hasNext()) {
  1021. SipProvider sipProvider = sipProviderIterator.next();
  1022. ListeningPoint[] listeningPoints = sipProvider.getListeningPoints();
  1023. for (ListeningPoint listeningPoint : listeningPoints) {
  1024. sipProvider.removeListeningPoint(listeningPoint);
  1025. sipStack.deleteListeningPoint(listeningPoint);
  1026. listeningPoints = sipProvid

Large files files are truncated, but you can click here to view the full file