/protocols/ss7/m3ua/impl/src/main/java/org/mobicents/protocols/ss7/m3ua/impl/sg/RemAspFactory.java

http://mobicents.googlecode.com/ · Java · 471 lines · 304 code · 80 blank · 87 comment · 51 complexity · 848982ae4e382a11c1cf92022b58ffa3 MD5 · raw 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.protocols.ss7.m3ua.impl.sg;
  23. import javolution.util.FastList;
  24. import javolution.xml.XMLFormat;
  25. import javolution.xml.stream.XMLStreamException;
  26. import org.apache.log4j.Logger;
  27. import org.mobicents.protocols.ss7.m3ua.M3UAProvider;
  28. import org.mobicents.protocols.ss7.m3ua.impl.As;
  29. import org.mobicents.protocols.ss7.m3ua.impl.Asp;
  30. import org.mobicents.protocols.ss7.m3ua.impl.AspFactory;
  31. import org.mobicents.protocols.ss7.m3ua.impl.AspState;
  32. import org.mobicents.protocols.ss7.m3ua.impl.M3UAManagement;
  33. import org.mobicents.protocols.ss7.m3ua.impl.TransitionState;
  34. import org.mobicents.protocols.ss7.m3ua.impl.fsm.FSM;
  35. import org.mobicents.protocols.ss7.m3ua.impl.fsm.UnknownTransitionException;
  36. import org.mobicents.protocols.ss7.m3ua.message.M3UAMessage;
  37. import org.mobicents.protocols.ss7.m3ua.message.MessageClass;
  38. import org.mobicents.protocols.ss7.m3ua.message.MessageType;
  39. import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPDown;
  40. import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPDownAck;
  41. import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPUp;
  42. import org.mobicents.protocols.ss7.m3ua.message.aspsm.ASPUpAck;
  43. import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPActive;
  44. import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPActiveAck;
  45. import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPInactive;
  46. import org.mobicents.protocols.ss7.m3ua.message.asptm.ASPInactiveAck;
  47. import org.mobicents.protocols.ss7.m3ua.message.transfer.PayloadData;
  48. import org.mobicents.protocols.ss7.m3ua.parameter.ASPIdentifier;
  49. import org.mobicents.protocols.ss7.m3ua.parameter.ErrorCode;
  50. import org.mobicents.protocols.ss7.m3ua.parameter.RoutingContext;
  51. import org.mobicents.protocols.ss7.m3ua.parameter.TrafficModeType;
  52. /**
  53. *
  54. * @author amit bhayani
  55. *
  56. */
  57. public class RemAspFactory extends AspFactory {
  58. private static Logger logger = Logger.getLogger(RemAspFactory.class);
  59. public RemAspFactory(){
  60. super();
  61. }
  62. public RemAspFactory(String name, String ip, int port, M3UAProvider provider, M3UAManagement m3uaManagement) {
  63. super(name, ip, port, provider, m3uaManagement);
  64. }
  65. @Override
  66. public Asp createAsp() {
  67. RemAspImpl remAsp = new RemAspImpl(this.name, this.m3UAProvider, this);
  68. this.aspList.add(remAsp);
  69. return remAsp;
  70. }
  71. @Override
  72. public void read(M3UAMessage message) {
  73. switch (message.getMessageClass()) {
  74. case MessageClass.MANAGEMENT:
  75. switch (message.getMessageType()) {
  76. case MessageType.ERROR:
  77. case MessageType.NOTIFY:
  78. }
  79. break;
  80. case MessageClass.TRANSFER_MESSAGES:
  81. switch (message.getMessageType()) {
  82. case MessageType.PAYLOAD:
  83. PayloadData payload = (PayloadData) message;
  84. this.handlePayload(payload);
  85. break;
  86. default:
  87. break;
  88. }
  89. break;
  90. case MessageClass.SIGNALING_NETWORK_MANAGEMENT:
  91. logger.warn(String.format("Received %s. Handling of SSNM message is not yet implemented", message));
  92. break;
  93. case MessageClass.ASP_STATE_MAINTENANCE:
  94. switch (message.getMessageType()) {
  95. case MessageType.ASP_UP:
  96. ASPUp aspUp = (ASPUp) message;
  97. this.handleAspUp(aspUp);
  98. break;
  99. case MessageType.ASP_DOWN:
  100. // The SGP MUST send an ASP Down Ack message in response to a
  101. // received ASP Down message from the ASP even if the ASP is
  102. // already marked as ASP-DOWN at the SGP.
  103. ASPDown aspDown = (ASPDown) message;
  104. this.handleAspDown(aspDown);
  105. break;
  106. case MessageType.HEARTBEAT:
  107. break;
  108. default:
  109. break;
  110. }
  111. break;
  112. case MessageClass.ASP_TRAFFIC_MAINTENANCE:
  113. // ASPTM should be given to only respective ASP's
  114. switch (message.getMessageType()) {
  115. case MessageType.ASP_ACTIVE:
  116. ASPActive aspActive = (ASPActive) message;
  117. this.handleAspActive(aspActive);
  118. break;
  119. case MessageType.ASP_INACTIVE:
  120. ASPInactive aspInactive = (ASPInactive) message;
  121. this.handleAspInactive(aspInactive);
  122. break;
  123. default:
  124. break;
  125. }
  126. break;
  127. case MessageClass.ROUTING_KEY_MANAGEMENT:
  128. break;
  129. default:
  130. break;
  131. }
  132. }
  133. private void handlePayload(PayloadData payload) {
  134. // Payload is always for single AS
  135. long rc = payload.getRoutingContext().getRoutingContexts()[0];
  136. Asp asp = this.getAsp(rc);
  137. if (asp == null) {
  138. logger.error(String.format("received PayloadData for RoutingContext=%d. But no ASP found. Message=%s", rc,
  139. payload));
  140. return;
  141. }
  142. if (asp.getState() == AspState.ACTIVE) {
  143. asp.getAs().received(payload);
  144. } else {
  145. logger.error(String.format("Received PayloadData for RoutingContext=%d. But ASP State=%s. Message=%s", rc,
  146. asp.getState(), payload));
  147. }
  148. }
  149. private void handleAspDown(ASPDown aspDown) {
  150. ASPDownAck aspDwnAck = (ASPDownAck) this.m3UAProvider.getMessageFactory().createMessage(
  151. MessageClass.ASP_STATE_MAINTENANCE, MessageType.ASP_DOWN_ACK);
  152. this.write(aspDwnAck);
  153. // ASPSM should be given to all ASP's
  154. for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
  155. Asp asp = n.getValue();
  156. try {
  157. // Signal ASP about state change
  158. asp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspDown);
  159. asp.getFSM().signal(TransitionState.ASP_DOWN);
  160. // Signal corresponding AS about ASP's state transition
  161. asp.getAs().aspStateChange(asp, TransitionState.ASP_DOWN);
  162. } catch (UnknownTransitionException e) {
  163. logger.error(e.getMessage(), e);
  164. }
  165. }
  166. }
  167. private void handleAspUp(ASPUp aspUp) {
  168. ASPUpAck aspUpAck = (ASPUpAck) this.m3UAProvider.getMessageFactory().createMessage(
  169. MessageClass.ASP_STATE_MAINTENANCE, MessageType.ASP_UP_ACK);
  170. ASPIdentifier aspId = aspUp.getASPIdentifier();
  171. if (aspId != null) {
  172. aspUpAck.setASPIdentifier(aspId);
  173. }
  174. this.write(aspUpAck);
  175. // If an ASP Up message is received and, internally, the remote ASP is
  176. // in the ASP-ACTIVE state, an ASP Up Ack message is returned, as well
  177. // as an Error message ("Unexpected Message"). In addition, the remote
  178. // ASP state is changed to ASP-INACTIVE in all relevant Application
  179. // Servers, and all registered Routing Keys are considered deregistered.
  180. for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
  181. Asp asp = n.getValue();
  182. // Set the ASPIdentifier for each ASP
  183. asp.setASPIdentifier(aspUp.getASPIdentifier());
  184. if (asp.getState() == AspState.ACTIVE) {
  185. // Check if ASP is in ACTIVE, its error state
  186. this.sendError(ErrorCode.Unexpected_Message, asp.getAs().getRoutingContext());
  187. // break;
  188. }
  189. try {
  190. // Signal ASP about state change
  191. asp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspUp);
  192. asp.getFSM().signal(TransitionState.ASP_UP);
  193. // Signal corresponding AS about ASP's state transition
  194. asp.getAs().aspStateChange(asp, TransitionState.ASP_UP);
  195. } catch (UnknownTransitionException e) {
  196. logger.error(e.getMessage(), e);
  197. }
  198. }
  199. }
  200. private void handleAspInactive(ASPInactive aspInactive) {
  201. long[] rcs = null;
  202. RoutingContext rcObj = aspInactive.getRoutingContext();
  203. if (rcObj == null) {
  204. if (this.aspList.isEmpty()) {
  205. // If the received ASP Inactive message does not contain
  206. // an RC parameter and the RK is not defined (by either
  207. // static configuration or dynamic registration), the
  208. // SGP/IPSP MUST respond with an ERROR message with the
  209. // Error Code "No configured AS for ASP".
  210. this.sendError(ErrorCode.No_Configured_AS_for_ASP, null);
  211. return;
  212. }
  213. // Send ASP Inactive to all ASP's
  214. rcs = new long[this.aspList.size()];
  215. for (int count = 0; count < rcs.length; count++) {
  216. rcs[count] = this.aspList.get(count).getAs().getRoutingContext().getRoutingContexts()[0];
  217. }
  218. } else {
  219. rcs = rcObj.getRoutingContexts();
  220. }
  221. for (long routCntx : rcs) {
  222. RemAspImpl remAsp = this.getAsp(routCntx);
  223. // RemAsp is null means Remote AS is null
  224. if (remAsp == null) {
  225. // If the received ASP Inactive message contains an RC parameter
  226. // that is not defined (by either static configuration or
  227. // dynamic registration), the SGP/IPSP MUST respond with an
  228. // ERROR message with the Error Code "Invalid Routing Context".
  229. RoutingContext rc1 = this.m3UAProvider.getParameterFactory().createRoutingContext(
  230. new long[] { routCntx });
  231. this.sendError(ErrorCode.Invalid_Routing_Context, rc1);
  232. }
  233. As appServer = remAsp.getAs();
  234. ASPInactiveAck aspInactAck = (ASPInactiveAck) this.m3UAProvider.getMessageFactory().createMessage(
  235. MessageClass.ASP_TRAFFIC_MAINTENANCE, MessageType.ASP_INACTIVE_ACK);
  236. aspInactAck.setRoutingContext(appServer.getRoutingContext());
  237. this.write(aspInactAck);
  238. try {
  239. remAsp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspInactive);
  240. remAsp.getFSM().signal(TransitionState.ASP_INACTIVE);
  241. // Signal AS to transition
  242. appServer.aspStateChange(remAsp, TransitionState.ASP_INACTIVE);
  243. } catch (UnknownTransitionException e) {
  244. logger.error(e.getMessage(), e);
  245. }
  246. }
  247. }
  248. private void handleAspActive(ASPActive aspActive) {
  249. RoutingContext rcObj = aspActive.getRoutingContext();
  250. long[] rcs = null;
  251. if (rcObj == null) {
  252. if (this.aspList.isEmpty()) {
  253. // If the RC parameter is not included in the ASP Active
  254. // message and there are no RKs defined, the peer node
  255. // SHOULD respond with and ERROR message with the Error
  256. // Code "Invalid Routing Context".
  257. this.sendError(ErrorCode.Invalid_Routing_Context, null);
  258. // TODO : Shouldn't the ErrorCode be
  259. // ErrorCode.No_Configured_AS_for_ASP?
  260. return;
  261. }
  262. // Send ASP Active to all ASP's
  263. rcs = new long[this.aspList.size()];
  264. for (int count = 0; count < rcs.length; count++) {
  265. rcs[count] = this.aspList.get(count).getAs().getRoutingContext().getRoutingContexts()[0];
  266. }
  267. } else {
  268. rcs = rcObj.getRoutingContexts();
  269. }
  270. TrafficModeType trfModType = aspActive.getTrafficModeType();
  271. for (long routCntx : rcs) {
  272. RemAspImpl remAsp = this.getAsp(routCntx);
  273. // RemAsp is null means Remote AS is null
  274. if (remAsp == null) {
  275. // If the RC parameter is included in the ASP Active message
  276. // and a corresponding RK has not been previously defined
  277. // (by either static configuration or dynamic registration),
  278. // the peer MUST respond with an ERROR message with the
  279. // Error Code "No configured AS for ASP".
  280. RoutingContext rc1 = this.m3UAProvider.getParameterFactory().createRoutingContext(
  281. new long[] { routCntx });
  282. this.sendError(ErrorCode.No_Configured_AS_for_ASP, rc1);
  283. // TODO : Shouldn't is be ErrorCode.Invalid_Routing_Context ?
  284. continue;
  285. }
  286. As appServer = remAsp.getAs();
  287. if (appServer.getTrafficModeType() != null) {
  288. // AppServer has Traffic Mode Type defined check if it
  289. // matches with sent ASP ACTIVE Message
  290. if (trfModType != null && appServer.getTrafficModeType().getMode() != trfModType.getMode()) {
  291. // Traffic Mode Type mismatch. Send Error.
  292. // TODO should send error or drop message?
  293. this.sendError(ErrorCode.Unsupported_Traffic_Mode_Type, appServer.getRoutingContext());
  294. continue;
  295. }
  296. // message doesn't have Traffic Mode Type
  297. } else {
  298. // AppServer Traffic Mode Type is optionally configured via
  299. // management config. If not select the first available in
  300. // AspUp message
  301. if (trfModType == null) {
  302. // Asp UP didn't specify the Traffic Mode either. use
  303. // default which is loadshare
  304. appServer.setDefaultTrafficModeType();
  305. } else {
  306. // Set the Traffic Mode Type passed in ASP ACTIVE
  307. appServer.setTrafficModeType(trfModType);
  308. }
  309. }
  310. ASPActiveAck aspActAck = (ASPActiveAck) this.m3UAProvider.getMessageFactory().createMessage(
  311. MessageClass.ASP_TRAFFIC_MAINTENANCE, MessageType.ASP_ACTIVE_ACK);
  312. aspActAck.setTrafficModeType(appServer.getTrafficModeType());
  313. aspActAck.setRoutingContext(appServer.getRoutingContext());
  314. this.write(aspActAck);
  315. try {
  316. remAsp.getFSM().setAttribute(FSM.ATTRIBUTE_MESSAGE, aspActive);
  317. remAsp.getFSM().signal(TransitionState.ASP_ACTIVE);
  318. // Signal AS to transition
  319. appServer.aspStateChange(remAsp, TransitionState.ASP_ACTIVE);
  320. } catch (UnknownTransitionException e) {
  321. logger.error(e.getMessage(), e);
  322. }
  323. }
  324. }
  325. private RemAspImpl getAsp(long rc) {
  326. for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
  327. Asp asp = n.getValue();
  328. if (asp.getAs().getRoutingContext().getRoutingContexts()[0] == rc) {
  329. return (RemAspImpl) asp;
  330. }
  331. }
  332. return null;
  333. }
  334. private void sendError(int iErrCode, RoutingContext rc) {
  335. // Send Error
  336. org.mobicents.protocols.ss7.m3ua.message.mgmt.Error error = (org.mobicents.protocols.ss7.m3ua.message.mgmt.Error) this.m3UAProvider
  337. .getMessageFactory().createMessage(MessageClass.MANAGEMENT, MessageType.ERROR);
  338. ErrorCode errCode = this.m3UAProvider.getParameterFactory().createErrorCode(iErrCode);
  339. error.setErrorCode(errCode);
  340. error.setRoutingContext(rc);
  341. this.write(error);
  342. }
  343. @Override
  344. public void start() {
  345. this.started = true;
  346. }
  347. @Override
  348. public void stop() {
  349. this.started = false;
  350. }
  351. public void onCommStateChange(CommunicationState state) {
  352. switch (state) {
  353. case UP:
  354. signalAspFsm(TransitionState.COMM_UP);
  355. break;
  356. case SHUTDOWN:
  357. signalAspFsm(TransitionState.COMM_DOWN);
  358. break;
  359. case LOST:
  360. signalAspFsm(TransitionState.COMM_DOWN);
  361. break;
  362. }
  363. }
  364. private void signalAspFsm(String asptransition) {
  365. for (FastList.Node<Asp> n = aspList.head(), end = aspList.tail(); (n = n.getNext()) != end;) {
  366. Asp asp = n.getValue();
  367. try {
  368. asp.getFSM().signal(asptransition);
  369. } catch (UnknownTransitionException e) {
  370. // This should never happen
  371. logger.error(e.getMessage(), e);
  372. }
  373. }
  374. }
  375. /**
  376. * XML Serialization/Deserialization
  377. */
  378. protected static final XMLFormat<RemAspFactory> REM_ASP_FACTORY_XML = new XMLFormat<RemAspFactory>(
  379. RemAspFactory.class) {
  380. @Override
  381. public void read(javolution.xml.XMLFormat.InputElement xml, RemAspFactory remAspFactory)
  382. throws XMLStreamException {
  383. ASP_FACTORY_XML.read(xml, remAspFactory);
  384. }
  385. @Override
  386. public void write(RemAspFactory remAspFactory, javolution.xml.XMLFormat.OutputElement xml)
  387. throws XMLStreamException {
  388. ASP_FACTORY_XML.write(remAspFactory, xml);
  389. }
  390. };
  391. }