diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java index 68971af31a46a208277ab550064144c2fd325a6b..b07ff8fbed71097a33238aed793137c7a917870d 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramReceiver.java @@ -22,9 +22,12 @@ interface SAMDatagramReceiver { * * @param sender Destination * @param data Byte array to be received + * @param proto I2CP protocol + * @param fromPort I2CP from port + * @param toPort I2CP to port * @throws IOException */ - public void receiveDatagramBytes(Destination sender, byte data[]) throws IOException; + public void receiveDatagramBytes(Destination sender, byte data[], int proto, int fromPort, int toPort) throws IOException; /** * Stop receiving data. diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java index ce3c1803c31b326e3c057109d0c73d9b74ee95b8..8324082be04c3848461ed79a0d446cb8361eaf40 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java @@ -95,7 +95,7 @@ class SAMDatagramSession extends SAMMessageSession { I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); } - protected void messageReceived(byte[] msg) { + protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) { byte[] payload; Destination sender; try { @@ -117,7 +117,7 @@ class SAMDatagramSession extends SAMMessageSession { } try { - recv.receiveDatagramBytes(sender, payload); + recv.receiveDatagramBytes(sender, payload, proto, fromPort, toPort); } catch (IOException e) { _log.error("Error forwarding message to receiver", e); close(); diff --git a/apps/sam/java/src/net/i2p/sam/SAMHandler.java b/apps/sam/java/src/net/i2p/sam/SAMHandler.java index 56d68878c612ec998fdc6a80f56e5b298f03f7e0..c7ec10388be2937cbda5a04c2944c76f8162c1fd 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMHandler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMHandler.java @@ -35,8 +35,8 @@ abstract class SAMHandler implements Runnable, Handler { private final Object socketWLock = new Object(); // Guards writings on socket protected final SocketChannel socket; - protected final int verMajor; - protected final int verMinor; + public final int verMajor; + public final int verMinor; /** I2CP options configuring the I2CP connection (port, host, numHops, etc) */ protected final Properties i2cpProps; diff --git a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java index db2450b0113dca84f2117c4a4faf05e0378adc2a..a9531fd1ed57670889500d4fcd61d9a03b628350 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java @@ -18,7 +18,7 @@ import net.i2p.client.I2PClient; import net.i2p.client.I2PClientFactory; import net.i2p.client.I2PSession; import net.i2p.client.I2PSessionException; -import net.i2p.client.I2PSessionListener; +import net.i2p.client.I2PSessionMuxedListener; import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; @@ -135,7 +135,7 @@ abstract class SAMMessageSession { * Handle a new received message * @param msg Message payload */ - protected abstract void messageReceived(byte[] msg); + protected abstract void messageReceived(byte[] msg, int proto, int fromPort, int toPort); /** * Do whatever is needed to shutdown the SAM session @@ -157,7 +157,7 @@ abstract class SAMMessageSession { * * @author human */ - class SAMMessageSessionHandler implements Runnable, I2PSessionListener { + class SAMMessageSessionHandler implements Runnable, I2PSessionMuxedListener { private final Object runningLock = new Object(); private volatile boolean stillRunning = true; @@ -186,7 +186,7 @@ abstract class SAMMessageSession { if (_log.shouldLog(Log.DEBUG)) _log.debug("I2P session connected"); - session.setSessionListener(this); + session.addMuxedSessionListener(this, I2PSession.PROTO_ANY, I2PSession.PORT_ANY); } /** @@ -217,6 +217,7 @@ abstract class SAMMessageSession { _log.debug("Shutting down SAM message-based session handler"); shutDown(); + session.removeListener(I2PSession.PROTO_ANY, I2PSession.PORT_ANY); try { if (_log.shouldLog(Log.DEBUG)) @@ -242,7 +243,15 @@ abstract class SAMMessageSession { stopRunning(); } - public void messageAvailable(I2PSession session, int msgId, long size){ + public void messageAvailable(I2PSession session, int msgId, long size) { + messageAvailable(session, msgId, size, I2PSession.PROTO_UNSPECIFIED, + I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); + } + + /** @since 0.9.22 */ + public void messageAvailable(I2PSession session, int msgId, long size, + int proto, int fromPort, int toPort) { + if (_log.shouldLog(Log.DEBUG)) { _log.debug("I2P message available (id: " + msgId + "; size: " + size + ")"); @@ -256,7 +265,7 @@ abstract class SAMMessageSession { + HexDump.dump(msg)); } - messageReceived(msg); + messageReceived(msg, proto, fromPort, toPort); } catch (I2PSessionException e) { _log.error("Error fetching I2P message", e); stopRunning(); diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java b/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java index 96ebe45d082102ffd98e4a35d1062a498fcfd5cd..564f95c3d8b39e53b2a20c07f3f4b1d5eac95d1f 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawReceiver.java @@ -20,9 +20,12 @@ interface SAMRawReceiver { * regarding the sender. * * @param data Byte array to be received + * @param proto I2CP protocol + * @param fromPort I2CP from port + * @param toPort I2CP to port * @throws IOException */ - public void receiveRawBytes(byte data[]) throws IOException; + public void receiveRawBytes(byte data[], int proto, int fromPort, int toPort) throws IOException; /** * Stop receiving data. diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java index e3c42160834a7f46fd736f33d779b4472ce9bae4..666d87049cbe6ec7afa8d3d461c06332d410c1fe 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java @@ -80,9 +80,9 @@ class SAMRawSession extends SAMMessageSession { I2PSession.PORT_UNSPECIFIED, I2PSession.PORT_UNSPECIFIED); } - protected void messageReceived(byte[] msg) { + protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) { try { - recv.receiveRawBytes(msg); + recv.receiveRawBytes(msg, proto, fromPort, toPort); } catch (IOException e) { _log.error("Error forwarding message to receiver", e); close(); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java index cf4d46b62e63cd35bf5bf545bfcecd18d24b0760..85322d76b24d1da6b49c9feefb7cdd59632d8d51 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv1Handler.java @@ -796,16 +796,21 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece } // SAMRawReceiver implementation - public void receiveRawBytes(byte data[]) throws IOException { + public void receiveRawBytes(byte data[], int proto, int fromPort, int toPort) throws IOException { if (getRawSession() == null) { _log.error("BUG! Received raw bytes, but session is null!"); return; } - ByteArrayOutputStream msg = new ByteArrayOutputStream(); + ByteArrayOutputStream msg = new ByteArrayOutputStream(64 + data.length); - String msgText = "RAW RECEIVED SIZE=" + data.length + "\n"; + String msgText = "RAW RECEIVED SIZE=" + data.length; msg.write(DataHelper.getASCII(msgText)); + if ((verMajor == 3 && verMinor >= 2) || verMajor > 3) { + msgText = " PROTOCOL=" + proto + " FROM_PORT=" + fromPort + " TO_PORT=" + toPort; + msg.write(DataHelper.getASCII(msgText)); + } + msg.write((byte) '\n'); msg.write(data); if (_log.shouldLog(Log.DEBUG)) @@ -832,17 +837,23 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece } // SAMDatagramReceiver implementation - public void receiveDatagramBytes(Destination sender, byte data[]) throws IOException { + public void receiveDatagramBytes(Destination sender, byte data[], int proto, + int fromPort, int toPort) throws IOException { if (getDatagramSession() == null) { _log.error("BUG! Received datagram bytes, but session is null!"); return; } - ByteArrayOutputStream msg = new ByteArrayOutputStream(); + ByteArrayOutputStream msg = new ByteArrayOutputStream(100 + data.length); String msgText = "DATAGRAM RECEIVED DESTINATION=" + sender.toBase64() - + " SIZE=" + data.length + "\n"; + + " SIZE=" + data.length; msg.write(DataHelper.getASCII(msgText)); + if ((verMajor == 3 && verMinor >= 2) || verMajor > 3) { + msgText = " FROM_PORT=" + fromPort + " TO_PORT=" + toPort; + msg.write(DataHelper.getASCII(msgText)); + } + msg.write((byte) '\n'); if (_log.shouldLog(Log.DEBUG)) _log.debug("sending to client: " + msgText); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java index a16c92327fe23cc2f055d850a3ab48cd08a546a9..268083b6384d67bb0f806421dbd51f515046d7d6 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramSession.java @@ -71,11 +71,18 @@ class SAMv3DatagramSession extends SAMDatagramSession implements SAMv3Handler.Se } } - public void receiveDatagramBytes(Destination sender, byte[] data) throws IOException { + public void receiveDatagramBytes(Destination sender, byte[] data, int proto, + int fromPort, int toPort) throws IOException { if (this.clientAddress==null) { - this.handler.receiveDatagramBytes(sender, data); + this.handler.receiveDatagramBytes(sender, data, proto, fromPort, toPort); } else { - String msg = sender.toBase64()+"\n"; + StringBuilder buf = new StringBuilder(600); + buf.append(sender.toBase64()); + if ((handler.verMajor == 3 && handler.verMinor >= 2) || handler.verMajor > 3) { + buf.append(" FROM_PORT=").append(fromPort).append(" TO_PORT=").append(toPort); + } + buf.append('\n'); + String msg = buf.toString(); ByteBuffer msgBuf = ByteBuffer.allocate(msg.length()+data.length); msgBuf.put(DataHelper.getASCII(msg)); msgBuf.put(data); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index 5e75dcf661d485c1fa1b94e8a54683b122dfa849..445f8d10aeede59188ccb1ced769ff17dbad060f 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -50,7 +50,7 @@ class SAMv3Handler extends SAMv1Handler public static final SessionsDB sSessionsHash = new SessionsDB(); private volatile boolean stolenSocket; private volatile boolean streamForwardingSocket; - + private final boolean sendPorts; interface Session { String getNick(); @@ -88,6 +88,7 @@ class SAMv3Handler extends SAMv1Handler Properties i2cpProps, SAMBridge parent) throws SAMException, IOException { super(s, verMajor, verMinor, i2cpProps, parent); + sendPorts = (verMajor == 3 && verMinor >= 2) || verMajor > 3; if (_log.shouldLog(Log.DEBUG)) _log.debug("SAM version 3 handler instantiated"); } @@ -808,7 +809,7 @@ class SAMv3Handler extends SAMv1Handler try { try { streamForwardingSocket = true ; - ((SAMv3StreamSession)streamSession).startForwardingIncoming(props); + ((SAMv3StreamSession)streamSession).startForwardingIncoming(props, sendPorts); notifyStreamResult( true, "OK", null ); return true ; } catch (SAMException e) { @@ -858,13 +859,18 @@ class SAMv3Handler extends SAMv1Handler } } - public void notifyStreamIncomingConnection(Destination d) throws IOException { + public void notifyStreamIncomingConnection(Destination d, int fromPort, int toPort) throws IOException { if (getStreamSession() == null) { _log.error("BUG! Received stream connection, but session is null!"); throw new NullPointerException("BUG! STREAM session is null!"); } - - if (!writeString(d.toBase64() + "\n")) { + StringBuilder buf = new StringBuilder(600); + buf.append(d.toBase64()); + if (sendPorts) { + buf.append(" FROM_PORT=").append(fromPort).append(" TO_PORT=").append(toPort); + } + buf.append('\n'); + if (!writeString(buf.toString())) { throw new IOException("Error notifying connection to SAM client"); } } @@ -874,6 +880,14 @@ class SAMv3Handler extends SAMv1Handler throw new IOException("Error notifying connection to SAM client"); } } + + /** @since 0.9.22 */ + public static void notifyStreamIncomingConnection(SocketChannel client, Destination d, + int fromPort, int toPort) throws IOException { + if (!writeString(d.toBase64() + " FROM_PORT=" + fromPort + " TO_PORT=" + toPort + '\n', client)) { + throw new IOException("Error notifying connection to SAM client"); + } + } } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java index 90eae76f9315f5e71bf4e7d1574bb1b332c78b1f..a228a89437c615bf6fa5d236a7f852edef188039 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3RawSession.java @@ -77,9 +77,9 @@ class SAMv3RawSession extends SAMRawSession implements SAMv3Handler.Session, SA } } - public void receiveRawBytes(byte[] data) throws IOException { + public void receiveRawBytes(byte[] data, int proto, int fromPort, int toPort) throws IOException { if (this.clientAddress==null) { - this.handler.receiveRawBytes(data); + this.handler.receiveRawBytes(data, proto, fromPort, toPort); } else { ByteBuffer msgBuf = ByteBuffer.allocate(data.length); msgBuf.put(data); diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java index fe9561cedbc4fca9edcb31dc4d6ec77753705441..544635aae59e7a18406b676e4c7f2f9b0efc05f5 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java @@ -166,9 +166,10 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi if ( rec==null || i2ps==null ) throw new InterruptedIOException() ; - if (verbose) - handler.notifyStreamIncomingConnection(i2ps.getPeerDestination()) ; - + if (verbose) { + handler.notifyStreamIncomingConnection(i2ps.getPeerDestination(), + i2ps.getPort(), i2ps.getLocalPort()); + } handler.stealSocket() ; ReadableByteChannel fromClient = handler.getClientSocket(); ReadableByteChannel fromI2P = Channels.newChannel(i2ps.getInputStream()); @@ -185,7 +186,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi } - public void startForwardingIncoming( Properties props ) throws SAMException, InterruptedIOException + public void startForwardingIncoming(Properties props, boolean sendPorts) throws SAMException, InterruptedIOException { SAMv3Handler.SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick); boolean verbose = props.getProperty("SILENT", "false").equals("false"); @@ -218,7 +219,7 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi this.socketServer = this.socketMgr.getServerSocket(); } - SocketForwarder forwarder = new SocketForwarder(host, port, this, verbose); + SocketForwarder forwarder = new SocketForwarder(host, port, this, verbose, sendPorts); (new Thread(rec.getThreadGroup(), forwarder, "SAMV3StreamForwarder")).start(); } @@ -227,13 +228,14 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi private final String host; private final int port; private final SAMv3StreamSession session; - private final boolean verbose; + private final boolean verbose, sendPorts; - SocketForwarder(String host, int port, SAMv3StreamSession session, boolean verbose) { + SocketForwarder(String host, int port, SAMv3StreamSession session, boolean verbose, boolean sendPorts) { this.host = host ; this.port = port ; this.session = session ; this.verbose = verbose ; + this.sendPorts = sendPorts; } public void run() @@ -264,9 +266,16 @@ class SAMv3StreamSession extends SAMStreamSession implements SAMv3Handler.Sessi // build pipes between both sockets try { clientServerSock.socket().setKeepAlive(true); - if (this.verbose) - SAMv3Handler.notifyStreamIncomingConnection( + if (this.verbose) { + if (sendPorts) { + SAMv3Handler.notifyStreamIncomingConnection( + clientServerSock, i2ps.getPeerDestination(), + i2ps.getPort(), i2ps.getLocalPort()); + } else { + SAMv3Handler.notifyStreamIncomingConnection( clientServerSock, i2ps.getPeerDestination()); + } + } ReadableByteChannel fromClient = clientServerSock ; ReadableByteChannel fromI2P = Channels.newChannel(i2ps.getInputStream()); WritableByteChannel toClient = clientServerSock ;