Hi All. I've written some code that may be useful to those who would like to run a Freenet node, but are forced to access the web via a web proxy server. This presents a problem if you're trying to read the list of nodes or add to it.
Before the connection to inform.php, a few lines of code set the Java system properties to use a proxy specified in the config file or on the command line. It is of no use whatsoever if you are behind a firewall which blocks incoming traffic, since other nodes will not be able to contact yours. Changes are limited to three files taken from the cvs snapshot Freenet-20000415.tgz: node/Node.java - lines 199-203, 244-245 scripts/freenet.ini - lines 35-38 scripts/sample.freenetrc - lines 35-38 I've made the changes to the version I'm running here, and all seems well. Unfortunately, you still have to unregister the node manually when you shut it down, since this isn't done using Java. Please feel free to make use of this, or disregard it totally:) All the best, Stuart -------------- next part -------------- package Freenet.node; import Freenet.*; import Freenet.crypt.*; import Freenet.support.*; import Freenet.message.HandshakeRequest; import java.util.*; import java.net.*; import java.io.*; /* This code is part of the Java Adaptive Network Client by Ian Clarke. It is distributed under the GNU Public Licence (GPL) version 2. See http://www.gnu.org/ for further details of the GPL. */ /** * This is a Wrapper object that contains the components of a Node in the * Adaptive Network. It uses a Network object to communicate with other * Nodes in the Network. * * @author <A HREF="mailto:I.Clarke at strs.co.uk">Ian Clarke</A> * @author <a href="mailto:blanu at uts.cc.utexas.edu">Brandon Wiley</a> **/ public class Node extends Core { public static Node n; static final String BUILD = "LATEST_BUILD="; // Look in inform.php public static Params params; public static void main(String[] args) { Hashtable at=new Hashtable(); // set revision number for handshake StringTokenizer cvsId = new StringTokenizer ("$Id: Node.java,v 1.19 2000/04/13 19:02:03 hobbex Exp $", " "); cvsId.nextToken(); cvsId.nextToken(); serverRevision = cvsId.nextToken(); try { Data.path = new File(".freenet"); if (!Data.path.exists()) Data.path.mkdir(); // parse command line String[] rcfiles = {".freenetrc", "freenet.ini"}; Logger.threshold = Logger.ERROR; params = new Params(rcfiles, args); // check for help if (params.getParam("help") != null) { usage(); return; } else if (params.getParam("version") != null) { version(); return; } if (params.getParam("logging")==null) Logger.threshold = Logger.NORMAL; else if (params.getParam("logging").equalsIgnoreCase("error")) Logger.threshold = Logger.ERROR; else if (params.getParam("logging").equalsIgnoreCase("normal")) Logger.threshold = Logger.NORMAL; else if (params.getParam("logging").equalsIgnoreCase("minor")) Logger.threshold = Logger.MINOR; else if (params.getParam("logging").equalsIgnoreCase("debugging")) Logger.threshold = Logger.DEBUGGING; Logger.verbosity = params.getint("verbosity",Logger.verbosity); String fname = params.getParam("logFile","NO"); if (!fname.equalsIgnoreCase("NO")) { try { Logger.logto(fname); } catch (Exception e) { System.out.println("Writing to log failed"); } } // timer must be initialized before datastore so that datastore // can register an event to write it to disk periodically Node.timer = new Ticker(params.getlong("tickerTime",500)); Node.timer.setDaemon(true); // set parameters // These should be taken from arguments or a config file int port = params.getint("listenPort", 0); try { n = new Node(params.getlong("diskCache", 500), params.getint("dataStoreSize", 500), params.getint("messageStoreSize", 500), new ListeningAddress ("tcp/" + port)); } catch (BindException e) { System.out.println("Could not bind to port " + port + " - maybe another node is running?"); if (port < 1024) { System.out.println("Or, you might not have privileges to bind to a port < 1024."); } System.exit(1); return; } tunneling = !((params.getParam("Tunnel", "YES")).equalsIgnoreCase("NO")); connectTimeout = params.getint("connectTimeout",30000); handshakeTimeout = params.getint("handshakeTimeout",30000); handshakeLife = params.getint("handshakeLife",10000000); if (!tunneling) Logger.log("Node.java","Tunneling turned off",Logger.DEBUGGING); try { if ( (params.getParam("informRead").equalsIgnoreCase("yes") || params.getParam("informWrite").equalsIgnoreCase("yes")) && params.getParam("informUrl") != null) inform(at); } catch(NullPointerException e) { Logger.log("Node.java","informRead/Write not set",Logger.ERROR); } try { BufferedReader br=new BufferedReader(new FileReader("nodes.config")); StringKey tname; SHA1 sha=new SHA1(true); while(br.ready()) { String addrstr=br.readLine(); addrstr=addrstr.trim(); if(!addrstr.equals("")) { tname = new StringKey(sha.doHash(addrstr)); if(n.ds.searchRef(tname)==null) at.put(addrstr, tname); } } } catch(IOException e) {} Enumeration iterator=at.keys(); while(iterator.hasMoreElements()) { String addr=(String)iterator.nextElement(); try { n.ds.put((StringKey)at.get(addr), new Address(addr), null); } catch(Exception e) {e.printStackTrace();} } n.acceptConnections(); } catch(Exception e) {e.printStackTrace();} } private static final void informWrite(HttpURLConnection c) throws IOException { if (params.getParam("informWrite").equalsIgnoreCase("yes")) { c.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); PrintWriter outStream = new PrintWriter(c.getOutputStream()); outStream.print("port="+params.getParam("listenPort")); outStream.close(); } } private static final void informRead(HttpURLConnection c, Hashtable at) throws IOException { if (params.getParam("informRead").equalsIgnoreCase("yes")) { InputStreamReader ir = new InputStreamReader(c.getInputStream()); BufferedReader br = new BufferedReader(ir); SHA1 sha=new SHA1(true); while(br.ready()) { String addrstr=br.readLine(); addrstr=addrstr.trim(); if(addrstr.startsWith(BUILD)) { String latestbuild = addrstr.substring(BUILD.length()); if (buildNumber.compareTo(latestbuild) < 0) System.err.println ( "Newer build "+latestbuild+" is available than this build "+buildNumber+", please upgrade!"); } else if(!addrstr.equals("")) { StringKey tname = new StringKey(sha.doHash(addrstr)); if(n.ds.searchRef(tname)==null) at.put(addrstr, tname); } } ir.close(); } } private static final void inform(Hashtable at) { try { if(!params.getParam("webProxyAddress").equalsIgnoreCase("")){ System.getProperties().put( "proxySet", "true" ); System.getProperties().put( "proxyHost", params.getParam("webProxyAddress")); System.getProperties().put( "proxyPort", params.getParam("webProxyPort")); } HttpURLConnection c = (HttpURLConnection)(new URL(params.getParam("informUrl"))).openConnection(); c.setDoInput(true); c.setDoOutput(true); c.setUseCaches(true); informWrite(c); informRead(c, at); c.disconnect(); } catch (Exception e) { Logger.log("Node.java","Inform Connection failed:"+e, Logger.ERROR); } } /** * Print version information **/ public static void version() { System.out.println("Freenet server version " + freenetVersion + " (build " + buildNumber + " revision " + serverRevision + ")"); } /** * Print usage information **/ public static void usage() { version(); System.out.println("Usage: freenet_server [options]"); System.out.println(""); System.out.println(" -connectTimeout msec Time to wait for connection to remote node"); System.out.println(" -dataStoreSize n Max number of items to keep in store"); System.out.println(" -diskCache bytes Max size of disk cache"); System.out.println(" -handshakeLife msec Time to treat old handshakes as good"); System.out.println(" -handshakeTimeout msec Time to wait for handshake from remote node"); System.out.println(" -informRead yes|no Read initial nodes from list on webserver"); System.out.println(" -informWrite yes|no Add this node to list on webserver"); System.out.println(" -informUrl url URL of node list"); System.out.println(" -webProxyAddress address Address of proxy server"); System.out.println(" -webProxyPort port Port number for proxy server"); System.out.println(" -listenPort port Local port to listen on"); System.out.println(" -logFile file Name of log file (`no' to log to console)"); System.out.println(" -logging error|normal|minor|debugging"); System.out.println(" Logging level"); System.out.println(" -messageStoreSize n Max number of pending messages to track"); System.out.println(" -timePerHop msec Time to wait for replies (per hop)"); System.out.println(" -tunnel yes|no Start forwarding messages while incomplete"); System.out.println(" -verbosity 1-5 Verbosity of log messages"); System.out.println(" -help Display this help and exit"); System.out.println(" -version Output version information and exit"); System.out.println(""); System.out.println("Send bug reports to freenet-dev at lists.sourceforge.net"); } public DataStore ds; public Node(long dataLen, int dataStoreSz, int messStoreSz, ListeningAddress lstaddr) throws BindException { super(lstaddr, null, new StandardHandshakeHandler()); mh = new StandardMessageHandler(this, messStoreSz); // give the DataStore a filename to write that reflects the port // I know this is protocol-dependent, but so is listenPort itself StandardDataStore.filename = ".freenet/store_" + ((tcpListeningAddress) myAddress.address).port; ds = StandardDataStore.makeDataStore(this, dataLen, dataStoreSz); } } -------------- next part -------------- # Freenet configuration file # Note that all properties may be overridden from the command line, # so for example, java Freenet.Node -listenPort 10000 will cause # the setting in this file to be ignored # Connection "tunneling" on or off Tunnel=YES # The port to which the Freenet Server should listen for connections listenPort=19114 # How often to write the datastore to disk (in seconds) checkpointInterval=60 # The size of the disk cache is specified here in bytes diskCache=10000000 # The number of items permitted in the dataStore dataStoreSize=500 # The number of outstanding message replies the node will # wait for before it starts to "forget" them messageStoreSize=100 # The URL of a CGI script which will allow the server # to learn about other servers in the Freenet, and # to inform other servers of its presence. informUrl=http://freenet.sourceforge.net/inform.php # Should we read some information about other nodes from the informUrl? informRead=yes # Should we write our address to the inform URL so that others might # find out about us more easily? informWrite=yes # The address and port of a web proxy server to allow access to the # informUrl for people who are forced to use a webcache. webProxyAddress= webProxyPort= # The number of milliseconds between ticks on the timer tickerTime=500 # The time to wait before starting a new request, per hops left # for the message to live timePerHop=3000 # How long to wait to connect to a host before giving up (in milliseconds) connectTimeout=2000 # How long to wait for a handshake (in milliseconds) handshakeTimeout=3000 # How long before a handshake expires (in milliseconds) handshakeLife=100000 # The error reporting threshold, one of: # Error: Errors only # Normal: Report significant events # Minor: Report minor events # Debugging: Report events only of relevance when debugging logging=DEBUGGING # The name of the log file (`no' to log to standard out) logFile=freenet.log # How verbose should tbe logging be? (1-5) verbosity=5 -------------- next part -------------- # Freenet configuration file # Note that all properties may be overridden from the command line, # so for example, java Freenet.Node -listenPort 10000 will cause # the setting in this file to be ignored # Connection "tunneling" on or off Tunnel=YES # The port to which the Freenet Server should listen for connections listenPort=19114 # How often to write the datastore to disk (in seconds) checkpointInterval=600 # The size of the disk cache is specified here in bytes diskCache=50000000 # The number of items permitted in the dataStore dataStoreSize=500 # The number of outstanding message replies the node will # wait for before it starts to "forget" them messageStoreSize=100 # The URL of a CGI script which will allow the server # to learn about other servers in the Freenet, and # to inform other servers of its presence. informUrl=http://freenet.sourceforge.net/inform.php # Should we read some information about other nodes from the informUrl? informRead=yes # Should we write our address to the inform URL so that others might # find out about us more easily? informWrite=yes # The address and port of a web proxy server to allow access to the # informUrl for people who are forced to use a webcache. webProxyAddress= webProxyPort= # The number of milliseconds between ticks on the timer tickerTime=500 # The expected time and standard deviation, in milliseconds, that it takes # a Freenet node to pass a message. These are used to calculate how long # the node should wait before assuming that a passed message is lost. # These are mostly here for debugging reasons - changing them will NOT # make requests come back faster for you. hopTimeExpected=12000 hopTimeDeviation=12000 # How long to wait to connect to a host before giving up (in milliseconds) connectTimeout=2000 # How long to wait for a handshake (in milliseconds) handshakeTimeout=3000 # How long before a handshake expires (in milliseconds) handshakeLife=100000 # The error reporting threshold, one of: # Error: Errors only # Normal: Report significant events # Minor: Report minor events # Debugging: Report events only of relevance when debugging logging=normal # The name of the log file (`no' to log to standard out) logFile=freenet.log # How verbose should tbe logging be? (1-5) verbosity=5
