Moved Network UDT files to their own project. The Network-UDT project

MUST be compiled on Java6, while the Network project MUST be compiled on
 Java7. This difference causes problems in the IDE, since one cannot set
  different source level version on different directories, but only on
  modules.
This commit is contained in:
nathan 2017-07-30 20:17:17 +02:00
parent a4e7447e48
commit b8849832ac
48 changed files with 0 additions and 8665 deletions

View File

@ -1,110 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.barchart.udt.net.NetSocketUDT;
public class AppClient {
static boolean finished = false;
/**
* @param args
* @throws IOException
*/
public static void main(final String[] args) {
String host;
int port = 9000;
final int size = 10000;
final byte[] data = new byte[size];
Future<Boolean> monResult = null;
if (args.length != 2) {
System.out.println("usage: appclient server_host server_port");
return;
}
host = args[0];
port = Integer.parseInt(args[1]);
try {
final NetSocketUDT socket = new NetSocketUDT();
if (System.getProperty("os.name").contains("win"))
socket.socketUDT().setOption(OptionUDT.UDT_MSS, 1052);
socket.connect(new InetSocketAddress(host, port));
final OutputStream os = socket.getOutputStream();
// Start the monitor background task
monResult = Executors.newSingleThreadExecutor().submit(
new Callable<Boolean>() {
@Override
public Boolean call() {
return monitor(socket.socketUDT());
}
});
for (int i = 0; i < 1000000; i++) {
os.write(data);
}
finished = true;
if (monResult != null)
monResult.get();
} catch (final IOException ioe) {
ioe.printStackTrace();
} catch (final InterruptedException e) {
e.printStackTrace();
} catch (final ExecutionException e) {
e.printStackTrace();
}
}
public static boolean monitor(final SocketUDT socket) {
System.out
.println("SendRate(Mb/s)\tRTT(ms)\tCWnd\tPktSndPeriod(us)\tRecvACK\tRecvNAK");
try {
while (!finished) {
Thread.sleep(1000);
socket.updateMonitor(false);
System.out.printf("%.2f\t\t" + "%.2f\t" + "%d\t" + "%.2f\t\t\t"
+ "%d\t" + "%d\n", socket.monitor().mbpsSendRate,
socket.monitor().msRTT,
socket.monitor().pktCongestionWindow,
socket.monitor().usPktSndPeriod,
socket.monitor().pktRecvACK,
socket.monitor().pktRecvNAK);
}
return true;
} catch (final Exception e) {
e.printStackTrace();
return false;
}
}
}

View File

@ -1,84 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import com.barchart.udt.net.NetServerSocketUDT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
public class AppServer {
/**
* @param args
* @throws IOException
*/
static Logger log = LoggerFactory.getLogger(AppServer.class);
public static void main(final String[] args) throws IOException {
int port = 9000;
if (args.length > 1) {
System.out.println("usage: appserver [server_port]");
return;
}
if (args.length == 1) {
port = Integer.parseInt(args[0]);
}
final NetServerSocketUDT acceptorSocket = new NetServerSocketUDT();
acceptorSocket.bind(new InetSocketAddress("0.0.0.0", port), 256);
System.out.println("Server is ready at port: " + port);
while (true) {
final Socket clientSocket = acceptorSocket.accept();
// Start the read ahead background task
Executors.newSingleThreadExecutor().submit(new Callable<Boolean>() {
@Override
public Boolean call() {
return clientTask(clientSocket);
}
});
}
}
public static boolean clientTask(final Socket clientSocket) {
final byte[] data = new byte[10000];
try {
final InputStream is = clientSocket.getInputStream();
while (true) {
int remain = data.length;
while (remain > 0) {
final int ret = is.read(data, data.length - remain, remain);
remain -= ret;
}
}
} catch (final IOException ioe) {
ioe.printStackTrace();
return false;
}
}
}

View File

@ -1,76 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A wrapper around the base UDT congestion control class
*
* @see <a href="http://udt.sourceforge.net/udt4/doc/ccc.htm">reference</a>
* @see <a href="http://udt.sourceforge.net/udt4/doc/t-cc.htm">tutorial</a>
* @see FactoryUDT
* @see FactoryInterfaceUDT
*
* @author CCob
*/
public class CCC {
/** Force SocketUDT to load JNI if it hasn't already */
private static boolean initOk = SocketUDT.INIT_OK;
/** Used internally by the JNI layer, points to JNICCC class */
private long nativeHandle;
private int msINT;
private int pktINT;
private int usRTO;
private final Logger log = LoggerFactory.getLogger(CCC.class);
private native void initNative();
protected native void setACKTimer(final int msINT);
protected native void setACKInterval(final int pktINT);
protected native void setRTO(final int usRTO);
protected native void setPacketSndPeriod(final double sndPeriod);
protected native void setCWndSize(final double cWndSize);
protected native MonitorUDT getPerfInfo();
public CCC() {
initNative();
}
public void init() {
log.info("CCC::init");
}
public void close() {
log.info("CCC::close");
}
public void onACK(final int ack) {
}
public void onLoss(final int[] lossList) {
}
public void onTimeout() {
}
// TODO: implement Java wrapper around CPacket
// public void onPktSent(const CPacket* pkt) {}
// public void onPktReceived(const CPacket* pkt) {}
// public void processCustomMsg(const CPacket& pkt) {}/
// void sendCustomMsg(CPacket& pkt) const;
}

View File

@ -1,245 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* UDT Epoll Manager
*
* @see <a href="http://en.wikipedia.org/wiki/Epoll">Epoll</a>
* @see <a href="http://udt.sourceforge.net/udt4/doc/epoll.htm">UDT Epoll</a>
*/
public class EpollUDT {
/**
* poll interest option mask
* <p>
* see udt.h enum - EPOLLOpt
*
* <pre>
* UDT_EPOLL_IN = 0x1,
* UDT_EPOLL_OUT = 0x4,
* UDT_EPOLL_ERR = 0x8
* </pre>
*
* this is subset adapted to jdk select pattern
*/
public static enum Opt {
/**
* not interested
*/
NONE(0x0), //
/**
* UDT_EPOLL_IN : interested in read
*/
READ(0x1), //
/**
* UDT_EPOLL_OUT: interested in write
*/
WRITE(0x4), //
/**
* UDT_EPOLL_ERR: interested in exceptions
*/
ERROR(0x8), //
BOTH(WRITE.code | READ.code), //
ERROR_READ(ERROR.code | READ.code), //
ERROR_WRITE(ERROR.code | WRITE.code), //
ALL(ERROR.code | WRITE.code | READ.code), //
UNKNOWN(-1);
;
private static final Opt[] ENUM_VALS = Opt.values();
public static Opt from(final int code) {
for (final Opt known : ENUM_VALS) {
if (known.code == code) {
return known;
}
}
return UNKNOWN;
}
/**
* poll event mask;
* <p>
* used for both requesting interest and reporting readiness
*/
public final int code;
Opt(final int code) {
this.code = code;
}
public boolean hasError() {
return (code & ERROR.code) != 0;
}
public boolean hasRead() {
return (code & READ.code) != 0;
}
public boolean hasWrite() {
return (code & WRITE.code) != 0;
}
/**
* Non-empty mask of 3 parts.
*/
public boolean isValidInterestRequest() {
switch (this) {
case NONE:
case READ:
case WRITE:
case ERROR:
case BOTH:
case ERROR_WRITE:
case ERROR_READ:
case ALL:
return true;
default:
return false;
}
}
}
protected static final Logger log = LoggerFactory.getLogger(EpollUDT.class);
protected final int id;
protected volatile boolean isActive;
/**
* place holder socket to work around logic in epoll.h CEPoll::wait() which
* expects at least one socket being monitored with non empty interest
*/
private final SocketUDT socketUDT;
/**
* allocate poll
*/
public EpollUDT() throws ExceptionUDT {
id = SocketUDT.epollCreate0();
isActive = true;
socketUDT = new SocketUDT(TypeUDT.DATAGRAM);
SocketUDT.epollAdd0(id, socketUDT.id(), Opt.BOTH.code);
log.debug("ep {} create", id());
}
/**
* deallocate poll; called on {@link #finalize()}
*/
public void destroy() throws ExceptionUDT {
SocketUDT.epollRemove0(id(), socketUDT.id());
socketUDT.close();
isActive = false;
SocketUDT.epollRelease0(id());
log.debug("ep {} delete", id());
}
/**
* poll descriptor id
*/
public int id() {
return id;
}
/**
* poll becomes active after instance creation and inactive after
* {@link #destroy()}
*/
public boolean isActive() {
return isActive;
}
/**
* deallocate poll
* <p>
* NOTE: catch all exceptions; else prevents GC
* <p>
* NOTE: do not leak "this" references; else prevents GC
*/
@Override
protected void finalize() {
try {
destroy();
super.finalize();
} catch (final Throwable e) {
log.error("failed to destroy id=" + id(), e);
}
}
/**
* register socket into event processing poll
*/
public void add(final SocketUDT socket, final Opt option)
throws ExceptionUDT {
log.debug("ep {} add {} {}", id(), socket, option);
// assert option.isValidInterestRequest();
SocketUDT.epollAdd0(id(), socket.id(), option.code);
}
/**
* unregister socket from event processing poll
*/
public void remove(final SocketUDT socket) throws ExceptionUDT {
log.debug("ep {} rem {}", id(), socket);
SocketUDT.epollRemove0(id(), socket.id());
}
/**
* update existing poll/socket registration with changed interest
*/
public void update(final SocketUDT socket, final Opt option)
throws ExceptionUDT {
log.debug("ep {} mod {} {}", id(), socket, option);
assert option.isValidInterestRequest();
SocketUDT.epollUpdate0(id(), socket.id(), option.code);
}
/** report current poll/socket readiness */
public Opt verify(final SocketUDT socket) throws ExceptionUDT {
final int code = SocketUDT.epollVerify0(id(), socket.id());
return Opt.from(code);
}
}

View File

@ -1,139 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
/**
* keep code values in sync with
*
* @see <a href="http://udt.sourceforge.net/udt4/doc/ecode.htm">UDT Error Codes
* List</a>
*/
public enum ErrorUDT {
SUCCESS(0, "success operation"), //
ECONNSETUP(1000, "connection setup failure"), //
NOSERVER(1001, "server does not exist"), //
ECONNREJ(1002, "connection request was rejected by server"), //
ESOCKFAIL(1003, "could not create/configure UDP socket"), //
ESECFAIL(1004, "connection request was aborted due to security reasons"), //
ECONNFAIL(2000, "connection failure"), //
ECONNLOST(2001, "connection was broken"), //
ENOCONN(2002, "connection does not exist"), //
ERESOURCE(3000, "system resource failure"), //
ETHREAD(3001, "could not create new thread"), //
ENOBUF(3002, "no memory space"), //
EFILE(4000, "file access error"), //
EINVRDOFF(4001, "invalid read offset"), //
ERDPERM(4002, "no read permission"), //
EINVWROFF(4003, "invalid write offset"), //
EWRPERM(4004, "no write permission"), //
EINVOP(5000, "operation not supported"), //
EBOUNDSOCK(5001, "cannot execute the operation on a bound socket"), //
ECONNSOCK(5002, "cannot execute the operation on a connected socket"), //
EINVPARAM(5003, "bad parameters"), //
EINVSOCK(5004, "invalid UDT socket"), //
EUNBOUNDSOCK(5005, "cannot listen on unbound socket"), //
ENOLISTEN(5006, "(accept) socket is not in listening state"), //
ERDVNOSERV(5007,
"rendezvous connection process does not allow listen and accept call"), //
ERDVUNBOUND(
5008,
"rendezvous connection setup is enabled but bind has not been called before connect"), //
ESTREAMILL(5009, "operation not supported in SOCK_STREAM mode"), //
EDGRAMILL(5010, "operation not supported in SOCK_DGRAM mode"), //
EDUPLISTEN(5011, "another socket is already listening on the same UDP port"), //
ELARGEMSG(5012, "message is too large to be hold in the sending buffer"), //
EINVPOLLID(5013, "epoll ID is invalid"), //
EASYNCFAIL(6000, "non-blocking call failure"), //
EASYNCSND(6001, "no buffer available for sending"), //
EASYNCRCV(6002, "no data available for read"), //
ETIMEOUT(6003, "timeout before operation completes"), //
EPEERERR(7000, "error has happened at the peer side"), //
// non UDT values:
WRAPPER_UNKNOWN(-1, "unknown error code"), //
WRAPPER_UNIMPLEMENTED(-2, "this feature is not yet implemented"), //
WRAPPER_MESSAGE(-3, "wrapper generated error"), //
USER_DEFINED_MESSAGE(-4, "user defined message"), //
;
private final int code;
public int getCode() {
return code;
}
private final String description;
public String getDescription() {
return description;
}
private ErrorUDT(final int code, final String description) {
this.code = code;
this.description = description;
}
static final ErrorUDT[] ENUM_VALS = values();
public static ErrorUDT errorFrom(final int code) {
for (final ErrorUDT known : ENUM_VALS) {
if (known.code == code) {
return known;
}
}
return WRAPPER_UNKNOWN;
}
//
public static String descriptionFrom(final int socketID,
final int errorCode, final String errorComment) {
final ErrorUDT error = ErrorUDT.errorFrom(errorCode);
return String.format("UDT Error : %d : %s : %s [id: 0x%08x]", //
errorCode, error.description, errorComment, socketID);
}
}

View File

@ -1,81 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import java.net.SocketException;
import com.barchart.udt.anno.Native;
/**
* The Class ExceptionUDT. Wraps all native UDT exceptions and more.
*/
@SuppressWarnings("serial")
public class ExceptionUDT extends SocketException {
/**
* The error udt. Keeps error description for this exception. Use this enum
* in switch/case to fine tune exception processing.
*/
@Native
private final ErrorUDT errorUDT;
public ErrorUDT getError() {
return errorUDT;
}
/**
* The socket id. Keeps socketID of the socket that produced this exception.
* Can possibly contain '0' when particular method can not determine
* {@link #socketID} that produced the exception.
*/
@Native
private final int socketID;
public int getSocketID() {
return socketID;
}
/**
* Instantiates a new exception udt for native UDT::Exception. This
* exception is generated in the underlying UDT method.
*
* @param socketID
* the socket id
* @param errorCode
* the error code
* @param comment
* the comment
*/
@Native
protected ExceptionUDT(final int socketID, final int errorCode,
final String comment) {
super(ErrorUDT.descriptionFrom(socketID, errorCode, comment));
errorUDT = ErrorUDT.errorFrom(errorCode);
this.socketID = socketID;
}
/**
* Instantiates a new exception udt for synthetic JNI wrapper exception.
* This exception is generated in the JNI glue code itself.
*
* @param socketID
* the socket id
* @param error
* the error
* @param comment
* the comment
*/
@Native
protected ExceptionUDT(final int socketID, final ErrorUDT error,
final String comment) {
super(ErrorUDT.descriptionFrom(socketID, error.getCode(), comment));
errorUDT = error;
this.socketID = socketID;
}
}

View File

@ -1,19 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
/**
* @author CCob
*/
public interface FactoryInterfaceUDT {
CCC create();
FactoryInterfaceUDT cloneFactory();
}

View File

@ -1,88 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Wrapper around the UDT CCCFactory class
*
* @see <a href="http://udt.sourceforge.net/udt4/doc/ccc.htm">reference</a>
* @see <a href="http://udt.sourceforge.net/udt4/doc/t-cc.htm">tutorial</a>
* @see CCC
*
* @author CCob
*/
public class FactoryUDT<C> implements FactoryInterfaceUDT {
C classType;
final Class<C> clazz;
Logger log = LoggerFactory.getLogger(FactoryUDT.class);
boolean doInit = false;
boolean doClose = false;
boolean doOnACK = false;
boolean doOnLoss = false;
boolean doOnTimeout = false;
public FactoryUDT(final Class<C> clazz) {
this.clazz = clazz;
if (!CCC.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException(
"Generic argument 'C' must be 'CCC' class or extension");
}
try {
if (clazz.getMethod("init").getDeclaringClass() != CCC.class)
doInit = true;
if (clazz.getMethod("close").getDeclaringClass() != CCC.class)
doClose = true;
if (clazz.getMethod("onACK", int.class).getDeclaringClass() != CCC.class)
doOnACK = true;
if (clazz.getMethod("onLoss", int[].class).getDeclaringClass() != CCC.class)
doOnLoss = true;
if (clazz.getMethod("onTimeout").getDeclaringClass() != CCC.class)
doOnTimeout = true;
} catch (final SecurityException e) {
log.error("Error setting up class factory", e);
} catch (final NoSuchMethodException e) {
log.error("Expected CCC method doesn't exsit", e);
}
}
@Override
public CCC create() {
try {
final Object cccObj = clazz.newInstance();
return (CCC) cccObj;
} catch (final InstantiationException e) {
log.error("Failed to instansiate CCC class", e);
} catch (final IllegalAccessException e) {
log.error("Failed to instansiate CCC class", e);
}
return null;
}
@Override
public FactoryInterfaceUDT cloneFactory() {
return new FactoryUDT<C>(clazz);
}
}

View File

@ -1,101 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
public class LingerUDT extends Number implements Comparable<LingerUDT> {
public static final LingerUDT LINGER_ZERO = new LingerUDT(0);
// measured in seconds
final int timeout;
/**
* Default constructor. NOTE: linger value is "u_short" on windows and "int"
* on linux:<br>
* Windows: <a
* href="http://msdn.microsoft.com/en-us/library/ms739165(VS.85).aspx">
* linger Structure on Windows</a><br>
* Linux: <a href=
* "http://www.gnu.org/s/libc/manual/html_node/Socket_002dLevel-Options.html"
* >GCC Socket-Level Options</a><br>
* Therefore select smallest range: 0 <= linger <= 65535 <br>
*
* @param lingerSeconds
* the seconds to linger; "0" means "do not linger"
*
* @throws IllegalArgumentException
* when lingerSeconds is out of range
*/
public LingerUDT(int lingerSeconds) throws IllegalArgumentException {
if (65535 < lingerSeconds) {
throw new IllegalArgumentException(
"lingerSeconds is out of range: 0 <= linger <= 65535");
}
this.timeout = lingerSeconds > 0 ? lingerSeconds : 0;
}
private static final long serialVersionUID = 3414455799823407217L;
@Override
public double doubleValue() {
return timeout;
}
/*
* (non-Javadoc)
*
* @see java.lang.Number#floatValue()
*/
@Override
public float floatValue() {
return timeout;
}
@Override
public int intValue() {
return timeout;
}
@Override
public long longValue() {
return timeout;
}
boolean isLingerOn() {
return timeout > 0;
}
int timeout() {
return timeout;
}
@Override
public boolean equals(Object otherLinger) {
if (otherLinger instanceof LingerUDT) {
LingerUDT other = (LingerUDT) otherLinger;
return other.timeout == this.timeout;
}
return false;
}
@Override
public int hashCode() {
return timeout;
}
@Override
public int compareTo(LingerUDT other) {
return other.timeout - this.timeout;
}
@Override
public String toString() {
return String.valueOf(timeout);
}
}

