/protocols/ss7/m3ua/impl/src/main/java/org/mobicents/protocols/ss7/m3ua/impl/sctp/SctpChannel.java

http://mobicents.googlecode.com/ · Java · 300 lines · 135 code · 44 blank · 121 comment · 15 complexity · 6a5776404d353fa77564291a062706d0 MD5 · raw file

  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.mobicents.protocols.ss7.m3ua.impl.sctp;
  23. import java.io.IOException;
  24. import java.net.SocketAddress;
  25. import java.nio.ByteBuffer;
  26. import java.nio.channels.spi.AbstractSelectableChannel;
  27. import java.util.Set;
  28. import org.mobicents.protocols.ss7.m3ua.impl.M3UAChannelImpl;
  29. import org.mobicents.protocols.ss7.m3ua.impl.message.M3UAMessageImpl;
  30. import org.mobicents.protocols.ss7.m3ua.impl.message.MessageFactoryImpl;
  31. import org.mobicents.protocols.ss7.m3ua.message.MessageClass;
  32. import org.mobicents.protocols.ss7.m3ua.message.transfer.PayloadData;
  33. import com.sun.nio.sctp.MessageInfo;
  34. import com.sun.nio.sctp.NotificationHandler;
  35. import com.sun.nio.sctp.SctpStandardSocketOptions;
  36. /**
  37. * @author amit bhayani
  38. *
  39. */
  40. public class SctpChannel extends M3UAChannelImpl {
  41. private static final int MAX_SLS = 32;
  42. // receiver buffer
  43. private ByteBuffer rxBuffer = ByteBuffer.allocateDirect(8192);
  44. // transmittor buffer
  45. private ByteBuffer txBuffer = ByteBuffer.allocateDirect(8192);
  46. // msgInfo
  47. private MessageInfo msgInfo;
  48. // provider instance
  49. private SctpProvider provider;
  50. private NotificationHandler notificationHandler = null;
  51. private int slsTable[] = new int[MAX_SLS];
  52. /**
  53. * Creates new channel.
  54. *
  55. * @param provider
  56. * the provider instance.
  57. * @param channel
  58. * the underlying socket channel.
  59. * @throws java.io.IOException
  60. */
  61. protected SctpChannel(SctpProvider provider, AbstractSelectableChannel channel) throws IOException {
  62. super(channel);
  63. this.provider = provider;
  64. // Set max stream in/out here
  65. ((com.sun.nio.sctp.SctpChannel) channel).setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS,
  66. SctpStandardSocketOptions.InitMaxStreams.create(32, 32));
  67. // set SCTP_FRAGMENT_INTERLEAVE to zero. The MessageFactory will fail if
  68. // set to 1 or 2
  69. //((com.sun.nio.sctp.SctpChannel) channel).setOption(SctpStandardSocketOption.SCTP_FRAGMENT_INTERLEAVE, 0);
  70. // clean transmission buffer
  71. txBuffer.clear();
  72. txBuffer.rewind();
  73. txBuffer.flip();
  74. // clean receiver buffer
  75. rxBuffer.clear();
  76. rxBuffer.rewind();
  77. rxBuffer.flip();
  78. }
  79. public NotificationHandler getNotificationHandler() {
  80. return notificationHandler;
  81. }
  82. public void setNotificationHandler(NotificationHandler notificationHandler) {
  83. this.notificationHandler = notificationHandler;
  84. }
  85. public void createSLSTable(int minimumBoundStream){
  86. //Stream 0 is for management messages, we start from 1
  87. int stream = 1;
  88. for (int i = 0; i < MAX_SLS; i++) {
  89. if (stream > minimumBoundStream) {
  90. stream = 1;
  91. }
  92. slsTable[i] = stream++;
  93. }
  94. }
  95. /**
  96. * Opens this channel
  97. *
  98. * @return the new channel
  99. * @throws java.io.IOException
  100. */
  101. public static SctpChannel open(SctpProvider provider) throws IOException {
  102. return new SctpChannel(provider, com.sun.nio.sctp.SctpChannel.open());
  103. }
  104. public Set<SocketAddress> getRemoteAddresses() throws IOException {
  105. return ((com.sun.nio.sctp.SctpChannel) channel).getRemoteAddresses();
  106. }
  107. /*
  108. * (non-Javadoc)
  109. *
  110. * @see
  111. * org.mobicents.protocols.ss7.m3ua.M3UAChannel#bind(java.net.SocketAddress)
  112. */
  113. @Override
  114. public void bind(SocketAddress address) throws IOException {
  115. ((com.sun.nio.sctp.SctpChannel) channel).bind(address);
  116. }
  117. /*
  118. * (non-Javadoc)
  119. *
  120. * @see
  121. * org.mobicents.protocols.ss7.m3ua.M3UAChannel#connect(java.net.SocketAddress
  122. * )
  123. */
  124. @Override
  125. public boolean connect(SocketAddress remote) throws IOException {
  126. return ((com.sun.nio.sctp.SctpChannel) channel).connect(remote);
  127. }
  128. /*
  129. * (non-Javadoc)
  130. *
  131. * @see org.mobicents.protocols.ss7.m3ua.M3UAChannel#finishConnect()
  132. */
  133. @Override
  134. public boolean finishConnect() throws IOException {
  135. return ((com.sun.nio.sctp.SctpChannel) channel).finishConnect();
  136. }
  137. /*
  138. * (non-Javadoc)
  139. *
  140. * @see org.mobicents.protocols.ss7.m3ua.M3UAChannel#close()
  141. */
  142. @Override
  143. public void close() throws IOException {
  144. ((com.sun.nio.sctp.SctpChannel) channel).close();
  145. }
  146. /*
  147. * (non-Javadoc)
  148. *
  149. * @see org.mobicents.protocols.ss7.m3ua.M3UAChannel#isConnected()
  150. */
  151. @Override
  152. public boolean isConnected() throws IOException {
  153. return ((com.sun.nio.sctp.SctpChannel) channel).association() != null;
  154. }
  155. /*
  156. * (non-Javadoc)
  157. *
  158. * @see org.mobicents.protocols.ss7.m3ua.M3UAChannel#isConnectionPending()
  159. */
  160. @Override
  161. public boolean isConnectionPending() {
  162. return ((com.sun.nio.sctp.SctpChannel) channel).isConnectionPending();
  163. }
  164. /*
  165. * (non-Javadoc)
  166. *
  167. * @see org.mobicents.protocols.ss7.m3ua.impl.M3UAChannelImpl#doRead()
  168. */
  169. @Override
  170. protected void doRead() throws IOException {
  171. // clean rx buffer
  172. rxBuffer.clear();
  173. // reading data from SctpChannel
  174. while ((msgInfo = ((com.sun.nio.sctp.SctpChannel) channel).receive(rxBuffer, this, notificationHandler)) != null) {
  175. int len = msgInfo.bytes();
  176. if (len <= 0) {
  177. // TODO Should close the SctpChannel?
  178. return;
  179. }
  180. rxBuffer.flip();
  181. // split stream on to the messages
  182. while (rxBuffer.position() < rxBuffer.limit()) {
  183. // try to read message
  184. M3UAMessageImpl message = ((MessageFactoryImpl) provider.getMessageFactory()).createMessage(rxBuffer);
  185. if (message != null) {
  186. rxQueue.offer(message);
  187. }
  188. }
  189. rxBuffer.clear();
  190. }// end of outer while loop
  191. }
  192. /*
  193. * (non-Javadoc)
  194. *
  195. * @see org.mobicents.protocols.ss7.m3ua.impl.M3UAChannelImpl#doWrite()
  196. */
  197. @Override
  198. protected void doWrite() throws IOException {
  199. if (txBuffer.hasRemaining()) {
  200. // All data wasn't sent in last doWrite. Try to send it now
  201. ((com.sun.nio.sctp.SctpChannel) channel).send(txBuffer, msgInfo);
  202. }
  203. if (!txQueue.isEmpty() && !txBuffer.hasRemaining()) {
  204. // If txBuffer has no data remaining to be sent and txQueue has more
  205. // messages to be sent, do it now
  206. while (!txQueue.isEmpty()) {
  207. // Lets read all the messages in txQueue and send
  208. txBuffer.clear();
  209. M3UAMessageImpl msg = txQueue.poll();
  210. msg.encode(txBuffer);
  211. // See section 1.4.7. SCTP Stream Mapping of RFC
  212. // http://tools.ietf.org/html/rfc4666
  213. // 1. The DATA message MUST NOT be sent on stream 0.
  214. // 2. The ASPSM, MGMT, RKM classes SHOULD be sent on stream 0
  215. // (other than BEAT, BEAT ACK and NTFY messages).
  216. // 3. The SSNM, ASPTM classes and BEAT, BEAT ACK and NTFY
  217. // messages can be sent on any stream.
  218. switch (msg.getMessageClass()) {
  219. case MessageClass.ASP_STATE_MAINTENANCE:
  220. case MessageClass.MANAGEMENT:
  221. case MessageClass.ROUTING_KEY_MANAGEMENT:
  222. msgInfo = MessageInfo.createOutgoing(null, 0);
  223. msgInfo.payloadProtocolID(3);
  224. break;
  225. case MessageClass.TRANSFER_MESSAGES:
  226. // MTP3-User traffic may be assigned to individual streams
  227. // based on, for example, the SLS value in the MTP3 Routing
  228. // Label, subject of course to the maximum number of streams
  229. // supported by the underlying SCTP association.
  230. PayloadData payload = (PayloadData) msg;
  231. int seqControl = payload.getData().getSLS();
  232. //we use max 32 streams
  233. seqControl = seqControl & 0x1F;
  234. msgInfo = MessageInfo.createOutgoing(null, this.slsTable[seqControl]);
  235. // 7.1. SCTP Payload Protocol Identifier : IANA has assigned
  236. // an M3UA value (3) for the Payload Protocol Identifier in
  237. // the SCTP DATA chunk.
  238. msgInfo.payloadProtocolID(3);
  239. break;
  240. // Let default messages also go through stream 0
  241. default:
  242. msgInfo = MessageInfo.createOutgoing(null, 0);
  243. msgInfo.payloadProtocolID(3);
  244. break;
  245. }
  246. txBuffer.flip();
  247. int sent = ((com.sun.nio.sctp.SctpChannel) channel).send(txBuffer, msgInfo);
  248. if (txBuffer.hasRemaining()) {
  249. // Couldn't send all data. Lets return now and try to send
  250. // this message
  251. return;
  252. }
  253. }// end of while
  254. }
  255. }
  256. }