PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/MutablePeerTableImpl.java

http://mobicents.googlecode.com/
Java | 694 lines | 587 code | 59 blank | 48 comment | 108 complexity | fdcecf2132ace1b95f99584f3a16550e 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 2006, 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.jdiameter.server.impl;
  23. import static org.jdiameter.client.impl.helpers.Parameters.PeerName;
  24. import static org.jdiameter.client.impl.helpers.Parameters.PeerTable;
  25. import static org.jdiameter.client.impl.helpers.Parameters.StopTimeOut;
  26. import static org.jdiameter.client.impl.helpers.Parameters.UseUriAsFqdn;
  27. import static org.jdiameter.common.api.concurrent.IConcurrentFactory.ScheduledExecServices.ConnectionTimer;
  28. import static org.jdiameter.common.api.concurrent.IConcurrentFactory.ScheduledExecServices.DuplicationMessageTimer;
  29. import static org.jdiameter.common.api.concurrent.IConcurrentFactory.ScheduledExecServices.PeerOverloadTimer;
  30. import static org.jdiameter.server.impl.helpers.Parameters.AcceptUndefinedPeer;
  31. import static org.jdiameter.server.impl.helpers.Parameters.DuplicateProtection;
  32. import static org.jdiameter.server.impl.helpers.Parameters.DuplicateSize;
  33. import static org.jdiameter.server.impl.helpers.Parameters.DuplicateTimer;
  34. import static org.jdiameter.server.impl.helpers.Parameters.PeerAttemptConnection;
  35. import java.io.IOException;
  36. import java.net.URISyntaxException;
  37. import java.net.UnknownServiceException;
  38. import java.util.Collection;
  39. import java.util.HashSet;
  40. import java.util.Iterator;
  41. import java.util.List;
  42. import java.util.Map;
  43. import java.util.Set;
  44. import java.util.concurrent.ConcurrentHashMap;
  45. import java.util.concurrent.CopyOnWriteArraySet;
  46. import java.util.concurrent.ScheduledExecutorService;
  47. import java.util.concurrent.ScheduledFuture;
  48. import java.util.concurrent.TimeUnit;
  49. import org.jdiameter.api.Avp;
  50. import org.jdiameter.api.AvpDataException;
  51. import org.jdiameter.api.Configuration;
  52. import org.jdiameter.api.ConfigurationListener;
  53. import org.jdiameter.api.DisconnectCause;
  54. import org.jdiameter.api.IllegalDiameterStateException;
  55. import org.jdiameter.api.InternalException;
  56. import org.jdiameter.api.Message;
  57. import org.jdiameter.api.MetaData;
  58. import org.jdiameter.api.MutableConfiguration;
  59. import org.jdiameter.api.MutablePeerTable;
  60. import org.jdiameter.api.Network;
  61. import org.jdiameter.api.Peer;
  62. import org.jdiameter.api.PeerTableListener;
  63. import org.jdiameter.api.Realm;
  64. import org.jdiameter.api.Statistic;
  65. import org.jdiameter.api.URI;
  66. import org.jdiameter.client.api.IContainer;
  67. import org.jdiameter.client.api.IMessage;
  68. import org.jdiameter.client.api.ISessionFactory;
  69. import org.jdiameter.client.api.StackState;
  70. import org.jdiameter.client.api.controller.IRealm;
  71. import org.jdiameter.client.api.fsm.EventTypes;
  72. import org.jdiameter.client.api.io.IConnection;
  73. import org.jdiameter.client.api.io.IConnectionListener;
  74. import org.jdiameter.client.api.io.TransportException;
  75. import org.jdiameter.client.api.parser.IMessageParser;
  76. import org.jdiameter.client.impl.controller.PeerTableImpl;
  77. import org.jdiameter.common.api.concurrent.IConcurrentFactory;
  78. import org.jdiameter.common.api.statistic.IStatisticManager;
  79. import org.jdiameter.server.api.IFsmFactory;
  80. import org.jdiameter.server.api.IMutablePeerTable;
  81. import org.jdiameter.server.api.INetwork;
  82. import org.jdiameter.server.api.IOverloadManager;
  83. import org.jdiameter.server.api.IPeer;
  84. import org.jdiameter.server.api.io.INetworkConnectionListener;
  85. import org.jdiameter.server.api.io.INetworkGuard;
  86. import org.jdiameter.server.api.io.ITransportLayerFactory;
  87. import org.jdiameter.server.impl.helpers.EmptyConfiguration;
  88. import org.slf4j.Logger;
  89. import org.slf4j.LoggerFactory;
  90. /**
  91. *
  92. * @author erick.svenson@yahoo.com
  93. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  94. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  95. */
  96. public class MutablePeerTableImpl extends PeerTableImpl implements IMutablePeerTable, ConfigurationListener {
  97. private static final Logger logger = LoggerFactory.getLogger(MutablePeerTableImpl.class);
  98. private static final int CONN_INVALIDATE_PERIOD = 60000;
  99. protected Configuration config;
  100. protected ISessionFactory sessionFactory;
  101. protected IFsmFactory fsmFactory;
  102. protected ITransportLayerFactory transportFactory;
  103. protected IMessageParser parser;
  104. protected org.jdiameter.server.api.IRouter router;
  105. // Duplicate handling -------------------------------------------------------
  106. protected boolean duplicateProtection = false;
  107. protected int duplicateSize;
  108. protected long duplicateTimer;
  109. protected ScheduledExecutorService duplicationScheduler = null;
  110. protected ScheduledFuture duplicationHandler = null;
  111. protected ConcurrentHashMap<String, StorageEntry> storageAnswers = new ConcurrentHashMap<String, StorageEntry>();
  112. protected boolean isAcceptUndefinedPeer = false;
  113. // Connections handling -----------------------------------------------------
  114. private ConcurrentHashMap<String, IConnection> incConnections;
  115. private ScheduledExecutorService connScheduler;
  116. private ScheduledFuture connHandler;
  117. // Network management -------------------------------------------------------
  118. protected INetworkGuard networkGuard;
  119. protected INetwork network;
  120. protected Set<String> predefinedPeerTable;
  121. // Overload handling --------------------------------------------------------
  122. protected IOverloadManager ovrManager;
  123. protected ScheduledExecutorService overloadScheduler = null;
  124. protected ScheduledFuture overloadHandler = null;
  125. protected PeerTableListener peerTableListener = null;
  126. protected IStatisticManager statisticFactory;
  127. private IContainer stack;
  128. protected class StorageEntry {
  129. private String duplicationKey;
  130. private long time = System.currentTimeMillis();
  131. private IMessage answer;
  132. public StorageEntry(IMessage message) {
  133. answer = message;
  134. // duplicationKey = message.getDuplicationKey(); doesn't work because it's answer
  135. String[] originInfo = router.getRequestRouteInfo(answer.getHopByHopIdentifier());
  136. duplicationKey = message.getDuplicationKey(originInfo[0], message.getEndToEndIdentifier());
  137. }
  138. public IMessage getMessage() {
  139. return answer;
  140. }
  141. public long getTime() {
  142. return time;
  143. }
  144. public String getDuplicationKey() {
  145. return duplicationKey;
  146. }
  147. }
  148. public MutablePeerTableImpl(Configuration config, MetaData metaData,IContainer stack, org.jdiameter.server.api.IRouter router,
  149. ISessionFactory sessionFactory, IFsmFactory fsmFactory, ITransportLayerFactory trFactory,
  150. IMessageParser parser, INetwork network, IOverloadManager ovrManager,
  151. IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory) {
  152. logger.debug("MutablePeerTableImpl is being created");
  153. this.metaData = metaData;
  154. this.config = config;
  155. this.router = router;
  156. this.sessionFactory = sessionFactory;
  157. this.statisticFactory = statisticFactory;
  158. this.concurrentFactory = concurrentFactory;
  159. this.fsmFactory = fsmFactory;
  160. this.transportFactory = trFactory;
  161. this.parser = parser;
  162. this.network = network;
  163. this.ovrManager = ovrManager;
  164. this.network.setPeerManager(this);
  165. this.stack = stack;
  166. this.isAcceptUndefinedPeer = config.getBooleanValue(AcceptUndefinedPeer.ordinal(), false);
  167. this.duplicateProtection = config.getBooleanValue(DuplicateProtection.ordinal(), (Boolean) DuplicateProtection.defValue());
  168. if (this.duplicateProtection) {
  169. this.duplicateTimer = config.getLongValue(DuplicateTimer.ordinal(), (Long) DuplicateTimer.defValue());
  170. this.duplicateSize = config.getIntValue(DuplicateSize.ordinal(), (Integer) DuplicateSize.defValue());
  171. }
  172. logger.debug("Duplicate Protection Configuration: Enabled? {}, Timer: {}, Size: {}", new Object[]{this.duplicateProtection, this.duplicateTimer, this.duplicateSize});
  173. if (predefinedPeerTable == null) {
  174. predefinedPeerTable = new CopyOnWriteArraySet<String>();
  175. }
  176. if (config instanceof MutableConfiguration) {
  177. ((MutableConfiguration) config).addChangeListener(this);
  178. }
  179. logger.debug("MutablePeerTableImpl is starting initialisation by calling init on super class");
  180. init(stack,router, config, metaData, fsmFactory, transportFactory, statisticFactory, concurrentFactory, parser);
  181. logger.debug("MutablePeerTableImpl has finished initialisation");
  182. }
  183. @Override
  184. protected Peer createPeer(int rating, String uri, String ip, String portRange, MetaData metaData, Configuration globalConfig,
  185. Configuration peerConfig, org.jdiameter.client.api.fsm.IFsmFactory fsmFactory,
  186. org.jdiameter.client.api.io.ITransportLayerFactory transportFactory,
  187. IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory,
  188. IMessageParser parser) throws InternalException, TransportException, URISyntaxException, UnknownServiceException {
  189. logger.debug("Creating Peer for URI [{}]", uri);
  190. if (predefinedPeerTable == null) {
  191. logger.debug("Creating new empty predefined peer table");
  192. predefinedPeerTable = new CopyOnWriteArraySet<String>();
  193. }
  194. logger.debug("Adding URI [{}] to predefinedPeerTable", uri);
  195. predefinedPeerTable.add(new URI(uri).getFQDN());
  196. if (peerConfig.getBooleanValue(PeerAttemptConnection.ordinal(), false)) {
  197. logger.debug("Peer at URI [{}] is configured to attempt a connection (i.e. acting as a client) and a new peer instance will be created and returned", uri);
  198. return newPeerInstance(rating, new URI(uri), ip, portRange, true, null,
  199. metaData, globalConfig, peerConfig, (IFsmFactory) fsmFactory,
  200. (ITransportLayerFactory) transportFactory, parser, statisticFactory, concurrentFactory);
  201. }
  202. else {
  203. logger.debug("Peer at URI [{}] is configured to NOT attempt a connection (i.e. acting as a server) and null will be returned", uri);
  204. return null;
  205. }
  206. }
  207. protected IPeer newPeerInstance(int rating, URI uri, String ip, String portRange, boolean attCnn, IConnection connection,
  208. MetaData metaData, Configuration globalConfig, Configuration peerConfig, IFsmFactory fsmFactory,
  209. ITransportLayerFactory transportFactory, IMessageParser parser,
  210. IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory) throws URISyntaxException, UnknownServiceException, InternalException, TransportException {
  211. logger.debug("Creating and returning a new Peer Instance for URI [{}].", uri);
  212. return new org.jdiameter.server.impl.PeerImpl(
  213. rating, uri, ip, portRange, attCnn, connection,
  214. this, (org.jdiameter.server.api.IMetaData) metaData, globalConfig, peerConfig, sessionFactory,
  215. fsmFactory, transportFactory, statisticFactory, concurrentFactory, parser, network, ovrManager, sessionDatasource
  216. );
  217. }
  218. public void setPeerTableListener(PeerTableListener peerTableListener) {
  219. this.peerTableListener = peerTableListener;
  220. }
  221. public boolean elementChanged(int i, Object data) {
  222. Configuration newConf = (Configuration) data;
  223. stopTimeOut = newConf.getLongValue(StopTimeOut.ordinal(), (Long) StopTimeOut.defValue());
  224. duplicateTimer = newConf.getLongValue(DuplicateTimer.ordinal(), (Long) DuplicateTimer.defValue());
  225. isAcceptUndefinedPeer = newConf.getBooleanValue(AcceptUndefinedPeer.ordinal(), false);
  226. return true;
  227. }
  228. public boolean isDuplicateProtection() {
  229. return duplicateProtection;
  230. }
  231. public void start() throws IllegalDiameterStateException, IOException { // TODO: use parent method
  232. logger.debug("Starting MutablePeerTableImpl. Starting router, overload scheduler, connection check timer, etc.");
  233. router.start();
  234. // Start overload manager
  235. overloadScheduler = concurrentFactory.getScheduledExecutorService(PeerOverloadTimer.name());
  236. Runnable overloadTask = new Runnable() {
  237. public void run() {
  238. if (ovrManager != null) {
  239. for (Peer p : peerTable.values()) {
  240. ((IPeer) p).notifyOvrManager(ovrManager);
  241. }
  242. }
  243. }
  244. };
  245. overloadHandler = overloadScheduler.scheduleAtFixedRate(overloadTask, 0, 1, TimeUnit.SECONDS);
  246. // Start duplication protection procedure
  247. if (duplicateProtection) {
  248. duplicationScheduler = concurrentFactory.getScheduledExecutorService(DuplicationMessageTimer.name());
  249. Runnable duplicateTask = new Runnable() {
  250. public void run() {
  251. long now = System.currentTimeMillis();
  252. if(logger.isDebugEnabled()) {
  253. logger.debug("Running Duplicate Cleaning Task. Duplicate Storage size is: {}. Removing entries with time <= '{}'", storageAnswers.size(), now - duplicateTimer);
  254. }
  255. for (StorageEntry s : storageAnswers.values()) {
  256. if (s != null && s.getTime() + duplicateTimer <= now) {
  257. if(logger.isTraceEnabled()) {
  258. logger.trace("Duplicate Cleaning Task - Removing Entry with key '{}' and time '{}'", s.getDuplicationKey(), s.getTime());
  259. }
  260. storageAnswers.remove(s.getDuplicationKey());
  261. }
  262. else {
  263. if(logger.isTraceEnabled()) {
  264. logger.trace("Duplicate Cleaning Task - Skipping Entry with key '{}' and time '{}'", s.getDuplicationKey(), s.getTime());
  265. }
  266. }
  267. }
  268. if(logger.isDebugEnabled()) {
  269. logger.debug("Completed Duplicate Cleaning Task. New Duplicate Storage size is: {}. Total task runtime: {}ms", storageAnswers.size(), System.currentTimeMillis() - now);
  270. }
  271. }
  272. };
  273. duplicationHandler = duplicationScheduler.scheduleAtFixedRate(duplicateTask, duplicateTimer, duplicateTimer, TimeUnit.MILLISECONDS);
  274. }
  275. //
  276. connScheduler = concurrentFactory.getScheduledExecutorService(ConnectionTimer.name());
  277. Runnable connectionCheckTask = new Runnable() {
  278. public void run() {
  279. Map<String, IConnection> connections = getIncConnections();
  280. for (IConnection connection : connections.values()) {
  281. if (System.currentTimeMillis() - connection.getCreatedTime() <= CONN_INVALIDATE_PERIOD) {
  282. logger.debug("External connection released by timeout [{}]", connection);
  283. try {
  284. connection.remAllConnectionListener();
  285. connection.release();
  286. }
  287. catch (IOException e) {
  288. logger.debug("Unable to release connection", e);
  289. }
  290. connections.remove(connection.getKey());
  291. }
  292. }
  293. }
  294. };
  295. connHandler = connScheduler.scheduleAtFixedRate(connectionCheckTask, CONN_INVALIDATE_PERIOD, CONN_INVALIDATE_PERIOD, TimeUnit.MILLISECONDS);
  296. // Start server socket
  297. try {
  298. logger.debug("Creating network guard");
  299. networkGuard = createNetworkGuard(transportFactory);
  300. }
  301. catch (TransportException e) {
  302. logger.debug("Unable to create server socket", e);
  303. }
  304. // Connect to predefined peers
  305. for (Peer p : peerTable.values()) {
  306. try {
  307. if(((IPeer) p).isAttemptConnection()) {
  308. p.connect();
  309. }
  310. }
  311. catch (Exception e) {
  312. logger.warn("Unable to start connect procedure for peer [" + p + "]", e);
  313. }
  314. }
  315. isStarted = true;
  316. }
  317. public Set<String> getPredefinedPeerTable() {
  318. return predefinedPeerTable;
  319. }
  320. public ConcurrentHashMap<String, IConnection> getIncConnections() {
  321. if (incConnections == null) {
  322. incConnections = new ConcurrentHashMap<String, IConnection>();
  323. }
  324. return incConnections;
  325. }
  326. private final Object regLock = new Object();
  327. private INetworkGuard createNetworkGuard(final ITransportLayerFactory transportFactory) throws TransportException {
  328. return transportFactory.createNetworkGuard(
  329. metaData.getLocalPeer().getIPAddresses()[0],
  330. metaData.getLocalPeer().getUri().getPort(),
  331. new INetworkConnectionListener() {
  332. public void newNetworkConnection(final IConnection connection) {
  333. synchronized (regLock) {
  334. final IConnectionListener listener = new IConnectionListener() {
  335. public void connectionOpened(String connKey) {
  336. logger.debug("Connection [{}] opened", connKey);
  337. }
  338. @SuppressWarnings("unchecked")
  339. public void connectionClosed(String connKey, List notSended) {
  340. logger.debug("Connection [{}] closed", connKey);
  341. unregister(true);
  342. }
  343. public void messageReceived(String connKey, IMessage message) {
  344. logger.debug("Message [{}] received to peer [{}]", message, connKey);
  345. if (message.isRequest() && message.getCommandCode() == Message.CAPABILITIES_EXCHANGE_REQUEST) {
  346. connection.remConnectionListener(this);
  347. IPeer peer = null;
  348. String host;
  349. try {
  350. host = message.getAvps().getAvp(Avp.ORIGIN_HOST).getDiameterIdentity();
  351. logger.debug("Origin-Host in new received message is [{}]", host);
  352. }
  353. catch (AvpDataException e) {
  354. logger.warn("Unable to retrieve find Origin-Host AVP in CER", e);
  355. unregister(true);
  356. return;
  357. }
  358. String realm;
  359. try {
  360. realm = message.getAvps().getAvp(Avp.ORIGIN_REALM).getDiameterIdentity();
  361. logger.debug("Origin-Realm in new received message is [{}]", realm);
  362. } catch (AvpDataException e) {
  363. logger.warn("Unable to retrieve find Origin-Realm AVP in CER", e);
  364. unregister(true);
  365. return;
  366. }
  367. boolean foundInPredefinedTable = false;
  368. // find into predefined table
  369. for (String fqdn : predefinedPeerTable) {
  370. if(logger.isDebugEnabled()) {
  371. logger.debug("Checking against entry in predefinedPeerTable with FQDN [{}]", fqdn);
  372. }
  373. if (fqdn.equals(host)) {
  374. if(logger.isDebugEnabled()) {
  375. logger.debug("{} == {}", fqdn, host);
  376. }
  377. peer = (IPeer) peerTable.get(fqdn);
  378. foundInPredefinedTable = true; // found but not init
  379. break;
  380. }
  381. else {
  382. if(logger.isDebugEnabled()) {
  383. logger.debug("{} != {}", fqdn, host);
  384. }
  385. }
  386. }
  387. // find in peer table for peer already connected to server but not removed
  388. if (peer == null) {
  389. logger.debug("Peer with FQDN [{}] was not found in predefined peer table. Checking at (previously) connected peers table", host);
  390. peer = (IPeer) peerTable.get(host);
  391. if (peer != null) {
  392. logger.debug("Got peer for FQDN [{}]. Is connection open ? {}.", host, peer.hasValidConnection());
  393. }
  394. else {
  395. logger.debug("Still haven't found peer for FQDN [{}]", host);
  396. }
  397. }
  398. if (peer != null) {
  399. //FIXME: define procedure when 'peer.getRealm() != realm'
  400. logger.debug("Add [{}] connection to peer [{}]", connection, peer);
  401. peer.addIncomingConnection(connection);
  402. try {
  403. logger.debug("Handle [{}] message on peer [{}]", message, peer);
  404. peer.handleMessage(message.isRequest() ? EventTypes.CER_EVENT : EventTypes.CER_EVENT, message, connKey);
  405. }
  406. catch (Exception e) {
  407. logger.debug("Unable to process CER message", e);
  408. }
  409. }
  410. else {
  411. if (isAcceptUndefinedPeer || foundInPredefinedTable) {
  412. try {
  413. int port = connection.getRemotePort();
  414. boolean hostAsUri = config.getBooleanValue(UseUriAsFqdn.ordinal(), (Boolean) UseUriAsFqdn.defValue());
  415. URI uri;
  416. if (hostAsUri || host.startsWith("aaa://")) {
  417. uri = new URI(host);
  418. }
  419. else {
  420. uri = new URI("aaa://" + host + ":" + port);
  421. }
  422. peer = newPeerInstance(0, uri, connection.getRemoteAddress().getHostAddress(), null, false, connection,
  423. metaData, config, null, fsmFactory, transportFactory, parser, statisticFactory, concurrentFactory);
  424. logger.debug("Created new peer instance [{}] and adding to peer table", peer);
  425. peer.setRealm(realm);
  426. appendPeerToPeerTable(peer);
  427. logger.debug("Handle [{}] message on peer [{}]", message, peer);
  428. peer.handleMessage(message.isRequest() ? EventTypes.CER_EVENT : EventTypes.CER_EVENT, message, connKey);
  429. }
  430. catch (Exception e) {
  431. logger.warn("Unable to create peer", e);
  432. unregister(true);
  433. }
  434. }
  435. else {
  436. logger.info("Skip anonymous connection [{}]", connection);
  437. unregister(true);
  438. }
  439. }
  440. }
  441. else {
  442. logger.debug("Unknown message [{}] by connection [{}]", message, connKey);
  443. unregister(true);
  444. }
  445. }
  446. public void internalError(String connKey, IMessage message, TransportException cause) {
  447. logger.debug("Connection [{}] internalError [{}]", connKey, cause);
  448. unregister(true);
  449. }
  450. public void unregister(boolean release) {
  451. getIncConnections().remove(connection.getKey());
  452. connection.remConnectionListener(this);
  453. if (release && connection.isConnected()) {
  454. try {
  455. connection.release();
  456. }
  457. catch (IOException e) {
  458. logger.debug("Unable to release connection [{}]", connection);
  459. }
  460. }
  461. }
  462. };
  463. getIncConnections().put(connection.getKey(), connection);
  464. connection.addConnectionListener(listener);
  465. }
  466. }
  467. }
  468. );
  469. }
  470. private void appendPeerToPeerTable(IPeer peer) {
  471. peerTable.put(peer.getUri().getFQDN(), peer);
  472. if (peerTableListener != null) {
  473. peerTableListener.peerAccepted(peer);
  474. }
  475. }
  476. public void stopping(int disconnectCause) {
  477. super.stopping(disconnectCause);
  478. if (networkGuard != null) {
  479. networkGuard.destroy();
  480. networkGuard = null;
  481. }
  482. //
  483. if (overloadScheduler != null) {
  484. concurrentFactory.shutdownNow(overloadScheduler);
  485. overloadScheduler = null;
  486. overloadHandler.cancel(true);
  487. overloadHandler = null;
  488. }
  489. //
  490. if (duplicationScheduler != null) {
  491. concurrentFactory.shutdownNow(duplicationScheduler);
  492. duplicationScheduler = null;
  493. }
  494. if (duplicationHandler != null) {
  495. duplicationHandler.cancel(true);
  496. duplicationHandler = null;
  497. }
  498. //
  499. if (connScheduler != null) {
  500. concurrentFactory.shutdownNow(connScheduler);
  501. connScheduler = null;
  502. }
  503. if (connHandler != null) {
  504. connHandler.cancel(true);
  505. connHandler = null;
  506. }
  507. //remove incoming data
  508. storageAnswers.clear();
  509. // Clear dynamic peers from peertable
  510. Iterator<String> it = super.peerTable.keySet().iterator();
  511. while(it.hasNext()) {
  512. String fqdn = it.next();
  513. if(this.predefinedPeerTable.contains(fqdn)) {
  514. continue;
  515. }
  516. else {
  517. it.remove();
  518. }
  519. }
  520. }
  521. public Peer addPeer(URI peerURI, String realm, boolean connecting) {
  522. //TODO: add sKey here, now it adds peer to all realms.
  523. //TODO: better, separate addPeer from realm!
  524. try {
  525. Configuration peerConfig = null;
  526. Configuration[] peers = config.getChildren(PeerTable.ordinal());
  527. // find peer config
  528. for (Configuration c : peers)
  529. if (peerURI.getFQDN().equals(c.getStringValue(PeerName.ordinal(), ""))) {
  530. peerConfig = c;
  531. break;
  532. }
  533. if (peerConfig == null) {
  534. peerConfig = new EmptyConfiguration(false).add(PeerAttemptConnection, connecting);
  535. }
  536. IPeer peer = (IPeer) createPeer(0, peerURI.toString(), null, null, metaData, config, peerConfig, fsmFactory,
  537. transportFactory, statisticFactory, concurrentFactory, parser);
  538. if (peer == null) return null;
  539. peer.setRealm(realm);
  540. appendPeerToPeerTable(peer);
  541. boolean found = false;
  542. Collection<Realm> realms = this.router.getRealmTable().getRealms(realm);
  543. for (Realm r : realms) {
  544. if (r.getName().equals(realm)) {
  545. ((IRealm)r).addPeerName(peerURI.toString());
  546. found = true;
  547. break;
  548. }
  549. }
  550. if (!found) {
  551. throw new IllegalArgumentException("Incorrect realm name");
  552. }
  553. if (StackState.STARTED.equals(stack.getState()) && connecting) {
  554. peer.connect();
  555. }
  556. return peer;
  557. }
  558. catch(Exception e) {
  559. logger.debug("Unable to add peer", e);
  560. return null;
  561. }
  562. }
  563. public Set<Realm> getAllRealms() {
  564. return new HashSet<Realm>(router.getRealmTable().getRealms());
  565. }
  566. public Peer removePeer(String host) {
  567. try {
  568. String fqdn = null;
  569. for (String f : peerTable.keySet()) {
  570. if (f.equals(host)) {
  571. fqdn = f;
  572. peerTable.get(fqdn).disconnect(DisconnectCause.BUSY);
  573. }
  574. }
  575. if (fqdn != null) {
  576. predefinedPeerTable.remove(fqdn);
  577. Peer removedPeer = peerTable.remove(fqdn);
  578. if (peerTableListener != null) {
  579. peerTableListener.peerRemoved(removedPeer);
  580. }
  581. return removedPeer;
  582. }
  583. else {
  584. return null;
  585. }
  586. }
  587. catch (Exception e) {
  588. logger.debug("Unable to remove peer", e);
  589. return null;
  590. }
  591. }
  592. public Statistic getStatistic(String name) {
  593. for (Peer p : peerTable.values()) {
  594. if (p.getUri().getFQDN().equals(name)) {
  595. return ((IPeer) p).getStatistic();
  596. }
  597. }
  598. return null;
  599. }
  600. public IMessage isDuplicate(IMessage request) {
  601. String key = request.getDuplicationKey();
  602. if (key != null && storageAnswers != null) {
  603. StorageEntry entry = storageAnswers.get(key);
  604. return entry != null ? (IMessage) entry.getMessage().clone() : null;
  605. }
  606. return null;
  607. }
  608. public void saveToDuplicate(String key, IMessage answer) {
  609. if (storageAnswers != null && storageAnswers.size() < duplicateSize) {
  610. if (key != null) {
  611. StorageEntry se = new StorageEntry((IMessage) answer.clone());
  612. if(logger.isTraceEnabled()) {
  613. logger.trace("Duplicate Protection - Inserting Entry with key '{}' and time '{}'", key, se.getTime());
  614. }
  615. storageAnswers.put(key, se);
  616. }
  617. }
  618. }
  619. public ISessionFactory getSessionFactory() {
  620. return sessionFactory;
  621. }
  622. public boolean isWrapperFor(Class<?> aClass) throws InternalException {
  623. boolean isWrapp = super.isWrapperFor(aClass);
  624. return aClass == MutablePeerTable.class || aClass == Network.class || isWrapp;
  625. }
  626. public <T> T unwrap(Class<T> aClass) throws InternalException {
  627. if (aClass == MutablePeerTable.class) {
  628. return (T) assembler.getComponentInstance(aClass);
  629. }
  630. if (aClass == Network.class) {
  631. return (T) assembler.getComponentInstance(aClass);
  632. }
  633. return null;
  634. }
  635. }