PageRenderTime 74ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/jain-slee/resources/diameter-gq/ra/src/main/java/org/mobicents/slee/resource/diameter/gq/DiameterGqResourceAdaptor.java

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