forked from I2P_Developers/i2p.i2p
Compare commits
10 Commits
i2p.i2p.2.
...
i2ptunnel-
Author | SHA1 | Date | |
---|---|---|---|
ab7d2ae8b4 | |||
17ad0900c2 | |||
87fb1b6faf | |||
1d78534c38 | |||
5671e1f686 | |||
e105294717 | |||
38208bab49 | |||
13bcc1fd75 | |||
1d8fff9632 | |||
3e22dc329a |
@ -43,6 +43,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -78,6 +79,7 @@ import net.i2p.i2ptunnel.socks.I2PSOCKSIRCTunnel;
|
||||
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
|
||||
import net.i2p.i2ptunnel.streamr.StreamrConsumer;
|
||||
import net.i2p.i2ptunnel.streamr.StreamrProducer;
|
||||
import net.i2p.i2ptunnel.udpTunnel.I2PTunnelUDPClient;
|
||||
import net.i2p.util.EventDispatcherImpl;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
@ -457,6 +459,12 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
runStreamrClient(args, l);
|
||||
} else if ("streamrserver".equals(cmdname)) {
|
||||
runStreamrServer(args, l);
|
||||
} else if ("udpclient".equals(cmdname)) {
|
||||
runUDPClient(args, l);
|
||||
} else if ("udpserver".equals(cmdname)) {
|
||||
runUDPServer(args, l);
|
||||
} else if ("udppeer".equals(cmdname)) {
|
||||
runUDPPeer(args, l);
|
||||
} else if ("config".equals(cmdname)) {
|
||||
runConfig(args, l);
|
||||
} else if ("listen_on".equals(cmdname)) {
|
||||
@ -1361,6 +1369,60 @@ public class I2PTunnel extends EventDispatcherImpl implements Logging {
|
||||
}
|
||||
}
|
||||
|
||||
public void runUDPClient(String args[], Logging l) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(getPrefix() + "Running UDP client with args" + Arrays.toString(args));
|
||||
if (args.length == 3) {
|
||||
InetAddress _host;
|
||||
try {
|
||||
_host = InetAddress.getByName(args[0]);
|
||||
} catch (UnknownHostException uhe) {
|
||||
l.log("unknown host");
|
||||
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
|
||||
notifyEvent("udptunnelTaskId", Integer.valueOf(-1));
|
||||
return;
|
||||
}
|
||||
|
||||
int _port = -1;
|
||||
try {
|
||||
_port = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
l.log("invalid port");
|
||||
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
|
||||
notifyEvent("udptunnelTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
if (_port <= 0)
|
||||
throw new IllegalArgumentException(getPrefix() + "Bad port " + args[0]);
|
||||
|
||||
try {
|
||||
I2PTunnelUDPClient task = new I2PTunnelUDPClient(_host.getHostAddress(), _port, args[2], l, this, this);
|
||||
//(lhost, lport, destina, l, notifyThis, tunnel)
|
||||
task.startRunning();
|
||||
addtask(task);
|
||||
notifyEvent("udptunnelTaskId", Integer.valueOf(task.getId()));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
String msg = "Invalid I2PTunnel configuration to create a UDP Client connecting to the router at " + host + ':'+ port +
|
||||
" and sending to " + _host + ':' + _port;
|
||||
_log.error(getPrefix() + msg, iae);
|
||||
l.log(msg);
|
||||
notifyEvent("udptunnnelTaskId", Integer.valueOf(-1));
|
||||
throw iae;
|
||||
}
|
||||
} else {
|
||||
l.log("udpclient <host> <port> <destination>\n" +
|
||||
" creates a tunnel that receives UDP data.");
|
||||
notifyEvent("udptunnelTaskId", Integer.valueOf(-1));
|
||||
}
|
||||
}
|
||||
|
||||
public void runUDPServer(String args[], Logging l) {
|
||||
|
||||
}
|
||||
|
||||
public void runUDPPeer(String args[], Logging l) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the i2cp host and port
|
||||
* Deprecated - only used by CLI
|
||||
|
@ -166,6 +166,9 @@ public class TunnelController implements Logging {
|
||||
public static final String TYPE_STREAMR_CLIENT = "streamrclient";
|
||||
/** Server in the UI and I2P side but a client on the localhost side */
|
||||
public static final String TYPE_STREAMR_SERVER = "streamrserver";
|
||||
public static final String TYPE_UDP_CLIENT = "udpclient";
|
||||
public static final String TYPE_UDP_SERVER = "udpserver";
|
||||
public static final String TYPE_UDP_PEER = "udppeer";
|
||||
|
||||
/**
|
||||
* This is guaranteed to be available.
|
||||
@ -482,6 +485,8 @@ public class TunnelController implements Logging {
|
||||
startClient();
|
||||
} else if (TYPE_STREAMR_CLIENT.equals(type)) {
|
||||
startStreamrClient();
|
||||
} else if (TYPE_UDP_CLIENT.equals(type)) {
|
||||
startUDPClient();
|
||||
} else if (TYPE_STD_SERVER.equals(type)) {
|
||||
startServer();
|
||||
} else if (TYPE_HTTP_SERVER.equals(type)) {
|
||||
@ -492,6 +497,10 @@ public class TunnelController implements Logging {
|
||||
startIrcServer();
|
||||
} else if (TYPE_STREAMR_SERVER.equals(type)) {
|
||||
startStreamrServer();
|
||||
} else if (TYPE_UDP_SERVER.equals(type)) {
|
||||
startUDPServer();
|
||||
} else if (TYPE_UDP_PEER.equals(type)) {
|
||||
startUDPPeer();
|
||||
} else {
|
||||
changeState(TunnelState.STOPPED);
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
@ -605,6 +614,47 @@ public class TunnelController implements Logging {
|
||||
_tunnel.runStreamrServer(new String[] { listenPort, privKeyFile }, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* UDP client is a UDP server, use the listenPort field for targetPort
|
||||
*/
|
||||
private void startUDPClient() {
|
||||
String targetHost = getTargetHost();
|
||||
String targetPort = getListenPort();
|
||||
String dest = getTargetDestination();
|
||||
_tunnel.runUDPClient(new String[] { targetHost, targetPort, dest }, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP server is a UDP client, use the targetPort field for listenPort
|
||||
*/
|
||||
private void startUDPServer() {
|
||||
String listenOn = getListenOnInterface();
|
||||
if ( (listenOn != null) && (listenOn.length() > 0) ) {
|
||||
_tunnel.runListenOn(new String[] { listenOn }, this);
|
||||
}
|
||||
String listenPort = getTargetPort();
|
||||
String privKeyFile = getPrivKeyFile();
|
||||
_tunnel.runUDPServer(new String[] { listenPort, privKeyFile }, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* UDP peer is a UDP client on one port, and a UDP server on
|
||||
* another, sort of like HTTP Bidirectional.
|
||||
* use the targetPort field for server listenPort
|
||||
* and the listenOn field for the client listenPort
|
||||
*/
|
||||
private void startUDPPeer() {
|
||||
String listenOn = getListenOnInterface();
|
||||
if ( (listenOn != null) && (listenOn.length() > 0) ) {
|
||||
_tunnel.runListenOn(new String[] { listenOn }, this);
|
||||
}
|
||||
String listenPort = getTargetPort();
|
||||
String targetHost = getTargetHost();
|
||||
String targetPort = getListenPort();
|
||||
String privKeyFile = getPrivKeyFile();
|
||||
_tunnel.runUDPPeer(new String[] { listenPort, targetHost, targetPort, privKeyFile }, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note the fact that we are using some sessions, so that they dont get
|
||||
* closed by some other tunnels
|
||||
@ -1076,6 +1126,7 @@ public class TunnelController implements Logging {
|
||||
TYPE_SOCKS_IRC.equals(type) ||
|
||||
TYPE_CONNECT.equals(type) ||
|
||||
TYPE_STREAMR_CLIENT.equals(type) ||
|
||||
TYPE_UDP_CLIENT.equals(type) ||
|
||||
TYPE_IRC_CLIENT.equals(type);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,204 @@
|
||||
package net.i2p.i2ptunnel.udpTunnel;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.client.streaming.I2PSocketAddress;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
import net.i2p.i2ptunnel.Logging;
|
||||
//import net.i2p.i2ptunnel.streamr.Pinger;
|
||||
import net.i2p.i2ptunnel.udp.UDPSink;
|
||||
import net.i2p.i2ptunnel.udp.UDPSource;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* Client side(I2PTunnelUDPClient.java):
|
||||
*
|
||||
* - permanent DatagramSocket at e.g. localhost:5353
|
||||
* - For EVERY incoming IP datagram request, assign a new I2CP source port,
|
||||
* store the source IP/port in a table keyed by the I2CP source port
|
||||
* - send a REPLIABLE datagram to the server with the I2CP source port
|
||||
*
|
||||
* Server side(I2PTunnelUDPServerClient.java):
|
||||
*
|
||||
* - receive request, store source I2P Dest/port associated with the request
|
||||
* - For EVERY incoming I2P datagram request, open a NEW DatagramSocket on
|
||||
* localhost with an EPHEMERAL port. Send the request out the socket and wait
|
||||
* for a single reply.
|
||||
* - Send reply as a RAW datagram to the stored I2P Dest/port. and CLOSE the
|
||||
* DatagramSocket.
|
||||
*
|
||||
* Client side:
|
||||
*
|
||||
* - receive reply on the destination I2CP port. Look up source IP/port in the
|
||||
* table by the destination I2CP port.
|
||||
* - Send reply to the stored IP/port, and remove entry from table.
|
||||
*
|
||||
* @author idk
|
||||
*/
|
||||
|
||||
public class I2PTunnelUDPClient extends I2PTunnelUDPClientBase implements Runnable {
|
||||
private final Log _log = new Log(I2PTunnelUDPClient.class);
|
||||
private final static int MAX_DATAGRAM_SIZE = 31744;
|
||||
private final Destination _remoteDestination;
|
||||
|
||||
// UDP Side
|
||||
// permanent DatagramSocket at e.g. localhost:5353
|
||||
private final DatagramSocket _localSocket;
|
||||
// InetAddress corresponding to local DatagramSocket
|
||||
private final InetAddress _localAddress;
|
||||
// UDP port corresponding to local DatagramSocket
|
||||
private final int _localPort;
|
||||
//private final int UDP_PORT;
|
||||
//private final int MAX_SIZE = 1024;
|
||||
private final UDPSink _sink;
|
||||
private final UDPSource _source;
|
||||
private final Thread thread;
|
||||
|
||||
// SourceIP/Port table
|
||||
private Map<Integer, InetSocketAddress> _sourceIPPortTable = new HashMap<>();
|
||||
private class outboundRequest {
|
||||
public final InetAddress _sourceAddress;
|
||||
public final int _i2cpSourcePort;
|
||||
public final byte[] _request;
|
||||
public int length() {
|
||||
return _request.length;
|
||||
}
|
||||
public int sendRequestToI2PServer() {
|
||||
try {
|
||||
//DatagramPacket packet = new DatagramPacket(_request, _request.length, _serverAddress, _serverPort);
|
||||
//send(packet);
|
||||
|
||||
send(_remoteDestination, _i2cpSourcePort, 0, _request);
|
||||
return _i2cpSourcePort;
|
||||
} catch (Exception e) {
|
||||
_log.error("Error sending request to I2PServer", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public outboundRequest(InetAddress sourceAddress, int sourcePort, byte[] request) {
|
||||
_sourceAddress = sourceAddress;
|
||||
_i2cpSourcePort = sourcePort;
|
||||
_request = request;
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor, host is localhost(usually) or the host of the UDP client, port
|
||||
// is the port of the UDP client
|
||||
public I2PTunnelUDPClient(String localhost, int localport, String destination, Logging l, EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) {
|
||||
super(destination, l, notifyThis, tunnel);
|
||||
_log.debug("I2PTunnelUDPClient: " + localhost + ":" + localport + " -> " + destination);
|
||||
this.thread = new I2PAppThread(this);
|
||||
try {
|
||||
this._localAddress = InetAddress.getByName(localhost);
|
||||
this._localPort = localport;
|
||||
} catch (Exception e) {
|
||||
_log.error("I2PTunnelUDPClient: " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
this._localSocket = new DatagramSocket(new InetSocketAddress(_localAddress, _localPort));
|
||||
} catch (Exception e) {
|
||||
_log.error("I2PTunnelUDPClient: " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
this._remoteDestination = new Destination(destination);
|
||||
} catch (Exception e) {
|
||||
_log.error("I2PTunnelUDPClient: " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
_sink = new UDPSink(this._localSocket, this._localAddress, this._localPort);
|
||||
//_localSocket, _remoteDestination, _log, notifyThis, tunnel);
|
||||
//_sink.start();
|
||||
this._source = new UDPSource(this._localSocket);
|
||||
this.setSink(this._sink);
|
||||
}
|
||||
|
||||
private DatagramPacket readDatagramFromLocalSocket() {
|
||||
byte[] buf = new byte[MAX_DATAGRAM_SIZE];
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
try {
|
||||
_localSocket.receive(packet);
|
||||
if (_log.shouldLog(Log.DEBUG)){
|
||||
_log.debug("I2PTunnelUDPClient: readDatagramFromLocalSocket: " + packet.getLength() + " bytes from " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
_log.error("I2PTunnelUDPClient: " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private outboundRequest readOutboundRequestFromLocalDatagram(){
|
||||
DatagramPacket packet = readDatagramFromLocalSocket();
|
||||
if (_log.shouldLog(Log.DEBUG)){
|
||||
_log.debug("I2PTunnelUDPClient: readOutboundRequestFromLocalDatagram: " + packet.getLength() + " bytes from " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
||||
}
|
||||
InetAddress sourceAddress = packet.getAddress();
|
||||
if (_log.shouldLog(Log.DEBUG)){
|
||||
_log.debug("I2PTunnelUDPClient: readOutboundRequestFromLocalDatagram: " + sourceAddress.getHostAddress() + ":" + packet.getPort());
|
||||
}
|
||||
int sourcePort = newI2CPSourcePort();
|
||||
if (_log.shouldLog(Log.DEBUG)){
|
||||
_log.debug("I2PTunnelUDPClient: readOutboundRequestFromLocalDatagram: " + sourcePort);
|
||||
}
|
||||
byte[] request = packet.getData();
|
||||
if (_log.shouldLog(Log.DEBUG)){
|
||||
_log.debug("I2PTunnelUDPClient: readOutboundRequestFromLocalDatagram: " + request.length);
|
||||
}
|
||||
return new outboundRequest(sourceAddress, sourcePort, request);
|
||||
}
|
||||
|
||||
private int sendOutboundRequest(){
|
||||
outboundRequest request = readOutboundRequestFromLocalDatagram();
|
||||
int i2cpSourcePort = request.sendRequestToI2PServer();
|
||||
_sourceIPPortTable.put(i2cpSourcePort, new InetSocketAddress(_localSocket.getInetAddress(), _localSocket.getPort()));
|
||||
return request.sendRequestToI2PServer();
|
||||
}
|
||||
|
||||
private int newI2CPSourcePort() {
|
||||
int randomPort = (int) (Math.random() * 55535);
|
||||
while (_sourceIPPortTable.containsKey(randomPort)) {
|
||||
randomPort = (int) (Math.random() * 55535);
|
||||
}
|
||||
return randomPort+10000;
|
||||
}
|
||||
|
||||
private void recieveInboundResponse() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void startRunning() {
|
||||
_log.logAlways(Log.INFO, "UDP Client is starting");
|
||||
super.startRunning();
|
||||
_log.logAlways(Log.INFO, "UDP Client is nearly started");
|
||||
this.thread.start();
|
||||
_log.logAlways(Log.INFO, "UDP Client is ready");
|
||||
}
|
||||
|
||||
public void run() {
|
||||
_log.logAlways(Log.INFO, "UDP Client is running");
|
||||
while (true) {
|
||||
int i2cpPortSent = this.sendOutboundRequest();
|
||||
_log.debug("I2PTunnelUDPClient: sent outbound request to I2PServer, i2cpPortSent: " + i2cpPortSent);
|
||||
//this.receive();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(boolean forced) {
|
||||
return super.close(forced);
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
package net.i2p.i2ptunnel.udpTunnel;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.client.streaming.I2PSocketAddress;
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
import net.i2p.i2ptunnel.Logging;
|
||||
import net.i2p.i2ptunnel.udp.UDPSink;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* Client side(I2PTunnelUDPClient.java):
|
||||
*
|
||||
* - permanent DatagramSocket at e.g. localhost:5353
|
||||
* - For EVERY incoming IP datagram request, assign a new I2CP source port,
|
||||
* store the source IP/port in a table keyed by the I2CP source port
|
||||
* - send a REPLIABLE datagram to the server with the I2CP source port
|
||||
*
|
||||
* Server side(I2PTunnelUDPServer.java):
|
||||
*
|
||||
* - receive request, store source I2P Dest/port associated with the request
|
||||
* - For EVERY incoming I2P datagram request, open a NEW DatagramSocket on
|
||||
* localhost with an EPHEMERAL port. Send the request out the socket and wait
|
||||
* for a single reply.
|
||||
* - Send reply as a RAW datagram to the stored I2P Dest/port. and CLOSE the
|
||||
* DatagramSocket.
|
||||
*
|
||||
* Client side(I2PTunnelUDPClient.java):
|
||||
*
|
||||
* - receive reply on the destination I2CP port. Look up source IP/port in the
|
||||
* table by the destination I2CP port.
|
||||
* - Send reply to the stored IP/port, and remove entry from table.
|
||||
*
|
||||
* @author idk
|
||||
*/
|
||||
|
||||
public class I2PTunnelUDPServer extends I2PTunnelUDPServerBase {
|
||||
private final static int MAX_DATAGRAM_SIZE = 31744;
|
||||
private final Log _log = new Log(I2PTunnelUDPServer.class);
|
||||
private final InetAddress _localAddress;
|
||||
private final int _localPort;
|
||||
private Map<Integer, inboundDatagram> _sourceIPPortTable = new HashMap<Integer, inboundDatagram>();
|
||||
|
||||
// outboundReply sends a DatagramPacket to the client over I2P
|
||||
private class outboundReply {
|
||||
public final I2PSocketAddress _destination;
|
||||
public final int _destinationPort; // I2CP source port
|
||||
public final byte[] _reply;
|
||||
public int length() {
|
||||
return _reply.length;
|
||||
}
|
||||
public void sendReplyToI2PClient() {
|
||||
try {
|
||||
_log.debug("Sending reply to I2P client");
|
||||
//_socket.send(_reply);
|
||||
} catch (Exception e) {
|
||||
_log.error("Error sending reply to I2P client", e);
|
||||
}
|
||||
}
|
||||
public outboundReply(I2PSocketAddress destination, int destinationPort, byte[] reply) {
|
||||
_destination = destination;
|
||||
_destinationPort = destinationPort;
|
||||
_reply = reply;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// inboundDatagram stores the source IP/port associated with a request recieved from I2P
|
||||
// and forwards it to a UDP socket on the localhost.
|
||||
private class inboundDatagram {
|
||||
public final I2PSocketAddress _destination;
|
||||
public final int _i2cpPort;
|
||||
public final byte[] _request;
|
||||
public final DatagramSocket socket;
|
||||
public int length() {
|
||||
return _request.length;
|
||||
}
|
||||
// sends the datagram to the local UDP socket, reads a single reply, then closes the DatagramSocket
|
||||
public outboundReply sendRequestToLocalhost() {
|
||||
//construct a datagram packet
|
||||
DatagramPacket packet = new DatagramPacket(_request, _request.length, _localAddress, _localPort);
|
||||
try {
|
||||
socket.send(packet);
|
||||
} catch (Exception e) {
|
||||
_log.error("Error sending datagram", e);
|
||||
}
|
||||
//read the reply
|
||||
byte[] reply = new byte[MAX_DATAGRAM_SIZE];
|
||||
DatagramPacket replyPacket = new DatagramPacket(reply, reply.length);
|
||||
try {
|
||||
socket.receive(replyPacket);
|
||||
} catch (Exception e) {
|
||||
_log.error("Error receiving datagram", e);
|
||||
}
|
||||
//close the socket
|
||||
socket.close();
|
||||
//construct the outbound reply
|
||||
return new outboundReply(_destination, _i2cpPort, reply);
|
||||
}
|
||||
public inboundDatagram(I2PSocketAddress dest, int i2cpPort, byte[] data) {
|
||||
this._destination = dest;
|
||||
this._i2cpPort = i2cpPort;
|
||||
this._request = data;
|
||||
// create a new DatagramSocket with an EPHEMERAL port
|
||||
try {
|
||||
this.socket = new DatagramSocket();
|
||||
} catch (Exception e) {
|
||||
_log.error("Error creating DatagramSocket", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Constructor, host is localhost(usually) or the host of the UDP client, port
|
||||
// is the port of the UDP client
|
||||
public I2PTunnelUDPServer(String host, int port, File privKeyFile, String privKeyPath, Logging l, EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) {
|
||||
super(privKeyFile, privKeyPath, l, notifyThis, tunnel);
|
||||
try {
|
||||
_localAddress = InetAddress.getByName(host);
|
||||
} catch (Exception e) {
|
||||
_log.error("Error getting InetAddress for host: " + host, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
_localPort = port;
|
||||
}
|
||||
|
||||
//private inboundDatagram receiveInboundI2PDatagram() {
|
||||
|
||||
//}
|
||||
|
||||
@Override
|
||||
public final void startRunning() {
|
||||
super.startRunning();
|
||||
while (true) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(boolean forced) {
|
||||
return super.close(forced);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package net.i2p.i2ptunnel.udpTunnel;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
import net.i2p.i2ptunnel.I2PTunnelTask;
|
||||
import net.i2p.i2ptunnel.Logging;
|
||||
import net.i2p.i2ptunnel.udp.Sink;
|
||||
import net.i2p.i2ptunnel.udp.Source;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
* * Client side:
|
||||
*
|
||||
* - permanent DatagramSocket at e.g. localhost:5353
|
||||
* - For EVERY incoming IP datagram request, assign a new I2CP source port,
|
||||
* store the source IP/port in a table keyed by the I2CP source port
|
||||
* - send a REPLIABLE datagram to the server with the I2CP source port
|
||||
*
|
||||
* Server side:
|
||||
*
|
||||
* - receive request, store source I2P Dest/port associated with the request
|
||||
* - For EVERY incoming I2P datagram request, open a NEW DatagramSocket on
|
||||
* localhost with an EPHEMERAL port. Send the request out the socket and wait
|
||||
* for a single reply.
|
||||
* - Send reply as a RAW datagram to the stored I2P Dest/port. and CLOSE the
|
||||
* DatagramSocket.
|
||||
*
|
||||
* Client side:
|
||||
*
|
||||
* - receive reply on the destination I2CP port. Look up source IP/port in the
|
||||
* table by the destination I2CP port.
|
||||
* - Send reply to the stored IP/port, and remove entry from table.
|
||||
*
|
||||
* @author idk
|
||||
*/
|
||||
public class I2PTunnelUDPServerClient extends I2PTunnelTask implements Source, Sink {
|
||||
private final Log _log = new Log(I2PTunnelUDPServerClient.class);
|
||||
|
||||
public I2PTunnelUDPServerClient(String host, int port, File privkey, String privkeyname, Logging l,
|
||||
EventDispatcher notifyThis,
|
||||
I2PTunnel tunnel) {
|
||||
super("UDPPeer <- " + privkeyname, notifyThis, tunnel);
|
||||
//super(privkey, privkeyname, l, notifyThis, tunnel);
|
||||
}
|
||||
|
||||
public final void start() {
|
||||
//super.startRunning();
|
||||
if (_log.shouldInfo())
|
||||
_log.info("I2PTunnelUDPServer server ready");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean close(boolean forced) {
|
||||
return forced;
|
||||
//return super.close(forced);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Destination src, int fromPort, int toPort, byte[] data) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSink(Sink sink) {
|
||||
// TODO
|
||||
}
|
||||
}
|
@ -509,6 +509,7 @@ public class GeneralHelper {
|
||||
String rv;
|
||||
if (TunnelController.TYPE_STD_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_IRC_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(tun.getType()) ||
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(tun.getType()))
|
||||
rv = tun.getTargetDestination();
|
||||
else
|
||||
|
@ -761,6 +761,7 @@ public class TunnelConfig {
|
||||
// override bundle setting set above
|
||||
if (!TunnelController.isClient(_type) &&
|
||||
!TunnelController.TYPE_HTTP_SERVER.equals(_type) &&
|
||||
!TunnelController.TYPE_UDP_SERVER.equals(_type) &&
|
||||
!TunnelController.TYPE_STREAMR_SERVER.equals(_type)) {
|
||||
config.setProperty(TunnelController.OPT_BUNDLE_REPLY, "true");
|
||||
}
|
||||
@ -815,7 +816,9 @@ public class TunnelConfig {
|
||||
|
||||
if (TunnelController.TYPE_IRC_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_STD_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(_type)) {
|
||||
TunnelController.TYPE_STREAMR_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_PEER.equals(_type)) {
|
||||
if (_targetDestination != null)
|
||||
config.setProperty(TunnelController.PROP_DEST, _targetDestination);
|
||||
} else if (TunnelController.TYPE_HTTP_SERVER.equals(_type) ||
|
||||
@ -826,7 +829,9 @@ public class TunnelConfig {
|
||||
if (_otherOptions.containsKey(p))
|
||||
config.setProperty(OPT + p, _otherOptions.get(p));
|
||||
}
|
||||
if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type)) {
|
||||
if (TunnelController.TYPE_HTTP_BIDIR_SERVER.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_SERVER.equals(_type) ||
|
||||
TunnelController.TYPE_UDP_CLIENT.equals(_type) ) {
|
||||
if (_port >= 0)
|
||||
config.setProperty(TunnelController.PROP_LISTEN_PORT, Integer.toString(_port));
|
||||
if (_reachableBy != null)
|
||||
|
@ -75,7 +75,7 @@
|
||||
String phdisabled = (canChangePort && isShared) ? "" : tstopFirst;
|
||||
%>
|
||||
<th colspan="2" <%=phdisabled%>>
|
||||
<% if ("streamrclient".equals(tunnelType)) { %>
|
||||
<% if ("streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) { %>
|
||||
<%=intl._t("Target")%>
|
||||
<% } else { %>
|
||||
<%=intl._t("Access Point")%>
|
||||
@ -98,7 +98,7 @@
|
||||
<input type="text" size="6" maxlength="5" name="port" title="<%=ptext%>" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext port" placeholder="required" <%=pdisabled%>/>
|
||||
</td>
|
||||
<%
|
||||
if ("streamrclient".equals(tunnelType)) {
|
||||
if ("streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) {
|
||||
%>
|
||||
<td>
|
||||
<b><%=intl._t("Host")%>:</b>
|
||||
@ -192,7 +192,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<%
|
||||
} else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "streamrclient".equals(tunnelType)) {
|
||||
} else if ("client".equals(tunnelType) || "ircclient".equals(tunnelType) || "streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) {
|
||||
%>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
@ -210,7 +210,7 @@
|
||||
<input type="text" size="30" id="targetDestination" name="targetDestination" title="<%=intl._t("Specify the .i2p address or destination (b32 or b64) of the tunnel here.")%> <%=intl._t("For a random selection from a pool, separate with commas e.g. server1.i2p,server2.i2p")%>" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext destination" placeholder="required" />
|
||||
<%=intl._t("name, name:port, or destination")%>
|
||||
<%
|
||||
if ("streamrclient".equals(tunnelType)) {
|
||||
if ("streamrclient".equals(tunnelType) || "udpclient".equals(tunnelType)) {
|
||||
/* deferred resolution unimplemented in streamr client */
|
||||
%>
|
||||
- <%=intl._t("b32 not recommended")%>
|
||||
@ -222,7 +222,7 @@
|
||||
<%
|
||||
}
|
||||
|
||||
if (!"streamrclient".equals(tunnelType)) {
|
||||
if (!"streamrclient".equals(tunnelType) && !"udpclient".equals(tunnelType)) {
|
||||
%>
|
||||
<tr>
|
||||
<th colspan="2" <%=phdisabled%>>
|
||||
@ -270,7 +270,7 @@
|
||||
</table>
|
||||
<h3><%=intl._t("Advanced networking options")%></h3>
|
||||
<%
|
||||
if (!"streamrclient".equals(tunnelType) && (canChangePort || isShared)) {
|
||||
if (!"streamrclient".equals(tunnelType) && !"udpclient".equals(tunnelType) && (canChangePort || isShared)) {
|
||||
// no shared client tunnels for streamr
|
||||
// If running and not shared, this doesn't apply.
|
||||
%>
|
||||
@ -393,7 +393,7 @@
|
||||
} // client
|
||||
%>
|
||||
<%
|
||||
if (!"streamrclient".equals(tunnelType)) {
|
||||
if (!"streamrclient".equals(tunnelType) && !"udpclient".equals(tunnelType)) {
|
||||
// streamr client sends pings so it will never be idle
|
||||
%>
|
||||
<tr>
|
||||
|
@ -239,6 +239,7 @@
|
||||
<option value="httpbidirserver">HTTP bidir</option>
|
||||
<option value="ircserver">IRC</option>
|
||||
<option value="streamrserver">Streamr</option>
|
||||
<option value="udpserver">UDP Peer(Server/Client)</option>
|
||||
</select>
|
||||
<input class="control" type="submit" value="<%=intl._t("Create")%>" />
|
||||
</form>
|
||||
@ -381,6 +382,7 @@
|
||||
<option value="socksirctunnel">SOCKS IRC</option>
|
||||
<option value="connectclient">CONNECT</option>
|
||||
<option value="streamrclient">Streamr</option>
|
||||
<option value="udpclient">UDP Peer(Client/Server)</option>
|
||||
</select>
|
||||
<input class="control" type="submit" value="<%=intl._t("Create")%>" />
|
||||
</form>
|
||||
|
Reference in New Issue
Block a user