Author: jolantern
Date: 2007-12-09 14:01:11 +0000 (Sun, 09 Dec 2007)
New Revision: 16440

Added:
   branches/legacy/stable/TODO
   branches/legacy/stable/TODO.old
Removed:
   branches/legacy/stable/TODO
   branches/legacy/stable/src/freenet/client/SplitFileDownloadStatus.java~
   branches/legacy/stable/src/freenet/client/SplitFileDownloader.java~
   branches/legacy/stable/src/freenet/client/SplitFileRequest.java~
Modified:
   branches/legacy/stable/
   branches/legacy/stable/README
   branches/legacy/stable/src/freenet/Core.java
   branches/legacy/stable/src/freenet/crypt/DiffieHellman.java
   branches/legacy/stable/src/freenet/session/FnpLink.java
Log:
README:
* small corrections and updates
* CVS -> SVN
* Updated section on securing Mozilla 

TODO:
Started rewrite. Old TODO has been kept as TODO.old for the time being.

contrib:
* fixed revision to 16289

src/freenet/Core.java:
* removed /dev/urandom because it is already used by 
src/freenet/crypt/Yarrow.java
* further whitespace-only changes

Removed unused files:
* src/freenet/client/SplitFileDownloader.java~
* src/freenet/client/SplitFileDownloadStatus.java~
* src/freenet/client/SplitFileRequest.java~

Whitespace only changes in:
* src/freenet/crypt/DiffieHellman.java
* src/freenet/session/FnpLink.java



Property changes on: branches/legacy/stable
___________________________________________________________________
Name: svn:externals
   - contrib https://emu.freenetproject.org/svn/branches/legacy/contrib/

   + contrib -r16289 https://emu.freenetproject.org/svn/branches/legacy/contrib/


Modified: branches/legacy/stable/README
===================================================================
--- branches/legacy/stable/README       2007-12-08 23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/README       2007-12-09 14:01:11 UTC (rev 16440)
@@ -1,6 +1,5 @@
-Freenet 0.5 and 0.6 are now in maintenance mode. All major 
-development is occurring on 0.7. As a result, the previously 
-incompatible 0.5 and 0.6 branches have been merged.
+Freenet 0.5 is now in maintenance mode. Freenet 0.6 is deprecated. All major
+development is occurring on 0.7.

 Fred 0.5
 ========
@@ -51,7 +50,7 @@
 Environment, we strongly suggest that you use the latest version of Sun's 
 Java Runtime Environment for your platform (see http://java.sun.com/). If 
 you want to use fproxy, we STRONGLY recommend you use a web browser that 
-doesn't ignore MIME types... Mozilla and Konqueror are OK, Internet 
+doesn't ignore MIME types... Firefox and Konqueror are OK, Internet 
 Explorer will seriously jeopardize your anonymity. Freenet also requires
 that your system clock is within a few minutes of the actual time.

@@ -73,29 +72,31 @@
    the listenPort setting in your freenet.conf file.
 3) Configure your NAT or firewall to forward incoming TCP connections
    on this port to your computer (see your NAT or firewall's manual
-   for instructions on how to do this)
+   for instructions on how to do this).

 3.2 Starting Freenet
 --------------------
 On *NIX Type:
-> sh start-freenet.sh 
+> sh start-freenet.sh

 To run Freenet.  The first time you run it it will ask you some questions 
 to create a configuration file (freenet.conf).  You can edit this
 manually later if you need to, but generally you shouldn't change
 anything unless you know what you are doing.

+FIXME: And on MS?
+
 3.3 Accessing Freenet via FProxy
 --------------------------------
 You can look at some websites in Freenet by visiting http://localhost:8888/
 in your web browser.  You can also find interesting information about what
 your node is doing there. Please read the SECURITY CAUTIONS below 
-BEFORE using a Web Browser with Freenet
+BEFORE using a Web Browser with Freenet!


 SETTING UP A BROWSER FOR BEST PERFORMANCE

----Mozilla and Gecko Based Browsers(ie. Netscape):
+---Mozilla and Gecko Based Browsers (ie. Firefox):
 Many browsers limit the number of simultaneous connections to something far
 too low for efficiently browsing Freenet (since Freenet pages often have
 much higher latency than web pages). This can usually be reconfigured. For
@@ -122,15 +123,16 @@

 ---Opera Browser
 Go to File/Preferences/Network
-- set 'Max connections to a server' to 20, 32 or 64,  if you find you are 
getting 
-'could not connect to server' warnings adjust your setting one step down
-- set ''Max total connections' to one setting higher than max connections, 
-this will allow Freenet to use all connections available to it without 
interfering
-with web browsing ie. if Max to server is 32 then Max total should be 64
+- set 'Max connections to a server' to 20, 32 or 64,  if you find you are
+  getting 'could not connect to server' warnings adjust your setting one step
+  down.
+- set 'Max total connections' to one setting higher than max connections, this
+  will allow Freenet to use all connections available to it without interfering
+  with web browsing ie. if Max to server is 32 then Max total should be 64.

 Note that these settings will cause Opera to use more connections for
 all your browsing, which may not be desirable from a network congestion
-point of view
+point of view.


 SECURITY CAUTIONS
@@ -140,25 +142,52 @@

 The following is VERY IMPORTANT:

-For Mozilla prior to 1.3: create a file with the following contents called
-user.js in the same directory with prefs.js, or append to an existing user.js:
+Mozilla has three features, GoBrowsing, Prefetching, and Safebrowsing, which
+may DESTROY YOUR ANONYMITY. GoBrowsing feeds failed queries into a search
+engine (Google seems to be the default), so when enter the URL of a freesite
+with a small typo, what you typed will be leaked to the internet. Prefetching
+loads pages in the background before you click on them. Malicious freesite
+authors may abuse this feature to find out who is reading their sites (sort of
+a web bug). Safebrowsing communicates with a so-called provider (once again,
+Google seems to be the default) to detect whether a web page was set up by
+phishers or other malicious entities. However, during this process details
+about the page contents may be transmitted to the provider.

-user_pref("browser.goBrowsing.enabled", false);
+To deactivate these features, follow these instructions
+(instructions for older Mozilla type browsers below):

-This disables Mozilla's default behaviour of feeding timed out
-queries into Google, thus DESTROYING YOUR ANONYMITY.
+Type "about:config" into the URL location box of your browser. You get a list
+of editable preferences. You must set these three pereferences to "false":

-In later versions of Mozilla, this setting can be edited within the program
-itself by typing the URL "about:config" into the URL location box, 
-right-clicking on "browser.goBrowsing.enabled" in the list of preferences
-that comes up, selecting "Modify", and changing the setting from true to false.
+* keyword.enabled
+* network.prefetch-next
+* browser.safebrowsing.enabled

+Follow these instructions for older Mozilla type browsers:
+
+If you can't find the configuration variables for Preloading and Safebrowsing
+(network.prefetch-next and browser.safebrowsing.enabled, respectively), these
+features are probably not supported by your browser and therefore do not pose a
+threat. But don't forget to switch them off once you update your browser.
+
+If you can't find the keyword.enabled configuration variable that's because
+it is named differently in older browsers. Set the following variable to false
+instead:
+
+* browser.goBrowsing.enabled
+
+Mozilla prior to 1.3 does not support in-browser configuration editing.
+Instead, create a file with the following contents called user.js in the same
+directory with prefs.js, or append to an existing user.js:
+
+user_pref("browser.goBrowsing.enabled", false);
+
 ---Microsoft Internet Explorer:
 Internet Explorer (all versions, we think) has a totally different
 ANONYMITY-DESTROYING BEHAVIOUR (not respecting MIME types), and also some 
 problems with auto-detecting UTF16 even when we tell it in the headers to use 
 some other charset). Internet Explorer is NOT recommended for 
-anonymous browsing
+anonymous browsing.

 ---Opera Browser:
 Opera's default behaviour is similar to Internet Explorer's and can compromise 
@@ -172,78 +201,83 @@
 It is possible that the anonymity filter can be circumvented by other means, so
 if you care about your anonymity while browsing Freenet:
 a) Don't use Internet Explorer and setup Opera properly, see above.
-b) Turn off javascript, java, active scripting, and any other scripting your 
-browser supports.
-c) Set your browser to only load images, frames, etc from the server that 
-originated the web page
-d) Be extra paranoid! Keep your browser up to date etc. Extreme measures 
include 
-browser proxies that block everything except localhost:8888 HTTP, encrypted 
disk
-partitions or virtual disks, and so on.
+b) Turn off javascript, java, active scripting, and any other scripting your
+   browser supports.
+c) Set your browser to only load images, frames, etc from the server that
+   originated the web page
+d) Be extra paranoid! Keep your browser up to date etc. Extreme measures
+   include browser proxies that block everything except localhost:8888 HTTP,
+   encrypted disk partitions or virtual disks, and so on.
 e) Set in your config file:
-mainport.params.servlet.1.params.filterParanoidStringCheck=true
-mainport.params.servlet.7.params.sfFilterParanoidStringCheck=true
-f) Consider using your operating system's security features to sandbox your 
-Freenet browsing. For example, on Linux, you can (after setting 
-httpInserts=false and fcpInserts=false in your freenet.conf) create a user 
-specifically for browsing freenet, only use that user to browse freenet, and
-type the following lines to prevent that user from accessing the regular 
-internet (assuming the safe user, which must not be the user running the node,
-is called "freenet"):
+      mainport.params.servlet.1.params.filterParanoidStringCheck=true
+      mainport.params.servlet.7.params.sfFilterParanoidStringCheck=true
+f) Consider using your operating system's security features to sandbox your
+   Freenet browsing. For example, on Linux, you can (after setting
+   httpInserts=false and fcpInserts=false in your freenet.conf) create a user
+   specifically for browsing freenet, only use that user to browse freenet, and
+   type the following lines to prevent that user from accessing the regular
+   internet (assuming the safe user, which must not be the user running the
+   node, is called "freenet"):

-# Accept TCP packets destined for local ports 8888 and 8481.
-iptables -A OUTPUT -d localhost -p tcp --dport 8888 -m owner --uid-owner 
freenet -j ACCEPT
-iptables -A OUTPUT -d localhost -p tcp --dport 8481 -m owner --uid-owner 
freenet -j ACCEPT
+      # Accept TCP packets destined for local ports 8888 and 8481.
+      iptables -A OUTPUT -d localhost -p tcp --dport 8888 -m owner --uid-owner 
freenet -j ACCEPT
+      iptables -A OUTPUT -d localhost -p tcp --dport 8481 -m owner --uid-owner 
freenet -j ACCEPT

-# Drop everything else.
-iptables -A OUTPUT -m owner --uid-owner freenet -j DROP
+      # Drop everything else.
+      iptables -A OUTPUT -m owner --uid-owner freenet -j DROP

-Your kernel must be configured with these options:
+   Your kernel must be configured with these options:

        CONFIG_IP_NF_IPTABLES
        CONFIG_IP_NF_MATCH_OWNER
        CONFIG_IP_NF_FILTER

-Verify that the filter rules have been added:
+   Verify that the filter rules have been added:

-$ iptables -L OUTPUT
-Chain OUTPUT (policy ACCEPT)
-target     prot opt source               destination
-ACCEPT     tcp  --  anywhere             localhost          OWNER UID match 
freenet tcp dpt:8888
-ACCEPT     tcp  --  anywhere             localhost          OWNER UID match 
freenet tcp dpt:8481
-DROP       all  --  anywhere             anywhere           OWNER UID match 
freenet
+      $ iptables -L OUTPUT
+      Chain OUTPUT (policy ACCEPT)
+      target     prot opt source               destination
+      ACCEPT     tcp  --  anywhere             localhost          OWNER UID 
match freenet tcp dpt:8888
+      ACCEPT     tcp  --  anywhere             localhost          OWNER UID 
match freenet tcp dpt:8481
+      DROP       all  --  anywhere             anywhere           OWNER UID 
match freenet

 g) If you are accessing files that will get you into serious trouble, consider
-using something simpler than a web browser to access Freenet... or better yet,
-DON'T DO IT! This is still beta software, it probably has more bugs. Having 
-said that, millions of people access questionable content through much less 
-secure systems than Freenet. Use your common sense. You can't conceal the fact
-that you are running a freenet node from a determined attacker, because of the
-way Freenet works (path shortening - for more details visit our web site). 
-However short of compromizing your computer, other expensive forms of 
-surveillance, you doing something stupid, or more bugs, it should be very 
-difficult for them to find out _what_ you browse (or publish) on Freenet.
+   using something simpler than a web browser to access Freenet... or better
+   yet, DON'T DO IT! This is still beta software, it probably has more bugs.
+   Having said that, millions of people access questionable content through
+   much less secure systems than Freenet. Use your common sense. You can't
+   conceal the fact that you are running a freenet node from a determined
+   attacker, because of the way Freenet works (path shortening - for more
+   details visit our web site). However short of compromising your computer,
+   other expensive forms of surveillance, you doing something stupid, or more
+   bugs, it should be very difficult for them to find out _what_ you browse
+   (or publish) on Freenet.

