PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/acc/ClientAccSessionImpl.java

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