implement keyfile persistence (storing name=privKeyDataBase64\n for each name)
filename specified on the command line: SAMBridge [keyfile [listenHost] listenPortNum [ name=val]*]
This commit is contained in:
@ -9,6 +9,11 @@ package net.i2p.sam;
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
@ -16,6 +21,7 @@ import java.util.Properties;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.DataFormatException;
|
||||
@ -24,6 +30,7 @@ import net.i2p.data.SigningPrivateKey;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* SAM bridge implementation.
|
||||
@ -31,10 +38,14 @@ import net.i2p.util.Log;
|
||||
* @author human
|
||||
*/
|
||||
public class SAMBridge implements Runnable {
|
||||
|
||||
private final static Log _log = new Log(SAMBridge.class);
|
||||
private ServerSocket serverSocket;
|
||||
private Properties i2cpProps;
|
||||
/**
|
||||
* filename in which the name to private key mapping should
|
||||
* be stored (and loaded from)
|
||||
*/
|
||||
private String persistFilename;
|
||||
/**
|
||||
* app designated destination name to the base64 of the I2P formatted
|
||||
* destination keys (Destination+PrivateKey+SigningPrivateKey)
|
||||
@ -43,7 +54,8 @@ public class SAMBridge implements Runnable {
|
||||
|
||||
private boolean acceptConnections = true;
|
||||
|
||||
private final static int SAM_LISTENPORT = 7656;
|
||||
private static final int SAM_LISTENPORT = 7656;
|
||||
public static final String DEFAULT_SAM_KEYFILE = "sam.keys";
|
||||
|
||||
private SAMBridge() {}
|
||||
|
||||
@ -53,8 +65,11 @@ public class SAMBridge implements Runnable {
|
||||
* @param listenHost hostname to listen for SAM connections on ("0.0.0.0" for all)
|
||||
* @param listenPort port number to listen for SAM connections on
|
||||
* @param i2cpProps set of I2CP properties for finding and communicating with the router
|
||||
* @param persistFile location to store/load named keys to/from
|
||||
*/
|
||||
public SAMBridge(String listenHost, int listenPort, Properties i2cpProps) {
|
||||
public SAMBridge(String listenHost, int listenPort, Properties i2cpProps, String persistFile) {
|
||||
persistFilename = persistFile;
|
||||
loadKeys();
|
||||
try {
|
||||
if ( (listenHost != null) && !("0.0.0.0".equals(listenHost)) ) {
|
||||
serverSocket = new ServerSocket(listenPort, 0, InetAddress.getByName(listenHost));
|
||||
@ -114,6 +129,57 @@ public class SAMBridge implements Runnable {
|
||||
*/
|
||||
public void addKeystream(String name, String stream) {
|
||||
nameToPrivKeys.put(name, stream);
|
||||
storeKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load up the keys from the persistFilename
|
||||
*
|
||||
*/
|
||||
private synchronized void loadKeys() {
|
||||
Map keys = new HashMap(16);
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(persistFilename);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
String line = null;
|
||||
while ( (line = reader.readLine()) != null) {
|
||||
int eq = line.indexOf('=');
|
||||
String name = line.substring(0, eq);
|
||||
String privKeys = line.substring(eq+1);
|
||||
keys.put(name, privKeys);
|
||||
}
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
_log.warn("Key file does not exist at " + persistFilename);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Unable to read the keys from " + persistFilename, ioe);
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
nameToPrivKeys = Collections.synchronizedMap(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the current keys to disk in the location specified on creation
|
||||
*
|
||||
*/
|
||||
private synchronized void storeKeys() {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(persistFilename);
|
||||
for (Iterator iter = nameToPrivKeys.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String privKeys = (String)nameToPrivKeys.get(name);
|
||||
out.write(name.getBytes());
|
||||
out.write('=');
|
||||
out.write(privKeys.getBytes());
|
||||
out.write('\n');
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error writing out the SAM keys to " + persistFilename, ioe);
|
||||
} finally {
|
||||
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,15 +191,17 @@ public class SAMBridge implements Runnable {
|
||||
* depth, etc.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
String keyfile = DEFAULT_SAM_KEYFILE;
|
||||
int port = SAM_LISTENPORT;
|
||||
String host = "0.0.0.0";
|
||||
Properties opts = null;
|
||||
if (args.length > 0) {
|
||||
int portIndex = 0;
|
||||
keyfile = args[0];
|
||||
int portIndex = 1;
|
||||
try {
|
||||
port = Integer.parseInt(args[portIndex]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
host = args[0];
|
||||
host = args[1];
|
||||
portIndex++;
|
||||
try {
|
||||
port = Integer.parseInt(args[portIndex]);
|
||||
@ -144,7 +212,7 @@ public class SAMBridge implements Runnable {
|
||||
}
|
||||
opts = parseOptions(args, portIndex+1);
|
||||
}
|
||||
SAMBridge bridge = new SAMBridge(host, port, opts);
|
||||
SAMBridge bridge = new SAMBridge(host, port, opts, keyfile);
|
||||
I2PThread t = new I2PThread(bridge, "SAMListener");
|
||||
t.start();
|
||||
}
|
||||
@ -167,7 +235,8 @@ public class SAMBridge implements Runnable {
|
||||
}
|
||||
|
||||
private static void usage() {
|
||||
System.err.println("Usage: SAMBridge [listenHost listenPortNum[ name=val]*]");
|
||||
System.err.println("Usage: SAMBridge [keyfile [listenHost] listenPortNum[ name=val]*]");
|
||||
System.err.println(" keyfile: location to persist private keys (default sam.keys)");
|
||||
System.err.println(" listenHost: interface to listen on (0.0.0.0 for all interfaces)");
|
||||
System.err.println(" listenPort: port to listen for SAM connections on (default 7656)");
|
||||
System.err.println(" name=val: options to pass when connecting via I2CP, such as ");
|
||||
|
Reference in New Issue
Block a user