PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

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

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