View File

@ -1,379 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import java.lang.reflect.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* note: do not change field names; used by JNI
*/
public class MonitorUDT {
private static final Logger log = LoggerFactory.getLogger(MonitorUDT.class);
protected final SocketUDT socketUDT;
protected MonitorUDT(final SocketUDT socketUDT) {
this.socketUDT = socketUDT;
}
// UDT API
// ### global measurements
/** time since the UDT entity is started, in milliseconds. */
protected volatile long msTimeStamp;
public long millisSinceStart() {
return msTimeStamp;
}
/**
* total number of sent data packets, including retransmissions
*/
protected volatile long pktSentTotal;
public long globalSentTotal() {
return pktSentTotal;
}
/**
* total number of received packets
*/
protected volatile long pktRecvTotal;
public long globalReceivedTotal() {
return pktRecvTotal;
}
/**
* total number of lost packets (sender side)
*/
protected volatile int pktSndLossTotal;
public int globalSenderLost() {
return pktSndLossTotal;
}
/**
* total number of lost packets (receiver side)
*/
protected volatile int pktRcvLossTotal;
public int globalReceiverLost() {
return pktRcvLossTotal;
}
/**
* total number of retransmitted packets
*/
protected volatile int pktRetransTotal;
public int globalRetransmittedTotal() {
return pktRetransTotal;
}
/**
* total number of sent ACK packets
*/
protected volatile int pktSentACKTotal;
public int globalSentAckTotal() {
return pktSentACKTotal;
}
/**
* total number of received ACK packets
*/
protected volatile int pktRecvACKTotal;
public int globalReceivedAckTotal() {
return pktRecvACKTotal;
}
/**
* total number of sent NAK packets
*/
protected volatile int pktSentNAKTotal;
public int globalSentNakTotal() {
return pktSentNAKTotal;
}
/**
* total number of received NAK packets
*/
protected volatile int pktRecvNAKTotal;
public int globalReceivedNakTotal() {
return pktRecvNAKTotal;
}
/**
* total time duration when UDT is sending data (idle time exclusive)
*/
protected volatile long usSndDurationTotal;
public long globalMicrosSendDurationTotal() {
return usSndDurationTotal;
}
// ### local measurements
/**
* number of sent data packets, including retransmissions
*/
protected volatile long pktSent;
public long localPacketsSent() {
return pktSent;
}
/**
* number of received packets
*/
protected volatile long pktRecv;
public long localPacketsReceived() {
return pktRecv;
}
/**
* number of lost packets (sender side)
*/
protected volatile int pktSndLoss;
public int localSenderLost() {
return pktSndLoss;
}
/**
* number of lost packets (receiverer side)
*/
protected volatile int pktRcvLoss;
public int localReceiverLost() {
return pktRcvLoss;
}
/**
* number of retransmitted packets
*/
protected volatile int pktRetrans;
public int localRetransmitted() {
return pktRetrans;
}
/**
* number of sent ACK packets
*/
protected volatile int pktSentACK;
public int localSentAck() {
return pktSentACK;
}
/**
* number of received ACK packets
*/
protected volatile int pktRecvACK;
public int localReceivedAck() {
return pktRecvACK;
}
/**
* number of sent NAK packets
*/
protected volatile int pktSentNAK;
public int localSentNak() {
return pktSentNAK;
}
/**
* number of received NAK packets
*/
protected volatile int pktRecvNAK;
public int localReceivedNak() {
return pktRecvNAK;
}
/**
* sending rate in Mb/s
*/
protected volatile double mbpsSendRate;
public double mbpsSendRate() {
return mbpsSendRate;
}
/**
* receiving rate in Mb/s
*/
protected volatile double mbpsRecvRate;
public double mbpsReceiveRate() {
return mbpsRecvRate;
}
/**
* busy sending time (i.e., idle time exclusive)
*/
protected volatile long usSndDuration;
public long microsSendTime() {
return usSndDuration;
}
// ### instant measurements
/**
* packet sending period, in microseconds
*/
protected volatile double usPktSndPeriod;
public double currentSendPeriod() {
return usPktSndPeriod;
}
/**
* flow window size, in number of packets
*/
protected volatile int pktFlowWindow;
public int currentFlowWindow() {
return pktFlowWindow;
}
/**
* congestion window size, in number of packets
*/
protected volatile int pktCongestionWindow;
public int currentCongestionWindow() {
return pktCongestionWindow;
}
/**
* number of packets on flight
*/
protected volatile int pktFlightSize;
public int currentFlightSize() {
return pktFlightSize;
}
/**
* RTT, in milliseconds
*/
protected volatile double msRTT;
public double currentMillisRTT() {
return msRTT;
}
/**
* estimated bandwidth, in Mb/s
*/
protected volatile double mbpsBandwidth;
public double currentMbpsBandwidth() {
return mbpsBandwidth;
}
/**
* available UDT sender buffer size
*/
protected volatile int byteAvailSndBuf;
public int currentAvailableInSender() {
return byteAvailSndBuf;
}
/**
* available UDT receiver buffer size
*/
protected volatile int byteAvailRcvBuf;
public int currentAvailableInReceiver() {
return byteAvailRcvBuf;
}
/**
* current monitor status snapshot for all parameters
*/
public void appendSnapshot(final StringBuilder text) {
text.append("\n\t");
text.append(String.format("[id: 0x%08x]", socketUDT.id()));
final Field fieldArray[] = MonitorUDT.class.getDeclaredFields();
for (final Field field : fieldArray) {
if (!isNumeric(field)) {
continue;
}
try {
field.setAccessible(true);
final String fieldName = field.getName();
final String fieldValue = field.get(this).toString();
text.append("\n\t");
text.append(fieldName);
text.append(" = ");
text.append(fieldValue);
} catch (final Exception e) {
log.error("unexpected", e);
}
}
final double localSendLoss = 100.0 * pktSndLoss / pktSent;
text.append("\n\t% localSendLoss = ");
text.append(localSendLoss);
final double localReceiveLoss = 100.0 * pktRcvLoss / pktRecv;
text.append("\n\t% localReceiveLoss = ");
text.append(localReceiveLoss);
}
protected boolean isNumeric(final Field field) {
final Class<?> fieledType = field.getType();
return fieledType == int.class || fieledType == long.class
|| fieledType == double.class;
}
@Override
public String toString() {
final StringBuilder text = new StringBuilder(1024);
appendSnapshot(text);
return text.toString();
}
}

View File

