PageRenderTime 55ms CodeModel.GetById 44ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

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