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

Reply via email to