-What you want to prevent (in parts a,b,c) is freesites accessing the Real 
-Internet, and giving away the combination of your IP address along and the
-fact that you visited a given freesite or downloaded (or uploaded) a specific
-file. This is called a Web Bug, and the simplest form is an image in a 
-freesite loaded from somewhere on the real web - this gives away your IP 
-address, and the page you are browsing (if the attacker is clever, or you have
-Referer: turned on), to the server the image is downloaded from. Fproxy 
-(freenet's web interface) contains code ("the anonymity filter") to try to
-warn about or remove such things, but there could always be bugs in freenet or
-in your web browser that would let something through. You can of course reduce
-the likelihood of this by turning off images support in your browser.
+   What you want to prevent (in parts a,b,c) is freesites accessing the Real
+   Internet, and giving away the combination of your IP address along and the
+   fact that you visited a given freesite or downloaded (or uploaded) a
+   specific file. This is called a Web Bug, and the simplest form is an image
+   in a freesite loaded from somewhere on the real web - this gives away your
+   IP address, and the page you are browsing (if the attacker is clever, or you
+   have Referer: turned on), to the server the image is downloaded from. Fproxy
+   (freenet's web interface) contains code ("the anonymity filter") to try to
+   warn about or remove such things, but there could always be bugs in freenet
+   or in your web browser that would let something through. You can of course
+   reduce the likelihood of this by turning off images support in your browser.

-The following formats are known to be able to carry data that could compromize 
your
-anonymity (but there are no doubt many more that can do this):
+   The following formats are known to be able to carry data that could
+   compromise your anonymity (but there are no doubt many more that can do
+   this):

-* RealPlayer
-* Windows Media Player
-* MP3s (some id3 tags cause winamp to open web sites and thus compromize your 
anonymity)
-* HTML and CSS, of course, hence the filter.
+   * RealPlayer
+   * Windows Media Player
+   * MP3s (some id3 tags cause winamp to open web sites and thus compromise
+     your anonymity).
+   * HTML and CSS, of course, hence the filter.

-Finally, you should disable your browser cache AND set the option 
mainport.params.servlet.1.params.noCache=true in your config file (to tell 
freenet to send no-cache directives to the browser).
+   Finally, you should disable your browser cache AND set the option
+   mainport.params.servlet.1.params.noCache=true in your config file (to tell
+   freenet to send no-cache directives to the browser).

 FILTER ISSUES FOR CONTENT AUTHORS
 ---------------------------------
@@ -254,18 +288,21 @@
   <img src="something.png" width="95" height="32" alt="grey cat" align="left" 
"hspace="5">
   or
   <IMG SRC="../../../Blah/2//issue.png"" ALT="Issue 2" WIDTH=95 HEIGHT=32>
-  will confuse it... this is partly because the HTML 4.01 spec seems to imply 
that <> 
-  characters are allowed in strings inside tags. This should not be a problem 
using GUI
-  tools; it is however a problem if you write the HTML directly.
-* Charsets. If you want to insert a file with a charset other than the default 
iso-8859-1,
-  tell your insertion tool to use the new charset in the mime type, for 
example 
-  "text/html;charset=UTF16". The META tag to set the mime type is NOT 
supported. Neither
-  is the UTF16 byte order mark.
+  will confuse it... this is partly because the HTML 4.01 spec seems to imply
+  that <> characters are allowed in strings inside tags. This should not be a
+  problem using GUI tools; it is however a problem if you write the HTML
+  directly.
+* Charsets. If you want to insert a file with a charset other than the default
+  iso-8859-1, tell your insertion tool to use the new charset in the mime type,
+  for example "text/html;charset=UTF16". The META tag to set the mime type is
+  NOT supported. Neither is the UTF16 byte order mark.
 * All unrecognized HTML tags are removed by fproxy, for security reasons.

 JVM ISSUES
 ----------

+FIXME: This information is probably out of date.
+
 There are issues with lots of JVMs.
 * RedHat 9.0 and other distributions having Native Posix Threads are 
   _very_ unstable. That's why the startup script has been modified to 
@@ -295,8 +332,9 @@
   it uses fds for many things other than connections). You will probably be
   able to raise the limit with the command ulimit -n 1024, and then set
   maxNodeConnections=512 explicitly in the config file. Most other unix(tm)
-  derived systems have a default limit of 1024, so they are ok (the default
-  512 connections should be plenty for most purposes).
+  derived systems have a default limit of 1024, so they are ok for the default
+  configuration. For a large node, you may want to increase this value as well,
+  however.

 TWEAKING
 --------
@@ -304,26 +342,28 @@
 1. How To Speed Up Large Splitfiles
 -----------------------------------

+FIXME: This is done automatically on at least some architectures, is it not?
+
 You can speed up splitfiles (FEC encoded splitfiles, the default), by using
 native compiled FEC libraries.

 Details are at this URL:
-http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/freenet/Contrib/fecimpl/onion/README?rev=HEAD&content-type=text/vnd.viewcvs-markup
-(that is fecimpl/onion/README in the freenet Contrib CVS module),
+http://freenet.googlecode.com/svn/branches/legacy/contrib/fecimpl/onion/README
+(that is fecimpl/onion/README in the freenet contrib SVN module).

 The info on Native FEC support on the Nubile freesite (edition 11) is 
completly obsolete.

-The zip file that the readme refers to is in CVS (in the Contrib module,
+The zip file that the readme refers to is in SVN (in the contrib module,
 *not* the main freenet module).

 You can access it on the web here:

-http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/freenet/Contrib/fecimpl/onion/alien/fec-1.0.3.zip
+http://freenet.googlecode.com/svn/branches/legacy/contrib/fecimpl/onion/alien/fec-1.0.3.zip

-(Do a "Save link as..."  on the "(download)" link from your browser)
+(Do a "Save link as..."  on the "(download)" link from your browser.)

 I didn't deploy native FEC support by default because I didn't want to deal
-with the per platform configuration issues.   The instructions in the file
+with the per platform configuration issues. The instructions in the file
 given above are geared toward people who already know about JNI libraries.

 If someone out there wants to write per platform (*nix, Windows) end user
@@ -336,7 +376,7 @@
 ----------------
 Special thanks to Justin Chapweske and Onion Networks
 (www.onionnetworks.com) for making their Java Forward 
-Error Correction (FEC) library available under 
+Error Correction (FEC) library available under
 an open license.

 Here's the text of the Onion license that is embedded in

Deleted: branches/legacy/stable/TODO
===================================================================
--- branches/legacy/stable/TODO 2007-12-08 23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/TODO 2007-12-09 14:01:11 UTC (rev 16440)
@@ -1,53 +0,0 @@
-# When marking something done/dropped, please add your name and the date.
-# This TODO started January 16th, 2002.
-
-
-+ means todo
-= means done
-- means the feature was dropped
-
-+ Logfile rotation with deletion of old logfiles and management of space 
usage. Logfile compression perhaps on the fly (write to .gz in parallel to the 
plain log then delete the plain log), and without gzip.
-+ Look at ways of making inserts self-regulating, as requests are with 
NGRouting.
-+ Find where we are using 128 bit AES keys, and upgrade them to 256 bits.
-+ Add an option for anonymizing logs - if true, never log keys in any form 
(hash them with a random node global session key, then you can use that for 
searching) - or base it on loglevel?
-+ Investigate why we get so many DOC_BAD_KEYs fetching ARKs. Error message 
looks like this:
-May 16, 2003 11:14:15 PM (freenet.client.GetRequestProcess, QThread-211, 
NORMAL): Event: The document was found to be invalid: DOC_BAD_KEY for 
freenet.client.GetRequestProcess:freenet:SSK at 
Cr1BZEnGOoH75ZV1Mqt6dUVrERgPAgM,mxFsJ7LjS0owBejcxoOnBCuZQHkM6FLd1TlDOka90Kw/d 
at 25,true before failure
-+ Add options to disable caching on all content sent by Freenet (not freenet 
content, things like the various builtin images, the servlets and so on - 
freenet CONTENT has a no cache option in the config file already), for the 
really paranoid.
-+ Track down cause of "Please close() me manually in finalizer:" messages - we 
_thought_ we had fixed them. We were wrong.
-+ Ditto for "FSDataStoreElement not closed in finalizer"
-+ Get the native FEC libraries working and include them with the installers.
-+ Implement online config updater options other than the very few already 
implemented
-+ Implement web reconfiguration interface with automatic writing out of 
options to config file and changing on the fly of all that are possible via 
above mechanism
-+ Make freenet work with just java -jar freenet.jar and go to the web 
interface... configure it on the web interface, no platform specific installer 
necessary
-+ NIO work: make trailing fields asynchronous, make message sends 
asynchronous, etc
-+ Clean up FProxy code - it is a mess - complete rewrite? Use NIO - 
LocalHTTPInterface is a good place to start, and AutoRequester now supports 
asynchronous fetches
-+ Add "rpm" target to build.xml to create a redhat install file
-+ Add "deb" target to create a debian install file
-+ Add "webstart" target to create a webstart file
-+ Make freenet nodes zero maintenance ("fire and forget") - firstly, we need 
to use fewer threads and less CPU, secondly we need to use less memory. Suggest 
profiling. Talk to Iakin about this.
-+ Support FS resize as an admin-passworded FCP command
-+ something is opening buffers, getting streams, and never closing them. This 
works OK with GC, but it would be better to find the leaks. However because it 
does work with GC, it is not urgent.
-+ limit total # of fds used by NativeFSDirectory
-+ implement the pre-mix stage to disguise HTL information
-+ when one request for a file is in progress and another comes in, combine 
them. This is harder than it looks to make work correctly (I tried in the 
native fs dir, it flamingoed up)
-+ is FNPClient being maintained? Does it handle Restarted etc correctly? Move 
it to attic if it's not being maintained
-+ Move bookkeeping variables somewhere else - RequestState base class, or a 
large object pointed to by Node or Core. Not _in_ Core, where they are now. 
Consider using logging mechanism to collect info.
-+ Allow multiple addresses in bindAddress - should be easy enough now that we 
have nio
-+ Look into the possibility of supporting _SAFE_ (this is hard, we need to 
prevent it from knowing what is in the datastore even by timing attacks) 
scripting in fproxy
-+ Look into including the length of the data in the key for a CHK. Useful for 
apps using prefetch - which are inevitable.
-+ <Fruser_> 
data:image/gif;base64,R0lGODdhIAAgAIAAAAAAAPj8+CwAAAAAIAAgAAAClYyPqcu
-          9AJyCjtIKc5w5xP14xgeO2tlY3nWcajmZZdeJcGKxrmimms1KMTa1Wg8UROx4MNUq1Hry
-          cMjHT9b6xKxaFLM6VRKzI+pKS9XtXpcbdun6uWVxJXA8pNPkdkkxhxc21LZHFOgD2KMoQ
-          Xa2KMWIJtnE2KizVUkYJVZZ1nczBxXlFopZBtoJ2diXGdNUymmJdFMAADs=
-       ( works in Mozilla at least )
-       - http://www.ietf.org/rfc/rfc2397.txt
-   -> inline images - do we want to support this in fproxy? We would need to 
-      check the MIME type and either block or filter dangerous content.
-
-+ add UPnP support to freenet (code available in Azureus' source tree)
-  + support detection of external IP address
-  + support autoconfig of port forwarding to hop NAT
-+ add a diagnostics page of current transfers' status (both local and
-  remote)
-+ measure amount of information in statistical evaluators (# samples?)
-  for use in newbie evaluation

Added: branches/legacy/stable/TODO
===================================================================
--- branches/legacy/stable/TODO                         (rev 0)
+++ branches/legacy/stable/TODO 2007-12-09 14:01:11 UTC (rev 16440)
@@ -0,0 +1,60 @@
+Building, installing, updating & running:
+- logging: scrub sensitive information
+- logrotate, logburst, log message repeat. We must be able to beat both
+  logflood DoS and attack obfuscation attacks. There are already (inadvertent) 
+  cases of logflooding ("Consecutive same winner")
+- Shell scripts preconfig.sh, start-freenet.sh, stop-freenet.sh, and update.sh
+  are outdated.
+- Find memory leaks (so we don't need a garbage collector)
+- building: unchecked operations
+- Vanessa's mod: problem: Vanessa did not license her mod.
+- building: deprecated language features
+- more platform specific build targets
+- Readme:
+  * goBrowsing?
+- general code cleanup:
+  * remove dead code
+  * check variable usage
+  * check inheritance structure
+- "Attempt to use a released TempFileBucket"
+
+Node:
+- Link level encryption DoS: Is is possible to enhance DH with JFKi?
+- General overload attack
+  http://archives.freenetproject.org/message/20071117.230422.5a8a3ac5.en.html
+  "Overload a node. Now you know all the requests it sends you are locally
+   originated."
+- Scaling properties of NGR?
+- "Look at ways of making inserts self-regulating, as requests are with
+   NGRouting."
+- DOC_BAD_KEY errors fetching ARKs
+- NIO asynchronization??? (should this go under FProxy?)
+- Premixing
+- multiple servers
+- UPnP?
+- Spread a node over several computers (Sparhawk's idea)
+
+Store:
+- Upgrade block cypher from AES128 to AES256
+- Avoid datastore access DoS: limit number of simultaneous accesses
+- Investigate log entries:
+  * "Please close() me manually in finalizer"
+  * "FSDataStoreElement not closed in finalizer"
+- Datastore request merging
+- multiple datastores
+
+FProxy/Web Interface:
+- Check filter security (CSS and HTML)
+- Cache control: nocache on servlet
+- Filter inline data and forbid page preloading
+- Remove dead default bookmarks. Add new ones? src/freenet/node/Node.java
+  Only "One More Time" still seems to work
+- Complete configurability via the web interface
+- Safe ECMAScript support
+- better diagnostics
+- default charset: replace ISO-8859-1 with UTF-8?
+
+Clients, Tools & Documentation:
+- junit generates a lot of errors
+- javadoc generates a lot of warnings
+- Enhance FCP

Copied: branches/legacy/stable/TODO.old (from rev 16289, 
branches/legacy/stable/TODO)
===================================================================
--- branches/legacy/stable/TODO.old                             (rev 0)
+++ branches/legacy/stable/TODO.old     2007-12-09 14:01:11 UTC (rev 16440)
@@ -0,0 +1,53 @@
+# When marking something done/dropped, please add your name and the date.
+# This TODO started January 16th, 2002.
+
+
++ means todo
+= means done
+- means the feature was dropped
+
++ Logfile rotation with deletion of old logfiles and management of space 
usage. Logfile compression perhaps on the fly (write to .gz in parallel to the 
plain log then delete the plain log), and without gzip.
++ Look at ways of making inserts self-regulating, as requests are with 
NGRouting.
++ Find where we are using 128 bit AES keys, and upgrade them to 256 bits.
++ Add an option for anonymizing logs - if true, never log keys in any form 
(hash them with a random node global session key, then you can use that for 
searching) - or base it on loglevel?
++ Investigate why we get so many DOC_BAD_KEYs fetching ARKs. Error message 
looks like this:
+May 16, 2003 11:14:15 PM (freenet.client.GetRequestProcess, QThread-211, 
NORMAL): Event: The document was found to be invalid: DOC_BAD_KEY for 
freenet.client.GetRequestProcess:freenet:SSK at 
Cr1BZEnGOoH75ZV1Mqt6dUVrERgPAgM,mxFsJ7LjS0owBejcxoOnBCuZQHkM6FLd1TlDOka90Kw/d 
at 25,true before failure
++ Add options to disable caching on all content sent by Freenet (not freenet 
content, things like the various builtin images, the servlets and so on - 
freenet CONTENT has a no cache option in the config file already), for the 
really paranoid.
++ Track down cause of "Please close() me manually in finalizer:" messages - we 
_thought_ we had fixed them. We were wrong.
++ Ditto for "FSDataStoreElement not closed in finalizer"
++ Get the native FEC libraries working and include them with the installers.
++ Implement online config updater options other than the very few already 
implemented
++ Implement web reconfiguration interface with automatic writing out of 
options to config file and changing on the fly of all that are possible via 
above mechanism
++ Make freenet work with just java -jar freenet.jar and go to the web 
interface... configure it on the web interface, no platform specific installer 
necessary
++ NIO work: make trailing fields asynchronous, make message sends 
asynchronous, etc
++ Clean up FProxy code - it is a mess - complete rewrite? Use NIO - 
LocalHTTPInterface is a good place to start, and AutoRequester now supports 
asynchronous fetches
++ Add "rpm" target to build.xml to create a redhat install file
++ Add "deb" target to create a debian install file
++ Add "webstart" target to create a webstart file
++ Make freenet nodes zero maintenance ("fire and forget") - firstly, we need 
to use fewer threads and less CPU, secondly we need to use less memory. Suggest 
profiling. Talk to Iakin about this.
++ Support FS resize as an admin-passworded FCP command
++ something is opening buffers, getting streams, and never closing them. This 
works OK with GC, but it would be better to find the leaks. However because it 
does work with GC, it is not urgent.
++ limit total # of fds used by NativeFSDirectory
++ implement the pre-mix stage to disguise HTL information
++ when one request for a file is in progress and another comes in, combine 
them. This is harder than it looks to make work correctly (I tried in the 
native fs dir, it flamingoed up)
++ is FNPClient being maintained? Does it handle Restarted etc correctly? Move 
it to attic if it's not being maintained
++ Move bookkeeping variables somewhere else - RequestState base class, or a 
large object pointed to by Node or Core. Not _in_ Core, where they are now. 
Consider using logging mechanism to collect info.
++ Allow multiple addresses in bindAddress - should be easy enough now that we 
have nio
++ Look into the possibility of supporting _SAFE_ (this is hard, we need to 
prevent it from knowing what is in the datastore even by timing attacks) 
scripting in fproxy
++ Look into including the length of the data in the key for a CHK. Useful for 
apps using prefetch - which are inevitable.
++ <Fruser_> 
data:image/gif;base64,R0lGODdhIAAgAIAAAAAAAPj8+CwAAAAAIAAgAAAClYyPqcu
+          9AJyCjtIKc5w5xP14xgeO2tlY3nWcajmZZdeJcGKxrmimms1KMTa1Wg8UROx4MNUq1Hry
+          cMjHT9b6xKxaFLM6VRKzI+pKS9XtXpcbdun6uWVxJXA8pNPkdkkxhxc21LZHFOgD2KMoQ
+          Xa2KMWIJtnE2KizVUkYJVZZ1nczBxXlFopZBtoJ2diXGdNUymmJdFMAADs=
+       ( works in Mozilla at least )
+       - http://www.ietf.org/rfc/rfc2397.txt
+   -> inline images - do we want to support this in fproxy? We would need to 
+      check the MIME type and either block or filter dangerous content.
+
++ add UPnP support to freenet (code available in Azureus' source tree)
+  + support detection of external IP address
+  + support autoconfig of port forwarding to hop NAT
++ add a diagnostics page of current transfers' status (both local and
+  remote)
++ measure amount of information in statistical evaluators (# samples?)
+  for use in newbie evaluation

Modified: branches/legacy/stable/src/freenet/Core.java
===================================================================
--- branches/legacy/stable/src/freenet/Core.java        2007-12-08 23:48:59 UTC 
(rev 16439)
+++ branches/legacy/stable/src/freenet/Core.java        2007-12-09 14:01:11 UTC 
(rev 16440)
@@ -745,18 +745,19 @@
      * @return Returns the randSource.
      */
     public static RandomSourcePool getRandSource() {
-        //Hmmm.. I dont think we need to synchornize on this because:
-        //1. Does it really matter if we would
-        //2. Do we multithread as early as the first call here..
+        // Hmmm.. I dont think we need to synchornize on this because:
+        // 1. Does it really matter if we would
+        // 2. Do we multithread as early as the first call here..
         if(randSource == null){
-               //Use a RandomSourcePool of 'ThrottledAsyncEntropyYarrow's 
instead of a single one
-               //in order to decrease the chance for lock contention on access 
to this very well-used resource
+               // Use a RandomSourcePool of 'ThrottledAsyncEntropyYarrow's 
instead of a single one
+               // in order to decrease the chance for lock contention on 
access to this very well-used resource
+               // /dev/[u]random will be used anyway, so don't use it as seed
             randSource = new RandomSourcePool(new RandomSource[]{
-                               new ThrottledAsyncEntropyYarrow((new 
File("/dev/urandom").exists()? "/dev/urandom" : "prng.seed"), "SHA1", 
"Rijndael",true,20),
-                               new ThrottledAsyncEntropyYarrow((new 
File("/dev/urandom").exists()? "/dev/urandom" : "prng.seed"), "SHA1", 
"Rijndael",false,20),
-                               new ThrottledAsyncEntropyYarrow((new 
File("/dev/urandom").exists()? "/dev/urandom" : "prng.seed"), "SHA1", 
"Rijndael",false,20),
-                               new ThrottledAsyncEntropyYarrow((new 
File("/dev/urandom").exists()? "/dev/urandom" : "prng.seed"), "SHA1", 
"Rijndael",false,20),
-                               new ThrottledAsyncEntropyYarrow((new 
File("/dev/urandom").exists()? "/dev/urandom" : "prng.seed"), "SHA1", 
"Rijndael",false,20)
+                               new ThrottledAsyncEntropyYarrow("prng.seed", 
"SHA1", "Rijndael",true,20),
+                               new ThrottledAsyncEntropyYarrow("prng.seed", 
"SHA1", "Rijndael",false,20),
+                               new ThrottledAsyncEntropyYarrow("prng.seed", 
"SHA1", "Rijndael",false,20),
+                               new ThrottledAsyncEntropyYarrow("prng.seed", 
"SHA1", "Rijndael",false,20),
+                               new ThrottledAsyncEntropyYarrow("prng.seed", 
"SHA1", "Rijndael",false,20)
             });
         }
         return randSource;

Deleted: branches/legacy/stable/src/freenet/client/SplitFileDownloadStatus.java~
===================================================================
--- branches/legacy/stable/src/freenet/client/SplitFileDownloadStatus.java~     
2007-12-08 23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/src/freenet/client/SplitFileDownloadStatus.java~     
2007-12-09 14:01:11 UTC (rev 16440)
@@ -1,211 +0,0 @@
-package freenet.client;
-
-import freenet.message.client.FEC.SegmentHeader;
-import freenet.client.*;
-import freenet.client.events.*;
-
-/**
- * A listener that collects information about the progress
- * of SplitFile downloads.
- * <p>
- * @author giannij
- */
-public class SplitFileDownloadStatus implements ClientEventListener {
-
-    protected SegmentHeader header;
-    protected int queued;
-    protected int running;
-    protected int downloaded;
-    protected int failed;
-    protected int retried;
-    protected int rnfs;
-    protected int dnfs;
-    protected int statusCode = STARTING;
-    protected long touched =  System.currentTimeMillis();
-
-    // Exit status values.
-    public final static int STARTING = 1;
-    public final static int FETCHING_BLOCKS = 2;
-    public final static int DECODING = 3;
-    public final static int SUCCEEDED = 4;
-    public final static int FAILED = 5;
-    public final static int CANCELED = 6;
-
-    protected void reset() {
-        header = null;
-        queued = 0;
-        running = 0;
-        downloaded = 0;
-        failed = 0;
-        retried = 0;
-        rnfs = 0;
-        dnfs = 0;
-        touched = System.currentTimeMillis();
-    }
-
-    /**
-     * The current segment.
-     **/
-    public final synchronized SegmentHeader segment() { return header; }
-
-    /**
-     * The number of data and check blocks that are
-     * queued up to be run.
-     **/
-    public final synchronized int blocksQueued() { return queued; }
-
-    /**
-     * The number of requests that are currently being executed.
-     **/
-    public final synchronized int blocksRunning() { return running; }
-
-
-    /**
-     * The number of blocks that have been successfully fetched.
-     **/
-    public final synchronized int blocksDownloaded() { return downloaded; }
-
-
-    /**
-     * The number of blocks that have failed.  Blocks are only 
-     * counted as failed after all allowed retries have failed.
-     **/
-    public final synchronized int blocksFailed() { return failed; }
-
-
-    /**
-     * The total number of blocks that were queued to be retried 
-     * after failing to download.
-     **/
-    public final synchronized int blocksRetried() { return retried; }
-
-    /**
-     * The number of request attemps that have failed 
-     * with RouteNotFound errors.
-     * <p>
-     * Note that because of retrying this can be
-     * incremented more than once for each request queued.
-     **/
-    public final synchronized int rnfs() { return rnfs; }
-
-    /**
-     * The number of request attemps that have failed 
-     * with DataNotFound errors.
-     * <p>
-     * Note that because of retrying this can be
-     * incremented more than once for each request queued.
-     **/
-    public final synchronized int dnfs() { return dnfs; }
-
-    /**
-     * The time the that the last low level status update
-     * event was retrieved. 
-     */
-    public final synchronized long touched() { return touched; }
-
-    /**
-     * A code indicating the status of the request.
-     */
-    public final synchronized int statusCode() { return statusCode; }
-    
-
-    private final static String[] names = { "STARTING","FETCHING_BLOCKS",
-                                            "DECODING", "SUCCEEDED",
-                                            "FAILED", "CANCELED" };
-    
-
-    public final static String statusString(int statusCode) {
-        if (statusCode < 1 || statusCode > names.length) {
-            return "UNKNOWN";
-        }
-
-        return names[statusCode - 1];
-    }
-
-    public synchronized void receive(ClientEvent ce) {
-        //System.err.println("SFDS: " + ce.getDescription());
-        if (!(ce instanceof SplitFileEvent)) {
-            return;
-        }
-        
-        touched = System.currentTimeMillis();
-        
-        switch (ce.getCode()) {
-        case SegmentRequestStartedEvent.code:
-            reset();
-            header = ((SegmentRequestStartedEvent)ce).getHeader();
-            statusCode = FETCHING_BLOCKS;
-            break;
-        case SegmentRequestFinishedEvent.code: {
-            SegmentRequestFinishedEvent rf = (SegmentRequestFinishedEvent)ce;
-            if ((header.getSegments() == header.getSegmentNum() + 1) ||
-                (rf.getExitCode() != SplitFileEvent.SUCCEEDED)) {
-                switch(rf.getExitCode()) {
-                    case SplitFileEvent.SUCCEEDED:
-                        statusCode = SUCCEEDED; break;
-                    case SplitFileEvent.FAILED:
-                        statusCode = FAILED; break;
-                    case SplitFileEvent.CANCELED:
-                        statusCode = CANCELED; break;
-                }
-            }
-            break;
-        }
-        case BlockQueuedEvent.code:
-            queued++;
-            break;
-        case BlockRequeuedEvent.code: {
-            retried++;
-            queued++;
-            running--;
-            BlockRequeuedEvent re = (BlockRequeuedEvent)ce;
-            if (re.reason() != null) {
-                if (re.reason() instanceof RouteNotFoundEvent) {
-                    rnfs++;
-                }
-                else if (re.reason() instanceof DataNotFoundEvent) {
-                    dnfs++;
-                }
-            }
-            break;
-        }
-        
-        case BlockStartedEvent.code:
-            running++;
-            queued--;
-            break;
-        case BlockFinishedEvent.code: {            
-            BlockFinishedEvent fe = (BlockFinishedEvent)ce;
-            running--;
-
-            if (fe.reason() != null) {
-                if (fe.reason() instanceof RouteNotFoundEvent) {
-                    rnfs++;
-                }
-                else if (fe.reason() instanceof DataNotFoundEvent) {
-                    dnfs++;
-                }
-            }
-
-            if (fe.exitCode() == SplitFileEvent.SUCCEEDED) {
-                downloaded++;
-            }
-            else if (fe.exitCode() == SplitFileEvent.FAILED) {
-                failed++;
-            }
-            // Don't count canceled blocks
-            break;
-
-        }
-        case SegmentDecodingEvent.code:
-            statusCode = DECODING;
-            break;
-        }
-        notifyAll();
-    }
-}
-
-
-
-
-

Deleted: branches/legacy/stable/src/freenet/client/SplitFileDownloader.java~
===================================================================
--- branches/legacy/stable/src/freenet/client/SplitFileDownloader.java~ 
2007-12-08 23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/src/freenet/client/SplitFileDownloader.java~ 
2007-12-09 14:01:11 UTC (rev 16440)
@@ -1,1151 +0,0 @@
-// REDFLAG: handle releasing ArrayBucketSink buckets on failure before FEC 
decode.
-
-package freenet.client;
-
-import freenet.Core;
-import freenet.Connection;
-import freenet.support.Logger;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
-import freenet.support.NullBucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketSink;
-import freenet.support.BucketSequence;
-import freenet.support.ArrayBucketSink;
-import freenet.client.Client;
-import freenet.client.events.StateReachedEvent;
-import freenet.client.events.DataNotFoundEvent;
-import freenet.client.events.RouteNotFoundEvent;
-
-import freenet.client.ClientFactory;
-import freenet.client.metadata.*;
-import freenet.message.client.FEC.BlockMap;
-import freenet.message.client.FEC.SegmentHeader;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.MalformedURLException;
-import java.util.Vector;
-
-// REDFLAG: double check nested locks
-//          Have another look at the 
-//          SplitFileLoader.this / retryQueue
-//          nested lock issue.
-//
-//          I think it's ok because only
-//          the worker thread holds nested locks.
-
-/*
-  This code is distributed under the GNU Public Licence (GPL)
-  version 2.  See http://www.gnu.org/ for further details of the GPL.
-*/
-
-/**
- * Class to do streamed downloads of Freenet 0.4 SplitFiles
- * using multiple concurrent threads.
- *
- * @author giannij
- **/
-public class SplitFileDownloader {
-
-    public final static int STARTING = 1;
-    public final static int DOWNLOADING_SEGMENT = 2;
-    public final static int FEC_DECODING = 3;
-    public final static int FINISHED = 4;
-    public final static int ABORTED = 5;
-    public final static int FAILED = 6;
-
-    //public final static int TRANSFERRING = 4; // REDFLAG: untenable?
-
-    private int state = STARTING;
-    private Status finalStatus = new Status();
-    
-    private final synchronized void setState(int value) {
-        state = value;
-    }
-
-    // For UI. *not* guaranteed to be in a consistent state.
-    public static class Status {
-        public int segment;
-        public int segments;
-        // hmmm. Digging myself in even deeper with 
-        // fixed block size assumption.
-        public int blockSize;
-        public int blocksRequired;
-        public int runningThreads;
-        public int blocksQueued;
-        public int blocksDownloaded;
-        // definitively, after retries exhausted.
-        public int blocksFailed;
-        // Can happen more than once per block
-        // if retrying is enabled.
-        public int dnfCount;
-        public int rnfCount;
-        // Requests that RNFed without ever leaving the 
-        // node.
-        public int localRNFCount;
-        public long lastActiveMs;
-
-        // LATER: for msg, "fec decoding 15 missing data blocks..."
-        //public int nDataBlocks;
-        public int retries;
-        public int state;
-    }
-    
-    // REDFLAG: event handler?
-
-    public synchronized Status getStatus() {
-        if (!isRunning()) {
-            return finalStatus;
-        }
-
-        Status ret = new Status();
-        ret.segments = segments;
-        ret.segment = currentSegment;
-        ret.blockSize = reportedBlockSize;
-        ret.blocksRequired = requiredSuccesses;
-        ret.runningThreads = nPending;
-        ret.blocksQueued = requestQueue.size();
-        ret.blocksDownloaded = successes;
-        ret.blocksFailed = failures;
-        ret.dnfCount = dnfCount;
-        ret.rnfCount = rnfCount;
-        ret.localRNFCount = localRNFCount;
-        ret.retries = cumulativeRetries;
-        ret.lastActiveMs = lastActiveMs;
-        ret.state = state;
-
-        return ret;
-    }
-
-    public SplitFileDownloader(int nThreads) {
-       this.nThreads = nThreads;
-        this.finalStatus.lastActiveMs = System.currentTimeMillis();
-    }
-    
-    public final void setHtl(int htl) { this.htl = htl;}
-    public final int getHtl() { return htl; }
-    
-    public final void setMaxRetries(int retries) { this.maxRetries = retries;}
-    public final int getMaxRetries() { return maxRetries; }
-
-    public final void setRetryHtlIncrement(int increment) { 
this.retryHtlIncrement = increment;}
-    public final int getRetryHtlIncrement() { return retryHtlIncrement; }
-
-    public final void setThreads(int nThreads) { this.nThreads = nThreads; }
-    public final int getThreads() { return nThreads; }
-
-    public final void setSkipDataStore(boolean skip) {
-        skipDS = skip;
-    }
-    // runs in another thread.
-    public synchronized BucketSequence start(SplitFile sf, ClientFactory 
factory,
-                                            BucketFactory bucketFactory,
-                                             int offset, int nBytes, 
Connection conn) {
-
-       if (isRunning()) {
-           throw new IllegalStateException("The SplitFileDownloader is already 
running.");
-       }
-
-       this.factory = factory;
-       this.bucketFactory = bucketFactory;
-       this.blockURIs = sf.getBlockURIs();
-       this.conn = conn;
-        this.reportedBlockSize = sf.getBlockSize();
-
-       // Reset state
-       nPending = 0;
-       failing = false;
-        stopping = false;
-       startedCanceling = false;
-        aborted = false;
-        currentSegment = 0;
-        segments = 1;
-        cumulativeRetries = 0;
-        dnfCount = 0;
-        rnfCount = 0;
-        localRNFCount = 0;
-
-        startBlock = offset/ sf.getBlockSize();
-        int startBlockOffset = offset - startBlock * sf.getBlockSize();
-        endBlock = (offset + nBytes) / sf.getBlockSize();
-
-        this.sequence = new BucketSequence(startBlock, endBlock, 
startBlockOffset,
-                                           nBytes, bucketFactory);
-
-        sink = sequence;
-        allowedFailures = 0;
-        requiredSuccesses = sf.getBlockCount();
-
-       Thread t = new Thread(task, "SplitFileDownloader -- worker thread");
-       t.start();
-       worker = t;
-        setState(STARTING);
-       return sequence; 
-    }
-
-    // Safer, doesn't depend on blockSize.
-    // Runs in another thread.
-    public synchronized BucketSequence start(SplitFile sf, ClientFactory 
factory,
-                                            BucketFactory bucketFactory,
-                                             FECTools tools, 
-                                             Connection conn) throws 
IOException {
-
-       if (isRunning()) {
-           throw new IllegalStateException("The SplitFileDownloader is already 
running.");
-       }
-
-       this.factory = factory;
-       this.bucketFactory = bucketFactory;
-       this.blockURIs = sf.getBlockURIs();
-        this.checkURIs = sf.getCheckBlockURIs();
-       this.conn = conn;
-        this.reportedBlockSize = sf.getBlockSize();
-
-       // Reset state
-       nPending = 0;
-       failing = false;
-        stopping = false;
-       startedCanceling = false;
-        aborted = false;
-        currentSegment = 0;
-        segments = 1;
-        cumulativeRetries = 0;
-        dnfCount = 0;
-        rnfCount = 0;
-        localRNFCount = 0;
-
-        // REDFLAG: size changed to long. hmmm... problems in other places?
-        this.sequence = new BucketSequence((int)sf.getSize(), bucketFactory);
-        // By default buckets go directly into the Bucket Sequence.
-        sink = sequence;
-
-        // Defaults for non-redundant downloading.
-        allowedFailures = 0;
-        requiredSuccesses = sf.getBlockCount();
-        startBlock = 0;
-        endBlock = sf.getBlockCount() - 1;
-
-        fecTools = null;
-        headersAndMaps = null;
-        if ((tools != null) && (sf.getCheckBlockCount() > 0)) {
-            // Ask the SplitFile which decoder we should load.
-            String decoderName = sf.getFECAlgorithm();
-            Bucket sfMeta = bucketFactory.makeBucket(-1); // REDFLAG: GRRRRR
-            try {
-                DocumentCommand doc = new DocumentCommand(new 
MetadataSettings());
-                doc.addPart(sf);
-            
-                Metadata md = new Metadata(new MetadataSettings());
-                md.addDocument(doc);
-                md.writeTo(sfMeta.getOutputStream());
-                // Throws if it can't find a decoder.
-                headersAndMaps = tools.segmentSplitFile(-1, sfMeta);
-                fecTools = tools;
-            }
-            catch (IOException ioe) {
-                System.err.println("Couldn't get decoder!");
-            }
-            catch (InvalidPartException ioe) {
-                // Something went very wrong.
-                throw new RuntimeException(ioe.toString());
-            }
-
-            finally {
-                bucketFactory.freeBucket(sfMeta);
-            }
-            
-            segments = headersAndMaps[0].header.getSegments();
-
-            // startBlock, endBlock, not used by FEC codePath
-            // allowedFailures, requiredSuccesses will be set by
-            // createRequests(). 
-        }
-
-       Thread t = new Thread(task, "SplitFileDownloader -- worker thread");
-       t.start();
-        worker = t;
-        setState(STARTING);
-       return sequence; 
-    }
-
-    private void setupSinkForSegment(int n) {
-        ArrayBucketSink a =  new ArrayBucketSink();
-        a.setLength(headersAndMaps[n].header.getBlockCount() +
-                    headersAndMaps[n].header.getCheckBlockCount());
-        
-        sink = a;
-    }
-
-    public synchronized void cancel() {
-        aborted = true;
-       failing = true;
-        stopping = true;
-        if (worker != null) {
-            worker.interrupt();
-        }
-       notifyAll();
-    }
-
-    public synchronized boolean isRunning() { return worker != null; }
-
-    ////////////////////////////////////////////////////////////
-
-    private final synchronized boolean handleBucket(Bucket b, int blockNum, 
boolean success) {
-        boolean ret = success;
-       try {
-           if (success && (!stopping)) {
-                // hmmm... We touch sequence / FECDecoder with a lock on
-                // SplitFileDownloader, ok?
-                //System.err.println("putting bucket: " + blockNum);
-               sink.putBucket(b, blockNum);
-               ret = true;
-           }
-           else {
-                //System.err.println("discarding bucket: " + blockNum);
-               bucketFactory.freeBucket(b);
-           }
-       }
-       catch (Exception e) {
-            //e.printStackTrace();
-            // REDFLAG: hiding InterruptedException ok?
-            try {bucketFactory.freeBucket(b);} catch (Exception e1) {}
-       }
-        return ret;
-    }
-
-    private final synchronized void requestFinished(Bucket b, int blockNum,  
boolean success) {
-        //  System.err.println("SplitFileDownloader.requestFinished -- " + 
blockNum + " " +
-        //                             success);
-
-        if (!handleBucket(b, blockNum, success)) {
-            failures++;
-            if (failures > allowedFailures) {
-                failing = true;
-                stopping = true;
-            }
-        }
-        else {
-            successes++;
-            if (successes >= requiredSuccesses) {
-                stopping = true;
-            }
-        }
-        nPending--;
-        SplitFileDownloader.this.notifyAll();
-    }
-
-    private final void queueRetry(BlockRequest request) {
-       synchronized (requestQueue) {
-            // IMPORTANT: 
-            // Non-redundant downloads won't work if 
-            // even a single block fails, so retry 
-            // the failed request as soon as possible.
-           if (fecTools == null) {
-                // Retry this request next.
-                requestQueue.insertElementAt(request, 0);
-            }
-            else {
-                // Retry after all other pending 
-                // requests are tried.
-                requestQueue.addElement(request);
-            }
-       }
-       synchronized (this) {
-           notifyAll();
-       }
-    }
-
-    private final void cancelRunningRequests() {
-        Vector copy = null;
-        synchronized (this) {
-            // runningRequests could shrink while the loop
-            // is running.
-            copy = (Vector)runningRequests.clone();
-            startedCanceling = true;
-        }
-
-        // IMPORTANT:^*&^*&(^*&^*&!@^&!^ InternalClient work around.
-        // Can't hold locks on any client objects while canceling
-        // or we may deadlock.
-        
-       for (int i = 0; i < copy.size(); i++) {
-            BlockRequest request = 
-                (BlockRequest)copy.elementAt(i);
-           if (request != null) {
-                request.cancel();
-           }
-       }
-    }
-
-    // This is a hack to detect when the client has
-    // dropped the connection.  It is ugly, but
-    // it keeps us from running many unnecessary
-    // conncurrent requests.
-    private final boolean pingConnection() throws IOException {
-       if (conn != null) {
-           int oldTimeout = -1;
-           InputStream in =  null;
-           Exception provoked = null;
-           try {
-               oldTimeout = conn.getSoTimeout(); 
-               conn.setSoTimeout(1); 
-               in = conn.getIn();
-               in.read();
-               Core.logger.log(this, "SplitFileDownloader.pingConnection -- 
hmmm actually read.", 
-                            Logger.MINOR);
-           }
-           catch (Exception e) {
-               provoked = e;
-           }
-           if (provoked == null || (!(provoked instanceof 
InterruptedIOException))) {
-               conn = null; // once is enough.
-                Core.logger.log(this, "The client dropped the connection.", 
-                                Logger.MINOR);
-                return true;
-           }
-
-           if (oldTimeout != -1) {
-               try {conn.setSoTimeout(oldTimeout);} catch (Exception e1) {}
-           }
-       }
-        return false;
-    }
-
-    private static void shuffle(Vector requests) {
-        Vector list = (Vector)requests.clone();
-        int count = 0;
-        while (list.size() > 0) {
-            int index = (int)(Math.random() * list.size());
-            requests.setElementAt(list.elementAt(index), count);
-            list.removeElementAt(index);
-            count++;
-        }
-    }
-
-    private final synchronized void createRequests(Vector requests) throws 
IOException {
-        if (failing) {
-            return;
-        }
-
-        // Reset for the new segment.
-        stopping = false;
-
-        requests.removeAllElements();
-        if (fecTools == null) {
-            final int len = endBlock - startBlock + 1;
-            for (int i = 0; i < len; i++) {
-                // Only data, no check blocks.
-                requests.addElement(new BlockRequest(blockURIs[i + 
startBlock], i + startBlock, htl));
-            }
-        }
-        else {
-            SegmentHeader header = headersAndMaps[currentSegment].header;
-            BlockMap map = headersAndMaps[currentSegment].map;
-
-            final int k = header.getBlockCount();
-            final int n = header.getBlockCount() + header.getCheckBlockCount();
-            
-            String[] dataCHKs = map.getDataBlocks();
-            int i = 0;
-            for (i = 0; i < dataCHKs.length; i++) {
-                requests.addElement(new BlockRequest(dataCHKs[i], 
-                                                     i, htl));
-            }
-
-            String[] checkCHKs = map.getCheckBlocks();
-            for (i = 0; i < checkCHKs.length; i++) {
-                requests.addElement(new BlockRequest(checkCHKs[i], 
-                                            i  + dataCHKs.length, htl));
-            }
-
-            allowedFailures = n - k;
-            requiredSuccesses = k;
-
-            System.err.println("Starting redundant download of segment " +
-                               currentSegment + ". Need " + k +
-                               " of " + n + " blocks.");
- 
-            // Shuffle to keep some blocks from becoming more popular
-            // than others in Freenet.
-            shuffle(requests);
-
-            // Grab the buckets so we can decode them.
-            setupSinkForSegment(currentSegment); 
-        }
-    }
-
-    // REDFLAG: remove eventually
-    private static final String arrayToString(int[] array) {
-        StringBuffer ret = new StringBuffer();
-        for (int i = 0; i < array.length; i++) {
-            ret.append(Integer.toString(array[i]) + " ");
-        }
-        return ret.toString().trim();
-    }
-
-    // Returns true if there are more segments to be decoded.
-    private final boolean doFECDecode() throws IOException {
-        if ((fecTools != null) && !failing) {
-            setState(FEC_DECODING);
-
-            SegmentHeader header = headersAndMaps[currentSegment].header;
-
-            Bucket[] blocks = null;
-            Bucket[] decoded = null;
-
-            try {
-                blocks = ((ArrayBucketSink)sink).getBuckets();
-                // We own the buckets now.  If any other
-                // thread is trying to put buckets that's
-                // a bug, so make sure we see it.
-                ((ArrayBucketSink)sink).setLength(0);
-
-                Vector list = new Vector();
-                int i = 0;
-                // Find data indices
-                for (i = 0; i < header.getBlockCount(); i++) {
-                    if (blocks[i] != null) {
-                        list.addElement(new Integer(i));
-                    }
-                }
-                int[] dataIndices = new int[list.size()];
-                for (i = 0; i < list.size(); i++) {
-                    dataIndices[i] = ((Integer)list.elementAt(i)).intValue();
-                }
-                
-                list.removeAllElements();
-                // Find check  indices
-                for (i = 0; i < header.getCheckBlockCount(); i++) {
-                    if (blocks[i + header.getBlockCount()] != null) {
-                        list.addElement(new Integer(i + 
header.getBlockCount()));
-                    }
-                }
-                int[] checkIndices = new int[list.size()];
-                for (i = 0; i < list.size(); i++) {
-                    checkIndices[i] = ((Integer)list.elementAt(i)).intValue();
-                }
-                
-                list.removeAllElements();
-                // Find required data  indices
-                for (i = 0; i < header.getBlockCount(); i++) {
-                    if (blocks[i] == null) {
-                        list.addElement(new Integer(i));
-                    }
-                }
-                int[] requestedIndices = new int[list.size()];
-                for (i = 0; i < list.size(); i++) {
-                    requestedIndices[i] = 
((Integer)list.elementAt(i)).intValue();
-                }
-                list.removeAllElements();
-
-                // Get non-null blocks
-                Bucket[] nonNulls = new Bucket[dataIndices.length + 
checkIndices.length];
-                for (i = 0; i < dataIndices.length; i++) {
-                    nonNulls[i] = blocks[dataIndices[i]];
-                }
-                for (i = 0; i < checkIndices.length; i++) {
-                    nonNulls[i + dataIndices.length] = blocks[checkIndices[i]];
-                }
-            
-                // Only decode if we are missing some data blocks.
-                if (dataIndices.length <header.getBlockCount()) {
-                    // FEC decode. Throws on failure
-                    decoded =  fecTools.decodeSegment(header, 
-                                                      dataIndices, 
-                                                      checkIndices, 
-                                                      requestedIndices,
-                                                      nonNulls);
-                    // Add the decoded blocks.
-                    for (i = 0; i < requestedIndices.length; i++) {
-                        blocks[requestedIndices[i]] = decoded[i];
-                    }
-
-                    decoded = null;
-                }                
-                // Now write the entire segment to the sequence.
-                for (i = 0; i < header.getBlockCount(); i++) {
-                    sequence.putBucket(blocks[i], i + 
header.getDataBlockOffset());
-                    blocks[i] = null; // Give up ownership of data blocks.
-                }
-
-                Core.logger.log(this, "FEC Decode succeeded.", 
-                                Logger.DEBUGGING);
-            }
-            catch (IOException e) {
-                Core.logger.log(this, "FEC Decode failed.", 
-                                Logger.DEBUGGING);
-                throw e;
-            }
-
-            finally {
-                BucketTools.freeBuckets(bucketFactory, blocks);
-                // NOTE: We always free the check blocks
-                //       even on success.
-                BucketTools.freeBuckets(bucketFactory, decoded);
-            }
-            
-            currentSegment++;
-            if (currentSegment >= segments) {
-                return false;
-            }
-            // createRequests handles setting up the FEC for the
-            // next segment.
-            return true;
-        }
-        return false;
-    }
-
-    // Runs requests in requestQueue and waits for 
-    // them to finish. Waits even on exception.
-    private final void runRequests()
-        throws InterruptedException, IOException {
-        Throwable t = null;
-        
-        boolean needToCancel = false;
-        unsynchronized_loop:
-        for (;;) {
-            if (needToCancel) {
-                // IMPORTANT: 
-                // The purpose of all of this flow control gobbledygook 
-                // is to cancel in an unlocked scope.
-                cancelRunningRequests();
-            }
-
-            needToCancel = false;
-
-            synchronized (this) {
-                while (((requestQueue.size() > 0) && (!stopping)) ||
-                       (nPending > 0)) {
-
-                    if (!stopping) {
-                        stopping = pingConnection();
-                    }
-                   if(Core.logger.shouldLog(Core.logger.DEBUG))
-                       Core.logger.log(this, "early: nPending = "+nPending+
-                                       ", nThreads = "+
-                                       nThreads+", rq.size = "+
-                                       requestQueue.size() + ", stopping = "+
-                                       stopping + ", startedCanceling = "+
-                                       startedCanceling, Core.logger.DEBUG);
-                   
-                    if (stopping && (!startedCanceling)) {
-                        needToCancel = true;
-                       if(Core.logger.shouldLog(Core.logger.DEBUG))
-                           Core.logger.log(this, "Continuing as stopping",
-                                           Core.logger.DEBUG);
-                        continue unsynchronized_loop;
-                    }
-                   if(Core.logger.shouldLog(Core.logger.DEBUG))
-                       Core.logger.log(this, "Still here", Core.logger.DEBUG);
-                    // Start tasks.
-                    while ((nPending < nThreads) && 
-                           (requestQueue.size() > 0) && 
-                           (!stopping)) {
-                       if(Core.logger.shouldLog(Core.logger.DEBUG))
-                           Core.logger.log(this, "In runRequests.while: "+
-                                           "nPending = "+nPending+", nThreads 
= "+
-                                           nThreads+", rq.size = "+
-                                           requestQueue.size(), 
-                                           Core.logger.DEBUG);
-                        BlockRequest request = null;
-                       
-                        // hmmm...
-                        // nested locks: (this), requestQueue.
-                        synchronized (requestQueue) {
-                            request = (BlockRequest)requestQueue.elementAt(0);
-                            requestQueue.removeElementAt(0);
-                        }
-                        
-                        boolean reallyStarted = false;
-                        try {
-                            Client c = factory.getClient(request);
-                            request.setClient(c);
-                           if(Core.logger.shouldLog(Core.logger.DEBUG))
-                               Core.logger.log(this, "requesting block " + 
-                                               request.getBlockNumber(), 
-                                               Logger.DEBUGGING);
-                            nPending++;
-                            c.start();
-                            reallyStarted = true;
-                        }
-                        catch (Throwable uho) {
-                           Core.logger.log(this, "IGNORED EXCEPTION", uho,
-                                           Core.logger.MINOR);
-                            System.err.println("IGNORED EXCEPTION: ");
-                            uho.printStackTrace();
-                            cancel();
-                            t = uho; // hmmm... Exception masking
-                        }
-                        finally {
-                           if(Core.logger.shouldLog(Core.logger.DEBUG))
-                               Core.logger.log(this, 
-                                               "Running runRequests.finally",
-                                               Core.logger.DEBUG);
-                            if (reallyStarted) {
-                                runningRequests.addElement(request);
-                               if(Core.logger.shouldLog(Core.logger.DEBUG))
-                                   Core.logger.log(this, "Added element 
"+request,
-                                                   Core.logger.DEBUG);
-                            }
-                            else {
-                                nPending--;
-                            }
-                           if(Core.logger.shouldLog(Core.logger.DEBUG))
-                               Core.logger.log(this, "nPending now "+nPending,
-                                               Core.logger.DEBUG);
-                        }
-                    }
-                    // REDFLAG: Stall???
-                    try {
-                       if(Core.logger.shouldLog(Core.logger.DEBUG))
-                           Core.logger.log(this, "Trying...", 
Core.logger.DEBUG);
-                        SplitFileDownloader.this.wait(POLLINGINTERVAL_MS);
-                    }
-                    catch (InterruptedException ie) {
-                        t = ie; // hmmm... Exception masking
-                    }
-                   if(Core.logger.shouldLog(Core.logger.DEBUG))
-                       Core.logger.log(this, "Leaving...", Core.logger.DEBUG);
-                }
-            }
-            break unsynchronized_loop;
-        }
-       if(Core.logger.shouldLog(Core.logger.DEBUG))
-           Core.logger.log(this, "Out of while()", Core.logger.DEBUG);
-        // Throw only after all pending requests have been
-        // canceled.
-        if (t != null) {
-            if (t instanceof InterruptedException) {
-                throw (InterruptedException)t;
-            }
-            else if (t instanceof IOException) {
-                throw (IOException)t;
-            } 
-            else {
-                // Somewhat underwhelming style.
-               if(Core.logger.shouldLog(Core.logger.DEBUG))
-                   Core.logger.log(this, "runRequests throwing because: ",
-                                   t, Core.logger.DEBUG);
-                throw new IOException(t.toString());
-            }
-        }
-       if(Core.logger.shouldLog(Core.logger.DEBUG))
-           Core.logger.log(this, "Exiting runRequests without throwing",
-                           Core.logger.DEBUG);
-    }
-
-    public class RunnableImpl implements Runnable {
-       public void run() {
-            boolean userAbort = false;
-           try {
-                boolean moreSegments = false;
-                do {
-                    // Reset for each segment.
-                    failures = 0;
-                    successes = 0;
-                    nPending = 0;                
-                    cumulativeRetries = 0;
-                    dnfCount = 0;
-                    rnfCount = 0;
-                    localRNFCount = 0;
-
-                    runningRequests.removeAllElements();
-                    createRequests(requestQueue);
-                    setState(DOWNLOADING_SEGMENT);
-                    runRequests();
-                    if (!failing) {
-                        lastActiveMs = System.currentTimeMillis();
-                        moreSegments = doFECDecode();
-                        lastActiveMs = System.currentTimeMillis();
-                    }
-                } while (moreSegments && (!failing));
-           }
-           catch (Exception e) {
-               if (Core.logger.shouldLog(Core.logger.DEBUG))
-                   Core.logger.log(this, e.toString(), Logger.DEBUGGING);
-               e.printStackTrace();
-               // So that we can distinguish user abort
-               // for exit status.
-               userAbort = aborted;
-               cancel();
-           }
-           finally {
-               if (sequence != null) {
-                   if (failing) {
-                       // Frees buckets and forces an error on the client 
input stream.
-                       sequence.abort("Couldn't read one or more segments from 
Freenet.", -1);
-                   }
-                   else {
-                       // REDFLAG: really nesc.???
-                       // Let the bucket sequence know that there's no more 
data coming.
-                       sequence.eod();
-                   }
-               }
-
-               synchronized (SplitFileDownloader.this) {
-                    if ((successes >= requiredSuccesses) && (!failing)) {
-                        setState(FINISHED);
-                    }
-                    else if (userAbort) {
-                        setState(ABORTED);
-                    }
-                    else {
-                       Core.logger.log(this, "run(): successes="+successes+
-                                       " requiredSuccesses="+requiredSuccesses+
-                                       " failing="+failing, 
Core.logger.NORMAL);
-                        setState(FAILED);
-                    }
-                    // Note: 
-                    // The BucketSequence can still be streaming data
-                    // when we return...
-                    
-                    finalStatus = getStatus();
-                   worker = null;
-                   SplitFileDownloader.this.notifyAll();
-               }
-           }
-       }
-    }
-
-    // REDFLAG: Remove once Freenet is behaving?
-    private final String getCHK(String cipherName, Bucket meta, Bucket data) {
-        ComputeCHKRequest request = new ComputeCHKRequest(cipherName,  meta, 
data);
-
-        FreenetURI chkURI = null;
-        try {
-            factory.getClient(request).blockingRun();
-        }
-        catch (Exception e) {
-            System.err.println("SplitFileDownloader.getCHK -- ignored 
exception: " + e);
-            e.printStackTrace();
-        }
-
-        chkURI = request.getURI();
-        if (chkURI == null) {
-            return "";
-        }
-        else {
-            return chkURI.toString();
-        }
-    }
-
-
-    ////////////////////////////////////////////////////////////
-    // Extending GetRequest to be a ClientEventListener is risky
-    // business.  REDFLAG:Grok code for deadlocks. Smells rotten...
-    //
-    // PESTER:
-    // I would have preferred to pull the BlockRequest ref out of
-    // ClientEvent by upcasting java.util.EventObject.getSource()
-    // as is the common Java idiom. But ClientEvent doesn't extend
-    // java.util.EventObject...
-    //
-    public class BlockRequest extends GetRequest implements 
ClientEventListener {
-       public BlockRequest(String uri, int blockNumber, int htl)  
-           throws MalformedURLException, IOException {
-           // PESTER: modify BucketFactory, get rid of -1
-           super(htl, uri, new NullBucket(), bucketFactory.makeBucket(-1));
-           this.blockNumber = blockNumber;
-           this.lastHtlUsed = htl;
-            // Optional igore keys in the local datastore.
-            setNonLocal(skipDS);
-
-           addEventListener(this);
-       }
-
-        public BlockRequest(String uri, int blockNumber, int htl, 
-                     int retries, Bucket data)  
-           throws MalformedURLException, IOException {
-           super(htl, uri, new NullBucket(), data);
-           this.blockNumber = blockNumber;
-           this.lastHtlUsed = htl;
-            this.retries = retries;
-           addEventListener(this);
-       }
-
-        private final void removeFromRunningList() {
-            // NO! deadlock.
-            //synchronized(SplitFileDownloader.this) {
-
-            // Be sloppy and sometimes cancel a request that
-            // has already stopped.
-
-            // Clear the entry in the list used to cancel
-            // running requests.
-            if (runningRequests.contains(BlockRequest.this)) {
-                runningRequests.removeElement(BlockRequest.this);
-            }
-            
-            //}
-        }
-
-        // 021019 gj (actually this was commented out a while back)
-        // Note: 0) Looks like courruption problem is fixed.
-        //       1) This gets called on the stack of an InternalClient
-        //          event, which seemed to cause weird intermittent stalls.
-        //          I never figured out whether it was a lock contention
-        //          problem in my code or a problem with InternalClient.
-        // Note: 
-        // I added this on 020128 because corrupted blocks can be
-        // retrieved without error.
-        // REDFLAG: Remove once bugs are beaten out of the new
-        //          DS merged code.
-        //
-        // Paranoid checking to catch bad blocks before they get
-        // tossed to the FEC decoder.
-        // ASSUMES CHK's have no metadata.
-        // ASSUMES Twofish encryption
-        private final boolean checkCHK() {
-//              if (!uri.toString().startsWith("freenet:CHK")) {
-//                  
System.err.println("SplitFileDownloader.BlockRequester.checkCHK -- ignored:  " 
+ uri);
-//                  return true;
-//              }
-            
-//              String candidate = getCHK("Twofish", new NullBucket(), data);
-
-//              if (!candidate.equals(uri.toString())) {
-//                  String msg = "expected: " + uri +
-//                      " got: " + candidate;
-//                  
System.err.println("SplitFileDownloader.BlockRequester.checkCHK -- " + msg);
-//                  Core.logger.log(this, msg, 
-//                                  Logger.MINOR);
-//                  return false;
-//              }
-            // REDFLAG: remove?
-            return true;
-        }
-
-       public void receive(ClientEvent ce) {
-
-            //hmmm perhaps too vociferous even for debug logging
-
-           //heh, you should see NativeFSDirectory.java :) - amphibian
-           if(Core.logger.shouldLog(Core.logger.DEBUG))
-               Core.logger.log(this, "block: " + blockNumber + " " + 
-                               ce.getDescription(), 
-                               Logger.DEBUGGING);
-           
-            lastActiveMs = System.currentTimeMillis();
-
-           if (ce instanceof StateReachedEvent) {
-               StateReachedEvent sr = (StateReachedEvent) ce;
-               
-               switch (sr.getState()) {
-               case Request.FAILED:
-                    removeFromRunningList();
-                    attemptRetry();
-                   break;
-               case Request.CANCELLED:
-                    removeFromRunningList();
-                   requestFinished(data, blockNumber, false);
-                   break;
-               case Request.DONE: {
-                    removeFromRunningList();
-                    // Double check for corrupted data blocks 
-                    // if we are FEC decoding.
-                    //
-                    // You need to know the metadata and cipher
-                    // in order to check the CHK.  I know this
-                    // for FEC SplitFiles because I wrote the only
-                    // insertion tools.  I don't check non-FEC
-                    // SplitFiles because for them I don't know.
-                    // 
-                    // REDFLAG: remove obsolete code?
-                    //
-                    //if ((fecTools == null) || checkCHK()) {
-                    requestFinished(data, blockNumber, true);
-                    //}
-                    //else {
-                    //    attemptRetry();
-                    //}
-                }
-                break;
-               default:
-                   // NOP
-               }
-           }
-           else if (ce instanceof RouteNotFoundEvent) {
-               rnf = (RouteNotFoundEvent)ce;
-                boolean localFailure = false;
-                final int total = rnf.getUnreachable() + 
-                    rnf.getRestarted() + 
-                    rnf.getRejected();
-                if (total == rnf.getUnreachable()) {
-                    localFailure = true;
-                }
-                synchronized (SplitFileDownloader.this) {
-                    rnfCount++;
-                    if (localFailure) {
-                        localRNFCount++;
-                    }
-                }
-           }
-           else if (ce instanceof DataNotFoundEvent) {
-               dnf = (DataNotFoundEvent)ce;
-                synchronized (SplitFileDownloader.this) {
-                    dnfCount++;
-                }
-           }
-       }
-       
-       // Keep track of client so we can cancel.
-       public void setClient(Client c) {
-           client = c;
-       }
-
-       public void cancel() {
-           if (client != null) {
-               client.cancel();
-           }
-       }
-
-       public final int getBlockNumber() { return blockNumber; }
-       public final int getHtl() { return BlockRequest.this.htl; }
-
-       public void release() {
-           try {
-               bucketFactory.freeBucket(data);
-           }
-           catch (Exception e) {
-           }
-       }
-
-       private void attemptRetry() {
-            synchronized (SplitFileDownloader.this) {
-                if (retries >= maxRetries) {
-                    requestFinished(data, blockNumber, false);
-                    return;
-                }
-            }
-
-            // REDFLAG: hmmm...
-           //if (rnf != null) {
-            // // Can't really recover from RNF
-           //  requestFinished(data, blockNumber, false);
-            // return;
-           //}
-
-           if ((dnf == null) && (rnf == null)) {
-                // We don't know what the hell happened, but
-                // we assume it wasn't good.
-               requestFinished(data, blockNumber, false);
-               return;
-           }
-
-            // Reuse the data bucket.
-           try { 
-               data.resetWrite(); 
-           } catch (IOException ioe) {
-               requestFinished(data, blockNumber, false);
-               return;
-           } 
-
-            BlockRequest next = null;
-            try {
-                // Make a new request because I am not sure that
-                // Client implementations support re-using requests.
-                next = new BlockRequest(uri.toString(), blockNumber, 
-                                                     lastHtlUsed + 
retryHtlIncrement, 
-                                        retries + 1, data);  
-            }
-            catch (Exception e) {
-               Core.logger.log(this, "Exception creating retry request. THIS 
SHOULD NEVER HAPPEN.", 
-                            Logger.ERROR);
-
-                requestFinished(data, blockNumber, false);
-                return;
-            }
-
-           queueRetry(next);
-            synchronized (SplitFileDownloader.this) {
-                // dec *after* queing the retry.
-                nPending--;
-                cumulativeRetries++;
-                SplitFileDownloader.this.notifyAll();
-            }
-       }
-
-       private RouteNotFoundEvent rnf = null;
-       private DataNotFoundEvent dnf = null;
-       
-       private int lastHtlUsed = -1;
-       private int retries;
-       
-       private int blockNumber = -1;
-       private Client client = null;
-    }
-
-    ////////////////////////////////////////////////////////////
-    private final static int POLLINGINTERVAL_MS = 5000;
-
-    ClientFactory factory = null;
-    BucketFactory bucketFactory = null;
-    Connection conn = null;
-    BucketSink sink = null;
-
-    int nThreads = -1;
-    volatile int nPending = -1;
-
-    boolean failing = false;
-    boolean stopping = false;
-    boolean aborted = false;
-
-    int failures = 0;
-    int successes = 0;
-    int allowedFailures = 0;
-    int requiredSuccesses = 0; 
-
-    boolean startedCanceling = false;
-    Thread worker = null;
-    Runnable task = new RunnableImpl();
-
-    String[] blockURIs = null;
-    String[] checkURIs = null;
-
-    int startBlock = -1;
-    int endBlock = -1;
-    int htl = -1;
-    int retryHtlIncrement = 20;
-    int maxRetries = 1;
-    boolean skipDS = false;
-
-    int segments = 1;
-    int currentSegment = 0;
-    int reportedBlockSize = -1;
-    int cumulativeRetries = -1;
-    int dnfCount = 0;
-    int rnfCount = 0;
-    int localRNFCount = 0;
-
-    long lastActiveMs = System.currentTimeMillis();
-    
-
-    Vector requestQueue = new Vector();
-    Vector runningRequests = new Vector();
-
-    BucketSequence sequence = null;
-
-    FECTools fecTools = null;
-    FECTools.HeaderAndMap[] headersAndMaps = null;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-

Deleted: branches/legacy/stable/src/freenet/client/SplitFileRequest.java~
===================================================================
--- branches/legacy/stable/src/freenet/client/SplitFileRequest.java~    
2007-12-08 23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/src/freenet/client/SplitFileRequest.java~    
2007-12-09 14:01:11 UTC (rev 16440)
@@ -1,67 +0,0 @@
-package freenet.client;
-
-import freenet.client.metadata.SplitFile;
-
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import java.net.MalformedURLException;
-
-/** Represents a request to retrieve a
- * and decode a FEC encoded SplitFile.
- *
- * @author giannij
- */
-public class SplitFileRequest extends Request {
-    SplitFile sf; 
-    int defaultHtl; 
-    int defaultRetryIncrement;
-    int defaultRetries;
-    int maxThreads;
-    ClientFactory cf;
-    BucketFactory bf;
-    Bucket destBucket;
-
-    // Switch that turns on extra debugging 
-    // code to check for corrupt SplitFile
-    // downloads.
-    boolean doParanoidChecks = false;
-
-    // NOTE: Client implementations must set this.
-    SplitFileRequestManager manager;
-
-    // Full CTOR
-    public SplitFileRequest(SplitFile sf, 
-                            int defaultHtl, 
-                            int defaultRetryIncrement,
-                            int defaultRetries,
-                            int maxThreads,
-                            ClientFactory cf,
-                            BucketFactory bf,
-                            Bucket destBucket) {
-
-        if (sf.getFECAlgorithm() == null) {
-            // They don't work so we shouldn't
-            // encourage people to use them.
-            throw new 
-                IllegalArgumentException("SplitFiles without FEC are not 
supported.");
-        }
-
-        this.sf = sf;
-        this.defaultHtl = defaultHtl;
-        this.defaultRetryIncrement = defaultRetryIncrement;
-        this.defaultRetries = defaultRetries;
-        this.maxThreads = maxThreads;
-        this.cf = cf;
-        this.bf = bf;
-        this.destBucket = destBucket;
-    }
-
-    public final void enableParanoidChecks(boolean value) { doParanoidChecks = 
value; }
-
-}
-
-
-
-
-
-

Modified: branches/legacy/stable/src/freenet/crypt/DiffieHellman.java
===================================================================
--- branches/legacy/stable/src/freenet/crypt/DiffieHellman.java 2007-12-08 
23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/src/freenet/crypt/DiffieHellman.java 2007-12-09 
14:01:11 UTC (rev 16440)
@@ -14,7 +14,7 @@
 import freenet.support.Logger;

 public class DiffieHellman {
-       
+
        /**
         * When the number of precalculations falls below this threshold 
generation
         * starts up to make more.
@@ -37,7 +37,7 @@
        private static Object precalcerWaitObj = new Object();

        private static Thread precalcThread;
-       
+
        public static final BigInteger MIN_EXPONENTIAL_VALUE = new 
BigInteger("2").pow(24);
        public static final BigInteger MAX_EXPONENTIAL_VALUE = 
group.getP().subtract(MIN_EXPONENTIAL_VALUE);

@@ -68,20 +68,20 @@
                                precalcThread.setPriority(Thread.NORM_PRIORITY);

                                synchronized (precalcerWaitObj) {
-                                               try {
+                                       try {
                                                // Do not set the thread 
priority here because the
                                                // thread may have been stopped 
while holding the
                                                // precalcerWaitObj lock. The 
stop causes the thread
                                                // group to be cleared and 
setPriority to throw a NPE.
                                                
precalcerWaitObj.wait(PRECALC_TIMEOUT);
                                                // TODO: this timeout might 
very well be unneccsary
-                                               } catch (InterruptedException 
ie) {
-                                                       // Ignored.
-                                               }
+                                       } catch (InterruptedException ie) {
+                                               // Ignored.
                                        }
                                }
                        }
                }
+       }

        /**
         * This method does not do anything, but calling it causes the
@@ -105,14 +105,14 @@
                                precalcerWaitObj.notify();
                        }
                }
-                       }
+       }

        public static BigInteger[] getParams() {
                synchronized (precalcBuffer) {
-                       //Ensure that we will have something to pop (at least 
pretty soon)
-                       askRefill(); 
+                       // Ensure that we will have something to pop (at least 
pretty soon)
+                       askRefill();

-                       //Wait until we actually have something to pop
+                       // Wait until we actually have something to pop
                        while (precalcBuffer.isEmpty()) {
                                try {
                                        precalcBuffer.wait();
@@ -123,10 +123,10 @@

                        BigInteger[] result = (BigInteger[]) 
precalcBuffer.pop();

-                       //Hint the precalcer that it might have something to do 
now
+                       // Hint the precalcer that it might have something to 
do now
                        askRefill();

-                       //Release possible other precalc value waiters
+                       // Release possible other precalc value waiters
                        precalcBuffer.notify();

                        return result;
@@ -140,7 +140,7 @@
                        params[0] = new BigInteger(256, r);
                        params[1] = group.getG().modPow(params[0], 
group.getP());
                } 
while(!DiffieHellman.checkDHExponentialValidity(DiffieHellman.class, 
params[1]));
-               
+
                return params;
        }

@@ -155,7 +155,7 @@
         */
        public static boolean checkDHExponentialValidity(Class caller, 
BigInteger exponential) {
                int onesCount=0, zerosCount=0;
-       
+
                // Ensure that we have at least 16 bits of each gender
                for(int i=0; i < exponential.bitLength(); i++)
                        if(exponential.testBit(i))
@@ -166,7 +166,7 @@
                        Core.logger.log(caller, "The provided exponential 
contains "+zerosCount+" zeros and "+onesCount+" ones wich is unacceptable!", 
Logger.ERROR);
                        return false;
                }
-               
+
                // Ensure that g^x > 2^24
                if(MIN_EXPONENTIAL_VALUE.compareTo(exponential) > -1) {
                        Core.logger.log(caller, "The provided exponential is 
smaller than 2^24 which is unacceptable!", Logger.ERROR);
@@ -177,14 +177,12 @@
                        Core.logger.log(caller, "The provided exponential is 
bigger than (p - 2^24) which is unacceptable!", Logger.ERROR);
                        return false;
                }
-               
+
                return true;
        }
-       
+
        public static DHGroup getGroup() {
                return group;
        }
-       
-       
-       
+
 }

Modified: branches/legacy/stable/src/freenet/session/FnpLink.java
===================================================================
--- branches/legacy/stable/src/freenet/session/FnpLink.java     2007-12-08 
23:48:59 UTC (rev 16439)
+++ branches/legacy/stable/src/freenet/session/FnpLink.java     2007-12-09 
14:01:11 UTC (rev 16440)
@@ -40,7 +40,7 @@

 public final class FnpLink implements LinkConstants, Link {

-    public static int AUTH_LAYER_VERSION = 0x01;
+       public static int AUTH_LAYER_VERSION = 0x01;

        protected static final int VER_BIT_LENGTH = 5,
                VER_BIT_MASK = 0x1f,
@@ -50,113 +50,113 @@
                SILENT_BOB_BYTE = 0xfb,
                SILENT_BOB_HANGUP = 0xfc;

-    protected CipherInputStream in;
+       protected CipherInputStream in;

-    protected CipherOutputStream out;
+       protected CipherOutputStream out;

-    protected AdapterOutputStream innerOut;
+       protected AdapterOutputStream innerOut;

-    protected AdapterInputStream innerIn;
+       protected AdapterInputStream innerIn;

-    protected Connection conn;
+       protected Connection conn;

-    protected boolean ready = false;
+       protected boolean ready = false;

-    protected FnpLinkToken linkInfo;
+       protected FnpLinkToken linkInfo;

-    protected FnpLinkManager linkManager;
+       protected FnpLinkManager linkManager;

-    protected DLES asymCipher = new DLES();
+       protected DLES asymCipher = new DLES();

-    protected boolean logDEBUG;
+       protected boolean logDEBUG;

-    // Due to ridiculously long observed authorizeTime's, this file is heavily
-    // augmented
-    // with debug logging and timings
+       // Due to ridiculously long observed authorizeTime's, this file is 
heavily
+       // augmented
+       // with debug logging and timings

-    //profiling
-    //WARNING:remove before release
-    public static volatile int instances = 0;
+       // profiling
+       // WARNING:remove before release
+       public static volatile int instances = 0;

-    private static final Object profLock = new Object();
+       private static final Object profLock = new Object();

-    protected FnpLink(FnpLinkManager flm, Connection c) {
-        linkManager = flm;
-        conn = c;
-        logDEBUG = Core.logger.shouldLog(Logger.DEBUG, this);
-        //profiling
-        //WARNING:remove before release
-        synchronized (profLock) {
-            instances++;
-        }
-    }
+       protected FnpLink(FnpLinkManager flm, Connection c) {
+               linkManager = flm;
+               conn = c;
+               logDEBUG = Core.logger.shouldLog(Logger.DEBUG, this);
+               //profiling
+               //WARNING:remove before release
+               synchronized (profLock) {
+                       instances++;
+               }
+       }

-    //     protected FnpLink(FnpLinkManager flm, FnpLinkToken linkInfo,
-    //                       CipherInputStream in, CipherOutputStream out,
-    //                       Connection conn) {
-    //         this(flm, conn);
-    //         this.linkInfo = linkInfo;
-    //         setInputStream(in);
-    //         setOutputStream(out);
-    //         ready = true;
-    //     }
+       //     protected FnpLink(FnpLinkManager flm, FnpLinkToken linkInfo,
+       //                       CipherInputStream in, CipherOutputStream out,
+       //                       Connection conn) {
+       //         this(flm, conn);
+       //         this.linkInfo = linkInfo;
+       //         setInputStream(in);
+       //         setOutputStream(out);
+       //         ready = true;
+       //     }

        protected void accept(
                DSAPrivateKey privMe,
                DSAIdentity pubMe,
                int paravect)
-            throws CommunicationException {
-        synchronized (conn) {
-            try {
-                int oldTimeout = conn.getSoTimeout();
-                try {
-                    conn.setSoTimeout(Core.authTimeout);
+               throws CommunicationException {
+               synchronized (conn) {
+                       try {
+                               int oldTimeout = conn.getSoTimeout();
+                               try {
+                                       conn.setSoTimeout(Core.authTimeout);

-                    InputStream rawIn = conn.getIn();
-                    int connType = rawIn.read();
+                                       InputStream rawIn = conn.getIn();
+                                       int connType = rawIn.read();

                                        if (((connType >> (8 - VER_BIT_LENGTH)) 
& VER_BIT_MASK)
                                                != AUTH_LAYER_VERSION)
                                                throw new 
NegotiationFailedException(conn.getPeerAddress(), "Wrong auth protocol 
version");

-                    int negmode = connType & NEGOTIATION_MODE_MASK;
+                                       int negmode = connType & 
NEGOTIATION_MODE_MASK;

-                    if (negmode == RESTART) {
-                        if (logDEBUG)
+                                       if (negmode == RESTART) {
+                                               if (logDEBUG)
                                                        Core.logger.log(this, 
"Accepting restart.", Logger.DEBUG);
                                                boolean worked =
                                                        
receiveRestartRequest(privMe, pubMe, paravect);
-                        if (worked) {
+                                               if (worked) {
                                                        
Core.diagnostics.occurrenceBinomial("inboundRestartRatio", 1, 1);
-                            return;
-                        } else {
-                            // reread
-                            connType = rawIn.read();
-                            negmode = connType & NEGOTIATION_MODE_MASK;
-                        }
-                    }
+                                                       return;
+                                               } else {
+                                                       // reread
+                                                       connType = rawIn.read();
+                                                       negmode = connType & 
NEGOTIATION_MODE_MASK;
+                                               }
+                                       }

-                    if (negmode == AUTHENTICATE) {
-                        if (logDEBUG)
+                                       if (negmode == AUTHENTICATE) {
+                                               if (logDEBUG)
                                                        Core.logger.log(this, 
"Accepting full negotiation", Logger.DEBUG);
-                        negotiateInbound(privMe, pubMe, paravect);
+                                               negotiateInbound(privMe, pubMe, 
paravect);
                                                
Core.diagnostics.occurrenceBinomial("inboundRestartRatio", 1, 0);
-                    } else {
+                                       } else {
                                                throw new 
NegotiationFailedException(conn.getPeerAddress(), "Invalid authentication 
mode");
-                    }
-                } finally {
-                    conn.setSoTimeout(oldTimeout);
-                }
-            } catch (InterruptedIOException e) {
+                                       }
+                               } finally {
+                                       conn.setSoTimeout(oldTimeout);
+                               }
+                       } catch (InterruptedIOException e) {
                                throw new 
ConnectFailedException(conn.getPeerAddress(), "authentication timed out");
-            } catch (IOException e) {
-                String s = "I/O error during inbound auth: " + e;
-                if(Core.logger.shouldLog(Logger.MINOR, this))
-                    Core.logger.log(this, s, e, Logger.MINOR);
-                throw new ConnectFailedException(conn.getPeerAddress(), s);
-            }
-        }
-    }
+                       } catch (IOException e) {
+                               String s = "I/O error during inbound auth: " + 
e;
+                               if (Core.logger.shouldLog(Logger.MINOR, this))
+                                       Core.logger.log(this, s, e, 
Logger.MINOR);
+                               throw new 
ConnectFailedException(conn.getPeerAddress(), s);
+                       }
+               }
+       }

        protected void solicit(
                DSAAuthentity privMe,
@@ -164,70 +164,70 @@
                DSAIdentity bob,
                boolean safe)
                throws CommunicationException {
-        long startTime = System.currentTimeMillis();
-        if (logDEBUG)
+               long startTime = System.currentTimeMillis();
+               if (logDEBUG)
                        Core.logger.log(this, "solicit() at " + startTime, 
Logger.DEBUG);
-        synchronized (conn) {
-            try {
-                int oldTimeout = conn.getSoTimeout();
-                conn.setSoTimeout(Core.authTimeout);
-                linkInfo = linkManager.searchOutboundLinks(bob);
-                if (linkInfo != null) {
-                    long solicitRestartTime = System.currentTimeMillis();
-                    if (logDEBUG)
+               synchronized (conn) {
+                       try {
+                               int oldTimeout = conn.getSoTimeout();
+                               conn.setSoTimeout(Core.authTimeout);
+                               linkInfo = linkManager.searchOutboundLinks(bob);
+                               if (linkInfo != null) {
+                                       long solicitRestartTime = 
System.currentTimeMillis();
+                                       if (logDEBUG)
                                                Core.logger.log(this, 
"Soliciting restart at " + (solicitRestartTime - startTime), Logger.DEBUG);
-                    try {
+                                       try {
                                                boolean worked =
                                                        negotiateRestart(bob, 
linkInfo.getKeyHash(), linkInfo.getKey(), safe);
-                        long negotiatedRestartTime = 
System.currentTimeMillis();
+                                               long negotiatedRestartTime = 
System.currentTimeMillis();
                                                long negrestartlen =
                                                        negotiatedRestartTime - 
solicitRestartTime;
-                        if (logDEBUG || negrestartlen > 500)
+                                               if (logDEBUG || negrestartlen > 
500)
                                                        Core.logger.log(this, 
"negotiateRestart took " + negrestartlen + " at "
                                                                        + 
negotiatedRestartTime, negrestartlen > 500 ? Logger.MINOR : Logger.DEBUG);
-                        if (worked) {
+                                               if (worked) {
                                                        
Core.diagnostics.occurrenceBinomial("outboundRestartRatio", 1, 1);
-                            return;
-                        } else
-                            linkManager.removeLink(linkInfo);
-                    } catch (AuthenticationFailedException e) {
-                        linkManager.removeLink(linkInfo);
-                        throw (AuthenticationFailedException) e
-                                .fillInStackTrace();
-                    }
-                }
-                long solicitFullTime = System.currentTimeMillis();
-                if (logDEBUG)
+                                                       return;
+                                               } else
+                                                       
linkManager.removeLink(linkInfo);
+                                       } catch (AuthenticationFailedException 
e) {
+                                               
linkManager.removeLink(linkInfo);
+                                               throw 
(AuthenticationFailedException) e
+                                                       .fillInStackTrace();
+                                       }
+                               }
+                               long solicitFullTime = 
System.currentTimeMillis();
+                               if (logDEBUG)
                                        Core.logger.log(this, "Soliciting full 
negotiation at " + solicitFullTime, Logger.DEBUG);
-                negotiateOutbound(privMe, pubMe, bob);
-                long negotiatedTime = System.currentTimeMillis();
-                long neglength = negotiatedTime - solicitFullTime;
-                if (logDEBUG || neglength > 500)
+                               negotiateOutbound(privMe, pubMe, bob);
+                               long negotiatedTime = 
System.currentTimeMillis();
+                               long neglength = negotiatedTime - 
solicitFullTime;
+                               if (logDEBUG || neglength > 500)
                                        Core.logger.log(this, 
"negotiateOutbound took " + neglength + " at " + negotiatedTime,
-                                neglength > 500 ? Logger.MINOR : Logger.DEBUG);
+                                                       neglength > 500 ? 
Logger.MINOR : Logger.DEBUG);
                                
Core.diagnostics.occurrenceBinomial("outboundRestartRatio", 1, 0);
-                boolean open = conn.isInClosed();
-                try {
-                    conn.setSoTimeout(oldTimeout);
-                } catch (IOException e) {
-                    if (open || Core.logger.shouldLog(Logger.DEBUG, this))
+                               boolean open = conn.isInClosed();
+                               try {
+                                       conn.setSoTimeout(oldTimeout);
+                               } catch (IOException e) {
+                                       if (open || 
Core.logger.shouldLog(Logger.DEBUG, this))
                                                Core.logger.log(this, "Caught " 
+ e + " setting timeout on " + conn, open
                                                                ? Logger.NORMAL
                                                                : Logger.DEBUG);
-                }
-            } catch (InterruptedIOException e) {
+                               }
+                       } catch (InterruptedIOException e) {
                                throw new 
ConnectFailedException(conn.getPeerAddress(), "authentication timed out");
-            } catch (IOException e) {
-                String s = "I/O error during outbound auth: " + e;
-                if(Core.logger.shouldLog(Logger.MINOR, this))
-                    Core.logger.log(this, s, e, Logger.MINOR);
+                       } catch (IOException e) {
+                               String s = "I/O error during outbound auth: " + 
e;
+                               if (Core.logger.shouldLog(Logger.MINOR, this))
+                                       Core.logger.log(this, s, e, 
Logger.MINOR);
                                ConnectFailedException ex =
                                        new 
ConnectFailedException(conn.getPeerAddress(), s);
-                ex.initCause(e);
-                throw ex; 
-            }
-        }
-    }
+                               ex.initCause(e);
+                               throw ex;
+                       }
+               }
+       }

        private boolean negotiateRestart(
                DSAIdentity bob,
@@ -236,138 +236,138 @@
                boolean safe)
                throws CommunicationException, IOException {

-        long startTime = System.currentTimeMillis();
-        if (logDEBUG)
+               long startTime = System.currentTimeMillis();
+               if (logDEBUG)
                        Core.logger.log(this, "negotiateRestart at " + 
startTime, Logger.DEBUG);

-        OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
-        InputStream rawIn = innerIn = new AdapterInputStream(conn.getIn());
+               OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
+               InputStream rawIn = innerIn = new 
AdapterInputStream(conn.getIn());

-        long gotStreamsTime = System.currentTimeMillis();
-        long gslen = gotStreamsTime - startTime;
-        if (logDEBUG || gslen > 500)
+               long gotStreamsTime = System.currentTimeMillis();
+               long gslen = gotStreamsTime - startTime;
+               if (logDEBUG || gslen > 500)
                        Core.logger.log(this, "Got streams in " + gslen + " at 
" + gotStreamsTime, gslen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        // Send restart challenge
-        BigInteger M = hk.shiftLeft(8);
+               // Send restart challenge
+               BigInteger M = hk.shiftLeft(8);
                if (safe)
                        M = M.setBit(0);

-        long shiftedSetTime = System.currentTimeMillis();
-        long sstlen = shiftedSetTime - gotStreamsTime;
-        if (logDEBUG || sstlen > 500)
+               long shiftedSetTime = System.currentTimeMillis();
+               long sstlen = shiftedSetTime - gotStreamsTime;
+               if (logDEBUG || sstlen > 500)
                        Core.logger.log(this, "Shifted and set in " + sstlen + 
" at " + shiftedSetTime, sstlen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        BigInteger[] C = asymCipher.encrypt(bob, M, Core.getRandSource());
+               BigInteger[] C = asymCipher.encrypt(bob, M, 
Core.getRandSource());

-        long madeChallengeTime = System.currentTimeMillis();
-        long mclen = madeChallengeTime - shiftedSetTime;
-        if (logDEBUG || mclen > 500)
+               long madeChallengeTime = System.currentTimeMillis();
+               long mclen = madeChallengeTime - shiftedSetTime;
+               if (logDEBUG || mclen > 500)
                        Core.logger.log(this, "Generated challenge in " + mclen 
+ " at " + madeChallengeTime, mclen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        rawOut.write((AUTH_LAYER_VERSION << (8 - VER_BIT_LENGTH)) + RESTART);
-        Util.writeMPI(C[0], rawOut);
-        Util.writeMPI(C[1], rawOut);
-        Util.writeMPI(C[2], rawOut);
+               rawOut.write((AUTH_LAYER_VERSION << (8 - VER_BIT_LENGTH)) + 
RESTART);
+               Util.writeMPI(C[0], rawOut);
+               Util.writeMPI(C[1], rawOut);
+               Util.writeMPI(C[2], rawOut);

-        long sentChallengeTime = System.currentTimeMillis();
-        long sclen = sentChallengeTime - madeChallengeTime;
-        if (logDEBUG || sclen > 500)
+               long sentChallengeTime = System.currentTimeMillis();
+               long sclen = sentChallengeTime - madeChallengeTime;
+               if (logDEBUG || sclen > 500)
                        Core.logger.log(this, "Sent challenge in " + sclen + " 
at " + sentChallengeTime, sclen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        //rawOut.flush(); Flushing is a pass on some level...
-        // Set up outbound link level encryption
-        BlockCipher c = new Rijndael();
-        c.initialize(k);
-        PCFBMode ctx = new PCFBMode(c);
+               //rawOut.flush(); Flushing is a pass on some level...
+               // Set up outbound link level encryption
+               BlockCipher c = new Rijndael();
+               c.initialize(k);
+               PCFBMode ctx = new PCFBMode(c);

-        long initCipherTime = System.currentTimeMillis();
-        long icl = initCipherTime - sentChallengeTime;
-        if (logDEBUG || icl > 500)
+               long initCipherTime = System.currentTimeMillis();
+               long icl = initCipherTime - sentChallengeTime;
+               if (logDEBUG || icl > 500)
                        Core.logger.log(this, "Initialized cipher in " + icl + 
" at " + initCipherTime, icl > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        // Set up inbound link level encryption
-        if (safe) {
-            rawOut.flush();
-            long flushedInSafeTime = System.currentTimeMillis();
-            long flushlen = flushedInSafeTime - initCipherTime;
-            if (logDEBUG || flushlen > 500)
+               // Set up inbound link level encryption
+               if (safe) {
+                       rawOut.flush();
+                       long flushedInSafeTime = System.currentTimeMillis();
+                       long flushlen = flushedInSafeTime - initCipherTime;
+                       if (logDEBUG || flushlen > 500)
                                Core.logger.log(this, "Flushed rawOut in safe 
branch in " + flushlen + " at " + flushedInSafeTime,
-                            flushlen > 500 ? Logger.MINOR : Logger.DEBUG);
+                                               flushlen > 500 ? Logger.MINOR : 
Logger.DEBUG);

-            int cb = rawIn.read();
-            long readByteTime = System.currentTimeMillis();
-            long rbl = readByteTime - flushedInSafeTime;
-            if (logDEBUG || rbl > 500)
+                       int cb = rawIn.read();
+                       long readByteTime = System.currentTimeMillis();
+                       long rbl = readByteTime - flushedInSafeTime;
+                       if (logDEBUG || rbl > 500)
                                Core.logger.log(this, "Read byte in " + rbl + " 
at " + readByteTime, rbl > 500
                                                ? Logger.MINOR
                                                : Logger.DEBUG);

-            if (cb == SILENT_BOB_BYTE) {
-                ctx.writeIV(Core.getRandSource(), rawOut);
-                long writtenIVTime = System.currentTimeMillis();
-                long ivt = writtenIVTime - readByteTime;
-                if (logDEBUG || ivt > 500)
+                       if (cb == SILENT_BOB_BYTE) {
+                               ctx.writeIV(Core.getRandSource(), rawOut);
+                               long writtenIVTime = System.currentTimeMillis();
+                               long ivt = writtenIVTime - readByteTime;
+                               if (logDEBUG || ivt > 500)
                                        Core.logger.log(this, "Written silent 
bob IV in " + ivt + " at " + writtenIVTime, ivt > 500
                                                        ? Logger.MINOR
                                                        : Logger.DEBUG);

-                // Must flush here: NIO
-                rawOut.flush();
-                
-                setOutputStream(ctx, rawOut);
-                if (logDEBUG)
+                               // Must flush here: NIO
+                               rawOut.flush();
+
+                               setOutputStream(ctx, rawOut);
+                               if (logDEBUG)
                                        Core.logger.log(this, "Set output 
stream", Logger.DEBUG);
-                setInputStream(c, rawIn);
-                if (logDEBUG)
-                        Core.logger.log(this, "Set input stream", 
Logger.DEBUG);
-                
-                if(in.needIV()) {
-                    if(logDEBUG)
-                        Core.logger.log(this, "Reading IV", Logger.DEBUG);
-                    in.getCipher().readIV(rawIn);
-                    if(logDEBUG)
-                        Core.logger.log(this, "Read IV", Logger.DEBUG);
-                }
-                
-                conn.notifyAll();
-                if (logDEBUG)
-                        Core.logger.log(this, "Notified all", Logger.DEBUG);
-                ready = true;
-                return true;
-            } else if (cb == SILENT_BOB_HANGUP) {
-                if (logDEBUG)
+                               setInputStream(c, rawIn);
+                               if (logDEBUG)
+                                       Core.logger.log(this, "Set input 
stream", Logger.DEBUG);
+
+                               if (in.needIV()) {
+                                       if (logDEBUG)
+                                               Core.logger.log(this, "Reading 
IV", Logger.DEBUG);
+                                       in.getCipher().readIV(rawIn);
+                                       if (logDEBUG)
+                                               Core.logger.log(this, "Read 
IV", Logger.DEBUG);
+                               }
+
+                               conn.notifyAll();
+                               if (logDEBUG)
+                                       Core.logger.log(this, "Notified all", 
Logger.DEBUG);
+                               ready = true;
+                               return true;
+                       } else if (cb == SILENT_BOB_HANGUP) {
+                               if (logDEBUG)
                                        Core.logger.log(this, "Silent bob 
hangup at " + System.currentTimeMillis(), Logger.DEBUG);
-                return false;
-            } else {
+                               return false;
+                       } else {
                                throw new 
NegotiationFailedException(conn.getPeerAddress(), cb == -1 ? "Peer hung up" : 
"Bad OK byte");
-            }
-        } else {
-            ctx.writeIV(Core.getRandSource(), rawOut);
-            long writtenIVTime = System.currentTimeMillis();
-            long wiv = writtenIVTime - initCipherTime;
-            if (logDEBUG || wiv > 500)
+                       }
+               } else {
+                       ctx.writeIV(Core.getRandSource(), rawOut);
+                       long writtenIVTime = System.currentTimeMillis();
+                       long wiv = writtenIVTime - initCipherTime;
+                       if (logDEBUG || wiv > 500)
                                Core.logger.log(this, "Written IV (unsafe) in " 
+ wiv + " at " + writtenIVTime, wiv > 500
                                                ? Logger.MINOR
                                                : Logger.DEBUG);

-            setOutputStream(ctx, rawOut);
-            setSilentBobCheckingInputStream(c, rawIn);
-            ready = true;
-            conn.notifyAll();
-            return true;
-        }
-    }
+                       setOutputStream(ctx, rawOut);
+                       setSilentBobCheckingInputStream(c, rawIn);
+                       ready = true;
+                       conn.notifyAll();
+                       return true;
+               }
+       }

        private boolean receiveRestartRequest(
                DSAPrivateKey privMe,
@@ -375,419 +375,419 @@
                int paravect)
                throws CommunicationException, IOException {

-        long startTime = System.currentTimeMillis();
-        if (logDEBUG)
+               long startTime = System.currentTimeMillis();
+               if (logDEBUG)
                        Core.logger.log(this, "Receiving restart request at " + 
startTime, Logger.DEBUG);

-        OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
-        InputStream rawIn = innerIn = new AdapterInputStream(conn.getIn());
+               OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
+               InputStream rawIn = innerIn = new 
AdapterInputStream(conn.getIn());

-        BigInteger[] C = new BigInteger[3];
-        C[0] = Util.readMPI(rawIn);
-        C[1] = Util.readMPI(rawIn);
-        C[2] = Util.readMPI(rawIn);
+               BigInteger[] C = new BigInteger[3];
+               C[0] = Util.readMPI(rawIn);
+               C[1] = Util.readMPI(rawIn);
+               C[2] = Util.readMPI(rawIn);

-        long readMPIsTime = System.currentTimeMillis();
-        long rlen = readMPIsTime - startTime;
+               long readMPIsTime = System.currentTimeMillis();
+               long rlen = readMPIsTime - startTime;

-        if (logDEBUG || rlen > 500)
+               if (logDEBUG || rlen > 500)
                        Core.logger.log(this, "got streams and read MPIs in " + 
rlen, rlen > 500 ? Logger.MINOR : Logger.DEBUG);

-        BigInteger P = null;
-        try {
-            P = asymCipher.decrypt(pubMe.getGroup(), privMe, C);
-        } catch (DecryptionFailedException dfe) {
+               BigInteger P = null;
+               try {
+                       P = asymCipher.decrypt(pubMe.getGroup(), privMe, C);
+               } catch (DecryptionFailedException dfe) {
                        throw new 
AuthenticationFailedException(conn.getPeerAddress(),
-                    "Invalid restart message (MAC verify must have failed)");
-        }
+                                       "Invalid restart message (MAC verify 
must have failed)");
+               }

-        long decryptedTime = System.currentTimeMillis();
-        long dlen = decryptedTime - readMPIsTime;
-        if (logDEBUG || dlen > 500)
+               long decryptedTime = System.currentTimeMillis();
+               long dlen = decryptedTime - readMPIsTime;
+               if (logDEBUG || dlen > 500)
                        Core.logger.log(this, "decrypted in " + dlen, dlen > 
500 ? Logger.MINOR : Logger.DEBUG);

-        boolean safe;
+               boolean safe;
                if (P.byteValue() == 0)
                        safe = false;
                else if (P.byteValue() == 1)
                        safe = true;
-        else {
-            String error = "Invalid restart message (low 8 bits not 0 or 1)";
+               else {
+                       String error = "Invalid restart message (low 8 bits not 
0 or 1)";
                        throw new 
AuthenticationFailedException(conn.getPeerAddress(), error);
-        }
+               }

-        P = P.shiftRight(8);
-        linkInfo = linkManager.searchInboundLinks(P);
+               P = P.shiftRight(8);
+               linkInfo = linkManager.searchInboundLinks(P);

-        if (linkInfo == null) {
-            rawOut.write(SILENT_BOB_HANGUP);
-            rawOut.flush();
+               if (linkInfo == null) {
+                       rawOut.write(SILENT_BOB_HANGUP);
+                       rawOut.flush();
                        if (safe)
                                return false;
-            else
+                       else
                                throw new 
AuthenticationFailedException(conn.getPeerAddress(),
-                        "Unknown Link trying to restart, and unable to do 
fallback.");
-        }
+                                               "Unknown Link trying to 
restart, and unable to do fallback.");
+               }

-        // oh glorious 0xfb
-        rawOut.write(SILENT_BOB_BYTE);
-        rawOut.flush();
+               // oh glorious 0xfb
+               rawOut.write(SILENT_BOB_BYTE);
+               rawOut.flush();

-        long bobTime = System.currentTimeMillis();
-        long boblen = bobTime - decryptedTime;
-        if (logDEBUG || boblen > 500)
+               long bobTime = System.currentTimeMillis();
+               long boblen = bobTime - decryptedTime;
+               if (logDEBUG || boblen > 500)
                        Core.logger.log(this, "Got link info, written silent 
bob and flushed in " + boblen, boblen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        // Set up outbound link level encryption
-        BlockCipher c = new Rijndael();
-        c.initialize(linkInfo.getKey());
-        PCFBMode ctx = new PCFBMode(c);
+               // Set up outbound link level encryption
+               BlockCipher c = new Rijndael();
+               c.initialize(linkInfo.getKey());
+               PCFBMode ctx = new PCFBMode(c);

-        long cipherTime = System.currentTimeMillis();
-        long clen = cipherTime - bobTime;
-        if (logDEBUG || clen > 500)
+               long cipherTime = System.currentTimeMillis();
+               long clen = cipherTime - bobTime;
+               if (logDEBUG || clen > 500)
                        Core.logger.log(this, "Set up cipher in " + clen, clen 
> 500 ? Logger.MINOR : Logger.DEBUG);

-        ctx.writeIV(Core.getRandSource(), rawOut);
-        long IVTime = System.currentTimeMillis();
-        long ivlen = IVTime - cipherTime;
-        if (logDEBUG || ivlen > 500)
+               ctx.writeIV(Core.getRandSource(), rawOut);
+               long IVTime = System.currentTimeMillis();
+               long ivlen = IVTime - cipherTime;
+               if (logDEBUG || ivlen > 500)
                        Core.logger.log(this, "Written IV in " + ivlen, ivlen > 
500 ? Logger.MINOR : Logger.DEBUG);

-        // we wait with flushing the IV until the first message. It is
-        // just as well since it is read with the first message now. /oskar
-        //rawOut.flush();
+               // we wait with flushing the IV until the first message. It is
+               // just as well since it is read with the first message now. 
/oskar
+               //rawOut.flush();

-        setOutputStream(ctx, rawOut);
+               setOutputStream(ctx, rawOut);

-        // Set up inbound link level encryption
-        setInputStream(c, rawIn);
+               // Set up inbound link level encryption
+               setInputStream(c, rawIn);

-        ready = true;
-        conn.notifyAll();
+               ready = true;
+               conn.notifyAll();

-        return true;
-    }
+               return true;
+       }

        private void negotiateInbound(
                DSAPrivateKey privMe,
                DSAIdentity pubMe,
                int paravect)
                throws CommunicationException, IOException {
-        boolean cbSent = false;
+               boolean cbSent = false;
                BigInteger[] dhParams = DiffieHellman.getParams(),
                        DLESCa = new BigInteger[3];

-        DSAIdentity Ya;
+               DSAIdentity Ya;

-        BigInteger Ca, Cb = dhParams[1], Z, R = dhParams[0];
+               BigInteger Ca, Cb = dhParams[1], Z, R = dhParams[0];

-        BlockCipher c = new Rijndael();
-        byte[] k = new byte[c.getKeySize() >> 3];
+               BlockCipher c = new Rijndael();
+               byte[] k = new byte[c.getKeySize() >> 3];

-        OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
-        InputStream rawIn = innerIn = new AdapterInputStream(conn.getIn());
+               OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
+               InputStream rawIn = innerIn = new 
AdapterInputStream(conn.getIn());

-        if ((paravect & SILENT_BOB) == 0) {
-            rawOut.write(SILENT_BOB_BYTE);
-            Util.writeMPI(Cb, rawOut);
-            cbSent = true;
-            rawOut.flush();
-        }
-        Ca = Util.readMPI(rawIn);
-        
-        if(!DiffieHellman.checkDHExponentialValidity(this.getClass(), Ca)) {
-               String err = "Cannot accept remote exponential. WARNING: WITH 
HIGH PROBABILITY, THIS WAS A DELIBERATE ATTACK!";
-               throw new NegotiationFailedException(conn.getPeerAddress(), 
err);
-        }
+               if ((paravect & SILENT_BOB) == 0) {
+                       rawOut.write(SILENT_BOB_BYTE);
+                       Util.writeMPI(Cb, rawOut);
+                       cbSent = true;
+                       rawOut.flush();
+               }
+               Ca = Util.readMPI(rawIn);

-        Z = Ca.modPow(R, DiffieHellman.getGroup().getP());
-        byte[] kent = Util.MPIbytes(Z);
-        Util.makeKey(kent, k, 0, k.length);
-        c.initialize(k);
+               if (!DiffieHellman.checkDHExponentialValidity(this.getClass(), 
Ca)) {
+                       String err = "Cannot accept remote exponential. 
WARNING: WITH HIGH PROBABILITY, THIS WAS A DELIBERATE ATTACK!";
+                       throw new 
NegotiationFailedException(conn.getPeerAddress(), err);
+               }

-        DLESCa[0] = Util.readMPI(rawIn);
-        DLESCa[1] = Util.readMPI(rawIn);
-        DLESCa[2] = Util.readMPI(rawIn);
+               Z = Ca.modPow(R, DiffieHellman.getGroup().getP());
+               byte[] kent = Util.MPIbytes(Z);
+               Util.makeKey(kent, k, 0, k.length);
+               c.initialize(k);

-        if ((paravect & VERIFY_BOBKNOWN) != 0) {
-            BigInteger Cav = null;
-            try {
-                Cav = asymCipher.decrypt(pubMe.getGroup(), privMe, DLESCa);
-            } catch (DecryptionFailedException dfe) {
-                String err = "Remote sent bogus DLES encrypted data";
+               DLESCa[0] = Util.readMPI(rawIn);
+               DLESCa[1] = Util.readMPI(rawIn);
+               DLESCa[2] = Util.readMPI(rawIn);
+
+               if ((paravect & VERIFY_BOBKNOWN) != 0) {
+                       BigInteger Cav = null;
+                       try {
+                               Cav = asymCipher.decrypt(pubMe.getGroup(), 
privMe, DLESCa);
+                       } catch (DecryptionFailedException dfe) {
+                               String err = "Remote sent bogus DLES encrypted 
data";
                                throw new 
AuthenticationFailedException(conn.getPeerAddress(), err);
-            }
-            if (!Cav.equals(Ca)) {
-                String err = "Remote does not know my identity";
+                       }
+                       if (!Cav.equals(Ca)) {
+                               String err = "Remote does not know my identity";
                                throw new 
AuthenticationFailedException(conn.getPeerAddress(), err);
-            }
-        }
+                       }
+               }

-        if (!cbSent) {
-            rawOut.write(SILENT_BOB_BYTE);
-            Util.writeMPI(Cb, rawOut);
-            cbSent = true;
-            rawOut.flush();
-        }
+               if (!cbSent) {
+                       rawOut.write(SILENT_BOB_BYTE);
+                       Util.writeMPI(Cb, rawOut);
+                       cbSent = true;
+                       rawOut.flush();
+               }

-        PCFBMode pcfb = new PCFBMode(c);
-        pcfb.writeIV(Core.getRandSource(), rawOut);
-        setOutputStream(pcfb, rawOut);
-        //setInputStream(c, rawIn);
+               PCFBMode pcfb = new PCFBMode(c);
+               pcfb.writeIV(Core.getRandSource(), rawOut);
+               setOutputStream(pcfb, rawOut);
+               //setInputStream(c, rawIn);

-        Digest ctx = SHA1.getInstance();
-        byte[] Cabytes = Util.MPIbytes(Ca);
-        byte[] Cbbytes = Util.MPIbytes(Cb);
-        ctx.update(Cabytes, 0, Cabytes.length);
-        ctx.update(Cbbytes, 0, Cbbytes.length);
+               Digest ctx = SHA1.getInstance();
+               byte[] Cabytes = Util.MPIbytes(Ca);
+               byte[] Cbbytes = Util.MPIbytes(Cb);
+               ctx.update(Cabytes, 0, Cabytes.length);
+               ctx.update(Cbbytes, 0, Cbbytes.length);
                BigInteger M = new NativeBigInteger(1, ctx.digest());
                DSASignature sigCaCb = DSA.sign(pubMe.getGroup(), privMe, M, 
Core.getRandSource());

-        sigCaCb.write(out);
-        out.flush();
+               sigCaCb.write(out);
+               out.flush();

-        setInputStream(c, rawIn);
-        Ya = (DSAIdentity) DSAIdentity.read(in);
+               setInputStream(c, rawIn);
+               Ya = (DSAIdentity) DSAIdentity.read(in);
                if(logDEBUG)
-                   Core.logger.log(this, "Read Ya: 
"+Ya.fingerprintToString()+": y="+
-                           Ya.getYAsHexString()+", group: "+Ya.getGroup(), 
Logger.DEBUG);
-        byte[] Yabytes = Ya.asBytes();
-        //System.err.println(freenet.support.HexUtil.bytesToHex(Yabytes));
-        //System.err.println(Ya.toString());
-        ctx.update(Yabytes, 0, Yabytes.length);
-        ctx.update(Cabytes, 0, Cabytes.length);
-        ctx.update(Cbbytes, 0, Cbbytes.length);
+                       Core.logger.log(this, "Read Ya: 
"+Ya.fingerprintToString()+": y="+
+                               Ya.getYAsHexString()+", group: "+Ya.getGroup(), 
Logger.DEBUG);
+               byte[] Yabytes = Ya.asBytes();
+               
//System.err.println(freenet.support.HexUtil.bytesToHex(Yabytes));
+               //System.err.println(Ya.toString());
+               ctx.update(Yabytes, 0, Yabytes.length);
+               ctx.update(Cabytes, 0, Cabytes.length);
+               ctx.update(Cbbytes, 0, Cbbytes.length);
                M = new NativeBigInteger(1, ctx.digest());
-        DSASignature sigYaCaCb = DSASignature.read(in);
+               DSASignature sigYaCaCb = DSASignature.read(in);
                if(logDEBUG)
-                   Core.logger.log(this, "Read signature: "+sigYaCaCb+", M 
should be: "+M+
-                           ", Ya="+Ya.fingerprintToString(), Logger.DEBUG);
-        if (!DSA.verify(Ya, sigYaCaCb, M)) {
+                       Core.logger.log(this, "Read signature: "+sigYaCaCb+", M 
should be: "+M+
+                               ", Ya="+Ya.fingerprintToString(), Logger.DEBUG);
+               if (!DSA.verify(Ya, sigYaCaCb, M)) {
                        String err = "Remote does not posess the private key to 
the public key it offered";
-            throw new AuthenticationFailedException(conn.getPeerAddress(), 
err);
-        }
+                       throw new 
AuthenticationFailedException(conn.getPeerAddress(), err);
+               }

                linkInfo = linkManager.addLink(Ya, pubMe, k);

-        ready = true;
-        conn.notifyAll();
-    }
+               ready = true;
+               conn.notifyAll();
+       }

        private void negotiateOutbound(
                DSAPrivateKey privMe,
                DSAIdentity pubMe,
                DSAIdentity bob)
                throws CommunicationException, IOException {
-        // FIXME: Most of this stuff should probably be diagnostics rather than
-        // logging
+               // FIXME: Most of this stuff should probably be diagnostics 
rather than
+               // logging

-        long startTime = System.currentTimeMillis();
-        if (logDEBUG)
+               long startTime = System.currentTimeMillis();
+               if (logDEBUG)
                        Core.logger.log(this, "negotiateOutbound at " + 
startTime, Logger.DEBUG);

-        BigInteger[] DLESCa, dhParams = DiffieHellman.getParams();
-        BigInteger Ca = dhParams[1], Cb, Z, R = dhParams[0], M;
+               BigInteger[] DLESCa, dhParams = DiffieHellman.getParams();
+               BigInteger Ca = dhParams[1], Cb, Z, R = dhParams[0], M;

-        BlockCipher c = new Rijndael();
-        byte[] k = new byte[c.getKeySize() >> 3];
+               BlockCipher c = new Rijndael();
+               byte[] k = new byte[c.getKeySize() >> 3];

-        long setupTime = System.currentTimeMillis();
-        long setuplen = setupTime - startTime;
-        if (logDEBUG || setuplen > 500)
+               long setupTime = System.currentTimeMillis();
+               long setuplen = setupTime - startTime;
+               if (logDEBUG || setuplen > 500)
                        Core.logger.log(this, "Setup in " + setuplen, setuplen 
> 500 ? Logger.MINOR : Logger.DEBUG);

-        OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
-        InputStream rawIn = innerIn = new AdapterInputStream(conn.getIn());
+               OutputStream rawOut = innerOut = new 
AdapterOutputStream(conn.getOut());
+               InputStream rawIn = innerIn = new 
AdapterInputStream(conn.getIn());

                rawOut.write(
                        (AUTH_LAYER_VERSION << (8 - VER_BIT_LENGTH)) + 
AUTHENTICATE);

-        long writtenByteTime = System.currentTimeMillis();
-        long wbtlen = writtenByteTime - setupTime;
-        if (logDEBUG || wbtlen > 500)
+               long writtenByteTime = System.currentTimeMillis();
+               long wbtlen = writtenByteTime - setupTime;
+               if (logDEBUG || wbtlen > 500)
                        Core.logger.log(this, "Written byte in " + wbtlen, 
wbtlen > 500 ? Logger.MINOR : Logger.DEBUG);

-        ByteArrayOutputStream buff = new ByteArrayOutputStream(10000);
+               ByteArrayOutputStream buff = new ByteArrayOutputStream(10000);

-        DLESCa = asymCipher.encrypt(bob, Ca, Core.getRandSource());
-        long encryptedTime = System.currentTimeMillis();
-        long elen = encryptedTime - writtenByteTime;
-        if (logDEBUG || elen > 500)
+               DLESCa = asymCipher.encrypt(bob, Ca, Core.getRandSource());
+               long encryptedTime = System.currentTimeMillis();
+               long elen = encryptedTime - writtenByteTime;
+               if (logDEBUG || elen > 500)
                        Core.logger.log(this, "Encrypted in " + elen, elen > 
500 ? Logger.MINOR : Logger.DEBUG);

-        Util.writeMPI(Ca, buff);
+               Util.writeMPI(Ca, buff);

-        Util.writeMPI(DLESCa[0], buff);
-        Util.writeMPI(DLESCa[1], buff);
-        Util.writeMPI(DLESCa[2], buff);
+               Util.writeMPI(DLESCa[0], buff);
+               Util.writeMPI(DLESCa[1], buff);
+               Util.writeMPI(DLESCa[2], buff);

-        long writtenToBufferTime = System.currentTimeMillis();
-        long wblen = writtenToBufferTime - encryptedTime;
-        if (logDEBUG || wblen > 500)
+               long writtenToBufferTime = System.currentTimeMillis();
+               long wblen = writtenToBufferTime - encryptedTime;
+               if (logDEBUG || wblen > 500)
                        Core.logger.log(this, "Written to buffer in " + wblen, 
wblen > 500 ? Logger.MINOR : Logger.DEBUG);

-        buff.writeTo(rawOut);
-        rawOut.flush();
+               buff.writeTo(rawOut);
+               rawOut.flush();

-        long flushedTime = System.currentTimeMillis();
-        long flushlen = flushedTime - writtenToBufferTime;
-        if (logDEBUG || flushlen > 500)
+               long flushedTime = System.currentTimeMillis();
+               long flushlen = flushedTime - writtenToBufferTime;
+               if (logDEBUG || flushlen > 500)
                        Core.logger.log(this, "Written to raw stream and 
flushed in " + flushlen, flushlen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        int sbb = rawIn.read();
-        long readByteTime = System.currentTimeMillis();
-        long readlen = readByteTime - flushedTime;
-        if (logDEBUG || readlen > 500)
+               int sbb = rawIn.read();
+               long readByteTime = System.currentTimeMillis();
+               long readlen = readByteTime - flushedTime;
+               if (logDEBUG || readlen > 500)
                        Core.logger.log(this, "Read byte in " + readlen, 
readlen > 500 ? Logger.MINOR : Logger.DEBUG);

-        if (SILENT_BOB_BYTE != sbb) {
+               if (SILENT_BOB_BYTE != sbb) {
                        String err = sbb == -1 ? "Peer hung up." : "Bob was not 
silent in the way that we like";
-            throw new NegotiationFailedException(conn.getPeerAddress(), err);
-        }
+                       throw new 
NegotiationFailedException(conn.getPeerAddress(), err);
+               }

-        Cb = Util.readMPI(rawIn);
-        
-        if(!DiffieHellman.checkDHExponentialValidity(this.getClass(), Cb)) {
-               String err = "Cannot accept remote exponential. WARNING: WITH 
HIGH PROBABILITY, THIS WAS A DELIBERATE ATTACK!";
-               throw new NegotiationFailedException(conn.getPeerAddress(), 
err);
-        }
-        
-        long readMPITime = System.currentTimeMillis();
-        long readmpilen = readMPITime - readByteTime;
-        if (logDEBUG || readmpilen > 500)
+               Cb = Util.readMPI(rawIn);
+
+               if (!DiffieHellman.checkDHExponentialValidity(this.getClass(), 
Cb)) {
+                       String err = "Cannot accept remote exponential. 
WARNING: WITH HIGH PROBABILITY, THIS WAS A DELIBERATE ATTACK!";
+                       throw new 
NegotiationFailedException(conn.getPeerAddress(), err);
+               }
+
+               long readMPITime = System.currentTimeMillis();
+               long readmpilen = readMPITime - readByteTime;
+               if (logDEBUG || readmpilen > 500)
                        Core.logger.log(this, "Read first MPI from peer in " + 
readmpilen, readmpilen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        Z = Cb.modPow(R, DiffieHellman.getGroup().getP());
-        byte[] kent = Util.MPIbytes(Z);
-        Util.makeKey(kent, k, 0, k.length);
-        c.initialize(k);
+               Z = Cb.modPow(R, DiffieHellman.getGroup().getP());
+               byte[] kent = Util.MPIbytes(Z);
+               Util.makeKey(kent, k, 0, k.length);
+               c.initialize(k);

-        PCFBMode pcfb = new PCFBMode(c);
-        long inittedBitsTime = System.currentTimeMillis();
-        long ilen = inittedBitsTime - readMPITime;
-        if (logDEBUG || ilen > 500)
+               PCFBMode pcfb = new PCFBMode(c);
+               long inittedBitsTime = System.currentTimeMillis();
+               long ilen = inittedBitsTime - readMPITime;
+               if (logDEBUG || ilen > 500)
                        Core.logger.log(this, "Initialized more cipher stuff in 
" + ilen, ilen > 500 ? Logger.MINOR : Logger.DEBUG);

-        pcfb.writeIV(Core.getRandSource(), rawOut);
-        long writtenIVTime = System.currentTimeMillis();
-        long wivlen = writtenIVTime - inittedBitsTime;
-        if (logDEBUG || wivlen > 500)
+               pcfb.writeIV(Core.getRandSource(), rawOut);
+               long writtenIVTime = System.currentTimeMillis();
+               long wivlen = writtenIVTime - inittedBitsTime;
+               if (logDEBUG || wivlen > 500)
                        Core.logger.log(this, "Written IV in " + wivlen, wivlen 
> 500 ? Logger.MINOR : Logger.DEBUG);

-        setOutputStream(pcfb, rawOut);
-        //setInputStream(c, rawIn);
-        //System.err.println("LALA " + pubMe.toString());
-        pubMe.writeForWire(out);
+               setOutputStream(pcfb, rawOut);
+               //setInputStream(c, rawIn);
+               //System.err.println("LALA " + pubMe.toString());
+               pubMe.writeForWire(out);
                if(logDEBUG)
-                   Core.logger.log(this, "Written pubMe: 
"+pubMe.fingerprintToString()+
-                           ": y="+pubMe.getYAsHexString()+", 
"+pubMe.getGroup().toString(),
-                           Logger.DEBUG);
-        long writtenPKTime = System.currentTimeMillis();
-        long wplen = writtenPKTime - writtenIVTime;
-        if (logDEBUG || wplen > 500)
+                       Core.logger.log(this, "Written pubMe: 
"+pubMe.fingerprintToString()+
+                               ": y="+pubMe.getYAsHexString()+", 
"+pubMe.getGroup().toString(),
+                               Logger.DEBUG);
+               long writtenPKTime = System.currentTimeMillis();
+               long wplen = writtenPKTime - writtenIVTime;
+               if (logDEBUG || wplen > 500)
                        Core.logger.log(this, "Set output stream, written PK in 
" + wplen, wplen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        Digest ctx = SHA1.getInstance();
-        byte[] Cabytes = Util.MPIbytes(Ca);
-        byte[] Cbbytes = Util.MPIbytes(Cb);
-        byte[] Yabytes = pubMe.asBytes();
-        ctx.update(Yabytes, 0, Yabytes.length);
-        ctx.update(Cabytes, 0, Cabytes.length);
-        ctx.update(Cbbytes, 0, Cbbytes.length);
+               Digest ctx = SHA1.getInstance();
+               byte[] Cabytes = Util.MPIbytes(Ca);
+               byte[] Cbbytes = Util.MPIbytes(Cb);
+               byte[] Yabytes = pubMe.asBytes();
+               ctx.update(Yabytes, 0, Yabytes.length);
+               ctx.update(Cabytes, 0, Cabytes.length);
+               ctx.update(Cbbytes, 0, Cbbytes.length);
                M = new NativeBigInteger(1, ctx.digest());

                DSASignature sigYaCaCb =
                        DSA.sign(pubMe.getGroup(), privMe, M, 
Core.getRandSource());
-        long signedTime = System.currentTimeMillis();
-        long siglen = signedTime - writtenPKTime;
-        if (logDEBUG || siglen > 500)
+               long signedTime = System.currentTimeMillis();
+               long siglen = signedTime - writtenPKTime;
+               if (logDEBUG || siglen > 500)
                        Core.logger.log(this, "Signed in " + siglen, siglen > 
500 ? Logger.MINOR : Logger.DEBUG);

-        sigYaCaCb.write(out);
-        long writtenSigTime = System.currentTimeMillis();
-        long wsiglen = writtenSigTime - signedTime;
-        if (logDEBUG || wsiglen > 500)
+               sigYaCaCb.write(out);
+               long writtenSigTime = System.currentTimeMillis();
+               long wsiglen = writtenSigTime - signedTime;
+               if (logDEBUG || wsiglen > 500)
                        Core.logger.log(this, "Written sig in " + wsiglen, 
wsiglen > 500 ? Logger.MINOR : Logger.DEBUG);
                if(logDEBUG)
-                   Core.logger.log(this, "Sig: "+sigYaCaCb+", M: "+M+" for 
"+pubMe.fingerprintToString(), Logger.DEBUG);
+                       Core.logger.log(this, "Sig: "+sigYaCaCb+", M: "+M+" for 
"+pubMe.fingerprintToString(), Logger.DEBUG);

-        out.flush();
-        long flushedAgainTime = System.currentTimeMillis();
-        long flushAgainLen = flushedAgainTime - writtenSigTime;
-        if (logDEBUG || flushAgainLen > 500)
+               out.flush();
+               long flushedAgainTime = System.currentTimeMillis();
+               long flushAgainLen = flushedAgainTime - writtenSigTime;
+               if (logDEBUG || flushAgainLen > 500)
                        Core.logger.log(this, "Flushed again in " + 
flushAgainLen, flushAgainLen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        setInputStream(c, rawIn);
-        DSASignature sigCaCb = DSASignature.read(in);
-        long readSigTime = System.currentTimeMillis();
-        long rslen = readSigTime - flushedAgainTime;
-        if (logDEBUG || rslen > 500)
+               setInputStream(c, rawIn);
+               DSASignature sigCaCb = DSASignature.read(in);
+               long readSigTime = System.currentTimeMillis();
+               long rslen = readSigTime - flushedAgainTime;
+               if (logDEBUG || rslen > 500)
                        Core.logger.log(this, "Set input stream, read signature 
in " + rslen, rslen > 500
                                        ? Logger.MINOR
                                        : Logger.DEBUG);

-        ctx.update(Cabytes, 0, Cabytes.length);
-        ctx.update(Cbbytes, 0, Cbbytes.length);
+               ctx.update(Cabytes, 0, Cabytes.length);
+               ctx.update(Cbbytes, 0, Cbbytes.length);
                M = new NativeBigInteger(1, ctx.digest());
-        if (!DSA.verify(bob, sigCaCb, M)) {
+               if (!DSA.verify(bob, sigCaCb, M)) {
                        String err =
                                "Remote is not who she claims to be, or did not 
"
-                    + "receive the correct DH parameters";
-            throw new AuthenticationFailedException(conn.getPeerAddress(), 
err);
-        }
+                                       + "receive the correct DH parameters";
+                       throw new 
AuthenticationFailedException(conn.getPeerAddress(), err);
+               }

-        long verifiedSigTime = System.currentTimeMillis();
-        long vstlen = verifiedSigTime - readSigTime;
-        if (logDEBUG || vstlen > 500)
+               long verifiedSigTime = System.currentTimeMillis();
+               long vstlen = verifiedSigTime - readSigTime;
+               if (logDEBUG || vstlen > 500)
                        Core.logger.log(this, "Verified signature in " + 
vstlen, vstlen > 500 ? Logger.MINOR : Logger.DEBUG);

                linkInfo = linkManager.addLink(bob, pubMe, k);
-        ready = true;
-        conn.notifyAll();
-    }
+               ready = true;
+               conn.notifyAll();
+       }

-    public final LinkManager getManager() {
-        return linkManager;
-    }
+       public final LinkManager getManager() {
+               return linkManager;
+       }

-    public final InputStream getInputStream() {
-        waitReady();
-        return in;
-    }
+       public final InputStream getInputStream() {
+               waitReady();
+               return in;
+       }

-    public final OutputStream getOutputStream() {
-        waitReady();
-        return out;
-    }
+       public final OutputStream getOutputStream() {
+               waitReady();
+               return out;
+       }

-    InputStream tis = null;
+       InputStream tis = null;

-    private final void setInputStream(CipherInputStream in) {
-        //     tis = ThrottledInputStream.throttledStream(in);
-        //     if(tis instanceof ThrottledInputStream)
-        //         ((ThrottledInputStream)tis).setDisabled(true);
+       private final void setInputStream(CipherInputStream in) {
+               //      tis = ThrottledInputStream.throttledStream(in);
+               //      if(tis instanceof ThrottledInputStream)
+               //          ((ThrottledInputStream)tis).setDisabled(true);
                if (in == null)
                        throw new IllegalArgumentException("null stream");
-        this.in = in;
-    }
+               this.in = in;
+       }

-    private final void setInputStream(BlockCipher c, InputStream raw)
-            throws IOException {
+       private final void setInputStream(BlockCipher c, InputStream raw)
+               throws IOException {
                if (raw == null)
                        throw new IllegalArgumentException("null stream");
-        this.in = new CipherInputStream(c, raw, true, true);
-    }
+               this.in = new CipherInputStream(c, raw, true, true);
+       }

        private final void setSilentBobCheckingInputStream(
                BlockCipher c,
@@ -795,289 +795,289 @@
                throws IOException {
                if (raw == null)
                        throw new IllegalArgumentException("null stream");
-        setInputStream(c, new SilentBobCheckingInputStream(raw));
-    }
+               setInputStream(c, new SilentBobCheckingInputStream(raw));
+       }

-    /**
-     * This lets us check the 0xfb that should precede Bob's encrypted messages
-     * after a resume, without adding an extra pass.
-     */
+       /**
+        * This lets us check the 0xfb that should precede Bob's encrypted 
messages
+        * after a resume, without adding an extra pass.
+        */
        private final class SilentBobCheckingInputStream
                extends FilterInputStream {
-        private boolean checked = false;
+               private boolean checked = false;

-        public SilentBobCheckingInputStream(InputStream in) {
-            super(in);
-        }
+               public SilentBobCheckingInputStream(InputStream in) {
+                       super(in);
+               }

-        public final int read() throws IOException {
+               public final int read() throws IOException {
                        if (!checked)
                                check();
-            return this.in.read();
-        }
+                       return this.in.read();
+               }

                public final int read(byte[] buf, int off, int len)
                        throws IOException {
                        if (!checked)
                                check();
-            return this.in.read(buf, off, len);
-        }
+                       return this.in.read(buf, off, len);
+               }

-        private void check() throws IOException {
-            checked = true;
-            if (this.in.read() != SILENT_BOB_BYTE) {
+               private void check() throws IOException {
+                       checked = true;
+                       if (this.in.read() != SILENT_BOB_BYTE) {
                                Core.logger.log(FnpLink.this, "Bob didn't send 
the magic byte after a resume; discarding "
                                                + "cached session key", 
Logger.MINOR);
-                FnpLink.this.close();
-                linkManager.removeLink(linkInfo);
+                               FnpLink.this.close();
+                               linkManager.removeLink(linkInfo);
                                throw new IOException("Bob didn't send the 
magic byte after a resume");
-            }
-        }
-    }
+                       }
+               }
+       }

-    public void encryptBytes(byte[] buf, int offset, int length)
-            throws IOException {
-        CipherOutputStream os = out;
+       public void encryptBytes(byte[] buf, int offset, int length)
+               throws IOException {
+               CipherOutputStream os = out;
                if (os == null)
                        throw new IOException("already closed!");
-        PCFBMode ctx = os.getCipher();
+               PCFBMode ctx = os.getCipher();
                if (ctx != null)
                        ctx.blockEncipher(buf, offset, length);
-    }
+       }

-    // FIXME: neither of these should be inner classes
+       // FIXME: neither of these should be inner classes

-    protected class AdapterOutputStream extends FilterOutputStream {
+       protected class AdapterOutputStream extends FilterOutputStream {

-        AdapterOutputStream() {
-            super(null);
-        }
+               AdapterOutputStream() {
+                       super(null);
+               }

-        AdapterOutputStream(OutputStream os) {
-            super(os);
-        }
+               AdapterOutputStream(OutputStream os) {
+                       super(os);
+               }

-        public synchronized void write(byte[] b) throws IOException {
+               public synchronized void write(byte[] b) throws IOException {
                        if (this.out == null)
                                throw new IOException("already closed!");
-            this.out.write(b);
-        }
+                       this.out.write(b);
+               }

-        public synchronized void write(int i) throws IOException {
+               public synchronized void write(int i) throws IOException {
                        if (this.out == null)
                                throw new IOException("already closed!");
-            this.out.write(i);
-        }
+                       this.out.write(i);
+               }

-        public synchronized void write(byte[] b, int off, int len)
-                throws IOException {
+               public synchronized void write(byte[] b, int off, int len)
+                       throws IOException {
                        if (this.out == null)
                                throw new IOException("already closed!");
-            this.out.write(b, off, len);
-        }
+                       this.out.write(b, off, len);
+               }

-        public void flush() throws IOException {
-            //Avoid doing a nested
-            // FNPLink$AdapterOutputStream/ConnectionHandler$CHOutputStream
-            // lock since other code is doing it in reverse (potential deadlock
-            // situation)
-            OutputStream o = this.out;
+               public void flush() throws IOException {
+                       //Avoid doing a nested
+                       // 
FNPLink$AdapterOutputStream/ConnectionHandler$CHOutputStream
+                       // lock since other code is doing it in reverse 
(potential deadlock
+                       // situation)
+                       OutputStream o = this.out;
                        if (o == null)
                                throw new IOException("already closed!");
-            o.flush();
-        }
+                       o.flush();
+               }

-        OutputStream getOut() {
-            return this.out;
-        }
+               OutputStream getOut() {
+                       return this.out;
+               }

-        synchronized void setOut(OutputStream out) {
-            this.out = out;
-        }
-    }
+               synchronized void setOut(OutputStream out) {
+                       this.out = out;
+               }
+       }

-    protected class AdapterInputStream extends FilterInputStream {
+       protected class AdapterInputStream extends FilterInputStream {

-        AdapterInputStream() {
-            super(null);
-        }
+               AdapterInputStream() {
+                       super(null);
+               }

-        AdapterInputStream(InputStream is) {
-            super(is);
-        }
+               AdapterInputStream(InputStream is) {
+                       super(is);
+               }

-        InputStream getIn() {
-            return this.in;
-        }
+               InputStream getIn() {
+                       return this.in;
+               }

-        void setIn(InputStream is) {
-            this.in = is;
-        }
-    }
+               void setIn(InputStream is) {
+                       this.in = is;
+               }
+       }

-    private final void setOutputStream(CipherOutputStream out) {
-        this.out = out; // tcpConn buffers us
-    }
+       private final void setOutputStream(CipherOutputStream out) {
+               this.out = out; // tcpConn buffers us
+       }

        private final void setOutputStream(PCFBMode c, OutputStream raw) {
-        this.out = new CipherOutputStream(c, raw);
-    }
+               this.out = new CipherOutputStream(c, raw);
+       }

-    public InputStream makeInputStream(InputStream is) {
+       public InputStream makeInputStream(InputStream is) {
                if (innerIn != null)
                        innerIn.setIn(is);
-        else
-            return null;
-        return getInputStream();
-    }
+               else
+                       return null;
+               return getInputStream();
+       }

-    public OutputStream makeOutputStream(OutputStream os) {
-        innerOut.setOut(os);
-        return getOutputStream();
-    }
+       public OutputStream makeOutputStream(OutputStream os) {
+               innerOut.setOut(os);
+               return getOutputStream();
+       }

-    //     protected boolean wrapped = false;
+       //     protected boolean wrapped = false;

-    public final void wrapThrottle() {
+       public final void wrapThrottle() {
                freenet.transport.tcpConnection tcpConn =
                        (freenet.transport.tcpConnection) conn;
-        tcpConn.enableThrottle();
-    }
+               tcpConn.enableThrottle();
+       }

-    //         if(!wrapped) {
-    //             out = ThrottledOutputStream.throttledStream(out);
-    //             if(tis != null && tis instanceof ThrottledInputStream) {
-    //                 ((ThrottledInputStream)tis).setDisabled(false);
-    //             } else {
-    //                 tis = in = ThrottledInputStream.throttledStream(in);
-    //             }
-    //             wrapped = true;
-    //         }
-    //     }
+       //      if(!wrapped) {
+       //          out = ThrottledOutputStream.throttledStream(out);
+       //          if(tis != null && tis instanceof ThrottledInputStream) {
+       //              ((ThrottledInputStream)tis).setDisabled(false);
+       //          } else {
+       //              tis = in = ThrottledInputStream.throttledStream(in);
+       //          }
+       //          wrapped = true;
+       //      }
+       //     }

-    public void close() {
-        if (logDEBUG)
+       public void close() {
+               if (logDEBUG)
                        Core.logger.log(this, "Closing FnpLink: " + this, new 
Exception("debug"), Logger.DEBUG);
-        synchronized (conn) {
-            try {
+               synchronized (conn) {
+                       try {
                                java.net.Socket sock =
                                        ((freenet.transport.tcpConnection) 
conn).getSocket();
                                // throws only if already closed, so
-                                      // ignore it
-                if (sock.getChannel().isBlocking()) {
-                    out.flush(); // ignore this too
-                }
-                conn.close(); // and this
-            } catch (IOException e) {
-                if (logDEBUG)
+                               // ignore it
+                               if (sock.getChannel().isBlocking()) {
+                                       out.flush(); // ignore this too
+                               }
+                               conn.close(); // and this
+                       } catch (IOException e) {
+                               if (logDEBUG)
                                        Core.logger.log(this, "close() got an 
IOException: " + e + " for " + this + " on " + conn,
-                                Logger.DEBUG);
-                // Purely for event tracking - no real significance
-            }
-            conn.notifyAll();
-            ready = true;
-        }
+                                                       Logger.DEBUG);
+                               // Purely for event tracking - no real 
significance
+                       }
+                       conn.notifyAll();
+                       ready = true;
+               }

-        // Set streams to null, so the buffer
-        // can be gc'ed (using the default configuration this frees
-        // up 128k)
-        //this.in = null; - this.in is not buffered - FIXME
-        // other reason: we may still have some process()ing to do
+               // Set streams to null, so the buffer
+               // can be gc'ed (using the default configuration this frees
+               // up 128k)
+               //this.in = null; - this.in is not buffered - FIXME
+               // other reason: we may still have some process()ing to do

-        this.in = null;
-        this.out = null;
-        AdapterOutputStream aos = this.innerOut;
-        AdapterInputStream ais = this.innerIn;
-        this.innerOut = null;
-        this.innerIn = null;
-        aos.setOut(null);
-        ais.setIn(null);
-        asymCipher = null;
-        //     conn = null; - needed for getPeerAddress etc
-    }
+               this.in = null;
+               this.out = null;
+               AdapterOutputStream aos = this.innerOut;
+               AdapterInputStream ais = this.innerIn;
+               this.innerOut = null;
+               this.innerIn = null;
+               aos.setOut(null);
+               ais.setIn(null);
+               asymCipher = null;
+               //      conn = null; - needed for getPeerAddress etc
+       }

-    public final void setTimeout(int timeout) throws IOException {
-        conn.setSoTimeout(timeout);
-    }
+       public final void setTimeout(int timeout) throws IOException {
+               conn.setSoTimeout(timeout);
+       }

-    public final int getTimeout() throws IOException {
-        return conn.getSoTimeout();
-    }
+       public final int getTimeout() throws IOException {
+               return conn.getSoTimeout();
+       }

-    public final Identity getMyIdentity() {
-        return linkInfo.getMyIdentity();
-    }
+       public final Identity getMyIdentity() {
+               return linkInfo.getMyIdentity();
+       }

        public final Address getMyAddress(ListeningAddress lstaddr) {
-        return conn.getMyAddress(lstaddr);
-    }
+               return conn.getMyAddress(lstaddr);
+       }

-    public final Address getMyAddress() {
-        return conn.getMyAddress();
-    }
+       public final Address getMyAddress() {
+               return conn.getMyAddress();
+       }

        public final Address getPeerAddress(ListeningAddress lstaddr) {
-        waitReady();
-        return conn.getPeerAddress(lstaddr);
-    }
+               waitReady();
+               return conn.getPeerAddress(lstaddr);
+       }

-    public final Address getPeerAddress() {
-        waitReady();
-        return conn.getPeerAddress();
-    }
+       public final Address getPeerAddress() {
+               waitReady();
+               return conn.getPeerAddress();
+       }

-    public final Identity getPeerIdentity() {
-        waitReady();
-        return linkInfo.getPeerIdentity();
-    }
+       public final Identity getPeerIdentity() {
+               waitReady();
+               return linkInfo.getPeerIdentity();
+       }

-    public final Connection getConnection() {
-        return conn;
-    }
+       public final Connection getConnection() {
+               return conn;
+       }

-    //public boolean sending() {
-    //    return true; //FIXME
-    //}
+       //public boolean sending() {
+       //    return true; //FIXME
+       //}

-    public int headerBytes() {
-        // REDFLAG
-        return new Rijndael().getKeySize() / 8;
-    }
+       public int headerBytes() {
+               // REDFLAG
+               return new Rijndael().getKeySize() / 8;
+       }

-    private void waitReady() {
-        if (!ready) {
-            synchronized (conn) {
-                while (!ready) {
-                    try {
-                        conn.wait(200);
-                    } catch (InterruptedException e) {
-                    }
-                }
-            }
-        }
-    }
+       private void waitReady() {
+               if (!ready) {
+                       synchronized (conn) {
+                               while (!ready) {
+                                       try {
+                                               conn.wait(200);
+                                       } catch (InterruptedException e) {
+                                       }
+                               }
+                       }
+               }
+       }

-    //profiling
-    //WARNING:remove before release
-    protected void finalize() {
-        synchronized (profLock) {
-            instances--;
-        }
-    }
+       //profiling
+       //WARNING:remove before release
+       protected void finalize() {
+               synchronized (profLock) {
+                       instances--;
+               }
+       }

-    /*
-     * (non-Javadoc)
-     * 
-     * @see freenet.session.Link#decryptBytes(byte[], int, int)
-     */
-    public void decryptBytes(byte[] decryptBuffer, int offset, int len)
-            throws IOException {
-        CipherInputStream is = in;
+       /*
+        * (non-Javadoc)
+        * 
+        * @see freenet.session.Link#decryptBytes(byte[], int, int)
+        */
+       public void decryptBytes(byte[] decryptBuffer, int offset, int len)
+               throws IOException {
+               CipherInputStream is = in;
                if (is == null)
                        throw new IOException("already closed");
-        PCFBMode ctx = is.getCipher();
+               PCFBMode ctx = is.getCipher();
                if (ctx != null)
                        ctx.blockDecipher(decryptBuffer, offset, len);
-    }
+       }

 }


Reply via email to