diff --git a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java index d4f026d98487dddfd1510cd7013dbeacae44a7bd..d49fd45d6bc0729c4b08b85e67b0c9ff1244513b 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMDatagramSession.java @@ -12,6 +12,7 @@ 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; @@ -77,6 +78,7 @@ class SAMDatagramSession extends SAMMessageSession { * * @param dest Destination * @param data Bytes to be sent + * @param proto ignored, will always use PROTO_DATAGRAM (17) * * @return True if the data was sent, false otherwise * @throws DataFormatException on unknown / bad dest @@ -90,7 +92,7 @@ class SAMDatagramSession extends SAMMessageSession { synchronized (dgramMaker) { dgram = dgramMaker.makeI2PDatagram(data); } - return sendBytesThroughMessageSession(dest, dgram, proto, fromPort, toPort); + return sendBytesThroughMessageSession(dest, dgram, I2PSession.PROTO_DATAGRAM, 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 a2ab4a712ddcb61b772e688d61689b0ba194a71d..9dca53ab1c3d8b9690ae42eda34ebc6565f78303 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMMessageSession.java @@ -22,7 +22,7 @@ import net.i2p.client.I2PSessionMuxedListener; import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; -import net.i2p.util.HexDump; +//import net.i2p.util.HexDump; import net.i2p.util.I2PAppThread; import net.i2p.util.Log; @@ -261,10 +261,10 @@ abstract class SAMMessageSession { byte msg[] = session.receiveMessage(msgId); if (msg == null) return; - if (_log.shouldLog(Log.DEBUG)) { - _log.debug("Content of message " + msgId + ":\n" - + HexDump.dump(msg)); - } + //if (_log.shouldLog(Log.DEBUG)) { + // _log.debug("Content of message " + msgId + ":\n" + // + HexDump.dump(msg)); + //} messageReceived(msg, proto, fromPort, toPort); } catch (I2PSessionException e) { diff --git a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java index e31f5950c5455b9151bf8e26b911a81f851b4268..ab1cd76322e36d6ca305510d14b9f0b1f82fffb9 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMRawSession.java +++ b/apps/sam/java/src/net/i2p/sam/SAMRawSession.java @@ -12,6 +12,7 @@ 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; @@ -66,6 +67,7 @@ class SAMRawSession extends SAMMessageSession { * Send bytes through a SAM RAW session. * * @param data Bytes to be sent + * @param proto if 0, will use PROTO_DATAGRAM_RAW (18) * * @return True if the data was sent, false otherwise * @throws DataFormatException on unknown / bad dest @@ -75,6 +77,8 @@ class SAMRawSession extends SAMMessageSession { int fromPort, int toPort) 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); } diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java index b410fb21b01a91a2f72e39be1aa5b2772182b27e..64202c51e4385ebb9fd996a77015016e3caa7ae9 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java @@ -164,6 +164,7 @@ class SAMv3DatagramServer implements Handler { 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; @@ -196,7 +197,7 @@ class SAMv3DatagramServer implements Handler { is.read(data); SAMv3Handler.Session sess = rec.getHandler().getSession(); if (sess != null) - rec.getHandler().getSession().sendBytes(dest,data, proto, fromPort, toPort); + sess.sendBytes(dest, data, proto, fromPort, toPort); else warn("Dropping datagram, no session for " + nick); } else { diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java index 551e686acc0e13c142bcec9df0226f5f95a7298f..7b53429b93f61659fb0bb479a55469effc7530b1 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java @@ -1,10 +1,14 @@ package net.i2p.sam.client; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; import java.net.Socket; import java.security.GeneralSecurityException; import java.util.HashMap; @@ -37,6 +41,7 @@ public class SAMStreamSend { private String _conOptions; private SAMReader _reader, _reader2; private boolean _isV3; + private boolean _isV32; private String _v3ID; //private boolean _dead; /** Connection id (Integer) to peer (Flooder) */ @@ -155,7 +160,7 @@ public class SAMStreamSend { throw new IOException("handshake failed"); if (_log.shouldLog(Log.DEBUG)) _log.debug("Handshake complete. we are " + ourDest); - if (_isV3 && mode != V1DG && mode != V1RAW) { + if (_isV3 && mode == STREAM) { Socket sock2 = connect(isSSL); eventHandler = new SendEventHandler(_context); _reader2 = new SAMReader(_context, sock2.getInputStream(), eventHandler); @@ -169,9 +174,9 @@ public class SAMStreamSend { if (_log.shouldLog(Log.DEBUG)) _log.debug("Handshake2 complete."); } - if (ourDest != null) { - send(out, eventHandler, mode); - } + if (mode == DG || mode == RAW) + out = null; + send(out, eventHandler, mode); } catch (IOException e) { _log.error("Unable to connect to SAM at " + _samHost + ":" + _samPort, e); if (_reader != null) @@ -241,6 +246,7 @@ public class SAMStreamSend { return "OK"; _isV3 = VersionComparator.comp(hisVersion, "3") >= 0; if (_isV3) { + _isV32 = VersionComparator.comp(hisVersion, "3.2") >= 0; byte[] id = new byte[5]; _context.random().nextBytes(id); _v3ID = Base32.encode(id); @@ -307,11 +313,21 @@ public class SAMStreamSend { private final OutputStream _samOut; private final SAMEventHandler _eventHandler; private final int _mode; + private final DatagramSocket _dgSock; + private final InetSocketAddress _dgSAM; - public Sender(OutputStream samOut, SAMEventHandler eventHandler, int mode) { + public Sender(OutputStream samOut, SAMEventHandler eventHandler, int mode) throws IOException { _samOut = samOut; _eventHandler = eventHandler; _mode = mode; + if (mode == DG || mode == RAW) { + // samOut will be null + _dgSock = new DatagramSocket(); + _dgSAM = new InetSocketAddress(_samHost, 7655); + } else { + _dgSock = null; + _dgSAM = null; + } synchronized (_remotePeers) { if (_v3ID != null) _connectionId = _v3ID; @@ -396,22 +412,42 @@ public class SAMStreamSend { _log.debug("Sending " + read + " on " + _connectionId + " after " + (now-lastSend)); lastSend = now; - synchronized (_samOut) { - if (!_isV3 || _mode == V1DG || _mode == V1RAW) { - String m; - if (_mode == STREAM) - m = "STREAM SEND ID=" + _connectionId + " SIZE=" + read + "\n"; - else if (_mode == V1DG) - m = "DATAGRAM SEND DESTINATION=" + _remoteDestination + " SIZE=" + read + "\n"; - else if (_mode == V1RAW) - m = "RAW SEND DESTINATION=" + _remoteDestination + " SIZE=" + read + "\n"; - else - throw new IOException("unsupported mode " + _mode); - byte msg[] = DataHelper.getASCII(m); - _samOut.write(msg); + if (_samOut != null) { + synchronized (_samOut) { + if (!_isV3 || _mode == V1DG || _mode == V1RAW) { + String m; + if (_mode == STREAM) { + m = "STREAM SEND ID=" + _connectionId + " SIZE=" + read + "\n"; + } else if (_mode == V1DG) { + m = "DATAGRAM SEND DESTINATION=" + _remoteDestination + " SIZE=" + read + "\n"; + } else if (_mode == V1RAW) { + m = "RAW SEND DESTINATION=" + _remoteDestination + " SIZE=" + read + "\n"; + } else { + throw new IOException("unsupported mode " + _mode); + } + byte msg[] = DataHelper.getASCII(m); + _samOut.write(msg); + } + _samOut.write(data, 0, read); + _samOut.flush(); } - _samOut.write(data, 0, read); - _samOut.flush(); + } else { + // real datagrams + ByteArrayOutputStream baos = new ByteArrayOutputStream(read + 1024); + baos.write(DataHelper.getASCII("3.0 ")); + baos.write(DataHelper.getASCII(_v3ID)); + baos.write((byte) ' '); + baos.write(DataHelper.getASCII(_remoteDestination)); + if (_isV32) { + // only set TO_PORT to test session setting of FROM_PORT + baos.write(DataHelper.getASCII(" TO_PORT=5678")); + } + baos.write((byte) '\n'); + baos.write(data, 0, read); + byte[] pkt = baos.toByteArray(); + DatagramPacket p = new DatagramPacket(pkt, pkt.length, _dgSAM); + _dgSock.send(p); + try { Thread.sleep(25); } catch (InterruptedException ie) {} } _totalSent += read; @@ -423,23 +459,27 @@ public class SAMStreamSend { } } - if (_isV3) { - try { - _samOut.close(); - } catch (IOException ioe) { - _log.info("Error closing", ioe); - } - } else { - byte msg[] = ("STREAM CLOSE ID=" + _connectionId + "\n").getBytes(); - try { - synchronized (_samOut) { - _samOut.write(msg); - _samOut.flush(); + if (_samOut != null) { + if (_isV3) { + try { _samOut.close(); + } catch (IOException ioe) { + _log.info("Error closing", ioe); + } + } else { + byte msg[] = ("STREAM CLOSE ID=" + _connectionId + "\n").getBytes(); + try { + synchronized (_samOut) { + _samOut.write(msg); + _samOut.flush(); + _samOut.close(); + } + } catch (IOException ioe) { + _log.info("Error closing", ioe); } - } catch (IOException ioe) { - _log.info("Error closing", ioe); } + } else if (_dgSock != null) { + _dgSock.close(); } closed(); diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java index e8682fb512403d9c84e9d439e2ac41e40a79b417..aea68e5516385318da4a2ab0abc22c3d90a4f74c 100644 --- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java +++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java @@ -163,7 +163,7 @@ public class SAMStreamSink { Thread t = new Pinger(out); t.start(); } - if (_isV3 && mode != V1DG && mode != V1RAW) { + if (_isV3 && mode == STREAM) { Socket sock2 = connect(isSSL); out = sock2.getOutputStream(); eventHandler = new SinkEventHandler2(_context, sock2.getInputStream(), out);