forked from I2P_Developers/i2p.i2p
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:
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user