PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/servers/jain-slee/resources/diameter-rf/ra/src/main/java/org/mobicents/slee/resource/diameter/rf/DiameterRfResourceAdaptor.java

http://mobicents.googlecode.com/
Java | 1146 lines | 694 code | 193 blank | 259 comment | 84 complexity | 187400ef2f930e9f709fd4b031995b1b 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. * 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.slee.resource.diameter.rf;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import javax.management.ObjectName;
  26. import javax.naming.OperationNotSupportedException;
  27. import javax.slee.Address;
  28. import javax.slee.facilities.EventLookupFacility;
  29. import javax.slee.facilities.Tracer;
  30. import javax.slee.resource.ActivityFlags;
  31. import javax.slee.resource.ActivityHandle;
  32. import javax.slee.resource.ConfigProperties;
  33. import javax.slee.resource.EventFlags;
  34. import javax.slee.resource.FailureReason;
  35. import javax.slee.resource.FireableEventType;
  36. import javax.slee.resource.InvalidConfigurationException;
  37. import javax.slee.resource.Marshaler;
  38. import javax.slee.resource.ReceivableService;
  39. import javax.slee.resource.ResourceAdaptor;
  40. import javax.slee.resource.ResourceAdaptorContext;
  41. import javax.slee.resource.SleeEndpoint;
  42. import javax.transaction.Transaction;
  43. import net.java.slee.resource.diameter.Validator;
  44. import net.java.slee.resource.diameter.base.CreateActivityException;
  45. import net.java.slee.resource.diameter.base.DiameterActivity;
  46. import net.java.slee.resource.diameter.base.DiameterException;
  47. import net.java.slee.resource.diameter.base.events.DiameterMessage;
  48. import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity;
  49. import net.java.slee.resource.diameter.rf.RfAvpFactory;
  50. import net.java.slee.resource.diameter.rf.RfClientSessionActivity;
  51. import net.java.slee.resource.diameter.rf.RfMessageFactory;
  52. import net.java.slee.resource.diameter.rf.RfProvider;
  53. import net.java.slee.resource.diameter.rf.RfServerSessionActivity;
  54. import net.java.slee.resource.diameter.rf.events.RfAccountingAnswer;
  55. import net.java.slee.resource.diameter.rf.events.RfAccountingRequest;
  56. import org.jboss.mx.util.MBeanServerLocator;
  57. import org.jdiameter.api.Answer;
  58. import org.jdiameter.api.ApplicationId;
  59. import org.jdiameter.api.Avp;
  60. import org.jdiameter.api.AvpDataException;
  61. import org.jdiameter.api.AvpSet;
  62. import org.jdiameter.api.IllegalDiameterStateException;
  63. import org.jdiameter.api.InternalException;
  64. import org.jdiameter.api.Message;
  65. import org.jdiameter.api.Peer;
  66. import org.jdiameter.api.PeerTable;
  67. import org.jdiameter.api.Request;
  68. import org.jdiameter.api.Session;
  69. import org.jdiameter.api.SessionFactory;
  70. import org.jdiameter.api.Stack;
  71. import org.jdiameter.api.auth.ClientAuthSession;
  72. import org.jdiameter.api.auth.ServerAuthSession;
  73. import org.jdiameter.api.rf.ClientRfSession;
  74. import org.jdiameter.api.rf.ServerRfSession;
  75. import org.jdiameter.client.api.ISessionFactory;
  76. import org.jdiameter.client.impl.app.rf.ClientRfSessionImpl;
  77. import org.jdiameter.common.api.app.rf.IRfSessionFactory;
  78. import org.jdiameter.server.impl.app.rf.ServerRfSessionImpl;
  79. import org.mobicents.diameter.stack.DiameterListener;
  80. import org.mobicents.diameter.stack.DiameterStackMultiplexerMBean;
  81. import org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext;
  82. import org.mobicents.slee.resource.diameter.AbstractClusteredDiameterActivityManagement;
  83. import org.mobicents.slee.resource.diameter.DiameterActivityManagement;
  84. import org.mobicents.slee.resource.diameter.LocalDiameterActivityManagement;
  85. import org.mobicents.slee.resource.diameter.ValidatorImpl;
  86. import org.mobicents.slee.resource.diameter.base.DiameterActivityHandle;
  87. import org.mobicents.slee.resource.diameter.base.DiameterActivityImpl;
  88. import org.mobicents.slee.resource.diameter.base.DiameterAvpFactoryImpl;
  89. import org.mobicents.slee.resource.diameter.base.DiameterBaseMarshaler;
  90. import org.mobicents.slee.resource.diameter.base.DiameterMessageFactoryImpl;
  91. import org.mobicents.slee.resource.diameter.base.EventIDFilter;
  92. import org.mobicents.slee.resource.diameter.base.events.DiameterMessageImpl;
  93. import org.mobicents.slee.resource.diameter.base.events.ErrorAnswerImpl;
  94. import org.mobicents.slee.resource.diameter.base.events.ExtensionDiameterMessageImpl;
  95. import org.mobicents.slee.resource.diameter.base.handlers.DiameterRAInterface;
  96. import org.mobicents.slee.resource.diameter.rf.events.RfAccountingAnswerImpl;
  97. import org.mobicents.slee.resource.diameter.rf.events.RfAccountingRequestImpl;
  98. import org.mobicents.slee.resource.diameter.rf.handlers.RfSessionFactory;
  99. /**
  100. * Diameter Rf Resource Adaptor
  101. *
  102. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  103. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  104. */
  105. public class DiameterRfResourceAdaptor implements ResourceAdaptor, DiameterListener, DiameterRAInterface,org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor<String, DiameterActivity> {
  106. private static final long serialVersionUID = 1L;
  107. // Config Properties Names ---------------------------------------------
  108. private static final String ACCT_APPLICATION_IDS = "acctApplicationIds";
  109. // Config Properties Values --------------------------------------------
  110. private List<ApplicationId> acctApplicationIds;
  111. /**
  112. * caches the eventIDs, avoiding lookup in container
  113. */
  114. public final EventIDCache eventIdCache = new EventIDCache();
  115. /**
  116. * tells the RA if an event with a specified ID should be filtered or not
  117. */
  118. private final EventIDFilter eventIDFilter = new EventIDFilter();
  119. /**
  120. * The ResourceAdaptorContext interface is implemented by the SLEE. It provides the Resource
  121. * Adaptor with the required capabilities in the SLEE to execute its work. The ResourceAdaptorCon-
  122. * text object holds references to a number of objects that are of interest to many Resource Adaptors. A
  123. * resource adaptor object is provided with a ResourceAdaptorContext object when the setResour-
  124. * ceAdaptorContext method of the ResourceAdaptor interface is invoked on the resource adaptor
  125. * object.
  126. */
  127. private ResourceAdaptorContext raContext;
  128. /**
  129. * FT/HA version of RA context.
  130. */
  131. private FaultTolerantResourceAdaptorContext<String, DiameterActivity> ftRAContext;
  132. protected DiameterBaseMarshaler marshaler = new DiameterBaseMarshaler();
  133. /**
  134. * The SLEE endpoint defines the contract between the SLEE and the resource
  135. * adaptor that enables the resource adaptor to deliver events
  136. * asynchronously to SLEE endpoints residing in the SLEE. This contract
  137. * serves as a generic contract that allows a wide range of resources to be
  138. * plugged into a SLEE environment via the resource adaptor architecture.
  139. * For further information see JSLEE v1.1 Specification Page 307 The
  140. * sleeEndpoint will be initialized in entityCreated() method.
  141. */
  142. private transient SleeEndpoint sleeEndpoint = null;
  143. /**
  144. * A tracer is represented in the SLEE by the Tracer interface. Notification sources access the Tracer Facil-
  145. * ity through a Tracer object that implements the Tracer interface. A Tracer object can be obtained by
  146. * SBBs via the SbbContext interface, by resource adaptor entities via the ResourceAdaptorContext
  147. * interface, and by profiles via the ProfileContext interface.
  148. */
  149. private Tracer tracer;
  150. // Diameter Specific Properties ----------------------------------------
  151. private Stack stack;
  152. private ObjectName diameterMultiplexerObjectName = null;
  153. private DiameterStackMultiplexerMBean diameterMux = null;
  154. private long activityRemoveDelay = 30000;
  155. // Diameter Base Factories
  156. private DiameterMessageFactoryImpl baseMessageFactory;
  157. private DiameterAvpFactoryImpl baseAvpFactory;
  158. //Rf Specific Factories
  159. private RfMessageFactoryImpl rfMessageFactory;
  160. private RfAvpFactory rfAvpFactory;
  161. private SessionFactory sessionFactory = null;
  162. private IRfSessionFactory rfSessionFactory;
  163. /**
  164. * the EventLookupFacility is used to look up the event id of incoming
  165. * events
  166. */
  167. private transient EventLookupFacility eventLookup = null;
  168. /**
  169. * The list of activities stored in this resource adaptor. If this resource
  170. * adaptor were a distributed and highly available solution, this storage
  171. * were one of the candidates for distribution.
  172. */
  173. //private transient ConcurrentHashMap<ActivityHandle, DiameterActivity> activities = null;
  174. private transient DiameterActivityManagement activities;
  175. /**
  176. * A link to the DiameterProvider which then will be exposed to Sbbs
  177. */
  178. private RfProviderImpl raProvider = null;
  179. /**
  180. * for all events we are interested in knowing when the event failed to be processed
  181. */
  182. private static final int EVENT_FLAGS = getEventFlags();
  183. private static int getEventFlags() {
  184. int eventFlags = EventFlags.REQUEST_EVENT_UNREFERENCED_CALLBACK;
  185. eventFlags = EventFlags.setRequestProcessingFailedCallback(eventFlags);
  186. eventFlags = EventFlags.setRequestProcessingSuccessfulCallback(eventFlags);
  187. return eventFlags;
  188. }
  189. private static final int DEFAULT_ACTIVITY_FLAGS = ActivityFlags.REQUEST_ENDED_CALLBACK;
  190. private static final int MARSHALABLE_ACTIVITY_FLAGS = ActivityFlags.setSleeMayMarshal(DEFAULT_ACTIVITY_FLAGS);
  191. public DiameterRfResourceAdaptor() {
  192. // TODO: Initialize any default values.
  193. }
  194. // Lifecycle methods ---------------------------------------------------
  195. public void setResourceAdaptorContext(ResourceAdaptorContext context) {
  196. this.raContext = context;
  197. this.tracer = context.getTracer("DiameterRfResourceAdaptor");
  198. this.sleeEndpoint = context.getSleeEndpoint();
  199. this.eventLookup = context.getEventLookupFacility();
  200. this.raProvider = new RfProviderImpl(this);
  201. }
  202. public void unsetResourceAdaptorContext() {
  203. this.raContext = null;
  204. this.tracer = null;
  205. this.sleeEndpoint = null;
  206. this.eventLookup = null;
  207. this.raProvider = null;
  208. }
  209. // FT Lifecycle methods ------------------------------------------------
  210. /*
  211. * (non-Javadoc)
  212. * @see org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor#setFaultTolerantResourceAdaptorContext
  213. * (org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptorContext)
  214. */
  215. public void setFaultTolerantResourceAdaptorContext(FaultTolerantResourceAdaptorContext<String, DiameterActivity> ctx) {
  216. this.ftRAContext = ctx;
  217. }
  218. /*
  219. * (non-Javadoc)
  220. * @see org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor#unsetFaultTolerantResourceAdaptorContext()
  221. */
  222. public void unsetFaultTolerantResourceAdaptorContext() {
  223. this.ftRAContext = null;
  224. //clear this.activities ??
  225. }
  226. // FT methods ----------------------------------------------------------
  227. /*
  228. * (non-Javadoc)
  229. * @see org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor#dataRemoved(java.io.Serializable)
  230. */
  231. public void dataRemoved(String arg0) {
  232. this.activities.remove(getActivityHandle(arg0));
  233. }
  234. /* (non-Javadoc)
  235. * @see org.mobicents.slee.resource.cluster.FaultTolerantResourceAdaptor#failOver(java.io.Serializable)
  236. */
  237. public void failOver(String arg0) {
  238. throw new UnsupportedOperationException();
  239. }
  240. public void raActive() {
  241. if(tracer.isFineEnabled()) {
  242. tracer.fine("Diameter Rf RA :: raActive.");
  243. }
  244. try {
  245. if(tracer.isInfoEnabled()) {
  246. tracer.info("Activating Diameter Rf RA Entity");
  247. }
  248. this.diameterMultiplexerObjectName = new ObjectName("diameter.mobicents:service=DiameterStackMultiplexer");
  249. Object object = MBeanServerLocator.locateJBoss().invoke(this.diameterMultiplexerObjectName, "getMultiplexerMBean", new Object[]{}, new String[]{});
  250. if(object instanceof DiameterStackMultiplexerMBean) {
  251. this.diameterMux = (DiameterStackMultiplexerMBean) object;
  252. }
  253. ///this.activities = new ConcurrentHashMap<ActivityHandle, DiameterActivity>();
  254. // Initialize the protocol stack
  255. initStack();
  256. //Init activities mgmt
  257. initActivitiesMgmt();
  258. // Initialize factories
  259. this.baseAvpFactory = new DiameterAvpFactoryImpl();
  260. this.baseMessageFactory = new DiameterMessageFactoryImpl(stack);
  261. this.rfAvpFactory = new RfAvpFactoryImpl();
  262. this.rfMessageFactory = new RfMessageFactoryImpl(baseMessageFactory,null, stack);
  263. // Set the first configured Application-Id as default for message factory
  264. ApplicationId firstAppId = acctApplicationIds.get(0);
  265. ((RfMessageFactoryImpl)this.rfMessageFactory).setApplicationId(firstAppId.getVendorId(), firstAppId.getAcctAppId());
  266. // Register Accounting App Session Factories
  267. this.sessionFactory = this.stack.getSessionFactory();
  268. this.rfSessionFactory = new RfSessionFactory(this,sessionFactory);
  269. ((ISessionFactory) sessionFactory).registerAppFacory(ServerRfSession.class, rfSessionFactory);
  270. ((ISessionFactory) sessionFactory).registerAppFacory(ClientRfSession.class, rfSessionFactory);
  271. }
  272. catch (Exception e) {
  273. tracer.severe("Error Activating Diameter Rf RA Entity", e);
  274. }
  275. }
  276. public void raStopping() {
  277. if(tracer.isFineEnabled()) {
  278. tracer.fine("Diameter Rf RA :: raStopping.");
  279. }
  280. try {
  281. diameterMux.unregisterListener(this);
  282. }
  283. catch (Exception e) {
  284. tracer.severe("Failed to unregister Rf RA from Diameter Mux.", e);
  285. }
  286. //synchronized (this.activities) {
  287. // for (ActivityHandle activityHandle : activities.keySet()) {
  288. // try {
  289. // if(tracer.isInfoEnabled()) {
  290. // tracer.info("Ending activity [" + activityHandle + "]");
  291. // }
  292. //
  293. // activities.get(activityHandle).endActivity();
  294. // }
  295. // catch (Exception e) {
  296. // tracer.severe("Error Deactivating Activity", e);
  297. // }
  298. // }
  299. //}
  300. if(tracer.isInfoEnabled()) {
  301. tracer.info("Diameter Rf RA :: raStopping completed.");
  302. }
  303. }
  304. public void raInactive() {
  305. if(tracer.isFineEnabled()) {
  306. tracer.fine("Diameter Rf RA :: raInactive.");
  307. }
  308. //synchronized (this.activities) {
  309. // activities.clear();
  310. //}
  311. activities = null;
  312. if(tracer.isInfoEnabled()) {
  313. tracer.info("Diameter Rf RA :: raInactive completed.");
  314. }
  315. }
  316. public void raConfigure(ConfigProperties properties) {
  317. parseApplicationIds((String) properties.getProperty(ACCT_APPLICATION_IDS).getValue());
  318. }
  319. private void parseApplicationIds(String appIdsStr) {
  320. if(appIdsStr != null) {
  321. appIdsStr = appIdsStr.replaceAll(" ", "");
  322. String[] appIdsStrings = appIdsStr.split(",");
  323. acctApplicationIds = new ArrayList<ApplicationId>(appIdsStrings.length);
  324. for(String appId : appIdsStrings) {
  325. String[] vendorAndAppId = appId.split(":");
  326. acctApplicationIds.add(ApplicationId.createByAccAppId(Long.valueOf(vendorAndAppId[0]), Long.valueOf(vendorAndAppId[1])));
  327. }
  328. }
  329. }
  330. public void raUnconfigure() {
  331. // Clean up!
  332. this.activities = null;
  333. this.raContext = null;
  334. this.eventLookup = null;
  335. this.raProvider = null;
  336. this.sleeEndpoint = null;
  337. this.stack = null;
  338. }
  339. // Configuration management methods ------------------------------------
  340. public void raVerifyConfiguration(ConfigProperties properties) throws InvalidConfigurationException {
  341. // TODO Auto-generated method stub
  342. }
  343. public void raConfigurationUpdate(ConfigProperties properties) {
  344. // this ra does not support config update while entity is active
  345. }
  346. // Interface access methods --------------------------------------------
  347. public Object getResourceAdaptorInterface(String className) {
  348. // this ra implements a single ra type
  349. return raProvider;
  350. }
  351. /*
  352. * (non-Javadoc)
  353. * @see javax.slee.resource.ResourceAdaptor#getMarshaler()
  354. */
  355. public Marshaler getMarshaler() {
  356. return marshaler;
  357. }
  358. // Event filtering methods ---------------------------------------------
  359. public void serviceActive(ReceivableService serviceInfo) {
  360. eventIDFilter.serviceActive(serviceInfo);
  361. }
  362. public void serviceStopping(ReceivableService serviceInfo) {
  363. eventIDFilter.serviceStopping(serviceInfo);
  364. }
  365. public void serviceInactive(ReceivableService serviceInfo) {
  366. eventIDFilter.serviceInactive(serviceInfo);
  367. }
  368. // Mandatory callback methods ------------------------------------------
  369. public void queryLiveness(ActivityHandle handle) {
  370. tracer.info("Diameter Rf RA :: queryLiveness :: handle[" + handle + "].");
  371. if(!(handle instanceof DiameterActivityHandle)){ return ;}
  372. DiameterActivityImpl activity = (DiameterActivityImpl) activities.get((DiameterActivityHandle)handle);
  373. if (activity != null && !activity.isValid()) {
  374. try {
  375. sleeEndpoint.endActivity(handle);
  376. }
  377. catch (Exception e) {
  378. tracer.severe("Failure ending non-live activity.", e);
  379. }
  380. }
  381. }
  382. public Object getActivity(ActivityHandle handle) {
  383. if(tracer.isFineEnabled()) {
  384. tracer.fine("Diameter Rf RA :: getActivity :: handle[" + handle + "].");
  385. }
  386. if(!(handle instanceof DiameterActivityHandle)){ return null;}
  387. return this.activities.get((DiameterActivityHandle)handle);
  388. }
  389. public ActivityHandle getActivityHandle(Object activity) {
  390. if(tracer.isFineEnabled()) {
  391. tracer.fine("Diameter Rf RA :: getActivityHandle :: activity[" + activity + "].");
  392. }
  393. if (!(activity instanceof DiameterActivity)) {
  394. return null;
  395. }
  396. DiameterActivityImpl inActivity = (DiameterActivityImpl) activity;
  397. return inActivity.getActivityHandle();
  398. }
  399. public void administrativeRemove(ActivityHandle handle) {
  400. // TODO what to do here?
  401. }
  402. // Optional callback methods -------------------------------------------
  403. public void eventProcessingFailed(ActivityHandle handle, FireableEventType eventType, Object event, Address address, ReceivableService service, int flags, FailureReason reason) {
  404. if(tracer.isInfoEnabled()) {
  405. tracer.info("Diameter Rf RA :: eventProcessingFailed :: handle[" + handle + "], eventType[" + eventType + "], event[" + event + "], address[" + address + "], flags[" + flags + "], reason[" + reason + "].");
  406. }
  407. if(!(handle instanceof DiameterActivityHandle)) {
  408. return;
  409. }
  410. processAfterEventDelivery(handle, eventType, event, address, service, flags);
  411. }
  412. public void eventProcessingSuccessful(ActivityHandle handle, FireableEventType eventType, Object event, Address address, ReceivableService service, int flags) {
  413. if(tracer.isInfoEnabled()) {
  414. tracer.info("Diameter Rf RA :: eventProcessingSuccessful :: handle[" + handle + "], eventType[" + eventType + "], event[" + event + "], address[" + address + "], flags[" + flags + "].");
  415. }
  416. if(!(handle instanceof DiameterActivityHandle)) {
  417. return;
  418. }
  419. processAfterEventDelivery(handle, eventType, event, address, service, flags);
  420. }
  421. public void eventUnreferenced(ActivityHandle handle, FireableEventType eventType, Object event, Address address, ReceivableService service, int flags) {
  422. if(tracer.isFineEnabled()) {
  423. tracer.fine("Diameter Rf RA :: eventUnreferenced :: handle[" + handle + "], eventType[" + eventType + "], event[" + event + "], address[" + address + "], service[" + service + "], flags[" + flags + "].");
  424. }
  425. if(!(handle instanceof DiameterActivityHandle)) {
  426. return;
  427. }
  428. processAfterEventDelivery(handle, eventType, event, address, service, flags);
  429. }
  430. private void processAfterEventDelivery(ActivityHandle handle, FireableEventType eventType, Object event, Address address, ReceivableService service,
  431. int flags) {
  432. DiameterActivityImpl activity = (DiameterActivityImpl) getActivity(handle);
  433. if (activity != null) {
  434. synchronized (activity) {
  435. if (activity.isTerminateAfterProcessing()) {
  436. activity.endActivity();
  437. }
  438. }
  439. }
  440. }
  441. public void activityEnded(ActivityHandle handle) {
  442. tracer.info("Diameter Rf RA :: activityEnded :: handle[" + handle + ".");
  443. if(!(handle instanceof DiameterActivityHandle)){ return ;}
  444. if(this.activities != null) {
  445. synchronized (this.activities) {
  446. this.activities.remove((DiameterActivityHandle)handle);
  447. }
  448. }
  449. }
  450. public void activityUnreferenced(ActivityHandle handle) {
  451. if(tracer.isFineEnabled()) {
  452. tracer.fine("Diameter Rf RA :: activityUnreferenced :: handle[" + handle + "].");
  453. }
  454. //this.activityEnded(handle);
  455. if(handle instanceof DiameterActivityHandle) {
  456. this.endActivity((DiameterActivityHandle) handle);
  457. }
  458. }
  459. // Event and Activities management -------------------------------------
  460. public boolean fireEvent(Object event, ActivityHandle handle, FireableEventType eventID, Address address, boolean useFiltering, boolean transacted) {
  461. if (useFiltering && eventIDFilter.filterEvent(eventID)) {
  462. if (tracer.isFineEnabled()) {
  463. tracer.fine("Event " + eventID + " filtered");
  464. }
  465. }
  466. else if (eventID == null) {
  467. tracer.severe("Event ID for " + eventID + " is unknown, unable to fire.");
  468. }
  469. else {
  470. if (tracer.isFineEnabled()) {
  471. tracer.fine("Firing event " + event + " on handle " + handle);
  472. }
  473. try {
  474. /* TODO: Support transacted fire of events when in cluster
  475. if (transacted){
  476. this.raContext.getSleeEndpoint().fireEventTransacted(handle, eventID, event, address, null, EVENT_FLAGS);
  477. }
  478. else */{
  479. //fetch state for Server Activities
  480. Object o = getActivity(handle);
  481. if(o == null) {
  482. Transaction t = raContext.getSleeTransactionManager().getTransaction();
  483. throw new IllegalStateException("TX[ "+t+" ] No activity for handle: "+handle);
  484. }
  485. if(o instanceof RfServerSessionActivityImpl && event instanceof RfAccountingRequest) {
  486. ((RfServerSessionActivityImpl)o).fetchSessionData((RfAccountingRequest)event,true);
  487. }
  488. this.raContext.getSleeEndpoint().fireEvent(handle, eventID, event, address, null, EVENT_FLAGS);
  489. }
  490. return true;
  491. }
  492. catch (Exception e) {
  493. tracer.severe("Error firing event.", e);
  494. }
  495. }
  496. return false;
  497. }
  498. /**
  499. * {@inheritDoc}
  500. */
  501. @Override
  502. public void endActivity(DiameterActivityHandle arg0) {
  503. this.sleeEndpoint.endActivity(arg0);
  504. }
  505. /**
  506. * {@inheritDoc}
  507. */
  508. @Override
  509. public void startActivityRemoveTimer(DiameterActivityHandle handle) {
  510. this.activities.startActivityRemoveTimer(handle);
  511. }
  512. /**
  513. * {@inheritDoc}
  514. */
  515. @Override
  516. public void stopActivityRemoveTimer(DiameterActivityHandle handle) {
  517. this.activities.stopActivityRemoveTimer(handle);
  518. }
  519. /**
  520. * {@inheritDoc}
  521. */
  522. @Override
  523. public void update(DiameterActivityHandle arg0, DiameterActivity arg1) {
  524. this.activities.update(arg0, arg1);
  525. }
  526. /*
  527. * (non-Javadoc)
  528. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#fireEvent(java.lang.String, org.jdiameter.api.Request, org.jdiameter.api.Answer)
  529. */
  530. public void fireEvent(String sessionId, Message message) {
  531. DiameterMessage event = (DiameterMessage) createEvent(message);
  532. FireableEventType eventId = eventIdCache.getEventId(eventLookup, message);
  533. this.fireEvent(event, getActivityHandle(sessionId), eventId, null, true, message.isRequest());
  534. }
  535. /**
  536. * Create Event object from a JDiameter message (request or answer)
  537. *
  538. * @return a DiameterMessage object wrapping the request/answer
  539. * @throws OperationNotSupportedException
  540. */
  541. private DiameterMessage createEvent(Message message) {
  542. if (message == null) {
  543. throw new NullPointerException("Message argument cannot be null while creating event.");
  544. }
  545. int commandCode = message.getCommandCode();
  546. if (message.isError()) {
  547. return new ErrorAnswerImpl(message);
  548. }
  549. boolean isRequest = message.isRequest();
  550. switch (commandCode) {
  551. case RfAccountingAnswer.commandCode: // ACR/ACA
  552. return isRequest ? new RfAccountingRequestImpl(message) : new RfAccountingAnswerImpl(message);
  553. default:
  554. return new ExtensionDiameterMessageImpl(message);
  555. }
  556. }
  557. // Session Management --------------------------------------------------
  558. /**
  559. * Method for performing tasks when activity is created, such as informing SLEE about it and storing into internal map.
  560. *
  561. * @param ac the activity that has been created
  562. */
  563. private void addActivity(DiameterActivity ac, boolean suspended) {
  564. try {
  565. // Inform SLEE that Activity Started
  566. DiameterActivityImpl activity = (DiameterActivityImpl) ac;
  567. if (suspended) {
  568. sleeEndpoint.startActivitySuspended(activity.getActivityHandle(), activity, MARSHALABLE_ACTIVITY_FLAGS);
  569. }
  570. else {
  571. sleeEndpoint.startActivity(activity.getActivityHandle(), activity, MARSHALABLE_ACTIVITY_FLAGS);
  572. }
  573. // Set the listener
  574. activity.setSessionListener(this);
  575. // Put it into our activities map
  576. activities.put(activity.getActivityHandle(), activity);
  577. if(tracer.isInfoEnabled()) {
  578. tracer.info("Activity started [" + activity.getActivityHandle() + "]");
  579. }
  580. }
  581. catch (Exception e) {
  582. tracer.severe("Error creating activity", e);
  583. throw new RuntimeException("Error creating activity", e);
  584. }
  585. }
  586. // Private Methods -----------------------------------------------------
  587. /**
  588. * Initializes the RA Diameter Stack.
  589. *
  590. * @throws Exception
  591. */
  592. private synchronized void initStack() throws Exception {
  593. // Register in the Mux as an app listener.
  594. this.diameterMux.registerListener(this, getSupportedApplications());
  595. // Get the stack (should not mess with)
  596. this.stack = this.diameterMux.getStack();
  597. if(tracer.isInfoEnabled()) {
  598. tracer.info("Diameter Rf RA :: Successfully initialized stack.");
  599. }
  600. }
  601. private void initActivitiesMgmt() {
  602. final DiameterRAInterface lst = this;
  603. if (this.ftRAContext.isLocal()) {
  604. if(tracer.isInfoEnabled()) {
  605. tracer.info(raContext.getEntityName() + " -- running in LOCAL mode.");
  606. }
  607. this.activities = new LocalDiameterActivityManagement(this.raContext, activityRemoveDelay);
  608. }
  609. else {
  610. tracer.info(raContext.getEntityName() + " -- running in CLUSTER mode.");
  611. final org.mobicents.slee.resource.cluster.ReplicatedData<String, DiameterActivity> clusteredData = this.ftRAContext.getReplicateData(true);
  612. // get special one
  613. this.activities = new AbstractClusteredDiameterActivityManagement(this.ftRAContext, activityRemoveDelay,this.raContext.getTracer(""), stack, this.raContext.getSleeTransactionManager(), clusteredData) {
  614. @Override
  615. protected void performBeforeReturn(DiameterActivityImpl activity) {
  616. // do all the dirty work;
  617. try {
  618. Session session = null;
  619. if (activity.getClass().equals(DiameterActivityImpl.class)) {
  620. // check as first. since it requires session recreation.
  621. // JIC: is this required?
  622. session = this.diameterStack.getSessionFactory().getNewSession(activity.getSessionId());
  623. performBeforeReturnOnBase(activity, session);
  624. return;
  625. }
  626. else if (activity instanceof RfServerSessionActivity) {
  627. RfServerSessionActivityImpl acc = (RfServerSessionActivityImpl) activity;
  628. ServerRfSession appSession = this.diameterStack.getSession(activity.getSessionId(), ServerRfSession.class);
  629. session = appSession.getSessions().get(0);
  630. performBeforeReturnOnBase(activity, session);
  631. performBeforeReturnRf(acc);
  632. acc.setSession(appSession);
  633. }
  634. else if (activity instanceof RfClientSessionActivity) {
  635. RfClientSessionActivityImpl acc = (RfClientSessionActivityImpl) activity;
  636. ClientRfSession appSession = this.diameterStack.getSession(activity.getSessionId(), ClientRfSession.class);
  637. session = appSession.getSessions().get(0);
  638. performBeforeReturnOnBase(activity, session);
  639. performBeforeReturnRf(acc);
  640. acc.setSession(appSession);
  641. }
  642. else {
  643. throw new IllegalArgumentException("Unknown activity type: " + activity);
  644. }
  645. }
  646. catch (Exception e) {
  647. throw new DiameterException(e);
  648. }
  649. }
  650. private void performBeforeReturnOnBase(DiameterActivityImpl ac, Session session) {
  651. DiameterMessageFactoryImpl msgFactory = new DiameterMessageFactoryImpl(session, stack, new DiameterIdentity[] {});
  652. ac.setAvpFactory(baseAvpFactory);
  653. ac.setMessageFactory(msgFactory);
  654. ac.setCurrentWorkingSession(session);
  655. ac.setSessionListener(lst);
  656. }
  657. private void performBeforeReturnRf(RfClientSessionActivityImpl ac) {
  658. // we just have to set factory
  659. RfMessageFactoryImpl rfMessageFactory = new RfMessageFactoryImpl(baseMessageFactory, ac.getSessionId(),stack);
  660. // Set the first configured Application-Id as default for message factory
  661. ApplicationId firstAppId = acctApplicationIds.get(0);
  662. rfMessageFactory.setApplicationId(firstAppId.getVendorId(), firstAppId.getAcctAppId());
  663. ac.setRfMessageFactory(rfMessageFactory);
  664. }
  665. private void performBeforeReturnRf(RfServerSessionActivityImpl ac) {
  666. // we just have to set factory
  667. RfMessageFactoryImpl rfMessageFactory = new RfMessageFactoryImpl(baseMessageFactory,ac.getSessionId(), stack);
  668. // Set the first configured Application-Id as default for message factory
  669. ApplicationId firstAppId = acctApplicationIds.get(0);
  670. rfMessageFactory.setApplicationId(firstAppId.getVendorId(), firstAppId.getAcctAppId());
  671. ac.setRfMessageFactory(rfMessageFactory);
  672. }
  673. @Override
  674. public DiameterActivity get(DiameterActivityHandle handle) {
  675. return super.get(handle);
  676. }
  677. @Override
  678. public void put(DiameterActivityHandle handle, DiameterActivity activity) {
  679. super.put(handle, activity);
  680. }
  681. @Override
  682. public DiameterActivity remove(DiameterActivityHandle handle) {
  683. return super.remove(handle);
  684. }
  685. };
  686. }
  687. }
  688. /**
  689. * Create the Diameter Activity Handle for an given session id
  690. *
  691. * @param sessionId the session identifier to create the activity handle from
  692. * @return a DiameterActivityHandle for the provided sessionId
  693. */
  694. protected DiameterActivityHandle getActivityHandle(String sessionId) {
  695. return new DiameterActivityHandle(sessionId);
  696. }
  697. // NetworkReqListener Implementation -----------------------------------
  698. /*
  699. * (non-Javadoc)
  700. * @see org.jdiameter.api.NetworkReqListener#processRequest(org.jdiameter.api.Request)
  701. */
  702. public Answer processRequest(Request request) {
  703. DiameterActivityImpl activity;
  704. try {
  705. activity = (DiameterActivityImpl) raProvider.createActivity(request);
  706. if(activity instanceof RfServerSessionActivityImpl) {
  707. RfServerSessionActivityImpl assai = (RfServerSessionActivityImpl)activity;
  708. ((ServerRfSessionImpl)assai.getSession()).processRequest(request);
  709. }
  710. else if(activity instanceof RfClientSessionActivityImpl) {
  711. RfClientSessionActivityImpl assai = (RfClientSessionActivityImpl)activity;
  712. ((ClientRfSessionImpl)assai.getSession()).processRequest(request);
  713. }
  714. }
  715. catch (CreateActivityException e) {
  716. tracer.severe("Failure trying to create Rf Activity.", e);
  717. }
  718. // returning null so we can answer later
  719. return null;
  720. }
  721. /*
  722. * (non-Javadoc)
  723. * @see org.jdiameter.api.EventListener#receivedSuccessMessage(org.jdiameter.api.Message, org.jdiameter.api.Message)
  724. */
  725. public void receivedSuccessMessage(Request request, Answer answer) {
  726. if(tracer.isFineEnabled()) {
  727. tracer.fine("Diameter Rf RA :: receivedSuccessMessage :: " + "Request[" + request + "], Answer[" + answer + "].");
  728. }
  729. tracer.warning("Resource Adaptor should not receive this (receivedSuccessMessage), a session should exist to handle it.");
  730. try {
  731. if(tracer.isInfoEnabled()) {
  732. tracer.info("Received Message Result-Code: " + answer.getResultCode().getUnsigned32());
  733. }
  734. }
  735. catch (AvpDataException ignore) {
  736. // ignore, this was just for informational purposes...
  737. }
  738. }
  739. /*
  740. * (non-Javadoc)
  741. * @see org.jdiameter.api.EventListener#timeoutExpired(org.jdiameter.api.Message)
  742. */
  743. public void timeoutExpired(Request request) {
  744. if(tracer.isInfoEnabled()) {
  745. tracer.info("Diameter Rf RA :: timeoutExpired :: " + "Request[" + request + "].");
  746. }
  747. tracer.warning("Resource Adaptor should not receive this (timeoutExpired), a session should exist to handle it.");
  748. try {
  749. // Message delivery timed out - we have to remove activity
  750. ((DiameterActivity) getActivity(getActivityHandle(request.getSessionId()))).endActivity();
  751. }
  752. catch (Exception e) {
  753. tracer.severe("Failure processing timeout message.", e);
  754. }
  755. }
  756. // Rf Session Creation Listener --------------------------------------
  757. /*
  758. * (non-Javadoc)
  759. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#sessionCreated(org.jdiameter.api.acc.ClientAccSession)
  760. */
  761. public void sessionCreated(ClientRfSession session) {
  762. RfClientSessionActivityImpl activity = new RfClientSessionActivityImpl(rfMessageFactory, rfAvpFactory, session, null, null,stack);
  763. activity.setSessionListener(this);
  764. session.addStateChangeNotification(activity);
  765. addActivity(activity, false /*true*/);
  766. }
  767. /*
  768. * (non-Javadoc)
  769. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#sessionCreated(org.jdiameter.api.acc.ServerAccSession)
  770. */
  771. public void sessionCreated(ServerRfSession session) {
  772. RfServerSessionActivityImpl activity = new RfServerSessionActivityImpl(rfMessageFactory, rfAvpFactory, session, null, null, stack);
  773. session.addStateChangeNotification(activity);
  774. activity.setSessionListener(this);
  775. addActivity(activity, false);
  776. }
  777. /*
  778. * (non-Javadoc)
  779. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#sessionCreated(org.jdiameter.api.auth.ServerAuthSession)
  780. */
  781. public void sessionCreated(ServerAuthSession session) {
  782. tracer.severe("Unexpected Auth Session at Rf Resource Adaptor.");
  783. }
  784. /*
  785. * (non-Javadoc)
  786. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#sessionCreated(org.jdiameter.api.auth.ClientAuthSession)
  787. */
  788. public void sessionCreated(ClientAuthSession session) {
  789. tracer.severe("Unexpected Auth Session at Rf Resource Adaptor.");
  790. }
  791. /*
  792. * (non-Javadoc)
  793. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#sessionExists(java.lang.String)
  794. */
  795. public boolean sessionExists(String sessionId) {
  796. return this.activities.containsKey(getActivityHandle(sessionId));
  797. }
  798. /*
  799. * (non-Javadoc)
  800. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#sessionDestroyed(java.lang.String, java.lang.Object)
  801. */
  802. public void sessionDestroyed(String sessionId, Object appSession) {
  803. try {
  804. this.sleeEndpoint.endActivity(getActivityHandle(sessionId));
  805. }
  806. catch (Exception e) {
  807. tracer.severe("Failure Ending Activity with Session-Id[" + sessionId + "]", e);
  808. }
  809. }
  810. /*
  811. * (non-Javadoc)
  812. * @see org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener#getSupportedApplications()
  813. */
  814. public ApplicationId[] getSupportedApplications() {
  815. return (ApplicationId[]) acctApplicationIds.toArray(new ApplicationId[acctApplicationIds.size()]);
  816. }
  817. // Provider Implementation ---------------------------------------------
  818. private class RfProviderImpl implements RfProvider {
  819. protected DiameterRfResourceAdaptor ra;
  820. protected Validator validator = new ValidatorImpl();
  821. /**
  822. * Constructor.
  823. *
  824. * @param rfResourceAdaptor The resource adaptor for this Provider.
  825. */
  826. public RfProviderImpl(DiameterRfResourceAdaptor rfResourceAdaptor) {
  827. this.ra = rfResourceAdaptor;
  828. }
  829. private DiameterActivity createActivity(Message message) throws CreateActivityException {
  830. DiameterActivity activity = activities.get(getActivityHandle(message.getSessionId()));
  831. if (activity == null) {
  832. if (message.isRequest()) {
  833. return createRfServerSessionActivity((Request) message);
  834. }
  835. else {
  836. AvpSet avps = message.getAvps();
  837. Avp avp = null;
  838. DiameterIdentity destinationHost = null;
  839. DiameterIdentity destinationRealm = null;
  840. if ((avp = avps.getAvp(Avp.DESTINATION_HOST)) != null) {
  841. try {
  842. destinationHost = new DiameterIdentity(avp.getDiameterIdentity());
  843. }
  844. catch (AvpDataException e) {
  845. tracer.severe("Failed to extract Destination-Host from Message.", e);
  846. }
  847. }
  848. if ((avp = avps.getAvp(Avp.DESTINATION_REALM)) != null) {
  849. try {
  850. destinationRealm = new DiameterIdentity(avp.getDiameterIdentity());
  851. }
  852. catch (AvpDataException e) {
  853. tracer.severe("Failed to extract Destination-Realm from Message.", e);
  854. }
  855. }
  856. return createRfClientSessionActivity(destinationHost, destinationRealm);
  857. }
  858. }
  859. return activity;
  860. }
  861. private DiameterActivity createRfServerSessionActivity(Request request) throws CreateActivityException {
  862. ServerRfSession session = null;
  863. try {
  864. ApplicationId appId = request.getApplicationIdAvps().isEmpty() ? null : request.getApplicationIdAvps().iterator().next();
  865. session = ((ISessionFactory) stack.getSessionFactory()).getNewAppSession(request.getSessionId(), appId, ServerRfSession.class, request);
  866. if (session == null) {
  867. throw new CreateActivityException("Got NULL Session while creating Server Accounting Activity");
  868. }
  869. sessionCreated(session);
  870. }
  871. catch (InternalException e) {
  872. throw new CreateActivityException("Internal exception while creating Server Accounting Activity", e);
  873. }
  874. catch (IllegalDiameterStateException e) {
  875. throw new CreateActivityException("Illegal Diameter State exception while creating Server Accounting Activity", e);
  876. }
  877. return (RfServerSessionActivityImpl) activities.get(getActivityHandle(session.getSessions().get(0).getSessionId()));
  878. }
  879. // Actual Provider Methods
  880. public RfClientSessionActivity createRfClientSessionActivity() throws CreateActivityException {
  881. return createRfClientSessionActivity(null, null);
  882. }
  883. public RfClientSessionActivity createRfClientSessionActivity(DiameterIdentity destinationHost, DiameterIdentity destinationRealm) throws CreateActivityException {
  884. try {
  885. ClientRfSession session = ((ISessionFactory) stack.getSessionFactory()).getNewAppSession(null, acctApplicationIds.get(0), ClientRfSession.class);
  886. if (session == null) {
  887. throw new CreateActivityException("Got NULL Session while creating Client Accounting Activity");
  888. }
  889. sessionCreated(session);
  890. return new RfClientSessionActivityImpl(rfMessageFactory, rfAvpFactory, session, destinationHost, destinationRealm, stack);
  891. }
  892. catch (Exception e) {
  893. throw new CreateActivityException("Internal exception while creating Client Accounting Activity", e);
  894. }
  895. }
  896. public RfMessageFactory getRfMessageFactory() {
  897. return ra.rfMessageFactory;
  898. }
  899. public RfAvpFactory getRfAvpFactory() {
  900. return ra.rfAvpFactory;
  901. }
  902. public RfAccountingAnswer sendRfAccountingRequest(RfAccountingRequest accountingRequest) {
  903. try {
  904. DiameterActivityImpl activity = (DiameterActivityImpl) getActivity(getActivityHandle(accountingRequest.getSessionId()));
  905. if (activity == null) {
  906. activity = (DiameterActivityImpl) createActivity(((DiameterMessageImpl)accountingRequest).getGenericData());
  907. }
  908. return (RfAccountingAnswer) activity.sendSyncMessage(accountingRequest);
  909. }
  910. catch (Exception e) {
  911. tracer.severe("Failure sending sync request.", e);
  912. }
  913. // FIXME Throw unknown message exception?
  914. return null;
  915. }
  916. public DiameterIdentity[] getConnectedPeers() {
  917. return ra.getConnectedPeers();
  918. }
  919. public int getPeerCount() {
  920. return ra.getConnectedPeers().length;
  921. }
  922. /* (non-Javadoc)
  923. * @see net.java.slee.resource.diameter.rf.RfProvider#getValidator()
  924. */
  925. @Override
  926. public Validator getValidator() {
  927. return this.validator;
  928. }
  929. }
  930. /**
  931. * @return
  932. */
  933. public DiameterIdentity[] getConnectedPeers() {
  934. if (this.stack != null) {
  935. try {
  936. // Get the list of peers from the stack
  937. List<Peer> peers = stack.unwrap(PeerTable.class).getPeerTable();
  938. DiameterIdentity[] result = new DiameterIdentity[peers.size()];
  939. int i = 0;
  940. // Get each peer from the list and make a DiameterIdentity
  941. for (Peer peer : peers) {
  942. DiameterIdentity identity = new DiameterIdentity(peer.getUri().toString());
  943. result[i++] = identity;
  944. }
  945. return result;
  946. }
  947. catch (Exception e) {
  948. tracer.severe("Failure getting peer list.", e);
  949. }
  950. }
  951. return new DiameterIdentity[0];
  952. }
  953. }