package org.commoncrawl.io; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.spi.AbstractSelectableChannel; import java.security.SecureRandom; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.commoncrawl.util.CCStringUtils; public class NIOClientUDPSocket extends NIOClientSocket { DatagramChannel _channel = null; int _socketId = NIOSocket._idFactory.getNextId(); NIOSocketListener _listener; InetSocketAddress _remoteAddress; private static final int EPHEMERAL_START = 1024; private static final int EPHEMERAL_STOP = 65535; private static final int EPHEMERAL_RANGE = EPHEMERAL_STOP - EPHEMERAL_START; private static SecureRandom prng = new SecureRandom(); public static final Log LOG = LogFactory.getLog(NIOClientUDPSocket.class); public NIOClientUDPSocket() throws IOException{ _channel = DatagramChannel.open(); _channel.configureBlocking(false); } @Override public void close() { if (_channel != null) { try { _channel.close(); } catch (IOException e) { LOG.error(CCStringUtils.stringifyException(e)); } finally { _channel = null; } } } @Override public AbstractSelectableChannel getChannel() { return _channel; } @Override public NIOSocketListener getListener() { // TODO Auto-generated method stub return null; } @Override public int getSocketId() { return _socketId; } @Override public boolean isOpen() { return _channel != null; } @Override public void setListener(NIOSocketListener listener) { _listener = listener; } private boolean bind_random(InetSocketAddress addr) throws IOException { InetSocketAddress temp; for (int i = 0; i < 1024; i++) { try { int port = prng.nextInt(EPHEMERAL_RANGE) + EPHEMERAL_START; if (addr != null) temp = new InetSocketAddress(addr.getAddress(),port); else temp = new InetSocketAddress(port); _channel.socket().bind(temp); return true; } catch (SocketException e) { } } return false; } @Override public void connect(InetSocketAddress remoteAddress) throws IOException { if (!bind_random(null)) { throw new IOException("Unable to bind to random port!"); } _channel.socket().connect(remoteAddress); } @Override public boolean finishConnect() throws IOException { return true; } @Override public InetSocketAddress getLocalSocketAddress() throws IOException { return new InetSocketAddress(_channel.socket().getLocalAddress(),_channel.socket().getLocalPort()); } @Override public InetSocketAddress getSocketAddress() throws IOException { return _remoteAddress; } @Override public int read(ByteBuffer dst) throws IOException { return _channel.read(dst); } @Override public int write(ByteBuffer dst) throws IOException { return _channel.write(dst); } }