PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://mobicents.googlecode.com/
Java | 1470 lines | 1036 code | 222 blank | 212 comment | 119 complexity | b1ca35d21c61fd16386ebc169fbea3c2 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 ProxyEarlyDialogRecoveryOn1xxTest 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. SimpleStatefulProxy proxyNode1;
  96. SimpleStatefulProxy proxyNode2;
  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. proxyNode2.stopPingBalancer();
  198. proxyNode2.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. System.out.println("shootme: got an ACK! ");
  249. Dialog dialog = requestEvent.getDialog();
  250. if(serverTransaction != null && dialog == null){
  251. dialog = serverTransaction.getDialog();
  252. }
  253. System.out.println("Dialog = " + dialog);
  254. if(dialog == null) {
  255. return ;
  256. }
  257. System.out.println("Dialog State = " + dialog.getState());
  258. firstTxComplete = true;
  259. // used in basic reinvite
  260. if(!firstReinviteSent && !((FromHeader)requestEvent.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  261. Thread.sleep(5000);
  262. Request request = dialog.createRequest("INVITE");
  263. ((SipURI)request.getRequestURI()).setPort(5080);
  264. final ClientTransaction ct = sipProvider.getNewClientTransaction(request);
  265. firstReinviteSent = true;
  266. dialog.sendRequest(ct);
  267. }
  268. } catch (Exception ex) {
  269. ex.printStackTrace();
  270. }
  271. }
  272. /**
  273. * Process the invite request.
  274. */
  275. public void processInvite(RequestEvent requestEvent,
  276. ServerTransaction serverTransaction) {
  277. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  278. Request request = requestEvent.getRequest();
  279. try {
  280. System.out.println("shootme: got an Invite sending Trying");
  281. // System.out.println("shootme: " + request);
  282. Response response = messageFactory.createResponse(Response.RINGING,
  283. request);
  284. ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
  285. toHeader.setTag("4321"); // Application is supposed to set.
  286. ServerTransaction st = requestEvent.getServerTransaction();
  287. if (st == null) {
  288. st = sipProvider.getNewServerTransaction(request);
  289. }
  290. dialog = st.getDialog();
  291. st.sendResponse(response);
  292. Thread.sleep(3000);
  293. this.okResponse = messageFactory.createResponse(Response.OK,
  294. request);
  295. Address address = addressFactory.createAddress("Shootme <sip:"
  296. + myAddress + ":" + myPort + ">");
  297. ContactHeader contactHeader = headerFactory
  298. .createContactHeader(address);
  299. response.addHeader(contactHeader);
  300. toHeader = (ToHeader) okResponse.getHeader(ToHeader.NAME);
  301. toHeader.setTag("4321"); // Application is supposed to set.
  302. okResponse.addHeader(contactHeader);
  303. this.inviteTid = st;
  304. // Defer sending the OK to simulate the phone ringing.
  305. // Answered in 1 second ( this guy is fast at taking calls)
  306. this.inviteRequest = request;
  307. sendInviteOK();
  308. } catch (Exception ex) {
  309. ex.printStackTrace();
  310. System.exit(0);
  311. }
  312. }
  313. private void sendInviteOK() {
  314. try {
  315. if (inviteTid.getState() != TransactionState.COMPLETED) {
  316. System.out.println("shootme: Dialog state before 200: "
  317. + inviteTid.getDialog().getState());
  318. inviteTid.sendResponse(okResponse);
  319. System.out.println("shootme: Dialog state after 200: "
  320. + inviteTid.getDialog().getState());
  321. }
  322. } catch (SipException ex) {
  323. ex.printStackTrace();
  324. } catch (InvalidArgumentException ex) {
  325. ex.printStackTrace();
  326. }
  327. }
  328. /**
  329. * Process the bye request.
  330. */
  331. public void processBye(RequestEvent requestEvent,
  332. ServerTransaction serverTransactionId) {
  333. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  334. Request request = requestEvent.getRequest();
  335. Dialog dialog = requestEvent.getDialog();
  336. System.out.println("local party = " + dialog.getLocalParty());
  337. try {
  338. System.out.println("shootme: got a bye sending OK.");
  339. Response response = messageFactory.createResponse(200, request);
  340. serverTransactionId.sendResponse(response);
  341. System.out.println("Dialog State is "
  342. + serverTransactionId.getDialog().getState());
  343. byeReceived = true;
  344. } catch (Exception ex) {
  345. ex.printStackTrace();
  346. System.exit(0);
  347. }
  348. }
  349. /**
  350. * Process the bye request.
  351. */
  352. public void processSubscribe(RequestEvent requestEvent,
  353. ServerTransaction serverTransactionId) {
  354. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  355. Request request = requestEvent.getRequest();
  356. Dialog dialog = requestEvent.getDialog();
  357. try {
  358. ServerTransaction st = requestEvent.getServerTransaction();
  359. if (st == null) {
  360. st = sipProvider.getNewServerTransaction(request);
  361. }
  362. System.out.println("shootme: got a subscribe sending OK.");
  363. Response response = messageFactory.createResponse(200, request);
  364. response.addHeader(headerFactory.createHeader(ExpiresHeader.NAME, "3600"));
  365. st.sendResponse(response);
  366. System.out.println("Dialog State is "
  367. + st.getDialog().getState());
  368. subscribeTxComplete = true;
  369. Thread.sleep(5000);
  370. Request notify = st.getDialog().createRequest(Request.NOTIFY);
  371. notify.addHeader(headerFactory.createHeader(SubscriptionStateHeader.NAME, SubscriptionStateHeader.ACTIVE));
  372. notify.addHeader(headerFactory.createHeader(EventHeader.NAME, "presence"));
  373. ((SipURI)notify.getRequestURI()).setUser(null);
  374. ((SipURI)notify.getRequestURI()).setHost(IP_ADDRESS);
  375. ((SipURI)notify.getRequestURI()).setPort(5080);
  376. st.getDialog().sendRequest(sipProvider.getNewClientTransaction(notify));
  377. } catch (Exception ex) {
  378. ex.printStackTrace();
  379. System.exit(0);
  380. }
  381. }
  382. public void processCancel(RequestEvent requestEvent,
  383. ServerTransaction serverTransactionId) {
  384. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  385. Request request = requestEvent.getRequest();
  386. try {
  387. System.out.println("shootme: got a cancel.");
  388. if (serverTransactionId == null) {
  389. System.out.println("shootme: null tid.");
  390. return;
  391. }
  392. Response response = messageFactory.createResponse(200, request);
  393. serverTransactionId.sendResponse(response);
  394. if (dialog.getState() != DialogState.CONFIRMED) {
  395. response = messageFactory.createResponse(
  396. Response.REQUEST_TERMINATED, inviteRequest);
  397. inviteTid.sendResponse(response);
  398. }
  399. } catch (Exception ex) {
  400. ex.printStackTrace();
  401. System.exit(0);
  402. }
  403. }
  404. public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
  405. Transaction transaction;
  406. if (timeoutEvent.isServerTransaction()) {
  407. transaction = timeoutEvent.getServerTransaction();
  408. } else {
  409. transaction = timeoutEvent.getClientTransaction();
  410. }
  411. System.out.println("state = " + transaction.getState());
  412. System.out.println("dialog = " + transaction.getDialog());
  413. System.out.println("dialogState = "
  414. + transaction.getDialog().getState());
  415. System.out.println("Transaction Time out");
  416. }
  417. public void init() {
  418. SipFactory sipFactory = null;
  419. sipStack = null;
  420. sipFactory = SipFactory.getInstance();
  421. sipFactory.setPathName("gov.nist");
  422. Properties properties = new Properties();
  423. properties.setProperty("javax.sip.STACK_NAME", stackName);
  424. String transport = "udp";
  425. String peerHostPort = IP_ADDRESS + ":" + BALANCER_PORT;
  426. properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
  427. + transport);
  428. // You need 16 for logging traces. 32 for debug + traces.
  429. // Your code will limp at 32 but it is best for debugging.
  430. properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
  431. properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "logs/" +
  432. stackName + "debug.txt");
  433. properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "logs/" +
  434. stackName + "log.xml");
  435. try {
  436. // Create SipStack object
  437. sipStack = sipFactory.createSipStack(properties);
  438. System.out.println("sipStack = " + sipStack);
  439. } catch (PeerUnavailableException e) {
  440. // could not find
  441. // gov.nist.jain.protocol.ip.sip.SipStackImpl
  442. // in the classpath
  443. e.printStackTrace();
  444. System.err.println(e.getMessage());
  445. if (e.getCause() != null)
  446. e.getCause().printStackTrace();
  447. System.exit(0);
  448. }
  449. try {
  450. headerFactory = sipFactory.createHeaderFactory();
  451. addressFactory = sipFactory.createAddressFactory();
  452. messageFactory = sipFactory.createMessageFactory();
  453. ListeningPoint lp = sipStack.createListeningPoint(myAddress,
  454. myPort, ListeningPoint.UDP);
  455. Shootme listener = this;
  456. sipProvider = sipStack.createSipProvider(lp);
  457. System.out.println("udp provider " + sipProvider);
  458. sipProvider.addSipListener(listener);
  459. // if(dialogs != null) {
  460. // Collection<Dialog> serializedDialogs = simulateDialogSerialization(dialogs);
  461. // for (Dialog dialog : serializedDialogs) {
  462. // ((SIPDialog)dialog).setSipProvider((SipProviderImpl)sipProvider);
  463. // ((SipStackImpl)sipStack).putDialog((SIPDialog)dialog);
  464. // }
  465. // this.dialog = (SIPDialog)serializedDialogs.iterator().next();
  466. // }
  467. sipStack.start();
  468. if(!callerSendsBye && this.dialog != null) {
  469. try {
  470. Request byeRequest = this.dialog.createRequest(Request.BYE);
  471. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  472. System.out.println("sending BYE " + byeRequest);
  473. dialog.sendRequest(ct);
  474. } catch (Exception ex) {
  475. ex.printStackTrace();
  476. fail("Unexpected exception ");
  477. }
  478. }
  479. } catch (Exception ex) {
  480. System.out.println(ex.getMessage());
  481. ex.printStackTrace();
  482. fail("Unexpected exception");
  483. }
  484. }
  485. private Collection<Dialog> simulateDialogSerialization(
  486. Collection<Dialog> dialogs) {
  487. Collection<Dialog> serializedDialogs = new ArrayList<Dialog>();
  488. for (Dialog dialog : dialogs) {
  489. try{
  490. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  491. ObjectOutputStream out = new ObjectOutputStream(baos);
  492. out.writeObject(dialog);
  493. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  494. ObjectInputStream in =new ObjectInputStream(bais);
  495. SIPDialog serializedDialog = (SIPDialog)in.readObject();
  496. serializedDialogs.add(serializedDialog);
  497. out.close();
  498. in.close();
  499. baos.close();
  500. bais.close();
  501. } catch (IOException e) {
  502. e.printStackTrace();
  503. } catch (ClassNotFoundException e) {
  504. e.printStackTrace();
  505. }
  506. }
  507. return serializedDialogs;
  508. }
  509. public void processIOException(IOExceptionEvent exceptionEvent) {
  510. System.out.println("IOException");
  511. }
  512. public void processTransactionTerminated(
  513. TransactionTerminatedEvent transactionTerminatedEvent) {
  514. if (transactionTerminatedEvent.isServerTransaction())
  515. System.out.println("Transaction terminated event recieved"
  516. + transactionTerminatedEvent.getServerTransaction());
  517. else
  518. System.out.println("Transaction terminated "
  519. + transactionTerminatedEvent.getClientTransaction());
  520. }
  521. public void processDialogTerminated(
  522. DialogTerminatedEvent dialogTerminatedEvent) {
  523. System.out.println("Dialog terminated event recieved");
  524. Dialog d = dialogTerminatedEvent.getDialog();
  525. System.out.println("Local Party = " + d.getLocalParty());
  526. }
  527. public void stop() {
  528. stopSipStack(sipStack, this);
  529. }
  530. public void checkState(boolean reinviteSubsNotify) {
  531. if(reinviteSubsNotify) {
  532. if(firstTxComplete && subscribeTxComplete && notifyTxComplete && firstReInviteComplete && secondReInviteComplete && byeReceived) {
  533. System.out.println("shootme state OK " );
  534. } else {
  535. fail("firstTxComplete " + firstTxComplete + " && subscribeTxComplete " + subscribeTxComplete + " && notifyComplete " + notifyTxComplete + " && firstReInviteComplete " + firstReInviteComplete + "&& secondReInviteComplete " + secondReInviteComplete + " && byeReceived " + byeReceived);
  536. }
  537. } else {
  538. if(firstTxComplete && firstReInviteComplete && byeReceived) {
  539. System.out.println("shootme state OK " );
  540. } else {
  541. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && byeReceived " + byeReceived);
  542. }
  543. }
  544. }
  545. }
  546. class Shootist implements SipListener {
  547. private SipProvider sipProvider;
  548. private SipStack sipStack;
  549. private ContactHeader contactHeader;
  550. private ListeningPoint udpListeningPoint;
  551. private ClientTransaction inviteTid;
  552. private Dialog dialog;
  553. private boolean byeTaskRunning;
  554. public boolean callerSendsBye = true;
  555. private static final String myAddress = IP_ADDRESS;
  556. public int myPort = 5050;
  557. private boolean sendSubscribe ;
  558. private boolean firstTxComplete;
  559. private boolean firstReInviteComplete;
  560. private boolean secondReInviteComplete;
  561. private boolean thirdReInviteComplete;
  562. private boolean okToByeReceived;
  563. // Save the created ACK request, to respond to retransmitted 2xx
  564. private Request ackRequest;
  565. private boolean notifyTxComplete;
  566. private boolean subscribeTxComplete;
  567. private String stackName;
  568. private boolean failoverOn1xx;
  569. private boolean failoverOn2xx;
  570. class ByeTask extends TimerTask {
  571. Dialog dialog;
  572. public ByeTask(Dialog dialog) {
  573. this.dialog = dialog;
  574. }
  575. public void run () {
  576. try {
  577. Request byeRequest = this.dialog.createRequest(Request.BYE);
  578. ClientTransaction ct = sipProvider.getNewClientTransaction(byeRequest);
  579. dialog.sendRequest(ct);
  580. } catch (Exception ex) {
  581. ex.printStackTrace();
  582. fail("Unexpected exception ");
  583. }
  584. }
  585. }
  586. public Shootist(String stackName, boolean callerSendsBye) {
  587. this.callerSendsBye = callerSendsBye;
  588. this.stackName = stackName;
  589. }
  590. public void processRequest(RequestEvent requestReceivedEvent) {
  591. Request request = requestReceivedEvent.getRequest();
  592. ServerTransaction serverTransactionId = requestReceivedEvent
  593. .getServerTransaction();
  594. System.out.println("\n\nRequest " + request.getMethod()
  595. + " received at " + sipStack.getStackName()
  596. + " with server transaction id " + serverTransactionId);
  597. // We are the UAC so the only request we get is the BYE.
  598. if (request.getMethod().equals(Request.BYE))
  599. processBye(request, serverTransactionId);
  600. else if(request.getMethod().equals(Request.NOTIFY)) {
  601. try {
  602. serverTransactionId.sendResponse( messageFactory.createResponse(200,request) );
  603. notifyTxComplete = true;
  604. } catch (Exception e) {
  605. e.printStackTrace();
  606. fail("Unxepcted exception ");
  607. }
  608. } else {
  609. if(!request.getMethod().equals(Request.ACK)) {
  610. // not used in basic reinvite
  611. if(((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber() == 1 && ((ToHeader)request.getHeader(ToHeader.NAME)).getAddress().getURI().toString().contains("ReInviteSubsNotify")) {
  612. try {
  613. serverTransactionId.sendResponse( messageFactory.createResponse(202,request) );
  614. } catch (Exception e) {
  615. e.printStackTrace();
  616. fail("Unxepcted exception ");
  617. }
  618. } else {
  619. processInvite(requestReceivedEvent, serverTransactionId);
  620. }
  621. } else {
  622. if(request.getMethod().equals(Request.ACK)) {
  623. long cseq = ((CSeqHeader) request.getHeader(CSeqHeader.NAME)).getSeqNumber();
  624. switch ((int) cseq) {
  625. case 1:
  626. firstReInviteComplete = true;
  627. // not used in basic reinvite
  628. if(sendSubscribe) {
  629. try {
  630. Request subscribe = requestReceivedEvent.getDialog().createRequest(Request.SUBSCRIBE);
  631. requestReceivedEvent.getDialog().sendRequest(sipProvider.getNewClientTransaction(subscribe));
  632. } catch (SipException e) {
  633. // TODO Auto-generated catch block
  634. e.printStackTrace();
  635. fail("Unxepcted exception ");
  636. }
  637. }
  638. break;
  639. case 2:
  640. secondReInviteComplete = true;
  641. break;
  642. case 3:
  643. secondReInviteComplete = true;
  644. break;
  645. case 4:
  646. thirdReInviteComplete = true;
  647. break;
  648. default:
  649. break;
  650. }
  651. }
  652. }
  653. }
  654. }
  655. /**
  656. * Process the invite request.
  657. */
  658. public void processInvite(RequestEvent requestEvent,
  659. ServerTransaction serverTransaction) {
  660. SipProvider sipProvider = (SipProvider) requestEvent.getSource();
  661. Request request = requestEvent.getRequest();
  662. if(!((ToHeader)requestEvent.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI().toString().contains("ReInvite") && !((FromHeader)requestEvent.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI().toString().contains("LittleGuy")) {
  663. throw new IllegalStateException("The From and To Headers are reversed !!!!");
  664. }
  665. try {
  666. if(failoverOn1xx && stopNodeOnReinvite) {
  667. //restart the sip stack
  668. try {
  669. proxyNode1.initStack(IP_ADDRESS, ListeningPoint.UDP);
  670. proxyNode1.pingBalancer();
  671. } catch (Exception e) {
  672. e.printStackTrace();
  673. }
  674. }
  675. System.out.println("shootme: got an Invite sending Trying");
  676. // System.out.println("shootme: " + request);
  677. Response response = messageFactory.createResponse(Response.RINGING,
  678. request);
  679. ServerTransaction st = requestEvent.getServerTransaction();
  680. if (st == null) {
  681. st = sipProvider.getNewServerTransaction(request);
  682. }
  683. dialog = st.getDialog();
  684. st.sendResponse(response);
  685. Thread.sleep(3000);
  686. Response okResponse = messageFactory.createResponse(Response.OK,
  687. request);
  688. Address address = addressFactory.createAddress("Shootme <sip:"
  689. + myAddress + ":" + myPort + ">");
  690. ContactHeader contactHeader = headerFactory
  691. .createContactHeader(address);
  692. response.addHeader(contactHeader);
  693. okResponse.addHeader(contactHeader);
  694. // this.inviteTid = st;
  695. // Defer sending the OK to simulate the phone ringing.
  696. // Answered in 1 second ( this guy is fast at taking calls)
  697. // this.inviteRequest = request;
  698. if (inviteTid.getState() != TransactionState.COMPLETED) {
  699. System.out.println("shootme: Dialog state before 200: "
  700. + inviteTid.getDialog().getState());
  701. st.sendResponse(okResponse);
  702. System.out.println("shootme: Dialog state after 200: "
  703. + inviteTid.getDialog().getState());
  704. }
  705. } catch (Exception ex) {
  706. ex.printStackTrace();
  707. System.exit(0);
  708. }
  709. }
  710. public void processBye(Request request,
  711. ServerTransaction serverTransactionId) {
  712. try {
  713. System.out.println("shootist: got a bye .");
  714. if (serverTransactionId == null) {
  715. System.out.println("shootist: null TID.");
  716. return;
  717. }
  718. Dialog dialog = serverTransactionId.getDialog();
  719. System.out.println("Dialog State = " + dialog.getState());
  720. Response response = messageFactory.createResponse(200, request);
  721. serverTransactionId.sendResponse(response);
  722. System.out.println("shootist: Sending OK.");
  723. System.out.println("Dialog State = " + dialog.getState());
  724. } catch (Exception ex) {
  725. fail("Unexpected exception");
  726. }
  727. }
  728. public void processResponse(ResponseEvent responseReceivedEvent) {
  729. System.out.println("Got a response");
  730. Response response = (Response) responseReceivedEvent.getResponse();
  731. ClientTransaction tid = responseReceivedEvent.getClientTransaction();
  732. CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
  733. System.out.println("Response received : Status Code = "
  734. + response.getStatusCode() + " " + cseq);
  735. if(cseq.getMethod().equalsIgnoreCase(Request.SUBSCRIBE)) {
  736. subscribeTxComplete = true;
  737. return;
  738. }
  739. if (tid == null) {
  740. // RFC3261: MUST respond to every 2xx
  741. if (ackRequest!=null && dialog!=null) {
  742. System.out.println("re-sending ACK");
  743. try {
  744. dialog.sendAck(ackRequest);
  745. } catch (SipException se) {
  746. se.printStackTrace();
  747. fail("Unxpected exception ");
  748. }
  749. }
  750. return;
  751. }
  752. // If the caller is supposed to send the bye
  753. if ( callerSendsBye && !byeTaskRunning) {
  754. byeTaskRunning = true;
  755. new Timer().schedule(new ByeTask(dialog), 50000) ;
  756. }
  757. System.out.println("transaction state is " + tid.getState());
  758. System.out.println("Dialog = " + tid.getDialog());
  759. System.out.println("Dialog State is " + tid.getDialog().getState());
  760. assertSame("Checking dialog identity",tid.getDialog(), this.dialog);
  761. try {
  762. if(failoverOn1xx && response.getStatusCode() == Response.RINGING) {
  763. // stop the sip stack w/o stopping the cache
  764. proxyNode1.stopPingBalancer();
  765. proxyNode1.stop(false);
  766. }
  767. if (response.getStatusCode() == Response.OK) {
  768. if (cseq.getMethod().equals(Request.INVITE)) {
  769. System.out.println("Dialog after 200 OK " + dialog);
  770. System.out.println("Dialog State after 200 OK " + dialog.getState());
  771. Request ackRequest = dialog.createAck(cseq.getSeqNumber());
  772. if (failoverOn2xx) {
  773. // stop the sip stack w/o stopping the cache
  774. proxyNode1.stopPingBalancer();
  775. proxyNode1.stop(false);
  776. ((SipURI)ackRequest.getRequestURI()).setPort(5081);
  777. }
  778. System.out.println("Sending " + ackRequest);
  779. dialog.sendAck(ackRequest);
  780. firstTxComplete = true;
  781. // JvB: test REFER, reported bug in tag handling
  782. // Request referRequest = dialog.createRequest("REFER");
  783. // //simulating a balancer that will forward the request to the recovery node
  784. // SipURI referRequestURI = addressFactory.createSipURI(null, "127.0.0.1:5080");
  785. // referRequest.setRequestURI(referRequestURI);
  786. // dialog.sendRequest( sipProvider.getNewClientTransaction(referRequest));
  787. //
  788. } else if (cseq.getMethod().equals(Request.CANCEL)) {
  789. if (dialog.getState() == DialogState.CONFIRMED) {
  790. // oops cancel went in too late. Need to hang up the
  791. // dialog.
  792. System.out
  793. .println("Sending BYE -- cancel went in too late !!");
  794. Request byeRequest = dialog.createRequest(Request.BYE);
  795. ClientTransaction ct = sipProvider
  796. .getNewClientTransaction(byeRequest);
  797. dialog.sendRequest(ct);
  798. }
  799. } else if (cseq.getMethod().equals(Request.BYE)) {
  800. okToByeReceived = true;
  801. }
  802. }
  803. } catch (Exception ex) {
  804. ex.printStackTrace();
  805. System.exit(0);
  806. }
  807. }
  808. public void processTimeout(javax.sip.TimeoutEvent timeoutEvent) {
  809. System.out.println("Transaction Time out");
  810. }
  811. public void sendCancel() {
  812. try {
  813. System.out.println("Sending cancel");
  814. Request cancelRequest = inviteTid.createCancel();
  815. ClientTransaction cancelTid = sipProvider
  816. .getNewClientTransaction(cancelRequest);
  817. cancelTid.sendRequest();
  818. } catch (Exception ex) {
  819. ex.printStackTrace();
  820. }
  821. }
  822. public void init(String from) {
  823. SipFactory sipFactory = null;
  824. sipStack = null;
  825. sipFactory = SipFactory.getInstance();
  826. sipFactory.setPathName("gov.nist");
  827. Properties properties = new Properties();
  828. // If you want to try TCP transport change the following to
  829. String transport = "udp";
  830. String peerHostPort = IP_ADDRESS + ":" + BALANCER_PORT;
  831. properties.setProperty("javax.sip.OUTBOUND_PROXY", peerHostPort + "/"
  832. + transport);
  833. // If you want to use UDP then uncomment this.
  834. properties.setProperty("javax.sip.STACK_NAME", stackName);
  835. // The following properties are specific to nist-sip
  836. // and are not necessarily part of any other jain-sip
  837. // implementation.
  838. // You can set a max message size for tcp transport to
  839. // guard against denial of service attack.
  840. properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",
  841. "logs/shootistdebug.txt");
  842. properties.setProperty("gov.nist.javax.sip.SERVER_LOG",
  843. "logs/shootistlog.xml");
  844. // Drop the client connection after we are done with the transaction.
  845. properties.setProperty("gov.nist.javax.sip.CACHE_CLIENT_CONNECTIONS",
  846. "false");
  847. // Set to 0 (or NONE) in your production code for max speed.
  848. // You need 16 (or TRACE) for logging traces. 32 (or DEBUG) for debug + traces.
  849. // Your code will limp at 32 but it is best for debugging.
  850. properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG");
  851. try {
  852. // Create SipStack object
  853. sipStack = sipFactory.createSipStack(properties);
  854. System.out.println("createSipStack " + sipStack);
  855. } catch (PeerUnavailableException e) {
  856. // could not find
  857. // gov.nist.jain.protocol.ip.sip.SipStackImpl
  858. // in the classpath
  859. e.printStackTrace();
  860. System.err.println(e.getMessage());
  861. System.exit(0);
  862. }
  863. try {
  864. headerFactory = sipFactory.createHeaderFactory();
  865. addressFactory = sipFactory.createAddressFactory();
  866. messageFactory = sipFactory.createMessageFactory();
  867. udpListeningPoint = sipStack.createListeningPoint(IP_ADDRESS, myPort, "udp");
  868. sipProvider = sipStack.createSipProvider(udpListeningPoint);
  869. Shootist listener = this;
  870. sipProvider.addSipListener(listener);
  871. String fromName = from;
  872. String fromSipAddress = "here.com";
  873. String fromDisplayName = "The Master Blaster";
  874. String toSipAddress = "there.com";
  875. String toUser = "LittleGuy";
  876. String toDisplayName = "The Little Blister";
  877. // create >From Header
  878. SipURI fromAddress = addressFactory.createSipURI(fromName,
  879. fromSipAddress);
  880. Address fromNameAddress = addressFactory.createAddress(fromAddress);
  881. fromNameAddress.setDisplayName(fromDisplayName);
  882. FromHeader fromHeader = headerFactory.createFromHeader(
  883. fromNameAddress, "12345");
  884. // create To Header
  885. SipURI toAddress = addressFactory
  886. .createSipURI(toUser, toSipAddress);
  887. Address toNameAddress = addressFactory.createAddress(toAddress);
  888. toNameAddress.setDisplayName(toDisplayName);
  889. ToHeader toHeader = headerFactory.createToHeader(toNameAddress,
  890. null);
  891. // create Request URI
  892. SipURI requestURI = addressFactory.createSipURI(toUser,
  893. IP_ADDRESS + ":" + 5080);
  894. // Create ViaHeaders
  895. ArrayList viaHeaders = new ArrayList();
  896. String ipAddress = udpListeningPoint.getIPAddress();
  897. ViaHeader viaHeader = headerFactory.createViaHeader(ipAddress,
  898. sipProvider.getListeningPoint(transport).getPort(),
  899. transport, null);
  900. // add via headers
  901. viaHeaders.add(viaHeader);
  902. // Create ContentTypeHeader
  903. ContentTypeHeader contentTypeHeader = headerFactory
  904. .createContentTypeHeader("application", "sdp");
  905. // Create a new CallId header
  906. CallIdHeader callIdHeader = sipProvider.getNewCallId();
  907. // Create a new Cseq header
  908. CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L,
  909. Request.INVITE);
  910. // Create a new MaxForwardsHeader
  911. MaxForwardsHeader maxForwards = headerFactory
  912. .createMaxForwardsHeader(70);
  913. // Create the request.
  914. Request request = messageFactory.createRequest(requestURI,
  915. Request.INVITE, callIdHeader, cSeqHeader, fromHeader,
  916. toHeader, viaHeaders, maxForwards);
  917. // Create contact headers
  918. String host = IP_ADDRESS;
  919. SipURI contactUrl = addressFactory.createSipURI(fromName, host);
  920. contactUrl.setPort(udpListeningPoint.getPort());
  921. contactUrl.setLrParam();
  922. // Create the contact name address.
  923. SipURI contactURI = addressFactory.createSipURI(fromName, host);
  924. contactURI.setPort(sipProvider.getListeningPoint(transport)
  925. .getPort());
  926. Address contactAddress = addressFactory.createAddress(contactURI);
  927. // Add the contact address.
  928. contactAddress.setDisplayName(fromName);
  929. contactHeader = headerFactory.createContactHeader(contactAddress);
  930. request.addHeader(contactHeader);
  931. // You can add extension headers of your own making
  932. // to the outgoing SIP request.
  933. // Add the extension header.
  934. Header extensionHeader = headerFactory.createHeader("My-Header",
  935. "my header value");
  936. request.addHeader(extensionHeader);
  937. String sdpData = "v=0\r\n"
  938. + "o=4855 13760799956958020 13760799956958020"
  939. + " IN IP4 129.6.55.78\r\n" + "s=mysession session\r\n"
  940. + "p=+46 8 52018010\r\n" + "c=IN IP4 129.6.55.78\r\n"
  941. + "t=0 0\r\n" + "m=audio 6022 RTP/AVP 0 4 18\r\n"
  942. + "a=rtpmap:0 PCMU/8000\r\n" + "a=rtpmap:4 G723/8000\r\n"
  943. + "a=rtpmap:18 G729A/8000\r\n" + "a=ptime:20\r\n";
  944. byte[] contents = sdpData.getBytes();
  945. request.setContent(contents, contentTypeHeader);
  946. // You can add as many extension headers as you
  947. // want.
  948. extensionHeader = headerFactory.createHeader("My-Other-Header",
  949. "my new header value ");
  950. request.addHeader(extensionHeader);
  951. Header callInfoHeader = headerFactory.createHeader("Call-Info",
  952. "<http://www.antd.nist.gov>");
  953. request.addHeader(callInfoHeader);
  954. // Create the client transaction.
  955. inviteTid = sipProvider.getNewClientTransaction(request);
  956. // send the request out.
  957. inviteTid.sendRequest();
  958. dialog = inviteTid.getDialog();
  959. } catch (Exception ex) {
  960. System.out.println(ex.getMessage());
  961. ex.printStackTrace();
  962. fail("Unxpected exception ");
  963. }
  964. }
  965. public void processIOException(IOExceptionEvent exceptionEvent) {
  966. System.out.println("IOException happened for "
  967. + exceptionEvent.getHost() + " port = "
  968. + exceptionEvent.getPort());
  969. }
  970. public void processTransactionTerminated(
  971. TransactionTerminatedEvent transactionTerminatedEvent) {
  972. System.out.println("Transaction terminated event recieved");
  973. }
  974. public void processDialogTerminated(
  975. DialogTerminatedEvent dialogTerminatedEvent) {
  976. System.out.println("dialogTerminatedEvent");
  977. }
  978. public void stop() {
  979. stopSipStack(sipStack, this);
  980. }
  981. public void checkState(boolean reinviteSubsNotify) {
  982. if(reinviteSubsNotify) {
  983. if(firstTxComplete && firstReInviteComplete && subscribeTxComplete && notifyTxComplete && secondReInviteComplete && thirdReInviteComplete && okToByeReceived) {
  984. System.out.println("shootist state OK " );
  985. } else {
  986. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && subscribeTxComplete " + subscribeTxComplete + " && notifyComplete " + notifyTxComplete + "&& secondReInviteComplete " + secondReInviteComplete + "&& thirdReInviteComplete " + thirdReInviteComplete + " && okToByeReceived " + okToByeReceived);
  987. }
  988. } else {
  989. if(firstTxComplete && firstReInviteComplete && okToByeReceived) {
  990. System.out.println("shootist state OK " );
  991. } else {
  992. fail("firstTxComplete " + firstTxComplete + " && firstReInviteComplete " + firstReInviteComplete + " && okToByeReceived " + okToByeReceived);
  993. }
  994. }
  995. }
  996. public void setSendSubscribe(boolean b) {
  997. sendSubscribe = b;
  998. }
  999. /**
  1000. * @param failoverOn2xx the failoverOn2xx to set
  1001. */
  1002. public void setFailoverOn2xx(boolean failoverOn2xx) {
  1003. this.failoverOn2xx = failoverOn2xx;
  1004. }
  1005. /**
  1006. * @return the failoverOn2xx
  1007. */
  1008. public boolean isFailoverOn2xx() {
  1009. return failoverOn2xx;
  1010. }
  1011. /**
  1012. * @param failoverOn1xx the failoverOn1xx to set
  1013. */
  1014. public void setFailoverOn1xx(boolean failoverOn1xx) {
  1015. this.failoverOn1xx = failoverOn1xx;
  1016. }
  1017. /**
  1018. * @return the failoverOn1xx
  1019. */
  1020. public boolean isFailoverOn1xx() {
  1021. return failoverOn1xx;
  1022. }
  1023. }
  1024. public static void stopSipStack(SipStack sipStack, SipListener listener) {
  1025. Iterator<SipProvider> sipProviderIterator = sipStack.getSipProviders();
  1026. try{
  1027. while (sipProviderIterator.hasNext()) {
  1028. SipProvider sipProvider = sipProviderIterator.next();
  1029. ListeningPoint[] listen

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