package net.i2p.i2ptunnel.socks; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.concurrent.ConcurrentHashMap; import java.util.Map; import net.i2p.data.Destination; import net.i2p.i2ptunnel.udp.*; /** * Implements a UDP port and Socks encapsulation / decapsulation. * This is for a single port. If there is demuxing for multiple * ports, it happens outside of here. * * TX: * UDPSource -> SOCKSUDPUnwrapper -> ReplyTracker ( -> I2PSink in SOCKSUDPTunnel) * * RX: * UDPSink <- SOCKSUDPWrapper ( <- MultiSink <- I2PSource in SOCKSUDPTunnel) * * The Unwrapper passes headers to the Wrapper through a cache. * The ReplyTracker passes sinks to MultiSink through a cache. * * @author zzz */ public class SOCKSUDPPort implements Source, Sink { public SOCKSUDPPort(InetAddress host, int port, Map<Destination, SOCKSUDPPort> replyMap) { // this passes the host and port from UDPUnwrapper to UDPWrapper Map<Destination, SOCKSHeader> cache = new ConcurrentHashMap<Destination, SOCKSHeader>(4); // rcv from I2P and send to a port this.wrapper = new SOCKSUDPWrapper(cache); this.udpsink = new UDPSink(host, port); this.wrapper.setSink(this.udpsink); // rcv from the same port and send to I2P DatagramSocket sock = this.udpsink.getSocket(); this.udpsource = new UDPSource(sock); this.unwrapper = new SOCKSUDPUnwrapper(cache); this.udpsource.setSink(this.unwrapper); this.udptracker = new ReplyTracker<SOCKSUDPPort>(this, replyMap); this.unwrapper.setSink(this.udptracker); } /** Socks passes this back to the client on the TCP connection */ public int getPort() { return this.udpsink.getPort(); } public void setSink(Sink sink) { this.udptracker.setSink(sink); } public void start() { // the other Sources don't use start this.udpsource.start(); } public void stop() { this.udpsink.stop(); this.udpsource.stop(); } /** * May throw RuntimeException from underlying sink * @throws RuntimeException */ public void send(Destination from, byte[] data) { this.wrapper.send(from, data); } private UDPSink udpsink; private UDPSource udpsource; private SOCKSUDPWrapper wrapper; private SOCKSUDPUnwrapper unwrapper; private ReplyTracker<SOCKSUDPPort> udptracker; }