diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java index 8324082be0..d4f026d984 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java @@ -12,7 +12,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; -import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.client.datagram.I2PDatagramDissector; import net.i2p.client.datagram.I2PDatagramMaker; @@ -83,16 +82,15 @@ class SAMDatagramSession extends SAMMessageSession { * @throws DataFormatException on unknown / bad dest * @throws I2PSessionException on serious error, probably session closed */ - public boolean sendBytes(String dest, byte[] data) throws DataFormatException, I2PSessionException { + public boolean sendBytes(String dest, byte[] data, int proto, + int fromPort, int toPort) 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); } - // TODO pass ports through - return sendBytesThroughMessageSession(dest, dgram, I2PSession.PROTO_DATAGRAM, - I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); + return sendBytesThroughMessageSession(dest, dgram, proto, fromPort, toPort); } protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java index a9531fd1ed..8613ed2d06 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java @@ -96,7 +96,8 @@ abstract class SAMMessageSession { * @throws DataFormatException on unknown / bad dest * @throws I2PSessionException on serious error, probably session closed */ - public abstract boolean sendBytes(String dest, byte[] data) throws DataFormatException, I2PSessionException; + public abstract boolean sendBytes(String dest, byte[] data, int proto, + int fromPort, int toPort) throws DataFormatException, I2PSessionException; /** * Actually send bytes through the SAM message-based session I2PSession diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java index 666d87049c..e31f5950c5 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java @@ -12,7 +12,6 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; -import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.data.DataFormatException; import net.i2p.util.Log; @@ -72,12 +71,11 @@ class SAMRawSession extends SAMMessageSession { * @throws DataFormatException on unknown / bad dest * @throws I2PSessionException on serious error, probably session closed */ - public boolean sendBytes(String dest, byte[] data) throws DataFormatException, I2PSessionException { + public boolean sendBytes(String dest, byte[] data, int proto, + int fromPort, int toPort) throws DataFormatException, I2PSessionException { if (data.length > RAW_SIZE_MAX) throw new DataFormatException("Data size limit exceeded (" + data.length + ")"); - // TODO pass ports through - return sendBytesThroughMessageSession(dest, data, I2PSession.PROTO_DATAGRAM_RAW, - I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); + return sendBytesThroughMessageSession(dest, data, proto, fromPort, toPort); } protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java index 85322d76b2..a0b5d53097 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java @@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicLong; import net.i2p.I2PException; import net.i2p.client.I2PClient; +import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.crypto.SigType; import net.i2p.data.Base64; @@ -438,25 +439,44 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece } int size; - { - String strsize = props.getProperty("SIZE"); - if (strsize == null) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Size not specified in DATAGRAM SEND message"); - return false; - } + 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 { - size = Integer.parseInt(strsize); + fromPort = Integer.parseInt(s); } catch (NumberFormatException e) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Invalid DATAGRAM SEND size specified: " + strsize); - return false; + if (_log.shouldLog(Log.WARN)) + _log.warn("Invalid DATAGRAM SEND port specified: " + s); } - if (!checkDatagramSize(size)) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Specified size (" + size - + ") is out of protocol limits"); - return false; + } + 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); } } @@ -466,7 +486,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece in.readFully(data); - if (!getDatagramSession().sendBytes(dest, data)) { + if (!getDatagramSession().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 @@ -523,25 +543,53 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece } int size; - { - String strsize = props.getProperty("SIZE"); - if (strsize == null) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Size not specified in RAW SEND message"); - return false; - } + String strsize = props.getProperty("SIZE"); + if (strsize == null) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Size not specified in RAW 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); + return false; + } + if (!checkSize(size)) { + 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 { - size = Integer.parseInt(strsize); + proto = Integer.parseInt(s); } catch (NumberFormatException e) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Invalid RAW SEND size specified: " + strsize); - return false; + if (_log.shouldLog(Log.WARN)) + _log.warn("Invalid RAW SEND protocol specified: " + s); } - if (!checkSize(size)) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Specified size (" + size - + ") is out of protocol limits"); - return false; + } + 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); + } + } + 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); } } @@ -551,7 +599,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece in.readFully(data); - if (!getRawSession().sendBytes(dest, data)) { + if (!getRawSession().sendBytes(dest, data, proto, fromPort, toPort)) { _log.error("RAW 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 diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index f623798dc8..3a0f55e13d 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -28,6 +28,7 @@ import java.util.StringTokenizer; import net.i2p.I2PAppContext; import net.i2p.I2PException; import net.i2p.client.I2PClient; +import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; import net.i2p.crypto.SigType; import net.i2p.data.Base64; @@ -56,7 +57,8 @@ class SAMv3Handler extends SAMv1Handler interface Session { String getNick(); void close(); - boolean sendBytes(String dest, byte[] data) throws DataFormatException, I2PSessionException; + boolean sendBytes(String dest, byte[] data, int proto, + int fromPort, int toPort) throws DataFormatException, I2PSessionException; } /** @@ -189,14 +191,16 @@ class SAMv3Handler extends SAMv1Handler try { String header = DataHelper.readLine(is).trim(); StringTokenizer tok = new StringTokenizer(header, " "); - if (tok.countTokens() != 3) { + if (tok.countTokens() < 3) { // This is not a correct message, for sure - //_log.debug("Error in message format"); - // FIXME log? throw? + warn("Bad datagram header received"); return; } String version = tok.nextToken(); - if (!"3.0".equals(version)) return ; + if (!version.startsWith("3")) { + warn("Bad datagram header received"); + return; + } String nick = tok.nextToken(); String dest = tok.nextToken(); @@ -204,18 +208,66 @@ class SAMv3Handler extends SAMv1Handler is.read(data); SessionRecord rec = sSessionsHash.get(nick); if (rec!=null) { - rec.getHandler().session.sendBytes(dest,data); + Properties sprops = rec.getProps(); + String pr = sprops.getProperty("PROTOCOL"); + String fp = sprops.getProperty("FROM_PORT"); + String tp = sprops.getProperty("TO_PORT"); + while (tok.hasMoreTokens()) { + String t = tok.nextToken(); + if (t.startsWith("PROTOCOL=")) + pr = t.substring("PROTOTCOL=".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()); + } + int proto = I2PSession.PROTO_UNSPECIFIED; + int fromPort = I2PSession.PORT_UNSPECIFIED; + int toPort = I2PSession.PORT_UNSPECIFIED; + if (pr != null) { + try { + proto = Integer.parseInt(pr); + } catch (NumberFormatException nfe) { + warn("Bad datagram header received"); + return; + } + } + if (fp != null) { + try { + fromPort = Integer.parseInt(fp); + } catch (NumberFormatException nfe) { + warn("Bad datagram header received"); + return; + } + } + if (tp != null) { + try { + toPort = Integer.parseInt(tp); + } catch (NumberFormatException nfe) { + warn("Bad datagram header received"); + return; + } + } + rec.getHandler().session.sendBytes(dest,data, proto, fromPort, toPort); } else { - Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class); - if (log.shouldLog(Log.WARN)) - log.warn("Dropping datagram, no session for " + nick); + warn("Dropping datagram, no session for " + nick); } } catch (Exception e) { - Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class); - if (log.shouldLog(Log.WARN)) - log.warn("Error handling datagram", e); + warn("Error handling datagram", e); } } + + /** @since 0.9.22 */ + private static void warn(String s) { + warn(s, null); + } + + /** @since 0.9.22 */ + private static void warn(String s, Throwable t) { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(SAMv3Handler.class); + if (log.shouldLog(Log.WARN)) + log.warn(s, t); + } } /** diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java index b5d613d189..d927c6f3c2 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java @@ -415,7 +415,11 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi socketMgr.destroySocketManager(); } - public boolean sendBytes(String s, byte[] b) throws DataFormatException + /** + * Unsupported + * @throws DataFormatException always + */ + public boolean sendBytes(String s, byte[] b, int pr, int fp, int tp) throws DataFormatException { throw new DataFormatException(null); }