Added apps/q - the Q distributed file store framework, by aum
This commit is contained in:
452
apps/q/java/src/net/i2p/aum/I2PCat.java
Normal file
452
apps/q/java/src/net/i2p/aum/I2PCat.java
Normal file
@ -0,0 +1,452 @@
|
||||
|
||||
// I2P equivalent of 'netcat'
|
||||
|
||||
package net.i2p.aum;
|
||||
|
||||
import java.lang.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
|
||||
import net.i2p.*;
|
||||
import net.i2p.client.*;
|
||||
import net.i2p.client.naming.*;
|
||||
import net.i2p.client.streaming.*;
|
||||
import net.i2p.data.*;
|
||||
|
||||
import net.i2p.util.*;
|
||||
|
||||
/**
|
||||
* A I2P equivalent of the much-beloved 'netcat' utility.
|
||||
* This command-line utility can either connect to a remote
|
||||
* destination, or listen on a private destination for incoming
|
||||
* connections. Once a connection is established, input on stdin
|
||||
* is sent to the remote peer, and anything received from the
|
||||
* remote peer is printed to stdout
|
||||
*/
|
||||
|
||||
public class I2PCat extends Thread
|
||||
{
|
||||
public I2PSocketManager socketManager;
|
||||
public I2PServerSocket serverSocket;
|
||||
public I2PSocket sessSocket;
|
||||
|
||||
public PrivDestination key;
|
||||
public Destination dest;
|
||||
|
||||
public InputStream socketIn;
|
||||
public OutputStream socketOutStream;
|
||||
public OutputStreamWriter socketOut;
|
||||
|
||||
public SockInput rxThread;
|
||||
|
||||
protected static Log _log;
|
||||
|
||||
public static String defaultHost = "127.0.0.1";
|
||||
public static int defaultPort = 7654;
|
||||
|
||||
/**
|
||||
* a thread for reading from socket and displaying on stdout
|
||||
*/
|
||||
private class SockInput extends Thread {
|
||||
|
||||
InputStream _in;
|
||||
|
||||
protected Log _log;
|
||||
public SockInput(InputStream i) {
|
||||
|
||||
_in = i;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
// the thread portion, receives incoming bytes on
|
||||
// the socket input stream and spits them to stdout
|
||||
|
||||
byte [] ch = new byte[1];
|
||||
|
||||
print("Receiver thread listening...");
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
|
||||
//String line = DataHelper.readLine(socketIn);
|
||||
if (_in.read(ch) != 1) {
|
||||
print("failed to receive from socket");
|
||||
break;
|
||||
}
|
||||
|
||||
//System.out.println(line);
|
||||
System.out.write(ch, 0, 1);
|
||||
System.out.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
print("Receiver thread crashed, terminating!!");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void print(String msg)
|
||||
{
|
||||
System.out.println("-=- I2PCat: "+msg);
|
||||
|
||||
if (_log != null) {
|
||||
_log.debug(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public I2PCat()
|
||||
{
|
||||
_log = new Log("I2PCat");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs I2PCat in server mode, listening on the given destination
|
||||
* for one incoming connection. Once connection is established,
|
||||
* copyies data between the remote peer and
|
||||
* the local terminal console.
|
||||
*/
|
||||
public void runServer(String keyStr) throws IOException, DataFormatException
|
||||
{
|
||||
Properties props = new Properties();
|
||||
props.setProperty("inbound.length", "0");
|
||||
props.setProperty("outbound.length", "0");
|
||||
props.setProperty("inbound.lengthVariance", "0");
|
||||
props.setProperty("outbound.lengthVariance", "0");
|
||||
|
||||
// generate new key if needed
|
||||
if (keyStr.equals("new")) {
|
||||
|
||||
try {
|
||||
key = PrivDestination.newKey();
|
||||
} catch (I2PException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
print("Creating new server dest...");
|
||||
|
||||
socketManager = I2PSocketManagerFactory.createManager(key.getInputStream(), props);
|
||||
|
||||
print("Getting server socket...");
|
||||
|
||||
serverSocket = socketManager.getServerSocket();
|
||||
|
||||
print("Server socket created, ready to run...");
|
||||
|
||||
dest = socketManager.getSession().getMyDestination();
|
||||
|
||||
print("private key follows:");
|
||||
System.out.println(key.toBase64());
|
||||
|
||||
print("dest follows:");
|
||||
System.out.println(dest.toBase64());
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
key = PrivDestination.fromBase64String(keyStr);
|
||||
|
||||
String dest64Abbrev = key.toBase64().substring(0, 16);
|
||||
|
||||
print("Creating server socket manager on dest "+dest64Abbrev+"...");
|
||||
|
||||
socketManager = I2PSocketManagerFactory.createManager(key.getInputStream(), props);
|
||||
|
||||
serverSocket = socketManager.getServerSocket();
|
||||
|
||||
print("Server socket created, ready to run...");
|
||||
}
|
||||
|
||||
print("Awaiting client connection...");
|
||||
|
||||
I2PSocket sessSocket;
|
||||
|
||||
try {
|
||||
sessSocket = serverSocket.accept();
|
||||
} catch (I2PException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (ConnectException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
print("Got connection from client");
|
||||
|
||||
chat(sessSocket);
|
||||
|
||||
}
|
||||
|
||||
public void runClient(String destStr)
|
||||
throws DataFormatException, IOException
|
||||
{
|
||||
runClient(destStr, defaultHost, defaultPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* runs I2PCat in client mode, connecting to a remote
|
||||
* destination then copying data between the remote peer and
|
||||
* the local terminal console
|
||||
*/
|
||||
public void runClient(String destStr, String host, int port)
|
||||
throws DataFormatException, IOException
|
||||
{
|
||||
// accept 'file:' prefix
|
||||
if (destStr.startsWith("file:", 0))
|
||||
{
|
||||
String path = destStr.substring(5);
|
||||
destStr = new SimpleFile(path, "r").read();
|
||||
}
|
||||
|
||||
else if (destStr.length() < 255) {
|
||||
// attempt hosts file lookup
|
||||
I2PAppContext ctx = new I2PAppContext();
|
||||
HostsTxtNamingService h = new HostsTxtNamingService(ctx);
|
||||
Destination dest1 = h.lookup(destStr);
|
||||
if (dest1 == null) {
|
||||
usage("Cannot resolve hostname: '"+destStr+"'");
|
||||
}
|
||||
|
||||
// successful lookup
|
||||
runClient(dest1, host, port);
|
||||
}
|
||||
|
||||
else {
|
||||
// otherwise, bigger strings are assumed to be base64 dests
|
||||
|
||||
Destination dest = new Destination();
|
||||
dest.fromBase64(destStr);
|
||||
runClient(dest, host, port);
|
||||
}
|
||||
}
|
||||
|
||||
public void runClient(Destination dest) {
|
||||
runClient(dest, "127.0.0.1", 7654);
|
||||
}
|
||||
|
||||
/**
|
||||
* An alternative constructor which accepts an I2P Destination object
|
||||
*/
|
||||
public void runClient(Destination dest, String host, int port)
|
||||
{
|
||||
this.dest = dest;
|
||||
|
||||
String destAbbrev = dest.toBase64().substring(0, 16)+"...";
|
||||
|
||||
print("Connecting via i2cp "+host+":"+port+" to destination "+destAbbrev+"...");
|
||||
System.out.flush();
|
||||
|
||||
try {
|
||||
// get a socket manager
|
||||
socketManager = I2PSocketManagerFactory.createManager(host, port);
|
||||
|
||||
// get a client socket
|
||||
print("socketManager="+socketManager);
|
||||
|
||||
sessSocket = socketManager.connect(dest);
|
||||
|
||||
} catch (I2PException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (ConnectException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (NoRouteToHostException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (InterruptedIOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
print("Successfully connected!");
|
||||
print("(Press Control-C to quit)");
|
||||
|
||||
// Perform console interaction
|
||||
chat(sessSocket);
|
||||
|
||||
try {
|
||||
sessSocket.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the background thread to copy incoming data to stdout, then
|
||||
* loop in foreground copying lines from stdin and sending them to remote peer
|
||||
*/
|
||||
public void chat(I2PSocket sessSocket) {
|
||||
|
||||
try {
|
||||
socketIn = sessSocket.getInputStream();
|
||||
socketOutStream = sessSocket.getOutputStream();
|
||||
socketOut = new OutputStreamWriter(socketOutStream);
|
||||
|
||||
// launch receiver thread
|
||||
start();
|
||||
//launchRx();
|
||||
|
||||
while (true) {
|
||||
|
||||
String line = DataHelper.readLine(System.in);
|
||||
print("sent: '"+line+"'");
|
||||
|
||||
socketOut.write(line+"\n");
|
||||
socketOut.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* executes in a thread, receiving incoming bytes on
|
||||
* the socket input stream and spitting them to stdout
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
|
||||
byte [] ch = new byte[1];
|
||||
|
||||
print("Receiver thread listening...");
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
|
||||
//String line = DataHelper.readLine(socketIn);
|
||||
if (socketIn.read(ch) != 1) {
|
||||
print("failed to receive from socket");
|
||||
break;
|
||||
}
|
||||
|
||||
//System.out.println(line);
|
||||
System.out.write(ch, 0, 1);
|
||||
System.out.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
print("Receiver thread crashed, terminating!!");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void launchRx() {
|
||||
|
||||
rxThread = new SockInput(socketIn);
|
||||
rxThread.start();
|
||||
|
||||
}
|
||||
|
||||
static void print(String msg)
|
||||
{
|
||||
System.out.println("-=- I2PCat: "+msg);
|
||||
|
||||
if (_log != null) {
|
||||
_log.debug(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void usage(String msg)
|
||||
{
|
||||
usage(msg, 1);
|
||||
}
|
||||
|
||||
public static void usage(String msg, int ret)
|
||||
{
|
||||
System.out.println(msg);
|
||||
usage(ret);
|
||||
}
|
||||
|
||||
public static void usage(int ret)
|
||||
{
|
||||
System.out.print(
|
||||
"This utility is an I2P equivalent of the standard *nix 'netcat' utility\n"+
|
||||
"usage:\n"+
|
||||
" net.i2p.aum.I2PCat [-h]\n"+
|
||||
" - display this help\n"+
|
||||
" net.i2p.aum.I2PCat dest [host [port]]\n"+
|
||||
" - run in client mode, 'dest' should be one of:\n"+
|
||||
" hostname.i2p - an I2P hostname listed in hosts.txt\n"+
|
||||
" (only works with a hosts.txt in current directory)\n"+
|
||||
" base64dest - a full base64 destination string\n"+
|
||||
" file:b64filename - filename of a file containing base64 dest\n"+
|
||||
" net.i2p.aum.I2PCat -l privkey\n"+
|
||||
" - run in server mode, 'key' should be one of:\n"+
|
||||
" base64privkey - a full base64 private key string\n"+
|
||||
" file:b64filename - filename of a file containing base64 privkey\n"+
|
||||
"\n"
|
||||
);
|
||||
System.exit(ret);
|
||||
}
|
||||
|
||||
public static void main(String [] args) throws IOException, DataFormatException
|
||||
{
|
||||
int argc = args.length;
|
||||
|
||||
// barf if no args
|
||||
if (argc == 0) {
|
||||
usage("Missing argument");
|
||||
}
|
||||
|
||||
// show help on request
|
||||
if (args[0].equals("-h") || args[0].equals("--help")) {
|
||||
usage(0);
|
||||
}
|
||||
|
||||
// server or client?
|
||||
if (args[0].equals("-l")) {
|
||||
if (argc != 2) {
|
||||
usage("Bad argument count");
|
||||
}
|
||||
|
||||
new I2PCat().runServer(args[1]);
|
||||
}
|
||||
else {
|
||||
// client mode - barf if not 1-3 args
|
||||
if (argc < 1 || argc > 3) {
|
||||
usage("Bad argument count");
|
||||
}
|
||||
|
||||
try {
|
||||
int port = defaultPort;
|
||||
String host = defaultHost;
|
||||
if (args.length > 1) {
|
||||
host = args[1];
|
||||
if (args.length > 2) {
|
||||
port = new Integer(args[2]).intValue();
|
||||
}
|
||||
}
|
||||
new I2PCat().runClient(args[0], host, port);
|
||||
|
||||
} catch (DataFormatException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user