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

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/rx/ClientRxSessionImpl.java

http://mobicents.googlecode.com/
Java | 851 lines | 634 code | 72 blank | 145 comment | 81 complexity | 642216bc55879c49dbe0cbd39038c9c9 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 2011, 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.rx;
  23. import java.nio.ByteBuffer;
  24. import java.util.ArrayList;
  25. import java.util.Arrays;
  26. import java.util.Collections;
  27. import java.util.HashSet;
  28. import java.util.Set;
  29. import java.util.concurrent.locks.Lock;
  30. import java.util.concurrent.locks.ReentrantLock;
  31. import org.jdiameter.api.Answer;
  32. import org.jdiameter.api.AvpDataException;
  33. import org.jdiameter.api.EventListener;
  34. import org.jdiameter.api.IllegalDiameterStateException;
  35. import org.jdiameter.api.InternalException;
  36. import org.jdiameter.api.Message;
  37. import org.jdiameter.api.NetworkReqListener;
  38. import org.jdiameter.api.OverloadException;
  39. import org.jdiameter.api.Request;
  40. import org.jdiameter.api.RouteException;
  41. import org.jdiameter.api.app.AppAnswerEvent;
  42. import org.jdiameter.api.app.AppEvent;
  43. import org.jdiameter.api.app.AppSession;
  44. import org.jdiameter.api.app.StateChangeListener;
  45. import org.jdiameter.api.app.StateEvent;
  46. import org.jdiameter.api.rx.ClientRxSession;
  47. import org.jdiameter.api.rx.ClientRxSessionListener;
  48. import org.jdiameter.api.rx.events.RxAAAnswer;
  49. import org.jdiameter.api.rx.events.RxAARequest;
  50. import org.jdiameter.api.rx.events.RxAbortSessionAnswer;
  51. import org.jdiameter.api.rx.events.RxAbortSessionRequest;
  52. import org.jdiameter.api.rx.events.RxReAuthAnswer;
  53. import org.jdiameter.api.rx.events.RxReAuthRequest;
  54. import org.jdiameter.api.rx.events.RxSessionTermAnswer;
  55. import org.jdiameter.api.rx.events.RxSessionTermRequest;
  56. import org.jdiameter.client.api.IContainer;
  57. import org.jdiameter.client.api.IMessage;
  58. import org.jdiameter.client.api.ISessionFactory;
  59. import org.jdiameter.client.api.parser.IMessageParser;
  60. import org.jdiameter.client.api.parser.ParseException;
  61. import org.jdiameter.client.impl.app.rx.Event.Type;
  62. import org.jdiameter.common.api.app.IAppSessionState;
  63. import org.jdiameter.common.api.app.rx.ClientRxSessionState;
  64. import org.jdiameter.common.api.app.rx.IClientRxSessionContext;
  65. import org.jdiameter.common.api.app.rx.IRxMessageFactory;
  66. import org.jdiameter.common.impl.app.AppAnswerEventImpl;
  67. import org.jdiameter.common.impl.app.AppRequestEventImpl;
  68. import org.jdiameter.common.impl.app.rx.AppRxSessionImpl;
  69. import org.slf4j.Logger;
  70. import org.slf4j.LoggerFactory;
  71. /**
  72. * 3GPP IMS Rx Reference Point Client Session implementation
  73. *
  74. * @author <a href="mailto:richard.good@smilecoms.com"> Richard Good </a>
  75. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  76. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  77. */
  78. public class ClientRxSessionImpl extends AppRxSessionImpl implements ClientRxSession, NetworkReqListener, EventListener<Request, Answer> {
  79. private static final Logger logger = LoggerFactory.getLogger(ClientRxSessionImpl.class);
  80. // Session State Handling ---------------------------------------------------
  81. //protected boolean isEventBased = true;
  82. //protected boolean requestTypeSet = false;
  83. //protected ClientRxSessionState state = ClientRxSessionState.IDLE;
  84. protected Lock sendAndStateLock = new ReentrantLock();
  85. // Factories and Listeners --------------------------------------------------
  86. protected transient IRxMessageFactory factory;
  87. protected transient ClientRxSessionListener listener;
  88. protected transient IClientRxSessionContext context;
  89. protected transient IMessageParser parser;
  90. protected IClientRxSessionData sessionData;
  91. // protected String originHost, originRealm;
  92. protected long[] authAppIds = new long[]{4};
  93. // Requested Action + Credit-Control and Direct-Debiting Failure-Handling ---
  94. static final int NON_INITIALIZED = -300;
  95. // Session State Handling ---------------------------------------------------
  96. protected boolean isEventBased = false;
  97. //protected boolean requestTypeSet = false;
  98. protected ClientRxSessionState state = ClientRxSessionState.IDLE;
  99. protected byte[] buffer;
  100. protected String originHost, originRealm;
  101. // Error Codes --------------------------------------------------------------
  102. private static final long INVALID_SERVICE_INFORMATION = 5061L;
  103. private static final long FILTER_RESTRICTIONS = 5062L;
  104. private static final long REQUESTED_SERVICE_NOT_AUTHORIZED = 5063L;
  105. private static final long DUPLICATED_AF_SESSION = 5064L;
  106. private static final long IP_CAN_SESSION_NOT_AVAILABLE = 5065L;
  107. private static final long UNAUTHORIZED_NON_EMERGENCY_SESSION = 5066L;
  108. private static final long UNAUTHORIZED_SPONSORED_DATA_CONNECTIVITY = 5067L;
  109. private static final long DIAMETER_UNABLE_TO_DELIVER = 3002L;
  110. private static final long DIAMETER_TOO_BUSY = 3004L;
  111. private static final long DIAMETER_LOOP_DETECTED = 3005L;
  112. protected static final Set<Long> temporaryErrorCodes;
  113. static {
  114. HashSet<Long> tmp = new HashSet<Long>();
  115. tmp.add(DIAMETER_UNABLE_TO_DELIVER);
  116. tmp.add(DIAMETER_TOO_BUSY);
  117. tmp.add(DIAMETER_LOOP_DETECTED);
  118. temporaryErrorCodes = Collections.unmodifiableSet(tmp);
  119. }
  120. // Session Based Queue
  121. protected ArrayList<Event> eventQueue = new ArrayList<Event>();
  122. public ClientRxSessionImpl(IClientRxSessionData sessionData, IRxMessageFactory fct, ISessionFactory sf, ClientRxSessionListener lst, IClientRxSessionContext ctx,
  123. StateChangeListener<AppSession> stLst) {
  124. super(sf, sessionData);
  125. if (lst == null) {
  126. throw new IllegalArgumentException("Listener can not be null");
  127. }
  128. if (fct.getApplicationIds() == null) {
  129. throw new IllegalArgumentException("ApplicationId can not be less than zero");
  130. }
  131. this.context = (IClientRxSessionContext) ctx;
  132. this.authAppIds = fct.getApplicationIds();
  133. this.listener = lst;
  134. this.factory = fct;
  135. IContainer icontainer = sf.getContainer();
  136. this.parser = icontainer.getAssemblerFacility().getComponentInstance(IMessageParser.class);
  137. this.sessionData = sessionData;
  138. super.addStateChangeNotification(stLst);
  139. }
  140. public void sendAARequest(RxAARequest request) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  141. try {
  142. this.handleEvent(new Event(true, request, null));
  143. }
  144. catch (AvpDataException e) {
  145. throw new InternalException(e);
  146. }
  147. }
  148. public void sendSessionTermRequest(RxSessionTermRequest request) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  149. try {
  150. this.handleEvent(new Event(true, request, null));
  151. }
  152. catch (AvpDataException e) {
  153. throw new InternalException(e);
  154. }
  155. }
  156. public void sendReAuthAnswer(RxReAuthAnswer answer) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  157. this.handleEvent(new Event(Event.Type.SEND_RAA, null, answer));
  158. }
  159. public void sendAbortSessionAnswer(RxAbortSessionAnswer answer) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  160. this.handleEvent(new Event(Event.Type.SEND_ASA, null, answer));
  161. }
  162. public boolean isStateless() {
  163. return false;
  164. }
  165. public boolean isEventBased() {
  166. return this.isEventBased;
  167. }
  168. @SuppressWarnings("unchecked")
  169. public <E> E getState(Class<E> stateType) {
  170. return stateType == ClientRxSessionState.class ? (E) state : null;
  171. }
  172. public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
  173. return this.isEventBased() ? handleEventForEventBased(event) : handleEventForSessionBased(event);
  174. }
  175. protected boolean handleEventForEventBased(StateEvent event) throws InternalException, OverloadException {
  176. try {
  177. sendAndStateLock.lock();
  178. Event localEvent = (Event) event;
  179. Event.Type eventType = (Type) localEvent.getType();
  180. switch (this.state) {
  181. case IDLE:
  182. switch (eventType) {
  183. case SEND_EVENT_REQUEST:
  184. // Current State: IDLE
  185. // Event: Client or device requests a one-time service
  186. // Action: Send AA event request
  187. // New State: PENDING_E
  188. setState(ClientRxSessionState.PENDING_EVENT);
  189. try {
  190. dispatchEvent(localEvent.getRequest());
  191. }
  192. catch (Exception e) {
  193. // This handles failure to send in PendingI state in FSM table
  194. logger.debug("Failure handling send event request", e);
  195. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  196. }
  197. break;
  198. default:
  199. logger.warn("Event Based Handling - Wrong event type ({}) on state {}", eventType, state);
  200. break;
  201. }
  202. break;
  203. case PENDING_EVENT:
  204. switch (eventType) {
  205. case RECEIVE_EVENT_ANSWER:
  206. AppAnswerEvent answer = (AppAnswerEvent) localEvent.getAnswer();
  207. try {
  208. long resultCode = answer.getResultCodeAvp().getUnsigned32();
  209. if (isSuccess(resultCode)) {
  210. // Current State: PENDING_E
  211. // Event: Successful AA event answer received
  212. // Action: Grant service to end user
  213. // New State: IDLE
  214. setState(ClientRxSessionState.IDLE, false);
  215. }
  216. if (isProvisional(resultCode) || isFailure(resultCode)) {
  217. handleFailureMessage((RxAAAnswer) answer, (RxAARequest) localEvent.getRequest(), eventType);
  218. }
  219. deliverRxAAAnswer((RxAARequest) localEvent.getRequest(), (RxAAAnswer) localEvent.getAnswer());
  220. }
  221. catch (AvpDataException e) {
  222. logger.debug("Failure handling received answer event", e);
  223. setState(ClientRxSessionState.IDLE, false);
  224. }
  225. break;
  226. default:
  227. logger.warn("Event Based Handling - Wrong event type ({}) on state {}", eventType, state);
  228. break;
  229. }
  230. break;
  231. case PENDING_BUFFERED:
  232. switch (eventType) {
  233. case RECEIVE_EVENT_ANSWER:
  234. // Current State: PENDING_B
  235. // Event: Successful CC answer received
  236. // Action: Delete request
  237. // New State: IDLE
  238. setState(ClientRxSessionState.IDLE, false);
  239. //this.sessionData.setBuffer(null);
  240. buffer = null;
  241. deliverRxAAAnswer((RxAARequest) localEvent.getRequest(), (RxAAAnswer) localEvent.getAnswer());
  242. break;
  243. default:
  244. logger.warn("Event Based Handling - Wrong event type ({}) on state {}", eventType, state);
  245. break;
  246. }
  247. break;
  248. default:
  249. logger.warn("Event Based Handling - Wrong event type ({}) on state {}", eventType, state);
  250. break;
  251. }
  252. dispatch();
  253. return true;
  254. }
  255. catch (Exception e) {
  256. throw new InternalException(e);
  257. }
  258. finally {
  259. sendAndStateLock.unlock();
  260. }
  261. }
  262. protected boolean handleEventForSessionBased(StateEvent event) throws InternalException, OverloadException {
  263. try {
  264. sendAndStateLock.lock();
  265. Event localEvent = (Event) event;
  266. Event.Type eventType = (Type) localEvent.getType();
  267. switch (this.state) {
  268. case IDLE:
  269. switch (eventType) {
  270. case SEND_AAR:
  271. // Current State: IDLE
  272. // Event: Client or device requests access/service
  273. // Action: Send AAR
  274. // New State: PENDING_AAR
  275. setState(ClientRxSessionState.PENDING_AAR);
  276. try {
  277. dispatchEvent(localEvent.getRequest());
  278. }
  279. catch (Exception e) {
  280. // This handles failure to send in PendingI state in FSM table
  281. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  282. }
  283. break;
  284. default:
  285. logger.warn("Session Based Handling - Wrong event type ({}) on state {}", eventType, state);
  286. break;
  287. }
  288. break;
  289. case PENDING_AAR:
  290. AppAnswerEvent answer = (AppAnswerEvent) localEvent.getAnswer();
  291. switch (eventType) {
  292. case RECEIVE_AAA:
  293. long resultCode = answer.getResultCodeAvp().getUnsigned32();
  294. if (isSuccess(resultCode)) {
  295. // Current State: PENDING_AAR
  296. // Event: Successful AA answer received
  297. // New State: OPEN
  298. setState(ClientRxSessionState.OPEN);
  299. }
  300. else if (isProvisional(resultCode) || isFailure(resultCode)) {
  301. handleFailureMessage((RxAAAnswer) answer, (RxAARequest) localEvent.getRequest(), eventType);
  302. }
  303. deliverRxAAAnswer((RxAARequest) localEvent.getRequest(), (RxAAAnswer) localEvent.getAnswer());
  304. break;
  305. case SEND_AAR:
  306. case SEND_STR:
  307. // Current State: PENDING_AAR
  308. // Event: User service terminated
  309. // Action: Queue termination event
  310. // New State: PENDING_AAR
  311. // Current State: PENDING_AAR
  312. // Event: Change in request
  313. // Action: Queue changed rating condition event
  314. // New State: PENDING_AAR
  315. eventQueue.add(localEvent);
  316. break;
  317. case RECEIVE_RAR:
  318. deliverReAuthRequest((RxReAuthRequest) localEvent.getRequest());
  319. break;
  320. case SEND_RAA:
  321. // Current State: PENDING_U
  322. // Event: RAR received
  323. // Action: Send RAA
  324. // New State: PENDING_U
  325. try {
  326. dispatchEvent(localEvent.getAnswer());
  327. }
  328. catch (Exception e) {
  329. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  330. }
  331. break;
  332. case RECEIVE_ASR:
  333. deliverAbortSessionRequest((RxAbortSessionRequest) localEvent.getRequest());
  334. break;
  335. case SEND_ASA:
  336. try {
  337. dispatchEvent(localEvent.getAnswer());
  338. }
  339. catch (Exception e) {
  340. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  341. }
  342. break;
  343. default:
  344. logger.warn("Session Based Handling - Wrong event type ({}) on state {}", eventType, state);
  345. break;
  346. }
  347. break;
  348. case PENDING_STR:
  349. AppAnswerEvent STanswer = (AppAnswerEvent) localEvent.getAnswer();
  350. switch (eventType) {
  351. case RECEIVE_STA:
  352. long resultCode = STanswer.getResultCodeAvp().getUnsigned32();
  353. if (isSuccess(resultCode)) {
  354. // Current State: PENDING_STR
  355. // Event: Successful ST answer received
  356. // New State: IDLE
  357. setState(ClientRxSessionState.IDLE, false);
  358. }
  359. else if (isProvisional(resultCode) || isFailure(resultCode)) {
  360. handleFailureMessage((RxAAAnswer) STanswer, (RxAARequest) localEvent.getRequest(), eventType);
  361. }
  362. deliverRxSessionTermAnswer((RxSessionTermRequest) localEvent.getRequest(), (RxSessionTermAnswer) localEvent.getAnswer());
  363. break;
  364. case SEND_AAR:
  365. try {
  366. // Current State: PENDING_STR
  367. // Event: Change in AA request
  368. // Action: -
  369. // New State: PENDING_STR
  370. dispatchEvent(localEvent.getRequest());
  371. // No transition
  372. }
  373. catch (Exception e) {
  374. // This handles failure to send in PendingI state in FSM table
  375. // handleSendFailure(e, eventType);
  376. }
  377. break;
  378. // case RECEIVE_STA:
  379. // // Current State: PENDING_T
  380. // // Event: Successful CC termination answer received
  381. // // Action: -
  382. // // New State: IDLE
  383. //
  384. // // Current State: PENDING_T
  385. // // Event: Failure to send, temporary error, or failed answer
  386. // // Action: -
  387. // // New State: IDLE
  388. //
  389. // //FIXME: Alex broke this, setting back "true" ?
  390. // setState(ClientRxSessionState.IDLE, false);
  391. // //setState(ClientRxSessionState.IDLE, true);
  392. // deliverRxSessionTermAnswer((RxSessionTermRequest) localEvent.getRequest(), (RxSessionTermAnswer) localEvent.getAnswer());
  393. // //setState(ClientRxSessionState.IDLE, true);
  394. // break;
  395. default:
  396. logger.warn("Session Based Handling - Wrong event type ({}) on state {}", eventType, state);
  397. break;
  398. }
  399. break;
  400. case OPEN:
  401. switch (eventType) {
  402. case SEND_AAR:
  403. // Current State: OPEN
  404. // Event: Updated AAR send by AF
  405. // Action: Send AAR update request
  406. // New State: PENDING_AAR
  407. setState(ClientRxSessionState.PENDING_AAR);
  408. try {
  409. dispatchEvent(localEvent.getRequest());
  410. }
  411. catch (Exception e) {
  412. // This handles failure to send in PendingI state in FSM table
  413. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  414. }
  415. break;
  416. case SEND_STR:
  417. // Current State: OPEN
  418. // Event: Session Termination event request received to be sent
  419. // Action: Terminate end user's service, send STR termination request
  420. // New State: PENDING STR
  421. setState(ClientRxSessionState.PENDING_STR);
  422. try {
  423. dispatchEvent(localEvent.getRequest());
  424. }
  425. catch (Exception e) {
  426. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  427. }
  428. break;
  429. case RECEIVE_RAR:
  430. deliverReAuthRequest((RxReAuthRequest) localEvent.getRequest());
  431. break;
  432. case SEND_RAA:
  433. try {
  434. dispatchEvent(localEvent.getAnswer());
  435. }
  436. catch (Exception e) {
  437. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  438. }
  439. break;
  440. case RECEIVE_ASR:
  441. deliverAbortSessionRequest((RxAbortSessionRequest) localEvent.getRequest());
  442. break;
  443. case SEND_ASA:
  444. try {
  445. dispatchEvent(localEvent.getAnswer());
  446. }
  447. catch (Exception e) {
  448. handleSendFailure(e, eventType, localEvent.getRequest().getMessage());
  449. }
  450. break;
  451. default:
  452. logger.warn("Session Based Handling - Wrong event type ({}) on state {}", eventType, state);
  453. break;
  454. }
  455. break;
  456. default:
  457. // any other state is bad
  458. setState(ClientRxSessionState.IDLE, true);
  459. break;
  460. }
  461. dispatch();
  462. return true;
  463. }
  464. catch (Exception e) {
  465. throw new InternalException(e);
  466. }
  467. finally {
  468. sendAndStateLock.unlock();
  469. }
  470. }
  471. public Answer processRequest(Request request) {
  472. RequestDelivery rd = new RequestDelivery();
  473. rd.session = this;
  474. rd.request = request;
  475. super.scheduler.execute(rd);
  476. return null;
  477. }
  478. public void receivedSuccessMessage(Request request, Answer answer) {
  479. AnswerDelivery ad = new AnswerDelivery();
  480. ad.session = this;
  481. ad.request = request;
  482. ad.answer = answer;
  483. super.scheduler.execute(ad);
  484. }
  485. public void timeoutExpired(Request request) {
  486. // if (request.getCommandCode() == RxAAAnswer.code) {
  487. // try {
  488. // handleSendFailure(null, null, request);
  489. // }
  490. // catch (Exception e) {
  491. // logger.debug("Failure processing timeout message for request", e);
  492. // }
  493. // }
  494. }
  495. protected void setState(ClientRxSessionState newState) {
  496. setState(newState, true);
  497. }
  498. @SuppressWarnings("unchecked")
  499. protected void setState(ClientRxSessionState newState, boolean release) {
  500. try {
  501. IAppSessionState oldState = this.sessionData.getClientRxSessionState();
  502. this.sessionData.setClientRxSessionState(newState);
  503. for (StateChangeListener i : stateListeners) {
  504. i.stateChanged(this, (Enum) oldState, (Enum) newState);
  505. }
  506. if (newState == ClientRxSessionState.IDLE) {
  507. if (release) {
  508. this.release();
  509. }
  510. }
  511. }
  512. catch (Exception e) {
  513. if (logger.isDebugEnabled()) {
  514. logger.debug("Failure switching to state " + this.sessionData.getClientRxSessionState() + " (release=" + release + ")", e);
  515. }
  516. }
  517. }
  518. @Override
  519. public void release() {
  520. if (isValid()) {
  521. try {
  522. this.sendAndStateLock.lock();
  523. super.release();
  524. }
  525. catch (Exception e) {
  526. logger.debug("Failed to release session", e);
  527. }
  528. finally {
  529. sendAndStateLock.unlock();
  530. }
  531. }
  532. else {
  533. logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
  534. }
  535. }
  536. protected void handleSendFailure(Exception e, Event.Type eventType, Message request) throws Exception {
  537. logger.debug("Failed to send message, type: {} message: {}, failure: {}", new Object[]{eventType, request, e != null ? e.getLocalizedMessage() : ""});
  538. //try {
  539. // setState(ClientRxSessionState.IDLE);
  540. //}
  541. //finally {
  542. // dispatch();
  543. //}
  544. }
  545. protected void handleFailureMessage(final RxAAAnswer event, final RxAARequest request, final Event.Type eventType) {
  546. try {
  547. setState(ClientRxSessionState.IDLE);
  548. }
  549. catch (Exception e) {
  550. if (logger.isDebugEnabled()) {
  551. logger.debug("Failure handling failure message for Event " + event + " (" + eventType + ") and Request " + request, e);
  552. }
  553. }
  554. }
  555. /**
  556. * This makes checks on queue, moves it to proper state if event there is
  557. * present on Open state ;]
  558. */
  559. protected void dispatch() {
  560. // Event Based ----------------------------------------------------------
  561. if (isEventBased()) {
  562. // Current State: IDLE
  563. // Event: Request in storage
  564. // Action: Send stored request
  565. // New State: PENDING_B
  566. if (buffer != null) {
  567. setState(ClientRxSessionState.PENDING_BUFFERED);
  568. try {
  569. dispatchEvent(new AppRequestEventImpl(messageFromBuffer(ByteBuffer.wrap(buffer))));
  570. }
  571. catch (Exception e) {
  572. try {
  573. handleSendFailure(e, Event.Type.SEND_EVENT_REQUEST, messageFromBuffer(ByteBuffer.wrap(buffer)));
  574. }
  575. catch (Exception e1) {
  576. logger.error("Failure handling buffer send failure", e1);
  577. }
  578. }
  579. }
  580. } // Session Based --------------------------------------------------------
  581. else {
  582. if (state == ClientRxSessionState.OPEN && eventQueue.size() > 0) {
  583. try {
  584. this.handleEvent(eventQueue.remove(0));
  585. }
  586. catch (Exception e) {
  587. logger.error("Failure handling queued event", e);
  588. }
  589. }
  590. }
  591. }
  592. protected void deliverRxAAAnswer(RxAARequest request, RxAAAnswer answer) {
  593. try {
  594. listener.doAAAnswer(this, request, answer);
  595. }
  596. catch (Exception e) {
  597. logger.warn("Failure delivering AAA", e);
  598. }
  599. }
  600. protected void deliverRxSessionTermAnswer(RxSessionTermRequest request, RxSessionTermAnswer answer) {
  601. try {
  602. listener.doSessionTermAnswer(this, request, answer);
  603. }
  604. catch (Exception e) {
  605. logger.warn("Failure delivering STA", e);
  606. }
  607. }
  608. protected void deliverReAuthRequest(RxReAuthRequest request) {
  609. try {
  610. listener.doReAuthRequest(this, request);
  611. }
  612. catch (Exception e) {
  613. logger.debug("Failure delivering RAR", e);
  614. }
  615. }
  616. protected void deliverAbortSessionRequest(RxAbortSessionRequest request) {
  617. try {
  618. listener.doAbortSessionRequest(this, request);
  619. }
  620. catch (Exception e) {
  621. logger.debug("Failure delivering RAR", e);
  622. }
  623. }
  624. protected void dispatchEvent(AppEvent event) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
  625. session.send(event.getMessage(), this);
  626. }
  627. protected boolean isProvisional(long resultCode) {
  628. return resultCode >= 1000 && resultCode < 2000;
  629. }
  630. protected boolean isSuccess(long resultCode) {
  631. return resultCode >= 2000 && resultCode < 3000;
  632. }
  633. protected boolean isFailure(long code) {
  634. return (!isProvisional(code) && !isSuccess(code) && ((code >= 3000 && /*code < 4000) || (code >= 5000 &&*/ code < 6000)) && !temporaryErrorCodes.contains(code));
  635. }
  636. /* (non-Javadoc)
  637. * @see org.jdiameter.common.impl.app.AppSessionImpl#isReplicable()
  638. */
  639. @Override
  640. public boolean isReplicable() {
  641. return true;
  642. }
  643. /* (non-Javadoc)
  644. * @see org.jdiameter.common.impl.app.AppSessionImpl#relink(org.jdiameter.client.api.IContainer)
  645. */
  646. private final Message messageFromBuffer(ByteBuffer request) throws InternalException {
  647. if (request != null) {
  648. Message m;
  649. try {
  650. m = parser.createMessage(request);
  651. return m;
  652. }
  653. catch (AvpDataException e) {
  654. throw new InternalException("Failed to decode message.", e);
  655. }
  656. }
  657. return null;
  658. }
  659. private ByteBuffer messageToBuffer(IMessage msg) throws InternalException {
  660. try {
  661. return parser.encodeMessage(msg);
  662. }
  663. catch (ParseException e) {
  664. throw new InternalException("Failed to encode message.", e);
  665. }
  666. }
  667. private class RequestDelivery implements Runnable {
  668. ClientRxSession session;
  669. Request request;
  670. public void run() {
  671. try {
  672. switch (request.getCommandCode()) {
  673. case RxReAuthRequest.code:
  674. handleEvent(new Event(Event.Type.RECEIVE_RAR, factory.createReAuthRequest(request), null));
  675. break;
  676. case RxAbortSessionRequest.code:
  677. handleEvent(new Event(Event.Type.RECEIVE_ASR, factory.createAbortSessionRequest(request), null));
  678. break;
  679. default:
  680. listener.doOtherEvent(session, new AppRequestEventImpl(request), null);
  681. break;
  682. }
  683. }
  684. catch (Exception e) {
  685. logger.debug("Failure processing request", e);
  686. }
  687. }
  688. }
  689. private class AnswerDelivery implements Runnable {
  690. ClientRxSession session;
  691. Answer answer;
  692. Request request;
  693. public void run() {
  694. try {
  695. switch (request.getCommandCode()) {
  696. case RxAAAnswer.code:
  697. final RxAARequest myAARequest = factory.createAARequest(request);
  698. final RxAAAnswer myAAAnswer = factory.createAAAnswer(answer);
  699. handleEvent(new Event(false, myAARequest, myAAAnswer));
  700. break;
  701. case RxSessionTermAnswer.code:
  702. final RxSessionTermRequest mySTRequest = factory.createSessionTermRequest(request);
  703. final RxSessionTermAnswer mySTAnswer = factory.createSessionTermAnswer(answer);
  704. handleEvent(new Event(false, mySTRequest, mySTAnswer));
  705. break;
  706. default:
  707. listener.doOtherEvent(session, new AppRequestEventImpl(request), new AppAnswerEventImpl(answer));
  708. break;
  709. }
  710. }
  711. catch (Exception e) {
  712. logger.debug("Failure processing success message", e);
  713. }
  714. }
  715. }
  716. /* (non-Javadoc)
  717. * @see java.lang.Object#hashCode()
  718. */
  719. @Override
  720. public int hashCode() {
  721. final int prime = 31;
  722. int result = 1;
  723. result = prime * result + Arrays.hashCode(authAppIds);
  724. result = prime * result + (isEventBased ? 1231 : 1237);
  725. result = prime * result + ((originHost == null) ? 0 : originHost.hashCode());
  726. result = prime * result + ((originRealm == null) ? 0 : originRealm.hashCode());
  727. result = prime * result + ((state == null) ? 0 : state.hashCode());
  728. return result;
  729. }
  730. /* (non-Javadoc)
  731. * @see java.lang.Object#equals(java.lang.Object)
  732. */
  733. @Override
  734. public boolean equals(Object obj) {
  735. if (this == obj) {
  736. return true;
  737. }
  738. if (obj == null) {
  739. return false;
  740. }
  741. if (getClass() != obj.getClass()) {
  742. return false;
  743. }
  744. ClientRxSessionImpl other = (ClientRxSessionImpl) obj;
  745. if (!Arrays.equals(authAppIds, other.authAppIds)) {
  746. return false;
  747. }
  748. if (isEventBased != other.isEventBased) {
  749. return false;
  750. }
  751. if (originHost == null) {
  752. if (other.originHost != null) {
  753. return false;
  754. }
  755. }
  756. else if (!originHost.equals(other.originHost)) {
  757. return false;
  758. }
  759. if (originRealm == null) {
  760. if (other.originRealm != null) {
  761. return false;
  762. }
  763. }
  764. else if (!originRealm.equals(other.originRealm)) {
  765. return false;
  766. }
  767. if (state == null) {
  768. if (other.state != null) {
  769. return false;
  770. }
  771. }
  772. else if (!state.equals(other.state)) {
  773. return false;
  774. }
  775. return true;
  776. }
  777. public void onTimer(String timerName) {
  778. }
  779. }