@ -1,323 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import static com.barchart.udt.OptionUDT.Format.BINARY;
import static com.barchart.udt.OptionUDT.Format.BOOLEAN;
import static com.barchart.udt.OptionUDT.Format.DECIMAL;
import static com.barchart.udt.OptionUDT.Format.DEFAULT;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.util.HelpUDT;
/**
* The Enum OptionUDT.
* <p>
* provide 2 names: 1) UDT original and 2) human-readble
* <p>
* keep code values in sync with udt.h - UDT::UDTOpt; enum starts with index 0
*
* @see <a href="http://udt.sourceforge.net/udt4/doc/opt.htm">udt options</a>
* <pre>
* UDT_MSS, // the Maximum Transfer Unit
* UDT_SNDSYN, // if sending is blocking
* UDT_RCVSYN, // if receiving is blocking
* UDT_CC, // custom congestion control algorithm
* UDT_FC, // Flight flag size (window size)
* UDT_SNDBUF, // maximum buffer in sending queue
* UDT_RCVBUF, // UDT receiving buffer size
* UDT_LINGER, // waiting for unsent data when closing
* UDP_SNDBUF, // UDP sending buffer size
* UDP_RCVBUF, // UDP receiving buffer size
* UDT_MAXMSG, // maximum datagram message size
* UDT_MSGTTL, // time-to-live of a datagram message
* UDT_RENDEZVOUS, // rendezvous connection mode
* UDT_SNDTIMEO, // send() timeout
* UDT_RCVTIMEO, // recv() timeout
* UDT_REUSEADDR, // reuse an existing port or create a new one
* UDT_MAXBW, // maximum bandwidth (bytes per second) that the connection can use
* UDT_STATE, // current socket state, see UDTSTATUS, read only
* UDT_EVENT, // current avalable events associated with the socket
* UDT_SNDDATA, // size of data in the sending buffer
* UDT_RCVDATA // size of data available for recv
* </pre>
*/
public class OptionUDT<T> {
static {
log = LoggerFactory.getLogger(OptionUDT.class);
values = new CopyOnWriteArrayList<OptionUDT<?>>();
}
/** the Maximum Transfer Unit. */
public static final OptionUDT<Integer> UDT_MSS = NEW(0, Integer.class, DECIMAL);
/** the Maximum Transfer Unit., bytes */
public static final OptionUDT<Integer> Maximum_Transfer_Unit = NEW(0, Integer.class, DECIMAL);
/** if sending is blocking. */
public static final OptionUDT<Boolean> UDT_SNDSYN = NEW(1, Boolean.class, BOOLEAN);
/** if sending is blocking., true/false */
public static final OptionUDT<Boolean> Is_Send_Synchronous = NEW(1, Boolean.class, BOOLEAN);
/** if receiving is blocking. */
public static final OptionUDT<Boolean> UDT_RCVSYN = NEW(2, Boolean.class, BOOLEAN);
/** if receiving is blocking, true/false */
public static final OptionUDT<Boolean> Is_Receive_Synchronous = NEW(2, Boolean.class, BOOLEAN);
/** custom congestion control algorithm */
@SuppressWarnings("rawtypes")
public static final OptionUDT<FactoryUDT> UDT_CC = NEW(3, FactoryUDT.class, DEFAULT);
/** custom congestion control algorithm, class factory */
@SuppressWarnings("rawtypes")
public static final OptionUDT<FactoryUDT> Custom_Congestion_Control = NEW(3, FactoryUDT.class, DEFAULT);
/** Flight flag size (window size). */
public static final OptionUDT<Integer> UDT_FC = NEW(4, Integer.class, BINARY);
/** Flight flag size (window size), bytes */
public static final OptionUDT<Integer> Flight_Window_Size = NEW(4, Integer.class, BINARY);
/** maximum buffer in sending queue. */
public static final OptionUDT<Integer> UDT_SNDBUF = NEW(5, Integer.class, DECIMAL);
/** maximum buffer in sending queue. */
public static final OptionUDT<Integer> Protocol_Send_Buffer_Size = NEW(5, Integer.class, DECIMAL);
/** UDT receiving buffer size. */
public static final OptionUDT<Integer> UDT_RCVBUF = NEW(6, Integer.class, DECIMAL);
/** UDT receiving buffer size limit, bytes */
public static final OptionUDT<Integer> Protocol_Receive_Buffer_Size = NEW(6, Integer.class, DECIMAL);
/** waiting for unsent data when closing. */
public static final OptionUDT<LingerUDT> UDT_LINGER = NEW(7, LingerUDT.class, DECIMAL);
/** waiting for unsent data when closing. true/false and timeout, seconds */
public static final OptionUDT<LingerUDT> Time_To_Linger_On_Close = NEW(7, LingerUDT.class, DECIMAL);
/** UDP sending buffer size. */
public static final OptionUDT<Integer> UDP_SNDBUF = NEW(8, Integer.class, DECIMAL);
/** UDP sending buffer size limit, bytes */
public static final OptionUDT<Integer> System_Send_Buffer_Size = NEW(8, Integer.class, DECIMAL);
/** UDP receiving buffer size. */
public static final OptionUDT<Integer> UDP_RCVBUF = NEW(9, Integer.class, DECIMAL);
/** UDP receiving buffer size limit, bytes */
public static final OptionUDT<Integer> System_Receive_Buffer_Size = NEW(9, Integer.class, DECIMAL);
/* maximum datagram message size */
// UDT_MAXMSG(10, Integer.class, DECIMAL); no support in udt core
/* time-to-live of a datagram message */
// UDT_MSGTTL(11, Integer.class, DECIMAL); no support in udt core
/** rendezvous connection mode. */
public static final OptionUDT<Boolean> UDT_RENDEZVOUS = NEW(12, Boolean.class, BOOLEAN);
/** rendezvous connection mode, enabled/disabled */
public static final OptionUDT<Boolean> Is_Randezvous_Connect_Enabled = NEW(12, Boolean.class, BOOLEAN);
/** send() timeout. */
public static final OptionUDT<Integer> UDT_SNDTIMEO = NEW(13, Integer.class, DECIMAL);
/** send() timeout. milliseconds */
public static final OptionUDT<Integer> Send_Timeout = NEW(13, Integer.class, DECIMAL);
/** recv() timeout. */
public static final OptionUDT<Integer> UDT_RCVTIMEO = NEW(14, Integer.class, DECIMAL);
/** recv() timeout. milliseconds */
public static final OptionUDT<Integer> Receive_Timeout = NEW(14, Integer.class, DECIMAL);
/** reuse an existing port or create a one. */
public static final OptionUDT<Boolean> UDT_REUSEADDR = NEW(15, Boolean.class, BOOLEAN);
/** reuse an existing port or create a one. true/false */
public static final OptionUDT<Boolean> Is_Address_Reuse_Enabled = NEW(15, Boolean.class, BOOLEAN);
/** maximum bandwidth (bytes per second) that the connection can use. */
public static final OptionUDT<Long> UDT_MAXBW = NEW(16, Long.class, DECIMAL);
/** maximum bandwidth (bytes per second) that the connection can use. */
public static final OptionUDT<Long> Maximum_Bandwidth = NEW(16, Long.class, DECIMAL);
/** current socket state, see UDTSTATUS, read only */
public static final OptionUDT<Integer> UDT_STATE = NEW(17, Integer.class, DECIMAL);
/** current socket status code, see {@link StatusUDT#getCode()}, read only */
public static final OptionUDT<Integer> Status_Code = NEW(17, Integer.class, DECIMAL);
/** current available events associated with the socket */
public static final OptionUDT<Integer> UDT_EVENT = NEW(18, Integer.class, DECIMAL);
/** current available epoll events, see {@link EpollUDT.Opt#code} */
public static final OptionUDT<Integer> Epoll_Event_Mask = NEW(18, Integer.class, DECIMAL);
/** size of data in the sending buffer */
public static final OptionUDT<Integer> UDT_SNDDATA = NEW(19, Integer.class, DECIMAL);
/** current consumed sending buffer utilization, read only, bytes */
public static final OptionUDT<Integer> Send_Buffer_Consumed = NEW(19, Integer.class, DECIMAL);
/** size of data available for recv */
public static final OptionUDT<Integer> UDT_RCVDATA = NEW(20, Integer.class, DECIMAL);
/** current available receiving buffer capacity, read only, bytes */
public static final OptionUDT<Integer> Receive_Buffer_Available = NEW(20, Integer.class, DECIMAL);
protected OptionUDT(final int code, final Class<T> klaz, final Format format) {
this.code = code;
this.type = klaz;
this.format = format;
values.add(this);
}
protected static <T> OptionUDT<T> NEW(final int code, final Class<T> klaz, final Format format) {
return new OptionUDT<T>(code, klaz, format);
}
public static void appendSnapshot(final SocketUDT socketUDT, final StringBuilder text) {
text.append("\n\t");
text.append(String.format("[id: 0x%08x]", socketUDT.id()));
for (final OptionUDT<?> option : values) {
int optionCode = 0;
String optionName = null;
String optionValue = null;
try {
optionCode = option.code;
optionName = option.name();
optionValue = option.format.convert(//
socketUDT.getOption(option));
if (optionName.startsWith("UD")) {
continue;
}
text.append("\n\t");
text.append(optionCode);
text.append(") ");
text.append(optionName);
text.append(" = ");
text.append(optionValue);
} catch (final Exception e) {
log.error("unexpected; " + optionName, e);
}
}
}
protected static final Logger log;
protected static final List<OptionUDT<?>> values;
private final int code;
private final Class<?> type;
private final Format format;
private String name;
public int code() {
return code;
}
public Class<?> type() {
return type;
}
public Format format() {
return format;
}
public String name() {
if (name == null) {
name = HelpUDT.constantFieldName(getClass(), this);
}
return name;
}
/**
* render options in human format
*/
public enum Format {
DECIMAL() {
@Override
public String convert(final Object value) {
if (value instanceof Number) {
final long number = ((Number) value).longValue();
return String.format("%,d", number);
}
return "invalid format";
}
}, //
BINARY() {
@Override
public String convert(final Object value) {
if (value instanceof Number) {
final long number = ((Number) value).longValue();
return String.format("%,d (%,d K)", number, number / 1024);
}
return "invalid format";
}
}, //
BOOLEAN() {
@Override
public String convert(final Object value) {
if (value instanceof Boolean) {
final boolean bool = ((Boolean) value).booleanValue();
return String.format("%b", bool);
}
return "invalid format";
}
}, //
DEFAULT() {
@Override
public String convert(final Object value) {
return "" + value;
}
}, //
;
public abstract String convert(Object value);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,100 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* status of underlying UDT native socket as reported by
* {@link SocketUDT#getStatus0()}
* <p>
* keep in sync with udt.h UDTSTATUS enum; see:
* <p>
* "enum UDTSTATUS { INIT = 1, OPENED = 2, LISTENING = 3, CONNECTING = 4, CONNECTED = 5, BROKEN = 6, CLOSING = 7, CLOSED = 8, NONEXIST = 9 };"
*/
public enum StatusUDT {
/** note: keep the order */
//
/** newly created socket; both connector and acceptor */
INIT(1), //
/** bound socket; both connector and acceptor */
OPENED(2), //
/** bound and listening acceptor socket */
LISTENING(3), //
/** bound connector socket trying to connect */
CONNECTING(4), //
/** bound and connected connector socket */
CONNECTED(5), //
/** acceptor socket after close(), connector socket after remote unreachable */
BROKEN(6), //
/** connector socket while close() is in progress */
CLOSING(7), //
/** connector socket after close() is done */
CLOSED(8), //
/** trying to check status on socket that was closed and removed */
NONEXIST(9), //
/** non udt constant, catch-all value */
UNKNOWN(100), //
;
protected static final Logger log = LoggerFactory
.getLogger(StatusUDT.class);
private final int code;
private StatusUDT(final int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static final StatusUDT from(final int code) {
switch (code) {
case 1:
return INIT;
case 2:
return OPENED;
case 3:
return LISTENING;
case 4:
return CONNECTING;
case 5:
return CONNECTED;
case 6:
return BROKEN;
case 7:
return CLOSING;
case 8:
return CLOSED;
case 9:
return NONEXIST;
default:
log.error("unexpected code={}", code);
return UNKNOWN;
}
}
}

View File

@ -1,51 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt;
/**
* UDT socket mode type.
*
* NOTE: {@link #TypeUDT} means stream vs datagram;
* {@link com.barchart.udt.nio.KindUDT} means server vs client.
* <p>
* maps to socket.h constants<br>
* SOCK_STREAM = 1<br>
* SOCK_DGRAM = 2<br>
*/
public enum TypeUDT {
/**
* The STREAM type. Defines "byte stream" UDT mode.
*/
STREAM(1), //
/**
* The DATAGRAM. Defines "datagram or message" UDT mode.
*/
DATAGRAM(2), //
;
protected final int code;
/**
* native UDT constant
*/
public int code() {
return code;
}
/**
* @param code
* native UDT constant
*/
private TypeUDT(final int code) {
this.code = code;
}
}

View File

@ -1,24 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.anno;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* annotation marks a native JNI entity, please not change it in any way
*/
@Documented
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
@Retention(RetentionPolicy.RUNTIME)
public @interface Native {
}

View File

@ -1,26 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.anno;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* annotation documents thread safe access contract
*/
@Documented
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
@Retention(RetentionPolicy.RUNTIME)
public @interface ThreadSafe {
String value();
}

View File

@ -1,30 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.ccc;
import com.barchart.udt.CCC;
/**
* Wrapper around the CUDPBlast class that demos the use of a custom congestion
* control algorithm
*
* @author CCob
*/
public class UDPBlast extends CCC {
static final int iSMSS = 1500;
public UDPBlast() {
setCWndSize(83333.0);
}
public void setRate(final int mbps) {
setPacketSndPeriod((iSMSS * 8.0) / mbps);
}
}

View File

@ -1,24 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import com.barchart.udt.ErrorUDT;
import com.barchart.udt.ExceptionUDT;
/**
*
*/
@SuppressWarnings("serial")
public class ExceptionReceiveUDT extends ExceptionUDT {
protected ExceptionReceiveUDT(final int socketID, final ErrorUDT error,
final String comment) {
super(socketID, error, comment);
}
}

View File

@ -1,24 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import com.barchart.udt.ErrorUDT;
import com.barchart.udt.ExceptionUDT;
/**
*
*/
@SuppressWarnings("serial")
public class ExceptionSendUDT extends ExceptionUDT {
protected ExceptionSendUDT(final int socketID, final ErrorUDT error,
final String comment) {
super(socketID, error, comment);
}
}

View File

@ -1,22 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import com.barchart.udt.SocketUDT;
/**
* custom/common acceptor/connector socket features
*/
public interface IceCommon {
/**
* expose underlying socket
*/
SocketUDT socketUDT();
}

View File

@ -1,560 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.PortUnreachableException;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.channels.DatagramChannel;
/**
* compatibility verification interface
*/
public interface IceDatagramSocket {
/**
* Binds this DatagramSocket to a specific address & port.
* <p>
* If the address is <code>null</code>, then the system will pick up an
* ephemeral port and a valid local address to bind the socket.
* <p>
*
* @param addr
* The address & port to bind to.
* @throws SocketException
* if any error happens during the bind, or if the socket is
* already bound.
* @throws SecurityException
* if a security manager exists and its <code>checkListen</code>
* method doesn't allow the operation.
* @throws IllegalArgumentException
* if addr is a SocketAddress subclass not supported by this
* socket.
* @since 1.4
*/
void bind(SocketAddress addr) throws SocketException;
/**
* Connects the socket to a remote address for this socket. When a socket is
* connected to a remote address, packets may only be sent to or received
* from that address. By default a datagram socket is not connected.
*
* <p>
* If the remote destination to which the socket is connected does not
* exist, or is otherwise unreachable, and if an ICMP destination
* unreachable packet has been received for that address, then a subsequent
* call to send or receive may throw a PortUnreachableException. Note, there
* is no guarantee that the exception will be thrown.
*
* <p>
* A caller's permission to send and receive datagrams to a given host and
* port are checked at connect time. When a socket is connected, receive and
* send <b>will not perform any security checks</b> on incoming and outgoing
* packets, other than matching the packet's and the socket's address and
* port. On a send operation, if the packet's address is set and the
* packet's address and the socket's address do not match, an
* IllegalArgumentException will be thrown. A socket connected to a
* multicast address may only be used to send packets.
*
* @param address
* the remote address for the socket
*
* @param port
* the remote port for the socket.
*
* @exception IllegalArgumentException
* if the address is null, or the port is out of range.
*
* @exception SecurityException
* if the caller is not allowed to send datagrams to and
* receive datagrams from the address and port.
*
* @see #disconnect
* @see #send
* @see #receive
*/
void connect(InetAddress address, int port);
/**
* Connects this socket to a remote socket address (IP address + port
* number).
* <p>
*
* @param addr
* The remote address.
* @throws SocketException
* if the connect fails
* @throws IllegalArgumentException
* if addr is null or addr is a SocketAddress subclass not
* supported by this socket
* @since 1.4
* @see #connect
*/
void connect(SocketAddress addr) throws SocketException;
/**
* Disconnects the socket. This does nothing if the socket is not connected.
*
* @see #connect
*/
void disconnect();
/**
* Returns the binding state of the socket.
*
* @return true if the socket succesfuly bound to an address
* @since 1.4
*/
boolean isBound();
/**
* Returns the connection state of the socket.
*
* @return true if the socket succesfuly connected to a server
* @since 1.4
*/
boolean isConnected();
/**
* Returns the address to which this socket is connected. Returns null if
* the socket is not connected.
*
* @return the address to which this socket is connected.
*/
InetAddress getInetAddress();
/**
* Returns the port for this socket. Returns -1 if the socket is not
* connected.
*
* @return the port to which this socket is connected.
*/
int getPort();
/**
* Returns the address of the endpoint this socket is connected to, or
* <code>null</code> if it is unconnected.
*
* @return a <code>SocketAddress</code> representing the remote endpoint of
* this socket, or <code>null</code> if it is not connected yet.
* @see #getInetAddress()
* @see #getPort()
* @see #connect(SocketAddress)
* @since 1.4
*/
SocketAddress getRemoteSocketAddress();
/**
* Returns the address of the endpoint this socket is bound to, or
* <code>null</code> if it is not bound yet.
*
* @return a <code>SocketAddress</code> representing the local endpoint of
* this socket, or <code>null</code> if it is not bound yet.
* @see #getLocalAddress()
* @see #getLocalPort()
* @see #bind(SocketAddress)
* @since 1.4
*/
SocketAddress getLocalSocketAddress();
/**
* Sends a datagram packet from this socket. The <code>DatagramPacket</code>
* includes information indicating the data to be sent, its length, the IP
* address of the remote host, and the port number on the remote host.
*
* <p>
* If there is a security manager, and the socket is not currently connected
* to a remote address, this method first performs some security checks.
* First, if <code>p.getAddress().isMulticastAddress()</code> is true, this
* method calls the security manager's <code>checkMulticast</code> method
* with <code>p.getAddress()</code> as its argument. If the evaluation of
* that expression is false, this method instead calls the security
* manager's <code>checkConnect</code> method with arguments
* <code>p.getAddress().getHostAddress()</code> and <code>p.getPort()</code>
* . Each call to a security manager method could result in a
* SecurityException if the operation is not allowed.
*
* @param p
* the <code>DatagramPacket</code> to be sent.
*
* @exception IOException
* if an I/O error occurs.
* @exception SecurityException
* if a security manager exists and its
* <code>checkMulticast</code> or <code>checkConnect</code>
* method doesn't allow the send.
* @exception PortUnreachableException
* may be thrown if the socket is connected to a currently
* unreachable destination. Note, there is no guarantee that
* the exception will be thrown.
* @exception java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel, and the channel
* is in non-blocking mode.
*
* @see DatagramPacket
* @see SecurityManager#checkMulticast(InetAddress)
* @see SecurityManager#checkConnect revised 1.4 spec JSR-51
*/
void send(DatagramPacket p) throws IOException;
/**
* Receives a datagram packet from this socket. When this method returns,
* the <code>DatagramPacket</code>'s buffer is filled with the data
* received. The datagram packet also contains the sender's IP address, and
* the port number on the sender's machine.
* <p>
* This method blocks until a datagram is received. The <code>length</code>
* field of the datagram packet object contains the length of the received
* message. If the message is longer than the packet's length, the message
* is truncated.
* <p>
* If there is a security manager, a packet cannot be received if the
* security manager's <code>checkAccept</code> method does not allow it.
*
* @param p
* the <code>DatagramPacket</code> into which to place the
* incoming data.
* @exception IOException
* if an I/O error occurs.
* @exception SocketTimeoutException
* if setSoTimeout was previously called and the timeout has
* expired.
* @exception PortUnreachableException
* may be thrown if the socket is connected to a currently
* unreachable destination. Note, there is no guarantee that
* the exception will be thrown.
* @exception java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel, and the channel
* is in non-blocking mode.
* @see DatagramPacket
* @see java.net.DatagramSocket revised 1.4 spec JSR-51
*/
void receive(DatagramPacket p) throws IOException;
/**
* Gets the local address to which the socket is bound.
*
* <p>
* If there is a security manager, its <code>checkConnect</code> method is
* first called with the host address and <code>-1</code> as its arguments
* to see if the operation is allowed.
*
* @see SecurityManager#checkConnect
* @return the local address to which the socket is bound, or an
* <code>InetAddress</code> representing any local address if either
* the socket is not bound, or the security manager
* <code>checkConnect</code> method does not allow the operation
* @since 1.1
*/
InetAddress getLocalAddress();
/**
* Returns the port number on the local host to which this socket is bound.
*
* @return the port number on the local host to which this socket is bound.
*/
int getLocalPort();
/**
* Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
* With this option set to a non-zero timeout, a call to receive() for this
* DatagramSocket will block for only this amount of time. If the timeout
* expires, a <B>java.net.SocketTimeoutException</B> is raised, though the
* DatagramSocket is still valid. The option <B>must</B> be enabled prior to
* entering the blocking operation to have effect. The timeout must be > 0.
* A timeout of zero is interpreted as an infinite timeout.
*
* @param timeout
* the specified timeout in milliseconds.
* @throws SocketException
* if there is an error in the underlying protocol, such as an
* UDP error.
* @since JDK1.1
* @see #getSoTimeout()
*/
void setSoTimeout(int timeout) throws SocketException;
/**
* Retrieve setting for SO_TIMEOUT. 0 returns implies that the option is
* disabled (i.e., timeout of infinity).
*
* @return the setting for SO_TIMEOUT
* @throws SocketException
* if there is an error in the underlying protocol, such as an
* UDP error.
* @since JDK1.1
* @see #setSoTimeout(int)
*/
int getSoTimeout() throws SocketException;
/**
* Sets the SO_SNDBUF option to the specified value for this
* <tt>DatagramSocket</tt>. The SO_SNDBUF option is used by the network
* implementation as a hint to size the underlying network I/O buffers. The
* SO_SNDBUF setting may also be used by the network implementation to
* determine the maximum size of the packet that can be sent on this socket.
* <p>
* As SO_SNDBUF is a hint, applications that want to verify what size the
* buffer is should call {@link #getSendBufferSize()}.
* <p>
* Increasing the buffer size may allow multiple outgoing packets to be
* queued by the network implementation when the send rate is high.
* <p>
* Note: If {@link #send(DatagramPacket)} is used to send a
* <code>DatagramPacket</code> that is larger than the setting of SO_SNDBUF
* then it is implementation specific if the packet is sent or discarded.
*
* @param size
* the size to which to set the send buffer size. This value must
* be greater than 0.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @exception IllegalArgumentException
* if the value is 0 or is negative.
* @see #getSendBufferSize()
*/
void setSendBufferSize(int size) throws SocketException;
/**
* Get value of the SO_SNDBUF option for this <tt>DatagramSocket</tt>, that
* is the buffer size used by the platform for output on this
* <tt>DatagramSocket</tt>.
*
* @return the value of the SO_SNDBUF option for this
* <tt>DatagramSocket</tt>
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @see #setSendBufferSize
*/
int getSendBufferSize() throws SocketException;
/**
* Sets the SO_RCVBUF option to the specified value for this
* <tt>DatagramSocket</tt>. The SO_RCVBUF option is used by the the network
* implementation as a hint to size the underlying network I/O buffers. The
* SO_RCVBUF setting may also be used by the network implementation to
* determine the maximum size of the packet that can be received on this
* socket.
* <p>
* Because SO_RCVBUF is a hint, applications that want to verify what size
* the buffers were set to should call {@link #getReceiveBufferSize()}.
* <p>
* Increasing SO_RCVBUF may allow the network implementation to buffer
* multiple packets when packets arrive faster than are being received using
* {@link #receive(DatagramPacket)}.
* <p>
* Note: It is implementation specific if a packet larger than SO_RCVBUF can
* be received.
*
* @param size
* the size to which to set the receive buffer size. This value
* must be greater than 0.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @exception IllegalArgumentException
* if the value is 0 or is negative.
* @see #getReceiveBufferSize()
*/
void setReceiveBufferSize(int size) throws SocketException;
/**
* Get value of the SO_RCVBUF option for this <tt>DatagramSocket</tt>, that
* is the buffer size used by the platform for input on this
* <tt>DatagramSocket</tt>.
*
* @return the value of the SO_RCVBUF option for this
* <tt>DatagramSocket</tt>
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @see #setReceiveBufferSize(int)
*/
int getReceiveBufferSize() throws SocketException;
/**
* Enable/disable the SO_REUSEADDR socket option.
* <p>
* For UDP sockets it may be necessary to bind more than one socket to the
* same socket address. This is typically for the purpose of receiving
* multicast packets (See {@link java.net.MulticastSocket}). The
* <tt>SO_REUSEADDR</tt> socket option allows multiple sockets to be bound
* to the same socket address if the <tt>SO_REUSEADDR</tt> socket option is
* enabled prior to binding the socket using {@link #bind(SocketAddress)}.
* <p>
* Note: This functionality is not supported by all existing platforms, so
* it is implementation specific whether this option will be ignored or not.
* However, if it is not supported then {@link #getReuseAddress()} will
* always return <code>false</code>.
* <p>
* When a <tt>DatagramSocket</tt> is created the initial setting of
* <tt>SO_REUSEADDR</tt> is disabled.
* <p>
* The behaviour when <tt>SO_REUSEADDR</tt> is enabled or disabled after a
* socket is bound (See {@link #isBound()}) is not defined.
*
* @param on
* whether to enable or disable the
* @exception SocketException
* if an error occurs enabling or disabling the
* <tt>SO_RESUEADDR</tt> socket option, or the socket is
* closed.
* @since 1.4
* @see #getReuseAddress()
* @see #bind(SocketAddress)
* @see #isBound()
* @see #isClosed()
*/
void setReuseAddress(boolean on) throws SocketException;
/**
* Tests if SO_REUSEADDR is enabled.
*
* @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @since 1.4
* @see #setReuseAddress(boolean)
*/
boolean getReuseAddress() throws SocketException;
/**
* Enable/disable SO_BROADCAST.
*
* @param on
* whether or not to have broadcast turned on.
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @since 1.4
* @see #getBroadcast()
*/
void setBroadcast(boolean on) throws SocketException;
/**
* Tests if SO_BROADCAST is enabled.
*
* @return a <code>boolean</code> indicating whether or not SO_BROADCAST is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as
* an UDP error.
* @since 1.4
* @see #setBroadcast(boolean)
*/
boolean getBroadcast() throws SocketException;
/**
* Sets traffic class or type-of-service octet in the IP datagram header for
* datagrams sent from this DatagramSocket. As the underlying network
* implementation may ignore this value applications should consider it a
* hint.
*
* <P>
* The tc <B>must</B> be in the range <code> 0 <= tc <=
* 255</code> or an IllegalArgumentException will be thrown.
* <p>
* Notes:
* <p>
* for Internet Protocol v4 the value consists of an octet with precedence
* and TOS fields as detailed in RFC 1349. The TOS field is bitset created
* by bitwise-or'ing values such the following :-
* <p>
* <UL>
* <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
* <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
* <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
* <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
* </UL>
* The last low order bit is always ignored as this corresponds to the MBZ
* (must be zero) bit.
* <p>
* Setting bits in the precedence field may result in a SocketException
* indicating that the operation is not permitted.
* <p>
* for Internet Protocol v6 <code>tc</code> is the value that would be
* placed into the sin6_flowinfo field of the IP header.
*
* @param tc
* an <code>int</code> value for the bitset.
* @throws SocketException
* if there is an error setting the traffic class or
* type-of-service
* @since 1.4
* @see #getTrafficClass
*/
void setTrafficClass(int tc) throws SocketException;
/**
* Gets traffic class or type-of-service in the IP datagram header for
* packets sent from this DatagramSocket.
* <p>
* As the underlying network implementation may ignore the traffic class or
* type-of-service set using {@link #setTrafficClass(int)} this method may
* return a different value than was previously set using the
* {@link #setTrafficClass(int)} method on this DatagramSocket.
*
* @return the traffic class or type-of-service already set
* @throws SocketException
* if there is an error obtaining the traffic class or
* type-of-service value.
* @since 1.4
* @see #setTrafficClass(int)
*/
int getTrafficClass() throws SocketException;
/**
* Closes this datagram socket.
* <p>
* Any thread currently blocked in {@link #receive} upon this socket will
* throw a {@link SocketException}.
*
* <p>
* If this socket has an associated channel then the channel is closed as
* well.
*
* revised 1.4 spec JSR-51
*/
void close();
/**
* Returns whether the socket is closed or not.
*
* @return true if the socket has been closed
* @since 1.4
*/
boolean isClosed();
/**
* Returns the unique {@link DatagramChannel} object
* associated with this datagram socket, if any.
*
* <p>
* A datagram socket will have a channel if, and only if, the channel itself
* was created via the {@link DatagramChannel#open
* DatagramChannel.open} method.
*
* @return the datagram channel associated with this datagram socket, or
* <tt>null</tt> if this socket was not created for a channel
*
* @since 1.4 spec JSR-51
*/
DatagramChannel getChannel();
}

View File

@ -1,375 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.channels.ServerSocketChannel;
/**
* compatibility verification interface
*/
public interface IceServerSocket {
/**
*
* Binds the <code>ServerSocket</code> to a specific address (IP address and
* port number).
* <p>
* If the address is <code>null</code>, then the system will pick up an
* ephemeral port and a valid local address to bind the socket.
* <p>
*
* @param endpoint
* The IP address & port number to bind to.
* @throws IOException
* if the bind operation fails, or if the socket is already
* bound.
* @throws SecurityException
* if a <code>SecurityManager</code> is present and its
* <code>checkListen</code> method doesn't allow the operation.
* @throws IllegalArgumentException
* if endpoint is a SocketAddress subclass not supported by this
* socket
* @since 1.4
*/
void bind(SocketAddress endpoint) throws IOException;
/**
*
* Binds the <code>ServerSocket</code> to a specific address (IP address and
* port number).
* <p>
* If the address is <code>null</code>, then the system will pick up an
* ephemeral port and a valid local address to bind the socket.
* <P>
* The <code>backlog</code> argument must be a positive value greater than
* 0. If the value passed if equal or less than 0, then the default value
* will be assumed.
*
* @param endpoint
* The IP address & port number to bind to.
* @param backlog
* The listen backlog length.
* @throws IOException
* if the bind operation fails, or if the socket is already
* bound.
* @throws SecurityException
* if a <code>SecurityManager</code> is present and its
* <code>checkListen</code> method doesn't allow the operation.
* @throws IllegalArgumentException
* if endpoint is a SocketAddress subclass not supported by this
* socket
* @since 1.4
*/
void bind(SocketAddress endpoint, int backlog) throws IOException;
/**
* Returns the local address of this server socket.
*
* @return the address to which this socket is bound, or <code>null</code>
* if the socket is unbound.
*/
InetAddress getInetAddress();
/**
* Returns the port on which this socket is listening.
*
* @return the port number to which this socket is listening or -1 if the
* socket is not bound yet.
*/
int getLocalPort();
/**
* Returns the address of the endpoint this socket is bound to, or
* <code>null</code> if it is not bound yet.
*
* @return a <code>SocketAddress</code> representing the local endpoint of
* this socket, or <code>null</code> if it is not bound yet.
* @see #getInetAddress()
* @see #getLocalPort()
* @see #bind(SocketAddress)
* @since 1.4
*/
SocketAddress getLocalSocketAddress();
/**
* Listens for a connection to be made to this socket and accepts it. The
* method blocks until a connection is made.
*
* <p>
* A new Socket <code>s</code> is created and, if there is a security
* manager, the security manager's <code>checkAccept</code> method is called
* with <code>s.getInetAddress().getHostAddress()</code> and
* <code>s.getPort()</code> as its arguments to ensure the operation is
* allowed. This could result in a SecurityException.
*
* @exception IOException
* if an I/O error occurs when waiting for a connection.
* @exception SecurityException
* if a security manager exists and its
* <code>checkAccept</code> method doesn't allow the
* operation.
* @exception SocketTimeoutException
* if a timeout was previously set with setSoTimeout and the
* timeout has been reached.
* @exception java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel, the channel is
* in non-blocking mode, and there is no connection ready to
* be accepted
*
* @return the new Socket
* @see SecurityManager#checkAccept revised 1.4 spec JSR-51
*/
Socket accept() throws IOException;
/**
* Closes this socket.
*
* Any thread currently blocked in {@link #accept()} will throw a
* {@link SocketException}.
*
* <p>
* If this socket has an associated channel then the channel is closed as
* well.
*
* @exception IOException
* if an I/O error occurs when closing the socket. revised
* 1.4 spec JSR-51
*/
void close() throws IOException;
/**
* Returns the unique {@link ServerSocketChannel} object
* associated with this socket, if any.
*
* <p>
* A server socket will have a channel if, and only if, the channel itself
* was created via the {@link ServerSocketChannel#open
* ServerSocketChannel.open} method.
*
* @return the server-socket channel associated with this socket, or
* <tt>null</tt> if this socket was not created for a channel
*
* @since 1.4 spec JSR-51
*/
ServerSocketChannel getChannel();
/**
* Returns the binding state of the ServerSocket.
*
* @return true if the ServerSocket succesfuly bound to an address
* @since 1.4
*/
boolean isBound();
/**
* Returns the closed state of the ServerSocket.
*
* @return true if the socket has been closed
* @since 1.4
*/
boolean isClosed();
/**
* Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
* With this option set to a non-zero timeout, a call to accept() for this
* ServerSocket will block for only this amount of time. If the timeout
* expires, a <B>java.net.SocketTimeoutException</B> is raised, though the
* ServerSocket is still valid. The option <B>must</B> be enabled prior to
* entering the blocking operation to have effect. The timeout must be > 0.
* A timeout of zero is interpreted as an infinite timeout.
*
* @param timeout
* the specified timeout, in milliseconds
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since JDK1.1
* @see #getSoTimeout()
*/
void setSoTimeout(int timeout) throws SocketException;
/**
* Retrieve setting for SO_TIMEOUT. 0 returns implies that the option is
* disabled (i.e., timeout of infinity).
*
* @return the SO_TIMEOUT value
* @exception IOException
* if an I/O error occurs
* @since JDK1.1
* @see #setSoTimeout(int)
*/
int getSoTimeout() throws IOException;
/**
* Enable/disable the SO_REUSEADDR socket option.
* <p>
* When a TCP connection is closed the connection may remain in a timeout
* state for a period of time after the connection is closed (typically
* known as the <tt>TIME_WAIT</tt> state or <tt>2MSL</tt> wait state). For
* applications using a well known socket address or port it may not be
* possible to bind a socket to the required <tt>SocketAddress</tt> if there
* is a connection in the timeout state involving the socket address or
* port.
* <p>
* Enabling <tt>SO_REUSEADDR</tt> prior to binding the socket using
* {@link #bind(SocketAddress)} allows the socket to be bound even though a
* previous connection is in a timeout state.
* <p>
* When a <tt>ServerSocket</tt> is created the initial setting of
* <tt>SO_REUSEADDR</tt> is not defined. Applications can use
* {@link #getReuseAddress()} to determine the initial setting of
* <tt>SO_REUSEADDR</tt>.
* <p>
* The behaviour when <tt>SO_REUSEADDR</tt> is enabled or disabled after a
* socket is bound (See {@link #isBound()}) is not defined.
*
* @param on
* whether to enable or disable the socket option
* @exception SocketException
* if an error occurs enabling or disabling the
* <tt>SO_RESUEADDR</tt> socket option, or the socket is
* closed.
* @since 1.4
* @see #getReuseAddress()
* @see #bind(SocketAddress)
* @see #isBound()
* @see #isClosed()
*/
void setReuseAddress(boolean on) throws SocketException;
/**
* Tests if SO_REUSEADDR is enabled.
*
* @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since 1.4
* @see #setReuseAddress(boolean)
*/
boolean getReuseAddress() throws SocketException;
/**
* Returns the implementation address and implementation port of this socket
* as a <code>String</code>.
*
* @return a string representation of this socket.
*/
@Override
String toString();
/**
* Sets a default proposed value for the SO_RCVBUF option for sockets
* accepted from this <tt>ServerSocket</tt>. The value actually set in the
* accepted socket must be determined by calling
* {@link Socket#getReceiveBufferSize()} after the socket is returned by
* {@link #accept()}.
* <p>
* The value of SO_RCVBUF is used both to set the size of the internal
* socket receive buffer, and to set the size of the TCP receive window that
* is advertized to the remote peer.
* <p>
* It is possible to change the value subsequently, by calling
* {@link Socket#setReceiveBufferSize(int)}. However, if the application
* wishes to allow a receive window larger than 64K bytes, as defined by
* RFC1323 then the proposed value must be set in the ServerSocket
* <B>before</B> it is bound to a local address. This implies, that the
* ServerSocket must be created with the no-argument constructor, then
* setReceiveBufferSize() must be called and lastly the ServerSocket is
* bound to an address by calling bind().
* <p>
* Failure to do this will not cause an error, and the buffer size may be
* set to the requested value but the TCP receive window in sockets accepted
* from this ServerSocket will be no larger than 64K bytes.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
*
* @param size
* the size to which to set the receive buffer size. This value
* must be greater than 0.
*
* @exception IllegalArgumentException
* if the value is 0 or is negative.
*
* @since 1.4
* @see #getReceiveBufferSize
*/
void setReceiveBufferSize(int size) throws SocketException;
/**
* Gets the value of the SO_RCVBUF option for this <tt>ServerSocket</tt>,
* that is the proposed buffer size that will be used for Sockets accepted
* from this <tt>ServerSocket</tt>.
*
* <p>
* Note, the value actually set in the accepted socket is determined by
* calling {@link Socket#getReceiveBufferSize()}.
*
* @return the value of the SO_RCVBUF option for this <tt>Socket</tt>.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @see #setReceiveBufferSize(int)
* @since 1.4
*/
int getReceiveBufferSize() throws SocketException;
/**
* Sets performance preferences for this ServerSocket.
*
* <p>
* Sockets use the TCP/IP protocol by default. Some implementations may
* offer alternative protocols which have different performance
* characteristics than TCP/IP. This method allows the application to
* express its own preferences as to how these tradeoffs should be made when
* the implementation chooses from the available protocols.
*
* <p>
* Performance preferences are described by three integers whose values
* indicate the relative importance of short connection time, low latency,
* and high bandwidth. The absolute values of the integers are irrelevant;
* in order to choose a protocol the values are simply compared, with larger
* values indicating stronger preferences. If the application prefers short
* connection time over both low latency and high bandwidth, for example,
* then it could invoke this method with the values <tt>(1, 0, 0)</tt>. If
* the application prefers high bandwidth above low latency, and low latency
* above short connection time, then it could invoke this method with the
* values <tt>(0, 1, 2)</tt>.
*
* <p>
* Invoking this method after this socket has been bound will have no
* effect. This implies that in order to use this capability requires the
* socket to be created with the no-argument constructor.
*
* @param connectionTime
* An <tt>int</tt> expressing the relative importance of a short
* connection time
*
* @param latency
* An <tt>int</tt> expressing the relative importance of low
* latency
*
* @param bandwidth
* An <tt>int</tt> expressing the relative importance of high
* bandwidth
*
* @since 1.5
*/
void setPerformancePreferences(int connectionTime, int latency, int bandwidth);
}

View File

@ -1,791 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.channels.SocketChannel;
/**
* compatibility verification interface
*/
public interface IceSocket {
/**
* Connects this socket to the server.
*
* @param endpoint
* the <code>SocketAddress</code>
* @throws IOException
* if an error occurs during the connection
* @throws java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel, and the channel is
* in non-blocking mode
* @throws IllegalArgumentException
* if endpoint is null or is a SocketAddress subclass not
* supported by this socket
* @since 1.4 spec JSR-51
*/
void connect(SocketAddress endpoint) throws IOException;
/**
* Connects this socket to the server with a specified timeout value. A
* timeout of zero is interpreted as an infinite timeout. The connection
* will then block until established or an error occurs.
*
* @param endpoint
* the <code>SocketAddress</code>
* @param timeout
* the timeout value to be used in milliseconds.
* @throws IOException
* if an error occurs during the connection
* @throws SocketTimeoutException
* if timeout expires before connecting
* @throws java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel, and the channel is
* in non-blocking mode
* @throws IllegalArgumentException
* if endpoint is null or is a SocketAddress subclass not
* supported by this socket
* @since 1.4 spec JSR-51
*/
void connect(SocketAddress endpoint, int timeout) throws IOException;
/**
* Binds the socket to a local address.
* <P>
* If the address is <code>null</code>, then the system will pick up an
* ephemeral port and a valid local address to bind the socket.
*
* @param bindpoint
* the <code>SocketAddress</code> to bind to
* @throws IOException
* if the bind operation fails, or if the socket is already
* bound.
* @throws IllegalArgumentException
* if bindpoint is a SocketAddress subclass not supported by
* this socket
*
* @since 1.4
* @see #isBound
*/
void bind(SocketAddress bindpoint) throws IOException;
/**
* Returns the address to which the socket is connected.
*
* @return the remote IP address to which this socket is connected, or
* <code>null</code> if the socket is not connected.
*/
InetAddress getInetAddress();
/**
* Gets the local address to which the socket is bound.
*
* @return the local address to which the socket is bound or
* <code>InetAddress.anyLocalAddress()</code> if the socket is not
* bound yet.
* @since JDK1.1
*/
InetAddress getLocalAddress();
/**
* Returns the remote port to which this socket is connected.
*
* @return the remote port number to which this socket is connected, or 0 if
* the socket is not connected yet.
*/
int getPort();
/**
* Returns the local port to which this socket is bound.
*
* @return the local port number to which this socket is bound or -1 if the
* socket is not bound yet.
*/
int getLocalPort();
/**
* Returns the address of the endpoint this socket is connected to, or
* <code>null</code> if it is unconnected.
*
* @return a <code>SocketAddress</code> reprensenting the remote endpoint of
* this socket, or <code>null</code> if it is not connected yet.
* @see #getInetAddress()
* @see #getPort()
* @see #connect(SocketAddress, int)
* @see #connect(SocketAddress)
* @since 1.4
*/
SocketAddress getRemoteSocketAddress();
/**
* Returns the address of the endpoint this socket is bound to, or
* <code>null</code> if it is not bound yet.
*
* @return a <code>SocketAddress</code> representing the local endpoint of
* this socket, or <code>null</code> if it is not bound yet.
* @see #getLocalAddress()
* @see #getLocalPort()
* @see #bind(SocketAddress)
* @since 1.4
*/
SocketAddress getLocalSocketAddress();
/**
* Returns the unique {@link SocketChannel SocketChannel}
* object associated with this socket, if any.
*
* <p>
* A socket will have a channel if, and only if, the channel itself was
* created via the {@link SocketChannel#open
* SocketChannel.open} or
* {@link java.nio.channels.ServerSocketChannel#accept
* ServerSocketChannel.accept} methods.
*
* @return the socket channel associated with this socket, or <tt>null</tt>
* if this socket was not created for a channel
*
* @since 1.4 spec JSR-51
*/
SocketChannel getChannel();
/**
* Returns an input stream for this socket.
*
* <p>
* If this socket has an associated channel then the resulting input stream
* delegates all of its operations to the channel. If the channel is in
* non-blocking mode then the input stream's <tt>read</tt> operations will
* throw an {@link java.nio.channels.IllegalBlockingModeException}.
*
* <p>
* Under abnormal conditions the underlying connection may be broken by the
* remote host or the network software (for example a connection reset in
* the case of TCP connections). When a broken connection is detected by the
* network software the following applies to the returned input stream :-
*
* <ul>
*
* <li>
* <p>
* The network software may discard bytes that are buffered by the socket.
* Bytes that aren't discarded by the network software can be read using
* {@link InputStream#read read}.
*
* <li>
* <p>
* If there are no bytes buffered on the socket, or all buffered bytes have
* been consumed by {@link InputStream#read read}, then all
* subsequent calls to {@link InputStream#read read} will throw an
* {@link IOException IOException}.
*
* <li>
* <p>
* If there are no bytes buffered on the socket, and the socket has not been
* closed using {@link #close close}, then
* {@link InputStream#available available} will return
* <code>0</code>.
*
* </ul>
*
* <p>
* Closing the returned {@link InputStream InputStream} will close
* the associated socket.
*
* @return an input stream for reading bytes from this socket.
* @exception IOException
* if an I/O error occurs when creating the input stream, the
* socket is closed, the socket is not connected, or the
* socket input has been shutdown using
* {@link #shutdownInput()}
*
* revised 1.4 spec JSR-51
*/
InputStream getInputStream() throws IOException;
/**
* Returns an output stream for this socket.
*
* <p>
* If this socket has an associated channel then the resulting output stream
* delegates all of its operations to the channel. If the channel is in
* non-blocking mode then the output stream's <tt>write</tt> operations will
* throw an {@link java.nio.channels.IllegalBlockingModeException}.
*
* <p>
* Closing the returned {@link OutputStream OutputStream} will close
* the associated socket.
*
* @return an output stream for writing bytes to this socket.
* @exception IOException
* if an I/O error occurs when creating the output stream or
* if the socket is not connected. revised 1.4 spec JSR-51
*/
OutputStream getOutputStream() throws IOException;
/**
* Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).
*
* @param on
* <code>true</code> to enable TCP_NODELAY, <code>false</code> to
* disable.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
*
* @since JDK1.1
*
* @see #getTcpNoDelay()
*/
void setTcpNoDelay(boolean on) throws SocketException;
/**
* Tests if TCP_NODELAY is enabled.
*
* @return a <code>boolean</code> indicating whether or not TCP_NODELAY is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since JDK1.1
* @see #setTcpNoDelay(boolean)
*/
boolean getTcpNoDelay() throws SocketException;
/**
* Enable/disable SO_LINGER with the specified linger time in seconds. The
* maximum timeout value is platform specific.
*
* The setting only affects socket close.
*
* @param on
* whether or not to linger on.
* @param linger
* how long to linger for, if on is true.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @exception IllegalArgumentException
* if the linger value is negative.
* @since JDK1.1
* @see #getSoLinger()
*/
void setSoLinger(boolean on, int linger) throws SocketException;
/**
* Returns setting for SO_LINGER. -1 returns implies that the option is
* disabled.
*
* The setting only affects socket close.
*
* @return the setting for SO_LINGER.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since JDK1.1
* @see #setSoLinger(boolean, int)
*/
int getSoLinger() throws SocketException;
/**
* Send one byte of urgent data on the socket. The byte to be sent is the
* lowest eight bits of the data parameter. The urgent byte is sent after
* any preceding writes to the socket OutputStream and before any future
* writes to the OutputStream.
*
* @param data
* The byte of data to send
* @exception IOException
* if there is an error sending the data.
* @since 1.4
*/
void sendUrgentData(int data) throws IOException;
/**
* Enable/disable OOBINLINE (receipt of TCP urgent data)
*
* By default, this option is disabled and TCP urgent data received on a
* socket is silently discarded. If the user wishes to receive urgent data,
* then this option must be enabled. When enabled, urgent data is received
* inline with normal data.
* <p>
* Note, only limited support is provided for handling incoming urgent data.
* In particular, no notification of incoming urgent data is provided and
* there is no capability to distinguish between normal data and urgent data
* unless provided by a higher level protocol.
*
* @param on
* <code>true</code> to enable OOBINLINE, <code>false</code> to
* disable.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
*
* @since 1.4
*
* @see #getOOBInline()
*/
void setOOBInline(boolean on) throws SocketException;
/**
* Tests if OOBINLINE is enabled.
*
* @return a <code>boolean</code> indicating whether or not OOBINLINE is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since 1.4
* @see #setOOBInline(boolean)
*/
boolean getOOBInline() throws SocketException;
/**
* Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
* With this option set to a non-zero timeout, a read() call on the
* InputStream associated with this Socket will block for only this amount
* of time. If the timeout expires, a <B>java.net.SocketTimeoutException</B>
* is raised, though the Socket is still valid. The option <B>must</B> be
* enabled prior to entering the blocking operation to have effect. The
* timeout must be > 0. A timeout of zero is interpreted as an infinite
* timeout.
*
* @param timeout
* the specified timeout, in milliseconds.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since JDK 1.1
* @see #getSoTimeout()
*/
void setSoTimeout(int timeout) throws SocketException;
/**
* Returns setting for SO_TIMEOUT. 0 returns implies that the option is
* disabled (i.e., timeout of infinity).
*
* @return the setting for SO_TIMEOUT
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since JDK1.1
* @see #setSoTimeout(int)
*/
int getSoTimeout() throws SocketException;
/**
* Sets the SO_SNDBUF option to the specified value for this <tt>Socket</tt>
* . The SO_SNDBUF option is used by the platform's networking code as a
* hint for the size to set the underlying network I/O buffers.
*
* <p>
* Because SO_SNDBUF is a hint, applications that want to verify what size
* the buffers were set to should call {@link #getSendBufferSize()}.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
*
* @param size
* the size to which to set the send buffer size. This value must
* be greater than 0.
*
* @exception IllegalArgumentException
* if the value is 0 or is negative.
*
* @see #getSendBufferSize()
* @since 1.2
*/
void setSendBufferSize(int size) throws SocketException;
/**
* Get value of the SO_SNDBUF option for this <tt>Socket</tt>, that is the
* buffer size used by the platform for output on this <tt>Socket</tt>.
*
* @return the value of the SO_SNDBUF option for this <tt>Socket</tt>.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
*
* @see #setSendBufferSize(int)
* @since 1.2
*/
int getSendBufferSize() throws SocketException;
/**
* Sets the SO_RCVBUF option to the specified value for this <tt>Socket</tt>
* . The SO_RCVBUF option is used by the platform's networking code as a
* hint for the size to set the underlying network I/O buffers.
*
* <p>
* Increasing the receive buffer size can increase the performance of
* network I/O for high-volume connection, while decreasing it can help
* reduce the backlog of incoming data.
*
* <p>
* Because SO_RCVBUF is a hint, applications that want to verify what size
* the buffers were set to should call {@link #getReceiveBufferSize()}.
*
* <p>
* The value of SO_RCVBUF is also used to set the TCP receive window that is
* advertized to the remote peer. Generally, the window size can be modified
* at any time when a socket is connected. However, if a receive window
* larger than 64K is required then this must be requested <B>before</B> the
* socket is connected to the remote peer. There are two cases to be aware
* of:
* <p>
* <ol>
* <li>For sockets accepted from a ServerSocket, this must be done by
* calling {@link ServerSocket#setReceiveBufferSize(int)} before the
* ServerSocket is bound to a local address.
* <p></li>
* <li>For client sockets, setReceiveBufferSize() must be called before
* connecting the socket to its remote peer.
* <p></li>
* </ol>
*
* @param size
* the size to which to set the receive buffer size. This value
* must be greater than 0.
*
* @exception IllegalArgumentException
* if the value is 0 or is negative.
*
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
*
* @see #getReceiveBufferSize()
* @see ServerSocket#setReceiveBufferSize(int)
* @since 1.2
*/
void setReceiveBufferSize(int size) throws SocketException;
/**
* Gets the value of the SO_RCVBUF option for this <tt>Socket</tt>, that is
* the buffer size used by the platform for input on this <tt>Socket</tt>.
*
* @return the value of the SO_RCVBUF option for this <tt>Socket</tt>.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @see #setReceiveBufferSize(int)
* @since 1.2
*/
int getReceiveBufferSize() throws SocketException;
/**
* Enable/disable SO_KEEPALIVE.
*
* @param on
* whether or not to have socket keep alive turned on.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since 1.3
* @see #getKeepAlive()
*/
void setKeepAlive(boolean on) throws SocketException;
/**
* Tests if SO_KEEPALIVE is enabled.
*
* @return a <code>boolean</code> indicating whether or not SO_KEEPALIVE is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since 1.3
* @see #setKeepAlive(boolean)
*/
boolean getKeepAlive() throws SocketException;
/**
* Sets traffic class or type-of-service octet in the IP header for packets
* sent from this Socket. As the underlying network implementation may
* ignore this value applications should consider it a hint.
*
* <P>
* The tc <B>must</B> be in the range <code> 0 <= tc <=
* 255</code> or an IllegalArgumentException will be thrown.
* <p>
* Notes:
* <p>
* For Internet Protocol v4 the value consists of an octet with precedence
* and TOS fields as detailed in RFC 1349. The TOS field is bitset created
* by bitwise-or'ing values such the following :-
* <p>
* <UL>
* <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
* <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
* <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
* <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
* </UL>
* The last low order bit is always ignored as this corresponds to the MBZ
* (must be zero) bit.
* <p>
* Setting bits in the precedence field may result in a SocketException
* indicating that the operation is not permitted.
* <p>
* As RFC 1122 section 4.2.4.2 indicates, a compliant TCP implementation
* should, but is not required to, let application change the TOS field
* during the lifetime of a connection. So whether the type-of-service field
* can be changed after the TCP connection has been established depends on
* the implementation in the underlying platform. Applications should not
* assume that they can change the TOS field after the connection.
* <p>
* For Internet Protocol v6 <code>tc</code> is the value that would be
* placed into the sin6_flowinfo field of the IP header.
*
* @param tc
* an <code>int</code> value for the bitset.
* @throws SocketException
* if there is an error setting the traffic class or
* type-of-service
* @since 1.4
* @see #getTrafficClass
*/
void setTrafficClass(int tc) throws SocketException;
/**
* Gets traffic class or type-of-service in the IP header for packets sent
* from this Socket
* <p>
* As the underlying network implementation may ignore the traffic class or
* type-of-service set using {@link #setTrafficClass(int)} this method may
* return a different value than was previously set using the
* {@link #setTrafficClass(int)} method on this Socket.
*
* @return the traffic class or type-of-service already set
* @throws SocketException
* if there is an error obtaining the traffic class or
* type-of-service value.
* @since 1.4
* @see #setTrafficClass(int)
*/
int getTrafficClass() throws SocketException;
/**
* Enable/disable the SO_REUSEADDR socket option.
* <p>
* When a TCP connection is closed the connection may remain in a timeout
* state for a period of time after the connection is closed (typically
* known as the <tt>TIME_WAIT</tt> state or <tt>2MSL</tt> wait state). For
* applications using a well known socket address or port it may not be
* possible to bind a socket to the required <tt>SocketAddress</tt> if there
* is a connection in the timeout state involving the socket address or
* port.
* <p>
* Enabling <tt>SO_REUSEADDR</tt> prior to binding the socket using
* {@link #bind(SocketAddress)} allows the socket to be bound even though a
* previous connection is in a timeout state.
* <p>
* When a <tt>Socket</tt> is created the initial setting of
* <tt>SO_REUSEADDR</tt> is disabled.
* <p>
* The behaviour when <tt>SO_REUSEADDR</tt> is enabled or disabled after a
* socket is bound (See {@link #isBound()}) is not defined.
*
* @param on
* whether to enable or disable the socket option
* @exception SocketException
* if an error occurs enabling or disabling the
* <tt>SO_RESUEADDR</tt> socket option, or the socket is
* closed.
* @since 1.4
* @see #getReuseAddress()
* @see #bind(SocketAddress)
* @see #isClosed()
* @see #isBound()
*/
void setReuseAddress(boolean on) throws SocketException;
/**
* Tests if SO_REUSEADDR is enabled.
*
* @return a <code>boolean</code> indicating whether or not SO_REUSEADDR is
* enabled.
* @exception SocketException
* if there is an error in the underlying protocol, such as a
* TCP error.
* @since 1.4
* @see #setReuseAddress(boolean)
*/
boolean getReuseAddress() throws SocketException;
/**
* Closes this socket.
* <p>
* Any thread currently blocked in an I/O operation upon this socket will
* throw a {@link SocketException}.
* <p>
* Once a socket has been closed, it is not available for further networking
* use (i.e. can't be reconnected or rebound). A new socket needs to be
* created.
*
* <p>
* Closing this socket will also close the socket's
* {@link InputStream InputStream} and {@link OutputStream
* OutputStream}.
*
* <p>
* If this socket has an associated channel then the channel is closed as
* well.
*
* @exception IOException
* if an I/O error occurs when closing this socket. revised
* 1.4 spec JSR-51
* @see #isClosed
*/
void close() throws IOException;
/**
* Places the input stream for this socket at "end of stream". Any data sent
* to the input stream side of the socket is acknowledged and then silently
* discarded.
* <p>
* If you read from a socket input stream after invoking shutdownInput() on
* the socket, the stream will return EOF.
*
* @exception IOException
* if an I/O error occurs when shutting down this socket.
*
* @since 1.3
* @see java.net.Socket#shutdownOutput()
* @see java.net.Socket#close()
* @see java.net.Socket#setSoLinger(boolean, int)
* @see #isInputShutdown
*/
void shutdownInput() throws IOException;
/**
* Disables the output stream for this socket. For a TCP socket, any
* previously written data will be sent followed by TCP's normal connection
* termination sequence.
*
* If you write to a socket output stream after invoking shutdownOutput() on
* the socket, the stream will throw an IOException.
*
* @exception IOException
* if an I/O error occurs when shutting down this socket.
*
* @since 1.3
* @see java.net.Socket#shutdownInput()
* @see java.net.Socket#close()
* @see java.net.Socket#setSoLinger(boolean, int)
* @see #isOutputShutdown
*/
void shutdownOutput() throws IOException;
/**
* Converts this socket to a <code>String</code>.
*
* @return a string representation of this socket.
*/
@Override
String toString();
/**
* Returns the connection state of the socket.
*
* @return true if the socket successfuly connected to a server
* @since 1.4
*/
boolean isConnected();
/**
* Returns the binding state of the socket.
*
* @return true if the socket successfuly bound to an address
* @since 1.4
* @see #bind
*/
boolean isBound();
/**
* Returns the closed state of the socket.
*
* @return true if the socket has been closed
* @since 1.4
* @see #close
*/
boolean isClosed();
/**
* Returns whether the read-half of the socket connection is closed.
*
* @return true if the input of the socket has been shutdown
* @since 1.4
* @see #shutdownInput
*/
boolean isInputShutdown();
/**
* Returns whether the write-half of the socket connection is closed.
*
* @return true if the output of the socket has been shutdown
* @since 1.4
* @see #shutdownOutput
*/
boolean isOutputShutdown();
/**
* Sets performance preferences for this socket.
*
* <p>
* Sockets use the TCP/IP protocol by default. Some implementations may
* offer alternative protocols which have different performance
* characteristics than TCP/IP. This method allows the application to
* express its own preferences as to how these tradeoffs should be made when
* the implementation chooses from the available protocols.
*
* <p>
* Performance preferences are described by three integers whose values
* indicate the relative importance of short connection time, low latency,
* and high bandwidth. The absolute values of the integers are irrelevant;
* in order to choose a protocol the values are simply compared, with larger
* values indicating stronger preferences. Negative values represent a lower
* priority than positive values. If the application prefers short
* connection time over both low latency and high bandwidth, for example,
* then it could invoke this method with the values <tt>(1, 0, 0)</tt>. If
* the application prefers high bandwidth above low latency, and low latency
* above short connection time, then it could invoke this method with the
* values <tt>(0, 1, 2)</tt>.
*
* <p>
* Invoking this method after this socket has been connected will have no
* effect.
*
* @param connectionTime
* An <tt>int</tt> expressing the relative importance of a short
* connection time
*
* @param latency
* An <tt>int</tt> expressing the relative importance of low
* latency
*
* @param bandwidth
* An <tt>int</tt> expressing the relative importance of high
* bandwidth
*
* @since 1.5
*/
void setPerformancePreferences(int connectionTime, int latency, int bandwidth);
}

View File

@ -1,146 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.IllegalBlockingModeException;
import com.barchart.udt.ErrorUDT;
import com.barchart.udt.SocketUDT;
/**
* {@link InputStream} implementation for UDT sockets.
*/
public class NetInputStreamUDT extends InputStream {
protected final SocketUDT socketUDT;
/**
*
* @param socketUDT
* The UDT socket.
*/
public NetInputStreamUDT(final SocketUDT socketUDT) {
if (!socketUDT.isBlocking()) {
throw new IllegalBlockingModeException();
}
this.socketUDT = socketUDT;
}
@Override
public int read() throws IOException {
/*
* Here's the contract from the JavaDoc on this for SocketChannel:
*
* A read operation might not fill the buffer, and in fact it might not
* read any bytes at all. Whether or not it does so depends upon the
* nature and state of the channel. A socket channel in non-blocking
* mode, for example, cannot read any more bytes than are immediately
* available from the socket's input buffer; similarly, a file channel
* cannot read any more bytes than remain in the file. It is guaranteed,
* however, that if a channel is in blocking mode and there is at least
* one byte remaining in the buffer then this method will block until at
* least one byte is read.
*
* Long story short: This UDT InputStream should only ever be created
* when the SocketChannel's in blocking mode, and when it's in blocking
* mode the SocketChannel read call below will block just like we need
* it too.
*/
final byte[] data = new byte[1];
final int count = read(data);
assert count == 1;
return data[0] & 0xFF;
}
@Override
public int read(final byte[] bytes) throws IOException {
return read(bytes, 0, bytes.length);
}
@SuppressWarnings("serial")
@Override
public int read(final byte[] bytes, final int off, final int len)
throws IOException {
final int count = socketUDT.receive(bytes, off, off + len);
if (count > 0) {
assert count <= len;
return count;
}
if (count == 0) {
throw new ExceptionReceiveUDT(socketUDT.id(),
ErrorUDT.USER_DEFINED_MESSAGE, "UDT receive time out") {
};
}
throw new IllegalStateException("should not happen");
}
@Override
public void close() throws IOException {
socketUDT.close();
}
@Override
public int available() throws IOException {
// This is the default InputStream return value.
// The java/net/SocketInputStream.java implementation delegates to
// the native implementation, which returns 0 on at least some OSes.
return 0;
}
@Override
public long skip(final long numbytes) throws IOException {
if (numbytes <= 0) {
return 0;
}
long n = numbytes;
final int buflen = (int) Math.min(1024, n);
final byte data[] = new byte[buflen];
while (n > 0) {
final int r = read(data, 0, (int) Math.min(buflen, n));
if (r < 0) {
break;
}
n -= r;
}
return numbytes - n;
}
@Override
public void mark(final int readlimit) {
throw new UnsupportedOperationException("mark not supported");
}
@Override
public void reset() throws IOException {
throw new UnsupportedOperationException("reset not supported");
}
@Override
public boolean markSupported() {
return false;
}
}

View File

@ -1,93 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
* <p/>
* All rights reserved. Licensed under the OSI BSD License.
* <p/>
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import com.barchart.udt.ErrorUDT;
import com.barchart.udt.SocketUDT;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.IllegalBlockingModeException;
/**
* {@link OutputStream} for UDT sockets.
*/
public
class NetOutputStreamUDT extends OutputStream {
protected final SocketUDT socketUDT;
/**
* @param socketUDT The UDT socket.
*/
public
NetOutputStreamUDT(final SocketUDT socketUDT) {
if (!socketUDT.isBlocking()) {
throw new IllegalBlockingModeException();
}
this.socketUDT = socketUDT;
}
@Override
public
void write(final int b) throws IOException {
// Just cast it -- this is the same thing SocketOutputStream does.
final byte[] bytes = {(byte) b};
write(bytes);
}
@Override
public
void write(final byte[] bytes) throws IOException {
write(bytes, 0, bytes.length);
}
@Override
public
void write(final byte[] bytes, final int off, final int len) throws IOException {
int bytesRemaining = len;
while (bytesRemaining > 0) {
final int count = socketUDT.send(bytes, off + len - bytesRemaining, off + len);
if (count > 0) {
bytesRemaining -= count;
continue;
}
if (count == 0) {
throw new ExceptionSendUDT(socketUDT.id(), ErrorUDT.USER_DEFINED_MESSAGE, "UDT send time out");
}
throw new IllegalStateException("Socket has been changed to non-blocking");
}
}
@Override
public
void close() throws IOException {
socketUDT.close();
}
@Override
public
void flush() throws IOException {
socketUDT.flush();
}
}

View File

@ -1,151 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.ServerSocketChannel;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
/**
* {@link ServerSocket} - like wrapper for {@link SocketUDT}
*/
public class NetServerSocketUDT extends ServerSocket implements
IceServerSocket, IceCommon {
protected final SocketUDT socketUDT;
/** uses {@link TypeUDT#STREAM} socket in blocking mode */
public NetServerSocketUDT() throws IOException {
this(new SocketUDT(TypeUDT.STREAM));
this.socketUDT.setBlocking(true);
}
/** uses provided socket keeping blocking mode */
protected NetServerSocketUDT(final SocketUDT socketUDT) throws IOException {
this.socketUDT = socketUDT;
}
@Override
public Socket accept() throws IOException {
final SocketUDT clientUDT = socketUDT.accept();
return new NetSocketUDT(clientUDT);
}
@Override
public void bind(final SocketAddress endpoint) throws IOException {
final int backlog = SocketUDT.DEFAULT_ACCEPT_QUEUE_SIZE;
bind(endpoint, backlog);
}
/**
* NOTE: bind() means listen() for UDT server socket
*/
@Override
public void bind(SocketAddress bindpoint, int backlog) throws IOException {
if (bindpoint == null) {
bindpoint = new InetSocketAddress(0);
}
if (backlog <= 0) {
backlog = SocketUDT.DEFAULT_ACCEPT_QUEUE_SIZE;
}
socketUDT.bind((InetSocketAddress) bindpoint);
socketUDT.listen(backlog);
}
@Override
public void close() throws IOException {
socketUDT.close();
}
@Override
public ServerSocketChannel getChannel() {
throw new UnsupportedOperationException("feature not available");
}
@Override
public InetAddress getInetAddress() {
return socketUDT.getLocalInetAddress();
}
@Override
public int getLocalPort() {
return socketUDT.getLocalInetPort();
}
@Override
public SocketAddress getLocalSocketAddress() {
try {
return socketUDT.getLocalSocketAddress();
} catch (final ExceptionUDT e) {
return null;
}
}
@Override
public int getReceiveBufferSize() throws SocketException {
return socketUDT.getReceiveBufferSize();
}
@Override
public boolean getReuseAddress() throws SocketException {
return socketUDT.getReuseAddress();
}
@Override
public int getSoTimeout() throws IOException {
return socketUDT.getSoTimeout();
}
@Override
public boolean isBound() {
return socketUDT.isBound();
}
@Override
public boolean isClosed() {
return socketUDT.isClosed();
}
@Override
public void setPerformancePreferences(final int connectionTime,
final int latency, final int bandwidth) {
throw new UnsupportedOperationException("feature not available");
}
// NOTE: set both send and receive, since they are inherited on accept()
@Override
public void setReceiveBufferSize(final int size) throws SocketException {
socketUDT.setReceiveBufferSize(size);
socketUDT.setSendBufferSize(size);
}
@Override
public void setReuseAddress(final boolean on) throws SocketException {
socketUDT.setReuseAddress(on);
}
@Override
public void setSoTimeout(final int timeout) throws SocketException {
socketUDT.setSoTimeout(timeout);
}
@Override
public SocketUDT socketUDT() {
return socketUDT;
}
}

View File

@ -1,282 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.anno.ThreadSafe;
/**
* {@link Socket} - like wrapper for {@link SocketUDT}
*/
public class NetSocketUDT extends Socket implements IceSocket, IceCommon {
private final Logger log = LoggerFactory.getLogger(getClass());
@ThreadSafe("this")
protected InputStream inputStream;
@ThreadSafe("this")
protected OutputStream outputStream;
protected final SocketUDT socketUDT;
/** uses {@link TypeUDT#STREAM} socket in blocking mode */
public NetSocketUDT() throws ExceptionUDT {
this(new SocketUDT(TypeUDT.STREAM));
this.socketUDT.setBlocking(true);
}
/** uses provided socket keeping blocking mode */
protected NetSocketUDT(final SocketUDT socketUDT) {
this.socketUDT = socketUDT;
}
@Override
public void bind(SocketAddress bindpoint) throws IOException {
if (bindpoint == null) {
bindpoint = new InetSocketAddress(0);
}
socketUDT.bind((InetSocketAddress) bindpoint);
}
@Override
public synchronized void close() throws IOException {
socketUDT.close();
}
@Override
public void connect(final SocketAddress endpoint) throws IOException {
socketUDT.connect((InetSocketAddress) endpoint);
}
@Override
public void connect(final SocketAddress endpoint, final int timeout)
throws IOException {
throw new UnsupportedOperationException("feature not available");
}
@Override
public SocketChannel getChannel() {
throw new UnsupportedOperationException("feature not available");
}
@Override
public InetAddress getInetAddress() {
return socketUDT.getRemoteInetAddress();
}
@Override
public synchronized InputStream getInputStream() throws IOException {
if (inputStream == null) {
inputStream = new NetInputStreamUDT(socketUDT);
}
return inputStream;
}
@Override
public boolean getKeepAlive() throws SocketException {
// UDT has keep alive automatically under the
// hood which I believe you cannot turn off
return true;
}
@Override
public InetAddress getLocalAddress() {
return socketUDT.getLocalInetAddress();
}
@Override
public int getLocalPort() {
return socketUDT.getLocalInetPort();
}
@Override
public SocketAddress getLocalSocketAddress() {
try {
return socketUDT.getLocalSocketAddress();
} catch (final ExceptionUDT e) {
return null;
}
}
@Override
public boolean getOOBInline() throws SocketException {
return false;
}
@Override
public synchronized OutputStream getOutputStream() throws IOException {
if (outputStream == null) {
outputStream = new NetOutputStreamUDT(socketUDT);
}
return outputStream;
}
@Override
public int getPort() {
return socketUDT.getRemoteInetPort();
}
@Override
public synchronized int getReceiveBufferSize() throws SocketException {
return socketUDT.getReceiveBufferSize();
}
@Override
public SocketAddress getRemoteSocketAddress() {
try {
return socketUDT.getRemoteSocketAddress();
} catch (final ExceptionUDT e) {
return null;
}
}
@Override
public boolean getReuseAddress() throws SocketException {
return socketUDT.getReuseAddress();
}
@Override
public synchronized int getSendBufferSize() throws SocketException {
return socketUDT.getSendBufferSize();
}
@Override
public int getSoLinger() throws SocketException {
return socketUDT.getSoLinger();
}
@Override
public synchronized int getSoTimeout() throws SocketException {
return socketUDT.getSoTimeout();
}
@Override
public boolean getTcpNoDelay() throws SocketException {
return false;
}
@Override
public int getTrafficClass() throws SocketException {
return 0;
}
@Override
public boolean isBound() {
return socketUDT.isBound();
}
@Override
public boolean isClosed() {
return socketUDT.isClosed();
}
@Override
public boolean isConnected() {
return socketUDT.isConnected();
}
@Override
public boolean isInputShutdown() {
return socketUDT.isClosed();
}
@Override
public boolean isOutputShutdown() {
return socketUDT.isClosed();
}
@Override
public void sendUrgentData(final int data) throws IOException {
log.debug("Sending urgent data not supported in Barchart UDT...");
}
@Override
public void setKeepAlive(final boolean on) throws SocketException {
log.debug("Keep alive not supported in Barchart UDT...");
}
@Override
public void setOOBInline(final boolean on) throws SocketException {
log.debug("OOB inline not supported in Barchart UDT...");
}
@Override
public void setPerformancePreferences(final int connectionTime,
final int latency, final int bandwidth) {
}
@Override
public synchronized void setReceiveBufferSize(final int size)
throws SocketException {
socketUDT.setReceiveBufferSize(size);
}
@Override
public void setReuseAddress(final boolean on) throws SocketException {
socketUDT.setReuseAddress(on);
}
@Override
public synchronized void setSendBufferSize(final int size)
throws SocketException {
socketUDT.setSendBufferSize(size);
}
@Override
public void setSoLinger(final boolean on, final int linger)
throws SocketException {
socketUDT.setSoLinger(on, linger);
}
@Override
public synchronized void setSoTimeout(final int timeout)
throws SocketException {
socketUDT.setSoTimeout(timeout);
}
@Override
public void setTcpNoDelay(final boolean on) throws SocketException {
log.debug("TCP no delay not supported in Barchart UDT...");
}
@Override
public void setTrafficClass(final int tc) throws SocketException {
log.debug("Traffic class not supported in Barchart UDT...");
}
@Override
public void shutdownInput() throws IOException {
socketUDT.close();
}
@Override
public void shutdownOutput() throws IOException {
socketUDT.close();
}
@Override
public SocketUDT socketUDT() {
return socketUDT;
}
}

View File

@ -1,55 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
/**
* Interface shared by all {@link KindUDT} kinds.
*/
public interface ChannelUDT extends Channel {
/**
* Was connection request
* {@link SocketChannelUDT#connect(java.net.SocketAddress)} acknowledged by
* {@link SocketChannelUDT#finishConnect()}?
*/
boolean isConnectFinished();
/**
* The kind of UDT channel.
*/
KindUDT kindUDT();
/**
* UDT specific provider which produced this channel.
*/
SelectorProviderUDT providerUDT();
/**
* Underlying UDT socket.
*/
SocketUDT socketUDT();
/**
* The type of UDT socket.
*/
TypeUDT typeUDT();
/**
* Mask of all interest options which are permitted for this channel.
*
* @see SelectionKey
*/
int validOps();
}

View File

@ -1,48 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
/**
* UDT channel role type, or kind.
* <p>
* {@link TypeUDT} means stream (byte oriented) vs datagram (message oriented).
* <p>
* {@link KindUDT} gives distinction between server vs client vs peer.
*/
public enum KindUDT {
/**
* Server mode: listens and accepts connections; generates
* {@link #CONNECTOR} as a result of {@link SocketUDT#accept()}
*
* @see ServerSocketChannelUDT
*/
ACCEPTOR, //
/**
* Client mode: channel which initiates connections to servers; options are
* user-provided.
* <p>
* Server mode: channel which is a result of accept(); inherits options from
* parent {@link #ACCEPTOR}.
*
* @see SocketChannelUDT
*/
CONNECTOR, //
/**
* Rendezvous mode: symmetric peer channel on each side of the connection.
*
* @see RendezvousChannelUDT
*/
RENDEZVOUS, //
}

View File

@ -1,135 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.IllegalBlockingModeException;
/**
* {@link InputStream} implementation for UDT sockets.
*/
public class NioInputStreamUDT extends InputStream {
protected final SocketChannelUDT channel;
/**
* Creates a new input stream for the specified channel.
*
* @param channel
* The UDT socket channel.
*/
protected NioInputStreamUDT(final SocketChannelUDT channel) {
if (channel == null) {
throw new NullPointerException("channel == null");
}
if (!channel.isBlocking()) {
throw new IllegalBlockingModeException();
}
this.channel = channel;
}
@Override
public int read() throws IOException {
/*
* Here's the contract from the JavaDoc on this for SocketChannel:
*
* A read operation might not fill the buffer, and in fact it might not
* read any bytes at all. Whether or not it does so depends upon the
* nature and state of the channel. A socket channel in non-blocking
* mode, for example, cannot read any more bytes than are immediately
* available from the socket's input buffer; similarly, a file channel
* cannot read any more bytes than remain in the file. It is guaranteed,
* however, that if a channel is in blocking mode and there is at least
* one byte remaining in the buffer then this method will block until at
* least one byte is read.
*
* Long story short: This UDT InputStream should only ever be created
* when the SocketChannel's in blocking mode, and when it's in blocking
* mode the SocketChannel read call below will block just like we need
* it too.
*/
final byte[] data = new byte[1];
read(data);
return data[0];
}
@Override
public int read(final byte[] bytes) throws IOException {
return read(bytes, 0, bytes.length);
}
@Override
public int read(final byte[] bytes, final int off, final int len)
throws IOException {
if (len > bytes.length - off) {
throw new IndexOutOfBoundsException("len > bytes.length - off");
}
final ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.position(off);
buffer.limit(off + len);
final int read = channel.read(buffer);
return read;
}
@Override
public long skip(final long n) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocateDirect(32768);
long remaining = n;
while (remaining > 0) {
buffer.limit((int) Math.min(remaining, buffer.capacity()));
final int ret = channel.read(buffer);
if (ret <= 0)
break;
remaining -= ret;
buffer.rewind();
}
return n - remaining;
}
@Override
public int available() throws IOException {
// This is the default InputStream return value.
// The java/net/SocketInputStream.java implementation delegates to
// the native implementation, which returns 0 on at least some OSes.
return 0;
}
@Override
public void close() throws IOException {
channel.close();
}
@Override
public void mark(final int readlimit) {
throw new UnsupportedOperationException("mark not supported");
}
@Override
public void reset() throws IOException {
throw new UnsupportedOperationException("reset not supported");
}
@Override
public boolean markSupported() {
return false;
}
}

View File

@ -1,54 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* {@link OutputStream} for UDT sockets.
*/
public class NioOutputStreamUDT extends OutputStream {
protected final SocketChannelUDT channel;
/**
* Creates a new UDT output stream.
*
* @param channel
* The UDT socket channel.
*/
protected NioOutputStreamUDT(final SocketChannelUDT channel) {
this.channel = channel;
}
@Override
public void write(final byte[] bytes, final int off, final int len)
throws IOException {
channel.write(ByteBuffer.wrap(bytes, off, len));
}
@Override
public void write(final byte[] bytes) throws IOException {
channel.write(ByteBuffer.wrap(bytes));
}
@Override
public void write(final int b) throws IOException {
// Just cast it -- this is the same thing SocketOutputStream does.
final byte[] bytes = { (byte) b };
channel.write(ByteBuffer.wrap(bytes));
}
@Override
public void close() throws IOException {
channel.close();
}
}

View File

@ -1,44 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;
import com.barchart.udt.net.NetServerSocketUDT;
public class NioServerSocketUDT extends NetServerSocketUDT {
protected final ServerSocketChannelUDT channelUDT;
protected NioServerSocketUDT(final ServerSocketChannelUDT channelUDT)
throws IOException {
super(channelUDT.socketUDT());
this.channelUDT = channelUDT;
}
@Override
public Socket accept() throws IOException {
throw new RuntimeException("feature not available");
}
@Override
public void bind(final SocketAddress endpoint) throws IOException {
final SelectorProviderUDT provider = //
(SelectorProviderUDT) channelUDT.provider();
final int backlog = provider.getAcceptQueueSize();
bind(endpoint, backlog);
}
@Override
public ServerSocketChannelUDT getChannel() {
return channelUDT;
}
}

View File

@ -1,48 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.net.NetSocketUDT;
public class NioSocketUDT extends NetSocketUDT {
protected final SocketChannelUDT channelUDT;
protected NioSocketUDT(final SocketChannelUDT channelUDT)
throws ExceptionUDT {
super(channelUDT.socketUDT());
this.channelUDT = channelUDT;
}
@Override
public SocketChannelUDT getChannel() {
return channelUDT;
}
@Override
public synchronized InputStream getInputStream() throws IOException {
if (inputStream == null) {
inputStream = new NioInputStreamUDT(channelUDT);
}
return inputStream;
}
@Override
public synchronized OutputStream getOutputStream() throws IOException {
if (outputStream == null) {
outputStream = new NioOutputStreamUDT(channelUDT);
}
return outputStream;
}
}

View File

@ -1,46 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.nio.channels.SocketChannel;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
/**
* {@link SocketChannel}-like wrapper for {@link SocketUDT}, can be either
* stream or message oriented, depending on {@link TypeUDT}
* <p>
* See <a href="http://udt.sourceforge.net/udt4/doc/t-firewall.htm">Firewall
* Traversing with UDT</a>
*/
public class RendezvousChannelUDT extends SocketChannelUDT implements
ChannelUDT {
/**
* Ensure rendezvous mode.
*/
protected RendezvousChannelUDT( //
final SelectorProviderUDT provider, //
final SocketUDT socketUDT //
) throws ExceptionUDT {
super(provider, socketUDT);
socketUDT.setReuseAddress(true);
socketUDT.setRendezvous(true);
}
@Override
public KindUDT kindUDT() {
return KindUDT.RENDEZVOUS;
}
}

View File

@ -1,506 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.EpollUDT;
import com.barchart.udt.EpollUDT.Opt;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.OptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.StatusUDT;
/**
* UDT selection key implementation.
*/
public class SelectionKeyUDT extends SelectionKey implements
Comparable<SelectionKeyUDT> {
/**
* JDK interest to Epoll READ mapping.
*/
protected static final int HAS_READ = OP_ACCEPT | OP_READ;
/**
* JDK interest to Epoll WRITE mapping.
*/
protected static final int HAS_WRITE = OP_CONNECT | OP_WRITE;
protected static final Logger log = LoggerFactory
.getLogger(SelectionKeyUDT.class);
/**
* Convert select options : from jdk into epoll.
*/
protected static Opt from(final int interestOps) {
final boolean hasRead = (interestOps & HAS_READ) != 0;
final boolean hasWrite = (interestOps & HAS_WRITE) != 0;
if (hasRead && hasWrite) {
return Opt.ALL;
}
if (hasRead) {
return Opt.ERROR_READ;
}
if (hasWrite) {
return Opt.ERROR_WRITE;
}
return Opt.ERROR;
}
/**
* Render select options.
*/
public static final String toStringOps(final int selectOps) {
final char A = (OP_ACCEPT & selectOps) != 0 ? 'A' : '-';
final char C = (OP_CONNECT & selectOps) != 0 ? 'C' : '-';
final char R = (OP_READ & selectOps) != 0 ? 'R' : '-';
final char W = (OP_WRITE & selectOps) != 0 ? 'W' : '-';
return String.format("%c%c%c%c", A, C, R, W);
}
/**
* Channel bound to the key.
*/
private final ChannelUDT channelUDT;
/**
* Requested interest in epoll format.
*/
private volatile Opt epollOpt;
/**
* Requested interest in JDK format.
*/
private volatile int interestOps;
/**
* Key validity state. Key is valid when created, and invalid when canceled.
*/
private volatile boolean isValid;
/**
* Reported ready interest.
*/
private volatile int readyOps;
/**
* Correlation index for {@link #doRead(int)} vs {@link #doWrite(int)}
*/
private volatile int resultIndex;
/**
* Selector bound to the key.
*/
private final SelectorUDT selectorUDT;
protected SelectionKeyUDT( //
final SelectorUDT selectorUDT, //
final ChannelUDT channelUDT, //
final Object attachment //
) {
super.attach(attachment);
this.selectorUDT = selectorUDT;
this.channelUDT = channelUDT;
makeValid(true);
}
/**
* Ensure key is NOT canceled.
*/
protected void assertValidKey() throws CancelledKeyException {
if (isValid()) {
return;
}
throw new CancelledKeyException();
}
/**
* Ensure only permitted interest mask bits are present.
*/
protected void assertValidOps(final int interestOps) {
if ((interestOps & ~(channel().validOps())) != 0) {
throw new IllegalArgumentException("invalid interestOps="
+ interestOps);
}
}
@Override
public void cancel() {
if (isValid()) {
selector().cancel(this);
}
}
@Override
public SelectableChannel channel() {
return (SelectableChannel) channelUDT;
}
/**
* Underlying UDT channel.
*/
protected ChannelUDT channelUDT() {
return channelUDT;
}
@Override
public int compareTo(final SelectionKeyUDT that) {
final int thisId = this.socketId();
final int thatId = that.socketId();
if (thisId > thatId) {
return +1;
}
if (thisId < thatId) {
return -1;
}
return 0;
}
/**
* Apply READ readiness according to {@link KindUDT} channel role.
* <p>
* Note: {@link #doRead(int)} is invoked before {@link #doWrite(int)}
* <p>
* Sockets with exceptions are returned to both read and write sets.
*
* @return Should report ready-state change?
*/
protected boolean doRead(final int resultIndex) {
int readyOps = 0;
final int interestOps = this.interestOps;
/** Store read/write verifier. */
this.resultIndex = resultIndex;
try {
/** Check error report. */
if (!epollOpt.hasRead()) {
if (isSocketBroken()) {
readyOps = channel().validOps();
return true;
} else {
logError("Unexpected error report.");
return false;
}
}
switch (kindUDT()) {
case ACCEPTOR:
if ((interestOps & OP_ACCEPT) != 0) {
readyOps = OP_ACCEPT;
return true;
} else {
logError("Ready to ACCEPT while not interested.");
return false;
}
case CONNECTOR:
case RENDEZVOUS:
if ((interestOps & OP_READ) != 0) {
readyOps = OP_READ;
return true;
} else {
logError("Ready to READ while not interested.");
return false;
}
default:
logError("Wrong kind.");
return false;
}
} finally {
this.readyOps = readyOps;
}
}
/**
* Apply WRITE readiness according to {@link KindUDT} channel role.
* <p>
* Note: {@link #doRead(int)} is invoked before {@link #doWrite(int)}
* <p>
* Sockets with exceptions are returned to both read and write sets.
*
* @return Should report ready-state change?
*/
protected boolean doWrite(final int resultIndex) {
int readyOps = 0;
final int interestOps = this.interestOps;
/** Verify read/write relationship. */
final boolean hadReadBeforeWrite = this.resultIndex == resultIndex;
try {
/** Check error report. */
if (!epollOpt.hasWrite()) {
if (isSocketBroken()) {
readyOps = channel().validOps();
return true;
} else {
logError("Unexpected error report.");
return false;
}
}
switch (kindUDT()) {
case ACCEPTOR:
logError("Ready to WRITE for acceptor.");
return false;
case CONNECTOR:
case RENDEZVOUS:
if (channelUDT().isConnectFinished()) {
if ((interestOps & OP_WRITE) != 0) {
readyOps = OP_WRITE;
return true;
} else {
logError("Ready to WRITE when not insterested.");
return false;
}
} else {
if ((interestOps & OP_CONNECT) != 0) {
readyOps = OP_CONNECT;
return true;
} else {
logError("Ready to CONNECT when not interested.");
return false;
}
}
default:
logError("Wrong kind.");
return false;
}
} finally {
if (hadReadBeforeWrite) {
this.readyOps |= readyOps;
} else {
this.readyOps = readyOps;
}
}
}
/**
* Requested interest in epoll format.
*/
protected Opt epollOpt() {
return epollOpt;
}
/**
* Epoll bound to this key.
*/
protected EpollUDT epollUDT() {
return selector().epollUDT();
}
/**
* Key equality based on socket-id.
*/
@Override
public boolean equals(final Object otherKey) {
if (otherKey instanceof SelectionKeyUDT) {
final SelectionKeyUDT other = (SelectionKeyUDT) otherKey;
return other.socketId() == this.socketId();
}
return false;
}
/**
* Check socket error condition.
*/
boolean hasError() throws ExceptionUDT {
final int code = socketUDT().getOption(OptionUDT.Epoll_Event_Mask);
return Opt.from(code).hasError();
}
/**
* Key hach code based on socket-id.
*/
@Override
public int hashCode() {
return socketId();
}
@Override
public int interestOps() {
return interestOps;
}
@Override
public SelectionKey interestOps(final int interestOps) {
assertValidKey();
assertValidOps(interestOps);
try {
final Opt epollNew = from(interestOps);
if (epollNew != epollOpt) {
if (Opt.ERROR == epollNew) {
epollUDT().remove(socketUDT());
} else {
epollUDT().remove(socketUDT());
epollUDT().add(socketUDT(), epollNew);
}
epollOpt = epollNew;
}
} catch (final Exception e) {
log.error("epoll udpate failure", e);
} finally {
this.interestOps = interestOps;
}
return this;
}
/**
* Check socket termination status.
*
* @return true if status is {@link StatusUDT#BROKEN} or worse
*/
protected boolean isSocketBroken() {
switch (socketUDT().status()) {
case INIT:
case OPENED:
case LISTENING:
case CONNECTING:
case CONNECTED:
return false;
case BROKEN:
case CLOSING:
case CLOSED:
case NONEXIST:
return true;
default:
logError("Unknown socket status.");
return true;
}
}
@Override
public boolean isValid() {
return isValid;
}
/**
* Channel role.
*/
protected KindUDT kindUDT() {
return channelUDT.kindUDT();
}
/**
* Key processing logic error logger.
*/
protected void logError(final String comment) {
final String message = "logic error : \n\t" + this;
log.warn(message, new Exception("" + comment));
}
/**
* Change socket registration with epoll, and change key validity status.
*/
protected void makeValid(final boolean isValid) {
try {
if (isValid) {
epollOpt = Opt.ERROR;
epollUDT().add(socketUDT(), epollOpt);
} else {
epollUDT().remove(socketUDT());
}
} catch (final Throwable e) {
log.error("Epoll failure.", e);
} finally {
this.isValid = isValid;
}
}
@Override
public int readyOps() {
return readyOps;
}
protected void readyOps(final int ops) {
readyOps = ops;
}
@Override
public SelectorUDT selector() {
return selectorUDT;
}
/**
* Id of a socket bound to this key.
*/
protected int socketId() {
return socketUDT().id();
}
/**
* Socket bound to this key.
*/
protected SocketUDT socketUDT() {
return channelUDT.socketUDT();
}
@Override
public String toString() {
return String
.format("[id: 0x%08x] poll=%s ready=%s inter=%s %s %s %s bind=%s:%s peer=%s:%s", //
socketUDT().id(), //
epollOpt, //
toStringOps(readyOps), //
toStringOps(interestOps), //
channelUDT.typeUDT(), //
channelUDT.kindUDT(), //
socketUDT().status(), //
socketUDT().getLocalInetAddress(), //
socketUDT().getLocalInetPort(), //
socketUDT().getRemoteInetAddress(), //
socketUDT().getRemoteInetPort() //
);
}
}

View File

@ -1,137 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Pipe;
import java.nio.channels.spi.SelectorProvider;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
/**
* selection provider for UDT
* <p>
* note: you must use the same system-wide provider instance for the same
* {@link TypeUDT} of UDT channels and UDT selectors;
*/
public class SelectorProviderUDT extends SelectorProvider {
/**
* system-wide provider instance, for {@link TypeUDT#DATAGRAM} UDT sockets
*/
public static final SelectorProviderUDT DATAGRAM = new SelectorProviderUDT(TypeUDT.DATAGRAM);
/**
* system-wide provider instance, for {@link TypeUDT#STREAM} UDT sockets
*/
public static final SelectorProviderUDT STREAM = new SelectorProviderUDT(TypeUDT.STREAM);
public static SelectorProviderUDT from(final TypeUDT type) {
switch (type) {
case DATAGRAM:
return DATAGRAM;
case STREAM:
return STREAM;
default:
throw new IllegalStateException("wrong type=" + type);
}
}
private volatile int acceptQueueSize = SocketUDT.DEFAULT_ACCEPT_QUEUE_SIZE;
private volatile int maxSelectorSize = SocketUDT.DEFAULT_MAX_SELECTOR_SIZE;
private final TypeUDT type;
/**
* {@link TypeUDT} of UDT sockets generated by this provider
*/
public final TypeUDT type() {
return type;
}
protected SelectorProviderUDT(final TypeUDT type) {
this.type = type;
}
public int getAcceptQueueSize() {
return acceptQueueSize;
}
public int getMaxSelectorSize() {
return maxSelectorSize;
}
/**
* Not supported.
*/
@Override
public DatagramChannel openDatagramChannel() throws IOException {
throw new UnsupportedOperationException("feature not available");
}
/**
* Not supported.
*/
@Override
public Pipe openPipe() throws IOException {
throw new UnsupportedOperationException("feature not available");
}
/**
* Open UDT {@link KindUDT#RENDEZVOUS} socket channel.
*
* @see RendezvousChannelUDT
*/
public RendezvousChannelUDT openRendezvousChannel() throws IOException {
final SocketUDT socketUDT = new SocketUDT(type);
return new RendezvousChannelUDT(this, socketUDT);
}
/**
* Open UDT specific selector.
*
* @see SelectorUDT
*/
@Override
public SelectorUDT openSelector() throws IOException {
return new SelectorUDT(this, maxSelectorSize);
}
/**
* Open UDT {@link KindUDT#ACCEPTOR} socket channel.
*
* @see ServerSocketChannelUDT
*/
@Override
public ServerSocketChannelUDT openServerSocketChannel() throws IOException {
final SocketUDT serverSocketUDT = new SocketUDT(type);
return new ServerSocketChannelUDT(this, serverSocketUDT);
}
/**
* Open UDT {@link KindUDT#CONNECTOR} socket channel.
*
* @see SocketChannelUDT
*/
@Override
public SocketChannelUDT openSocketChannel() throws IOException {
final SocketUDT socketUDT = new SocketUDT(type);
return new SocketChannelUDT(this, socketUDT);
}
public void setAcceptQueueSize(final int queueSize) {
acceptQueueSize = queueSize;
}
public void setMaxSelectorSize(final int selectorSize) {
maxSelectorSize = selectorSize;
}
}

View File

@ -1,489 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import static com.barchart.udt.SocketUDT.*;
import java.io.IOException;
import java.nio.IntBuffer;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.IllegalSelectorException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.AbstractSelector;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.EpollUDT;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.util.HelpUDT;
/**
* selector
* <p>
* design guidelines:
* <p>
* 1) follow general contracts of jdk 6 nio; see <a href=
* "https://github.com/barchart/barchart-udt/tree/master/barchart-udt-reference-jdk6"
* >barchart-udt-reference-jdk6</a>
* <p>
* 2) adapt to how netty is doing select; see <a href=
* "https://github.com/netty/netty/blob/master/transport/src/main/java/io/netty/channel/socket/nio/NioEventLoop.java"
* >NioEventLoop</a>
* <p>
* note: you must use {@link SelectorProviderUDT#openSelector()} to obtain
* instance of this class; do not use JDK
* {@link Selector#open()}
*/
public class SelectorUDT extends AbstractSelector {
protected static final Logger log = LoggerFactory
.getLogger(SelectorUDT.class);
/**
* use this call to instantiate a selector for UDT
*/
protected static Selector open(final TypeUDT type) throws IOException {
final SelectorProviderUDT provider;
switch (type) {
case DATAGRAM:
provider = SelectorProviderUDT.DATAGRAM;
break;
case STREAM:
provider = SelectorProviderUDT.STREAM;
break;
default:
log.error("unsupported type={}", type);
throw new IOException("unsupported type");
}
return provider.openSelector();
}
private final EpollUDT epollUDT = new EpollUDT();
/**
*/
public final int maximimSelectorSize;
/**
* list of epoll sockets with read interest
*/
private final IntBuffer readBuffer;
/**
* [ socket-id : selection-key ]
*/
private final ConcurrentMap<Integer, SelectionKeyUDT> //
registeredKeyMap = new ConcurrentHashMap<Integer, SelectionKeyUDT>();
/**
* public view : immutable
*/
private final Set<? extends SelectionKey> //
registeredKeySet = HelpUDT.unmodifiableSet(registeredKeyMap.values());
/**
* tracks correlation read with write for the same key
*/
private volatile int resultIndex;
/**
* set of keys with data ready for an operation
*/
private final ConcurrentMap<SelectionKeyUDT, SelectionKeyUDT> //
selectedKeyMap = new ConcurrentHashMap<SelectionKeyUDT, SelectionKeyUDT>();
/**
* public view : removal allowed, but not addition
*/
private final Set<? extends SelectionKey> //
selectedKeySet = HelpUDT.ungrowableSet(selectedKeyMap.keySet());
/** select is exclusive */
private final Lock selectLock = new ReentrantLock();
/** reported epoll socket list sizes */
private final IntBuffer sizeBuffer;
/**
* Canceled keys.
*/
private final ConcurrentMap<SelectionKeyUDT, SelectionKeyUDT> //
terminatedKeyMap = new ConcurrentHashMap<SelectionKeyUDT, SelectionKeyUDT>();
/** guarded by {@link #doSelectLocked} */
private volatile int wakeupBaseCount;
private volatile int wakeupStepCount;
/** list of epoll sockets with write interest */
private final IntBuffer writeBuffer;
protected SelectorUDT( //
final SelectorProvider provider, //
final int maximumSelectorSize //
) throws ExceptionUDT {
super(provider);
this.maximimSelectorSize = maximumSelectorSize;
readBuffer = HelpUDT.newDirectIntBufer(maximumSelectorSize);
writeBuffer = HelpUDT.newDirectIntBufer(maximumSelectorSize);
sizeBuffer = HelpUDT.newDirectIntBufer(UDT_SIZE_COUNT);
}
/**
* Enqueue cancel request.
*/
protected void cancel(final SelectionKeyUDT keyUDT) {
terminatedKeyMap.putIfAbsent(keyUDT, keyUDT);
}
/**
* Process pending cancel requests.
*/
protected void doCancel() {
if (terminatedKeyMap.isEmpty()) {
return;
}
final Iterator<SelectionKeyUDT> iterator = terminatedKeyMap.values()
.iterator();
while (iterator.hasNext()) {
final SelectionKeyUDT keyUDT = iterator.next();
iterator.remove();
if (keyUDT.isValid()) {
keyUDT.makeValid(false);
registeredKeyMap.remove(keyUDT.socketId());
}
}
}
/**
* @param millisTimeout
* <0 : invinite; =0 : immediate; >0 : finite;
*/
protected int doEpollEnter(final long millisTimeout) throws IOException {
if (!isOpen()) {
log.error("slector is closed");
throw new ClosedSelectorException();
}
try {
selectLock.lock();
return doEpollExclusive(millisTimeout);
} finally {
selectLock.unlock();
}
}
/**
* @param millisTimeout
*
* <0 : invinite;
*
* =0 : immediate;
*
* >0 : finite;
* @return
*
* <0 : should not happen
*
* =0 : means nothing was selected/timeout
*
* >0 : number of selected keys
*/
protected int doEpollExclusive(final long millisTimeout) throws IOException {
try {
/** java.nio.Selector contract for wakeup() */
// begin();
/** pre select */
doCancel();
/** select proper */
doEpollSelect(millisTimeout);
/** post select */
doResults();
} finally {
/** java.nio.Selector contract for wakeup() */
// end();
}
return selectedKeyMap.size();
}
/**
* @param millisTimeout
*
* <0 : infinite
*
* =0 : immediate
*
* >0 : finite
*/
protected int doEpollSelect(long millisTimeout) throws ExceptionUDT {
wakeupMarkBase();
int readyCount = 0;
if (millisTimeout < 0) {
/** infinite: do select in slices; check for wakeup; */
do {
readyCount = doEpollSelectUDT(DEFAULT_MIN_SELECTOR_TIMEOUT);
if (readyCount > 0 || wakeupIsPending()) {
break;
}
} while (true);
} else if (millisTimeout > 0) {
/** finite: do select in slices; check for wakeup; count down */
do {
readyCount = doEpollSelectUDT(DEFAULT_MIN_SELECTOR_TIMEOUT);
if (readyCount > 0 || wakeupIsPending()) {
break;
}
millisTimeout -= DEFAULT_MIN_SELECTOR_TIMEOUT;
} while (millisTimeout > 0);
} else {
/** immediate */
readyCount = doEpollSelectUDT(0);
}
return readyCount;
}
protected int doEpollSelectUDT(final long timeout) throws ExceptionUDT {
return SocketUDT.selectEpoll(//
epollUDT.id(), //
readBuffer, //
writeBuffer, //
sizeBuffer, //
timeout //
);
}
protected void doResults() {
final int resultIndex = this.resultIndex++;
doResultsRead(resultIndex);
doResultsWrite(resultIndex);
}
protected void doResultsRead(final int resultIndex) {
final int readSize = sizeBuffer.get(UDT_READ_INDEX);
for (int index = 0; index < readSize; index++) {
final int socketId = readBuffer.get(index);
final SelectionKeyUDT keyUDT = registeredKeyMap.get(socketId);
/**
* Epoll will report closed socket once in both read and write sets.
* But selector consumer may cancel the key before close.
*/
if (keyUDT == null) {
logSocketId("missing from read ", socketId);
continue;
}
if (keyUDT.doRead(resultIndex)) {
selectedKeyMap.putIfAbsent(keyUDT, keyUDT);
}
}
}
protected void doResultsWrite(final int resultIndex) {
final int writeSize = sizeBuffer.get(UDT_WRITE_INDEX);
for (int index = 0; index < writeSize; index++) {
final int socketId = writeBuffer.get(index);
final SelectionKeyUDT keyUDT = registeredKeyMap.get(socketId);
/**
* Epoll will report closed socket once in both read and write sets.
* But selector consumer may cancel the key before close.
*/
if (keyUDT == null) {
logSocketId("missing from write", socketId);
continue;
}
if (keyUDT.doWrite(resultIndex)) {
selectedKeyMap.putIfAbsent(keyUDT, keyUDT);
}
}
}
protected EpollUDT epollUDT() {
return epollUDT;
}
@Override
protected void implCloseSelector() throws IOException {
wakeup();
try {
selectLock.lock();
for (final SelectionKeyUDT keyUDT : registeredKeyMap.values()) {
cancel(keyUDT);
}
} finally {
selectLock.unlock();
}
doCancel();
}
@SuppressWarnings("unchecked")
@Override
public Set<SelectionKey> keys() {
if (!isOpen()) {
throw new ClosedSelectorException();
}
return (Set<SelectionKey>) registeredKeySet;
}
protected void logSocketId(final String title, final int socketId) {
if (log.isDebugEnabled()) {
log.debug("{} {}", title, String.format("[id: 0x%08x]", socketId));
}
}
/**
*/
@Override
protected SelectionKey register( //
final AbstractSelectableChannel channel, //
final int interestOps, //
final Object attachment //
) {
if (registeredKeyMap.size() >= maximimSelectorSize) {
log.error("reached maximimSelectorSize");
throw new IllegalSelectorException();
}
if (!(channel instanceof ChannelUDT)) {
log.error("!(channel instanceof ChannelUDT)");
throw new IllegalSelectorException();
}
final ChannelUDT channelUDT = (ChannelUDT) channel;
final Integer socketId = channelUDT.socketUDT().id();
SelectionKeyUDT keyUDT = registeredKeyMap.get(socketId);
if (keyUDT == null) {
keyUDT = new SelectionKeyUDT(this, channelUDT, attachment);
registeredKeyMap.putIfAbsent(socketId, keyUDT);
keyUDT = registeredKeyMap.get(socketId);
}
keyUDT.interestOps(interestOps);
return keyUDT;
}
@Override
public int select() throws IOException {
return select(0);
}
@Override
public int select(final long timeout) throws IOException {
if (timeout < 0) {
throw new IllegalArgumentException("negative timeout");
} else if (timeout > 0) {
return doEpollEnter(timeout);
} else {
return doEpollEnter(SocketUDT.TIMEOUT_INFINITE);
}
}
@SuppressWarnings("unchecked")
@Override
public Set<SelectionKey> selectedKeys() {
if (!isOpen()) {
throw new ClosedSelectorException();
}
return (Set<SelectionKey>) selectedKeySet;
}
@Override
public int selectNow() throws IOException {
return doEpollEnter(SocketUDT.TIMEOUT_NONE);
}
@Override
public Selector wakeup() {
wakeupStepCount++;
return this;
}
protected boolean wakeupIsPending() {
return wakeupBaseCount != wakeupStepCount;
}
protected void wakeupMarkBase() {
wakeupBaseCount = wakeupStepCount;
}
}

View File

@ -1,132 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.nio.channels.ServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.anno.ThreadSafe;
/**
* {@link ServerSocketChannel}-like wrapper for {@link SocketUDT} can be either
* stream or message oriented, depending on {@link TypeUDT}
* <p>
* you must use {@link SelectorProviderUDT#openServerSocketChannel()} to obtain
* instance of this class; do not use JDK
* {@link ServerSocketChannel#open()};
* <p>
* example:
*
* <pre>
* SelectorProvider provider = SelectorProviderUDT.DATAGRAM;
* ServerSocketChannel acceptChannel = provider.openServerSocketChannel();
* ServerSocket acceptSocket = acceptChannel.socket();
* InetSocketAddress acceptAddress = new InetSocketAddress(&quot;localhost&quot;, 12345);
* acceptorSocket.bind(acceptAddress);
* assert acceptSocket.isBound();
* SocketChannel connectChannel = acceptChannel.accept();
* assert connectChannel.isConnected();
* </pre>
*/
public class ServerSocketChannelUDT extends ServerSocketChannel implements ChannelUDT {
protected static final Logger log = LoggerFactory.getLogger(ServerSocketChannelUDT.class);
@ThreadSafe("this")
protected NioServerSocketUDT socketAdapter;
protected final SocketUDT socketUDT;
protected ServerSocketChannelUDT(final SelectorProviderUDT provider, final SocketUDT socketUDT) {
super(provider);
this.socketUDT = socketUDT;
}
@Override
public SocketChannelUDT accept() throws IOException {
try {
begin();
final SocketUDT clientUDT = socketUDT.accept();
if (clientUDT == null) {
return null;
} else {
return new SocketChannelUDT( //
providerUDT(), //
clientUDT, //
clientUDT.isConnected() //
);
}
} finally {
end(true);
}
}
@Override
protected void implCloseSelectableChannel() throws IOException {
socketUDT.close();
}
@Override
protected void implConfigureBlocking(final boolean block) throws IOException {
socketUDT.setBlocking(block);
}
@Override
public boolean isConnectFinished() {
return true;
}
@Override
public KindUDT kindUDT() {
return KindUDT.ACCEPTOR;
}
@Override
public SelectorProviderUDT providerUDT() {
return (SelectorProviderUDT) super.provider();
}
@Override
public synchronized NioServerSocketUDT socket() {
if (socketAdapter == null) {
try {
socketAdapter = new NioServerSocketUDT(this);
} catch (final Exception e) {
log.error("failed to make socket", e);
return null;
}
}
return socketAdapter;
}
@Override
public SocketUDT socketUDT() {
return socketUDT;
}
@Override
public String toString() {
return socketUDT.toString();
}
@Override
public TypeUDT typeUDT() {
return providerUDT().type();
}
}

View File

@ -1,506 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ConnectionPendingException;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnresolvedAddressException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.ExceptionUDT;
import com.barchart.udt.SocketUDT;
import com.barchart.udt.TypeUDT;
import com.barchart.udt.anno.ThreadSafe;
/**
* {@link SocketChannel}-like wrapper for {@link SocketUDT}, can be either
* stream or message oriented, depending on {@link TypeUDT}
* <p>
* The UDT socket that this SocketChannel wraps will be switched to blocking
* mode since this is the default for all SocketChannels on construction. If you
* require non-blocking functionality, you will need to call configureBlocking
* on the constructed SocketChannel class.
* <p>
* you must use {@link SelectorProviderUDT#openSocketChannel()} to obtain
* instance of this class; do not use JDK
* {@link SocketChannel#open()};
* <p>
* example:
*
* <pre>
* SelectorProvider provider = SelectorProviderUDT.DATAGRAM;
* SocketChannel clientChannel = provider.openSocketChannel();
* clientChannel.configureBlocking(true);
* Socket clientSocket = clientChannel.socket();
* InetSocketAddress clientAddress = new InetSocketAddress(&quot;localhost&quot;, 10000);
* clientSocket.bind(clientAddress);
* assert clientSocket.isBound();
* InetSocketAddress serverAddress = new InetSocketAddress(&quot;localhost&quot;, 12345);
* clientChannel.connect(serverAddress);
* assert clientSocket.isConnected();
* </pre>
*/
public class SocketChannelUDT extends SocketChannel implements ChannelUDT {
protected static final Logger log = LoggerFactory.getLogger(SocketChannelUDT.class);
protected final Object connectLock = new Object();
/**
* local volatile variable, which mirrors super.blocking, to avoid the cost
* of synchronized call inside isBlocking()
*/
protected volatile boolean isBlockingMode = isBlocking();
protected volatile boolean isConnectFinished;
protected volatile boolean isConnectionPending;
@ThreadSafe("this")
protected NioSocketUDT socketAdapter;
protected final SocketUDT socketUDT;
private InetSocketAddress remoteSocket;
protected SocketChannelUDT(final SelectorProviderUDT provider, final SocketUDT socketUDT) throws ExceptionUDT {
super(provider);
this.socketUDT = socketUDT;
this.socketUDT.setBlocking(true);
}
protected SocketChannelUDT(final SelectorProviderUDT provider, final SocketUDT socketUDT, final boolean isConnected) throws ExceptionUDT {
this(provider, socketUDT);
if (isConnected) {
isConnectFinished = true;
isConnectionPending = false;
} else {
isConnectFinished = false;
isConnectionPending = true;
}
}
@Override
public boolean connect(final SocketAddress remote) throws IOException {
if (!isOpen()) {
throw new ClosedChannelException();
}
if (isConnected()) {
log.warn("already connected; ignoring remote={}", remote);
return true;
}
if (remote == null) {
close();
log.error("remote == null");
throw new NullPointerException();
}
remoteSocket = (InetSocketAddress) remote;
if (remoteSocket.isUnresolved()) {
log.error("can not use unresolved address: remote={}", remote);
close();
throw new UnresolvedAddressException();
}
if (isBlocking()) {
synchronized (connectLock) {
try {
if (isConnectionPending) {
close();
throw new ConnectionPendingException();
}
isConnectionPending = true;
begin();
socketUDT.connect(remoteSocket);
} finally {
end(true);
isConnectionPending = false;
connectLock.notifyAll();
}
}
return socketUDT.isConnected();
} else {
/** non Blocking */
if (!isRegistered()) {
/** this channel is independent of any selector */
log.error("UDT channel is in NON blocking mode; "
+ "must register with a selector " //
+ "before trying to connect(); " //
+ "socketId=" + socketUDT.id());
throw new IllegalBlockingModeException();
}
/** this channel is registered with a selector */
synchronized (connectLock) {
if (isConnectionPending) {
close();
log.error("connection already in progress");
throw new ConnectionPendingException();
}
isConnectFinished = false;
isConnectionPending = true;
socketUDT.connect(remoteSocket);
}
/**
* connection operation must later be completed by invoking the
* #finishConnect() method.
*/
return false;
}
}
@Override
public boolean finishConnect() throws IOException {
if (!isOpen()) {
throw new ClosedChannelException();
}
if (isBlocking()) {
synchronized (connectLock) {
while (isConnectionPending) {
try {
connectLock.wait();
} catch (final InterruptedException e) {
throw new IOException(e);
}
}
}
}
if (isConnected()) {
isConnectFinished = true;
isConnectionPending = false;
return true;
} else {
log.error("connect failure : {}", socketUDT);
throw new IOException();
}
}
@Override
protected void implCloseSelectableChannel() throws IOException {
socketUDT.close();
}
@Override
protected void implConfigureBlocking(final boolean block)
throws IOException {
socketUDT.setBlocking(block);
isBlockingMode = block;
}
@Override
public boolean isConnected() {
return socketUDT.isConnected();
}
@Override
public boolean isConnectFinished() {
return isConnectFinished;
}
@Override
public boolean isConnectionPending() {
return isConnectionPending;
}
@Override
public KindUDT kindUDT() {
return KindUDT.CONNECTOR;
}
@Override
public SelectorProviderUDT providerUDT() {
return (SelectorProviderUDT) super.provider();
}
/**
* See {@link SocketChannel#read(ByteBuffer)} contract;
* note: this method does not return (-1) as EOS (end of stream flag)
*
* @return <code><0</code> should not happen<br>
* <code>=0</code> blocking mode: timeout occurred on receive<br>
* <code>=0</code> non-blocking mode: nothing is received by the
* underlying UDT socket<br>
* <code>>0</code> actual bytes received count<br>
* @see SocketUDT#receive(ByteBuffer)
* @see SocketUDT#receive(byte[], int, int)
*/
@Override
public int read(final ByteBuffer buffer) throws IOException {
final int remaining = buffer.remaining();
if (remaining <= 0) {
return 0;
}
final SocketUDT socket = socketUDT;
final boolean isBlocking = isBlockingMode;
final int sizeReceived;
try {
if (isBlocking) {
begin(); // JDK contract for NIO blocking calls
}
if (buffer.isDirect()) {
sizeReceived = socket.receive(buffer);
} else {
final byte[] array = buffer.array();
final int position = buffer.position();
final int limit = buffer.limit();
sizeReceived = socket.receive(array, position, limit);
if (0 < sizeReceived && sizeReceived <= remaining) {
buffer.position(position + sizeReceived);
}
}
} finally {
if (isBlocking) {
end(true); // JDK contract for NIO blocking calls
}
}
// see contract for receive()
if (sizeReceived < 0) {
// log.trace("nothing was received; socket={}", socket);
return 0;
}
if (sizeReceived == 0) {
// log.trace("receive timeout; socket={}", socket);
return 0;
}
if (sizeReceived <= remaining) {
return sizeReceived;
} else {
log.error("should not happen: socket={}", socket);
return 0;
}
}
@Override
public long read(final ByteBuffer[] dsts, final int offset, final int length)
throws IOException {
throw new RuntimeException("feature not available");
}
@Override
public synchronized NioSocketUDT socket() {
if (socketAdapter == null) {
try {
socketAdapter = new NioSocketUDT(this);
} catch (final ExceptionUDT e) {
log.error("failed to make socket", e);
}
}
return socketAdapter;
}
@Override
public SocketUDT socketUDT() {
return socketUDT;
}
@Override
public String toString() {
return socketUDT.toString();
}
/**
* See {@link SocketChannel#write(ByteBuffer)} contract;
*
* @return <code><0</code> should not happen<br>
* <code>=0</code> blocking mode: timeout occurred on send<br>
* <code>=0</code> non-blocking mode: buffer is full in the
* underlying UDT socket; nothing is sent<br>
* <code>>0</code> actual bytes sent count<br>
* @see SocketUDT#send(ByteBuffer)
* @see SocketUDT#send(byte[], int, int)
*/
@Override
public int write(final ByteBuffer buffer) throws IOException {
// writeCount.incrementAndGet();
if (buffer == null) {
throw new NullPointerException("buffer == null");
}
final int remaining = buffer.remaining();
if (remaining <= 0) {
return 0;
}
final SocketUDT socket = socketUDT;
final boolean isBlocking = isBlockingMode;
int sizeSent = 0;
int ret = 0;
try {
if (isBlocking) {
begin(); // JDK contract for NIO blocking calls
}
if (buffer.isDirect()) {
do {
ret = socket.send(buffer);
if (ret > 0)
sizeSent += ret;
} while (buffer.hasRemaining() && isBlocking);
} else {
final byte[] array = buffer.array();
int position = buffer.position();
final int limit = buffer.limit();
do {
ret = socket.send(array, position, limit);
if (0 < ret && ret <= remaining) {
sizeSent += ret;
position += ret;
buffer.position(position);
}
} while (buffer.hasRemaining() && isBlocking);
}
} finally {
if (isBlocking) {
end(true); // JDK contract for NIO blocking calls
}
}
// see contract for send()
if (ret < 0) {
// log.trace("no buffer space; socket={}", socket);
return 0;
}
if (ret == 0) {
// log.trace("send timeout; socket={}", socket);
return 0;
}
if (sizeSent <= remaining) {
return sizeSent;
} else {
log.error("should not happen; socket={}", socket);
return 0;
}
}
@Override
public long write(final ByteBuffer[] bufferArray, final int offset, final int length) throws IOException {
try {
long total = 0;
for (int index = offset; index < offset + length; index++) {
final ByteBuffer buffer = bufferArray[index];
final int remaining = buffer.remaining();
final int processed = write(buffer);
if (remaining == processed) {
total += processed;
} else {
throw new IllegalStateException(
"failed to write buffer in array");
}
}
return total;
} catch (final Throwable e) {
throw new IOException("failed to write buffer array", e);
}
}
@Override
public TypeUDT typeUDT() {
return providerUDT().type();
}
/** java 7 */
public SocketChannelUDT bind(final SocketAddress localAddress) throws IOException {
socketUDT.bind((InetSocketAddress) localAddress);
return this;
}
}

View File

@ -1,140 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.util;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.barchart.udt.EpollUDT;
/**
* miscellaneous utilities
*/
public class HelpUDT {
protected static final Logger log = LoggerFactory.getLogger(EpollUDT.class);
public static long md5sum(final String text) {
final byte[] defaultBytes = text.getBytes();
try {
final MessageDigest algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(defaultBytes);
final byte digest[] = algorithm.digest();
final ByteBuffer buffer = ByteBuffer.wrap(digest);
return buffer.getLong();
} catch (final NoSuchAlgorithmException e) {
log.error("md5 failed", e);
return 0;
}
}
/**
* direct integer buffer with proper native byte order
*/
public static final IntBuffer newDirectIntBufer(final int capacity) {
/** java int is 4 bytes */
return ByteBuffer. //
allocateDirect(capacity * 4). //
order(ByteOrder.nativeOrder()). //
asIntBuffer();
}
public static <E> Set<E> ungrowableSet(final Set<E> set) {
return new UngrowableSet<E>(set);
}
public static <E> Set<E> unmodifiableSet(final Collection<E> values) {
return new UnmodifiableSet<E>(values);
}
private HelpUDT() {
}
public static final void checkBuffer(final ByteBuffer buffer) {
if (buffer == null) {
throw new IllegalArgumentException("buffer == null");
}
if (!buffer.isDirect()) {
throw new IllegalArgumentException("must use DirectByteBuffer");
}
}
public static final void checkArray(final byte[] array) {
if (array == null) {
throw new IllegalArgumentException("array == null");
}
}
public static String constantFieldName(final Class<?> klaz,
final Object instance) {
final Field[] filedArray = klaz.getDeclaredFields();
for (final Field field : filedArray) {
final int modifiers = field.getModifiers();
final boolean isConstant = true && //
Modifier.isPublic(modifiers) && //
Modifier.isStatic(modifiers) && //
Modifier.isFinal(modifiers) //
;
if (isConstant) {
try {
if (instance == field.get(null)) {
return field.getName();
}
} catch (final Throwable e) {
log.debug("", e);
}
}
}
return "unknown";
}
public static void checkSocketAddress(final InetSocketAddress socketAddress) {
if (socketAddress == null) {
throw new IllegalArgumentException("socketAddress can't be null");
}
/** can not use in JNI ; internal InetAddress field is null */
if (socketAddress.isUnresolved()) {
throw new IllegalArgumentException("socketAddress is unresolved : "
+ socketAddress + " : check your DNS settings");
}
}
}

View File

@ -1,102 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.util;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
class UngrowableSet<E> implements Set<E> {
private final Set<E> set;
UngrowableSet(final Set<E> set) {
this.set = set;
}
@Override
public boolean add(final E o) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
set.clear();
}
@Override
public boolean contains(final Object o) {
return set.contains(o);
}
@Override
public boolean containsAll(final Collection<?> coll) {
return set.containsAll(coll);
}
@Override
public boolean equals(final Object o) {
return set.equals(o);
}
@Override
public int hashCode() {
return set.hashCode();
}
@Override
public boolean isEmpty() {
return set.isEmpty();
}
@Override
public Iterator<E> iterator() {
return set.iterator();
}
@Override
public boolean remove(final Object o) {
return set.remove(o);
}
@Override
public boolean removeAll(final Collection<?> coll) {
return set.removeAll(coll);
}
@Override
public boolean retainAll(final Collection<?> coll) {
return set.retainAll(coll);
}
@Override
public int size() {
return set.size();
}
@Override
public Object[] toArray() {
return set.toArray();
}
@Override
public <T> T[] toArray(final T[] a) {
return set.toArray(a);
}
@Override
public String toString() {
return set.toString();
}
}

View File

@ -1,87 +0,0 @@
/**
* Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
*
* All rights reserved. Licensed under the OSI BSD License.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package com.barchart.udt.util;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
class UnmodifiableSet<E> implements Set<E> {
private final Collection<E> values;
UnmodifiableSet(final Collection<E> values) {
this.values = values;
}
@Override
public boolean add(final E e) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(final Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean contains(final Object o) {
return values.contains(o);
}
@Override
public boolean containsAll(final Collection<?> c) {
return values.containsAll(c);
}
@Override
public boolean isEmpty() {
return values.isEmpty();
}
@Override
public Iterator<E> iterator() {
return values.iterator();
}
@Override
public boolean remove(final Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
return values.size();
}
@Override
public Object[] toArray() {
return values.toArray();
}
@Override
public <T> T[] toArray(final T[] a) {
return values.toArray(a);
}
}