PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/diameter/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/parser/MessageImpl.java

http://mobicents.googlecode.com/
Java | 564 lines | 410 code | 79 blank | 75 comment | 103 complexity | dd6484aba8c321bf0574a833a6e869d8 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2006, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jdiameter.client.impl.parser;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import java.util.concurrent.ScheduledExecutorService;
  26. import java.util.concurrent.ScheduledFuture;
  27. import java.util.concurrent.ThreadPoolExecutor;
  28. import java.util.concurrent.TimeUnit;
  29. import org.jdiameter.api.Answer;
  30. import org.jdiameter.api.ApplicationId;
  31. import org.jdiameter.api.Avp;
  32. import org.jdiameter.api.AvpDataException;
  33. import org.jdiameter.api.AvpSet;
  34. import org.jdiameter.api.InternalException;
  35. import org.jdiameter.client.api.IEventListener;
  36. import org.jdiameter.client.api.IMessage;
  37. import org.jdiameter.client.api.controller.IPeer;
  38. import org.slf4j.Logger;
  39. import org.slf4j.LoggerFactory;
  40. /**
  41. * Represents a Diameter message.
  42. *
  43. * @author erick.svenson@yahoo.com
  44. * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
  45. * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
  46. */
  47. public class MessageImpl implements IMessage {
  48. private static final long serialVersionUID = 1L;
  49. private static final Logger logger = LoggerFactory.getLogger(MessageImpl.class);
  50. private static final MessageParser parser = new MessageParser();
  51. int state = STATE_NOT_SENT;
  52. short version = 1, flags;
  53. int commandCode;
  54. long applicationId;
  55. long hopByHopId;
  56. boolean notMutableHopByHop;
  57. long endToEndId;
  58. AvpSetImpl avpSet;
  59. boolean isNetworkRequest = false;
  60. transient IPeer peer;
  61. transient TimerTask timerTask;
  62. transient IEventListener listener;
  63. // Cached result for getApplicationIdAvps() method. It is called extensively and takes some time.
  64. // Potential place for dirt, but Application IDs don't change during message life time.
  65. transient List<ApplicationId> applicationIds;
  66. /**
  67. * Create empty message
  68. *
  69. * @param parser
  70. * @param commandCode
  71. * @param appId
  72. */
  73. MessageImpl(int commandCode, long appId) {
  74. this.commandCode = commandCode;
  75. this.applicationId = appId;
  76. this.avpSet = new AvpSetImpl();
  77. this.endToEndId = parser.getNextEndToEndId();
  78. }
  79. /**
  80. * Create empty message
  81. *
  82. * @param parser
  83. * @param commandCode
  84. * @param applicationId
  85. * @param flags
  86. * @param hopByHopId
  87. * @param endToEndId
  88. * @param avpSet
  89. */
  90. MessageImpl(int commandCode, long applicationId, short flags, long hopByHopId, long endToEndId, AvpSetImpl avpSet) {
  91. this(commandCode, applicationId);
  92. this.flags = flags;
  93. this.hopByHopId = hopByHopId;
  94. this.endToEndId = endToEndId;
  95. if (avpSet != null) {
  96. this.avpSet = avpSet;
  97. }
  98. }
  99. // /**
  100. // * Create empty message
  101. // *
  102. // * @param metaData
  103. // * @param parser
  104. // * @param commandCode
  105. // * @param appId
  106. // */
  107. // MessageImpl(MetaData metaData, MessageParser parser, int commandCode, long appId) {
  108. // this(commandCode, appId);
  109. // try {
  110. // getAvps().addAvp(Avp.ORIGIN_HOST, metaData.getLocalPeer().getUri().getFQDN(), true, false, true);
  111. // getAvps().addAvp(Avp.ORIGIN_REALM, metaData.getLocalPeer().getRealmName(), true, false, true);
  112. // }
  113. // catch (Exception e) {
  114. // logger.debug("Can not create message", e);
  115. // }
  116. // }
  117. /**
  118. * Create Answer
  119. *
  120. * @param request parent request
  121. */
  122. private MessageImpl(MessageImpl request) {
  123. this(request.getCommandCode(), request.getHeaderApplicationId());
  124. copyHeader(request);
  125. setRequest(false);
  126. parser.copyBasicAvps(this, request, true);
  127. }
  128. public byte getVersion() {
  129. return (byte) version;
  130. }
  131. public boolean isRequest() {
  132. return (flags & 0x80) != 0;
  133. }
  134. public void setRequest(boolean b) {
  135. if (b) {
  136. flags |= 0x80;
  137. }
  138. else {
  139. flags &= 0x7F;
  140. }
  141. }
  142. public boolean isProxiable() {
  143. return (flags & 0x40) != 0;
  144. }
  145. public void setProxiable(boolean b) {
  146. if (b) {
  147. flags |= 0x40;
  148. }
  149. else {
  150. flags &= 0xBF;
  151. }
  152. }
  153. public boolean isError() {
  154. return (flags & 0x20) != 0;
  155. }
  156. public void setError(boolean b) {
  157. if (b) {
  158. flags |= 0x20;
  159. }
  160. else {
  161. flags &= 0xDF;
  162. }
  163. }
  164. public boolean isReTransmitted() {
  165. return (flags & 0x10) != 0;
  166. }
  167. public void setReTransmitted(boolean b) {
  168. if (b) {
  169. flags |= 0x10;
  170. }
  171. else {
  172. flags &= 0xEF;
  173. }
  174. }
  175. public int getCommandCode() {
  176. return this.commandCode;
  177. }
  178. public String getSessionId() {
  179. try {
  180. Avp avpSessionId = avpSet.getAvp(Avp.SESSION_ID);
  181. return avpSessionId != null ? avpSessionId.getUTF8String() : null;
  182. }
  183. catch (AvpDataException ade) {
  184. logger.error("Failed to fetch Session-Id", ade);
  185. return null;
  186. }
  187. }
  188. public Answer createAnswer() {
  189. MessageImpl answer = new MessageImpl(this);
  190. return answer;
  191. }
  192. public Answer createAnswer(long resultCode) {
  193. MessageImpl answer = new MessageImpl(this);
  194. try {
  195. answer.getAvps().addAvp(Avp.RESULT_CODE, resultCode, true, false, true);
  196. }
  197. catch (Exception e) {
  198. logger.debug("Can not create answer message", e);
  199. }
  200. //Its set in constructor.
  201. //answer.setRequest(false);
  202. return answer;
  203. }
  204. public Answer createAnswer(long vendorId, long experementalResultCode) {
  205. MessageImpl answer = new MessageImpl(this);
  206. try {
  207. AvpSet exp_code = answer.getAvps().addGroupedAvp(297, true, false);
  208. exp_code.addAvp(Avp.VENDOR_ID, vendorId, true, false, true);
  209. exp_code.addAvp(Avp.EXPERIMENTAL_RESULT_CODE, experementalResultCode, true, false, true);
  210. }
  211. catch (Exception e) {
  212. logger.debug("Can not create answer message", e);
  213. }
  214. answer.setRequest(false);
  215. return answer;
  216. }
  217. public long getApplicationId() {
  218. return applicationId;
  219. }
  220. public ApplicationId getSingleApplicationId() {
  221. return getSingleApplicationId(this.applicationId);
  222. }
  223. public List<ApplicationId> getApplicationIdAvps() {
  224. if (this.applicationIds != null) {
  225. return this.applicationIds;
  226. }
  227. List<ApplicationId> rc = new ArrayList<ApplicationId>();
  228. try {
  229. AvpSet authAppId = avpSet.getAvps(Avp.AUTH_APPLICATION_ID);
  230. for (Avp anAuthAppId : authAppId) {
  231. rc.add(ApplicationId.createByAuthAppId((anAuthAppId).getInteger32()));
  232. }
  233. AvpSet accAppId = avpSet.getAvps(Avp.ACCT_APPLICATION_ID);
  234. for (Avp anAccAppId : accAppId) {
  235. rc.add(ApplicationId.createByAccAppId((anAccAppId).getInteger32()));
  236. }
  237. AvpSet specAppId = avpSet.getAvps(Avp.VENDOR_SPECIFIC_APPLICATION_ID);
  238. for (Avp aSpecAppId : specAppId) {
  239. long vendorId = 0, acctApplicationId = 0, authApplicationId = 0;
  240. AvpSet avps = (aSpecAppId).getGrouped();
  241. for (Avp localAvp : avps) {
  242. if (localAvp.getCode() == Avp.VENDOR_ID) {
  243. vendorId = localAvp.getUnsigned32();
  244. }
  245. if (localAvp.getCode() == Avp.AUTH_APPLICATION_ID) {
  246. authApplicationId = localAvp.getUnsigned32();
  247. }
  248. if (localAvp.getCode() == Avp.ACCT_APPLICATION_ID) {
  249. acctApplicationId = localAvp.getUnsigned32();
  250. }
  251. }
  252. if (authApplicationId != 0) {
  253. rc.add(ApplicationId.createByAuthAppId(vendorId, authApplicationId));
  254. }
  255. if (acctApplicationId != 0) {
  256. rc.add(ApplicationId.createByAccAppId(vendorId, acctApplicationId));
  257. }
  258. }
  259. }
  260. catch (Exception exception) {
  261. return new ArrayList<ApplicationId>();
  262. }
  263. this.applicationIds = rc;
  264. return this.applicationIds;
  265. }
  266. public ApplicationId getSingleApplicationId(long applicationId) {
  267. logger.debug("In getSingleApplicationId for application id [{}]", applicationId);
  268. List<ApplicationId> appIds = getApplicationIdAvps();
  269. logger.debug("Application Ids in this message are:");
  270. ApplicationId firstOverall = null;
  271. ApplicationId firstWithZeroVendor = null;
  272. ApplicationId firstWithNonZeroVendor = null;
  273. for (ApplicationId id : appIds) {
  274. logger.debug("[{}]", id);
  275. if (firstOverall == null) {
  276. firstOverall = id;
  277. }
  278. if (applicationId != 0) {
  279. if (firstWithZeroVendor == null && id.getVendorId() == 0 && (applicationId == id.getAuthAppId() || applicationId == id.getAcctAppId())) {
  280. firstWithZeroVendor = id;
  281. }
  282. if (firstWithNonZeroVendor == null && id.getVendorId() != 0 && (applicationId == id.getAuthAppId() || applicationId == id.getAcctAppId())) {
  283. firstWithNonZeroVendor = id;
  284. break;
  285. }
  286. }
  287. }
  288. ApplicationId toReturn = null;
  289. if (firstWithNonZeroVendor != null) {
  290. toReturn = firstWithNonZeroVendor;
  291. logger.debug("Returning [{}] as the first application id because its the first vendor specific one found", toReturn);
  292. }
  293. else if (firstWithZeroVendor != null) {
  294. toReturn = firstWithZeroVendor;
  295. logger.debug("Returning [{}] as the first application id because there are no vendor specific ones found", toReturn);
  296. }
  297. else {
  298. toReturn = firstOverall;
  299. logger.debug("Returning [{}] as the first application id because none with the requested app ids were found", toReturn);
  300. }
  301. if (toReturn == null) {
  302. // TODO: ammendonca: improve this (find vendor? use common app list map?)
  303. logger.debug("There are no Application-Id AVPs. Using the value in the header and assuming as Auth Application-Id [{}]", this.applicationId);
  304. toReturn = ApplicationId.createByAuthAppId(this.applicationId);
  305. }
  306. return toReturn;
  307. }
  308. public long getHopByHopIdentifier() {
  309. return hopByHopId;
  310. }
  311. public long getEndToEndIdentifier() {
  312. return endToEndId;
  313. }
  314. public AvpSet getAvps() {
  315. return avpSet;
  316. }
  317. protected void copyHeader(MessageImpl request) {
  318. endToEndId = request.endToEndId;
  319. hopByHopId = request.hopByHopId;
  320. version = request.version;
  321. flags = request.flags;
  322. peer = request.peer;
  323. }
  324. public Avp getResultCode() {
  325. return getAvps().getAvp(Avp.RESULT_CODE);
  326. }
  327. public void setNetworkRequest(boolean isNetworkRequest) {
  328. this.isNetworkRequest = isNetworkRequest;
  329. }
  330. public boolean isNetworkRequest() {
  331. return isNetworkRequest;
  332. }
  333. public boolean isWrapperFor(Class<?> aClass) throws InternalException {
  334. return false;
  335. }
  336. public <T> T unwrap(Class<T> aClass) throws InternalException {
  337. return null;
  338. }
  339. // Inner API
  340. public void setHopByHopIdentifier(long hopByHopId) {
  341. if (hopByHopId < 0) {
  342. this.hopByHopId = -hopByHopId;
  343. this.notMutableHopByHop = true;
  344. }
  345. else {
  346. if (!this.notMutableHopByHop) {
  347. this.hopByHopId = hopByHopId;
  348. }
  349. }
  350. }
  351. public void setEndToEndIdentifier(long endByEndId) {
  352. this.endToEndId = endByEndId;
  353. }
  354. public IPeer getPeer() {
  355. return peer;
  356. }
  357. public void setPeer(IPeer peer) {
  358. this.peer = peer;
  359. }
  360. public int getState() {
  361. return state;
  362. }
  363. public long getHeaderApplicationId() {
  364. return applicationId;
  365. }
  366. public void setHeaderApplicationId(long applicationId) {
  367. this.applicationId = applicationId;
  368. }
  369. public int getFlags() {
  370. return flags;
  371. }
  372. public void setState(int newState) {
  373. state = newState;
  374. }
  375. public void createTimer(ScheduledExecutorService scheduledFacility, long timeOut, TimeUnit timeUnit) {
  376. timerTask = new TimerTask(this);
  377. timerTask.setTimerHandler(scheduledFacility, scheduledFacility.schedule(timerTask, timeOut, timeUnit));
  378. }
  379. public void runTimer() {
  380. if (timerTask != null && !timerTask.isDone() && !timerTask.isCancelled()) {
  381. timerTask.run();
  382. }
  383. }
  384. public boolean isTimeOut() {
  385. return timerTask != null && timerTask.isDone() && !timerTask.isCancelled();
  386. }
  387. public void setListener(IEventListener listener) {
  388. this.listener = listener;
  389. }
  390. public IEventListener getEventListener() {
  391. return listener;
  392. }
  393. public void clearTimer() {
  394. if (timerTask != null) {
  395. timerTask.cancel();
  396. }
  397. }
  398. public String toString() {
  399. return "MessageImpl{" + "commandCode=" + commandCode + ", flags=" + flags + '}';
  400. }
  401. public boolean equals(Object o) {
  402. if (this == o) {
  403. return true;
  404. }
  405. if (o == null || getClass() != o.getClass()) {
  406. return false;
  407. }
  408. MessageImpl message = (MessageImpl) o;
  409. return applicationId == message.applicationId && commandCode == message.commandCode &&
  410. endToEndId == message.endToEndId && hopByHopId == message.hopByHopId;
  411. }
  412. public int hashCode() {
  413. long result;
  414. result = commandCode;
  415. result = 31 * result + applicationId;
  416. result = 31 * result + hopByHopId;
  417. result = 31 * result + endToEndId;
  418. return new Long(result).hashCode();
  419. }
  420. public String getDuplicationKey() {
  421. try {
  422. return getDuplicationKey(getAvps().getAvp(Avp.ORIGIN_HOST).getDiameterIdentity(), getEndToEndIdentifier());
  423. }
  424. catch (AvpDataException e) {
  425. throw new IllegalArgumentException(e);
  426. }
  427. }
  428. public String getDuplicationKey(String host, long endToEndId) {
  429. return host + endToEndId;
  430. }
  431. public Object clone() {
  432. try {
  433. return parser.createMessage(parser.encodeMessage(this));
  434. }
  435. catch (Exception e) {
  436. throw new IllegalArgumentException(e);
  437. }
  438. }
  439. protected static class TimerTask implements Runnable {
  440. ScheduledFuture timerHandler;
  441. MessageImpl message;
  442. ScheduledExecutorService scheduledFacility;
  443. public TimerTask(MessageImpl message) {
  444. this.message = message;
  445. }
  446. public void setTimerHandler(ScheduledExecutorService scheduledFacility, ScheduledFuture timerHandler) {
  447. this.scheduledFacility = scheduledFacility;
  448. this.timerHandler = timerHandler;
  449. }
  450. public void run() {
  451. try {
  452. if (message != null && message.state != STATE_ANSWERED) {
  453. IEventListener listener = null;
  454. if (message.listener instanceof IEventListener) {
  455. listener = message.listener;
  456. }
  457. if (listener != null && listener.isValid()) {
  458. if (message.peer != null) {
  459. message.peer.remMessage(message);
  460. }
  461. message.listener.timeoutExpired(message);
  462. }
  463. }
  464. }
  465. catch(Throwable e) {
  466. logger.debug("Can not process timeout", e);
  467. }
  468. }
  469. public void cancel() {
  470. if (timerHandler != null) {
  471. timerHandler.cancel(true);
  472. if (scheduledFacility instanceof ThreadPoolExecutor && timerHandler instanceof Runnable) {
  473. ((ThreadPoolExecutor) scheduledFacility).remove((Runnable) timerHandler);
  474. }
  475. }
  476. message = null;
  477. }
  478. public boolean isDone() {
  479. return timerHandler != null && timerHandler.isDone();
  480. }
  481. public boolean isCancelled() {
  482. return timerHandler == null || timerHandler.isCancelled();
  483. }
  484. }
  485. }