PageRenderTime 137ms CodeModel.GetById 47ms RepoModel.GetById 0ms app.codeStats 1ms

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

http://mobicents.googlecode.com/
Java | 624 lines | 473 code | 51 blank | 100 comment | 93 complexity | 38bcc6748a471a7fb80c6963cd2d624d 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.api.PeerState.DOWN;
  24. import static org.jdiameter.api.PeerState.INITIAL;
  25. import java.io.IOException;
  26. import java.net.InetAddress;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import org.jdiameter.api.ApplicationId;
  30. import org.jdiameter.api.Avp;
  31. import org.jdiameter.api.AvpDataException;
  32. import org.jdiameter.api.Configuration;
  33. import org.jdiameter.api.InternalException;
  34. import org.jdiameter.api.LocalAction;
  35. import org.jdiameter.api.Message;
  36. import org.jdiameter.api.NetworkReqListener;
  37. import org.jdiameter.api.OverloadException;
  38. import org.jdiameter.api.PeerState;
  39. import org.jdiameter.api.ResultCode;
  40. import org.jdiameter.api.StatisticRecord;
  41. import org.jdiameter.api.URI;
  42. import org.jdiameter.client.api.IMessage;
  43. import org.jdiameter.client.api.IMetaData;
  44. import org.jdiameter.client.api.IRequest;
  45. import org.jdiameter.client.api.ISessionFactory;
  46. import org.jdiameter.client.api.controller.IRealm;
  47. import org.jdiameter.client.api.controller.IRealmTable;
  48. import org.jdiameter.client.api.fsm.IContext;
  49. import org.jdiameter.client.api.io.IConnection;
  50. import org.jdiameter.client.api.io.ITransportLayerFactory;
  51. import org.jdiameter.client.api.io.TransportException;
  52. import org.jdiameter.client.api.parser.IMessageParser;
  53. import org.jdiameter.common.api.concurrent.IConcurrentFactory;
  54. import org.jdiameter.common.api.data.ISessionDatasource;
  55. import org.jdiameter.common.api.statistic.IStatisticManager;
  56. import org.jdiameter.common.api.statistic.IStatisticRecord;
  57. import org.jdiameter.server.api.IFsmFactory;
  58. import org.jdiameter.server.api.INetwork;
  59. import org.jdiameter.server.api.IOverloadManager;
  60. import org.jdiameter.server.api.IPeer;
  61. import org.jdiameter.server.api.IStateMachine;
  62. import org.slf4j.Logger;
  63. import org.slf4j.LoggerFactory;
  64. /**
  65. *
  66. * @author erick.svenson@yahoo.com
  67. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  68. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  69. */
  70. public class PeerImpl extends org.jdiameter.client.impl.controller.PeerImpl implements IPeer {
  71. private static final Logger logger = LoggerFactory.getLogger(org.jdiameter.server.impl.PeerImpl.class);
  72. // External references
  73. private MutablePeerTableImpl peerTable;
  74. protected Set<String> predefinedPeerTable;
  75. protected INetwork network;
  76. protected IOverloadManager ovrManager;
  77. protected ISessionFactory sessionFactory;
  78. // Internal parameters and members
  79. protected boolean isDuplicateProtection;
  80. protected boolean isAttemptConnection;
  81. protected boolean isElection = true;
  82. protected Map<String, IConnection> incConnections;
  83. /**
  84. * Create instance of class
  85. */
  86. public PeerImpl(int rating, URI remotePeer, String ip, String portRange, boolean attCnn, IConnection connection,
  87. MutablePeerTableImpl peerTable, IMetaData metaData, Configuration config, Configuration peerConfig,
  88. ISessionFactory sessionFactory, IFsmFactory fsmFactory, ITransportLayerFactory trFactory,
  89. IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory,
  90. IMessageParser parser, INetwork nWork, IOverloadManager oManager, final ISessionDatasource sessionDataSource)
  91. throws InternalException, TransportException {
  92. super(peerTable, rating, remotePeer, ip, portRange, metaData, config, peerConfig, fsmFactory, trFactory, parser,
  93. statisticFactory, concurrentFactory, connection, sessionDataSource);
  94. // Create specific action context
  95. this.peerTable = peerTable;
  96. this.isDuplicateProtection = this.peerTable.isDuplicateProtection();
  97. this.sessionFactory = sessionFactory;
  98. this.isAttemptConnection = attCnn;
  99. this.incConnections = this.peerTable.getIncConnections();
  100. this.predefinedPeerTable = this.peerTable.getPredefinedPeerTable();
  101. this.network = nWork;
  102. this.ovrManager = oManager;
  103. }
  104. protected void createPeerStatistics() {
  105. super.createPeerStatistics();
  106. // Append fsm statistic
  107. if (this.fsm instanceof IStateMachine) {
  108. StatisticRecord[] records = ((IStateMachine) fsm).getStatistic().getRecords();
  109. IStatisticRecord[] recordsArray = new IStatisticRecord[records.length];
  110. int count = 0;
  111. for(StatisticRecord st: records) {
  112. recordsArray[count++] = (IStatisticRecord) st;
  113. }
  114. this.statistic.appendCounter(recordsArray);
  115. }
  116. }
  117. protected void preProcessRequest(IMessage message) {
  118. // ammendonca: this is non-sense, we don't want to save requests
  119. //if (isDuplicateProtection && message.isRequest()) {
  120. // peerTable.saveToDuplicate(message.getDuplicationKey(), message);
  121. //}
  122. }
  123. public boolean isAttemptConnection() {
  124. return isAttemptConnection;
  125. }
  126. public IContext getContext() {
  127. return new LocalActionConext();
  128. }
  129. public IConnection getConnection() {
  130. return connection;
  131. }
  132. public void addIncomingConnection(IConnection conn) {
  133. PeerState state = fsm.getState(PeerState.class);
  134. if (DOWN == state || INITIAL == state) {
  135. conn.addConnectionListener(connListener);
  136. logger.debug("Append external connection [{}]", conn.getKey());
  137. }
  138. else {
  139. logger.debug("Releasing connection [{}]", conn.getKey());
  140. incConnections.remove(conn.getKey());
  141. try {
  142. conn.release();
  143. }
  144. catch (IOException e) {
  145. logger.debug("Can not close external connection", e);
  146. }
  147. finally {
  148. logger.debug("Close external connection");
  149. }
  150. }
  151. }
  152. public void setElection(boolean isElection) {
  153. this.isElection = isElection;
  154. }
  155. public void notifyOvrManager(IOverloadManager ovrManager) {
  156. ovrManager.changeNotification(0, getUri(), fsm.getQueueInfo());
  157. }
  158. public String toString() {
  159. if(fsm!=null)
  160. return "SPeer{" + "Uri=" + uri + "; State=" + fsm.getState(PeerState.class) + "; con="+ connection +"; incCon"+incConnections+" }";
  161. return "SPeer{" + "Uri=" + uri + "; State=" + fsm + "; con="+ connection +"; incCon"+incConnections+" }";
  162. }
  163. protected class LocalActionConext extends ActionContext {
  164. public void sendCeaMessage(int resultCode, Message cer, String errMessage) throws TransportException, OverloadException {
  165. logger.debug("Send CEA message");
  166. IMessage message = parser.createEmptyMessage(Message.CAPABILITIES_EXCHANGE_ANSWER, 0);
  167. message.setRequest(false);
  168. message.setHopByHopIdentifier(cer.getHopByHopIdentifier());
  169. message.setEndToEndIdentifier(cer.getEndToEndIdentifier());
  170. message.getAvps().addAvp(Avp.ORIGIN_HOST, metaData.getLocalPeer().getUri().getFQDN(), true, false, true);
  171. message.getAvps().addAvp(Avp.ORIGIN_REALM, metaData.getLocalPeer().getRealmName(), true, false, true);
  172. for (InetAddress ia : metaData.getLocalPeer().getIPAddresses()) {
  173. message.getAvps().addAvp(Avp.HOST_IP_ADDRESS, ia, true, false);
  174. }
  175. message.getAvps().addAvp(Avp.VENDOR_ID, metaData.getLocalPeer().getVendorId(), true, false, true);
  176. for (ApplicationId appId: metaData.getLocalPeer().getCommonApplications()) {
  177. addAppId(appId, message);
  178. }
  179. message.getAvps().addAvp(Avp.PRODUCT_NAME, metaData.getLocalPeer().getProductName(), false);
  180. message.getAvps().addAvp(Avp.RESULT_CODE, resultCode, true, false, true);
  181. message.getAvps().addAvp(Avp.FIRMWARE_REVISION, metaData.getLocalPeer().getFirmware(), true);
  182. if (errMessage != null) {
  183. message.getAvps().addAvp(Avp.ERROR_MESSAGE, errMessage, false);
  184. }
  185. sendMessage(message);
  186. }
  187. public int processCerMessage(String key, IMessage message) {
  188. // Workaround for Issue #3205 (http://code.google.com/p/mobicents/issues/detail?id=3205)
  189. // BEGIN WORKAROUND // Give some time to initialization...
  190. try {
  191. Thread.sleep(100);
  192. }
  193. catch (InterruptedException e) {
  194. // ignore
  195. }
  196. // END WORKAROUND // Give some time to initialization...
  197. logger.debug("Processing CER");
  198. int resultCode = ResultCode.SUCCESS;
  199. try {
  200. if (connection == null || !connection.isConnected()) {
  201. if (logger.isDebugEnabled()) {
  202. logger.debug("Connection is null or not connected. Looking for one in incConnections with key [{}]. Here are the incConnections :", key);
  203. for (String c : incConnections.keySet()) {
  204. logger.debug(c);
  205. }
  206. }
  207. connection = incConnections.get(key);
  208. }
  209. // Process cer
  210. Set<ApplicationId> newAppId = getCommonApplicationIds(message);
  211. if (newAppId.isEmpty()) {
  212. if(logger.isDebugEnabled()) {
  213. logger.debug("Processing CER failed, no common application. Message AppIds [{}]", message.getApplicationIdAvps());
  214. }
  215. return ResultCode.NO_COMMON_APPLICATION;
  216. }
  217. // Handshake
  218. if (!connection.getKey().equals(key)) { // received cer by other connection
  219. logger.debug("CER received by other connection [{}]", key);
  220. switch(fsm.getState(PeerState.class)) {
  221. case DOWN:
  222. resultCode = ResultCode.SUCCESS;
  223. break;
  224. case INITIAL:
  225. boolean isLocalWin = false;
  226. if (isElection)
  227. try {
  228. // ammendonca: can't understand why it checks for <= 0 ... using equals
  229. //isLocalWin = metaData.getLocalPeer().getUri().getFQDN().compareTo(
  230. // message.getAvps().getAvp(Avp.ORIGIN_HOST).getOctetString()) <= 0;
  231. isLocalWin = metaData.getLocalPeer().getUri().getFQDN().equals(
  232. message.getAvps().getAvp(Avp.ORIGIN_HOST).getOctetString());
  233. }
  234. catch(Exception exc) {
  235. isLocalWin = true;
  236. }
  237. logger.debug("local peer is win - [{}]", isLocalWin);
  238. resultCode = 0;
  239. if (isLocalWin) {
  240. IConnection c = incConnections.get(key);
  241. c.remConnectionListener(connListener);
  242. c.disconnect();
  243. incConnections.remove(key);
  244. }
  245. else {
  246. connection.disconnect(); // close current connection and work with other connection
  247. connection.remConnectionListener(connListener);
  248. connection = incConnections.remove(key);
  249. resultCode = ResultCode.SUCCESS;
  250. }
  251. break;
  252. }
  253. }
  254. else {
  255. if (logger.isDebugEnabled()) {
  256. logger.debug("CER received by current connection, key: [{}] PeerState: [{}] ", key, fsm.getState(PeerState.class));
  257. }
  258. if (fsm.getState(PeerState.class).equals(INITIAL)) { // received cer by current connection
  259. resultCode = 0; // NOP
  260. }
  261. incConnections.remove(key);
  262. }
  263. if (resultCode == ResultCode.SUCCESS) {
  264. commonApplications.clear();
  265. commonApplications.addAll(newAppId);
  266. fillIPAddressTable(message);
  267. }
  268. }
  269. catch (Exception exc) {
  270. logger.debug("Can not process CER", exc);
  271. }
  272. logger.debug("CER result [{}]", resultCode);
  273. return resultCode;
  274. }
  275. public boolean isRestoreConnection() {
  276. return isAttemptConnection;
  277. }
  278. public String getPeerDescription() {
  279. return PeerImpl.this.toString();
  280. }
  281. public boolean receiveMessage(IMessage message) {
  282. logger.debug("Receiving message in server.");
  283. boolean isProcessed = false;
  284. if (message.isRequest()) {
  285. IRequest req = message;
  286. Avp destRealmAvp = req.getAvps().getAvp(Avp.DESTINATION_REALM);
  287. String destRealm = null;
  288. if (destRealmAvp == null) {
  289. // TODO: add that missing avp in "Failed-AVP" avp...
  290. sendErrorAnswer(message, "Missing Destination-Realm AVP", ResultCode.MISSING_AVP);
  291. return true;
  292. }
  293. else {
  294. try{
  295. destRealm = destRealmAvp.getDiameterIdentity();
  296. }
  297. catch(AvpDataException ade) {
  298. sendErrorAnswer(message, "Failed to parse Destination-Realm AVP", ResultCode.INVALID_AVP_VALUE, destRealmAvp);
  299. return true;
  300. }
  301. }
  302. IRealmTable realmTable = router.getRealmTable();
  303. if (!realmTable.realmExists(destRealm)) {
  304. // send no such realm answer.
  305. logger.warn("Received a request for an unrecognized realm: [{}]. Answering with 3003 (DIAMETER_REALM_NOT_SERVED) Result-Code.", destRealm);
  306. sendErrorAnswer(message, null, ResultCode.REALM_NOT_SERVED);
  307. return true;
  308. }
  309. ApplicationId appId = message.getSingleApplicationId();
  310. if (appId == null) {
  311. logger.warn("Receive a message with no Application Id. Answering with 5005 (MISSING_AVP) Result-Code.");
  312. sendErrorAnswer(message, "Missing Application-Id", ResultCode.MISSING_AVP);
  313. // TODO: add Auth-Application-Id, Acc-Application-Id and Vendor-Specific-Application-Id, can be empty
  314. return true;
  315. }
  316. // check condition for local processing.
  317. Avp destHostAvp = req.getAvps().getAvp(Avp.DESTINATION_HOST);
  318. //messages for local stack:
  319. // - The Destination-Host AVP contains the local host's identity,
  320. // - The Destination-Host AVP is not present, the Destination-Realm AVP
  321. // contains a realm the server is configured to process locally, and
  322. // the Diameter application is locally supported, or
  323. //check conditions for immediate consumption.
  324. //this includes
  325. if (destHostAvp != null) {
  326. try{
  327. String destHost = destHostAvp.getDiameterIdentity();
  328. //FIXME: add check with DNS/names to check 127 vs localhost
  329. if (destHost.equals(metaData.getLocalPeer().getUri().getFQDN())) {
  330. // this is for handling possible REDIRECT, destRealm != local.realm
  331. LocalAction action = null;
  332. IRealm matched = null;
  333. matched = (IRealm) realmTable.matchRealm(req);
  334. if(matched != null) {
  335. action = matched.getLocalAction();
  336. }
  337. else {
  338. // We don't support it locally, its not defined as remote, so send no such realm answer.
  339. sendErrorAnswer(message, null, ResultCode.APPLICATION_UNSUPPORTED);
  340. // or REALM_NOT_SERVED ?
  341. return true;
  342. }
  343. switch (action) {
  344. case LOCAL: // always call listener - this covers realms
  345. // configured as localy processed and
  346. // LocalPeer.realm
  347. isProcessed = consumeMessage(message);
  348. break;
  349. case PROXY:
  350. //TODO: change this its almost the same as above, make it sync, so no router code involved
  351. if(handleByAgent(message, isProcessed, req, matched)) {
  352. isProcessed = true;
  353. }
  354. break;
  355. case RELAY: // might be complicated, lets make it listener
  356. // now
  357. isProcessed = consumeMessage(message); //if its not redirected its
  358. break;
  359. case REDIRECT:
  360. //TODO: change this its almost the same as above, make it sync, so no router code involved
  361. if(handleByAgent(message, isProcessed, req, matched)) {
  362. isProcessed = true;
  363. }
  364. break;
  365. }
  366. }
  367. else {
  368. //NOTE: this check should be improved, it checks if there is connection to peer, otherwise we cant serve it.
  369. //possibly also match realm.
  370. IPeer p = (IPeer) peerTable.getPeer(destHost);
  371. if(p != null && p.hasValidConnection()) {
  372. isProcessed = consumeMessage(message);
  373. }
  374. else {
  375. // RFC 3588 // 6.1
  376. // 4. If none of the above is successful, an answer is returned with the
  377. // Result-Code set to DIAMETER_UNABLE_TO_DELIVER, with the E-bit set.
  378. logger.warn("Received message for unknown peer [{}]. Answering with 3002 (UNABLE_TO_DELIVER) Result-Code.", destHost);
  379. sendErrorAnswer(req, "No connection to peer", ResultCode.UNABLE_TO_DELIVER);
  380. isProcessed = true;
  381. }
  382. }
  383. }
  384. catch(AvpDataException ade) {
  385. logger.warn("Received message with present but unparsable Destination-Host. Answering with 5004 (INVALID_AVP_VALUE) Result-Code.");
  386. sendErrorAnswer(message, "Failed to parse Destination-Host AVP", ResultCode.INVALID_AVP_VALUE, destHostAvp);
  387. return true;
  388. }
  389. }
  390. else {
  391. // we have to match realms :) this MUST include local realm
  392. LocalAction action = null;
  393. IRealm matched = null;
  394. matched = (IRealm) realmTable.matchRealm(req);
  395. if(matched != null) {
  396. action = matched.getLocalAction();
  397. }
  398. else{
  399. // We don't support it locally, its not defined as remote, so send no such realm answer.
  400. sendErrorAnswer(message, null, ResultCode.APPLICATION_UNSUPPORTED);
  401. // or REALM_NOT_SERVED ?
  402. return true;
  403. }
  404. switch (action) {
  405. case LOCAL: // always call listener - this covers realms
  406. // configured as locally processed and LocalPeer.realm
  407. isProcessed = consumeMessage(message);
  408. break;
  409. case PROXY:
  410. //TODO: change this its almost the same as above, make it sync, so no router code involved
  411. if( handleByAgent(message, isProcessed, req, matched)) {
  412. isProcessed = true;
  413. }
  414. break;
  415. case RELAY: // might be complicated, lets make it listener
  416. // now
  417. isProcessed = consumeMessage(message);
  418. break;
  419. case REDIRECT:
  420. //TODO: change this its almost the same as above, make it sync, so no router code involved
  421. if(handleByAgent(message, isProcessed, req, matched)) {
  422. isProcessed = true;
  423. }
  424. break;
  425. }
  426. }
  427. }
  428. else {
  429. // answer, let client do its work
  430. isProcessed = super.receiveMessage(message);
  431. }
  432. return isProcessed;
  433. }
  434. /**
  435. * @param message
  436. * @param isProcessed
  437. * @param req
  438. * @param matched
  439. * @return
  440. */
  441. private boolean handleByAgent(IMessage message, boolean isProcessed, IRequest req, IRealm matched) {
  442. if (ovrManager != null && ovrManager.isParenAppOverload(message.getSingleApplicationId())) {
  443. logger.debug("Request [{}] skipped, because server application is overloaded", message);
  444. sendErrorAnswer(message, "Overloaded", ResultCode.TOO_BUSY);
  445. return true;
  446. }
  447. else {
  448. try {
  449. router.registerRequestRouteInfo(message);
  450. IMessage answer = (IMessage)matched.getAgent().processRequest(req,matched);
  451. if (isDuplicateProtection && answer != null) {
  452. peerTable.saveToDuplicate(message.getDuplicationKey(), answer);
  453. }
  454. isProcessed = true;
  455. if(answer != null) {
  456. sendMessage(answer);
  457. }
  458. if (statistic.isEnabled()) {
  459. statistic.getRecordByName(IStatisticRecord.Counters.SysGenResponse.name()).inc();
  460. }
  461. }
  462. catch (Exception exc) {
  463. // TODO: check this!!
  464. logger.warn("Error during processing message by " + matched.getAgent().getClass(), exc);
  465. sendErrorAnswer(message, "Unable to process", ResultCode.UNABLE_TO_COMPLY);
  466. return true;
  467. }
  468. }
  469. if (isProcessed) {
  470. // NOTE: done to inc stat which informs on net work request consumption :)
  471. if (statistic.isEnabled()) {
  472. statistic.getRecordByName(IStatisticRecord.Counters.NetGenRequest.name()).inc();
  473. }
  474. }
  475. return isProcessed;
  476. }
  477. /**
  478. * @param message
  479. * @return
  480. */
  481. private boolean consumeMessage(IMessage message) {
  482. // now its safe to call stupid client code....
  483. logger.debug("In Server consumeMessage. Going to call parents class receiveMessage");
  484. boolean isProcessed = super.receiveMessage(message);
  485. logger.debug("Did client PeerImpl process the message? [{}]", isProcessed);
  486. IMessage answer = null;
  487. // this will process if session exists.
  488. if (!isProcessed) {
  489. if (statistic.isEnabled()) {
  490. // Decrement what we have incremented in super.receiveMessage(message) since it wasn't processed
  491. statistic.getRecordByName(IStatisticRecord.Counters.NetGenRejectedRequest.name()).dec();
  492. }
  493. NetworkReqListener listener = network.getListener(message);
  494. if (listener != null) {
  495. if (logger.isDebugEnabled()) {
  496. logger.debug("We have found an application that is a listener for this message. It is [{}]", listener.getClass().getName());
  497. }
  498. if (isDuplicateProtection) {
  499. logger.debug("Checking if it's a duplicate, since duplicate protection is ENABLED.");
  500. answer = peerTable.isDuplicate(message);
  501. }
  502. if (answer != null) {
  503. logger.debug("This message was detected as being a duplicate");
  504. answer.setProxiable(message.isProxiable());
  505. answer.getAvps().removeAvp(Avp.PROXY_INFO);
  506. for (Avp avp : message.getAvps().getAvps(Avp.PROXY_INFO)) {
  507. answer.getAvps().addAvp(avp);
  508. }
  509. answer.setHopByHopIdentifier(message.getHopByHopIdentifier());
  510. isProcessed = true;
  511. try{
  512. sendMessage(answer);
  513. if (statistic.isEnabled()) {
  514. statistic.getRecordByName(IStatisticRecord.Counters.SysGenResponse.name()).inc();
  515. }
  516. }
  517. catch(Exception e) {
  518. // TODO: check this!!
  519. logger.warn("Error during processing message by duplicate protection", e);
  520. sendErrorAnswer(message, "Unable to process", ResultCode.UNABLE_TO_COMPLY);
  521. return true;
  522. }
  523. }
  524. else {
  525. if (ovrManager != null && ovrManager.isParenAppOverload(message.getSingleApplicationId())) {
  526. logger.debug("Request [{}] skipped, because server application is overloaded", message);
  527. sendErrorAnswer(message, "Overloaded", ResultCode.TOO_BUSY);
  528. return true;
  529. }
  530. else {
  531. try {
  532. router.registerRequestRouteInfo(message);
  533. answer = (IMessage) listener.processRequest(message);
  534. if (isDuplicateProtection && answer != null) {
  535. peerTable.saveToDuplicate(message.getDuplicationKey(), answer);
  536. }
  537. isProcessed = true;
  538. if(isProcessed && answer != null) {
  539. sendMessage(answer);
  540. }
  541. if (statistic.isEnabled()) {
  542. statistic.getRecordByName(IStatisticRecord.Counters.AppGenResponse.name()).inc();
  543. }
  544. }
  545. catch (Exception exc) {
  546. // TODO: check this!!
  547. logger.warn("Error during processing message by listener", exc);
  548. sendErrorAnswer(message, "Unable to process", ResultCode.UNABLE_TO_COMPLY);
  549. return true;
  550. }
  551. }
  552. }
  553. }
  554. else {
  555. // NOTE: no listener defined for messages apps, response with "bad peer" stuff.
  556. logger.warn("Received message for unsupported Application-Id [{}]", message.getSingleApplicationId());
  557. sendErrorAnswer(message, "Unsupported Application-Id", ResultCode.APPLICATION_UNSUPPORTED);
  558. return true;
  559. }
  560. }
  561. if (isProcessed) {
  562. // NOTE: done to inc stat which informs on net work request consumption :)...
  563. if (statistic.isEnabled()) {
  564. statistic.getRecordByName(IStatisticRecord.Counters.NetGenRequest.name()).inc();
  565. }
  566. }
  567. return isProcessed;
  568. }
  569. public String toString() {
  570. return new StringBuffer("LocalActionConext [isRestoreConnection()=").append(isRestoreConnection()).append(", getPeerDescription()=").append(getPeerDescription()).append(", isConnected()=").append(isConnected()).append(", LocalPeer=").append(metaData.getLocalPeer().getUri()).append(" ]").toString();
  571. }
  572. }
  573. }