PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/media/test-suite/core/src/main/java/org/mobicents/media/server/testsuite/general/cnf/CnfCall.java

http://mobicents.googlecode.com/
Java | 574 lines | 368 code | 87 blank | 119 comment | 56 complexity | f77ab3b4d4bd9b965cb5dca509509143 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
  1. /**
  2. *
  3. */
  4. package org.mobicents.media.server.testsuite.general.cnf;
  5. import jain.protocol.ip.mgcp.JainMgcpCommandEvent;
  6. import jain.protocol.ip.mgcp.JainMgcpEvent;
  7. import jain.protocol.ip.mgcp.JainMgcpResponseEvent;
  8. import jain.protocol.ip.mgcp.message.Constants;
  9. import jain.protocol.ip.mgcp.message.CreateConnection;
  10. import jain.protocol.ip.mgcp.message.CreateConnectionResponse;
  11. import jain.protocol.ip.mgcp.message.DeleteConnection;
  12. import jain.protocol.ip.mgcp.message.NotificationRequest;
  13. import jain.protocol.ip.mgcp.message.Notify;
  14. import jain.protocol.ip.mgcp.message.NotifyResponse;
  15. import jain.protocol.ip.mgcp.message.parms.ConflictingParameterException;
  16. import jain.protocol.ip.mgcp.message.parms.ConnectionDescriptor;
  17. import jain.protocol.ip.mgcp.message.parms.ConnectionIdentifier;
  18. import jain.protocol.ip.mgcp.message.parms.ConnectionMode;
  19. import jain.protocol.ip.mgcp.message.parms.EndpointIdentifier;
  20. import jain.protocol.ip.mgcp.message.parms.EventName;
  21. import jain.protocol.ip.mgcp.message.parms.NotifiedEntity;
  22. import jain.protocol.ip.mgcp.message.parms.RequestIdentifier;
  23. import jain.protocol.ip.mgcp.message.parms.RequestedAction;
  24. import jain.protocol.ip.mgcp.message.parms.RequestedEvent;
  25. import jain.protocol.ip.mgcp.message.parms.ReturnCode;
  26. import jain.protocol.ip.mgcp.pkg.MgcpEvent;
  27. import jain.protocol.ip.mgcp.pkg.PackageName;
  28. import java.io.IOException;
  29. import java.net.InetAddress;
  30. import java.net.InetSocketAddress;
  31. import java.net.SocketAddress;
  32. import java.net.UnknownHostException;
  33. import java.util.ArrayList;
  34. import java.util.Collection;
  35. import java.util.HashMap;
  36. import java.util.Iterator;
  37. import java.util.List;
  38. import java.util.ListIterator;
  39. import java.util.Vector;
  40. import java.util.logging.Level;
  41. import javax.sdp.MediaDescription;
  42. import javax.sdp.SdpException;
  43. import javax.sdp.SdpParseException;
  44. import javax.sdp.SessionDescription;
  45. import org.apache.log4j.Logger;
  46. import org.mobicents.media.server.testsuite.general.AbstractCall;
  47. import org.mobicents.media.server.testsuite.general.AbstractTestCase;
  48. import org.mobicents.media.server.testsuite.general.CallState;
  49. import org.mobicents.media.server.testsuite.general.ann.AnnCall;
  50. import org.mobicents.media.server.testsuite.general.ann.AnnCallState;
  51. import org.mobicents.media.server.testsuite.general.rtp.RtpPacket;
  52. import org.mobicents.media.server.testsuite.general.rtp.RtpSocketFactory;
  53. /**
  54. * @author baranowb
  55. *
  56. */
  57. public class CnfCall extends AbstractCall {
  58. protected transient Logger logger = Logger.getLogger(CnfCall.class);
  59. private AnnCallState localFlowState = AnnCallState.INITIAL;
  60. private String HELLO_WORLD = "";
  61. private int numberOfConnections = 1;
  62. private int createdConnections = 0;
  63. private RequestIdentifier ri = null;
  64. private HashMap<String, org.mobicents.media.server.testsuite.general.rtp.RtpSocket> connectionIdToSocket = new HashMap<String, org.mobicents.media.server.testsuite.general.rtp.RtpSocket>();
  65. private HashMap<String, List<RtpPacket>> connectionIdToRtpData = new HashMap<String, List<RtpPacket>>();
  66. private org.mobicents.media.server.testsuite.general.rtp.RtpSocket tenativeSocket;
  67. public CnfCall(AbstractTestCase testCase, String fileToPlay)
  68. throws IOException {
  69. super(testCase);
  70. super.endpointName = "/mobicents/media/cnf/$";
  71. this.HELLO_WORLD = fileToPlay;
  72. }
  73. /*
  74. * (non-Javadoc)
  75. *
  76. * @see
  77. * org.mobicents.media.server.testsuite.general.AbstractCall#performDataDumps
  78. * (boolean)
  79. */
  80. @Override
  81. protected void performDataDumps(boolean isEnding) {
  82. // TODO Auto-generated method stub
  83. }
  84. /*
  85. * (non-Javadoc)
  86. *
  87. * @seeorg.mobicents.media.server.testsuite.general.AbstractCall#
  88. * releaseResourcesOnTermination()
  89. */
  90. @Override
  91. protected void releaseResourcesOnTermination() {
  92. // TODO Auto-generated method stub
  93. }
  94. /*
  95. * (non-Javadoc)
  96. *
  97. * @see org.mobicents.media.server.testsuite.general.AbstractCall#start()
  98. */
  99. @Override
  100. public void start() {
  101. try {
  102. sendCrCx(null, true);
  103. this.setLocalFlowState(AnnCallState.SENT_CRCX);
  104. setState(CallState.INITIAL);
  105. super.onStart();
  106. } catch (Exception e) {
  107. e.printStackTrace();
  108. this.setLocalFlowState(AnnCallState.TERMINATED);
  109. super.setState(CallState.IN_ERROR);
  110. }
  111. }
  112. private void sendCrCx(EndpointIdentifier ei, boolean addCall)
  113. throws IOException, ConflictingParameterException {
  114. initSocket();
  115. if (ei == null)
  116. ei = new EndpointIdentifier(super.endpointName, super.testCase
  117. .getServerJbossBindAddress().getHostAddress()
  118. + ":"
  119. + super.testCase.getCallDisplayInterface().getRemotePort());
  120. CreateConnection crcx = new CreateConnection(this, this.callIdentifier,
  121. ei, ConnectionMode.SendOnly);
  122. // int localPort = this.datagramChannel.socket().getLocalPort();
  123. int localPort = tenativeSocket.getLocalPort();
  124. String sdp = super.getLocalDescriptor(localPort);
  125. // System.err.println(sdp);
  126. crcx.setRemoteConnectionDescriptor(new ConnectionDescriptor(sdp));
  127. crcx.setTransactionHandle(this.provider.getUniqueTransactionHandler());
  128. if (addCall)
  129. super.testCase.addCall(crcx, this);
  130. super.provider.sendMgcpEvents(new JainMgcpEvent[] { crcx });
  131. }
  132. /*
  133. * (non-Javadoc)
  134. *
  135. * @see org.mobicents.media.server.testsuite.general.AbstractCall#stop()
  136. */
  137. @Override
  138. public void stop() {
  139. cancelTimeoutHandle();
  140. if (ri != null) {
  141. super.testCase.removeCall(ri.toString());
  142. }
  143. if (this.state == CallState.IN_ERROR
  144. || this.state == CallState.TIMED_OUT) {
  145. this.setLocalFlowState(AnnCallState.TERMINATED);
  146. } else {
  147. // FIXME: Should in case of forced stop this indicate error?
  148. super.setState(CallState.ENDED);
  149. this.setLocalFlowState(AnnCallState.TERMINATED);
  150. }
  151. super.onStop();
  152. }
  153. /*
  154. * (non-Javadoc)
  155. *
  156. * @see org.mobicents.media.server.testsuite.general.AbstractCall#timeOut()
  157. */
  158. @Override
  159. public void timeOut() {
  160. sendDelete();
  161. }
  162. /*
  163. * (non-Javadoc)
  164. *
  165. * @see
  166. * org.mobicents.mgcp.stack.JainMgcpExtendedListener#transactionEnded(int)
  167. */
  168. public void transactionEnded(int arg0) {
  169. // TODO Auto-generated method stub
  170. }
  171. /*
  172. * (non-Javadoc)
  173. *
  174. * @see
  175. * org.mobicents.mgcp.stack.JainMgcpExtendedListener#transactionRxTimedOut
  176. * (jain.protocol.ip.mgcp.JainMgcpCommandEvent)
  177. */
  178. public void transactionRxTimedOut(JainMgcpCommandEvent arg0) {
  179. // TODO Auto-generated method stub
  180. }
  181. /*
  182. * (non-Javadoc)
  183. *
  184. * @see
  185. * org.mobicents.mgcp.stack.JainMgcpExtendedListener#transactionTxTimedOut
  186. * (jain.protocol.ip.mgcp.JainMgcpCommandEvent)
  187. */
  188. public void transactionTxTimedOut(JainMgcpCommandEvent arg0) {
  189. switch (this.localFlowState) {
  190. case SENT_CRCX:
  191. this.setLocalFlowState(AnnCallState.TERMINATED);
  192. setState(CallState.IN_ERROR);
  193. break;
  194. case SENT_ANN:
  195. // THis is really bad, ... wech
  196. sendDelete();
  197. // If it fails, we dont have means to recover do we?
  198. this.setLocalFlowState(AnnCallState.TERMINATED);
  199. setState(CallState.IN_ERROR);
  200. break;
  201. case SENT_DLCX:
  202. this.setLocalFlowState(AnnCallState.TERMINATED);
  203. setState(CallState.IN_ERROR);
  204. break;
  205. }
  206. }
  207. /*
  208. * (non-Javadoc)
  209. *
  210. * @see
  211. * jain.protocol.ip.mgcp.JainMgcpListener#processMgcpCommandEvent(jain.protocol
  212. * .ip.mgcp.JainMgcpCommandEvent)
  213. */
  214. public void processMgcpCommandEvent(JainMgcpCommandEvent mgcpCommand) {
  215. switch (this.localFlowState) {
  216. case SENT_ANN:
  217. if (mgcpCommand instanceof Notify) {
  218. // here we could do something, instead we respond with 200 and
  219. // remove
  220. Notify notify = (Notify) mgcpCommand;
  221. ReturnCode rc = ReturnCode.Transaction_Executed_Normally;
  222. NotifyResponse notifyResponse = new NotifyResponse(this, rc);
  223. notifyResponse.setTransactionHandle(notify
  224. .getTransactionHandle());
  225. super.provider
  226. .sendMgcpEvents(new JainMgcpEvent[] { notifyResponse });
  227. // lets remove us from call maps
  228. super.testCase.removeCall(mgcpCommand);
  229. super.testCase.removeCall(notify.getRequestIdentifier()
  230. .toString());
  231. cancelTimeoutHandle();
  232. sendDelete();
  233. // stop();
  234. }
  235. break;
  236. default:
  237. stop();
  238. sendDelete();
  239. }
  240. }
  241. /*
  242. * (non-Javadoc)
  243. *
  244. * @see
  245. * jain.protocol.ip.mgcp.JainMgcpListener#processMgcpResponseEvent(jain.
  246. * protocol.ip.mgcp.JainMgcpResponseEvent)
  247. */
  248. public void processMgcpResponseEvent(JainMgcpResponseEvent mgcpResponse) {
  249. int code = mgcpResponse.getReturnCode().getValue();
  250. int objId = mgcpResponse.getObjectIdentifier();
  251. super.testCase.removeCall(mgcpResponse);
  252. switch (this.localFlowState) {
  253. case SENT_CRCX:
  254. // here we wait for answer, we need to send 200 to invite
  255. if (objId == Constants.RESP_CREATE_CONNECTION) {
  256. CreateConnectionResponse ccr = (CreateConnectionResponse) mgcpResponse;
  257. if (99 < code && code < 200) {
  258. // its provisional
  259. } else if (199 < code && code < 300) {
  260. try {
  261. // its success
  262. if (super.endpointIdentifier == null) {
  263. super.endpointIdentifier = ccr
  264. .getSpecificEndpointIdentifier();
  265. }
  266. this.createdConnections++;
  267. // store socket
  268. this.connectToPeer(ccr);
  269. if (this.numberOfConnections != this.createdConnections) {
  270. // we must send crcx again, and again ;)
  271. sendCrCx(super.endpointIdentifier, true);
  272. break;
  273. } else {
  274. ri = provider.getUniqueRequestIdentifier();
  275. NotificationRequest notificationRequest = new NotificationRequest(
  276. this, super.endpointIdentifier, ri);
  277. EventName[] signalRequests = { new EventName(
  278. PackageName.Announcement, MgcpEvent.ann
  279. .withParm(HELLO_WORLD), null) };
  280. notificationRequest
  281. .setSignalRequests(signalRequests);
  282. RequestedAction[] actions = new RequestedAction[] { RequestedAction.NotifyImmediately };
  283. RequestedEvent[] requestedEvents = { new RequestedEvent(
  284. new EventName(PackageName.Announcement,
  285. MgcpEvent.oc, null), actions) };
  286. notificationRequest
  287. .setRequestedEvents(requestedEvents);
  288. // notificationRequest.setTransactionHandle(mgcpProvider.getUniqueTransactionHandler());
  289. NotifiedEntity notifiedEntity = new NotifiedEntity(
  290. super.testCase.getClientTestNodeAddress()
  291. .getHostAddress(), super.testCase
  292. .getClientTestNodeAddress()
  293. .getHostAddress(), super.testCase
  294. .getCallDisplayInterface()
  295. .getLocalPort());
  296. notificationRequest
  297. .setNotifiedEntity(notifiedEntity);
  298. notificationRequest.setTransactionHandle(provider
  299. .getUniqueTransactionHandler());
  300. // We dont care
  301. // super.testCase.addCall(ri, this);
  302. super.testCase.addCall(notificationRequest, this);
  303. super.testCase.addCall(ri.toString(), this);
  304. super.provider
  305. .sendMgcpEvents(new JainMgcpCommandEvent[] { notificationRequest });
  306. // IS this wrong? should we wait unitl notification
  307. // is
  308. // played?
  309. setState(CallState.ESTABILISHED);
  310. this.setLocalFlowState(AnnCallState.SENT_ANN);
  311. }
  312. } catch (Exception ex) {
  313. java.util.logging.Logger.getLogger(
  314. AnnCall.class.getName()).log(Level.SEVERE,
  315. null, ex);
  316. this.setLocalFlowState(AnnCallState.TERMINATED);
  317. setState(CallState.IN_ERROR);
  318. }
  319. } else {
  320. // ADD ERROR
  321. this.setLocalFlowState(AnnCallState.TERMINATED);
  322. setState(CallState.IN_ERROR);
  323. // FIXME: add error dump
  324. logger.error("FAILED[" + this.localFlowState
  325. + "] ON CRCX RESPONSE: "
  326. + buildResponseHeader(mgcpResponse));
  327. }
  328. } else {
  329. // ADD ERROR
  330. this.setLocalFlowState(AnnCallState.TERMINATED);
  331. setState(CallState.IN_ERROR);
  332. // FIXME: add error dump
  333. logger
  334. .error("FAILED[" + this.localFlowState
  335. + "] ON RESPONSE: "
  336. + buildResponseHeader(mgcpResponse));
  337. }
  338. break;
  339. case SENT_ANN:
  340. if (objId == Constants.RESP_NOTIFICATION_REQUEST) {
  341. if (99 < code && code < 200) {
  342. // its provisional
  343. } else if (199 < code && code < 300) {
  344. // its success
  345. } else {
  346. // its error always?
  347. // ADD ERROR
  348. this.setLocalFlowState(AnnCallState.TERMINATED);
  349. setState(CallState.IN_ERROR);
  350. // FIXME: add error dump
  351. logger.error("FAILED[" + this.localFlowState
  352. + "] ON RESPONSE: "
  353. + buildResponseHeader(mgcpResponse));
  354. }
  355. } else {
  356. this.setLocalFlowState(AnnCallState.TERMINATED);
  357. setState(CallState.IN_ERROR);
  358. // FIXME: add error dump
  359. logger.error("FAILED[" + this.localFlowState
  360. + "] ON CRCX RESPONSE: "
  361. + buildResponseHeader(mgcpResponse) + " objId1 = "
  362. + objId);
  363. }
  364. break;
  365. case SENT_DLCX:
  366. if (objId == Constants.RESP_DELETE_CONNECTION) {
  367. if (99 < code && code < 200) {
  368. // its provisional
  369. } else if (199 < code && code < 300) {
  370. // its success
  371. stop();
  372. } else {
  373. // its error always?
  374. // ADD ERROR
  375. this.setLocalFlowState(AnnCallState.TERMINATED);
  376. setState(CallState.IN_ERROR);
  377. // FIXME: add error dump
  378. logger.error("FAILED[" + this.localFlowState
  379. + "] ON DLCX RESPONSE: "
  380. + buildResponseHeader(mgcpResponse));
  381. }
  382. } else {
  383. this.setLocalFlowState(AnnCallState.TERMINATED);
  384. setState(CallState.IN_ERROR);
  385. // FIXME: add error dump
  386. logger.error("FAILED[" + this.localFlowState
  387. + "] ON CRCX RESPONSE: "
  388. + buildResponseHeader(mgcpResponse) + " objId = "
  389. + objId);
  390. }
  391. break;
  392. default:
  393. logger.error("GOT RESPONSE UNKONWN[" + this.localFlowState
  394. + "] ON CRCX RESPONSE: "
  395. + buildResponseHeader(mgcpResponse));
  396. }
  397. }
  398. @Override
  399. public void receive(RtpPacket packet) {
  400. // TODO Auto-generated method stub
  401. }
  402. // //////////////////
  403. // HELPER METHODS //
  404. // //////////////////
  405. protected void initSocket() throws IOException {
  406. if (this.testCase != null && this.testCase.getSocketFactory() != null) {
  407. RtpSocketFactory factory = this.testCase.getSocketFactory();
  408. this.tenativeSocket = factory.createSocket();
  409. tenativeSocket.addListener(this);
  410. }
  411. }
  412. protected void setLocalFlowState(AnnCallState state) {
  413. if (this.localFlowState == state) {
  414. return;
  415. }
  416. // FIXME: add more
  417. this.localFlowState = state;
  418. }
  419. private String buildResponseHeader(JainMgcpResponseEvent response) {
  420. ReturnCode r = response.getReturnCode();
  421. String s = new String(r.getValue() + " "
  422. + response.getTransactionHandle() + " "
  423. + (r.getComment() == null ? "" : r.getComment()) + " "
  424. + this.getMGCPComand(response.getObjectIdentifier()) + "\n");
  425. return s;
  426. }
  427. private String getMGCPComand(int objectIdentifier) {
  428. String cmd = null;
  429. switch (objectIdentifier) {
  430. case Constants.RESP_CREATE_CONNECTION:
  431. cmd = "CRCX";
  432. break;
  433. case Constants.RESP_DELETE_CONNECTION:
  434. cmd = "DLCX";
  435. break;
  436. case Constants.RESP_NOTIFICATION_REQUEST:
  437. cmd = "RQNT";
  438. break;
  439. default:
  440. cmd = "UNKNOWN";
  441. break;
  442. }
  443. return cmd;
  444. }
  445. private void cancelTimeoutHandle() {
  446. if (super.getTimeoutHandle() != null) {
  447. super.getTimeoutHandle().cancel(false);
  448. }
  449. }
  450. private void sendDelete() {
  451. DeleteConnection dlcx = new DeleteConnection(this,
  452. super.endpointIdentifier);
  453. dlcx.setCallIdentifier(this.callIdentifier);
  454. // dlcx.setConnectionIdentifier(this.allocatedConnection);
  455. dlcx.setTransactionHandle(provider.getUniqueTransactionHandler());
  456. super.testCase.addCall(dlcx, this);
  457. // IS this wrong? should we wait unitl notification is played?
  458. this.setLocalFlowState(AnnCallState.SENT_DLCX);
  459. super.provider.sendMgcpEvents(new JainMgcpCommandEvent[] { dlcx });
  460. }
  461. private void connectToPeer(CreateConnectionResponse ccr)
  462. throws SdpParseException, SdpException, UnknownHostException,
  463. IOException {
  464. String connectionId = ccr.getConnectionIdentifier().toString();
  465. this.connectionIdToRtpData
  466. .put(connectionId, new ArrayList<RtpPacket>());
  467. this.connectionIdToSocket.put(connectionId, this.tenativeSocket);
  468. this.tenativeSocket.setConnectionIdentifier(connectionId);
  469. ConnectionDescriptor cd = ccr.getLocalConnectionDescriptor();
  470. SessionDescription sessionDesc = super.testCase.getSdpFactory()
  471. .createSessionDescription(cd.toString());
  472. String cAddress = sessionDesc.getConnection().getAddress();
  473. Vector v = sessionDesc.getMediaDescriptions(true);
  474. MediaDescription md = (MediaDescription) v.get(0);
  475. int port = md.getMedia().getMediaPort();
  476. SocketAddress sa = new InetSocketAddress(InetAddress
  477. .getAllByName(cAddress)[0], port);
  478. // for now we do that like that this will go away with
  479. // rtp socket
  480. tenativeSocket.setPeer(InetAddress.getAllByName(cAddress)[0], port);
  481. tenativeSocket = null;
  482. }
  483. @Override
  484. protected void performGraphs() {
  485. // TODO Auto-generated method stub
  486. }
  487. }