This commit is contained in:
jrandom
2004-11-25 21:49:29 +00:00
committed by zzz
parent f10db9d91a
commit b0513fff8a
6 changed files with 65 additions and 2 deletions

View File

@ -6,6 +6,11 @@ import net.i2p.I2PAppContext;
import net.i2p.util.Log;
/**
* Receive data from the MessageOutputStream, build a packet,
* and send it through a connection. The write calls on this
* do NOT block, but they also do not necessary imply immediate
* delivery, or even the generation of a new packet. This class
* is the only one that builds useful outbound Packet objects.
*
*/
class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
@ -21,6 +26,17 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
_dummyStatus = new DummyStatus();
}
/**
* Send some data through the connection, or if there is no new data, this
* may generate a packet with a plain ACK/NACK or CLOSE, or nothing whatsoever
* if there's nothing new to send.
*
* @param buf data to be sent - may be null
* @param off offset into the buffer to start writing from
* @param size how many bytes of the buffer to write (may be 0)
* @return an object to allow optional blocking for data acceptance or
* delivery.
*/
public MessageOutputStream.WriteStatus writeData(byte[] buf, int off, int size) {
boolean doSend = true;
if ( (size <= 0) && (_connection.getLastSendId() >= 0) ) {
@ -54,12 +70,25 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
}
/**
* Send some data through the connection, attaching any appropriate flags
* onto the packet.
*
* @param buf data to be sent - may be null
* @param off offset into the buffer to start writing from
* @param size how many bytes of the buffer to write (may be 0)
* @return the packet sent
*/
public PacketLocal send(byte buf[], int off, int size) {
return send(buf, off, size, false);
}
/**
* @param buf data to be sent - may be null
* @param off offset into the buffer to start writing from
* @param size how many bytes of the buffer to write (may be 0)
* @param forceIncrement even if the buffer is empty, increment the packetId
* so we get an ACK back
* @return the packet sent
*/
public PacketLocal send(byte buf[], int off, int size, boolean forceIncrement) {
PacketLocal packet = buildPacket(buf, off, size, forceIncrement);
@ -123,7 +152,9 @@ class ConnectionDataReceiver implements MessageOutputStream.DataReceiver {
return packet;
}
/**
* Used if no new packet was sent.
*/
private static final class DummyStatus implements MessageOutputStream.WriteStatus {
public final void waitForAccept(int maxWaitMs) { return; }
public final void waitForCompletion(int maxWaitMs) { return; }

View File

@ -50,6 +50,14 @@ class ConnectionHandler {
}
}
/**
* Receive an incoming connection (built from a received SYN)
*
* @param timeoutMs max amount of time to wait for a connection (if less
* than 1ms, wait indefinitely)
* @return connection received, or null if there was a timeout or the
* handler was shut down
*/
public Connection accept(long timeoutMs) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Accept("+ timeoutMs+") called");

View File

@ -91,6 +91,7 @@ public class ConnectionManager {
public void setAllowIncomingConnections(boolean allow) {
_connectionHandler.setActive(allow);
}
/** should we acceot connections, or just reject everyone? */
public boolean getAllowIncomingConnections() {
return _connectionHandler.getActive();
}
@ -262,6 +263,10 @@ public class ConnectionManager {
}
}
/**
* Drop the (already closed) connection on the floor.
*
*/
public void removeConnection(Connection con) {
boolean removed = false;
synchronized (_connectionLock) {
@ -287,6 +292,7 @@ public class ConnectionManager {
}
}
/** return a set of Connection objects */
public Set listConnections() {
synchronized (_connectionLock) {
return new HashSet(_connectionByInboundId.values());

View File

@ -7,6 +7,8 @@ import net.i2p.client.I2PSessionException;
import net.i2p.util.Log;
/**
* Receive raw information from the I2PSession and turn it into
* Packets, if we can.
*
*/
public class MessageHandler implements I2PSessionListener {

View File

@ -10,7 +10,9 @@ import net.i2p.util.ByteCache;
import net.i2p.util.Log;
/**
*
* A stream that we can shove data into that fires off those bytes
* on flush or when the buffer is full. It also blocks according
* to the data receiver's needs.
*/
public class MessageOutputStream extends OutputStream {
private I2PAppContext _context;
@ -104,6 +106,13 @@ public class MessageOutputStream extends OutputStream {
throwAnyError();
}
/**
* Flush the data already queued up, blocking until it has been
* delivered.
*
* @throws IOException if the write fails
* @throws InterruptedIOException if the write times out
*/
public void flush() throws IOException {
WriteStatus ws = null;
synchronized (_dataLock) {
@ -148,6 +157,7 @@ public class MessageOutputStream extends OutputStream {
_dataCache.release(ba);
}
}
/** nonblocking close */
public void closeInternal() {
_closed = true;
_streamError = new IOException("Closed internally");
@ -217,6 +227,7 @@ public class MessageOutputStream extends OutputStream {
_dataReceiver = null;
}
/** Define a component to receive data flushed from this stream */
public interface DataReceiver {
/**
* Nonblocking write
@ -224,6 +235,7 @@ public class MessageOutputStream extends OutputStream {
public WriteStatus writeData(byte buf[], int off, int size);
}
/** Define a way to detect the status of a write */
public interface WriteStatus {
/** wait until the data written either fails or succeeds */
public void waitForCompletion(int maxWaitMs);

View File

@ -13,6 +13,10 @@ import net.i2p.util.ByteCache;
import net.i2p.util.Log;
/**
* Queue out packets to be sent through the session.
* Well, thats the theory at least... in practice we just
* send them immediately with no blocking, since the
* mode=bestEffort doesnt block in the SDK.
*
*/
class PacketQueue {