PageRenderTime 65ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://mobicents.googlecode.com/
Java | 1658 lines | 1147 code | 241 blank | 270 comment | 113 complexity | 9f9ed3e90ae9d4d7a5bdefc5be967854 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.BalancerContext;
  81. import org.mobicents.tools.sip.balancer.BalancerRunner;
  82. /**
  83. * This test aims to test Mobicents Jain Sip Early Dialog failover recovery.
  84. *
  85. * @author <A HREF="mailto:jean.deruelle@gmail.com">Jean Deruelle</A>
  86. *
  87. */
  88. public class B2BUAEarlyDialogRecoveryOn1xxTCPTest extends TestCase {
  89. public static final String IP_ADDRESS = "192.168.0.10";
  90. public static final int BALANCER_PORT = 5060;
  91. private static AddressFactory addressFactory;
  92. private static MessageFactory messageFactory;
  93. private static HeaderFactory headerFactory;
  94. Shootist shootist;
  95. Shootme shootme;
  96. SimpleB2BUA b2buaNode1;
  97. SimpleB2BUA b2buaNode2;
  98. BalancerRunner balancer;
  99. boolean stopNodeOnReinvite = false;
  100. class Shootme implements SipListener {
  101. private SipStack sipStack;
  102. private static final String myAddress = IP_ADDRESS;
  103. private String stackName;
  104. public int myPort = 5090;
  105. protected ServerTransaction inviteTid;
  106. private Response okResponse;
  107. private Request inviteRequest;
  108. private Dialog dialog;
  109. public boolean callerSendsBye = true;
  110. private SipProvider sipProvider;
  111. private boolean byeTaskRunning;
  112. private boolean secondReinviteSent;
  113. private boolean firstReinviteSent;
  114. private boolean firstTxComplete;
  115. private boolean firstReInviteComplete;
  116. private boolean secondReInviteComplete;
  117. private boolean byeReceived;
  118. private boolean subscribeTxComplete;
  119. private boolean notifyTxComplete;
  120. public Shootme(String stackName, int myPort, boolean callerSendsBye) {
  121. this.stackName = stackName;
  122. this.myPort = myPort;
  123. this.callerSendsBye = callerSendsBye;
  124. System.setProperty("jgroups.bind_addr", IP_ADDRESS);
  125. System.setProperty("java.net.preferIPv4Stack", "true");
  126. }
  127. class ByeTask extends TimerTask {
  128. Dialog dialog;
  129. public ByeTask(Dialog dialog) {
  130. this.dialog = dialog;
  131. }
  132. public void run () {
  133. try {
  134. Request byeRequest = this.dialog.createRequest(Request.BYE);
  135. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  136. dialog.sendRequest(ct);
  137. } catch (Exception ex) {
  138. ex.printStackTrace();
  139. fail("Unexpected exception ");
  140. }
  141. }
  142. }
  143. class MyTimerTask extends TimerTask {
  144. Shootme shootme;
  145. public MyTimerTask(Shootme shootme) {
  146. this.shootme = shootme;
  147. }
  148. public void run() {
  149. shootme.sendInviteOK();
  150. }
  151. }
  152. protected static final String usageString = "java "
  153. + "examples.shootist.Shootist \n"
  154. + ">>>> is your class path set to the root?";
  155. private static final long TIMEOUT = 10000;
  156. public void processRequest(RequestEvent requestEvent) {
  157. Request request = requestEvent.getRequest();
  158. ServerTransaction serverTransactionId = requestEvent
  159. .getServerTransaction();
  160. System.out.println("\n\nRequest " + request.getMethod()
  161. + " received at " + sipStack.getStackName()
  162. + " with server transaction id " + serverTransactionId);
  163. if (request.getMethod().equals(Request.INVITE)) {
  164. processInvite(requestEvent, serverTransactionId);
  165. } else if (request.getMethod().equals(Request.ACK)) {
  166. processAck(requestEvent, serverTransactionId);
  167. } else if (request.getMethod().equals(Request.BYE)) {
  168. processBye(requestEvent, serverTransactionId);
  169. } else if (request.getMethod().equals(Request.SUBSCRIBE)) {
  170. processSubscribe(requestEvent, serverTransactionId);
  171. } else if (request.getMethod().equals(Request.CANCEL)) {
  172. processCancel(requestEvent, serverTransactionId);
  173. } else {
  174. try {
  175. serverTransactionId.sendResponse( messageFactory.createResponse( 202, request ) );
  176. // send one back
  177. SipProvider prov = (SipProvider) requestEvent.getSource();
  178. Request refer = requestEvent.getDialog().createRequest("REFER");
  179. requestEvent.getDialog().sendRequest( prov.getNewClientTransaction(refer) );
  180. } catch (SipException e) {
  181. // TODO Auto-generated catch block
  182. e.printStackTrace();
  183. } catch (InvalidArgumentException e) {
  184. // TODO Auto-generated catch block
  185. e.printStackTrace();
  186. } catch (ParseException e) {
  187. // TODO Auto-generated catch block
  188. e.printStackTrace();
  189. }
  190. }
  191. }
  192. public void processResponse(ResponseEvent responseEvent) {
  193. Dialog dialog = responseEvent.getDialog();
  194. CSeqHeader cSeqHeader = (CSeqHeader)responseEvent.getResponse().getHeader(CSeqHeader.NAME);
  195. try {
  196. if(stopNodeOnReinvite && responseEvent.getResponse().getStatusCode() == Response.RINGING) {
  197. // stop the sip stack w/o stopping the cache
  198. b2buaNode2.stopPingBalancer();
  199. b2buaNode2.stop(false);
  200. }
  201. if(responseEvent.getResponse().getStatusCode() >= 200 && cSeqHeader.getMethod().equalsIgnoreCase(Request.INVITE)) {
  202. Request ackRequest = dialog.createAck(cSeqHeader.getSeqNumber());
  203. int port = 5080;
  204. if(firstReinviteSent) {
  205. port = 5081;
  206. firstReinviteSent = false;
  207. firstReInviteComplete = true;
  208. }
  209. if(secondReinviteSent) {
  210. secondReInviteComplete = true;
  211. }
  212. System.out.println("Sending ACK");
  213. ((SipURI)ackRequest.getRequestURI()).setPort(port);
  214. dialog.sendAck(ackRequest);
  215. // if(!secondReinviteSent) {
  216. // Thread.sleep(2000);
  217. // Request request = dialog.createRequest("INVITE");
  218. // ((SipURI)request.getRequestURI()).setPort(5080);
  219. // final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  220. // dialog.sendRequest(ct);
  221. // secondReinviteSent = true;
  222. // }
  223. } else if(responseEvent.getResponse().getStatusCode() >= 200 && cSeqHeader.getMethod().equalsIgnoreCase(Request.NOTIFY)) {
  224. notifyTxComplete = true;
  225. Thread.sleep(5000);
  226. Request request = dialog.createRequest("INVITE");
  227. ((SipURI)request.getRequestURI()).setPort(5081);
  228. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  229. firstReinviteSent = true;
  230. dialog.sendRequest(ct);
  231. }
  232. } catch (SipException e) {
  233. // TODO Auto-generated catch block
  234. e.printStackTrace();
  235. } catch (InvalidArgumentException e) {
  236. // TODO Auto-generated catch block
  237. e.printStackTrace();
  238. } catch (InterruptedException e) {
  239. // TODO Auto-generated catch block
  240. e.printStackTrace();
  241. }
  242. }
  243. /**
  244. * Process the ACK request. Send the bye and complete the call flow.
  245. */
  246. public void processAck(RequestEvent requestEvent,
  247. ServerTransaction serverTransaction) {
  248. try {
  249. Dialog dialog = serverTransaction.getDialog();
  250. System.out.println("shootme: got an ACK! ");
  251. System.out.println("Dialog State = " + dialog.getState());
  252. firstTxComplete = true;
  253. // used in basic reinvite
  254. if(!firstReinviteSent && !((FromHeader)requestEvent.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  255. Thread.sleep(5000);
  256. Request request = dialog.createRequest("INVITE");
  257. ((SipURI)request.getRequestURI()).setPort(5081);
  258. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  259. firstReinviteSent = true;
  260. dialog.sendRequest(ct);
  261. }
  262. } catch (Exception ex) {
  263. ex.printStackTrace();
  264. }
  265. }
  266. /**
  267. * Process the invite request.
  268. */
  269. public void processInvite(RequestEvent requestEvent,
  270. ServerTransaction serverTransaction) {
  271. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  272. Request request = requestEvent.getRequest();
  273. try {
  274. System.out.println("shootme: got an Invite sending Trying");
  275. // System.out.println("shootme: " + request);
  276. Response response = messageFactory.createResponse(Response.RINGING,
  277. request);
  278. ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
  279. toHeader.setTag("4321"); // Application is supposed to set.
  280. ServerTransaction st = requestEvent.getServerTransaction();
  281. if (st == null) {
  282. st = sipProvider.getNewServerTransaction(request);
  283. }
  284. dialog = st.getDialog();
  285. st.sendResponse(response);
  286. Thread.sleep(4000);
  287. this.okResponse = messageFactory.createResponse(Response.OK,
  288. request);
  289. Address address = addressFactory.createAddress("Shootme <sip:"
  290. + myAddress + ":" + myPort + ">");
  291. ContactHeader contactHeader = headerFactory
  292. .createContactHeader(address);
  293. response.addHeader(contactHeader);
  294. toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME);
  295. toHeader.setTag("4321"); // Application is supposed to set.
  296. okResponse.addHeader(contactHeader);
  297. this.inviteTid = st;
  298. // Defer sending the OK to simulate the phone ringing.
  299. // Answered in 1 second ( this guy is fast at taking calls)
  300. this.inviteRequest = request;
  301. sendInviteOK();
  302. } catch (Exception ex) {
  303. ex.printStackTrace();
  304. System.exit(0);
  305. }
  306. }
  307. private void sendInviteOK() {
  308. try {
  309. if (inviteTid.getState() != TransactionState.COMPLETED) {
  310. System.out.println("shootme: Dialog state before 200: "
  311. + inviteTid.getDialog().getState());
  312. inviteTid.sendResponse(okResponse);
  313. System.out.println("shootme: Dialog state after 200: "
  314. + inviteTid.getDialog().getState());
  315. }
  316. } catch (SipException ex) {
  317. ex.printStackTrace();
  318. } catch (InvalidArgumentException ex) {
  319. ex.printStackTrace();
  320. }
  321. }
  322. /**
  323. * Process the bye request.
  324. */
  325. public void processBye(RequestEvent requestEvent,
  326. ServerTransaction serverTransactionId) {
  327. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  328. Request request = requestEvent.getRequest();
  329. Dialog dialog = requestEvent.getDialog();
  330. System.out.println("local party = " + dialog.getLocalParty());
  331. try {
  332. System.out.println("shootme: got a bye sending OK.");
  333. Response response = messageFactory.createResponse(200, request);
  334. serverTransactionId.sendResponse(response);
  335. System.out.println("Dialog State is "
  336. + serverTransactionId.getDialog().getState());
  337. byeReceived = true;
  338. } catch (Exception ex) {
  339. ex.printStackTrace();
  340. System.exit(0);
  341. }
  342. }
  343. /**
  344. * Process the bye request.
  345. */
  346. public void processSubscribe(RequestEvent requestEvent,
  347. ServerTransaction serverTransactionId) {
  348. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  349. Request request = requestEvent.getRequest();
  350. Dialog dialog = requestEvent.getDialog();
  351. try {
  352. ServerTransaction st = requestEvent.getServerTransaction();
  353. if (st == null) {
  354. st = sipProvider.getNewServerTransaction(request);
  355. }
  356. System.out.println("shootme: got a subscribe sending OK.");
  357. Response response = messageFactory.createResponse(200, request);
  358. response.addHeader(headerFactory.createHeader(ExpiresHeader.NAME, "3600"));
  359. st.sendResponse(response);
  360. System.out.println("Dialog State is "
  361. + st.getDialog().getState());
  362. subscribeTxComplete = true;
  363. Thread.sleep(5000);
  364. Request notify = st.getDialog().createRequest(Request.NOTIFY);
  365. notify.addHeader(headerFactory.createHeader(SubscriptionStateHeader.NAME, SubscriptionStateHeader.ACTIVE));
  366. notify.addHeader(headerFactory.createHeader(EventHeader.NAME, "presence"));
  367. ((SipURI)notify.getRequestURI()).setUser(null);
  368. ((SipURI)notify.getRequestURI()).setHost(IP_ADDRESS);
  369. ((SipURI)notify.getRequestURI()).setPort(5080);
  370. st.getDialog().sendRequest(sipProvider.getNewClientTransaction(notify));
  371. } catch (Exception ex) {
  372. ex.printStackTrace();
  373. System.exit(0);
  374. }
  375. }
  376. public void processCancel(RequestEvent requestEvent,
  377. ServerTransaction serverTransactionId) {
  378. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  379. Request request = requestEvent.getRequest();
  380. try {
  381. System.out.println("shootme: got a cancel.");
  382. if (serverTransactionId == null) {
  383. System.out.println("shootme: null tid.");
  384. return;
  385. }
  386. Response response = messageFactory.createResponse(200, request);
  387. serverTransactionId.sendResponse(response);
  388. if (dialog.getState() != DialogState.CONFIRMED) {
  389. response = messageFactory.createResponse(
  390. Response.REQUEST_TERMINATED, inviteRequest);
  391. inviteTid.sendResponse(response);
  392. }
  393. } catch (Exception ex) {
  394. ex.printStackTrace();
  395. System.exit(0);
  396. }
  397. }
  398. public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
  399. Transaction transaction;
  400. if (timeoutEvent.isServerTransaction()) {
  401. transaction = timeoutEvent.getServerTransaction();
  402. } else {
  403. transaction = timeoutEvent.getClientTransaction();
  404. }
  405. System.out.println("state = " + transaction.getState());
  406. System.out.println("dialog = " + transaction.getDialog());
  407. System.out.println("dialogState = "
  408. + transaction.getDialog().getState());
  409. System.out.println("Transaction Time out");
  410. }
  411. public void init() {
  412. SipFactory sipFactory = null;
  413. sipStack = null;
  414. sipFactory = SipFactory.getInstance();
  415. sipFactory.setPathName("gov.nist");
  416. Properties properties = new Properties();
  417. properties.setProperty("javax.sip.STACK_NAME", stackName);
  418. String transport = "tcp";
  419. String peerHostPort = IP_ADDRESS + ":" + BALANCER_PORT;
  420. properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
  421. + transport);
  422. // You need 16 for logging traces. 32 for debug + traces.
  423. // Your code will limp at 32 but it is best for debugging.
  424. properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
  425. properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "logs/" +
  426. stackName + "debug.txt");
  427. properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "logs/" +
  428. stackName + "log.xml");
  429. try {
  430. // Create SipStack object
  431. sipStack = sipFactory.createSipStack(properties);
  432. System.out.println("sipStack = " + sipStack);
  433. } catch (PeerUnavailableException e) {
  434. // could not find
  435. // gov.nist.jain.protocol.ip.sip.SipStackImpl
  436. // in the classpath
  437. e.printStackTrace();
  438. System.err.println(e.getMessage());
  439. if (e.getCause() != null)
  440. e.getCause().printStackTrace();
  441. System.exit(0);
  442. }
  443. try {
  444. headerFactory = sipFactory.createHeaderFactory();
  445. addressFactory = sipFactory.createAddressFactory();
  446. messageFactory = sipFactory.createMessageFactory();
  447. ListeningPoint lp = sipStack.createListeningPoint(myAddress,
  448. myPort, ListeningPoint.TCP);
  449. Shootme listener = this;
  450. sipProvider = sipStack.createSipProvider(lp);
  451. System.out.println("tcp provider " + sipProvider);
  452. sipProvider.addSipListener(listener);
  453. // if(dialogs != null) {
  454. // Collection<Dialog> serializedDialogs = simulateDialogSerialization(dialogs);
  455. // for (Dialog dialog : serializedDialogs) {
  456. // ((SIPDialog)dialog).setSipProvider((SipProviderImpl)sipProvider);
  457. // ((SipStackImpl)sipStack).putDialog((SIPDialog)dialog);
  458. // }
  459. // this.dialog = (SIPDialog)serializedDialogs.iterator().next();
  460. // }
  461. sipStack.start();
  462. if(!callerSendsBye && this.dialog != null) {
  463. try {
  464. Request byeRequest = this.dialog.createRequest(Request.BYE);
  465. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  466. System.out.println("sending BYE " + byeRequest);
  467. dialog.sendRequest(ct);
  468. } catch (Exception ex) {
  469. ex.printStackTrace();
  470. fail("Unexpected exception ");
  471. }
  472. }
  473. } catch (Exception ex) {
  474. System.out.println(ex.getMessage());
  475. ex.printStackTrace();
  476. fail("Unexpected exception");
  477. }
  478. }
  479. private Collection<Dialog> simulateDialogSerialization(
  480. Collection<Dialog> dialogs) {
  481. Collection<Dialog> serializedDialogs = new ArrayList<Dialog>();
  482. for (Dialog dialog : dialogs) {
  483. try{
  484. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  485. ObjectOutputStream out = new ObjectOutputStream(baos);
  486. out.writeObject(dialog);
  487. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  488. ObjectInputStream in =new ObjectInputStream(bais);
  489. SIPDialog serializedDialog = (SIPDialog)in.readObject();
  490. serializedDialogs.add(serializedDialog);
  491. out.close();
  492. in.close();
  493. baos.close();
  494. bais.close();
  495. } catch (IOException e) {
  496. e.printStackTrace();
  497. } catch (ClassNotFoundException e) {
  498. e.printStackTrace();
  499. }
  500. }
  501. return serializedDialogs;
  502. }
  503. public void processIOException(IOExceptionEvent exceptionEvent) {
  504. System.out.println("IOException");
  505. }
  506. public void processTransactionTerminated(
  507. TransactionTerminatedEvent transactionTerminatedEvent) {
  508. if (transactionTerminatedEvent.isServerTransaction())
  509. System.out.println("Transaction terminated event recieved"
  510. + transactionTerminatedEvent.getServerTransaction());
  511. else
  512. System.out.println("Transaction terminated "
  513. + transactionTerminatedEvent.getClientTransaction());
  514. }
  515. public void processDialogTerminated(
  516. DialogTerminatedEvent dialogTerminatedEvent) {
  517. System.out.println("Dialog terminated event recieved");
  518. Dialog d = dialogTerminatedEvent.getDialog();
  519. System.out.println("Local Party = " + d.getLocalParty());
  520. }
  521. public void stop() {
  522. stopSipStack(sipStack, this);
  523. }
  524. public void checkState(boolean reinviteSubsNotify) {
  525. if(reinviteSubsNotify) {
  526. if(firstTxComplete && subscribeTxComplete && notifyTxComplete && firstReInviteComplete && secondReInviteComplete && byeReceived) {
  527. System.out.println("shootme state OK " );
  528. } else {
  529. fail("firstTxComplete " + firstTxComplete + " && subscribeTxComplete " + subscribeTxComplete + " && notifyComplete " + notifyTxComplete + " && firstReInviteComplete " + firstReInviteComplete + "&& secondReInviteComplete " + secondReInviteComplete + " && byeReceived " + byeReceived);
  530. }
  531. } else {
  532. if(firstTxComplete && firstReInviteComplete && byeReceived) {
  533. System.out.println("shootme state OK " );
  534. } else {
  535. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && byeReceived " + byeReceived);
  536. }
  537. }
  538. }
  539. }
  540. class Shootist implements SipListener {
  541. private SipProvider sipProvider;
  542. private SipStack sipStack;
  543. private ContactHeader contactHeader;
  544. private ListeningPoint tcpListeningPoint;
  545. private ClientTransaction inviteTid;
  546. private Dialog dialog;
  547. private boolean byeTaskRunning;
  548. public boolean callerSendsBye = true;
  549. private static final String myAddress = IP_ADDRESS;
  550. public int myPort = 5050;
  551. private boolean sendSubscribe ;
  552. private boolean firstTxComplete;
  553. private boolean firstReInviteComplete;
  554. private boolean secondReInviteComplete;
  555. private boolean thirdReInviteComplete;
  556. private boolean okToByeReceived;
  557. // Save the created ACK request, to respond to retransmitted 2xx
  558. private Request ackRequest;
  559. private boolean notifyTxComplete;
  560. private boolean subscribeTxComplete;
  561. private String stackName;
  562. private boolean failoverOn1xx;
  563. private boolean failoverOn2xx;
  564. class ByeTask extends TimerTask {
  565. Dialog dialog;
  566. public ByeTask(Dialog dialog) {
  567. this.dialog = dialog;
  568. }
  569. public void run () {
  570. try {
  571. Request byeRequest = this.dialog.createRequest(Request.BYE);
  572. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  573. dialog.sendRequest(ct);
  574. } catch (Exception ex) {
  575. ex.printStackTrace();
  576. fail("Unexpected exception ");
  577. }
  578. }
  579. }
  580. public Shootist(String stackName, boolean callerSendsBye) {
  581. this.callerSendsBye = callerSendsBye;
  582. this.stackName = stackName;
  583. }
  584. public void processRequest(RequestEvent requestReceivedEvent) {
  585. Request request = requestReceivedEvent.getRequest();
  586. ServerTransaction serverTransactionId = requestReceivedEvent
  587. .getServerTransaction();
  588. System.out.println("\n\nRequest " + request.getMethod()
  589. + " received at " + sipStack.getStackName()
  590. + " with server transaction id " + serverTransactionId);
  591. // We are the UAC so the only request we get is the BYE.
  592. if (request.getMethod().equals(Request.BYE))
  593. processBye(request, serverTransactionId);
  594. else if(request.getMethod().equals(Request.NOTIFY)) {
  595. try {
  596. serverTransactionId.sendResponse( messageFactory.createResponse(200,request) );
  597. notifyTxComplete = true;
  598. } catch (Exception e) {
  599. e.printStackTrace();
  600. fail("Unxepcted exception ");
  601. }
  602. } else {
  603. if(!request.getMethod().equals(Request.ACK)) {
  604. // not used in basic reinvite
  605. if(((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber() == 1 && ((ToHeader)request.getHeader(ToHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  606. try {
  607. serverTransactionId.sendResponse( messageFactory.createResponse(202,request) );
  608. } catch (Exception e) {
  609. e.printStackTrace();
  610. fail("Unxepcted exception ");
  611. }
  612. } else {
  613. processInvite(requestReceivedEvent, serverTransactionId);
  614. }
  615. } else {
  616. if(request.getMethod().equals(Request.ACK)) {
  617. long cseq = ((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber();
  618. switch ((int) cseq) {
  619. case 1:
  620. firstReInviteComplete = true;
  621. // not used in basic reinvite
  622. if(sendSubscribe) {
  623. try {
  624. Request subscribe = requestReceivedEvent.getDialog().createRequest(Request.SUBSCRIBE);
  625. requestReceivedEvent.getDialog().sendRequest(sipProvider.getNewClientTransaction(subscribe));
  626. } catch (SipException e) {
  627. // TODO Auto-generated catch block
  628. e.printStackTrace();
  629. fail("Unxepcted exception ");
  630. }
  631. }
  632. break;
  633. case 2:
  634. secondReInviteComplete = true;
  635. break;
  636. case 3:
  637. secondReInviteComplete = true;
  638. break;
  639. case 4:
  640. thirdReInviteComplete = true;
  641. break;
  642. default:
  643. break;
  644. }
  645. }
  646. }
  647. }
  648. }
  649. /**
  650. * Process the invite request.
  651. */
  652. public void processInvite(RequestEvent requestEvent,
  653. ServerTransaction serverTransaction) {
  654. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  655. Request request = requestEvent.getRequest();
  656. if(!((ToHeader)requestEvent.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI().toString().contains("ReInvite") && !((FromHeader)requestEvent.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("LittleGuy")) {
  657. throw new IllegalStateException("The From and To Headers are reversed !!!!");
  658. }
  659. try {
  660. if(failoverOn2xx || failoverOn1xx) {
  661. //restart the sip stack
  662. try {
  663. b2buaNode1.initStack(IP_ADDRESS, ListeningPoint.TCP);
  664. b2buaNode1.pingBalancer();
  665. } catch (Exception e) {
  666. e.printStackTrace();
  667. }
  668. }
  669. System.out.println("shootme: got an Invite sending Trying");
  670. // System.out.println("shootme: " + request);
  671. Response response = messageFactory.createResponse(Response.RINGING,
  672. request);
  673. ServerTransaction st = requestEvent.getServerTransaction();
  674. if (st == null) {
  675. st = sipProvider.getNewServerTransaction(request);
  676. }
  677. dialog = st.getDialog();
  678. st.sendResponse(response);
  679. Thread.sleep(3000);
  680. Response okResponse = messageFactory.createResponse(Response.OK,
  681. request);
  682. Address address = addressFactory.createAddress("Shootme <sip:"
  683. + myAddress + ":" + myPort + ">");
  684. ContactHeader contactHeader = headerFactory
  685. .createContactHeader(address);
  686. response.addHeader(contactHeader);
  687. okResponse.addHeader(contactHeader);
  688. // this.inviteTid = st;
  689. // Defer sending the OK to simulate the phone ringing.
  690. // Answered in 1 second ( this guy is fast at taking calls)
  691. // this.inviteRequest = request;
  692. if (inviteTid.getState() != TransactionState.COMPLETED) {
  693. System.out.println("shootme: Dialog state before 200: "
  694. + inviteTid.getDialog().getState());
  695. st.sendResponse(okResponse);
  696. System.out.println("shootme: Dialog state after 200: "
  697. + inviteTid.getDialog().getState());
  698. }
  699. } catch (Exception ex) {
  700. ex.printStackTrace();
  701. System.exit(0);
  702. }
  703. }
  704. public void processBye(Request request,
  705. ServerTransaction serverTransactionId) {
  706. try {
  707. System.out.println("shootist: got a bye .");
  708. if (serverTransactionId == null) {
  709. System.out.println("shootist: null TID.");
  710. return;
  711. }
  712. Dialog dialog = serverTransactionId.getDialog();
  713. System.out.println("Dialog State = " + dialog.getState());
  714. Response response = messageFactory.createResponse(200, request);
  715. serverTransactionId.sendResponse(response);
  716. System.out.println("shootist: Sending OK.");
  717. System.out.println("Dialog State = " + dialog.getState());
  718. } catch (Exception ex) {
  719. fail("Unexpected exception");
  720. }
  721. }
  722. public void processResponse(ResponseEvent responseReceivedEvent) {
  723. System.out.println("Got a response");
  724. Response response = (Response) responseReceivedEvent.getResponse();
  725. ClientTransaction tid = responseReceivedEvent.getClientTransaction();
  726. CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
  727. System.out.println("Response received : Status Code = "
  728. + response.getStatusCode() + " " + cseq);
  729. if(cseq.getMethod().equalsIgnoreCase(Request.SUBSCRIBE)) {
  730. subscribeTxComplete = true;
  731. return;
  732. }
  733. if (tid == null) {
  734. // RFC3261: MUST respond to every 2xx
  735. if (ackRequest!=null && dialog!=null) {
  736. System.out.println("re-sending ACK");
  737. try {
  738. dialog.sendAck(ackRequest);
  739. } catch (SipException se) {
  740. se.printStackTrace();
  741. fail("Unxpected exception ");
  742. }
  743. }
  744. return;
  745. }
  746. // If the caller is supposed to send the bye
  747. if ( callerSendsBye && !byeTaskRunning) {
  748. byeTaskRunning = true;
  749. new Timer().schedule(new ByeTask(dialog), 50000) ;
  750. }
  751. System.out.println("transaction state is " + tid.getState());
  752. System.out.println("Dialog = " + tid.getDialog());
  753. System.out.println("Dialog State is " + tid.getDialog().getState());
  754. assertSame("Checking dialog identity",tid.getDialog(), this.dialog);
  755. try {
  756. if(failoverOn1xx && response.getStatusCode() == Response.RINGING) {
  757. // stop the sip stack w/o stopping the cache
  758. b2buaNode1.stopPingBalancer();
  759. b2buaNode1.stop(false);
  760. }
  761. if (response.getStatusCode() == Response.OK) {
  762. if (cseq.getMethod().equals(Request.INVITE)) {
  763. System.out.println("Dialog after 200 OK " + dialog);
  764. System.out.println("Dialog State after 200 OK " + dialog.getState());
  765. Request ackRequest = dialog.createAck(cseq.getSeqNumber());
  766. if (failoverOn2xx) {
  767. // stop the sip stack w/o stopping the cache
  768. b2buaNode1.stopPingBalancer();
  769. b2buaNode1.stop(false);
  770. ((SipURI)ackRequest.getRequestURI()).setPort(5081);
  771. }
  772. System.out.println("Sending " + ackRequest);
  773. dialog.sendAck(ackRequest);
  774. firstTxComplete = true;
  775. // JvB: test REFER, reported bug in tag handling
  776. // Request referRequest = dialog.createRequest("REFER");
  777. // //simulating a balancer that will forward the request to the recovery node
  778. // SipURI referRequestURI = addressFactory.createSipURI(null, "127.0.0.1:5080");
  779. // referRequest.setRequestURI(referRequestURI);
  780. // dialog.sendRequest( sipProvider.getNewClientTransaction(referRequest));
  781. //
  782. } else if (cseq.getMethod().equals(Request.CANCEL)) {
  783. if (dialog.getState() == DialogState.CONFIRMED) {
  784. // oops cancel went in too late. Need to hang up the
  785. // dialog.
  786. System.out
  787. .println("Sending BYE -- cancel went in too late !!");
  788. Request byeRequest = dialog.createRequest(Request.BYE);
  789. ClientTransaction ct = sipProvider
  790. .getNewClientTransaction(byeRequest);
  791. dialog.sendRequest(ct);
  792. }
  793. } else if (cseq.getMethod().equals(Request.BYE)) {
  794. okToByeReceived = true;
  795. }
  796. }
  797. } catch (Exception ex) {
  798. ex.printStackTrace();
  799. System.exit(0);
  800. }
  801. }
  802. public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
  803. System.out.println("Transaction Time out");
  804. }
  805. public void sendCancel() {
  806. try {
  807. System.out.println("Sending cancel");
  808. Request cancelRequest = inviteTid.createCancel();
  809. ClientTransaction cancelTid = sipProvider
  810. .getNewClientTransaction(cancelRequest);
  811. cancelTid.sendRequest();
  812. } catch (Exception ex) {
  813. ex.printStackTrace();
  814. }
  815. }
  816. public void init(String from) {
  817. SipFactory sipFactory = null;
  818. sipStack = null;
  819. sipFactory = SipFactory.getInstance();
  820. sipFactory.setPathName("gov.nist");
  821. Properties properties = new Properties();
  822. // If you want to try TCP transport change the following to
  823. String transport = "tcp";
  824. String peerHostPort = IP_ADDRESS + ":" + BALANCER_PORT;
  825. properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
  826. + transport);
  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. tcpListeningPoint = sipStack.createListeningPoint(IP_ADDRESS, myPort, "tcp");
  861. sipProvider = sipStack.createSipProvider(tcpListeningPoint);
  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 = tcpListeningPoint.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(tcpListeningPoint.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. try {
  1025. sipProvider.removeListeningPoint(listeningPoint);
  1026. sipStack.deleteListeningPoint(listeningPoint);
  1027. } catch (Exception e) {
  1028. System.err.print

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