All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nist.javax.sip.stack.sctp.SCTPMessageProcessor Maven / Gradle / Ivy

There is a newer version: 1.3.0-91
Show newest version
package gov.nist.javax.sip.stack.sctp;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;

import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;

import gov.nist.core.HostPort;
import gov.nist.javax.sip.stack.MessageChannel;
import gov.nist.javax.sip.stack.MessageProcessor;
import gov.nist.javax.sip.stack.SIPTransactionStack;

/**
 * SCTP Message Processor
 * 
 * @author Jeroen van Bemmel
 */
public final class SCTPMessageProcessor extends MessageProcessor implements Runnable {

	private SctpServerChannel sctpServerChannel;
	private Selector selector;
	private SelectionKey key;
	private boolean isRunning, doClose;
	
	private final Set channels 
		= new ConcurrentSkipListSet();
	
	/**
	 * Constructor, called via Class.newInstance() by SIPTransactionStack
	 */
	public SCTPMessageProcessor() {
		super( "sctp" );
	}

	Selector getSelector() { return selector; }
	
	SelectionKey registerChannel( SCTPMessageChannel c, SctpChannel channel ) 
		throws ClosedChannelException {
		synchronized (this) {
			selector.wakeup();
			return channel.register( selector, SelectionKey.OP_READ, c );
		}
	}
	
	@Override
	public MessageChannel createMessageChannel(HostPort targetHostPort)
			throws IOException {		
		return this.createMessageChannel( targetHostPort.getInetAddress(), targetHostPort.getPort() );
	}

	@Override
	public MessageChannel createMessageChannel(InetAddress targetHost, int port)
			throws IOException {
		
		SCTPMessageChannel c = new SCTPMessageChannel( this, 
				new InetSocketAddress(targetHost,port) );
		channels.add( c );
		return c;
	}

	@Override
	public int getDefaultTargetPort() {		
		return 5060;	// same as UDP and TCP
	}

	@Override
	public int getMaximumMessageSize() {
		return Integer.MAX_VALUE;
	}

	@Override
	public SIPTransactionStack getSIPStack() {
		return sipStack;
	}

	@Override
	public boolean inUse() {
		return isRunning;
	}

	@Override
	public boolean isSecure() {
		return false;
	}

	public void run() {
		try {
			do {
				int n = selector.select();
				if (n>0) {
					Iterator i = selector.selectedKeys().iterator();
					while ( i.hasNext() ) {
						SelectionKey key = i.next();
						i.remove();
						if ( key.isReadable() ) {
							SCTPMessageChannel channel = (SCTPMessageChannel) key.attachment();
							channel.readMessages();
						} else if (key.isAcceptable()) {
							SctpChannel ch = sctpServerChannel.accept();
							SCTPMessageChannel c = new SCTPMessageChannel( this, ch );
							channels.add( c );
						}
					}
				}
				
				synchronized (this) {
					if (doClose) {
						selector.close();
						return;
					}
				}				
			} while ( selector.isOpen() );
		} catch (IOException ioe) {
			ioe.printStackTrace();
			try {
				selector.close();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				this.stop();
			}
		}
	}

	@Override
	public void start() throws IOException {

		this.sctpServerChannel = SctpServerChannel.open();		
		sctpServerChannel.bind( new InetSocketAddress(this.getIpAddress(),this.getPort()) );
		sctpServerChannel.configureBlocking( false );
		
		this.selector = Selector.open();
		this.key = sctpServerChannel.register( selector, SelectionKey.OP_ACCEPT );
				
		// Start a daemon thread to handle reception
		this.isRunning = true;
        Thread thread = new Thread(this);
        thread.setDaemon(true);
        thread.setName("SCTPMessageProcessorThread");
        thread.setPriority(Thread.MAX_PRIORITY);
        thread.start();
	}

	@Override
	public void stop() {
		this.isRunning = false;
		this.doClose = true;
		
		for ( SCTPMessageChannel c : channels ) {
			c.closeNoRemove();	// avoids call to removeChannel -> ConcurrentModification
		}
		channels.clear();
		try {
			key.cancel();
			sctpServerChannel.close();			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			synchronized (this) {
				selector.wakeup();
			}
		}
	}

	void removeChannel(SCTPMessageChannel messageChannel) {
		channels.remove( messageChannel );
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy