PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/rf/ClientRfSessionImpl.java

http://mobicents.googlecode.com/
Java | 770 lines | 514 code | 42 blank | 214 comment | 110 complexity | be205a17173ea0e3ca6e38c61cff63b5 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 2010, 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.client.impl.app.rf;
  23. import static org.jdiameter.api.Avp.ACCOUNTING_REALTIME_REQUIRED;
  24. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.IDLE;
  25. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.OPEN;
  26. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.PENDING_BUFFERED;
  27. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.PENDING_CLOSE;
  28. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.PENDING_EVENT;
  29. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.PENDING_INTERIM;
  30. import static org.jdiameter.common.api.app.rf.ClientRfSessionState.PENDING_START;
  31. import java.io.Serializable;
  32. import org.jdiameter.api.Answer;
  33. import org.jdiameter.api.ApplicationId;
  34. import org.jdiameter.api.Avp;
  35. import org.jdiameter.api.EventListener;
  36. import org.jdiameter.api.InternalException;
  37. import org.jdiameter.api.Message;
  38. import org.jdiameter.api.OverloadException;
  39. import org.jdiameter.api.Request;
  40. import org.jdiameter.api.RouteException;
  41. import org.jdiameter.api.app.AppSession;
  42. import org.jdiameter.api.app.StateChangeListener;
  43. import org.jdiameter.api.app.StateEvent;
  44. import org.jdiameter.api.rf.ClientRfSession;
  45. import org.jdiameter.api.rf.ClientRfSessionListener;
  46. import org.jdiameter.api.rf.events.RfAccountingRequest;
  47. import org.jdiameter.client.api.ISessionFactory;
  48. import org.jdiameter.common.api.app.IAppSessionState;
  49. import org.jdiameter.common.api.app.rf.ClientRfSessionState;
  50. import org.jdiameter.common.api.app.rf.IClientRfActionContext;
  51. import org.jdiameter.common.impl.app.rf.AppRfSessionImpl;
  52. import org.slf4j.Logger;
  53. import org.slf4j.LoggerFactory;
  54. /**
  55. * Client Accounting session implementation
  56. *
  57. *
  58. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  59. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  60. */
  61. public class ClientRfSessionImpl extends AppRfSessionImpl implements EventListener<Request, Answer>, ClientRfSession {
  62. private static final Logger logger = LoggerFactory.getLogger(ClientRfSessionImpl.class);
  63. // Constants ----------------------------------------------------------------
  64. public static final int DELIVER_AND_GRANT = 1;
  65. public static final int GRANT_AND_LOSE = 3;
  66. // Factories and Listeners --------------------------------------------------
  67. protected transient IClientRfActionContext context;
  68. protected transient ClientRfSessionListener listener;
  69. protected static final String TIMER_NAME_INTERIM = "CLIENT_INTERIM";
  70. protected IClientRfSessionData sessionData;
  71. public ClientRfSessionImpl(IClientRfSessionData sessionData, ISessionFactory sessionFactory,ClientRfSessionListener clientAccSessionListener, IClientRfActionContext iClientRfActionContext,
  72. StateChangeListener<AppSession> stateChangeListener, ApplicationId applicationId) {
  73. super(sessionFactory,sessionData);
  74. super.appId = applicationId;
  75. this.listener = clientAccSessionListener;
  76. this.context = iClientRfActionContext;
  77. this.sessionData = sessionData;
  78. super.addStateChangeNotification(stateChangeListener);
  79. }
  80. public void sendAccountRequest(RfAccountingRequest accountRequest) throws InternalException, IllegalStateException, RouteException, OverloadException {
  81. try {
  82. sendAndStateLock.lock();
  83. handleEvent(new Event(accountRequest));
  84. try {
  85. session.send(accountRequest.getMessage(), this);
  86. // Store last destination information
  87. sessionData.setDestinationRealm(accountRequest.getMessage().getAvps().getAvp(Avp.DESTINATION_REALM).getDiameterIdentity());
  88. Avp destHostAvp = accountRequest.getMessage().getAvps().getAvp(Avp.DESTINATION_HOST);
  89. if(destHostAvp != null) {
  90. sessionData.setDestinationHost(destHostAvp.getDiameterIdentity());
  91. }
  92. }
  93. catch (Throwable t) {
  94. logger.debug("Failed to send ACR.", t);
  95. handleEvent(new Event(Event.Type.FAILED_SEND_RECORD, accountRequest));
  96. }
  97. }
  98. catch (Exception exc) {
  99. throw new InternalException(exc);
  100. }
  101. finally {
  102. sendAndStateLock.unlock();
  103. }
  104. }
  105. protected synchronized void storeToBuffer(Request accountRequest) {
  106. sessionData.setBuffer(accountRequest);
  107. }
  108. protected synchronized boolean checkBufferSpace() {
  109. return sessionData.getBuffer() == null;
  110. }
  111. @SuppressWarnings("unchecked")
  112. protected void setState(IAppSessionState newState) {
  113. IAppSessionState oldState = sessionData.getClientRfSessionState();
  114. sessionData.setClientRfSessionState((ClientRfSessionState) newState);
  115. for (StateChangeListener i : stateListeners) {
  116. i.stateChanged(this,(Enum) oldState, (Enum) newState);
  117. }
  118. }
  119. public boolean isStateless() {
  120. return false;
  121. }
  122. public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
  123. final ClientRfSessionState state = this.sessionData.getClientRfSessionState();
  124. ClientRfSessionState oldState = state;
  125. try {
  126. switch (state) {
  127. // Idle ==========
  128. case IDLE: {
  129. switch ((Event.Type) event.getType()) {
  130. // Client or device requests access
  131. case SEND_START_RECORD:
  132. // Current State: IDLE
  133. // Event: Client or Device Requests access
  134. // Action: Send accounting start req.
  135. // New State: PENDING_S
  136. setState(PENDING_START);
  137. break;
  138. case SEND_EVENT_RECORD:
  139. // Current State: IDLE
  140. // Event: Client or device requests a one-time service
  141. // Action: Send accounting event req
  142. // New State: PENDING_E
  143. setState(PENDING_EVENT);
  144. break;
  145. // Send buffered message action in other section of this method see below
  146. default:
  147. throw new IllegalStateException("Current state " + state + " action " + event.getType());
  148. }
  149. break;
  150. }
  151. // PendingS ==========
  152. case PENDING_START: {
  153. switch ((Event.Type) event.getType()) {
  154. case FAILED_SEND_RECORD:
  155. RfAccountingRequest request = (RfAccountingRequest) event.getData();
  156. Avp accRtReq = request.getMessage().getAvps().getAvp(ACCOUNTING_REALTIME_REQUIRED);
  157. // Current State: PENDING_S
  158. // Event: Failure to send and buffer space available and realtime not equal to DELIVER_AND_GRANT
  159. // Action: Store Start Record
  160. // New State: OPEN
  161. if (checkBufferSpace() && accRtReq != null && accRtReq.getInteger32() != DELIVER_AND_GRANT) {
  162. storeToBuffer((Request) request.getMessage());
  163. setState(OPEN);
  164. }
  165. else {
  166. // Current State: PENDING_S
  167. // Event: Failure to send and no buffer space available and realtime equal to GRANT_AND_LOSE
  168. // Action: -
  169. // New State: OPEN
  170. if (!checkBufferSpace() && accRtReq != null && accRtReq.getInteger32() == GRANT_AND_LOSE) {
  171. setState(OPEN);
  172. }
  173. else {
  174. // Current State: PENDING_S
  175. // Event: Failure to send and no buffer space available and realtime not equal to GRANT_AND_LOSE
  176. // Action: Disconnect User/Device
  177. // New State: IDLE
  178. try{
  179. if (context != null) {
  180. Request str = createSessionTermRequest();
  181. context.disconnectUserOrDev(this, str);
  182. session.send(str, this);
  183. }
  184. }
  185. finally {
  186. setState(IDLE);
  187. }
  188. }
  189. }
  190. break;
  191. case RECEIVED_RECORD:
  192. // Current State: PENDING_S
  193. // Event: Successful accounting start answer received
  194. // Action: -
  195. // New State: OPEN
  196. processInterimIntervalAvp(event);
  197. setState(OPEN);
  198. break;
  199. case FAILED_RECEIVE_RECORD:
  200. try {
  201. RfAccountingRequest answer = (RfAccountingRequest) event.getData();
  202. accRtReq = answer.getMessage().getAvps().getAvp(ACCOUNTING_REALTIME_REQUIRED);
  203. // Current State: PENDING_S
  204. // Event: Failed accounting start answer received and realtime equal to GRANT_AND_LOSE
  205. // Action: -
  206. // New State: OPEN
  207. if (accRtReq != null && accRtReq.getInteger32() == GRANT_AND_LOSE) {
  208. setState(OPEN);
  209. }
  210. else {
  211. // Current State: PENDING_S
  212. // Event: Failed accounting start answer received and realtime not equal to GRANT_AND_LOSE
  213. // Action: Disconnect User/Device
  214. // New State: IDLE
  215. if (accRtReq != null && accRtReq.getInteger32() != GRANT_AND_LOSE) {
  216. try {
  217. if (context != null) {
  218. Request str = createSessionTermRequest();
  219. context.disconnectUserOrDev(this, str);
  220. session.send(str, this);
  221. }
  222. }
  223. finally {
  224. setState(IDLE);
  225. }
  226. }
  227. }
  228. }
  229. catch (Exception e) {
  230. logger.debug("Can not process answer", e);
  231. setState(IDLE);
  232. }
  233. break;
  234. case SEND_STOP_RECORD:
  235. // Current State: PENDING_S
  236. // Event: User service terminated
  237. // Action: Store stop record
  238. // New State: PENDING_S
  239. if (context != null) {
  240. Request str = createSessionTermRequest();
  241. context.disconnectUserOrDev(this,str);
  242. storeToBuffer(str);
  243. }
  244. break;
  245. }
  246. break;
  247. }
  248. // OPEN ==========
  249. case OPEN: {
  250. switch ((Event.Type) event.getType()) {
  251. // User service terminated
  252. case SEND_STOP_RECORD:
  253. // Current State: OPEN
  254. // Event: User service terminated
  255. // Action: Send accounting stop request
  256. // New State: PENDING_L
  257. setState(PENDING_CLOSE);
  258. break;
  259. case SEND_INTERIM_RECORD:
  260. // FIXME: Shouldn't this be different ?
  261. // Current State: OPEN
  262. // Event: Interim interval elapses
  263. // Action: Send accounting interim record
  264. // New State: PENDING_I
  265. setState(PENDING_INTERIM);
  266. break;
  267. // Create timer for "Interim interval elapses" event
  268. case RECEIVED_RECORD:
  269. processInterimIntervalAvp(event);
  270. break;
  271. }
  272. }
  273. break;
  274. //FIXME: add check for abnormal
  275. // PendingI ==========
  276. case PENDING_INTERIM: {
  277. switch ((Event.Type) event.getType()) {
  278. case RECEIVED_RECORD:
  279. // Current State: PENDING_I
  280. // Event: Successful accounting interim answer received
  281. // Action: -
  282. // New State: OPEN
  283. processInterimIntervalAvp(event);
  284. setState(OPEN);
  285. break;
  286. case FAILED_SEND_RECORD:
  287. RfAccountingRequest request = (RfAccountingRequest) event.getData();
  288. Avp accRtReq = ((Message) event.getData()).getAvps().getAvp(ACCOUNTING_REALTIME_REQUIRED);
  289. // Current State: PENDING_I
  290. // Event: Failure to send and buffer space available (or old record interim can be overwritten) and realtime not equal to DELIVER_AND_GRANT
  291. // Action: Store interim record
  292. // New State: OPEN
  293. if (checkBufferSpace() && accRtReq != null && accRtReq.getInteger32() != DELIVER_AND_GRANT) {
  294. storeToBuffer((Request) request.getMessage());
  295. setState(OPEN);
  296. }
  297. else {
  298. // Current State: PENDING_I
  299. // Event: Failure to send and no buffer space available and realtime equal to GRANT_AND_LOSE
  300. // Action: -
  301. // New State: OPEN
  302. if (!checkBufferSpace() && accRtReq != null && accRtReq.getInteger32() == GRANT_AND_LOSE) {
  303. setState(OPEN);
  304. }
  305. else {
  306. // Current State: PENDING_I
  307. // Event: Failure to send and no buffer space available and realtime not equal to GRANT_AND_LOSE
  308. // Action: Disconnect User/Device
  309. // New State: IDLE
  310. if (!checkBufferSpace() && accRtReq != null && accRtReq.getInteger32() != GRANT_AND_LOSE) {
  311. try {
  312. if (context != null) {
  313. Request str = createSessionTermRequest();
  314. context.disconnectUserOrDev(this, str);
  315. session.send(str, this);
  316. }
  317. }
  318. finally {
  319. setState(IDLE);
  320. }
  321. }
  322. }
  323. }
  324. break;
  325. case FAILED_RECEIVE_RECORD:
  326. try {
  327. RfAccountingRequest answer = (RfAccountingRequest) event.getData();
  328. accRtReq = answer.getMessage().getAvps().getAvp(ACCOUNTING_REALTIME_REQUIRED);
  329. // Current State: PENDING_I
  330. // Event: Failed accounting interim answer received and realtime equal to GRANT_AND_LOSE
  331. // Action: -
  332. // New State: OPEN
  333. if (accRtReq != null && accRtReq.getInteger32() == GRANT_AND_LOSE) {
  334. setState(OPEN);
  335. }
  336. else {
  337. // Current State: PENDING_I
  338. // Event: Failed account interim answer received and realtime not equal to GRANT_AND_LOSE
  339. // Action: Disconnect User/Device
  340. // New State: IDLE
  341. if (accRtReq != null && accRtReq.getInteger32() != GRANT_AND_LOSE) {
  342. try {
  343. if (context != null) {
  344. Request str = createSessionTermRequest();
  345. context.disconnectUserOrDev(this,str);
  346. session.send(str, this);
  347. }
  348. }
  349. finally {
  350. setState(IDLE);
  351. }
  352. }
  353. }
  354. }
  355. catch (Exception e) {
  356. logger.debug("Can not process received request", e);
  357. setState(IDLE);
  358. }
  359. break;
  360. case SEND_STOP_RECORD:
  361. // Current State: PENDING_I
  362. // Event: User service terminated
  363. // Action: Store stop record
  364. // New State: PENDING_I
  365. if (context != null) {
  366. Request str = createSessionTermRequest();
  367. context.disconnectUserOrDev(this,str);
  368. storeToBuffer(str);
  369. }
  370. break;
  371. }
  372. break;
  373. }
  374. // PendingE ==========
  375. case PENDING_EVENT: {
  376. switch ((Event.Type) event.getType()) {
  377. case RECEIVED_RECORD:
  378. // Current State: PENDING_E
  379. // Event: Successful accounting event answer received
  380. // Action: -
  381. // New State: IDLE
  382. setState(IDLE);
  383. break;
  384. case FAILED_SEND_RECORD:
  385. if (checkBufferSpace()) {
  386. // Current State: PENDING_E
  387. // Event: Failure to send and buffer space available
  388. // Action: Store event record
  389. // New State: IDLE
  390. RfAccountingRequest data = (RfAccountingRequest) event.getData();
  391. storeToBuffer((Request) data.getMessage());
  392. }
  393. // Current State: PENDING_E
  394. // Event: Failure to send and no buffer space available
  395. // Action: -
  396. // New State: IDLE
  397. setState(IDLE);
  398. break;
  399. case FAILED_RECEIVE_RECORD:
  400. // Current State: PENDING_E
  401. // Event: Failed accounting event answer received
  402. // Action: -
  403. // New State: IDLE
  404. setState(IDLE);
  405. break;
  406. }
  407. break;
  408. }
  409. // PendingB ==========
  410. case PENDING_BUFFERED: {
  411. switch ((Event.Type) event.getType()) {
  412. case RECEIVED_RECORD:
  413. // Current State: PENDING_B
  414. // Event: Successful accounting answer received
  415. // Action: Delete record
  416. // New State: IDLE
  417. synchronized (this) {
  418. storeToBuffer(null);
  419. }
  420. setState(IDLE);
  421. break;
  422. // Failure to send
  423. case FAILED_SEND_RECORD:
  424. // Current State: PENDING_B
  425. // Event: Failure to send
  426. // Action: -
  427. // New State: IDLE
  428. setState(IDLE);
  429. break;
  430. // Failed accounting answer received
  431. case FAILED_RECEIVE_RECORD:
  432. // Current State: PENDING_B
  433. // Event: Failed accounting answer received
  434. // Action: Delete record
  435. // New State: IDLE
  436. synchronized (this) {
  437. storeToBuffer(null);
  438. }
  439. setState(IDLE);
  440. break;
  441. }
  442. break;
  443. }
  444. // PendingL ==========
  445. case PENDING_CLOSE: {
  446. switch ((Event.Type) event.getType()) {
  447. case RECEIVED_RECORD:
  448. // Current State: PENDING_L
  449. // Event: Successful accounting stop answer received
  450. // Action: -
  451. // New State: IDLE
  452. setState(IDLE);
  453. break;
  454. case FAILED_SEND_RECORD:
  455. if (checkBufferSpace()) {
  456. // Current State: PENDING_L
  457. // Event: Failure to send and buffer space available
  458. // Action: Store stop record
  459. // New State: IDLE
  460. RfAccountingRequest data = (RfAccountingRequest) event.getData();
  461. storeToBuffer((Request) data.getMessage());
  462. }
  463. // Current State: PENDING_L
  464. // Event: Failure to send and no buffer space available
  465. // Action: -
  466. // New State: IDLE
  467. setState(IDLE);
  468. break;
  469. // Failed accounting stop answer received
  470. case FAILED_RECEIVE_RECORD:
  471. // Current State: PENDING_L
  472. // Event: Failed accounting stop answer received
  473. // Action: -
  474. // New State: IDLE
  475. setState(IDLE);
  476. break;
  477. }
  478. break;
  479. }
  480. }
  481. // Post processing
  482. if (oldState != state) {
  483. switch (state) {
  484. // IDLE ===========
  485. case IDLE:
  486. {
  487. // Current State: IDLE
  488. // Event: Records in storage
  489. // Action: Send record
  490. // New State: PENDING_B
  491. try {
  492. synchronized (this) {
  493. if (sessionData.getBuffer() != null) {
  494. session.send(sessionData.getBuffer(), this);
  495. setState(PENDING_BUFFERED);
  496. }
  497. }
  498. }
  499. catch (Exception e) {
  500. logger.debug("can not send buffered message", e);
  501. synchronized (this) {
  502. Request buffer = sessionData.getBuffer();
  503. if (context != null && buffer != null) {
  504. if (!context.failedSendRecord(this,buffer)) {
  505. storeToBuffer(null);
  506. }
  507. }
  508. }
  509. }
  510. }
  511. }
  512. }
  513. }
  514. catch (Throwable t) {
  515. throw new InternalException(t);
  516. }
  517. return true;
  518. }
  519. protected void processInterimIntervalAvp(StateEvent event) throws InternalException {
  520. // Avp interval = ((AppEvent) event.getData()).getMessage().getAvps().getAvp(Avp.ACCT_INTERIM_INTERVAL);
  521. // if (interval != null) {
  522. // // create timer
  523. // try {
  524. // long v = interval.getUnsigned32();
  525. // if (v != 0) {
  526. // // scheduler.schedule(
  527. // // new Runnable() {
  528. // // public void run() {
  529. // // if (context != null) {
  530. // // try {
  531. // // Request interimRecord = createInterimRecord();
  532. // // context.interimIntervalElapses(interimRecord);
  533. // // sendAndStateLock.lock();
  534. // // session.send(interimRecord, ClientRfSessionImpl.this);
  535. // // setState(PENDING_INTERIM);
  536. // // }
  537. // // catch (Exception e) {
  538. // // logger.debug("Can not process Interim Interval AVP", e);
  539. // // }
  540. // // finally {
  541. // // sendAndStateLock.unlock();
  542. // // }
  543. // // }
  544. // // }
  545. // // },
  546. // // v, TimeUnit.SECONDS
  547. // // );
  548. // cancelInterimTimer();
  549. // this.timerId_interim = startInterimTimer(v);
  550. // }
  551. // }
  552. // catch (AvpDataException e) {
  553. // logger.debug("Unable to retrieve Acct-Interim-Interval AVP value", e);
  554. // }
  555. // }
  556. }
  557. /* (non-Javadoc)
  558. * @see org.jdiameter.common.impl.app.AppSessionImpl#onTimer(java.lang.String)
  559. */
  560. @Override
  561. public void onTimer(String timerName) {
  562. if(timerName.equals(TIMER_NAME_INTERIM)) {
  563. if (context != null) {
  564. try {
  565. Request interimRecord = createInterimRecord();
  566. context.interimIntervalElapses(this,interimRecord);
  567. sendAndStateLock.lock();
  568. session.send(interimRecord, ClientRfSessionImpl.this);
  569. setState(PENDING_INTERIM);
  570. sessionData.setTsTimerId(null);
  571. }
  572. catch (Exception e) {
  573. logger.debug("Can not process Interim Interval AVP", e);
  574. }
  575. finally {
  576. sendAndStateLock.unlock();
  577. }
  578. }
  579. }
  580. else {
  581. }
  582. }
  583. private void startInterimTimer(long v) {
  584. try{
  585. sendAndStateLock.lock();
  586. sessionData.setTsTimerId(super.timerFacility.schedule(getSessionId(), TIMER_NAME_INTERIM, v));
  587. return;
  588. }
  589. finally {
  590. sendAndStateLock.unlock();
  591. }
  592. }
  593. private void cancelInterimTimer() {
  594. try{
  595. sendAndStateLock.lock();
  596. final Serializable timerId = this.sessionData.getTsTimerId();
  597. if(timerId != null) {
  598. super.timerFacility.cancel(timerId);
  599. this.sessionData.setTsTimerId(null);
  600. }
  601. }
  602. finally {
  603. sendAndStateLock.unlock();
  604. }
  605. }
  606. @SuppressWarnings("unchecked")
  607. public <E> E getState(Class<E> eClass) {
  608. return eClass == ClientRfSessionState.class ? (E) this.sessionData.getTsTimerId() : null;
  609. }
  610. public void receivedSuccessMessage(Request request, Answer answer) {
  611. if (request.getCommandCode() == RfAccountingRequest.code) {
  612. // state should be changed before event listener call
  613. try {
  614. sendAndStateLock.lock();
  615. handleEvent(new Event(createAccountAnswer(answer)));
  616. }
  617. catch (Exception e) {
  618. logger.debug("Can not process received request", e);
  619. }
  620. finally {
  621. sendAndStateLock.unlock();
  622. }
  623. try {
  624. listener.doRfAccountingAnswerEvent(this, createAccountRequest(request), createAccountAnswer(answer));
  625. }
  626. catch (Exception e) {
  627. logger.debug("Unable to deliver message to listener.", e);
  628. }
  629. }
  630. else {
  631. try {
  632. listener.doOtherEvent(this, createAccountRequest(request), createAccountAnswer(answer));
  633. }
  634. catch (Exception e) {
  635. logger.debug("Can not process received request", e);
  636. }
  637. }
  638. }
  639. public void timeoutExpired(Request request) {
  640. try {
  641. sendAndStateLock.lock();
  642. handleEvent(new Event(Event.Type.FAILED_RECEIVE_RECORD, createAccountRequest(request)));
  643. }
  644. catch (Exception e) {
  645. logger.debug("Can not handle timeout event", e);
  646. }
  647. finally {
  648. sendAndStateLock.unlock();
  649. }
  650. }
  651. public Answer processRequest(Request request) {
  652. if (request.getCommandCode() == RfAccountingRequest.code) {
  653. try {
  654. // FIXME Is this wrong?
  655. listener.doRfAccountingAnswerEvent(this, createAccountRequest(request), null);
  656. }
  657. catch (Exception e) {
  658. logger.debug("Can not process received request", e);
  659. }
  660. }
  661. else {
  662. try {
  663. listener.doOtherEvent(this, createAccountRequest(request), null);
  664. }
  665. catch (Exception e) {
  666. logger.debug("Can not process received request", e);
  667. }
  668. }
  669. return null;
  670. }
  671. /* (non-Javadoc)
  672. * @see org.jdiameter.common.impl.app.AppSessionImpl#isReplicable()
  673. */
  674. @Override
  675. public boolean isReplicable() {
  676. return true;
  677. }
  678. protected Request createInterimRecord() {
  679. Request interimRecord = session.createRequest(RfAccountingRequest.code, appId, sessionData.getDestinationRealm(), sessionData.getDestinationHost());
  680. interimRecord.getAvps().addAvp(Avp.ACC_RECORD_TYPE, 3);
  681. return interimRecord;
  682. }
  683. protected Request createSessionTermRequest() {
  684. return session.createRequest(Message.SESSION_TERMINATION_REQUEST, appId, sessionData.getDestinationRealm(), sessionData.getDestinationHost());
  685. }
  686. @Override
  687. public int hashCode() {
  688. final int prime = 31;
  689. int result = super.hashCode();
  690. result = prime * result + ((sessionData == null) ? 0 : sessionData.hashCode());
  691. return result;
  692. }
  693. @Override
  694. public boolean equals(Object obj) {
  695. if (this == obj)
  696. return true;
  697. if (!super.equals(obj))
  698. return false;
  699. if (getClass() != obj.getClass())
  700. return false;
  701. ClientRfSessionImpl other = (ClientRfSessionImpl) obj;
  702. if (sessionData == null) {
  703. if (other.sessionData != null)
  704. return false;
  705. } else if (!sessionData.equals(other.sessionData))
  706. return false;
  707. return true;
  708. }
  709. @Override
  710. public void release() {
  711. if (isValid()) {
  712. try {
  713. sendAndStateLock.lock();
  714. //TODO: cancel timer?
  715. super.release();
  716. }
  717. catch (Exception e) {
  718. logger.debug("Failed to release session", e);
  719. }
  720. finally {
  721. sendAndStateLock.unlock();
  722. }
  723. }
  724. else {
  725. logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
  726. }
  727. }
  728. }