PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/cca/ClientCCASessionImpl.java

http://mobicents.googlecode.com/
Java | 1342 lines | 929 code | 111 blank | 302 comment | 188 complexity | 5a64e93c4b08c05edbe4031bba346460 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

Large files files are truncated, but you can click here to view the full file

  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.cca;
  23. import java.io.Serializable;
  24. import java.util.ArrayList;
  25. import java.util.Collections;
  26. import java.util.HashSet;
  27. import java.util.Set;
  28. import java.util.concurrent.locks.Lock;
  29. import java.util.concurrent.locks.ReentrantLock;
  30. import org.jdiameter.api.Answer;
  31. import org.jdiameter.api.AvpDataException;
  32. import org.jdiameter.api.EventListener;
  33. import org.jdiameter.api.IllegalDiameterStateException;
  34. import org.jdiameter.api.InternalException;
  35. import org.jdiameter.api.Message;
  36. import org.jdiameter.api.NetworkReqListener;
  37. import org.jdiameter.api.OverloadException;
  38. import org.jdiameter.api.Request;
  39. import org.jdiameter.api.RouteException;
  40. import org.jdiameter.api.app.AppAnswerEvent;
  41. import org.jdiameter.api.app.AppEvent;
  42. import org.jdiameter.api.app.AppSession;
  43. import org.jdiameter.api.app.StateChangeListener;
  44. import org.jdiameter.api.app.StateEvent;
  45. import org.jdiameter.api.auth.events.ReAuthAnswer;
  46. import org.jdiameter.api.auth.events.ReAuthRequest;
  47. import org.jdiameter.api.cca.ClientCCASession;
  48. import org.jdiameter.api.cca.ClientCCASessionListener;
  49. import org.jdiameter.api.cca.events.JCreditControlAnswer;
  50. import org.jdiameter.api.cca.events.JCreditControlRequest;
  51. import org.jdiameter.client.api.ISessionFactory;
  52. import org.jdiameter.client.impl.app.cca.Event.Type;
  53. import org.jdiameter.common.api.app.IAppSessionState;
  54. import org.jdiameter.common.api.app.cca.ClientCCASessionState;
  55. import org.jdiameter.common.api.app.cca.ICCAMessageFactory;
  56. import org.jdiameter.common.api.app.cca.IClientCCASessionContext;
  57. import org.jdiameter.common.impl.app.AppAnswerEventImpl;
  58. import org.jdiameter.common.impl.app.AppEventImpl;
  59. import org.jdiameter.common.impl.app.AppRequestEventImpl;
  60. import org.jdiameter.common.impl.app.auth.ReAuthAnswerImpl;
  61. import org.jdiameter.common.impl.app.cca.AppCCASessionImpl;
  62. import org.slf4j.Logger;
  63. import org.slf4j.LoggerFactory;
  64. /**
  65. * Client Credit-Control Application session implementation
  66. *
  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 ClientCCASessionImpl extends AppCCASessionImpl implements ClientCCASession, NetworkReqListener, EventListener<Request, Answer> {
  71. private static final Logger logger = LoggerFactory.getLogger(ClientCCASessionImpl.class);
  72. // session data pojo, local reference so we dont have to cast super.data to IClientCCASessionData
  73. protected IClientCCASessionData sessionData;
  74. // Session State Handling ---------------------------------------------------
  75. protected Lock sendAndStateLock = new ReentrantLock();
  76. // Session Based Queue
  77. protected ArrayList<Event> eventQueue = new ArrayList<Event>(); //FIXME: this is not replicable?
  78. // Factories and Listeners --------------------------------------------------
  79. protected ICCAMessageFactory factory;
  80. protected ClientCCASessionListener listener;
  81. protected IClientCCASessionContext context;
  82. protected final static String TX_TIMER_NAME = "CCA_CLIENT_TX_TIMER";
  83. protected static final long TX_TIMER_DEFAULT_VALUE = 30 * 60 * 1000; // miliseconds
  84. protected long[] authAppIds = new long[] { 4 };
  85. // Requested Action + Credit-Control and Direct-Debiting Failure-Handling ---
  86. public static final int NON_INITIALIZED = -300;
  87. protected static final int CCFH_TERMINATE = 0;
  88. protected static final int CCFH_CONTINUE = 1;
  89. protected static final int CCFH_RETRY_AND_TERMINATE = 2;
  90. private static final int DDFH_TERMINATE_OR_BUFFER = 0;
  91. private static final int DDFH_CONTINUE = 1;
  92. // CC-Request-Type Values ---------------------------------------------------
  93. private static final int DIRECT_DEBITING = 0;
  94. private static final int REFUND_ACCOUNT = 1;
  95. private static final int CHECK_BALANCE = 2;
  96. private static final int PRICE_ENQUIRY = 3;
  97. private static final int EVENT_REQUEST = 4;
  98. // Error Codes --------------------------------------------------------------
  99. private static final long END_USER_SERVICE_DENIED = 4010;
  100. private static final long CREDIT_CONTROL_NOT_APPLICABLE = 4011;
  101. private static final long USER_UNKNOWN = 5030;
  102. private static final long DIAMETER_UNABLE_TO_DELIVER = 3002L;
  103. private static final long DIAMETER_TOO_BUSY = 3004L;
  104. private static final long DIAMETER_LOOP_DETECTED = 3005L;
  105. protected static final Set<Long> temporaryErrorCodes;
  106. static {
  107. HashSet<Long> tmp = new HashSet<Long>();
  108. tmp.add(DIAMETER_UNABLE_TO_DELIVER);
  109. tmp.add(DIAMETER_TOO_BUSY);
  110. tmp.add(DIAMETER_LOOP_DETECTED);
  111. temporaryErrorCodes = Collections.unmodifiableSet(tmp);
  112. }
  113. public ClientCCASessionImpl(IClientCCASessionData data, ICCAMessageFactory fct, ISessionFactory sf, ClientCCASessionListener lst,IClientCCASessionContext ctx, StateChangeListener<AppSession> stLst) {
  114. super(sf,data);
  115. if (lst == null) {
  116. throw new IllegalArgumentException("Listener can not be null");
  117. }
  118. if (data == null) {
  119. throw new IllegalArgumentException("SessionData can not be null");
  120. }
  121. if (fct.getApplicationIds() == null) {
  122. throw new IllegalArgumentException("ApplicationId can not be less than zero");
  123. }
  124. this.sessionData = data;
  125. this.context = (IClientCCASessionContext)ctx;
  126. this.authAppIds = fct.getApplicationIds();
  127. this.listener = lst;
  128. this.factory = fct;
  129. super.addStateChangeNotification(stLst);
  130. }
  131. protected int getLocalCCFH() {
  132. return sessionData.getGatheredCCFH() >= 0 ? sessionData.getGatheredCCFH() : context.getDefaultCCFHValue();
  133. }
  134. protected int getLocalDDFH() {
  135. return sessionData.getGatheredDDFH() >= 0 ? sessionData.getGatheredDDFH() : context.getDefaultDDFHValue();
  136. }
  137. public void sendCreditControlRequest(JCreditControlRequest request) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  138. extractFHAVPs(request, null);
  139. this.handleEvent(new Event(true, request, null));
  140. }
  141. public void sendReAuthAnswer(ReAuthAnswer answer) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  142. this.handleEvent(new Event(Event.Type.SEND_RAA, null, answer));
  143. }
  144. public boolean isStateless() {
  145. return false;
  146. }
  147. public boolean isEventBased() {
  148. return this.sessionData.isEventBased();
  149. }
  150. @SuppressWarnings("unchecked")
  151. public <E> E getState(Class<E> stateType) {
  152. return stateType == ClientCCASessionState.class ? (E) this.sessionData.getClientCCASessionState() : null;
  153. }
  154. public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
  155. return this.isEventBased() ? handleEventForEventBased(event) : handleEventForSessionBased(event);
  156. }
  157. protected boolean handleEventForEventBased(StateEvent event) throws InternalException, OverloadException {
  158. try {
  159. sendAndStateLock.lock();
  160. final Event localEvent = (Event) event;
  161. final Event.Type eventType = (Type) localEvent.getType();
  162. final ClientCCASessionState state = this.sessionData.getClientCCASessionState();
  163. switch (state) {
  164. case IDLE:
  165. switch (eventType) {
  166. case SEND_EVENT_REQUEST:
  167. // Current State: IDLE
  168. // Event: Client or device requests a one-time service
  169. // Action: Send CC event request, start Tx
  170. // New State: PENDING_E
  171. startTx((JCreditControlRequest) localEvent.getRequest());
  172. setState(ClientCCASessionState.PENDING_EVENT);
  173. try {
  174. dispatchEvent(localEvent.getRequest());
  175. }
  176. catch (Exception e) {
  177. // This handles failure to send in PendingI state in FSM table
  178. logger.debug("Failure handling send event request", e);
  179. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  180. }
  181. break;
  182. default:
  183. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  184. break;
  185. }
  186. break;
  187. case PENDING_EVENT:
  188. switch (eventType) {
  189. case RECEIVE_EVENT_ANSWER:
  190. AppAnswerEvent answer = (AppAnswerEvent) localEvent.getAnswer();
  191. try {
  192. long resultCode = answer.getResultCodeAvp().getUnsigned32();
  193. if (isSuccess(resultCode)) {
  194. // Current State: PENDING_E
  195. // Event: Successful CC event answer received
  196. // Action: Grant service to end user
  197. // New State: IDLE
  198. setState(ClientCCASessionState.IDLE, false);
  199. }
  200. if (isProvisional(resultCode) || isFailure(resultCode)) {
  201. handleFailureMessage((JCreditControlAnswer) answer, (JCreditControlRequest) localEvent.getRequest(), eventType);
  202. }
  203. deliverCCAnswer((JCreditControlRequest) localEvent.getRequest(), (JCreditControlAnswer) localEvent.getAnswer());
  204. }
  205. catch (AvpDataException e) {
  206. logger.debug("Failure handling received answer event", e);
  207. setState(ClientCCASessionState.IDLE, false);
  208. }
  209. break;
  210. case Tx_TIMER_FIRED:
  211. handleTxExpires(localEvent.getRequest().getMessage());
  212. break;
  213. default:
  214. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  215. break;
  216. }
  217. break;
  218. case PENDING_BUFFERED:
  219. switch (eventType) {
  220. case RECEIVE_EVENT_ANSWER:
  221. // Current State: PENDING_B
  222. // Event: Successful CC answer received
  223. // Action: Delete request
  224. // New State: IDLE
  225. setState(ClientCCASessionState.IDLE, false);
  226. sessionData.setBuffer(null);
  227. deliverCCAnswer((JCreditControlRequest) localEvent.getRequest(), (JCreditControlAnswer) localEvent.getAnswer());
  228. break;
  229. default:
  230. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  231. break;
  232. }
  233. break;
  234. default:
  235. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  236. break;
  237. }
  238. dispatch();
  239. return true;
  240. }
  241. catch (Exception e) {
  242. throw new InternalException(e);
  243. }
  244. finally {
  245. sendAndStateLock.unlock();
  246. }
  247. }
  248. protected boolean handleEventForSessionBased(StateEvent event) throws InternalException, OverloadException {
  249. try {
  250. sendAndStateLock.lock();
  251. Event localEvent = (Event) event;
  252. Event.Type eventType = (Type) localEvent.getType();
  253. ClientCCASessionState state = this.sessionData.getClientCCASessionState();
  254. switch (state) {
  255. case IDLE:
  256. switch (eventType) {
  257. case SEND_INITIAL_REQUEST:
  258. // Current State: IDLE
  259. // Event: Client or device requests access/service
  260. // Action: Send CC initial request, start Tx
  261. // New State: PENDING_I
  262. startTx((JCreditControlRequest) localEvent.getRequest());
  263. setState(ClientCCASessionState.PENDING_INITIAL);
  264. try {
  265. dispatchEvent(localEvent.getRequest());
  266. }
  267. catch (Exception e) {
  268. // This handles failure to send in PendingI state in FSM table
  269. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  270. }
  271. break;
  272. default:
  273. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  274. break;
  275. }
  276. break;
  277. case PENDING_INITIAL:
  278. AppAnswerEvent answer = (AppAnswerEvent) localEvent.getAnswer();
  279. switch (eventType) {
  280. case RECEIVED_INITIAL_ANSWER:
  281. long resultCode = answer.getResultCodeAvp().getUnsigned32();
  282. if (isSuccess(resultCode)) {
  283. // Current State: PENDING_I
  284. // Event: Successful CC initial answer received
  285. // Action: Stop Tx
  286. // New State: OPEN
  287. stopTx();
  288. setState(ClientCCASessionState.OPEN);
  289. }
  290. else if (isProvisional(resultCode) || isFailure(resultCode)) {
  291. handleFailureMessage((JCreditControlAnswer) answer, (JCreditControlRequest) localEvent.getRequest(), eventType);
  292. }
  293. deliverCCAnswer((JCreditControlRequest) localEvent.getRequest(), (JCreditControlAnswer) localEvent.getAnswer());
  294. break;
  295. case Tx_TIMER_FIRED:
  296. handleTxExpires(localEvent.getRequest().getMessage());
  297. break;
  298. case SEND_UPDATE_REQUEST:
  299. case SEND_TERMINATE_REQUEST:
  300. // Current State: PENDING_I
  301. // Event: User service terminated
  302. // Action: Queue termination event
  303. // New State: PENDING_I
  304. // Current State: PENDING_I
  305. // Event: Change in rating condition
  306. // Action: Queue changed rating condition event
  307. // New State: PENDING_I
  308. eventQueue.add(localEvent);
  309. break;
  310. default:
  311. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  312. break;
  313. }
  314. break;
  315. case OPEN:
  316. switch (eventType) {
  317. case SEND_UPDATE_REQUEST:
  318. // Current State: OPEN
  319. // Event: Granted unit elapses and no final unit indication received
  320. // Action: Send CC update request, start Tx
  321. // New State: PENDING_U
  322. // Current State: OPEN
  323. // Event: Change in rating condition in queue
  324. // Action: Send CC update request, start Tx
  325. // New State: PENDING_U
  326. // Current State: OPEN
  327. // Event: Change in rating condition or Validity-Time elapses
  328. // Action: Send CC update request, start Tx
  329. // New State: PENDING_U
  330. // Current State: OPEN
  331. // Event: RAR received
  332. // Action: Send RAA followed by CC update request, start Tx
  333. // New State: PENDING_U
  334. startTx((JCreditControlRequest) localEvent.getRequest());
  335. setState(ClientCCASessionState.PENDING_UPDATE);
  336. try {
  337. dispatchEvent(localEvent.getRequest());
  338. }
  339. catch (Exception e) {
  340. // This handles failure to send in PendingI state in FSM table
  341. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  342. }
  343. break;
  344. case SEND_TERMINATE_REQUEST:
  345. // Current State: OPEN
  346. // Event: Granted unit elapses and final unit action equal to TERMINATE received
  347. // Action: Terminate end user?s service, send CC termination request
  348. // New State: PENDING_T
  349. // Current State: OPEN
  350. // Event: Service terminated in queue
  351. // Action: Send CC termination request
  352. // New State: PENDING_T
  353. // Current State: OPEN
  354. // Event: User service terminated
  355. // Action: Send CC termination request
  356. // New State: PENDING_T
  357. setState(ClientCCASessionState.PENDING_TERMINATION);
  358. try {
  359. dispatchEvent(localEvent.getRequest());
  360. }
  361. catch (Exception e) {
  362. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  363. }
  364. break;
  365. case RECEIVED_RAR:
  366. deliverRAR((ReAuthRequest) localEvent.getRequest());
  367. break;
  368. case SEND_RAA:
  369. try {
  370. dispatchEvent(localEvent.getAnswer());
  371. }
  372. catch (Exception e) {
  373. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  374. }
  375. break;
  376. default:
  377. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  378. break;
  379. }
  380. break;
  381. case PENDING_UPDATE:
  382. answer = (AppAnswerEvent) localEvent.getAnswer();
  383. switch (eventType) {
  384. case RECEIVED_UPDATE_ANSWER:
  385. long resultCode = answer.getResultCodeAvp().getUnsigned32();
  386. if (isSuccess(resultCode)) {
  387. // Current State: PENDING_U
  388. // Event: Successful CC update answer received
  389. // Action: Stop Tx
  390. // New State: OPEN
  391. stopTx();
  392. setState(ClientCCASessionState.OPEN);
  393. }
  394. else if (isProvisional(resultCode) || isFailure(resultCode)) {
  395. handleFailureMessage((JCreditControlAnswer) answer, (JCreditControlRequest) localEvent.getRequest(), eventType);
  396. }
  397. deliverCCAnswer((JCreditControlRequest) localEvent.getRequest(), (JCreditControlAnswer) localEvent.getAnswer());
  398. break;
  399. case Tx_TIMER_FIRED:
  400. handleTxExpires(localEvent.getRequest().getMessage());
  401. break;
  402. case SEND_UPDATE_REQUEST:
  403. case SEND_TERMINATE_REQUEST:
  404. // Current State: PENDING_U
  405. // Event: User service terminated
  406. // Action: Queue termination event
  407. // New State: PENDING_U
  408. // Current State: PENDING_U
  409. // Event: Change in rating condition
  410. // Action: Queue changed rating condition event
  411. // New State: PENDING_U
  412. eventQueue.add(localEvent);
  413. break;
  414. case RECEIVED_RAR:
  415. deliverRAR((ReAuthRequest) localEvent.getRequest());
  416. break;
  417. case SEND_RAA:
  418. // Current State: PENDING_U
  419. // Event: RAR received
  420. // Action: Send RAA
  421. // New State: PENDING_U
  422. try {
  423. dispatchEvent(localEvent.getAnswer());
  424. }
  425. catch (Exception e) {
  426. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  427. }
  428. break;
  429. }
  430. break;
  431. case PENDING_TERMINATION:
  432. switch (eventType) {
  433. case SEND_UPDATE_REQUEST:
  434. try {
  435. // Current State: PENDING_T
  436. // Event: Change in rating condition
  437. // Action: -
  438. // New State: PENDING_T
  439. dispatchEvent(localEvent.getRequest());
  440. // No transition
  441. }
  442. catch (Exception e) {
  443. // This handles failure to send in PendingI state in FSM table
  444. // handleSendFailure(e, eventType);
  445. }
  446. break;
  447. case RECEIVED_TERMINATED_ANSWER:
  448. // Current State: PENDING_T
  449. // Event: Successful CC termination answer received
  450. // Action: -
  451. // New State: IDLE
  452. // Current State: PENDING_T
  453. // Event: Failure to send, temporary error, or failed answer
  454. // Action: -
  455. // New State: IDLE
  456. //FIXME: Alex broke this, setting back "true" ?
  457. //setState(ClientCCASessionState.IDLE, false);
  458. deliverCCAnswer((JCreditControlRequest) localEvent.getRequest(), (JCreditControlAnswer) localEvent.getAnswer());
  459. setState(ClientCCASessionState.IDLE, true);
  460. break;
  461. default:
  462. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  463. break;
  464. }
  465. break;
  466. default:
  467. // any other state is bad
  468. setState(ClientCCASessionState.IDLE, true);
  469. }
  470. dispatch();
  471. return true;
  472. }
  473. catch (Exception e) {
  474. throw new InternalException(e);
  475. }
  476. finally {
  477. sendAndStateLock.unlock();
  478. }
  479. }
  480. public Answer processRequest(Request request) {
  481. RequestDelivery rd = new RequestDelivery();
  482. rd.session = this;
  483. rd.request = request;
  484. super.scheduler.execute(rd);
  485. return null;
  486. }
  487. public void receivedSuccessMessage(Request request, Answer answer) {
  488. AnswerDelivery ad = new AnswerDelivery();
  489. ad.session = this;
  490. ad.request = request;
  491. ad.answer = answer;
  492. super.scheduler.execute(ad);
  493. }
  494. public void timeoutExpired(Request request) {
  495. if(request.getCommandCode()== JCreditControlAnswer.code) {
  496. try {
  497. handleSendFailure(null, null, request);
  498. }
  499. catch (Exception e) {
  500. logger.debug("Failure processing timeout message for request", e);
  501. }
  502. }
  503. }
  504. protected void startTx(JCreditControlRequest request) {
  505. long txTimerValue = context.getDefaultTxTimerValue();
  506. if (txTimerValue < 0) {
  507. txTimerValue = TX_TIMER_DEFAULT_VALUE;
  508. }
  509. stopTx();
  510. logger.debug("Scheduling TX Timer {}", txTimerValue);
  511. //this.txFuture = scheduler.schedule(new TxTimerTask(this, request), txTimerValue, TimeUnit.SECONDS);
  512. try {
  513. this.sessionData.setTxTimerRequest((Request) ((AppEventImpl)request).getMessage());
  514. }
  515. catch (Exception e) {
  516. throw new IllegalArgumentException("Failed to store request.", e);
  517. }
  518. this.sessionData.setTxTimerId(this.timerFacility.schedule(this.getSessionId(), TX_TIMER_NAME, TX_TIMER_DEFAULT_VALUE));
  519. }
  520. protected void stopTx() {
  521. Serializable txTimerId = this.sessionData.getTxTimerId();
  522. if(txTimerId!= null) {
  523. this.sessionData.setTxTimerRequest(null);
  524. this.timerFacility.cancel(txTimerId);
  525. this.sessionData.setTxTimerId(null);
  526. }
  527. }
  528. /* (non-Javadoc)
  529. * @see org.jdiameter.common.impl.app.AppSessionImpl#onTimer(java.lang.String)
  530. */
  531. @Override
  532. public void onTimer(String timerName) {
  533. if(timerName.equals(TX_TIMER_NAME)) {
  534. new TxTimerTask(this, this.sessionData.getTxTimerRequest()).run();
  535. }
  536. }
  537. protected void setState(ClientCCASessionState newState) {
  538. setState(newState, true);
  539. }
  540. @SuppressWarnings("unchecked")
  541. protected void setState(ClientCCASessionState newState, boolean release) {
  542. try {
  543. IAppSessionState oldState = this.sessionData.getClientCCASessionState();
  544. this.sessionData.setClientCCASessionState(newState);
  545. for (StateChangeListener i : stateListeners) {
  546. i.stateChanged(this,(Enum) oldState, (Enum) newState);
  547. }
  548. if (newState == ClientCCASessionState.IDLE) {
  549. if (release) {
  550. this.release();
  551. }
  552. stopTx();
  553. }
  554. }
  555. catch (Exception e) {
  556. if(logger.isDebugEnabled()) {
  557. logger.debug("Failure switching to state " + this.sessionData.getClientCCASessionState() + " (release=" + release + ")", e);
  558. }
  559. }
  560. }
  561. @Override
  562. public void release() {
  563. if (isValid()) {
  564. try {
  565. this.sendAndStateLock.lock();
  566. super.release();
  567. }
  568. catch (Exception e) {
  569. logger.debug("Failed to release session", e);
  570. }
  571. finally {
  572. sendAndStateLock.unlock();
  573. }
  574. }
  575. else {
  576. logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
  577. }
  578. }
  579. protected void handleSendFailure(Exception e, Event.Type eventType, Message request) throws Exception {
  580. logger.debug("Failed to send message, type: {} message: {}, failure: {}", new Object[]{eventType, request, e != null ? e.getLocalizedMessage() : ""});
  581. try {
  582. this.sendAndStateLock.lock();
  583. ClientCCASessionState state = this.sessionData.getClientCCASessionState();
  584. int gatheredRequestedAction = this.sessionData.getGatheredRequestedAction();
  585. // Event Based ----------------------------------------------------------
  586. if (isEventBased()) {
  587. switch (state) {
  588. case PENDING_EVENT:
  589. if (gatheredRequestedAction == CHECK_BALANCE || gatheredRequestedAction == PRICE_ENQUIRY) {
  590. // Current State: PENDING_E
  591. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action CHECK_BALANCE or PRICE_ENQUIRY
  592. // Action: Indicate service error
  593. // New State: IDLE
  594. setState(ClientCCASessionState.IDLE);
  595. context.indicateServiceError(this);
  596. }
  597. else if (gatheredRequestedAction == DIRECT_DEBITING) {
  598. switch(getLocalDDFH()) {
  599. case DDFH_TERMINATE_OR_BUFFER:
  600. // Current State: PENDING_E
  601. // Event: Failure to send; request action DIRECT_DEBITING; DDFH equal to TERMINATE_OR_BUFFER
  602. // Action: Store request with T-flag
  603. // New State: IDLE
  604. request.setReTransmitted(true);
  605. this.sessionData.setBuffer((Request) ((AppEventImpl)request).getMessage());
  606. setState(ClientCCASessionState.IDLE, false);
  607. break;
  608. case DDFH_CONTINUE:
  609. // Current State: PENDING_E
  610. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action DIRECT_DEBITING; DDFH equal to CONTINUE
  611. // Action: Grant service to end user
  612. // New State: IDLE
  613. context.grantAccessOnDeliverFailure(this, request);
  614. break;
  615. default:
  616. logger.warn("Invalid Direct-Debiting-Failure-Handling AVP value {}", getLocalDDFH());
  617. }
  618. }
  619. else if (gatheredRequestedAction == REFUND_ACCOUNT) {
  620. // Current State: PENDING_E
  621. // Event: Failure to send or Tx expired; requested action REFUND_ACCOUNT
  622. // Action: Store request with T-flag
  623. // New State: IDLE
  624. setState(ClientCCASessionState.IDLE, false);
  625. request.setReTransmitted(true);
  626. this.sessionData.setBuffer((Request) ((AppEventImpl)request).getMessage());
  627. }
  628. else {
  629. logger.warn("Invalid Requested-Action AVP value {}", gatheredRequestedAction);
  630. }
  631. break;
  632. case PENDING_BUFFERED:
  633. // Current State: PENDING_B
  634. // Event: Failure to send or temporary error
  635. // Action: -
  636. // New State: IDLE
  637. setState(ClientCCASessionState.IDLE, false);
  638. this.sessionData.setBuffer(null); // FIXME: Action does not mention, but ...
  639. break;
  640. default:
  641. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  642. break;
  643. }
  644. }
  645. // Session Based --------------------------------------------------------
  646. else {
  647. switch (getLocalCCFH()) {
  648. case CCFH_CONTINUE:
  649. // Current State: PENDING_I
  650. // Event: Failure to send, or temporary error and CCFH equal to CONTINUE
  651. // Action: Grant service to end user
  652. // New State: IDLE
  653. // Current State: PENDING_U
  654. // Event: Failure to send, or temporary error and CCFH equal to CONTINUE
  655. // Action: Grant service to end user
  656. // New State: IDLE
  657. setState(ClientCCASessionState.IDLE, false);
  658. this.context.grantAccessOnDeliverFailure(this, request);
  659. break;
  660. default:
  661. // Current State: PENDING_I
  662. // Event: Failure to send, or temporary error and CCFH equal to TERMINATE or to RETRY_AND_TERMINATE
  663. // Action: Terminate end user?s service
  664. // New State: IDLE
  665. // Current State: PENDING_U
  666. // Event: Failure to send, or temporary error and CCFH equal to TERMINATE or to RETRY_AND_TERMINATE
  667. // Action: Terminate end user?s service
  668. // New State: IDLE
  669. this.context.denyAccessOnDeliverFailure(this, request);
  670. setState(ClientCCASessionState.IDLE, true);
  671. break;
  672. }
  673. }
  674. dispatch();
  675. }
  676. finally {
  677. this.sendAndStateLock.unlock();
  678. }
  679. }
  680. protected void handleFailureMessage(JCreditControlAnswer event, JCreditControlRequest request, Event.Type eventType) {
  681. try {
  682. // Event Based ----------------------------------------------------------
  683. long resultCode = event.getResultCodeAvp().getUnsigned32();
  684. ClientCCASessionState state = this.sessionData.getClientCCASessionState();
  685. Serializable txTimerId = this.sessionData.getTxTimerId();
  686. int gatheredRequestedAction = this.sessionData.getGatheredRequestedAction();
  687. if (isEventBased()) {
  688. switch (state) {
  689. case PENDING_EVENT:
  690. if (resultCode == END_USER_SERVICE_DENIED || resultCode == USER_UNKNOWN) {
  691. if(txTimerId != null) {
  692. // Current State: PENDING_E
  693. // Event: CC event answer received with result code END_USER_SERVICE_DENIED or USER_UNKNOWN and Tx running
  694. // Action: Terminate end user?s service
  695. // New State: IDLE
  696. context.denyAccessOnFailureMessage(this);
  697. deliverCCAnswer(request, event);
  698. setState(ClientCCASessionState.IDLE);
  699. }
  700. else if(gatheredRequestedAction == DIRECT_DEBITING && txTimerId == null) {
  701. // Current State: PENDING_E
  702. // Event: Failed answer or answer received with result code END_USER_SERVICE DENIED or USER_UNKNOWN; requested action DIRECT_DEBITING; Tx expired
  703. // Action: -
  704. // New State: IDLE
  705. setState(ClientCCASessionState.IDLE);
  706. }
  707. }
  708. else if (resultCode == CREDIT_CONTROL_NOT_APPLICABLE && gatheredRequestedAction == DIRECT_DEBITING) {
  709. // Current State: PENDING_E
  710. // Event: CC event answer received with result code CREDIT_CONTROL_NOT_APPLICABLE; requested action DIRECT_DEBITING
  711. // Action: Grant service to end user
  712. // New State: IDLE
  713. context.grantAccessOnFailureMessage(this);
  714. deliverCCAnswer(request, event);
  715. setState(ClientCCASessionState.IDLE);
  716. }
  717. else if (temporaryErrorCodes.contains(resultCode)) {
  718. if (gatheredRequestedAction == CHECK_BALANCE || gatheredRequestedAction == PRICE_ENQUIRY) {
  719. // Current State: PENDING_E
  720. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action CHECK_BALANCE or PRICE_ENQUIRY
  721. // Action: Indicate service error
  722. // New State: IDLE
  723. context.indicateServiceError(this);
  724. deliverCCAnswer(request, event);
  725. setState(ClientCCASessionState.IDLE);
  726. }
  727. else if (gatheredRequestedAction == DIRECT_DEBITING) {
  728. if(getLocalDDFH() == DDFH_CONTINUE) {
  729. // Current State: PENDING_E
  730. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action DIRECT_DEBITING; DDFH equal to CONTINUE
  731. // Action: Grant service to end user
  732. // New State: IDLE
  733. context.grantAccessOnFailureMessage(this);
  734. deliverCCAnswer(request, event);
  735. setState(ClientCCASessionState.IDLE);
  736. }
  737. else if (getLocalDDFH() == DDFH_TERMINATE_OR_BUFFER && txTimerId != null) {
  738. // Current State: PENDING_E
  739. // Event: Failed CC event answer received or temporary error; requested action DIRECT_DEBITING; DDFH equal to TERMINATE_OR_BUFFER and Tx running
  740. // Action: Terminate end user?s service
  741. // New State: IDLE
  742. context.denyAccessOnFailureMessage(this);
  743. deliverCCAnswer(request, event);
  744. setState(ClientCCASessionState.IDLE);
  745. }
  746. }
  747. else if (gatheredRequestedAction == REFUND_ACCOUNT) {
  748. // Current State: PENDING_E
  749. // Event: Temporary error, and requested action REFUND_ACCOUNT
  750. // Action: Store request
  751. // New State: IDLE
  752. this.sessionData.setBuffer((Request) ((AppEventImpl)request).getMessage());
  753. setState(ClientCCASessionState.IDLE, false);
  754. }
  755. else {
  756. logger.warn("Invalid combination for CCA Client FSM: State {}, Result-Code {}, Requested-Action {}, DDFH {}, Tx {}", new Object[]{state, resultCode, gatheredRequestedAction, getLocalDDFH(), txTimerId});
  757. }
  758. }
  759. else { // Failure
  760. if (gatheredRequestedAction == CHECK_BALANCE || gatheredRequestedAction == PRICE_ENQUIRY) {
  761. // Current State: PENDING_E
  762. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action CHECK_BALANCE or PRICE_ENQUIRY
  763. // Action: Indicate service error
  764. // New State: IDLE
  765. context.indicateServiceError(this);
  766. deliverCCAnswer(request, event);
  767. setState(ClientCCASessionState.IDLE);
  768. }
  769. else if (gatheredRequestedAction == DIRECT_DEBITING) {
  770. if(getLocalDDFH() == DDFH_CONTINUE) {
  771. // Current State: PENDING_E
  772. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action DIRECT_DEBITING; DDFH equal to CONTINUE
  773. // Action: Grant service to end user
  774. // New State: IDLE
  775. context.grantAccessOnFailureMessage(this);
  776. deliverCCAnswer(request, event);
  777. setState(ClientCCASessionState.IDLE);
  778. }
  779. else if (getLocalDDFH() == DDFH_TERMINATE_OR_BUFFER && txTimerId != null) {
  780. // Current State: PENDING_E
  781. // Event: Failed CC event answer received or temporary error; requested action DIRECT_DEBITING; DDFH equal to TERMINATE_OR_BUFFER and Tx running
  782. // Action: Terminate end user?s service
  783. // New State: IDLE
  784. context.denyAccessOnFailureMessage(this);
  785. deliverCCAnswer(request, event);
  786. setState(ClientCCASessionState.IDLE);
  787. }
  788. }
  789. else if (gatheredRequestedAction == REFUND_ACCOUNT) {
  790. // Current State: PENDING_E
  791. // Event: Failed CC event answer received; requested action REFUND_ACCOUNT
  792. // Action: Indicate service error and delete request
  793. // New State: IDLE
  794. this.sessionData.setBuffer(null);
  795. context.indicateServiceError(this);
  796. deliverCCAnswer(request, event);
  797. setState(ClientCCASessionState.IDLE);
  798. }
  799. else {
  800. logger.warn("Invalid combination for CCA Client FSM: State {}, Result-Code {}, Requested-Action {}, DDFH {}, Tx {}", new Object[]{state, resultCode, gatheredRequestedAction, getLocalDDFH(), txTimerId});
  801. }
  802. }
  803. break;
  804. case PENDING_BUFFERED:
  805. // Current State: PENDING_B
  806. // Event: Failed CC answer received
  807. // Action: Delete request
  808. // New State: IDLE
  809. this.sessionData.setBuffer(null);
  810. setState(ClientCCASessionState.IDLE, false);
  811. break;
  812. default:
  813. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  814. }
  815. }
  816. // Session Based --------------------------------------------------------
  817. else {
  818. switch (state) {
  819. case PENDING_INITIAL:
  820. if (resultCode == CREDIT_CONTROL_NOT_APPLICABLE) {
  821. // Current State: PENDING_I
  822. // Event: CC initial answer received with result code equal to CREDIT_CONTROL_NOT_APPLICABLE
  823. // Action: Grant service to end user
  824. // New State: IDLE
  825. context.grantAccessOnFailureMessage(this);
  826. setState(ClientCCASessionState.IDLE, false);
  827. }
  828. else if ((resultCode == END_USER_SERVICE_DENIED) || (resultCode == USER_UNKNOWN)) {
  829. // Current State: PENDING_I
  830. // Event: CC initial answer received with result code END_USER_SERVICE_DENIED or USER_UNKNOWN
  831. // Action: Terminate end user?s service
  832. // New State: IDLE
  833. context.denyAccessOnFailureMessage(this);
  834. setState(ClientCCASessionState.IDLE, false);
  835. }
  836. else {
  837. // Temporary errors and others
  838. switch (getLocalCCFH()) {
  839. case CCFH_CONTINUE:
  840. // Current State: PENDING_I
  841. // Event: Failed CC initial answer received and CCFH equal to CONTINUE
  842. // Action: Grant service to end user
  843. // New State: IDLE
  844. context.grantAccessOnFailureMessage(this);
  845. setState(ClientCCASessionState.IDLE, false);
  846. break;
  847. case CCFH_TERMINATE:
  848. case CCFH_RETRY_AND_TERMINATE:
  849. // Current State: PENDING_I
  850. // Event: Failed CC initial answer received and CCFH equal to TERMINATE or to RETRY_AND_TERMINATE
  851. // Action: Terminate end user?s service
  852. // New State: IDLE
  853. context.denyAccessOnFailureMessage(this);
  854. setState(ClientCCASessionState.IDLE, false);
  855. break;
  856. default:
  857. logger.warn("Invalid value for CCFH: {}", getLocalCCFH());
  858. break;
  859. }
  860. }
  861. break;
  862. case PENDING_UPDATE:
  863. if (resultCode == CREDIT_CONTROL_NOT_APPLICABLE) {
  864. // Current State: PENDING_U
  865. // Event: CC update answer received with result code equal to CREDIT_CONTROL_NOT_APPLICABLE
  866. // Action: Grant service to end user
  867. // New State: IDLE
  868. context.grantAccessOnFailureMessage(this);
  869. setState(ClientCCASessionState.IDLE, false);
  870. }
  871. else if (resultCode == END_USER_SERVICE_DENIED) {
  872. // Current State: PENDING_U
  873. // Event: CC update answer received with result code END_USER_SERVICE_DENIED
  874. // Action: Terminate end user?s service
  875. // New State: IDLE
  876. context.denyAccessOnFailureMessage(this);
  877. setState(ClientCCASessionState.IDLE, false);
  878. }
  879. else {
  880. // Temporary errors and others
  881. switch (getLocalCCFH()) {
  882. case CCFH_CONTINUE:
  883. // Current State: PENDING_U
  884. // Event: Failed CC update answer received and CCFH equal to CONTINUE
  885. // Action: Grant service to end user
  886. // New State: IDLE
  887. context.grantAccessOnFailureMessage(this);
  888. setState(ClientCCASessionState.IDLE, false);
  889. break;
  890. case CCFH_TERMINATE:
  891. case CCFH_RETRY_AND_TERMINATE:
  892. // Current State: PENDING_U
  893. // Event: Failed CC update answer received and CCFH equal to CONTINUE or to RETRY_AND_CONTINUE
  894. // Action: Terminate end user?s service
  895. // New State: IDLE
  896. context.denyAccessOnFailureMessage(this);
  897. setState(ClientCCASessionState.IDLE, false);
  898. break;
  899. default:
  900. logger.warn("Invalid value for CCFH: " + getLocalCCFH());
  901. break;
  902. }
  903. }
  904. break;
  905. default:
  906. logger.warn("Wrong event type ({}) on state {}", eventType, state);
  907. }
  908. }
  909. }
  910. catch (Exception e) {
  911. if(logger.isDebugEnabled()) {
  912. logger.debug("Failure handling failure message for Event " + event + " (" + eventType + ") and Request " + request, e);
  913. }
  914. }
  915. }
  916. protected void handleTxExpires(Message message) {
  917. // Event Based ----------------------------------------------------------
  918. ClientCCASessionState state = this.sessionData.getClientCCASessionState();
  919. Serializable txTimerId = this.sessionData.getTxTimerId();
  920. int gatheredRequestedAction = this.sessionData.getGatheredRequestedAction();
  921. int gatheredDDFH = this.sessionData.getGatheredDDFH();
  922. if (isEventBased()) {
  923. if (gatheredRequestedAction == CHECK_BALANCE || gatheredRequestedAction == PRICE_ENQUIRY) {
  924. // Current State: PENDING_E
  925. // Event: Failure to send, temporary error, failed CC event answer received or Tx expired; requested action CHECK_BALANCE or PRICE_ENQUIRY
  926. // Action: Indicate service error
  927. // New State: IDLE
  928. context.indicateServiceError(this);
  929. setState(ClientCCASessionState.IDLE);
  930. }
  931. else if (gatheredRequestedAction == DIRECT_DEBITING) {
  932. if(gatheredDDFH == DDFH_TERMINATE_OR_BUFFER) {
  933. // Current State: PENDING_E
  934. // Event: Temporary error; requested action DIRECT_DEBITING; DDFH equal to TERMINATE_OR_BUFFER; Tx expired
  935. // Action: Store request
  936. // New State: IDLE
  937. this.sessionData.setBuffer((Request) message);
  938. setState(ClientCCASessionState.IDLE, false);
  939. }
  940. else {
  941. // Current State: PENDING_E
  942. // Event: Tx expired; requested action DIRECT_DEBITING
  943. // Action: Grant service to end user
  944. // New State: PENDING_E
  945. context.grantAccessOnTxExpire(this);
  946. setState(ClientCCASessionState.PENDING_EVENT);
  947. }
  948. }
  949. else if (gatheredRequestedAction == REFUND_ACCOUNT) {
  950. // Current State: PENDING_E
  951. // Event: Failure to send or Tx expired; requested action REFUND_ACCOUNT
  952. // Action: Store request with T-flag
  953. // New State: IDLE
  954. message.setReTransmitted(true);
  955. this.sessionData.setBuffer((Request) message);
  956. setState(ClientCCASessionState.IDLE, false);
  957. }
  958. }
  959. // Session Based --------------------------------------------------------
  960. else {
  961. switch (state) {
  962. case PENDING_INITIAL:
  963. switch (getLocalCCFH()) {
  964. case CCFH_CONTINUE:
  965. case CCFH_RETRY_AND_TERMINATE:
  966. // Current State: PENDING_I
  967. // Event: Tx expired and CCFH equal to CONTINUE or to RETRY_AND_TERMINATE
  968. // Action: Grant service to end user
  969. // New State: PENDING_I
  970. context.grantAccessOnTxExpire(this);
  971. break;
  972. case CCFH_TERMINATE:
  973. // Current State: PENDING_I
  974. // Event: Tx expired and CCFH equal to TERMINATE
  975. // Action: Terminate end user?s service
  976. // New State: IDLE
  977. context.denyAccessOnTxExpire(this);
  978. setState(ClientCCASessionState.IDLE, true);
  979. break;
  980. default:
  981. logger.warn("Invalid value for CCFH: " + getLocalCCFH());
  982. break;
  983. }
  984. break;
  985. case PENDING_UPDATE:
  986. switch (getLocalCCFH()) {
  987. case CCFH_CONTINUE:
  988. case CCFH_RETRY_AND_TERMINATE:
  989. // Current State: PENDING_U
  990. // Event: Tx expired and CCFH equal to CONTINUE or to RETRY_AND_TERMINATE
  991. // Action: Grant service to end user
  992. // New State: PENDING_U
  993. context.grantAccessOnTxExpire(this);
  994. break;
  995. case CCFH_TERMINATE:
  996. // Current State: PENDING_U
  997. // Event: Tx expired and CCFH equal to TERMINATE
  998. // Action: Terminate end user?s service
  999. // New State: IDLE
  1000. context.denyAccessOnTxExpire(this);
  1001. setState(ClientCCASessionState.IDLE, true);
  1002. break;
  1003. default:
  1004. logger.error("Bad value of CCFH: " + getLocalCCFH());
  1005. break;
  1006. }
  1007. break;
  1008. default:
  1009. logger.error("Unknown state (" + state + ") on txExpire");
  1010. break;
  1011. }
  1012. }
  1013. }
  1014. /**
  1015. * This makes checks on queue, moves it to proper state if event there is
  1016. * present on Open state ;]
  1017. */
  1018. protected void dispatch() {
  1019. // Event Based ----------------------------------------------------------
  1020. if (isEventBased()) {
  1021. // Current State: IDLE
  1022. // Event: Request in storage
  1023. // Action: Send stored request
  1024. // New State: PENDING_B
  1025. Request buffer = this.sessionData.getBuffer();
  1026. if (buffer != null) {
  1027. setState(ClientCCASessionState.PENDING_BUFFERED);
  1028. try {
  1029. dispatchEvent(new AppRequestEventImpl(buffer));
  1030. }
  1031. catch (Exception e) {
  1032. try {
  1033. handleSendFailure(e, Event.Type.SEND_EVENT_REQUEST, buffer);
  1034. }
  1035. catch (Exception e1) {
  1036. logger.error("Failure handling buffer send failure", e1);
  1037. }
  1038. }
  1039. }
  1040. }
  1041. // Session Based --------------------------------------------------------
  1042. else {
  1043. if (this.sessionData.getClientCCASessionState() == ClientCCASessionState.OPEN && eventQueue.size() > 0) {
  1044. try {
  1045. this.handleEvent(eventQueue.remove(0));
  1046. }
  1047. catch (Exception e) {
  1048. logger.error("Failure handling queued event", e);
  1049. }
  1050. }
  1051. }
  1052. }
  1053. protected void deliverCCAnswer(JCreditControlRequest request, JCreditControlAnswer answer) {
  1054. try {
  1055. listener.doCreditControlAnswer(this, request, answer);
  1056. }
  1057. catch (Exception e) {
  1058. logger.warn("Failure delivering CCA Answer", e);
  1059. }
  1060. }
  1061. protected void extractFHAVPs(JCreditControlRequest request, JCreditControlAnswer answer) {
  1062. if (answer != null) {
  1063. try {
  1064. if (answer.isCreditControlFailureHandlingAVPPresent()) {
  1065. this.sessionData.setGatheredCCFH(answer.getCredidControlFailureHandlingAVPValue());
  1066. }
  1067. }
  1068. catch (Exception e) {
  1069. logger.debug("Failure trying to obtain Credit-Control-Failure-Handling AVP value", e);
  1070. }
  1071. try {
  1072. if (answer.isDirectDebitingFailureHandlingAVPPresent()) {
  1073. this.sessionData.setGatheredDDFH(answer.getDirectDebitingFailureHandlingAVPValue());
  1074. }
  1075. }
  1076. catch (Exception e) {
  1077. logger.debug("Failure trying to obtain Direct-Debit-Failure-Handling AVP value", e);
  1078. }
  1079. if(!this.sessionData.isRequestTypeSet()) {
  1080. this.sessionData.setRequestTypeSet(true);
  1081. // No need to check if it exists.. it must, if not fail with exception
  1082. this.sessionData.setEventBased(answer.getRequestTypeAVPValue() == EVENT_REQUEST);
  1083. }
  1084. }
  1085. else if (request != null) {
  1086. try {
  1087. if (request.isRequestedActionAVPPresent()) {
  1088. this.sessionData.setGatheredRequestedAction(request.getRequestedActionAVPValue());
  1089. }
  1090. }
  1091. catch (Exception e) {
  1092. logger.debug("Failure trying to obtain Request-Action AVP value", e);
  1093. }
  1094. if(!this.sessionData.isRequestTypeSet()) {
  1095. this.sessionData.setRequestTypeSet(true);
  1096. // No need to check if it exists.. it must, if not fail with exception
  1097. this.sessionData.setEventBased(request.getRequestTypeAVPValue() == EVENT_REQUEST);
  1098. }
  1099. }
  1100. }
  1101. protected void deliverRAR(ReAuthRequest request) {
  1102. try {
  1103. listener.doReAuthRequest(this, request);
  1104. }
  1105. catch (Exception e) {
  1106. logger.debug("Failure delivering RAR", e);
  1107. }
  1108. }
  1109. protected void dispatchEvent(AppEvent event) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  1110. session.send(event.getMessage(), this);
  1111. }
  1112. protected boolean isProvisional(long resultCode) {
  1113. return resultCode >= 1000 && resultCode < 2000;
  1114. }
  1115. protected boolean isSuccess(long resultCode) {
  1116. return resultCode >= 2000 && resultCode < 3000;
  1117. }
  1118. protected boolean isFailure(long code) {
  1119. return (!isProvisional(code) && !isSuccess(code) && ((code >= 3000 && /*code < 4000) || (code >= 5000 &&*/ code < 6000)) && !temporaryErrorCodes.contains(code));
  1120. }
  1121. /* (non-Javadoc)
  1122. * @see org.jdiameter.common.impl.app.AppSessionImpl#isReplicable()
  1123. */
  1124. @Override
  1125. public boolean isReplicable() {
  1126. return true;
  1127. }
  1128. private class TxTimerTask implements Runnable {
  1129. private ClientCCASession session = null;
  1130. private Request request = null;
  1131. private TxTimerTask(ClientCCASession session, Request request) {
  1132. super();
  1133. this.session = session;
  1134. this.request = request;
  1135. }
  1136. public void run() {
  1137. try {
  1138. sendAndStateLock.lock();
  1139. logger.debug("Fired TX Timer");
  1140. sessionData.setTxTimerId(null);
  1141. try {
  1142. context.txTimerExpired(session);
  1143. }
  1144. catch (Exception e) {
  1145. logger.debug("Failure handling TX…

Large files files are truncated, but you can click here to view the full file