SAM v3.3:

- More master session option checks
- Add support for SEND_TAGS, TAG_THRESHOLD, EXPIRES, and SEND_LEASESET
  (untested)
- Consolidate dup code in SAMv1Handler
- Change Session to extend SAMMessageSess
- Pass options down to v1 handlers in case we need it later
This commit is contained in:
zzz
2016-02-07 18:45:26 +00:00
parent b6deae9b23
commit d962be9d7e
12 changed files with 187 additions and 181 deletions

View File

@ -42,7 +42,8 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
private final SAMv3DatagramServer dgs;
private final Map<String, SAMMessageSess> sessions;
private final StreamAcceptor streamAcceptor;
private static final String[] INVALID_OPTS = { "PORT", "HOST", "FROM_PORT", "TO_PORT", "PROTOCOL" };
private static final String[] INVALID_OPTS = { "PORT", "HOST", "FROM_PORT", "TO_PORT",
"PROTOCOL", "LISTEN_PORT", "LISTEN_PROTOCOL" };
/**
* Build a Session according to information

View File

@ -32,7 +32,6 @@ class SAMDatagramSession extends SAMMessageSession {
// FIXME make final after fixing SAMv3DatagramSession override
protected SAMDatagramReceiver recv;
private final I2PDatagramMaker dgramMaker;
private final I2PDatagramDissector dgramDissector = new I2PDatagramDissector();
@ -50,7 +49,6 @@ class SAMDatagramSession extends SAMMessageSession {
SAMDatagramReceiver recv) throws IOException,
DataFormatException, I2PSessionException {
super(dest, props);
this.recv = recv;
dgramMaker = new I2PDatagramMaker(getI2PSession());
}
@ -71,7 +69,6 @@ class SAMDatagramSession extends SAMMessageSession {
SAMDatagramReceiver recv) throws IOException,
DataFormatException, I2PSessionException {
super(destStream, props);
this.recv = recv;
dgramMaker = new I2PDatagramMaker(getI2PSession());
}
@ -79,13 +76,13 @@ class SAMDatagramSession extends SAMMessageSession {
/**
* Create a new SAM DATAGRAM session on an existing I2P session.
*
* @param props unused for now
* @since 0.9.25
*/
protected SAMDatagramSession(I2PSession sess, int listenPort,
protected SAMDatagramSession(I2PSession sess, Properties props, int listenPort,
SAMDatagramReceiver recv) throws IOException,
DataFormatException, I2PSessionException {
super(sess, I2PSession.PROTO_DATAGRAM, listenPort);
this.recv = recv;
dgramMaker = new I2PDatagramMaker(getI2PSession());
}
@ -107,11 +104,31 @@ class SAMDatagramSession extends SAMMessageSession {
throw new DataFormatException("Datagram size exceeded (" + data.length + ")");
byte[] dgram ;
synchronized (dgramMaker) {
dgram = dgramMaker.makeI2PDatagram(data);
dgram = dgramMaker.makeI2PDatagram(data);
}
return sendBytesThroughMessageSession(dest, dgram, I2PSession.PROTO_DATAGRAM, fromPort, toPort);
}
/**
* Send bytes through a SAM DATAGRAM session.
*
* @since 0.9.25
*/
public boolean sendBytes(String dest, byte[] data, int proto,
int fromPort, int toPort,
boolean sendLeaseSet, int sendTags,
int tagThreshold, int expiration)
throws DataFormatException, I2PSessionException {
if (data.length > DGRAM_SIZE_MAX)
throw new DataFormatException("Datagram size exceeded (" + data.length + ")");
byte[] dgram ;
synchronized (dgramMaker) {
dgram = dgramMaker.makeI2PDatagram(data);
}
return sendBytesThroughMessageSession(dest, dgram, I2PSession.PROTO_DATAGRAM, fromPort, toPort,
sendLeaseSet, sendTags,tagThreshold, expiration);
}
protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) {
byte[] payload;
Destination sender;

View File

@ -46,6 +46,17 @@ interface SAMMessageSess extends Closeable {
public boolean sendBytes(String dest, byte[] data, int proto,
int fromPort, int toPort) throws DataFormatException, I2PSessionException;
/**
* Send bytes through a SAM message-based session.
*
* @since 0.9.25
*/
public boolean sendBytes(String dest, byte[] data, int proto,
int fromPort, int toPort,
boolean sendLeaseSet, int sendTags,
int tagThreshold, int expiration)
throws DataFormatException, I2PSessionException;
public int getListenProtocol();
public int getListenPort();

View File

@ -37,6 +37,7 @@ abstract class SAMMessageSession implements SAMMessageSess {
protected final Log _log;
private final I2PSession session;
protected final boolean _isOwnSession;
private final SAMMessageSessionHandler handler;
private final int listenProtocol;
private final int listenPort;
@ -69,6 +70,7 @@ abstract class SAMMessageSession implements SAMMessageSess {
_log.debug("Initializing SAM message-based session");
listenProtocol = I2PSession.PROTO_ANY;
listenPort = I2PSession.PORT_ANY;
_isOwnSession = true;
handler = new SAMMessageSessionHandler(destStream, props);
session = handler.getSession();
}
@ -90,6 +92,7 @@ abstract class SAMMessageSession implements SAMMessageSess {
_log.debug("Initializing SAM message-based session");
this.listenProtocol = listenProtocol;
this.listenPort = listenPort;
_isOwnSession = false;
session = sess;
handler = new SAMMessageSessionHandler(session);
}
@ -165,14 +168,19 @@ abstract class SAMMessageSession implements SAMMessageSess {
}
/**
* Actually send bytes through the SAM message-based session I2PSession.
* TODO unused, umimplemented in the sessions and handlers
* Actually send bytes through the SAM message-based session I2PSession,
* using per-message extended options.
* For efficiency, use the method without all the extra options if they are all defaults.
*
* @param dest Destination
* @param data Bytes to be sent
* @param proto I2CP protocol
* @param fromPort I2CP from port
* @param toPort I2CP to port
* @param sendLeaseSet true is the usual setting and the I2CP default
* @param sendTags 0 to leave as default
* @param tagThreshold 0 to leave as default
* @param expiration SECONDS from now, NOT absolute time, 0 to leave as default
*
* @return True if the data was sent, false otherwise
* @throws DataFormatException on unknown / bad dest
@ -182,7 +190,7 @@ abstract class SAMMessageSession implements SAMMessageSess {
protected boolean sendBytesThroughMessageSession(String dest, byte[] data,
int proto, int fromPort, int toPort,
boolean sendLeaseSet, int sendTags,
int tagThreshold, long expires)
int tagThreshold, int expiration)
throws DataFormatException, I2PSessionException {
Destination d = SAMUtils.getDest(dest);
@ -190,10 +198,14 @@ abstract class SAMMessageSession implements SAMMessageSess {
_log.debug("Sending " + data.length + " bytes to " + dest);
}
SendMessageOptions opts = new SendMessageOptions();
opts.setSendLeaseSet(sendLeaseSet);
opts.setTagsToSend(sendTags);
opts.setTagThreshold(tagThreshold);
opts.setDate(expires);
if (!sendLeaseSet)
opts.setSendLeaseSet(false);
if (sendTags > 0)
opts.setTagsToSend(sendTags);
if (tagThreshold > 0)
opts.setTagThreshold(tagThreshold);
if (expiration > 0)
opts.setDate(I2PAppContext.getGlobalContext().clock().now() + (expiration * 1000));
return session.sendMessage(d, data, 0, data.length, proto, fromPort, toPort, opts);
}
@ -234,7 +246,6 @@ abstract class SAMMessageSession implements SAMMessageSess {
private class SAMMessageSessionHandler implements Runnable, I2PSessionMuxedListener {
private final I2PSession _session;
private final boolean _isOwnSession;
private final Object runningLock = new Object();
private volatile boolean stillRunning = true;
@ -254,7 +265,6 @@ abstract class SAMMessageSession implements SAMMessageSess {
props.setProperty("inbound.nickname", "SAM UDP Client");
props.setProperty("outbound.nickname", "SAM UDP Client");
}
_isOwnSession = true;
_session = client.createSession(destStream, props);
if (_log.shouldLog(Log.DEBUG))
@ -272,7 +282,6 @@ abstract class SAMMessageSession implements SAMMessageSess {
* @since 0.9.25
*/
public SAMMessageSessionHandler(I2PSession sess) throws I2PSessionException {
_isOwnSession = false;
_session = sess;
_session.addMuxedSessionListener(this, listenProtocol, listenPort);
}

View File

@ -42,7 +42,6 @@ class SAMRawSession extends SAMMessageSession {
protected SAMRawSession(String dest, Properties props,
SAMRawReceiver recv) throws IOException, DataFormatException, I2PSessionException {
super(dest, props);
this.recv = recv;
}
@ -61,16 +60,16 @@ class SAMRawSession extends SAMMessageSession {
public SAMRawSession(InputStream destStream, Properties props,
SAMRawReceiver recv) throws IOException, DataFormatException, I2PSessionException {
super(destStream, props);
this.recv = recv;
}
/**
* Create a new SAM RAW session on an existing I2P session.
*
* @param props unused for now
* @since 0.9.25
*/
protected SAMRawSession(I2PSession sess, int listenProtocol, int listenPort,
protected SAMRawSession(I2PSession sess, Properties props, int listenProtocol, int listenPort,
SAMRawReceiver recv) throws IOException,
DataFormatException, I2PSessionException {
super(sess, listenProtocol, listenPort);
@ -96,6 +95,24 @@ class SAMRawSession extends SAMMessageSession {
return sendBytesThroughMessageSession(dest, data, proto, fromPort, toPort);
}
/**
* Send bytes through a SAM RAW session.
*
* @since 0.9.25
*/
public boolean sendBytes(String dest, byte[] data, int proto,
int fromPort, int toPort,
boolean sendLeaseSet, int sendTags,
int tagThreshold, int expiration)
throws DataFormatException, I2PSessionException {
if (data.length > RAW_SIZE_MAX)
throw new DataFormatException("Data size limit exceeded (" + data.length + ")");
if (proto == I2PSession.PROTO_UNSPECIFIED)
proto = I2PSession.PROTO_DATAGRAM_RAW;
return sendBytesThroughMessageSession(dest, data, proto, fromPort, toPort,
sendLeaseSet, sendTags,tagThreshold, expiration);
}
protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) {
try {
recv.receiveRawBytes(msg, proto, fromPort, toPort);

View File

@ -372,7 +372,19 @@ class SAMStreamSession implements SAMMessageSess {
* @since 0.9.25 moved from subclass SAMv3StreamSession to implement SAMMessageSess
*/
public boolean sendBytes(String s, byte[] b, int pr, int fp, int tp) throws I2PSessionException {
throw new I2PSessionException("Unsupported in STREAM or MASTER session");
throw new I2PSessionException("Unsupported in STREAM or MASTER session");
}
/**
* Unsupported
* @throws I2PSessionException always
* @since 0.9.25
*/
public boolean sendBytes(String s, byte[] b, int pr, int fp, int tp,
boolean sendLeaseSet, int sendTags,
int tagThreshold, int expiration)
throws I2PSessionException {
throw new I2PSessionException("Unsupported in STREAM or MASTER session");
}
/**

View File

@ -419,102 +419,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
_log.error("DATAGRAM message received, but no DATAGRAM session exists");
return false;
}
if (opcode.equals("SEND")) {
if (props.isEmpty()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("No parameters specified in DATAGRAM SEND message");
return false;
}
String dest = props.getProperty("DESTINATION");
if (dest == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Destination not specified in DATAGRAM SEND message");
return false;
}
int size;
String strsize = props.getProperty("SIZE");
if (strsize == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Size not specified in DATAGRAM SEND message");
return false;
}
try {
size = Integer.parseInt(strsize);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid DATAGRAM SEND size specified: " + strsize);
return false;
}
if (!checkDatagramSize(size)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Specified size (" + size
+ ") is out of protocol limits");
return false;
}
int proto = I2PSession.PROTO_DATAGRAM;
int fromPort = I2PSession.PORT_UNSPECIFIED;
int toPort = I2PSession.PORT_UNSPECIFIED;
String s = props.getProperty("FROM_PORT");
if (s != null) {
try {
fromPort = Integer.parseInt(s);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid DATAGRAM SEND port specified: " + s);
}
}
s = props.getProperty("TO_PORT");
if (s != null) {
try {
toPort = Integer.parseInt(s);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid RAW SEND port specified: " + s);
}
}
try {
DataInputStream in = new DataInputStream(getClientSocket().socket().getInputStream());
byte[] data = new byte[size];
in.readFully(data);
if (!datagramSession.sendBytes(dest, data, proto, fromPort, toPort)) {
_log.error("DATAGRAM SEND failed");
// a message send failure is no reason to drop the SAM session
// for raw and repliable datagrams, just carry on our merry way
return true;
}
return true;
} catch (EOFException e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Too few bytes with DATAGRAM SEND message (expected: "
+ size);
return false;
} catch (IOException e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Caught IOException while parsing DATAGRAM SEND message",
e);
return false;
} catch (DataFormatException e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Invalid key specified with DATAGRAM SEND message",
e);
return false;
} catch (I2PSessionException e) {
_log.error("Session error with DATAGRAM SEND message", e);
return false;
}
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unrecognized DATAGRAM message opcode: \""
+ opcode + "\"");
return false;
}
return execDgOrRawMessage(false, opcode, props);
}
/* Parse and execute a RAW message */
@ -523,18 +428,33 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
_log.error("RAW message received, but no RAW session exists");
return false;
}
return execDgOrRawMessage(true, opcode, props);
}
/*
* Parse and execute a RAW or DATAGRAM SEND message.
* This is for v1/v2 compatible sending only.
* For v3 sending, see SAMv3DatagramServer.
*
* Note that props are from the command line only.
* Session defaults from CREATE are NOT honored here.
* FIXME if we care, but nobody's probably using v3.2 options for v1/v2 sending.
*
* @since 0.9.25 consolidated from execDatagramMessage() and execRawMessage()
*/
private boolean execDgOrRawMessage(boolean isRaw, String opcode, Properties props) {
if (opcode.equals("SEND")) {
if (props.isEmpty()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("No parameters specified in RAW SEND message");
_log.debug("No parameters specified in SEND message");
return false;
}
String dest = props.getProperty("DESTINATION");
if (dest == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Destination not specified in RAW SEND message");
_log.debug("Destination not specified in SEND message");
return false;
}
@ -542,41 +462,47 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
String strsize = props.getProperty("SIZE");
if (strsize == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Size not specified in RAW SEND message");
_log.warn("Size not specified in SEND message");
return false;
}
try {
size = Integer.parseInt(strsize);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid RAW SEND size specified: " + strsize);
_log.warn("Invalid SEND size specified: " + strsize);
return false;
}
if (!checkSize(size)) {
boolean ok = isRaw ? checkSize(size) : checkDatagramSize(size);
if (!ok) {
if (_log.shouldLog(Log.WARN))
_log.warn("Specified size (" + size
+ ") is out of protocol limits");
return false;
}
int proto = I2PSession.PROTO_DATAGRAM_RAW;
int fromPort = I2PSession.PORT_UNSPECIFIED;
int toPort = I2PSession.PORT_UNSPECIFIED;
String s = props.getProperty("PROTOCOL");
if (s != null) {
try {
proto = Integer.parseInt(s);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid RAW SEND protocol specified: " + s);
int proto;
if (isRaw) {
proto = I2PSession.PROTO_DATAGRAM_RAW;
String s = props.getProperty("PROTOCOL");
if (s != null) {
try {
proto = Integer.parseInt(s);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid SEND protocol specified: " + s);
}
}
} else {
proto = I2PSession.PROTO_DATAGRAM;
}
s = props.getProperty("FROM_PORT");
String s = props.getProperty("FROM_PORT");
if (s != null) {
try {
fromPort = Integer.parseInt(s);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid RAW SEND port specified: " + s);
_log.warn("Invalid SEND port specified: " + s);
}
}
s = props.getProperty("TO_PORT");
@ -585,7 +511,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
toPort = Integer.parseInt(s);
} catch (NumberFormatException e) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid RAW SEND port specified: " + s);
_log.warn("Invalid SEND port specified: " + s);
}
}
@ -595,8 +521,9 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
in.readFully(data);
if (!rawSession.sendBytes(dest, data, proto, fromPort, toPort)) {
_log.error("RAW SEND failed");
SAMMessageSess sess = isRaw ? rawSession : datagramSession;
if (sess.sendBytes(dest, data, proto, fromPort, toPort)) {
_log.error("SEND failed");
// a message send failure is no reason to drop the SAM session
// for raw and repliable datagrams, just carry on our merry way
return true;
@ -605,26 +532,26 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
return true;
} catch (EOFException e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Too few bytes with RAW SEND message (expected: "
_log.debug("Too few bytes with SEND message (expected: "
+ size);
return false;
} catch (IOException e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Caught IOException while parsing RAW SEND message",
_log.debug("Caught IOException while parsing SEND message",
e);
return false;
} catch (DataFormatException e) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Invalid key specified with RAW SEND message",
_log.debug("Invalid key specified with SEND message",
e);
return false;
} catch (I2PSessionException e) {
_log.error("Session error with RAW SEND message", e);
_log.error("Session error with SEND message", e);
return false;
}
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unrecognized RAW message opcode: \""
_log.debug("Unrecognized message opcode: \""
+ opcode + "\"");
return false;
}
@ -645,7 +572,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
return execStreamClose(props);
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Unrecognized RAW message opcode: \""
_log.debug("Unrecognized STREAM message opcode: \""
+ opcode + "\"");
return false;
}

View File

@ -163,54 +163,79 @@ class SAMv3DatagramServer implements Handler {
SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
if (rec!=null) {
Properties sprops = rec.getProps();
// 3.2 props
String pr = sprops.getProperty("PROTOCOL");
String fp = sprops.getProperty("FROM_PORT");
String tp = sprops.getProperty("TO_PORT");
// 3.3 props
String st = sprops.getProperty("SEND_TAGS");
String tt = sprops.getProperty("TAG_THRESHOLD");
String ex = sprops.getProperty("EXPIRES");
String sl = sprops.getProperty("SEND_LEASESET");
while (tok.hasMoreTokens()) {
String t = tok.nextToken();
// 3.2 props
if (t.startsWith("PROTOCOL="))
pr = t.substring("PROTOCOL=".length());
else if (t.startsWith("FROM_PORT="))
fp = t.substring("FROM_PORT=".length());
else if (t.startsWith("TO_PORT="))
tp = t.substring("TO_PORT=".length());
// 3.3 props
else if (t.startsWith("SEND_TAGS="))
st = t.substring("SEND_TAGS=".length());
else if (t.startsWith("TAG_THRESHOLD="))
tt = t.substring("TAG_THRESHOLD=".length());
else if (t.startsWith("EXPIRES="))
ex = t.substring("EXPIRES=".length());
else if (t.startsWith("SEND_LEASESET="))
sl = t.substring("SEND_LEASESET=".length());
}
// 3.2 props
int proto = I2PSession.PROTO_UNSPECIFIED;
int fromPort = I2PSession.PORT_UNSPECIFIED;
int toPort = I2PSession.PORT_UNSPECIFIED;
if (pr != null) {
try {
// 3.3 props
int sendTags = 0;
int tagThreshold = 0;
int expires = 0;
boolean sendLeaseSet = true;
try {
// 3.2 props
if (pr != null)
proto = Integer.parseInt(pr);
} catch (NumberFormatException nfe) {
warn("Bad datagram header received");
return;
}
}
if (fp != null) {
try {
if (fp != null)
fromPort = Integer.parseInt(fp);
} catch (NumberFormatException nfe) {
warn("Bad datagram header received");
return;
}
}
if (tp != null) {
try {
if (tp != null)
toPort = Integer.parseInt(tp);
} catch (NumberFormatException nfe) {
warn("Bad datagram header received");
return;
}
// 3.3 props
if (st != null)
sendTags = Integer.parseInt(st);
if (tt != null)
tagThreshold = Integer.parseInt(tt);
if (ex != null)
expires = Integer.parseInt(ex);
if (sl != null)
sendLeaseSet = Boolean.parseBoolean(sl);
} catch (NumberFormatException nfe) {
warn("Bad datagram header received");
return;
}
// TODO too many allocations and copies. One here and one in Listener above.
byte[] data = new byte[is.available()];
is.read(data);
Session sess = rec.getHandler().getSession();
if (sess != null)
sess.sendBytes(dest, data, proto, fromPort, toPort);
else
if (sess != null) {
if (sendTags > 0 || tagThreshold > 0 || expires > 0 || !sendLeaseSet) {
sess.sendBytes(dest, data, proto, fromPort, toPort,
sendLeaseSet, sendTags, tagThreshold, expires);
} else {
sess.sendBytes(dest, data, proto, fromPort, toPort);
}
} else {
warn("Dropping datagram, no session for " + nick);
}
} else {
warn("Dropping datagram, no session for " + nick);
}

View File

@ -74,7 +74,7 @@ class SAMv3DatagramSession extends SAMDatagramSession implements Session, SAMDat
public SAMv3DatagramSession(String nick, Properties props, SAMv3Handler handler, I2PSession isess,
int listenPort, SAMv3DatagramServer dgServer)
throws IOException, DataFormatException, I2PSessionException {
super(isess, listenPort, null); // to be replaced by this
super(isess, props, listenPort, null); // to be replaced by this
this.nick = nick ;
this.recv = this ; // replacement
this.server = dgServer;

View File

@ -75,7 +75,7 @@ class SAMv3RawSession extends SAMRawSession implements Session, SAMRawReceiver {
public SAMv3RawSession(String nick, Properties props, SAMv3Handler handler, I2PSession isess,
int listenProtocol, int listenPort, SAMv3DatagramServer dgServer)
throws IOException, DataFormatException, I2PSessionException {
super(isess, listenProtocol, listenPort, null); // to be replace by this
super(isess, props, listenProtocol, listenPort, null); // to be replaced by this
this.nick = nick ;
this.recv = this ; // replacement
this.server = dgServer;

View File

@ -131,6 +131,7 @@ class SAMv3StreamSession extends SAMStreamSession implements Session
if (_acceptQueue == null)
throw new IllegalStateException();
try {
// TODO there's no CoDel or expiration in this queue
return _acceptQueue.take();
} catch (InterruptedException ie) {
ConnectException ce = new ConnectException("interrupted");

View File

@ -1,25 +1,11 @@
package net.i2p.sam;
/*
* free (adj.): unencumbered; not under the control of others
* Written by human in 2004 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import net.i2p.client.I2PSessionException;
import net.i2p.data.DataFormatException;
/**
* A V3 session.
*
* @since 0.9.25 moved from SAMv3Handler
*/
interface Session {
interface Session extends SAMMessageSess {
String getNick();
void close();
boolean sendBytes(String dest, byte[] data, int proto,
int fromPort, int toPort) throws DataFormatException, I2PSessionException;
}