Compare commits

...

230 Commits

Author SHA1 Message Date
baebd1fdd2 * Update versions, package release 2009-01-24 23:57:39 +00:00
zzz
28cfd8cffe sv back in the updater 2009-01-22 17:36:03 +00:00
zzz
a4468219c7 sv take 4 2009-01-22 17:24:38 +00:00
zzz
70f07e5bc7 sv encoding take 3 2009-01-22 16:03:12 +00:00
zzz
173e8a0434 console css tweaks 2009-01-22 16:00:41 +00:00
zzz
72fd42ef9b -11 2009-01-17 17:35:14 +00:00
zzz
ba7dbf9064 propagate from branch 'i2p.i2p.zzz.test' (head d4e23b124489f9a3dd9410aa941e88823702b950)
to branch 'i2p.i2p' (head 7a54e1c58b8cf2ad43830ddec6d404229e3e6e60)
2009-01-17 17:33:17 +00:00
zzz
807f0665b1 tweak 2009-01-17 17:31:00 +00:00
zzz
416b0e4540 Prevent two NTCP Pumpers 2009-01-17 17:28:37 +00:00
zzz
011ded2ee4 -10 2009-01-14 17:06:52 +00:00
zzz
f9faf3c70d propagate from branch 'i2p.i2p.zzz.test' (head 4bd16d213231d7bd4373d4b57c449b358389f568)
to branch 'i2p.i2p' (head c7655ab1094ca15b4485ea2ac66085e87e28b0d6)
2009-01-14 17:04:35 +00:00
zzz
0ea532c72e reduce initial RTT to 8s 2009-01-14 13:50:44 +00:00
zzz
104cf8346e add .de thx echelon 2009-01-13 21:17:01 +00:00
zzz
3e7e5d6113 dont build sam tests by default 2009-01-13 19:54:07 +00:00
zzz
0275c5e13b crstrack 2009-01-13 19:53:35 +00:00
zzz
1c76d240e0 * i2psnark:
- Fix double completion message
      - Add crstrack
2009-01-13 19:52:45 +00:00
zzz
366da1b37c add b32 config for mosfet 2009-01-13 19:32:10 +00:00
zzz
bdcb625e6d fix rare NPE 2009-01-13 19:28:09 +00:00
zzz
8296723533 * HTTPClient: Fix per-tunnel settings for i2cp.gzip and i2ptunnel.httpclient.send* (thx tino) 2009-01-13 19:27:14 +00:00
zzz
957c809774 drop more syndie files 2009-01-12 16:28:36 +00:00
zzz
70b99cf4f9 prevent possible latency-measuring attack 2009-01-12 14:51:38 +00:00
zzz
05a6353142 .b32.i2p 2009-01-12 14:31:43 +00:00
zzz
85615b972b noobhelp 2009-01-12 05:21:16 +00:00
zzz
e3abea1ad2 add netdb links on tunnels.jsp 2009-01-11 15:25:23 +00:00
zzz
bc54908a22 cleanups using getProperty(String, int) 2009-01-10 22:34:07 +00:00
zzz
60bd9803f0 fix burst seconds display 2009-01-10 22:30:43 +00:00
zzz
c3360cc3d7 remove 1m fail column 2009-01-10 21:47:38 +00:00
zzz
aa71725159 -9 2009-01-08 21:00:08 +00:00
zzz
574713e608 propagate from branch 'i2p.i2p.zzz.test' (head 27dec7ffd064f6ecb40189c0438e4aee9f887a9c)
to branch 'i2p.i2p' (head 5aa9ccf6d6abec74c2d0d92ca02bc807463be93b)
2009-01-08 20:53:56 +00:00
zzz
0aaae0b0da robt4 2009-01-08 20:48:57 +00:00
zzz
ed34964747 reduce fast retx threshold to 2 2009-01-08 20:41:50 +00:00
zzz
7b758d89d0 * ExploreJob/SearchJob - more fixes:
- Disable ExploreKeySelectorJob completely, just have
        StartExplorersJob select a random key if queue is empty
      - Add netDb.alwaysQuery=[B64Hash] for debugging
      - Queue results of exploration for more exploration
      - Floodfills periodically shuffle their KBuckets, and
        FloodfillPeerSelector sorts more keys, so that
        exploration works well
2009-01-08 19:27:57 +00:00
zzz
1c7111eca0 alternate base32 check 2009-01-07 14:48:16 +00:00
zzz
831f09c91a fix corruption of update urls 2009-01-05 20:30:36 +00:00
zzz
4f836a20e1 * ExploreJob/SearchJob - fix brokenness:
- Give each search a minimum of time even at the end
      - Fix ExploreJob exclude peer list
      - Always add floodfills to exclude peer list
      - Don't queue keys for exploration or run ExploreJob
        if floodfill
      - Allow floodfills to return non-floodfills in
        a DSRM msg so exploration works
2009-01-05 15:21:00 +00:00
zzz
8faeaaa1ae Transport: Don't shitlist a peer if we are at our connection limit 2009-01-05 15:16:14 +00:00
zzz
7271289c1f Shitlist: Reduce max time to 30m (was 60m) 2009-01-05 15:13:42 +00:00
zzz
8421ae1ed4 * Streaming: Reduce default initial window size from 12 to 6,
to account for the MTU increase in the last release
2009-01-05 15:12:56 +00:00
zzz
d042c6b921 recognize robert 0.3 2009-01-05 15:11:36 +00:00
zzz
e2e4516a8f Fix display of outbound backup count 2009-01-05 15:11:00 +00:00
zzz
efc604a25c Remove readme_xx.html from updater 2009-01-05 15:06:56 +00:00
zzz
5c1864ed5e addressbook: Prevent Base32 hostnames 2009-01-05 15:06:29 +00:00
zzz
debf92fd9b history for prop., -8 2009-01-03 00:49:33 +00:00
zzz
9477b139be propagate from branch 'i2p.i2p.zzz.test' (head 014db28e7b42a25a02de0c0eee5f2fc57352e268)
to branch 'i2p.i2p' (head e4d9945a49c24434a8eaf34d142e033a3a6e0828)
2009-01-03 00:42:14 +00:00
zzz
53ce3c4802 sort torrents with a locale-based sort 2009-01-03 00:05:03 +00:00
zzz
d61af12867 clean up and fix the possibly broken browser launcher config 2009-01-02 20:09:20 +00:00
zzz
908c542b40 move buttons 2009-01-02 18:07:16 +00:00
zzz
ef998349cc require router.memoryUsed stat 2009-01-01 13:58:00 +00:00
zzz
44446d76e4 convert db to concurrent 2009-01-01 13:54:42 +00:00
zzz
a616a5f1c9 prep for upcoming torrent updater 2009-01-01 13:13:04 +00:00
zzz
c0b616e519 revert core version, -7 2009-01-01 12:45:33 +00:00
b4d3986006 router and core version bump 2008-12-31 07:53:30 +00:00
ba9108f937 bump revision to 0.0.3 2008-12-30 13:20:54 +00:00
161379f004 Removed debug line. 2008-12-30 10:29:39 +00:00
841feaedff Bugfix for getting Properties to actually work. 2008-12-30 07:52:04 +00:00
ba8de6c565 Spelling error correction. 2008-12-22 23:04:41 +00:00
zzz
d6148db455 * NetDb:
- Expire routers with introducers after 90m.
        This should improve reachability to firewalled routers
        by keeping introducer info current.
      - Expire routers with no addresses after 90m.
2008-12-21 14:43:09 +00:00
zzz
33b43f40b9 try again to kill the i2psnarkurl files 2008-12-20 02:33:57 +00:00
zzz
4336dc441e Remove spurious UDP warning on startup 2008-12-20 01:04:19 +00:00
zzz
2d86e7cf60 add router.memoryUsed stat 2008-12-20 01:00:53 +00:00
zzz
219e96d416 Remove apps/ bogobot jdom pants q rome stasher syndie 2008-12-15 21:54:52 +00:00
zzz
0c72fe7383 history for prop -5 2008-12-14 15:14:05 +00:00
zzz
369599fedd propagate from branch 'i2p.i2p.zzz.test' (head c021d3213ed91036828c43f1e93916e319d47bc1)
to branch 'i2p.i2p' (head f571e6566b12cd0ae93fd57157b849d5a963612f)
2008-12-14 15:10:12 +00:00
zzz
847c9dafce * I2CP, HostsTxtNamingService, I2PTunnel:
Implement Base32 Hash hostnames, via the naming service.
      Names are of the form [52-characters].i2p, where
      the 52 characters are the Base32 representation of our
      256-byte hash. The client requests a lookup of the hash
      via a brief I2CP session using new I2CP request/reply
      messages. The router looks up the leaseset for the hash
      to convert the hash to a dest. Convert the I2PTunnel
      'preview' links to use Base32 hostnames as a
      demonstration.
2008-12-14 15:03:11 +00:00
zzz
734818f651 * Transport:
- Cleanup max connections code
      - Add i2np.udp.maxConnections
      - Set max connections based on share bandwidth
      - Add haveCapacity() that can be used for connection
        throttling in the router
      - Reject IBGW/OBEP requests when near connection limit
      - Reduce idle timeout when near connection limit
    * Tunnel request handler:
      - Require tunnel.dropLoad* stats
      - Speed up request loop
2008-12-14 14:07:37 +00:00
zzz
dae6fd47d9 javadoc fixes 2008-12-13 18:07:20 +00:00
zzz
0956393cf3 add int getProperty(String prop, int default) 2008-12-10 16:32:26 +00:00
zzz
d16f187394 change restart/shutdown/update links to buttons 2008-12-10 16:25:09 +00:00
zzz
962a8f6f49 more splitting classes 2008-12-10 15:37:28 +00:00
9aa8707647 Prepended log LVL to messages, added INFO LVL 2008-12-08 22:34:45 +00:00
zzz
1fdd228a9d constructor fix 2008-12-08 16:38:46 +00:00
zzz
819d857550 Do not build tests 2008-12-08 15:03:45 +00:00
zzz
04fb12932f prop history, -4 2008-12-08 14:12:29 +00:00
zzz
703b6ed190 propagate from branch 'i2p.i2p.zzz.test' (head eac1d36c16cf82b0d98167c58e1562aa443ee5e5)
to branch 'i2p.i2p' (head b1fa07e8a4dabc26e731f7d486677abb165d975c)
2008-12-08 14:00:09 +00:00
zzz
bd6c63cc7e add findbugs target 2008-12-06 00:11:13 +00:00
zzz
7dbb13d6dc move atalk from core to apps 2008-12-05 20:31:54 +00:00
zzz
ebdc69cbc2 remove PRNG from summary bar 2008-12-05 14:52:15 +00:00
zzz
868fe90d7a increase max files to 256 2008-12-05 14:38:59 +00:00
9e39f34473 BOB: removed debugging (oops!)
BUMP: BOB to 00.00.02
BUMP router to -3
2008-12-05 10:12:10 +00:00
45ed744210 BUMP to -2 for bug reporting. 2008-12-05 09:55:53 +00:00
701904d119 BUGFIX: streaming lib blocking on a write() will now fail when the socket
is closed from under it.
Enhancement: BOB can now clear a destination in under 1 second with the above fix.
	BOB also will do a thread dump when something really aweful happens,
	so that developers/users can help in debugging.
2008-12-05 09:51:48 +00:00
zzz
dcf4bb595f split classes into their own files 2008-12-04 21:56:22 +00:00
zzz
e9f27c60dd avoid two NPEs on corrupt fragments 2008-12-04 00:09:52 +00:00
zzz
321f11c055 robert + xl 2008-12-03 23:38:13 +00:00
zzz
85cebc7992 * Transport:
- Fixes and cleanups when NTCP and/or UDP transports disabled
      - More TCP removal cleanup
      - Clean up bandwidth limiting, centralize defaults
      - Force burst to be >= limit
      - Increase default bw to 48/24, burst 64/32
2008-12-03 18:53:57 +00:00
zzz
8e5c4a3e22 error to warn 2008-12-03 16:55:48 +00:00
zzz
dff75de97a tweak 2008-12-03 14:46:37 +00:00
zzz
f1fd35265a enable blocklists by default 2008-12-03 14:26:39 +00:00
zzz
b73b3fc5ac * i2psnark:
- Add default i2psnark.config for new installs
      - Remove wishlist link
2008-12-03 01:49:19 +00:00
zzz
13d4ccf2e7 remove restart button if no wrapper 2008-12-02 19:07:58 +00:00
zzz
8c9ac941bf fix NPE on early shutdown 2008-12-02 16:28:29 +00:00
zzz
3fc698c7d3 disable eepsite webapps by default 2008-12-02 16:26:26 +00:00
zzz
15596c9230 add textareas to susidns 2008-12-02 16:25:43 +00:00
zzz
7fdbe9b87b post-0.6.5 netdb stats cleanup 2008-12-02 16:25:16 +00:00
zzz
5acc56c184 increase standalone to 128MB max mem 2008-12-02 16:23:54 +00:00
zzz
c524231c6d history for the propagate of the snark rewrite 2008-12-01 02:57:24 +00:00
zzz
5d4a7967cb propagate from branch 'i2p.i2p.zzz.i2psnark' (head 738b0ee2a3e938f83c8524d7ee1cbd66c83d7d56)
to branch 'i2p.i2p' (head 7bc276bf13158ca72d687031fdf5e9921efc5050)
2008-12-01 02:51:28 +00:00
01101f9867 * Fix typos in news.xml 2008-12-01 01:07:22 +00:00
c93ccd15eb * Update versions, package release, fix typo in comment 2008-12-01 00:23:53 +00:00
zzz
73280ab834 amiga->echelon 2008-11-28 18:08:15 +00:00
6a3c52b7fa Added verify command to check that a destination's BASE64 is correct for
external applications that need it.
2008-11-28 16:07:29 +00:00
dev
90983c8761 added inital version of a deploy script 2008-11-27 19:19:24 +00:00
zzz
daac598bde fix windows url launcher 2008-11-26 18:32:51 +00:00
dev
41d98acc95 minor style changes 2008-11-26 15:56:36 +00:00
dev
c8970c0fc6 changed some of the URL's 2008-11-26 15:20:00 +00:00
zzz
4e5825c648 * Cache DNS and negative DNS for 5m (was 1m and forever)
* Delay shitlist cleaner at startup
    * Strip wrapper properties from client config
    * Define multiple cert type
    * Prohibit negative maxSends in streaming
    * HTML fixup on configtunnels.jsp
    * Increase wrapper exit timeout from default 15s to 30s
2008-11-21 16:29:16 +00:00
zzz
93f0092437 propagate from branch 'i2p.i2p.zzz.test' (head fa1d7d3151cb0b03dde308766d3d350afda8f14a)
to branch 'i2p.i2p' (head 8cb6295e6a3492fd3b93366bfb0ebf231115fa85)
2008-11-20 15:53:30 +00:00
zzz
bad4c4a133 SAM: Convert from I2PThread to I2PAppThread so it won't
shutdown the whole router when ooming.
2008-11-20 14:59:55 +00:00
zzz
da9a4ce557 EepGet:
- Better handling of 504 gateway timeout
     (keep going up to limit of retry count rather
      than just one more partial fetch)
   - Add -t cmd line option for timeout
   - Better handling of 403, 409, 503 errors
   - Don't keep going after unknown return code
   - Don't delay before exiting after a failure
2008-11-20 14:14:13 +00:00
zzz
0ff8167425 i2psnark:
- Don't create SnarkManager instance until first call,
      so it doesn't create the i2psnark dir, read the config,
      etc., for single Snark instances.
    - Don't read i2psnark.config twice; fix setting
      i2psnark.dir
    - More Snark constructor changes for calling from router
    - Make max connections per torrent configurable
2008-11-18 02:18:23 +00:00
zzz
9ae589449d tweak 2008-11-16 19:12:58 +00:00
zzz
134764b154 i2psnark:
- Use new I2PAppThread that does not call global listeners on OOM,
      so that OOMing apps will not shutdown the whole router.
2008-11-16 17:24:08 +00:00
zzz
23699e46e5 i2psnark:
- Remove static instances of I2PSnarkUtil, ConnectionAcceptor,
      and PeerCoordinatorSet
    - Convert static classes in Snark to listeners
    - Fix Snark to work in single torrent mode again
    - Should now work with multiple single Snarks
2008-11-16 17:11:53 +00:00
zzz
fa23a7b066 i2psnark:
- Refactor to allow running a single Snark without a SnarkManager again,
    by moving some things from SnarkManager to I2PSnarkUtil,
    having Snark call completeListener callbacks,
    and having Storage call storageListener callbacks.
    This is in preparation for using Snark for router updates.
    Step 2 is to allow multiple I2PSnarkUtil instances.
  - Big rewrite of Storage to open file descriptors on demand, and
    close them when unused, so we can support large numbers of torrents.
2008-11-15 23:52:40 +00:00
zzz
de21a5ec48 drop old tcp transport and old tunnel build sources 2008-11-15 20:57:52 +00:00
zzz
b1a9dcf77e move dummy to his own file to help the build dependencies 2008-11-15 19:09:56 +00:00
zzz
15e7783477 handle missing fields in i2ptunnel edit pages better 2008-11-15 19:00:08 +00:00
zzz
afa17a8c04 * I2CP Compression:
- Add i2cp.gzip option (default true)
      - Don't bother compressing if really small
2008-11-15 15:03:19 +00:00
zzz
c7bb2e8f76 * build files:
- Don't die if depend not available
   - Only verify Jetty hash once
   - Add streaming lib tests to depends task
2008-11-14 14:48:08 +00:00
zzz
b4d299804b update history before propagate 2008-11-13 20:12:45 +00:00
zzz
77f5dd2d14 Fix blocklists with hashes only 2008-11-12 22:46:07 +00:00
zzz
c941d7bfa1 HTTPClient: Add config options to pass Via, Referer, and User-Agent through 2008-11-12 20:14:08 +00:00
zzz
049d6b2fa8 * Streaming:
- Add more info to Connection.toString() for debugging
      - Fix lifetimeMessages{Sent,Received} stats
      - Reduce RTT damping to 0.875 (was 0.9)
      - Add a stream.con.initialRTT.{in,out} stats
2008-11-12 20:10:39 +00:00
zzz
98038e9282 * Build files:
- Use the depend task with caching for more accurate dependencies
      - Make sure the routerconsole gets the latest router version
      - Fix addressbook repeated builds
2008-11-12 17:08:09 +00:00
zzz
6169904c76 oops remove extra stuff in IndexBean 2008-11-11 13:02:45 +00:00
zzz
04509f593a * Streaming: Enforce a minimum MTU of 512 2008-11-11 02:30:49 +00:00
zzz
875dd65dcb * I2PTunnel: Change "interactive" max window size to 16 (was 1) 2008-11-11 02:30:21 +00:00
zzz
b0ec6a0870 * Streaming - Fix several bugs and improve performance
when the initial data is larger than one MTU,
      e.g. HTTP GETs with large URLs, CGI params or cookies,
      or large HTTP POSTS:
      - Don't reject additional packets received without a
        send stream ID (i.e. sent before the SYN ACK was received)
      - Put unknown non-SYN packets on the SYN queue also
        so they won't be rejected
      - Reduce flusher delay to 250ms (was 500)
      - Flush unless window is full (was window is non-empty)
2008-11-10 20:30:14 +00:00
zzz
6ce2767514 * NetDb: Fix a deadlock caused by last checkin 2008-11-10 20:28:47 +00:00
zzz
5271838a14 -9 2008-11-09 16:18:45 +00:00
zzz
9ec45bbcf5 provide a link when starting a webapp 2008-11-09 16:10:59 +00:00
zzz
c9cef19a68 * Tunnel BuildHandler: add config router.participantOnly,
set to true to refuse OBEP and IBGW roles, should
      reduce connections significantly if set.
2008-11-09 16:08:24 +00:00
zzz
9f57be5f03 * Jetty: Add a I2PRequestLog class to log request dest hash 2008-11-09 16:05:13 +00:00
zzz
1793b05784 * NetDb: Don't drop routerInfos if we have connectivity issues or other problems 2008-11-09 16:02:44 +00:00
zzz
f95c324832 * configtunnels.jsp:
- Code cleanup
      - Add 4-hop option
      - Remove +/- 0-2 option
2008-11-09 15:59:35 +00:00
zzz
016c843ad6 * I2PTunnelHTTPServer: Put the requestor's dest hash
in the request headers
2008-11-09 15:57:58 +00:00
zzz
e52526b256 * NTCP: Lower idle timeout to 10m (was 15m) 2008-11-09 15:57:07 +00:00
zzz
7722ab5f6f * Routerconsole: Replace wtf msg w/ something nicer 2008-11-09 15:55:40 +00:00
zzz
c024398b93 Add some javadoc files 2008-11-09 15:54:04 +00:00
zzz
2e72ece384 * build.xml: Build speedups:
- Don't distclean in the updaterRouter target
      - Don't make prepUpdate and prepupdateSmall depend
        on distclean
      - Don't make susimail build always clean
      - Make pkg depend on distclean to be sure
      - Clean out more routerconsole and susidns files in 'ant clean'
      - i2ptunnel, routerconsole, susidns:
        Only build WEB-INF when necessary
      - systray: Only build jar when necessary
      - Don't build i2psnark standalone for the updater target
2008-11-09 15:46:08 +00:00
zzz
2b8d59d9f4 more override removals 2008-11-09 15:42:50 +00:00
dev
28b4c92241 should compile on 1.5 again now 2008-11-09 14:32:27 +00:00
dev
c9d9a83f73 finished core 2008-11-09 10:09:01 +00:00
dev
7bf57870d6 and again some more ;) 2008-11-09 09:49:54 +00:00
dev
d41b68438d and another bunch 2008-11-08 23:14:47 +00:00
dev
c634e5005d cleanup: annotated a bunch of files 2008-11-08 22:46:42 +00:00
dev
e0926b8ccd minor update to the checklist 2008-11-08 21:56:45 +00:00
dev
5ea7adb857 updated style of PrivateKeyFile to conform (more or less) to sun coding standards 2008-11-08 19:11:41 +00:00
zzz
bf12c5f9bf * Certificates:
- Add a signed Certificate type
      - Add a main() to PrivateKeyFile to generate
        Destinations with various Certificate types
      - Add a VerifiedDestination class to check Certificates
        of various types
      - Add a HashCash library from http://www.nettgryppa.com/code/
        (no distribution restrictions)
      - Allow non-null Certificates in addressbook
2008-11-02 22:13:11 +00:00
zzz
47d5e44b16 * Throttle: Reduce default max tunnels to 2000 (was 2500) 2008-11-02 21:53:17 +00:00
zzz
f6996c7d8b * NamingServices: Implement caching in the abstract class 2008-11-02 21:41:08 +00:00
zzz
fb7f4f2d11 * clients.config: Disable SAM and BOB by default for new installs 2008-11-02 21:39:32 +00:00
zzz
d89f97acd5 * I2PTunnel: Move some wayward stats to the I2PTunnel group 2008-11-02 21:38:49 +00:00
zzz
f3c9343c79 * NewsFetcher: Fix last updated time 2008-11-02 21:37:28 +00:00
zzz
16ec091209 * Streaming: Increase MTU to 1730 (was 960);
see ConnectionOptions.java for analysis
2008-11-02 21:36:52 +00:00
0b599c45ec Refactored code.
Piles of pedantic lock checks to ensure we don't get deadlocked, it's ugly.
2008-10-31 21:11:03 +00:00
7f3f6dfde3 Patches to (hoefully) fix deadlock in BOB and revision bumpped to B
SusiMail JavaDoc additions.
2008-10-30 15:04:16 +00:00
d736b75dc2 merge of '146998571b0b88243eb67af215b740f504fbcc50'
and 'ee93f3940b59255ddab5fa4aafd6f567f46783f7'
2008-10-29 09:00:13 +00:00
fa2f06b1d8 JavaDoc fixes 2008-10-29 08:59:56 +00:00
zzz
4212858409 fix english link in readme_nl.html 2008-10-28 19:07:39 +00:00
zzz
33221ce7fd More findbugs cleanup 2008-10-26 18:18:34 +00:00
zzz
fd5fcebae9 * NetDb:
- Fix behavior when router.isHidden=true
       - Delay StartExplorersJob for 10m at startup
       - More findbugs cleanups
    * netdb.jsp: Indicate if hidden
2008-10-26 18:16:18 +00:00
zzz
b743449715 * NetDb:
- Update dbLookup profile stats in FloodOnlySearchJob
         and FloodfillVerifyStoreJob
       - Fix response time store in profile in SearchJob
    * profiles.jsp: Don't override locale number format,
       clean up the response time output for floodfills
2008-10-26 18:12:36 +00:00
zzz
2a08fc7a34 * FloodfillMonitor:
- Fix ff count (we forgot ourselves)
       - Don't become ff if hidden
2008-10-26 18:08:20 +00:00
zzz
0c520de6e5 * HandleFloodfillDatabaseLookupMessageJob:
- Send back your routerinfo with the DSRM if not ff to
         spread the word that you aren't ff anymore
       - Fix behavior when router.isHidden=true
2008-10-26 18:05:51 +00:00
zzz
09b868e243 * Blocklist: Change logging from ERROR to WARN 2008-10-26 18:02:21 +00:00
zzz
83801c9feb * Stats:
- Remove unused tunnel.buildSuccess and tunnel.buildFailure
       - Remove tunnel.buildRequestTime and 5m rate stats from
         netDb, effective in next release
2008-10-26 18:00:49 +00:00
zzz
152f824779 * config.jsp: Add more help
* summary.jsp: Indicate if hidden
2008-10-26 17:24:11 +00:00
zzz
68256930b9 * UDP:
- Don't do peer tests when hidden
       - Don't offer to introduce when hidden
       - Don't continually rebuild routerInfo when hidden
       - Don't continually rebuild routerInfo when
         i2np.udp.internalPort is set but i2np.udp.port is not
       - Remove some unused functions
2008-10-26 17:20:19 +00:00
zzz
622951c794 * tunnels.jsp: Indicate if pool is dead 2008-10-26 17:18:07 +00:00
zzz
baa70299fc * I2Ping:
- Add -n count option
       - Add rtt output
       - Enhance help
       - Fix option handling
2008-10-26 17:15:59 +00:00
zzz
47856f312c * i2ptunnel/edit.jsp: Disable word wrap in textarea 2008-10-26 17:14:07 +00:00
zzz
b4c808918b * peers.jsp: Clean up 'Listening on' formatting 2008-10-26 17:11:12 +00:00
e6e4c60a25 BOB version bump to 0xA 2008-10-22 06:59:48 +00:00
2dc699b382 Better handling of listening sockets. 2008-10-22 06:57:07 +00:00
zzz
22454a06d4 UTF-8 readme_sv.html 2008-10-21 17:45:19 +00:00
zzz
0e0459f88a more findbugs 2008-10-19 22:36:18 +00:00
zzz
20effe3a7f Big findbugs cleanup 2008-10-19 22:09:14 +00:00
zzz
8a756a6e81 * FloodOnlySearchJob: Recover better if the floodfills
you know are no longer floodfill or are gone
2008-10-19 21:50:12 +00:00
zzz
a7e876da1e * FloodfillMonitor:
- Don't become ff if clock skew is high
       - Rebuild routerinfo immediately when ff status changes
2008-10-19 21:48:55 +00:00
zzz
06be4515e4 * ShellCommand: Fix main() 2008-10-19 21:46:04 +00:00
zzz
af630e9559 * configclients.jsp: Handle clients with no args 2008-10-19 21:45:04 +00:00
zzz
50c93e25c7 * Installer: Bump min JRE to 1.5 2008-10-19 21:43:56 +00:00
zzz
2d6007cf49 readme_sv.html 2008-10-19 21:42:56 +00:00
zzz
7aaed8e686 * Client: Prevent a race causing session reconnect 2008-10-19 21:41:07 +00:00
zzz
e2a1835142 readme_nl.html 2008-10-15 20:05:21 +00:00
zzz
078256da83 change to _de links 2008-10-14 17:53:16 +00:00
zzz
4f8d84e9e7 Add multilanguage support for index.jsp 2008-10-14 16:23:23 +00:00
zzz
ae967d6ef4 Disable word wrap in textareas 2008-10-14 15:46:21 +00:00
zzz
3b46b16038 Remove failing count from summary bar 2008-10-14 14:28:02 +00:00
zzz
25bf6e59bc Update install.txt files for 1.5 2008-10-14 14:26:40 +00:00
c4030f8dab Fixed one javadoc problem in snark.
This patch completes the javadoc fixups. Additions are pending.
2008-10-13 03:18:44 +00:00
e103f33c29 Addressbook javadoc fixes
Addressbook now JDK5
build.xml fixed to remove annoying javadoc warnings.
2008-10-12 17:07:21 +00:00
1c6b78a8da SAM davadoc cleanups
JDK5 compliance
2008-10-12 16:07:23 +00:00
8117d0465c BOB fixes: Default Properties work, files are properly closed. 2008-10-11 21:59:18 +00:00
0ff846deee Added package details for BOB 2008-10-11 16:50:55 +00:00
87a992bd3f Patched java docs to remove sam and bob from the SDK;
SAM and BOB are not part of the SDK in the first place.
2008-10-11 16:50:20 +00:00
41c38e64c3 Added JDK5 lint fixes
Streaming lib javadocs
2008-10-11 13:23:55 +00:00
ca5c15d4de Added more complete javadocs to ministreaming and cleaned up overrides so
the code is JDK5 compliant. There remains some unchecked warnings, but these
aren't important at this juncture.
2008-10-11 10:28:31 +00:00
f3f7537ec6 Set BOB source/target to JDK 5 (AKA 1.5)
Minor bugfixes/code cleanup on BOB
Add/Cleanup some documentation to streaming lib javadocs
2008-10-11 07:45:30 +00:00
zzz
855293d673 * Tunnels: Implement random discard to enforce share limit 2008-10-10 17:34:25 +00:00
zzz
4c2d4144d1 * i2psnark: Change default tunnel length from 1+1 to 2+0 2008-10-10 17:33:27 +00:00
zzz
387587b0b6 * Throttle: Change reject to BANDWIDTH from CRIT on shutdown
for improved anonymity
2008-10-10 17:30:35 +00:00
zzz
43e95a70d1 * configpeer.jsp: Table cleanup 2008-10-10 17:29:48 +00:00
zzz
ad56eb7220 * UDPPacketReader: Adjust logging 2008-10-10 17:29:18 +00:00
zzz
d2d32f0ad1 * peers.jsp: Change <,> to in,out for UDP 2008-10-10 17:28:23 +00:00
zzz
0428726e30 * Profiles: Reduce reject penalty in
capacity calculation to avoid a congestion collapse
2008-10-10 17:27:23 +00:00
zzz
2eb154c24c * Tunnel Tests: Add time for outbound delay, to avoid
congestion collapse
2008-10-10 17:26:44 +00:00
zzz
4ec82beec5 * build files: Change to source=1.5, target=1.5 2008-10-10 17:25:58 +00:00
224ebb16d4 Bugfixes for BOB, Important database locking to prevent thread collisions. 2008-10-09 11:58:00 +00:00
cb17fb8805 Made BOB 1.4 java compliant. 2008-10-08 16:40:07 +00:00
2c048d7465 Revision/history changes 2008-10-08 15:39:39 +00:00
00d537e5e4 Added new command to BOB, and made API a little better. 2008-10-08 15:28:06 +00:00
5eef43d239 BOB "option" added, next small push will have an API fix. 2008-10-08 14:57:02 +00:00
caaf0ccfc3 Additional BOB fixes.
Added BOB to clients.config and wrapper.config for new installs.
2008-10-08 14:28:35 +00:00
18d42ec925 A few fixes to make BOB a little more quiet,
there is possibly a little left, though.
2008-10-07 20:00:08 +00:00
872d2c48c9 Added demos for BOB 2008-10-07 19:43:43 +00:00
a3b9345ff1 Patch to reflect build version 2008-10-07 18:52:19 +00:00
eae67a44f0 merge of '07188d6eb4d52af5bdde5cbb23dc6facea726ad0'
and 'be6f83df49d5f766fd655b9ca0388bb30d68dfeb'
2008-10-07 18:50:53 +00:00
a988358ebb history.txt additions 2008-10-07 18:38:45 +00:00
bb32672c11 NEW BOB, a replacement for SAM, added It does have a different API. See it's java-doc. 2008-10-07 18:30:07 +00:00
f1c4a85991 Code cleanup in I2PSocketManagerFull and I2PServerSocketFull
BUGFIX ConnectionHandler had a comparason bug that caused it to block when infact it was asked NOT to block
2008-10-06 09:28:59 +00:00
0a5eeed370 merge of '2f46bb4293a808d63ad2494aaebced5cf2227f52'
and '702d19f746dabc901ebadec705ce42950c124f55'
2008-10-04 18:41:55 +00:00
5913d9ee4a ADDED SimpleStore, cuz I forgot to add it 2008-09-28 16:36:59 +00:00
61749aaaa9 Added Simple true/false storage class to the utilities
Added socketSoTimeout
CHANGED RetransmissionTimer is now public
FIXED SimpleTimer has a way to be stopped, and reap it's children
CLEANUP A few javadoc additions, where I could figgure out bits
CLEANUP all code that needed to catch the timeout exception for socketSoTimeout
2008-09-27 22:59:22 +00:00
b0313bd6bf disapproval of revision '7ed18fd4c3a5430150a2d76bfe202bc491115974' 2008-09-27 16:00:06 +00:00
dd7d993631 Added Simple true/false storage class to the utilities
Added socketSoTimeout
CHANGED RetransmissionTimer is now public
FIXED SimpleTimer has a way to be stopped, and reap it's children
FIXED Lots of javadoc additions, where I could
CLEANUP all code that needed to catch the timeout exception for socketSoTimeout
2008-09-25 23:59:01 +00:00
ee2fd32a97 disapproval of revision 'bd09bb36a90e766b3a406d78055d427a6200dd41' 2008-09-25 23:31:57 +00:00
fa5c7219d3 Added {get,set}SOTimeout() to the ServerSocket API,
and fixed all the broken mainstream applications depending on it.
Fixed a grave bug in SimpleTimer.
Fixed Steraming Timer to be public.
Fixed a pile of JavaDoc comments, and reformatted the files I touched.
2008-09-25 06:55:04 +00:00
8d78a77a8c Allow SimplerTimer to die.
Still needs some methods to be able to reap it, and it's children.
2008-09-24 10:35:32 +00:00
701 changed files with 14262 additions and 59790 deletions

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="echoclient" default="default" basedir=".">
<description>Builds, tests, and runs the project echoclient.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="echoclient-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@ -0,0 +1,5 @@
#!/bin/bash
(
cd dist
java -jar echoclient.jar main 37338 testclient $1
)

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

View File

@ -0,0 +1,629 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
For the purpose of easier reading the script
is divided into following sections:
- initialization
- compilation
- jar
- execution
- debugging
- javadoc
- junit compilation
- junit execution
- junit debugging
- applet
- cleanup
-->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="echoclient-impl">
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
<!--
======================
INITIALIZATION SECTION
======================
-->
<target name="-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init" name="-init-private">
<property file="nbproject/private/config.properties"/>
<property file="nbproject/private/configs/${config}.properties"/>
<property file="nbproject/private/private.properties"/>
</target>
<target depends="-pre-init,-init-private" name="-init-user">
<property file="${user.properties.file}"/>
<!-- The two properties below are usually overridden -->
<!-- by the active platform. Just a fallback. -->
<property name="default.javac.source" value="1.4"/>
<property name="default.javac.target" value="1.4"/>
</target>
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
<property file="nbproject/configs/${config}.properties"/>
<property file="nbproject/project.properties"/>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
<available file="${manifest.file}" property="manifest.available"/>
<condition property="manifest.available+main.class">
<and>
<isset property="manifest.available"/>
<isset property="main.class"/>
<not>
<equals arg1="${main.class}" arg2="" trim="true"/>
</not>
</and>
</condition>
<condition property="manifest.available+main.class+mkdist.available">
<and>
<istrue value="${manifest.available+main.class}"/>
<isset property="libs.CopyLibs.classpath"/>
</and>
</condition>
<condition property="have.tests">
<or>
<available file="${test.src.dir}"/>
</or>
</condition>
<condition property="have.sources">
<or>
<available file="${src.dir}"/>
</or>
</condition>
<condition property="netbeans.home+have.tests">
<and>
<isset property="netbeans.home"/>
<isset property="have.tests"/>
</and>
</condition>
<condition property="no.javadoc.preview">
<and>
<isset property="javadoc.preview"/>
<isfalse value="${javadoc.preview}"/>
</and>
</condition>
<property name="run.jvmargs" value=""/>
<property name="javac.compilerargs" value=""/>
<property name="work.dir" value="${basedir}"/>
<condition property="no.deps">
<and>
<istrue value="${no.dependencies}"/>
</and>
</condition>
<property name="javac.debug" value="true"/>
<property name="javadoc.preview" value="true"/>
<property name="application.args" value=""/>
<property name="source.encoding" value="${file.encoding}"/>
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
<and>
<isset property="javadoc.encoding"/>
<not>
<equals arg1="${javadoc.encoding}" arg2=""/>
</not>
</and>
</condition>
<property name="javadoc.encoding.used" value="${source.encoding}"/>
<property name="includes" value="**"/>
<property name="excludes" value=""/>
<property name="do.depend" value="false"/>
<condition property="do.depend.true">
<istrue value="${do.depend}"/>
</condition>
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
<and>
<isset property="jaxws.endorsed.dir"/>
<available file="nbproject/jaxws-build.xml"/>
</and>
</condition>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
<fail unless="src.dir">Must set src.dir</fail>
<fail unless="test.src.dir">Must set test.src.dir</fail>
<fail unless="build.dir">Must set build.dir</fail>
<fail unless="dist.dir">Must set dist.dir</fail>
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
<fail unless="dist.jar">Must set dist.jar</fail>
</target>
<target name="-init-macrodef-property">
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-javac">
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="${javac.debug}" name="debug"/>
<attribute default="" name="sourcepath"/>
<element name="customize" optional="true"/>
<sequential>
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
<classpath>
<path path="@{classpath}"/>
</classpath>
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
<customize/>
</javac>
</sequential>
</macrodef>
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<sequential>
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</depend>
</sequential>
</macrodef>
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${build.classes.dir}" name="destdir"/>
<sequential>
<fail unless="javac.includes">Must set javac.includes</fail>
<pathconvert pathsep="," property="javac.includes.binary">
<path>
<filelist dir="@{destdir}" files="${javac.includes}"/>
</path>
<globmapper from="*.java" to="*.class"/>
</pathconvert>
<delete>
<files includes="${javac.includes.binary}"/>
</delete>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-junit">
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="**" name="testincludes"/>
<sequential>
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
<batchtest todir="${build.test.results.dir}">
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
</batchtest>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
<jvmarg line="${run.jvmargs}"/>
</junit>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-nbjpda">
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="name"/>
<attribute default="${debug.classpath}" name="classpath"/>
<attribute default="" name="stopclassname"/>
<sequential>
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="dt_socket">
<classpath>
<path path="@{classpath}"/>
</classpath>
</nbjpdastart>
</sequential>
</macrodef>
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${build.classes.dir}" name="dir"/>
<sequential>
<nbjpdareload>
<fileset dir="@{dir}" includes="${fix.classes}">
<include name="${fix.includes}*.class"/>
</fileset>
</nbjpdareload>
</sequential>
</macrodef>
</target>
<target name="-init-debug-args">
<property name="version-output" value="java version &quot;${ant.java.version}"/>
<condition property="have-jdk-older-than-1.4">
<or>
<contains string="${version-output}" substring="java version &quot;1.0"/>
<contains string="${version-output}" substring="java version &quot;1.1"/>
<contains string="${version-output}" substring="java version &quot;1.2"/>
<contains string="${version-output}" substring="java version &quot;1.3"/>
</or>
</condition>
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
<istrue value="${have-jdk-older-than-1.4}"/>
</condition>
</target>
<target depends="-init-debug-args" name="-init-macrodef-debug">
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${main.class}" name="classname"/>
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="@{classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-java">
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="classname"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="${run.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}"/>
</jar>
</presetdef>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
<!--
===================
COMPILATION SECTION
===================
-->
<target depends="init" name="deps-jar" unless="no.deps"/>
<target depends="init,deps-jar" name="-pre-pre-compile">
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="-pre-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-depend">
<j2seproject3:depend/>
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
<j2seproject3:javac/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
<target name="-pre-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile/>
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
</target>
<target name="-post-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
<!--
====================
JAR BUILDING SECTION
====================
-->
<target depends="init" name="-pre-pre-jar">
<dirname file="${dist.jar}" property="dist.jar.dir"/>
<mkdir dir="${dist.jar.dir}"/>
</target>
<target name="-pre-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
<j2seproject1:jar/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
<j2seproject1:jar manifest="${manifest.file}"/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
<j2seproject1:jar manifest="${manifest.file}">
<j2seproject1:manifest>
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
</j2seproject1:manifest>
</j2seproject1:jar>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<pathconvert property="run.classpath.with.dist.jar">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
</pathconvert>
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target name="-post-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
<!--
=================
EXECUTION SECTION
=================
-->
<target depends="init,compile" description="Run a main class." name="run">
<j2seproject1:java>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject1:java>
</target>
<target name="-do-not-recompile">
<property name="javac.includes.binary" value=""/>
</target>
<target depends="init,-do-not-recompile,compile-single" name="run-single">
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
<j2seproject1:java classname="${run.class}"/>
</target>
<!--
=================
DEBUGGING SECTION
=================
-->
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
<j2seproject1:nbjpdastart name="${debug.class}"/>
</target>
<target depends="init,compile" name="-debug-start-debuggee">
<j2seproject3:debug>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
</target>
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
<j2seproject3:debug classname="${debug.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
<target depends="init" name="-pre-debug-fix">
<fail unless="fix.includes">Must set fix.includes</fail>
<property name="javac.includes" value="${fix.includes}.java"/>
</target>
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
<j2seproject1:nbjpdareload/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
<!--
===============
JAVADOC SECTION
===============
-->
<target depends="init" name="-javadoc-build">
<mkdir dir="${dist.javadoc.dir}"/>
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
<classpath>
<path path="${javac.classpath}"/>
</classpath>
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
<filename name="**/*.java"/>
</fileset>
</javadoc>
</target>
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
</target>
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
<!--
=========================
JUNIT COMPILATION SECTION
=========================
-->
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
<mkdir dir="${build.test.classes.dir}"/>
</target>
<target name="-pre-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-test-depend">
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
<target name="-pre-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
<!--
=======================
JUNIT EXECUTION SECTION
=======================
-->
<target depends="init" if="have.tests" name="-pre-test-run">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
<j2seproject3:junit testincludes="**/*Test.java"/>
</target>
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init" if="have.tests" name="test-report"/>
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
<target depends="init" if="have.tests" name="-pre-test-run-single">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
<j2seproject3:junit excludes="" includes="${test.includes}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
<!--
=======================
JUNIT DEBUGGING SECTION
=======================
-->
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
<delete file="${test.report.file}"/>
<mkdir dir="${build.test.results.dir}"/>
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
<customize>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<arg value="${test.class}"/>
<arg value="showoutput=true"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
<!--
=========================
APPLET EXECUTION SECTION
=========================
-->
<target depends="init,compile-single" name="run-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject1:java classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject1:java>
</target>
<!--
=========================
APPLET DEBUGGING SECTION
=========================
-->
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject3:debug classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
<!--
===============
CLEANUP SECTION
===============
-->
<target depends="init" name="deps-clean" unless="no.deps"/>
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
</target>
<target name="-post-clean">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
</project>

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=8ce3cee9
build.xml.script.CRC32=d1de2df3
build.xml.stylesheet.CRC32=be360661
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=8ce3cee9
nbproject/build-impl.xml.script.CRC32=22d1fbbb
nbproject/build-impl.xml.stylesheet.CRC32=487672f9

View File

@ -0,0 +1,2 @@
jaxws.endorsed.dir=/usr/local/netbeans-6.1/java2/modules/ext/jaxws21/api
user.properties.file=/root/.netbeans/6.1/build.properties

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
<file>file:/root/NetBeansProjects/BOB/Demos/echo/echoclient/src/net/i2p/BOB/Demos/echo/echoclient/Main.java</file>
</open-files>
</project-private>

View File

@ -0,0 +1,60 @@
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/echoclient.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
file.reference.BOB.jar=../../../dist/BOB.jar
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.source=1.5
javac.target=1.5
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=net.i2p.BOB.Demos.echo.echoclient.Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>echoclient</name>
<minimum-ant-version>1.6.5</minimum-ant-version>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -0,0 +1,201 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB.Demos.echo.echoclient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author sponge
*/
public class Main {
public static String Lread(InputStream in) throws IOException {
String S;
int b;
char c;
S = new String();
while(true) {
b = in.read();
if(b == 13) {
//skip CR
continue;
}
if(b < 20 || b > 126) {
// exit on anything not legal
break;
}
c = (char)(b & 0x7f); // We only really give a fuck about ASCII
S = new String(S + c);
}
return S;
}
/**
* Check for "ERROR" and if so, throw RuntimeException
* @param line
* @throws java.lang.RuntimeException
*/
static void checkline(String line) throws RuntimeException {
System.out.println(line); // print status
if(line.startsWith("ERROR")) {
throw new RuntimeException(line);
}
}
static void wrtxt(OutputStream CMDout, String s) throws IOException {
CMDout.write(s.getBytes());
CMDout.write('\n');
CMDout.flush();
}
static void setupconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
String line;
Socket CMDsock = new Socket("localhost", 0xB0B);
InputStream CMDin = CMDsock.getInputStream();
OutputStream CMDout = CMDsock.getOutputStream();
// setup the tunnel.
line = Lread(CMDin);
System.out.println(line); // print the banner
line = Lread(CMDin);
System.out.println(line); // print initial status, should always be "OK"
try {
wrtxt(CMDout, "status " + args[2]);
line = Lread(CMDin); // get the status of this nickname, if it's an error, create it
checkline(line);
} catch(RuntimeException rte) {
wrtxt(CMDout, "setnick " + args[2]);
line = Lread(CMDin); // create a new nickname
checkline(line);
wrtxt(CMDout, "newkeys");
line = Lread(CMDin); // set up new keys
checkline(line);
wrtxt(CMDout, "inport " + args[1]);
line = Lread(CMDin); // set the port we connect in on
checkline(line);
}
wrtxt(CMDout, "getnick " + args[2]);
line = Lread(CMDin); // Set to our nick
try {
checkline(line);
} catch(RuntimeException rte) {
System.out.println("Continuing on existing tunnel..");
return;
}
wrtxt(CMDout, "start");
line = Lread(CMDin); // an error here is OK
System.out.println(line); // print status
CMDsock.close(); // we no longer need this particular socket
}
static void deleteconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
String line;
// Wait for things to flush
try {
Thread.sleep(10000);
} catch(InterruptedException ex) {
// nop
}
Socket CMDsock = new Socket("localhost", 0xB0B);
InputStream CMDin = CMDsock.getInputStream();
OutputStream CMDout = CMDsock.getOutputStream();
// delete the tunnel.
line = Lread(CMDin);
System.out.println(line); // print the banner
line = Lread(CMDin);
System.out.println(line); // print initial status, should always be "OK"
wrtxt(CMDout, "getnick " + args[2]); // Set to our nick
line = Lread(CMDin);
checkline(line);
wrtxt(CMDout, "stop");
line = Lread(CMDin);
checkline(line);
try {
Thread.sleep(2000); //sleep for 2000 ms (Two seconds)
} catch(Exception e) {
// nop
}
wrtxt(CMDout, "clear");
line = Lread(CMDin);
while(line.startsWith("ERROR")) {
wrtxt(CMDout, "clear");
line = Lread(CMDin);
}
System.out.println(line); // print status
CMDsock.close(); // we no longer need this particular socket
}
static void chatter(String[] args) throws UnknownHostException, IOException, RuntimeException {
String line;
Socket sock = new Socket("localhost", Integer.parseInt(args[1]));
InputStream in = sock.getInputStream();
OutputStreamWriter out = new OutputStreamWriter(sock.getOutputStream());
out.write(args[3] + "\n"); // send out the i2p address to connect to
out.flush();
System.out.println("Connecting to " + args[3]);
line = Lread(in); // get server greeting
System.out.println("Got " + line); // show user
out.write("Test complete.\n"); // send something back
out.flush(); // make sure it's sent.
sock.close(); // done.
}
/**
*
* @param args tunnelport tunnelnickname I2Pdestkey
*/
public static void main(String[] args) {
// I'm lazy, and want to exit on any failures.
try {
setupconn(args); // talk to BOB, set up an outbound port
chatter(args); // talk over the connection
} catch(UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch(IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
try {
deleteconn(args);
} catch(UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch(IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch(RuntimeException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<project name="echoserver" default="default" basedir=".">
<description>Builds, tests, and runs the project echoserver.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="echoserver-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

View File

@ -0,0 +1,629 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
For the purpose of easier reading the script
is divided into following sections:
- initialization
- compilation
- jar
- execution
- debugging
- javadoc
- junit compilation
- junit execution
- junit debugging
- applet
- cleanup
-->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="echoserver-impl">
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
<!--
======================
INITIALIZATION SECTION
======================
-->
<target name="-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init" name="-init-private">
<property file="nbproject/private/config.properties"/>
<property file="nbproject/private/configs/${config}.properties"/>
<property file="nbproject/private/private.properties"/>
</target>
<target depends="-pre-init,-init-private" name="-init-user">
<property file="${user.properties.file}"/>
<!-- The two properties below are usually overridden -->
<!-- by the active platform. Just a fallback. -->
<property name="default.javac.source" value="1.4"/>
<property name="default.javac.target" value="1.4"/>
</target>
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
<property file="nbproject/configs/${config}.properties"/>
<property file="nbproject/project.properties"/>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
<available file="${manifest.file}" property="manifest.available"/>
<condition property="manifest.available+main.class">
<and>
<isset property="manifest.available"/>
<isset property="main.class"/>
<not>
<equals arg1="${main.class}" arg2="" trim="true"/>
</not>
</and>
</condition>
<condition property="manifest.available+main.class+mkdist.available">
<and>
<istrue value="${manifest.available+main.class}"/>
<isset property="libs.CopyLibs.classpath"/>
</and>
</condition>
<condition property="have.tests">
<or>
<available file="${test.src.dir}"/>
</or>
</condition>
<condition property="have.sources">
<or>
<available file="${src.dir}"/>
</or>
</condition>
<condition property="netbeans.home+have.tests">
<and>
<isset property="netbeans.home"/>
<isset property="have.tests"/>
</and>
</condition>
<condition property="no.javadoc.preview">
<and>
<isset property="javadoc.preview"/>
<isfalse value="${javadoc.preview}"/>
</and>
</condition>
<property name="run.jvmargs" value=""/>
<property name="javac.compilerargs" value=""/>
<property name="work.dir" value="${basedir}"/>
<condition property="no.deps">
<and>
<istrue value="${no.dependencies}"/>
</and>
</condition>
<property name="javac.debug" value="true"/>
<property name="javadoc.preview" value="true"/>
<property name="application.args" value=""/>
<property name="source.encoding" value="${file.encoding}"/>
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
<and>
<isset property="javadoc.encoding"/>
<not>
<equals arg1="${javadoc.encoding}" arg2=""/>
</not>
</and>
</condition>
<property name="javadoc.encoding.used" value="${source.encoding}"/>
<property name="includes" value="**"/>
<property name="excludes" value=""/>
<property name="do.depend" value="false"/>
<condition property="do.depend.true">
<istrue value="${do.depend}"/>
</condition>
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
<and>
<isset property="jaxws.endorsed.dir"/>
<available file="nbproject/jaxws-build.xml"/>
</and>
</condition>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
<fail unless="src.dir">Must set src.dir</fail>
<fail unless="test.src.dir">Must set test.src.dir</fail>
<fail unless="build.dir">Must set build.dir</fail>
<fail unless="dist.dir">Must set dist.dir</fail>
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
<fail unless="dist.jar">Must set dist.jar</fail>
</target>
<target name="-init-macrodef-property">
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-javac">
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="${javac.debug}" name="debug"/>
<attribute default="" name="sourcepath"/>
<element name="customize" optional="true"/>
<sequential>
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
<classpath>
<path path="@{classpath}"/>
</classpath>
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
<customize/>
</javac>
</sequential>
</macrodef>
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<sequential>
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</depend>
</sequential>
</macrodef>
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${build.classes.dir}" name="destdir"/>
<sequential>
<fail unless="javac.includes">Must set javac.includes</fail>
<pathconvert pathsep="," property="javac.includes.binary">
<path>
<filelist dir="@{destdir}" files="${javac.includes}"/>
</path>
<globmapper from="*.java" to="*.class"/>
</pathconvert>
<delete>
<files includes="${javac.includes.binary}"/>
</delete>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-junit">
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="**" name="testincludes"/>
<sequential>
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
<batchtest todir="${build.test.results.dir}">
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
</batchtest>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
<jvmarg line="${run.jvmargs}"/>
</junit>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-nbjpda">
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="name"/>
<attribute default="${debug.classpath}" name="classpath"/>
<attribute default="" name="stopclassname"/>
<sequential>
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="dt_socket">
<classpath>
<path path="@{classpath}"/>
</classpath>
</nbjpdastart>
</sequential>
</macrodef>
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${build.classes.dir}" name="dir"/>
<sequential>
<nbjpdareload>
<fileset dir="@{dir}" includes="${fix.classes}">
<include name="${fix.includes}*.class"/>
</fileset>
</nbjpdareload>
</sequential>
</macrodef>
</target>
<target name="-init-debug-args">
<property name="version-output" value="java version &quot;${ant.java.version}"/>
<condition property="have-jdk-older-than-1.4">
<or>
<contains string="${version-output}" substring="java version &quot;1.0"/>
<contains string="${version-output}" substring="java version &quot;1.1"/>
<contains string="${version-output}" substring="java version &quot;1.2"/>
<contains string="${version-output}" substring="java version &quot;1.3"/>
</or>
</condition>
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
<istrue value="${have-jdk-older-than-1.4}"/>
</condition>
</target>
<target depends="-init-debug-args" name="-init-macrodef-debug">
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${main.class}" name="classname"/>
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="@{classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-java">
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="classname"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="${run.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}"/>
</jar>
</presetdef>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
<!--
===================
COMPILATION SECTION
===================
-->
<target depends="init" name="deps-jar" unless="no.deps"/>
<target depends="init,deps-jar" name="-pre-pre-compile">
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="-pre-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-depend">
<j2seproject3:depend/>
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
<j2seproject3:javac/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
<target name="-pre-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile/>
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
</target>
<target name="-post-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
<!--
====================
JAR BUILDING SECTION
====================
-->
<target depends="init" name="-pre-pre-jar">
<dirname file="${dist.jar}" property="dist.jar.dir"/>
<mkdir dir="${dist.jar.dir}"/>
</target>
<target name="-pre-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
<j2seproject1:jar/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
<j2seproject1:jar manifest="${manifest.file}"/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
<j2seproject1:jar manifest="${manifest.file}">
<j2seproject1:manifest>
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
</j2seproject1:manifest>
</j2seproject1:jar>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<pathconvert property="run.classpath.with.dist.jar">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
</pathconvert>
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target name="-post-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
<!--
=================
EXECUTION SECTION
=================
-->
<target depends="init,compile" description="Run a main class." name="run">
<j2seproject1:java>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject1:java>
</target>
<target name="-do-not-recompile">
<property name="javac.includes.binary" value=""/>
</target>
<target depends="init,-do-not-recompile,compile-single" name="run-single">
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
<j2seproject1:java classname="${run.class}"/>
</target>
<!--
=================
DEBUGGING SECTION
=================
-->
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
<j2seproject1:nbjpdastart name="${debug.class}"/>
</target>
<target depends="init,compile" name="-debug-start-debuggee">
<j2seproject3:debug>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
</target>
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
<j2seproject3:debug classname="${debug.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
<target depends="init" name="-pre-debug-fix">
<fail unless="fix.includes">Must set fix.includes</fail>
<property name="javac.includes" value="${fix.includes}.java"/>
</target>
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
<j2seproject1:nbjpdareload/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
<!--
===============
JAVADOC SECTION
===============
-->
<target depends="init" name="-javadoc-build">
<mkdir dir="${dist.javadoc.dir}"/>
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
<classpath>
<path path="${javac.classpath}"/>
</classpath>
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
<filename name="**/*.java"/>
</fileset>
</javadoc>
</target>
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
</target>
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
<!--
=========================
JUNIT COMPILATION SECTION
=========================
-->
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
<mkdir dir="${build.test.classes.dir}"/>
</target>
<target name="-pre-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-test-depend">
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
<target name="-pre-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
<!--
=======================
JUNIT EXECUTION SECTION
=======================
-->
<target depends="init" if="have.tests" name="-pre-test-run">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
<j2seproject3:junit testincludes="**/*Test.java"/>
</target>
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init" if="have.tests" name="test-report"/>
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
<target depends="init" if="have.tests" name="-pre-test-run-single">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
<j2seproject3:junit excludes="" includes="${test.includes}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
<!--
=======================
JUNIT DEBUGGING SECTION
=======================
-->
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
<delete file="${test.report.file}"/>
<mkdir dir="${build.test.results.dir}"/>
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
<customize>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<arg value="${test.class}"/>
<arg value="showoutput=true"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
<!--
=========================
APPLET EXECUTION SECTION
=========================
-->
<target depends="init,compile-single" name="run-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject1:java classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject1:java>
</target>
<!--
=========================
APPLET DEBUGGING SECTION
=========================
-->
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject3:debug classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
<!--
===============
CLEANUP SECTION
===============
-->
<target depends="init" name="deps-clean" unless="no.deps"/>
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
</target>
<target name="-post-clean">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
</project>

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=4ce39738
build.xml.script.CRC32=c1deb82c
build.xml.stylesheet.CRC32=be360661
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=4ce39738
nbproject/build-impl.xml.script.CRC32=555cdd2d
nbproject/build-impl.xml.stylesheet.CRC32=487672f9

View File

@ -0,0 +1,2 @@
jaxws.endorsed.dir=/usr/local/netbeans-6.1/java2/modules/ext/jaxws21/api
user.properties.file=/root/.netbeans/6.1/build.properties

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
<file>file:/root/NetBeansProjects/BOB/Demos/echo/echoserver/src/net/i2p/BOB/Demos/echo/echoserver/Main.java</file>
</open-files>
</project-private>

View File

@ -0,0 +1,60 @@
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/echoserver.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
file.reference.BOB.jar=../../../dist/BOB.jar
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.source=1.5
javac.target=1.5
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=net.i2p.BOB.Demos.echo.echoserver.Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>echoserver</name>
<minimum-ant-version>1.6.5</minimum-ant-version>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -0,0 +1,4 @@
(
cd dist
java -jar echoserver.jar main 37337 testserver
)

View File

@ -0,0 +1,197 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB.Demos.echo.echoserver;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author sponge
*/
public class Main {
public static String Lread(InputStream in) throws IOException {
String S;
int b;
char c;
S = new String();
while(true) {
b = in.read();
if(b < 20) {
break;
}
c = (char)(b & 0x7f); // We only really give a fuck about ASCII
S = new String(S + c);
}
return S;
}
/**
* Check for "ERROR" and if so, throw RuntimeException
* @param line
* @throws java.lang.RuntimeException
*/
static void checkline(String line) throws RuntimeException {
System.out.println(line); // print status
if(line.startsWith("ERROR")) {
throw new RuntimeException(line);
}
}
static void wrtxt(OutputStream CMDout, String s) throws IOException {
CMDout.write(s.getBytes());
CMDout.write('\n');
CMDout.flush();
}
static void setupconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
String line;
Socket CMDsock = new Socket("localhost", 0xB0B);
InputStream CMDin = CMDsock.getInputStream();
OutputStream CMDout = CMDsock.getOutputStream();
// setup the tunnel.
line = Lread(CMDin);
System.out.println(line); // print the banner
line = Lread(CMDin);
System.out.println(line); // print initial status, should always be "OK"
try {
wrtxt(CMDout, "status " + args[2]);
line =Lread(CMDin); // get the status of this nickname, if it's an error, create it
checkline(line);
} catch(RuntimeException rte) {
wrtxt(CMDout, "setnick " + args[2]);
line =Lread(CMDin); // create a new nickname
checkline(line);
wrtxt(CMDout, "newkeys ");
line =Lread(CMDin); // set up new keys
checkline(line);
wrtxt(CMDout, "outport " + args[1]);
line = Lread(CMDin); // set the port we connect out on
checkline(line);
}
wrtxt(CMDout, "getnick " + args[2]);
line = Lread(CMDin); // Set to our nick
checkline(line);
wrtxt(CMDout, "start ");
line = Lread(CMDin); // an error here is OK
System.out.println(line); // print status
CMDsock.close(); // we no longer need this particular socket
}
static void deleteconn(String[] args) throws UnknownHostException, IOException, RuntimeException {
String line;
Socket CMDsock = new Socket("localhost", 0xB0B);
InputStream CMDin = CMDsock.getInputStream();
OutputStream CMDout = CMDsock.getOutputStream();
// delete the tunnel.
line = Lread(CMDin);
System.out.println(line); // print the banner
line = Lread(CMDin);
System.out.println(line); // print initial status, should always be "OK"
wrtxt(CMDout, "getnick " + args[2]); // Set to our nick
line = Lread(CMDin);
checkline(line);
wrtxt(CMDout, "stop");
line = Lread(CMDin);
checkline(line);
try {
Thread.sleep(2000); //sleep for 2000 ms (Two seconds)
} catch(Exception e) {
// nop
}
wrtxt(CMDout, "clear");
line = Lread(CMDin);
while(line.startsWith("ERROR")) {
wrtxt(CMDout, "clear");
line = Lread(CMDin);
}
System.out.println(line); // print status
CMDsock.close(); // we no longer need this particular socket
}
static void chatter(Socket sock) throws UnknownHostException, IOException, RuntimeException {
String line;
InputStream in = sock.getInputStream();
OutputStreamWriter out = new OutputStreamWriter(new BufferedOutputStream(sock.getOutputStream()));
line = Lread(in); // get remote I2P address
System.out.println("Connect from: " + line); // show user
out.write("Hello, You are connecting from " + line + "\n"); // send greeting
out.flush(); // make sure it's sent.
line = Lread(in); // get test text from client
System.out.println("Got "+line); // show user
sock.close(); // done.
}
private static void serverlistener(String[] args) throws UnknownHostException, IOException, RuntimeException {
ServerSocket listener = new ServerSocket(Integer.parseInt(args[1]), 10, InetAddress.getByName("localhost"));
Socket server;
while(true) {
server = listener.accept();
chatter(server);
}
}
/**
*
* @param args tunnelport tunnelnickname
*/
public static void main(String[] args) {
// I'm lazy, and want to exit on any failures.
try {
setupconn(args); // talk to BOB, set up an inbound port
serverlistener(args); // talk over the connection
} catch(UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch(IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
try {
deleteconn(args);
} catch(UnknownHostException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch(IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch(RuntimeException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

14
apps/BOB/bob.config Normal file
View File

@ -0,0 +1,14 @@
#bob.config
#Tue Dec 30 00:00:00 UTC 2008
# Please leave this file here for testing.
# Thank you,
# Sponge
i2cp.tcp.port=7654
BOB.host=localhost
inbound.lengthVariance=0
i2cp.messageReliability=BestEffort
BOB.port=45067
outbound.length=1
inbound.length=1
outbound.lengthVariance=0
i2cp.tcp.host=localhost

74
apps/BOB/build.xml Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="BOB" default="default" basedir=".">
<description>Builds, tests, and runs the project BOB.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="BOB-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

3
apps/BOB/manifest.mf Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

View File

@ -0,0 +1,642 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
*** GENERATED FROM project.xml - DO NOT EDIT ***
*** EDIT ../build.xml INSTEAD ***
For the purpose of easier reading the script
is divided into following sections:
- initialization
- compilation
- jar
- execution
- debugging
- javadoc
- junit compilation
- junit execution
- junit debugging
- applet
- cleanup
-->
<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="BOB-impl">
<target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
<!--
======================
INITIALIZATION SECTION
======================
-->
<target name="-pre-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init" name="-init-private">
<property file="nbproject/private/config.properties"/>
<property file="nbproject/private/configs/${config}.properties"/>
<property file="nbproject/private/private.properties"/>
</target>
<target depends="-pre-init,-init-private" name="-init-user">
<property file="${user.properties.file}"/>
<!-- The two properties below are usually overridden -->
<!-- by the active platform. Just a fallback. -->
<property name="default.javac.source" value="1.4"/>
<property name="default.javac.target" value="1.4"/>
</target>
<target depends="-pre-init,-init-private,-init-user" name="-init-project">
<property file="nbproject/configs/${config}.properties"/>
<property file="nbproject/project.properties"/>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
<available file="${manifest.file}" property="manifest.available"/>
<condition property="manifest.available+main.class">
<and>
<isset property="manifest.available"/>
<isset property="main.class"/>
<not>
<equals arg1="${main.class}" arg2="" trim="true"/>
</not>
</and>
</condition>
<condition property="manifest.available+main.class+mkdist.available">
<and>
<istrue value="${manifest.available+main.class}"/>
<isset property="libs.CopyLibs.classpath"/>
</and>
</condition>
<condition property="have.tests">
<or>
<available file="${test.src.dir}"/>
</or>
</condition>
<condition property="have.sources">
<or>
<available file="${src.dir}"/>
</or>
</condition>
<condition property="netbeans.home+have.tests">
<and>
<isset property="netbeans.home"/>
<isset property="have.tests"/>
</and>
</condition>
<condition property="no.javadoc.preview">
<and>
<isset property="javadoc.preview"/>
<isfalse value="${javadoc.preview}"/>
</and>
</condition>
<property name="run.jvmargs" value=""/>
<property name="javac.compilerargs" value=""/>
<property name="work.dir" value="${basedir}"/>
<condition property="no.deps">
<and>
<istrue value="${no.dependencies}"/>
</and>
</condition>
<property name="javac.debug" value="true"/>
<property name="javadoc.preview" value="true"/>
<property name="application.args" value=""/>
<property name="source.encoding" value="${file.encoding}"/>
<condition property="javadoc.encoding.used" value="${javadoc.encoding}">
<and>
<isset property="javadoc.encoding"/>
<not>
<equals arg1="${javadoc.encoding}" arg2=""/>
</not>
</and>
</condition>
<property name="javadoc.encoding.used" value="${source.encoding}"/>
<property name="includes" value="**"/>
<property name="excludes" value=""/>
<property name="do.depend" value="false"/>
<condition property="do.depend.true">
<istrue value="${do.depend}"/>
</condition>
<condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
<and>
<isset property="jaxws.endorsed.dir"/>
<available file="nbproject/jaxws-build.xml"/>
</and>
</condition>
</target>
<target name="-post-init">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
<fail unless="src.dir">Must set src.dir</fail>
<fail unless="test.src.dir">Must set test.src.dir</fail>
<fail unless="build.dir">Must set build.dir</fail>
<fail unless="dist.dir">Must set dist.dir</fail>
<fail unless="build.classes.dir">Must set build.classes.dir</fail>
<fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
<fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
<fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
<fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
<fail unless="dist.jar">Must set dist.jar</fail>
</target>
<target name="-init-macrodef-property">
<macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-javac">
<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="${javac.debug}" name="debug"/>
<attribute default="" name="sourcepath"/>
<element name="customize" optional="true"/>
<sequential>
<javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
<classpath>
<path path="@{classpath}"/>
</classpath>
<compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
<customize/>
</javac>
</sequential>
</macrodef>
<macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${src.dir}" name="srcdir"/>
<attribute default="${build.classes.dir}" name="destdir"/>
<attribute default="${javac.classpath}" name="classpath"/>
<sequential>
<depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</depend>
</sequential>
</macrodef>
<macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${build.classes.dir}" name="destdir"/>
<sequential>
<fail unless="javac.includes">Must set javac.includes</fail>
<pathconvert pathsep="," property="javac.includes.binary">
<path>
<filelist dir="@{destdir}" files="${javac.includes}"/>
</path>
<globmapper from="*.java" to="*.class"/>
</pathconvert>
<delete>
<files includes="${javac.includes.binary}"/>
</delete>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-junit">
<macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${includes}" name="includes"/>
<attribute default="${excludes}" name="excludes"/>
<attribute default="**" name="testincludes"/>
<sequential>
<junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
<batchtest todir="${build.test.results.dir}">
<fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
<filename name="@{testincludes}"/>
</fileset>
</batchtest>
<classpath>
<path path="${run.test.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<formatter type="brief" usefile="false"/>
<formatter type="xml"/>
<jvmarg line="${run.jvmargs}"/>
</junit>
</sequential>
</macrodef>
</target>
<target depends="-init-debug-args" name="-init-macrodef-nbjpda">
<macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="name"/>
<attribute default="${debug.classpath}" name="classpath"/>
<attribute default="" name="stopclassname"/>
<sequential>
<nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
<classpath>
<path path="@{classpath}"/>
</classpath>
</nbjpdastart>
</sequential>
</macrodef>
<macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${build.classes.dir}" name="dir"/>
<sequential>
<nbjpdareload>
<fileset dir="@{dir}" includes="${fix.classes}">
<include name="${fix.includes}*.class"/>
</fileset>
</nbjpdareload>
</sequential>
</macrodef>
</target>
<target name="-init-debug-args">
<property name="version-output" value="java version &quot;${ant.java.version}"/>
<condition property="have-jdk-older-than-1.4">
<or>
<contains string="${version-output}" substring="java version &quot;1.0"/>
<contains string="${version-output}" substring="java version &quot;1.1"/>
<contains string="${version-output}" substring="java version &quot;1.2"/>
<contains string="${version-output}" substring="java version &quot;1.3"/>
</or>
</condition>
<condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
<istrue value="${have-jdk-older-than-1.4}"/>
</condition>
<condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
<os family="windows"/>
</condition>
<condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
<isset property="debug.transport"/>
</condition>
</target>
<target depends="-init-debug-args" name="-init-macrodef-debug">
<macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
<attribute default="${main.class}" name="classname"/>
<attribute default="${debug.classpath}" name="classpath"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${debug-args-line}"/>
<jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="@{classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-macrodef-java">
<macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
<attribute default="${main.class}" name="classname"/>
<element name="customize" optional="true"/>
<sequential>
<java classname="@{classname}" dir="${work.dir}" fork="true">
<jvmarg line="${run.jvmargs}"/>
<classpath>
<path path="${run.classpath}"/>
</classpath>
<syspropertyset>
<propertyref prefix="run-sys-prop."/>
<mapper from="run-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<customize/>
</java>
</sequential>
</macrodef>
</target>
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}"/>
</jar>
</presetdef>
</target>
<target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
<!--
===================
COMPILATION SECTION
===================
-->
<target depends="init" name="deps-jar" unless="no.deps"/>
<target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
<target depends="init" name="-check-automatic-build">
<available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
</target>
<target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
<antcall target="clean"/>
</target>
<target depends="init,deps-jar" name="-pre-pre-compile">
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="-pre-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-depend">
<j2seproject3:depend/>
</target>
<target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
<j2seproject3:javac/>
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
<target name="-pre-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile/>
<j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
</target>
<target name="-post-compile-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
<!--
====================
JAR BUILDING SECTION
====================
-->
<target depends="init" name="-pre-pre-jar">
<dirname file="${dist.jar}" property="dist.jar.dir"/>
<mkdir dir="${dist.jar.dir}"/>
</target>
<target name="-pre-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
<j2seproject1:jar/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
<j2seproject1:jar manifest="${manifest.file}"/>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
<j2seproject1:jar manifest="${manifest.file}">
<j2seproject1:manifest>
<j2seproject1:attribute name="Main-Class" value="${main.class}"/>
</j2seproject1:manifest>
</j2seproject1:jar>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<pathconvert property="run.classpath.with.dist.jar">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
</pathconvert>
<echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
</target>
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
<target name="-post-jar">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
<!--
=================
EXECUTION SECTION
=================
-->
<target depends="init,compile" description="Run a main class." name="run">
<j2seproject1:java>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject1:java>
</target>
<target name="-do-not-recompile">
<property name="javac.includes.binary" value=""/>
</target>
<target depends="init,-do-not-recompile,compile-single" name="run-single">
<fail unless="run.class">Must select one file in the IDE or set run.class</fail>
<j2seproject1:java classname="${run.class}"/>
</target>
<!--
=================
DEBUGGING SECTION
=================
-->
<target depends="init" if="netbeans.home" name="-debug-start-debugger">
<j2seproject1:nbjpdastart name="${debug.class}"/>
</target>
<target depends="init,compile" name="-debug-start-debuggee">
<j2seproject3:debug>
<customize>
<arg line="${application.args}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
<target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
<j2seproject1:nbjpdastart stopclassname="${main.class}"/>
</target>
<target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
<fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
<j2seproject3:debug classname="${debug.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
<target depends="init" name="-pre-debug-fix">
<fail unless="fix.includes">Must set fix.includes</fail>
<property name="javac.includes" value="${fix.includes}.java"/>
</target>
<target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
<j2seproject1:nbjpdareload/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
<!--
===============
JAVADOC SECTION
===============
-->
<target depends="init" name="-javadoc-build">
<mkdir dir="${dist.javadoc.dir}"/>
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
<classpath>
<path path="${javac.classpath}"/>
</classpath>
<fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
<filename name="**/*.java"/>
</fileset>
</javadoc>
</target>
<target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
<nbbrowse file="${dist.javadoc.dir}/index.html"/>
</target>
<target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
<!--
=========================
JUNIT COMPILATION SECTION
=========================
-->
<target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
<mkdir dir="${build.test.classes.dir}"/>
</target>
<target name="-pre-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target if="do.depend.true" name="-compile-test-depend">
<j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
<target name="-pre-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
<fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
<j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
<j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
<copy todir="${build.test.classes.dir}">
<fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
</copy>
</target>
<target name="-post-compile-test-single">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
<!--
=======================
JUNIT EXECUTION SECTION
=======================
-->
<target depends="init" if="have.tests" name="-pre-test-run">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
<j2seproject3:junit testincludes="**/*Test.java"/>
</target>
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init" if="have.tests" name="test-report"/>
<target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
<target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
<target depends="init" if="have.tests" name="-pre-test-run-single">
<mkdir dir="${build.test.results.dir}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
<fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
<j2seproject3:junit excludes="" includes="${test.includes}"/>
</target>
<target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
<fail if="tests.failed">Some tests failed; see details above.</fail>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
<!--
=======================
JUNIT DEBUGGING SECTION
=======================
-->
<target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
<fail unless="test.class">Must select one file in the IDE or set test.class</fail>
<property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
<delete file="${test.report.file}"/>
<mkdir dir="${build.test.results.dir}"/>
<j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
<customize>
<syspropertyset>
<propertyref prefix="test-sys-prop."/>
<mapper from="test-sys-prop.*" to="*" type="glob"/>
</syspropertyset>
<arg value="${test.class}"/>
<arg value="showoutput=true"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
<arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
<j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
</target>
<target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
<target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
<j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
</target>
<target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
<!--
=========================
APPLET EXECUTION SECTION
=========================
-->
<target depends="init,compile-single" name="run-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject1:java classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject1:java>
</target>
<!--
=========================
APPLET DEBUGGING SECTION
=========================
-->
<target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
<fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
<j2seproject3:debug classname="sun.applet.AppletViewer">
<customize>
<arg value="${applet.url}"/>
</customize>
</j2seproject3:debug>
</target>
<target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
<!--
===============
CLEANUP SECTION
===============
-->
<target depends="init" name="deps-clean" unless="no.deps"/>
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
</target>
<target name="-post-clean">
<!-- Empty placeholder for easier customization. -->
<!-- You can override this target in the ../build.xml file. -->
</target>
<target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
</project>

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=209349b6
build.xml.script.CRC32=403e69e6
build.xml.stylesheet.CRC32=958a1d3e
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=209349b6
nbproject/build-impl.xml.script.CRC32=75fac64c
nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5

View File

@ -0,0 +1,7 @@
compile.on.save=false
do.depend=false
do.jar=true
javac.debug=true
javadoc.preview=true
jaxws.endorsed.dir=/usr/local/netbeans-6.5/java2/modules/ext/jaxws21/api:/usr/local/netbeans-6.5/ide10/modules/ext/jaxb/api
user.properties.file=/root/.netbeans/6.5/build.properties

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
</project-private>

View File

@ -0,0 +1,107 @@
application.title=BOB
application.vendor=root
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/BOB.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
file.reference.core.jar=../i2p.i2p/core/dist/core.jar
file.reference.i2p.jar=../../bob/i2p/i2p.i2p/build/i2p.jar
file.reference.i2p.jar-1=../../core/java/build/i2p.jar
file.reference.i2p.jar-2=../i2p.i2p/core/java/build/i2p.jar
file.reference.i2ptunnel.jar=../i2ptunnel/java/build/i2ptunnel.jar
file.reference.java-src=../i2p.i2p/core/java/src/
file.reference.jbigi.jar=../../bob/i2p/i2p.i2p/build/jbigi.jar
file.reference.mstreaming.jar=../../bob/i2p/i2p.i2p/build/mstreaming.jar
file.reference.mstreaming.jar-1=../ministreaming/java/build/mstreaming.jar
file.reference.NetBeansProjects-i2p.i2p=../i2p.i2p/
file.reference.streaming.jar=../../bob/i2p/i2p.i2p/build/streaming.jar
file.reference.streaming.jar-1=../streaming/java/build/streaming.jar
file.reference.wrapper-freebsd=../../installer/lib/wrapper/freebsd/
file.reference.wrapper-linux=../../installer/lib/wrapper/linux/
file.reference.wrapper-linux64=../../installer/lib/wrapper/linux64/
file.reference.wrapper-macosx=../../installer/lib/wrapper/macosx/
file.reference.wrapper-solaris=../../installer/lib/wrapper/solaris/
file.reference.wrapper-win32=../../installer/lib/wrapper/win32/
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
file.reference.wrapper.jar-1=../../installer/lib/wrapper/freebsd/wrapper.jar
file.reference.wrapper.jar-2=../../installer/lib/wrapper/linux64/wrapper.jar
file.reference.wrapper.jar-3=../../installer/lib/wrapper/macosx/wrapper.jar
file.reference.wrapper.jar-4=../../installer/lib/wrapper/solaris/wrapper.jar
file.reference.wrapper.jar-5=../../installer/lib/wrapper/win32/wrapper.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.i2p.jar-1}:\
${file.reference.i2ptunnel.jar}:\
${file.reference.mstreaming.jar-1}:\
${file.reference.streaming.jar-1}:\
${file.reference.wrapper.jar-1}:\
${file.reference.wrapper.jar}:\
${file.reference.wrapper.jar-2}:\
${file.reference.wrapper.jar-3}:\
${file.reference.wrapper.jar-4}:\
${file.reference.wrapper.jar-5}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.source=1.5
javac.target=1.5
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
jnlp.codebase.type=local
jnlp.codebase.url=file:/root/NetBeansProjects/i2p.i2p/apps/BOB/dist/
jnlp.descriptor=application
jnlp.enabled=false
jnlp.offline-allowed=false
jnlp.signed=false
main.class=net.i2p.BOB.Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>BOB</name>
<minimum-ant-version>1.6.5</minimum-ant-version>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@ -0,0 +1,238 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import net.i2p.client.I2PClient;
import net.i2p.client.streaming.RetransmissionTimer;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer;
/**
* <span style="font-size:8px;font-family:courier;color:#EEEEEE;background-color:#000000">
* ################################################################################<br>
* ############################.#..........#..#..........##########################<br>
* #######################......................................###################<br>
* ####################...........................#.......#........################<br>
* #################..................##...................#.........##############<br>
* ###############................###...####.....#..###.....#.........#############<br>
* #############...........###..#..###...#####...###.##........#.......############<br>
* ###########................#......##...#####...##..##.......#..#........########<br>
* ##########.........................#....##.##..#...##.....................######<br>
* #########...................................#....#.........................#####<br>
* ########.........................................#...............#..........####<br>
* ########.........................................#..........#######..........###<br>
* #######.................................................############..........##<br>
* #######..........................................####################.........##<br>
* #######............####################......########################.........##<br>
* ######.............###############################################.##.........##<br>
* ######............################################################..##........##<br>
* ######............################################################..##........##<br>
* ######.............##############################################..##.........##<br>
* ######............##############################################...##..........#<br>
* ######............#..###########################################...##..........#<br>
* ######.............#############################################....#..........#<br>
* #######...........###############################################..##.........##<br>
* #######...........#####.#.#.#.########################.....#.####...##........##<br>
* ######............#..............##################.................##.........#<br>
* ######................####.........###############........#####......##........#<br>
* ######..............####..#.........############.......##.#.######...##.......##<br>
* ######.................#.####.........########...........##....###...##.......##<br>
* #######....#....###...................#######...............#...###..##.......##<br>
* #######.........###..###.....###.......######.##.#####.........####..##.......##<br>
* #######.....#...##############.........############......###########.###......##<br>
* #######....##...##########.......##...##############......#.############.....###<br>
* ########....#..########......######...##################################....####<br>
* ########....##.####################...##################################....####<br>
* ########..#.##..###################..##################################..#..####<br>
* ##########..###..#################...##################################...#.####<br>
* #########....##...##############....########..#####.################.##..#.#####<br>
* ############.##....##########.......#########.###.......###########..#.#########<br>
* ###############.....#######...#.......########.....##.....######.....###########<br>
* ###############......###....##..........##.......######....#.........#.#########<br>
* ##############............##..................##########..............##########<br>
* ##############..............................##########..#.............##########<br>
* ###############.......##..................#####..............####....###########<br>
* ###############.......#####.......#.............####.....#######.....###########<br>
* ################...#...####......##################.....########....############<br>
* ################...##..#####.........####.##.....#....##########....############<br>
* ##################..##..####...........#####.#....############.....#############<br>
* ##################......#####.................################....##############<br>
* ###################.....####..........##########..###########....###############<br>
* ####################..#..#..........................########.....###############<br>
* #####################.##.......###.................########....#################<br>
* ######################.........#.......#.##.###############....#################<br>
* #############.#######...............#####################....###################<br>
* ###..#.....##...####..........#.....####################....####################<br>
* ####......##........................##################....######################<br>
* #.##...###..............###.........###############......#######################<br>
* #...###..##............######...........................########################<br>
* ##.......###..........##########....#...#...........############################<br>
* ##.........##.......############################################################<br>
* ###........##.....##############################################################<br>
* ####.............###############################################################<br>
* ######.........#################################################################<br>
* #########....###################################################################<br>
* ################################################################################<br>
* </span>
* BOB, main command socket listener, launches the command parser engine.
*
* @author sponge
*/
public class BOB {
private final static Log _log = new Log(BOB.class);
public final static String PROP_CONFIG_LOCATION = "BOB.config";
public final static String PROP_BOB_PORT = "BOB.port";
public final static String PROP_BOB_HOST = "BOB.host";
private static int maxConnections = 0;
private static NamedDB database;
private static Properties props = new Properties();
/**
* Log a warning
*
* @param arg
*/
public static void info(String arg) {
System.out.println("INFO:" + arg);
_log.info(arg);
}
/**
* Log a warning
*
* @param arg
*/
public static void warn(String arg) {
System.out.println("WARNING:" + arg);
_log.warn(arg);
}
/**
* Log an error
*
* @param arg
*/
public static void error(String arg) {
System.out.println("ERROR: " + arg);
_log.error(arg);
}
/**
* Listen for incoming connections and handle them
*
* @param args
*/
public static void main(String[] args) {
database = new NamedDB();
int i = 0;
boolean save = false;
// Set up all defaults to be passed forward to other threads.
// Re-reading the config file in each thread is pretty damn stupid.
// I2PClient client = I2PClientFactory.createClient();
String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config");
// This is here just to ensure there is no interference with our threadgroups.
SimpleTimer Y = RetransmissionTimer.getInstance();
i = Y.hashCode();
{
try {
FileInputStream fi = new FileInputStream(configLocation);
props.load(fi);
fi.close();
} catch(FileNotFoundException fnfe) {
warn("Unable to load up the BOB config file " + configLocation + ", Using defaults.");
warn(fnfe.toString());
save = true;
} catch(IOException ioe) {
warn("IOException on BOB config file " + configLocation + ", using defaults.");
warn(ioe.toString());
}
}
// Global router and client API configurations that are missing are set to defaults here.
if(!props.containsKey(I2PClient.PROP_TCP_HOST)) {
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
}
if(!props.containsKey(I2PClient.PROP_TCP_PORT)) {
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
}
if(!props.containsKey(I2PClient.PROP_RELIABILITY)) {
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
}
if(!props.containsKey(PROP_BOB_PORT)) {
props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
}
if(!props.containsKey("inbound.length")) {
props.setProperty("inbound.length", "1");
}
if(!props.containsKey("outbound.length")) {
props.setProperty("outbound.length", "1");
}
if(!props.containsKey("inbound.lengthVariance")) {
props.setProperty("inbound.lengthVariance", "0");
}
if(!props.containsKey("outbound.lengthVariance")) {
props.setProperty("outbound.lengthVariance", "0");
}
if(!props.containsKey(PROP_BOB_HOST)) {
props.setProperty(PROP_BOB_HOST, "localhost");
}
if(save) {
try {
warn("Writing new defaults file " + configLocation);
FileOutputStream fo = new FileOutputStream(configLocation);
props.store(fo, configLocation);
fo.close();
} catch(IOException ioe) {
error("IOException on BOB config file " + configLocation + ", " + ioe);
}
}
try {
info("BOB is now running.");
ServerSocket listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)) {
//DoCMDS connection;
server = listener.accept();
DoCMDS conn_c = new DoCMDS(server, props, database, _log);
Thread t = new Thread(conn_c);
t.start();
}
} catch(IOException ioe) {
error("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}

View File

@ -0,0 +1,21 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) sponge
Planet Earth
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
See...
http://sam.zoy.org/wtfpl/
and
http://en.wikipedia.org/wiki/WTFPL
...for any additional details and license questions.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import net.i2p.I2PException;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log;
/**
* Listen on I2P and connect to TCP
*
* @author sponge
*/
public class I2Plistener implements Runnable {
private NamedDB info, database;
private Log _log;
private int tgwatch;
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
/**
* Constructor
* @param S
* @param info
* @param database
* @param _log
*/
I2Plistener(I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
this.database = database;
this.info = info;
this._log = _log;
this.socketManager = S;
serverSocket = this.socketManager.getServerSocket();
tgwatch = 1;
}
/**
* Simply listen on I2P port, and thread connections
*
*/
public void run() {
boolean g = false;
I2PSocket sessSocket = null;
serverSocket.setSoTimeout(100);
database.getReadLock();
info.getReadLock();
if(info.exists("INPORT")) {
tgwatch = 2;
}
info.releaseReadLock();
database.releaseReadLock();
boolean spin = true;
while(spin) {
database.getReadLock();
info.getReadLock();
spin = info.get("RUNNING").equals(Boolean.TRUE);
info.releaseReadLock();
database.releaseReadLock();
try {
try {
sessSocket = serverSocket.accept();
g = true;
} catch(ConnectException ce) {
g = false;
} catch(SocketTimeoutException ste) {
g = false;
}
if(g) {
g = false;
// toss the connection to a new thread.
I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database);
Thread t = new Thread(conn_c, "BOBI2PtoTCP");
t.start();
}
} catch(I2PException e) {
// System.out.println("Exception " + e);
}
}
// System.out.println("I2Plistener: Close");
try {
serverSocket.close();
} catch(I2PException e) {
// nop
}
// need to kill off the socket manager too.
I2PSession session = socketManager.getSession();
if(session != null) {
// System.out.println("I2Plistener: destroySession");
try {
session.destroySession();
} catch(I2PSessionException ex) {
// nop
}
}
// System.out.println("I2Plistener: Waiting for children");
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(Exception e) {
// nop
}
}
// System.out.println("I2Plistener: Done.");
}
}

View File

@ -0,0 +1,144 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import net.i2p.client.streaming.I2PSocket;
/**
* Process I2P->TCP
*
* @author sponge
*/
public class I2PtoTCP implements Runnable {
private I2PSocket I2P;
private NamedDB info, database;
private Socket sock;
/**
* Constructor
*
* @param I2Psock
* @param info
* @param database
*/
I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database) {
this.I2P = I2Psock;
this.info = info;
this.database = database;
}
private void rlock() throws Exception {
database.getReadLock();
info.getReadLock();
}
private void runlock() throws Exception {
database.releaseReadLock();
info.releaseReadLock();
}
/**
* I2P stream to TCP stream thread starter
*
*/
public void run() {
String host;
int port;
boolean tell;
die: {
try {
try {
rlock();
} catch(Exception e) {
break die;
}
try {
host = info.get("OUTHOST").toString();
port = Integer.parseInt(info.get("OUTPORT").toString());
tell = info.get("QUIET").equals(Boolean.FALSE);
} catch(Exception e) {
runlock();
break die;
}
try {
runlock();
} catch(Exception e) {
break die;
}
sock = new Socket(host, port);
// make readers/writers
InputStream in = sock.getInputStream();
OutputStream out = sock.getOutputStream();
InputStream Iin = I2P.getInputStream();
OutputStream Iout = I2P.getOutputStream();
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
if(tell) {
// tell who is connecting
out.write(I2P.getPeerDestination().toBase64().getBytes());
out.write(10); // nl
out.flush(); // not really needed, but...
}
// setup to cross the streams
TCPio conn_c = new TCPio(in, Iout, info, database); // app -> I2P
TCPio conn_a = new TCPio(Iin, out, info, database); // I2P -> app
Thread t = new Thread(conn_c, "TCPioA");
Thread q = new Thread(conn_a, "TCPioB");
// Fire!
t.start();
q.start();
while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
try {
Thread.sleep(10); //sleep for 10 ms
} catch(InterruptedException e) {
// nop
}
}
// System.out.println("I2PtoTCP: Going away...");
} catch(Exception e) {
// System.out.println("I2PtoTCP: Owch! damn!");
break die;
}
} // die
try {
// System.out.println("I2PtoTCP: Close I2P");
I2P.close();
} catch(Exception e) {
tell = false;
}
//System.out.println("I2PtoTCP: Closed I2P");
try {
// System.out.println("I2PtoTCP: Close sock");
sock.close();
} catch(Exception e) {
tell = false;
}
// System.out.println("I2PtoTCP: Done");
}
}

View File

@ -0,0 +1,56 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.util.Enumeration;
import java.util.Properties;
/**
* Sets of "friendly" utilities to make life easier.
* Any "Lifted" code will apear here, and credits given.
* It's better to "Lift" a small chunk of "free" code than add in piles of
* code we don't need, and don't want.
*
* @author sponge
*/
public class Lifted {
/**
* Copy a set of properties from one Property to another.
* Lifted from Apache Derby code svn repository.
* Liscenced as follows:
* http://svn.apache.org/repos/asf/db/derby/code/trunk/LICENSE
*
* @param src_prop Source set of properties to copy from.
* @param dest_prop Dest Properties to copy into.
*
**/
public static void copyProperties(Properties src_prop, Properties dest_prop) {
for (Enumeration propertyNames = src_prop.propertyNames();
propertyNames.hasMoreElements();) {
Object key = propertyNames.nextElement();
dest_prop.put(key, src_prop.get(key));
}
}
}

View File

@ -0,0 +1,276 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.util.Properties;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.util.Log;
import org.tanukisoftware.wrapper.WrapperManager;
/**
*
* Multiplex listeners for TCP and I2P
*
* @author sponge
*/
public class MUXlisten implements Runnable {
private NamedDB database, info;
private Log _log;
private I2PSocketManager socketManager;
private ByteArrayInputStream prikey;
private ThreadGroup tg;
private String N;
private ServerSocket listener;
private int backlog = 50; // should this be more? less?
boolean go_out;
boolean come_in;
/**
* Constructor Will fail if INPORT is occupied.
*
* @param info
* @param database
* @param _log
* @throws net.i2p.I2PException
* @throws java.io.IOException
*/
MUXlisten(NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
int port = 0;
InetAddress host = null;
this.tg = null;
this.database = database;
this.info = info;
this._log = _log;
this.database.getReadLock();
this.info.getReadLock();
N = this.info.get("NICKNAME").toString();
prikey = new ByteArrayInputStream((byte[])info.get("KEYS"));
// Make a new copy so that anything else won't muck with our database.
Properties R = (Properties)info.get("PROPERTIES");
Properties Q = new Properties();
Lifted.copyProperties(R, Q);
this.database.releaseReadLock();
this.info.releaseReadLock();
this.database.getReadLock();
this.info.getReadLock();
this.go_out = info.exists("OUTPORT");
this.come_in = info.exists("INPORT");
if(this.come_in) {
port = Integer.parseInt(info.get("INPORT").toString());
host = InetAddress.getByName(info.get("INHOST").toString());
}
this.database.releaseReadLock();
this.info.releaseReadLock();
socketManager = I2PSocketManagerFactory.createManager(prikey, Q);
if(this.come_in) {
this.listener = new ServerSocket(port, backlog, host);
}
// Everything is OK as far as we can tell.
this.database.getWriteLock();
this.info.getWriteLock();
this.info.add("STARTING", Boolean.TRUE);
this.info.releaseWriteLock();
this.database.releaseWriteLock();
}
private void rlock() throws Exception {
database.getReadLock();
info.getReadLock();
}
private void runlock() throws Exception {
database.releaseReadLock();
info.releaseReadLock();
}
private void wlock() throws Exception {
database.getWriteLock();
info.getWriteLock();
}
private void wunlock() throws Exception {
info.releaseWriteLock();
database.releaseWriteLock();
}
/**
* MUX sockets, fire off a thread to connect, get destination info, and do I/O
*
*/
public void run() {
try {
wlock();
try {
info.add("RUNNING", Boolean.TRUE);
info.add("STARTING", Boolean.FALSE);
} catch(Exception e) {
wunlock();
return;
}
} catch(Exception e) {
return;
}
try {
wunlock();
} catch(Exception e) {
return;
}
quit: {
try {
tg = new ThreadGroup(N);
die: {
// toss the connections to a new threads.
// will wrap with TCP and UDP when UDP works
if(go_out) {
// I2P -> TCP
I2Plistener conn = new I2Plistener(socketManager, info, database, _log);
Thread t = new Thread(tg, conn, "BOBI2Plistener " + N);
t.start();
}
if(come_in) {
// TCP -> I2P
TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log);
Thread q = new Thread(tg, conn, "BOBTCPlistener" + N);
q.start();
}
boolean spin = true;
while(spin) {
try {
Thread.sleep(1000); //sleep for 1000 ms (One second)
} catch(InterruptedException e) {
// nop
}
try {
rlock();
try {
spin = info.get("STOPPING").equals(Boolean.FALSE);
} catch(Exception e) {
runlock();
break die;
}
} catch(Exception e) {
break die;
}
try {
runlock();
} catch(Exception e) {
break die;
}
}
try {
wlock();
try {
info.add("RUNNING", Boolean.FALSE);
} catch(Exception e) {
wunlock();
break die;
}
} catch(Exception e) {
break die;
}
try {
wunlock();
} catch(Exception e) {
break die;
}
} // die
// wait for child threads and thread groups to die
// System.out.println("MUXlisten: waiting for children");
while(tg.activeCount() + tg.activeGroupCount() != 0) {
tg.interrupt(); // unwedge any blocking threads.
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(InterruptedException ex) {
// nop
}
}
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
} catch(Exception e) {
// System.out.println("MUXlisten: Caught an exception" + e);
break quit;
}
} // quit
// This is here to catch when something fucks up REALLY bad.
if(tg != null) {
System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
System.out.println("BOB: MUXlisten: Please email the following dump to sponge@mail.i2p");
WrapperManager.requestThreadDump();
System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
System.out.println("BOB: MUXlisten: Please email the above dump to sponge@mail.i2p");
}
// zero out everything, just incase.
try {
socketManager.destroySocketManager();
} catch(Exception e) {
// nop
}
try {
wlock();
try {
info.add("STARTING", Boolean.FALSE);
info.add("STOPPING", Boolean.FALSE);
info.add("RUNNING", Boolean.FALSE);
} catch(Exception e) {
wunlock();
return;
}
wunlock();
} catch(Exception e) {
}
// This is here to catch when something fucks up REALLY bad.
if(tg != null) {
while(tg.activeCount() + tg.activeGroupCount() != 0) {
tg.interrupt(); // unwedge any blocking threads.
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(InterruptedException ex) {
// nop
}
}
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
}
}
}

View File

@ -0,0 +1,46 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import net.i2p.client.streaming.RetransmissionTimer;
import net.i2p.util.SimpleTimer;
/**
* Start from command line
*
* @author sponge
*
*/
public class Main {
/**
* @param args the command line arguments, these are not used yet
*/
public static void main(String[] args) {
// THINK THINK THINK THINK THINK THINK
SimpleTimer Y = RetransmissionTimer.getInstance();
BOB.main(args);
Y.removeSimpleTimer();
}
}

View File

@ -0,0 +1,195 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
/**
* Internal database to relate nicknames to options to values
*
* @author sponge
*/
public class NamedDB {
private volatile Object[][] data;
private volatile int index, writersWaiting, readers;
/**
* make initial NULL object
*
*/
public NamedDB() {
this.data = new Object[1][2];
this.index = this.writersWaiting = this.readers = 0;
}
synchronized public void getReadLock() {
while((writersWaiting != 0)) {
try {
wait();
} catch(InterruptedException ie) {
}
}
readers++;
}
synchronized public void releaseReadLock() {
readers--;
notifyAll();
}
synchronized public void getWriteLock() {
writersWaiting++;
while(readers != 0 && writersWaiting != 1 ) {
try {
wait();
} catch(InterruptedException ie) {
}
}
}
synchronized public void releaseWriteLock() {
writersWaiting--;
notifyAll();
}
/**
* Find objects in the array, returns it's index or throws exception
* @param key
* @return an objects index
* @throws ArrayIndexOutOfBoundsException when key does not exist
*/
public int idx(Object key) throws ArrayIndexOutOfBoundsException {
for(int i = 0; i < index; i++) {
if(key.equals(data[i][0])) {
return i;
}
}
throw new ArrayIndexOutOfBoundsException("Can't locate key for index");
}
/**
* Delete an object from array if it exists
*
* @param key
*/
public void kill(Object key) {
int i, j, k, l;
Object[][] olddata;
int didsomething = 0;
try {
k = idx(key);
} catch(ArrayIndexOutOfBoundsException b) {
return;
}
olddata = new Object[index + 2][2];
// copy to olddata, skipping 'k'
for(i = 0 , l = 0; l < index; i++, l++) {
if(i == k) {
l++;
didsomething++;
}
for(j = 0; j < 2; j++) {
olddata[i][j] = data[l][j];
}
}
index -= didsomething;
data = olddata;
}
/**
* Add object to the array, deletes the old one if it exists
*
* @param key
* @param val
*/
public void add(Object key, Object val) {
Object[][] olddata;
int i, j;
i = 0;
kill(key);
olddata = new Object[index + 2][2];
// copy to olddata
for(i = 0; i < index; i++) {
for(j = 0; j < 2; j++) {
olddata[i][j] = data[i][j];
}
}
data = olddata;
data[index++] = new Object[] {key, val};
}
/**
* Get the object, and return it, throws RuntimeException
*
* @param key
* @return Object
* @throws java.lang.RuntimeException
*/
public Object get(Object key) throws RuntimeException {
for(int i = 0; i < index; i++) {
if(key.equals(data[i][0])) {
return data[i][1];
}
}
throw new RuntimeException("Key not found");
}
/**
* returns true if an object exists, else returns false
*
* @param key
* @return true if an object exists, else returns false
*/
public boolean exists(Object key) {
for(int i = 0; i < index; i++) {
if(key.equals(data[i][0])) {
return true;
}
}
return false;
}
/**
*
* @param i index
* @return an indexed Object
* @throws java.lang.RuntimeException
*/
public Object getnext(int i) throws RuntimeException {
if(i < index && i > -1) {
return data[i][1];
}
throw new RuntimeException("No more data");
}
/**
* @return the count of how many objects
*/
public int getcount() {
return index;
}
}

View File

@ -0,0 +1,105 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Shove data from one stream to the other.
*
* @author sponge
*/
public class TCPio implements Runnable {
private InputStream Ain;
private OutputStream Aout;
private NamedDB info, database;
/**
* Constructor
*
* @param Ain
* @param Aout
* @param info
* @param database
*/
TCPio(InputStream Ain, OutputStream Aout, NamedDB info, NamedDB database) {
this.Ain = Ain;
this.Aout = Aout;
this.info = info;
this.database = database;
}
/**
* Copy from source to destination...
* and yes, we are totally OK to block here on writes,
* The OS has buffers, and I intend to use them.
*
*/
public void run() {
int b;
byte a[] = new byte[1];
boolean spin = true;
try {
while(spin) {
database.getReadLock();
info.getReadLock();
spin = info.get("RUNNING").equals(Boolean.TRUE);
info.releaseReadLock();
database.releaseReadLock();
b = Ain.read(a, 0, 1);
// System.out.println(info.get("NICKNAME").toString() + " " + b);
if(b > 0) {
Aout.write(a, 0, b);
} else if(b == 0) {
Thread.yield(); // this should act like a mini sleep.
if(Ain.available() == 0) {
try {
// Thread.yield();
Thread.sleep(10);
} catch(InterruptedException ex) {
}
}
} else {
/* according to the specs:
*
* The total number of bytes read into the buffer,
* or -1 if there is no more data because the end of
* the stream has been reached.
*
*/
// System.out.println("TCPio: End Of Stream");
return;
}
}
// System.out.println("TCPio: RUNNING = false");
} catch(Exception e) {
// Eject!!! Eject!!!
// System.out.println("TCPio: Caught an exception " + e);
return;
}
// System.out.println("TCPio: Leaving.");
}
}

View File

@ -0,0 +1,147 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.util.Log;
/**
* Listen on TCP port and connect to I2P
*
* @author sponge
*/
public class TCPlistener implements Runnable {
private NamedDB info, database;
private Log _log;
private int tgwatch;
public I2PSocketManager socketManager;
public I2PServerSocket serverSocket;
private ServerSocket listener;
/**
* Constructor
* @param S
* @param info
* @param database
* @param _log
*/
TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Log _log) {
this.database = database;
this.info = info;
this._log = _log;
this.socketManager = S;
this.listener = listener;
tgwatch = 1;
}
/**
* Simply listen on TCP port, and thread connections
*
*/
public void run() {
boolean g = false;
boolean spin = true;
database.getReadLock();
info.getReadLock();
if(info.exists("OUTPORT")) {
tgwatch = 2;
}
try {
Socket server = new Socket();
listener.setSoTimeout(1000);
info.releaseReadLock();
database.releaseReadLock();
while(spin) {
database.getReadLock();
info.getReadLock();
spin = info.get("RUNNING").equals(Boolean.TRUE);
info.releaseReadLock();
database.releaseReadLock();
try {
server = listener.accept();
g = true;
} catch(SocketTimeoutException ste) {
g = false;
}
if(g) {
// toss the connection to a new thread.
TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database);
Thread t = new Thread(conn_c, "BOBTCPtoI2P");
t.start();
g = false;
}
}
//System.out.println("TCPlistener: destroySession");
listener.close();
} catch(IOException ioe) {
try {
listener.close();
} catch(IOException e) {
}
// Fatal failure, cause a stop event
database.getReadLock();
info.getReadLock();
spin = info.get("RUNNING").equals(Boolean.TRUE);
info.releaseReadLock();
database.releaseReadLock();
if(spin) {
database.getWriteLock();
info.getWriteLock();
info.add("STOPPING", new Boolean(true));
info.add("RUNNING", new Boolean(false));
info.releaseWriteLock();
database.releaseWriteLock();
}
}
// need to kill off the socket manager too.
I2PSession session = socketManager.getSession();
if(session != null) {
try {
session.destroySession();
} catch(I2PSessionException ex) {
// nop
}
}
//System.out.println("TCPlistener: Waiting for children");
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(Exception e) {
// nop
}
}
//System.out.println("TCPlistener: Done.");
}
}

View File

@ -0,0 +1,186 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.Socket;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
/**
*
* Process TCP->I2P
*
* @author sponge
*/
public class TCPtoI2P implements Runnable {
private I2PSocket I2P;
private NamedDB info, database;
private Socket sock;
private I2PSocketManager socketManager;
/**
* This is a more forgiving readline,
* it works on unbuffered streams
*
* @param in
* @return line of text as a String
* @throws Exception
*/
private static String lnRead(InputStream in) throws Exception {
String S;
int b;
char c;
S = new String();
while(true) {
b = in.read();
if(b == 13) {
//skip CR
continue;
}
if(b < 20 || b > 126) {
// exit on anything not legal
break;
}
c = (char)(b & 0x7f); // We only really give a fuck about ASCII
S = new String(S + c);
}
return S;
}
/**
* Constructor
* @param i2p
* @param socket
* @param info
* @param database
*/
TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database) {
this.sock = socket;
this.info = info;
this.database = database;
this.socketManager = i2p;
}
/**
* Print an error message to out
*
* @param e
* @param out
* @throws java.io.IOException
*/
private void Emsg(String e, OutputStream out) throws IOException {
// Debugging System.out.println("ERROR TCPtoI2P: " + e);
out.write("ERROR".concat(e).getBytes());
out.write(13); // cr
out.flush();
}
/**
* TCP stream to I2P stream thread starter
*/
public void run() {
String line, input;
try {
InputStream in = sock.getInputStream();
OutputStream out = sock.getOutputStream();
try {
line = lnRead(in);
input = line.toLowerCase();
Destination dest = null;
if(input.endsWith(".i2p")) {
dest = I2PTunnel.destFromName(input);
line = dest.toBase64();
}
dest = new Destination();
dest.fromBase64(line);
try {
// get a client socket
I2P = socketManager.connect(dest);
I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
// make readers/writers
InputStream Iin = I2P.getInputStream();
OutputStream Iout = I2P.getOutputStream();
// setup to cross the streams
TCPio conn_c = new TCPio(in, Iout, info, database); // app -> I2P
TCPio conn_a = new TCPio(Iin, out, info, database); // I2P -> app
Thread t = new Thread(conn_c, "TCPioA");
Thread q = new Thread(conn_a, "TCPioB");
// Fire!
t.start();
q.start();
while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread
try {
Thread.sleep(10); //sleep for 10 ms
} catch(InterruptedException e) {
// nop
}
}
// System.out.println("TCPtoI2P: Going away...");
} catch(I2PException e) {
Emsg("ERROR " + e.toString(), out);
} catch(ConnectException e) {
Emsg("ERROR " + e.toString(), out);
} catch(NoRouteToHostException e) {
Emsg("ERROR " + e.toString(), out);
} catch(InterruptedIOException e) {
Emsg("ERROR " + e.toString(), out);
}
} catch(Exception e) {
Emsg("ERROR " + e.toString(), out);
}
} catch(IOException ioe) {
}
try {
// System.out.println("TCPtoI2P: Close I2P");
I2P.close();
} catch(Exception e) {
}
try {
// System.out.println("TCPtoI2P: Close sock");
sock.close();
} catch(Exception e) {
}
// System.out.println("TCPtoI2P: Done.");
}
}

View File

@ -0,0 +1,144 @@
/**
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
*
* Copyright (C) sponge
* Planet Earth
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*
* See...
*
* http://sam.zoy.org/wtfpl/
* and
* http://en.wikipedia.org/wiki/WTFPL
*
* ...for any additional details and liscense questions.
*/
package net.i2p.BOB;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSessionListener;
import net.i2p.data.Destination;
import net.i2p.util.Log;
/**
* UDP IO on I2P
*
* FIX ME: Untested, and incomplete!
* I have no personal need to UDP yet,
* however alot of p2p apps pretty much demand it.
* The skeletal frame is here, just needs to be finished.
*
* @author sponge
*/
public class UDPIOthread implements I2PSessionListener, Runnable {
private NamedDB info;
private Log _log;
private Socket socket;
private DataInputStream in;
private DataOutputStream out;
private I2PSession _session;
private Destination _peerDestination;
private boolean up;
/**
* Constructor
* @param info
* @param _log
* @param socket
* @param _session
*/
UDPIOthread(NamedDB info, Log _log, Socket socket, I2PSession _session) {
this.info = info;
this._log = _log;
this.socket = socket;
this._session = _session;
}
/**
*
*/
public void run() {
byte data[] = new byte[1024];
up = true;
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
while(up) {
int c = in.read(data);
// Note: could do a loopback test here with a wrapper.
boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
if(!ok) {
up = false; // Is this the right thing to do??
}
}
} catch(IOException ioe) {
_log.error("Error running", ioe);
} catch(I2PSessionException ise) {
_log.error("Error communicating", ise);
// } catch(DataFormatException dfe) {
// _log.error("Peer destination file is not valid", dfe);
} finally {
if(_session != null) {
try {
_session.destroySession();
} catch(I2PSessionException ise) {
// ignored
}
}
}
}
/**
*
* @param session
* @param msgId
* @param size
*/
public void messageAvailable(I2PSession session, int msgId, long size) {
// _log.debug("Message available: id = " + msgId + " size = " + size);
try {
byte msg[] = session.receiveMessage(msgId);
out.write(msg);
out.flush();
} catch(I2PSessionException ise) {
up = false;
} catch(IOException ioe) {
up = false;
}
}
// Great, can these be used to kill ourselves.
/** required by {@link I2PSessionListener I2PSessionListener} to notify of disconnect */
public void disconnected(I2PSession session) {
_log.debug("Disconnected");
// up = false;
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of error */
public void errorOccurred(I2PSession session, String message, Throwable error) {
_log.debug("Error occurred: " + message, error);
// up = false;
}
/** required by {@link I2PSessionListener I2PSessionListener} to notify of abuse */
public void reportAbuse(I2PSession session, int severity) {
_log.debug("Abuse reported of severity " + severity);
// up = false;
}
}

View File

@ -0,0 +1,5 @@
<html>
<body>
<p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P.</p>
</body>
</html>

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<project name="addressbook" default="war" basedir=".">
<property name="src" value="java/src/addressbook"/>
<property name="src" value="java/src"/>
<property name="build" value="build"/>
<property name="dist" location="dist"/>
<property name="jar" value="addressbook.jar"/>
@ -19,8 +19,24 @@
<target name="distclean" depends="clean" />
<target name="compile" depends="init">
<javac debug="true" deprecation="on" source="1.3" target="1.3"
<condition property="depend.available">
<typefound name="depend" />
</condition>
<target name="depend" if="depend.available">
<depend
cache="../../build"
srcdir="${src}"
destdir="${build}" >
<!-- Depend on classes instead of jars where available -->
<classpath>
<pathelement location="../../core/java/build/obj" />
<pathelement location="../jetty/jettylib/javax.servlet.jar" />
</classpath>
</depend>
</target>
<target name="compile" depends="init, depend">
<javac debug="true" deprecation="on" source="1.5" target="1.5"
srcdir="${src}" destdir="${build}">
<classpath>
<pathelement location="../../core/java/build/i2p.jar" />
@ -37,7 +53,7 @@
</jar>
</target>
<target name="war" depends="compile">
<target name="war" depends="compile" unless="war.uptodate">
<mkdir dir="${dist}/tmp"/>
<mkdir dir="${dist}/tmp/WEB-INF"/>
<mkdir dir="${dist}/tmp/WEB-INF/classes"/>
@ -48,4 +64,8 @@
<delete dir="${dist}/tmp"/>
</target>
<uptodate property="war.uptodate" targetfile="${dist}/${war}">
<srcfiles dir= "." includes="${build}/**/*.class, web.xml"/>
</uptodate>
</project>

View File

@ -57,7 +57,7 @@ public class AddressBook {
this.addresses = addresses;
}
/**
/*
* Construct an AddressBook from the contents of the file at url. If the
* remote file cannot be read, construct an empty AddressBook
*
@ -81,6 +81,7 @@ public class AddressBook {
new File("addressbook.tmp").delete();
}
*/
static final long MAX_SUB_SIZE = 3 * 1024 * 1024l; //about 5,000 hosts
/**
* Construct an AddressBook from the Subscription subscription. If the
* address book at subscription has not changed since the last time it was
@ -89,8 +90,9 @@ public class AddressBook {
*
* @param subscription
* A Subscription instance pointing at a remote address book.
* @param proxyHost hostname of proxy
* @param proxyPort port number of proxy
*/
static final long MAX_SUB_SIZE = 3 * 1024 * 1024l; //about 5,000 hosts
public AddressBook(Subscription subscription, String proxyHost, int proxyPort) {
this.location = subscription.getLocation();
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
@ -152,10 +154,14 @@ public class AddressBook {
*
* @return A String representing the contents of the AddressBook.
*/
@Override
public String toString() {
return this.addresses.toString();
}
private static final int MIN_DEST_LENGTH = 516;
private static final int MAX_DEST_LENGTH = MIN_DEST_LENGTH + 100; // longer than any known cert type for now
/**
* Do basic validation of the hostname and dest
* hostname was already converted to lower case by ConfigParser.parse()
@ -173,6 +179,11 @@ public class AddressBook {
// IDN - basic check, not complete validation
(host.indexOf("--") < 0 || host.startsWith("xn--") || host.indexOf(".xn--") > 0) &&
host.replaceAll("[a-z0-9.-]", "").length() == 0 &&
// Base32 spoofing (52chars.i2p)
(! (host.length() == 56 && host.substring(0,52).replaceAll("[a-z2-7]", "").length() == 0)) &&
// ... or maybe we do Base32 this way ...
(! host.equals("b32.i2p")) &&
(! host.endsWith(".b32.i2p")) &&
// some reserved names that may be used for local configuration someday
(! host.equals("proxy.i2p")) &&
(! host.equals("router.i2p")) &&
@ -181,8 +192,8 @@ public class AddressBook {
(! host.endsWith(".router.i2p")) &&
(! host.endsWith(".console.i2p")) &&
dest.length() == 516 &&
dest.endsWith("AAAA") &&
((dest.length() == MIN_DEST_LENGTH && dest.endsWith("AAAA")) ||
(dest.length() > MIN_DEST_LENGTH && dest.length() <= MAX_DEST_LENGTH)) &&
dest.replaceAll("[a-zA-Z0-9~-]", "").length() == 0
;
}
@ -195,6 +206,7 @@ public class AddressBook {
*
* @param other
* An AddressBook to merge with.
* @param overwrite True to overwrite
* @param log
* The log to write messages about new addresses or conflicts to.
*/

View File

@ -107,7 +107,11 @@ public class ConfigParser {
FileInputStream fileStream = new FileInputStream(file);
BufferedReader input = new BufferedReader(new InputStreamReader(
fileStream));
return ConfigParser.parse(input);
Map rv = ConfigParser.parse(input);
try {
fileStream.close();
} catch (IOException ioe) {}
return rv;
}
/**
@ -138,7 +142,7 @@ public class ConfigParser {
* cannot be read, map.
*/
public static Map parse(File file, Map map) {
Map result = new HashMap();
Map result;
try {
result = ConfigParser.parse(file);
} catch (IOException exp) {
@ -188,7 +192,11 @@ public class ConfigParser {
FileInputStream fileStream = new FileInputStream(file);
BufferedReader input = new BufferedReader(new InputStreamReader(
fileStream));
return ConfigParser.parseSubscriptions(input);
List rv = ConfigParser.parseSubscriptions(input);
try {
fileStream.close();
} catch (IOException ioe) {}
return rv;
}
/**
@ -213,13 +221,12 @@ public class ConfigParser {
*
* @param file
* A File to attempt to parse.
* @param string
* A List to use as the default, if file fails.
* @param list list of files to parse
* @return A List consisting of one element for each line in file, or if
* file cannot be read, list.
*/
public static List parseSubscriptions(File file, List list) {
List result = new LinkedList();
List result;
try {
result = ConfigParser.parseSubscriptions(file);
} catch (IOException exp) {

View File

@ -125,7 +125,6 @@ public class Daemon {
public void run(String[] args) {
String settingsLocation = "config.txt";
Map settings = new HashMap();
String home;
if (args.length > 0) {
home = args[0];
@ -157,10 +156,11 @@ public class Daemon {
File settingsFile = new File(homeFile, settingsLocation);
settings = ConfigParser.parse(settingsFile, defaultSettings);
Map settings = ConfigParser.parse(settingsFile, defaultSettings);
// wait
try {
Thread.currentThread().sleep(5*60*1000);
Thread.sleep(5*60*1000);
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
} catch (InterruptedException ie) {}
while (true) {

View File

@ -43,6 +43,7 @@ public class DaemonThread extends Thread {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
//try {
// Thread.sleep(5 * 60 * 1000);

View File

@ -54,14 +54,17 @@ public class Log {
* A String containing a message to append to the log.
*/
public void append(String entry) {
BufferedWriter bw = null;
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(this.file,
bw = new BufferedWriter(new FileWriter(this.file,
true));
String timestamp = new Date().toString();
bw.write(timestamp + " -- " + entry);
bw.newLine();
bw.close();
} catch (IOException exp) {
} finally {
if (bw != null)
try { bw.close(); } catch (IOException ioe) {}
}
}
@ -73,4 +76,4 @@ public class Log {
public File getFile() {
return this.file;
}
}
}

View File

@ -44,6 +44,7 @@ public class Servlet extends GenericServlet {
/* (non-Javadoc)
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig config) {
try {
super.init(config);

View File

@ -41,6 +41,8 @@ public class SubscriptionIterator implements Iterator {
*
* @param subscriptions
* List of Subscription objects that represent address books.
* @param proxyHost proxy hostname
* @param proxyPort proxt port number
*/
public SubscriptionIterator(List subscriptions, String proxyHost, int proxyPort) {
this.subIterator = subscriptions.iterator();

View File

@ -60,6 +60,9 @@ public class SubscriptionList {
* @param lastModifiedFile
* A file containg the last-modified headers used for conditional
* GET. The file is in the format "url=leastmodified".
* @param defaultSubs default subscription file
* @param proxyHost proxy hostname
* @param proxyPort proxy port number
*/
public SubscriptionList(File locationsFile, File etagsFile,
File lastModifiedFile, List defaultSubs, String proxyHost,

View File

@ -41,24 +41,34 @@ import net.i2p.util.Log;
public class ATalk implements I2PSessionListener, Runnable {
/** logging hook - status messages are piped to this */
private final static Log _log = new Log(ATalk.class);
/** platform independent newline */
private final static String NL = System.getProperty("line.separator");
/** the current session */
private I2PSession _session;
/** who am i */
private Destination _myDestination;
/** who are you? */
private Destination _peerDestination;
/** location of my secret key file */
private String _myKeyFile;
/** location of their public key */
private String _theirDestinationFile;
/** where the application reads input from. currently set to standard input */
private BufferedReader _in;
/** where the application sends output to. currently set to standard output */
private BufferedWriter _out;
/** string that messages must begin with to be treated as files */
private final static String FILE_COMMAND = ".file: ";
/** the, erm, manual */
private final static String MANUAL = "ATalk: Anonymous Talk, a demo program for the Invisible Internet Project SDK"
+ NL
@ -84,7 +94,9 @@ public class ATalk implements I2PSessionListener, Runnable {
+ NL
+ "To end the talk session, enter a period on a line by itself and hit return"
+ NL;
public final static String PROP_CONFIG_LOCATION = "configFile";
private static final SimpleDateFormat _fmt = new SimpleDateFormat("hh:mm:ss.SSS");
/** Construct the talk engine, but don't connect yet */
@ -111,11 +123,12 @@ public class ATalk implements I2PSessionListener, Runnable {
_log.warn("Unable to load up the ATalk config file " + configLocation);
}
// Provide any router or client API configuration here.
if (!props.containsKey(I2PClient.PROP_TCP_HOST)) props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
if (!props.containsKey(I2PClient.PROP_TCP_PORT)) props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
if (!props.containsKey(I2PClient.PROP_TCP_HOST))
props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
if (!props.containsKey(I2PClient.PROP_TCP_PORT))
props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
if (!props.containsKey(I2PClient.PROP_RELIABILITY))
props.setProperty(I2PClient.PROP_RELIABILITY,
I2PClient.PROP_RELIABILITY_BEST_EFFORT);
props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT);
_session = client.createSession(new FileInputStream(myFile), props);
_session.setSessionListener(this);
_session.connect();
@ -364,4 +377,5 @@ public class ATalk implements I2PSessionListener, Runnable {
public void reportAbuse(I2PSession session, int severity) {
_log.debug("Abuse reported of severity " + severity);
}
}
}

View File

@ -1,347 +0,0 @@
/*
* bogobot - A simple join/part stats logger bot for I2P IRC.
*
* Bogobot.java
* 2004 The I2P Project
* http://www.i2p.net
* This code is public domain.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.jibble.pircbot.IrcException;
import org.jibble.pircbot.NickAlreadyInUseException;
import org.jibble.pircbot.PircBot;
import org.jibble.pircbot.User;
/**
* TODO 0.5 Add multi-server capability.
*
* @author hypercubus, oOo
* @version 0.4
*/
public class Bogobot extends PircBot {
private static final String INTERVAL_DAILY = "daily";
private static final String INTERVAL_MONTHLY = "monthly";
private static final String INTERVAL_WEEKLY = "weekly";
private boolean _isIntentionalDisconnect = false;
private long _lastUserlistCommandTimestamp = 0;
private Logger _logger = Logger.getLogger(Bogobot.class);
private int _currentAutoRoundTripTag = 0;
private long _lastAutoRoundTripSentTime = 0;
private Timer _tickTimer;
private String _configFile;
private String _botPrimaryNick;
private String _botSecondaryNick;
private String _botNickservPassword;
private String _botUsername;
private String _ownerPrimaryNick;
private String _ownerSecondaryNick;
private String _botShutdownPassword;
private String _ircChannel;
private String _ircServer;
private int _ircServerPort;
private boolean _isLoggerEnabled;
private String _loggedHostnamePattern;
private boolean _isUserlistCommandEnabled;
private String _logFilePrefix;
private String _logFileRotationInterval;
private long _commandAntiFloodInterval;
private String _userlistCommandTrigger;
private boolean _isRoundTripDelayEnabled;
private int _roundTripDelayPeriod;
class BogobotTickTask extends TimerTask {
private Bogobot _caller;
public BogobotTickTask(Bogobot caller) {
_caller = caller;
}
public void run() {
_caller.onTick();
}
}
private void loadConfigFile(String configFileName) {
_configFile = configFileName;
Properties config = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(configFileName);
config.load(fis);
} catch (IOException ioe) {
System.err.println("Error loading configuration file");
System.exit(2);
} finally {
if (fis != null) try {
fis.close();
} catch (IOException ioe) { // nop
}
}
_botPrimaryNick = config.getProperty("botPrimaryNick", "somebot");
_botSecondaryNick = config.getProperty("botSecondaryNick", "somebot_");
_botNickservPassword = config.getProperty("botNickservPassword", "");
_botUsername = config.getProperty("botUsername", "somebot");
_ownerPrimaryNick = config.getProperty("ownerPrimaryNick", "somenick");
_ownerSecondaryNick = config.getProperty("ownerSecondaryNick", "somenick_");
_botShutdownPassword = config.getProperty("botShutdownPassword", "take off eh");
_ircChannel = config.getProperty("ircChannel", "#i2p-chat");
_ircServer = config.getProperty("ircServer", "irc.postman.i2p");
_ircServerPort = Integer.parseInt(config.getProperty("ircServerPort", "6668"));
_isLoggerEnabled = Boolean.valueOf(config.getProperty("isLoggerEnabled", "true")).booleanValue();
_loggedHostnamePattern = config.getProperty("loggedHostnamePattern", "");
_logFilePrefix = config.getProperty("logFilePrefix", "irc.postman.i2p.i2p-chat");
_logFileRotationInterval = config.getProperty("logFileRotationInterval", INTERVAL_DAILY);
_isRoundTripDelayEnabled = Boolean.valueOf(config.getProperty("isRoundTripDelayEnabled", "false")).booleanValue();
_roundTripDelayPeriod = Integer.parseInt(config.getProperty("roundTripDelayPeriod", "300"));
_isUserlistCommandEnabled = Boolean.valueOf(config.getProperty("isUserlistCommandEnabled", "true")).booleanValue();
_userlistCommandTrigger = config.getProperty("userlistCommandTrigger", "!who");
_commandAntiFloodInterval = Long.parseLong(config.getProperty("commandAntiFloodInterval", "60"));
}
public Bogobot(String configFileName) {
loadConfigFile(configFileName);
this.setName(_botPrimaryNick);
this.setLogin(_botUsername);
_tickTimer = new Timer();
_tickTimer.scheduleAtFixedRate(new BogobotTickTask(this), 1000, 10 * 1000);
}
public static void main(String[] args) {
Bogobot bogobot;
if (args.length > 1) {
System.err.println("Too many arguments, the only allowed parameter is configuration file name");
System.exit(3);
}
if (args.length == 1) {
bogobot = new Bogobot(args[0]);
} else {
bogobot = new Bogobot("bogobot.config");
}
bogobot.setVerbose(true);
if (bogobot._isLoggerEnabled)
bogobot.initLogger();
bogobot.connectToServer();
}
protected void onTick() {
// Tick about once every ten seconds
if (this.isConnected() && _isRoundTripDelayEnabled) {
if( ( (System.currentTimeMillis() - _lastAutoRoundTripSentTime) >= (_roundTripDelayPeriod * 1000) ) && (this.getOutgoingQueueSize() == 0) ) {
// Connected, sending queue is empty and last RoundTrip is more then 5 minutes old -> Send a new one
_currentAutoRoundTripTag ++;
_lastAutoRoundTripSentTime = System.currentTimeMillis();
sendNotice(this.getNick(),"ROUNDTRIP " + _currentAutoRoundTripTag);
}
}
}
protected void onDisconnect() {
if (_isIntentionalDisconnect)
System.exit(0);
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " quits *** " + this.getName() + " *** (Lost connection)");
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
// No worries.
}
connectToServer();
}
protected void onJoin(String channel, String sender, String login, String hostname) {
if (_isLoggerEnabled) {
if (sender.equals(this.getName())) {
_logger.info(System.currentTimeMillis() + " joins *** " + _botPrimaryNick + " ***");
} else {
String prependedHostname = "@" + hostname;
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
_logger.info(System.currentTimeMillis() + " joins " + sender);
}
}
}
}
protected void onMessage(String channel, String sender, String login, String hostname, String message) {
message = message.replaceFirst("<.+?> ", "");
if (_isUserlistCommandEnabled && message.equals(_userlistCommandTrigger)) {
if (System.currentTimeMillis() - _lastUserlistCommandTimestamp < _commandAntiFloodInterval * 1000)
return;
Object[] users = getUsers(_ircChannel);
String output = "Userlist for " + _ircChannel + ": ";
for (int i = 0; i < users.length; i++)
output += "[" + ((User) users[i]).getNick() + "] ";
sendMessage(_ircChannel, output);
_lastUserlistCommandTimestamp = System.currentTimeMillis();
}
}
protected void onPart(String channel, String sender, String login, String hostname) {
if (_isLoggerEnabled) {
if (sender.equals(this.getName())) {
_logger.info(System.currentTimeMillis() + " parts *** " + _botPrimaryNick + " ***");
} else {
String prependedHostname = "@" + hostname;
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
_logger.info(System.currentTimeMillis() + " parts " + sender);
}
}
}
}
protected void onPrivateMessage(String sender, String login, String hostname, String message) {
/*
* Nobody else except the bot's owner can shut it down, unless of
* course the owner's nick isn't registered and someone's spoofing it.
*/
if ((sender.equals(_ownerPrimaryNick) || sender.equals(_ownerSecondaryNick)) && message.equals(_botShutdownPassword)) {
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " quits *** " + this.getName() + " ***");
_isIntentionalDisconnect = true;
disconnect();
}
}
protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) {
String prependedHostname = "@" + sourceHostname;
if (sourceNick.equals(_botPrimaryNick))
changeNick(_botPrimaryNick);
if (_isLoggerEnabled) {
if (prependedHostname.endsWith(_loggedHostnamePattern)) {
_logger.info(System.currentTimeMillis() + " quits " + sourceNick + " " + reason);
}
}
}
private void connectToServer() {
int loginAttempts = 0;
while (true) {
try {
connect(_ircServer, _ircServerPort);
break;
} catch (NickAlreadyInUseException e) {
if (loginAttempts == 1) {
System.out.println("Sorry, the primary and secondary bot nicks are already taken. Exiting.");
System.exit(1);
}
loginAttempts++;
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// Hmph.
}
if (getName().equals(_botPrimaryNick))
setName(_botSecondaryNick);
else
setName(_botPrimaryNick);
continue;
} catch (IOException e) {
System.out.println("Error during login: ");
e.printStackTrace();
System.exit(1);
} catch (IrcException e) {
System.out.println("Error during login: ");
e.printStackTrace();
System.exit(1);
}
}
joinChannel(_ircChannel);
}
protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) {
if (sourceNick.equals("NickServ") && (notice.indexOf("/msg NickServ IDENTIFY") >= 0) && (_botNickservPassword != "")) {
sendRawLineViaQueue("NICKSERV IDENTIFY " + _botNickservPassword);
}
if (sourceNick.equals(getNick()) && notice.equals( "ROUNDTRIP " + _currentAutoRoundTripTag)) {
int delay = (int)((System.currentTimeMillis() - _lastAutoRoundTripSentTime) / 100);
// sendMessage(_ircChannel, "Round-trip delay = " + (delay / 10.0f) + " seconds");
if (_isLoggerEnabled)
_logger.info(System.currentTimeMillis() + " roundtrip " + delay);
}
}
private void initLogger() {
String logFilePath = "logs" + File.separator + _logFilePrefix;
DailyRollingFileAppender rollingFileAppender = null;
if (!(new File("logs").exists()))
(new File("logs")).mkdirs();
try {
if (_logFileRotationInterval.equals("monthly"))
rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-MM'.log'");
else if (_logFileRotationInterval.equals("weekly"))
rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-ww'.log'");
else
rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-MM-dd'.log'");
rollingFileAppender.setThreshold(Level.INFO);
_logger.addAppender(rollingFileAppender);
} catch (IOException ex) {
System.out.println("Error: Couldn't create or open an existing log file. Exiting.");
System.exit(1);
}
}
}

View File

@ -1,353 +0,0 @@
/*
* bogoparser - A simple logfile analyzer for bogobot.
*
* Bogoparser.java
* 2004 The I2P Project
* http://www.i2p.net
* This code is public domain.
*/
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author hypercubus
* @version 0.4
*/
public class Bogoparser {
private static void displayUsageAndExit() {
System.out.println("\r\nUsage:\r\n\r\n java Bogoparser [--by-duration] <logfile>\r\n");
System.exit(1);
}
public static void main(String[] args) {
Bogoparser bogoparser;
if (args.length < 1 || args.length > 2)
displayUsageAndExit();
if (args.length == 2) {
if (!args[0].equals("--by-duration"))
displayUsageAndExit();
bogoparser = new Bogoparser(args[1], true);
}
if (args.length == 1)
bogoparser = new Bogoparser(args[0], false);
}
private Bogoparser(String logfile, boolean sortByDuration) {
ArrayList sortedSessions;
if (sortByDuration) {
sortedSessions = sortSessionsByDuration(calculateSessionDurations(sortSessionsByTime(readLogfile(logfile))));
formatAndOutputByDuration(sortedSessions);
} else {
sortedSessions = calculateSessionDurations(sortSessionsByQuitReason(sortSessionsByNick(sortSessionsByTime(readLogfile(logfile)))));
formatAndOutput(sortedSessions);
}
}
private ArrayList calculateSessionDurations(ArrayList sortedSessionsByQuitReasonOrDuration) {
ArrayList calculatedSessionDurations = new ArrayList();
for (int i = 0; i+1 < sortedSessionsByQuitReasonOrDuration.size(); i += 2) {
String joinsEntry = (String) sortedSessionsByQuitReasonOrDuration.get(i);
String[] joinsEntryFields = joinsEntry.split(" ");
String quitsEntry = (String) sortedSessionsByQuitReasonOrDuration.get(i+1);
Pattern p = Pattern.compile("^([^ ]+) [^ ]+ ([^ ]+) (.*)$");
Matcher m = p.matcher(quitsEntry);
if (m.matches()) {
String currentJoinTime = joinsEntryFields[0];
String currentNick = m.group(2);
String currentQuitReason = m.group(3);
String currentQuitTime = m.group(1);
long joinsTimeInMilliseconds;
long quitsTimeInMilliseconds;
long sessionLengthInMilliseconds;
joinsTimeInMilliseconds = Long.parseLong(currentJoinTime);
quitsTimeInMilliseconds = Long.parseLong(currentQuitTime);
sessionLengthInMilliseconds = quitsTimeInMilliseconds - joinsTimeInMilliseconds;
String hours = "" + sessionLengthInMilliseconds/1000/60/60;
String minutes = "" + (sessionLengthInMilliseconds/1000/60)%60;
if (hours.length() < 2)
hours = "0" + hours;
if (hours.length() < 3)
hours = "0" + hours;
if (minutes.length() < 2)
minutes = "0" + minutes;
int columnPadding = 19-currentNick.length();
String columnPaddingString = " ";
for (int j = 0; j < columnPadding; j++)
columnPaddingString = columnPaddingString + " ";
calculatedSessionDurations.add(sessionLengthInMilliseconds + " " + currentNick + columnPaddingString + " online " + hours + " hours " + minutes + " minutes " + currentQuitReason);
} else {
System.out.println("\r\nError: Unexpected entry in logfile: " + quitsEntry);
System.exit(1);
}
}
return calculatedSessionDurations;
}
private void formatAndOutput(ArrayList sortedSessions) {
String quitReason = null;
for (int i = 0; i < sortedSessions.size(); i++) {
String entry = (String) sortedSessions.get(i);
Pattern p = Pattern.compile("^[\\d]+ ([^ ]+ +online [\\d]+ hours [\\d]+ minutes) (.*)$");
Matcher m = p.matcher(entry);
if (m.matches()) {
if (quitReason == null) {
quitReason = m.group(2);
System.out.println("\r\nQUIT: " + ((m.group(2).equals("")) ? "No Reason Given" : quitReason) + "\r\n");
}
String tempQuitReason = m.group(2);
String tempSession = m.group(1);
if (tempQuitReason.equals(quitReason)) {
System.out.println(" " + tempSession);
} else {
quitReason = null;
i -= 1;
continue;
}
} else {
System.out.println("\r\nError: Unexpected entry in logfile: " + entry);
System.exit(1);
}
}
System.out.println("\r\n");
}
private void formatAndOutputByDuration(ArrayList sortedSessions) {
System.out.println("\r\n");
for (int i = 0; i < sortedSessions.size(); i++) {
String[] columns = ((String) sortedSessions.get(i)).split(" ", 2);
System.out.println(columns[1]);
}
System.out.println("\r\n");
}
private ArrayList readLogfile(String logfile) {
ArrayList log = new ArrayList();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(logfile)));
for (String line; (line = in.readLine()) != null; )
log.add(line);
in.close();
} catch (FileNotFoundException e) {
System.out.println("\r\nError: Can't find logfile '" + logfile + "'.\r\n");
System.exit(1);
} catch (IOException e) {
System.out.println("\r\nError: Can't read logfile '" + logfile + "'.\r\n");
System.exit(1);
}
return log;
}
/*
* Performs an odd-even transposition sort.
*/
private ArrayList sortSessionsByDuration(ArrayList calculatedSessionDurations) {
for (int i = 0; i < calculatedSessionDurations.size()/2; i++) {
for (int j = 0; j+1 < calculatedSessionDurations.size(); j += 2) {
String[] currentDurationString = ((String) calculatedSessionDurations.get(j)).split(" ", 2);
long currentDuration = Long.parseLong(currentDurationString[0]);
String[] nextDurationString = ((String) calculatedSessionDurations.get(j+1)).split(" ", 2);
long nextDuration = Long.parseLong(nextDurationString[0]);
if (currentDuration > nextDuration) {
calculatedSessionDurations.add(j, calculatedSessionDurations.get(j+1));
calculatedSessionDurations.remove(j+2);
}
}
for (int j = 1; j+1 < calculatedSessionDurations.size(); j += 2) {
String[] currentDurationString = ((String) calculatedSessionDurations.get(j)).split(" ", 2);
long currentDuration = Long.parseLong(currentDurationString[0]);
String[] nextDurationString = ((String) calculatedSessionDurations.get(j+1)).split(" ", 2);
long nextDuration = Long.parseLong(nextDurationString[0]);
if (currentDuration > nextDuration) {
calculatedSessionDurations.add(j, calculatedSessionDurations.get(j+1));
calculatedSessionDurations.remove(j+2);
}
}
}
return calculatedSessionDurations;
}
private ArrayList sortSessionsByNick(ArrayList sortedSessionsByTime) {
ArrayList sortedSessionsByNick = new ArrayList();
while (sortedSessionsByTime.size() != 0) {
String entry = (String) sortedSessionsByTime.get(0);
String[] entryFields = entry.split(" ");
String currentNick = entryFields[2];
sortedSessionsByNick.add(entry);
sortedSessionsByNick.add(sortedSessionsByTime.get(1));
sortedSessionsByTime.remove(0);
sortedSessionsByTime.remove(0);
for (int i = 0; i+1 < sortedSessionsByTime.size(); i += 2) {
String nextEntry = (String) sortedSessionsByTime.get(i);
String[] nextEntryFields = nextEntry.split(" ");
if (nextEntryFields[2].equals(currentNick)) {
sortedSessionsByNick.add(nextEntry);
sortedSessionsByNick.add(sortedSessionsByTime.get(i+1));
sortedSessionsByTime.remove(i);
sortedSessionsByTime.remove(i);
i -= 2;
}
}
}
return sortedSessionsByNick;
}
private ArrayList sortSessionsByQuitReason(ArrayList sortedSessionsByNick) {
ArrayList sortedSessionsByQuitReason = new ArrayList();
while (sortedSessionsByNick.size() != 0) {
String entry = (String) sortedSessionsByNick.get(1);
Pattern p = Pattern.compile("^[^ ]+ [^ ]+ [^ ]+ (.*)$");
Matcher m = p.matcher(entry);
if (m.matches()) {
String currentQuitReason = m.group(1);
sortedSessionsByQuitReason.add(sortedSessionsByNick.get(0));
sortedSessionsByQuitReason.add(entry);
sortedSessionsByNick.remove(0);
sortedSessionsByNick.remove(0);
for (int i = 0; i+1 < sortedSessionsByNick.size(); i += 2) {
String nextEntry = (String) sortedSessionsByNick.get(i+1);
Pattern p2 = Pattern.compile("^[^ ]+ [^ ]+ [^ ]+ (.*)$");
Matcher m2 = p2.matcher(nextEntry);
if (m2.matches()) {
String nextQuitReason = m2.group(1);
if (nextQuitReason.equals(currentQuitReason)) {
sortedSessionsByQuitReason.add(sortedSessionsByNick.get(i));
sortedSessionsByQuitReason.add(nextEntry);
sortedSessionsByNick.remove(i);
sortedSessionsByNick.remove(i);
i -= 2;
}
} else {
System.out.println("\r\nError: Unexpected entry in logfile: " + nextEntry);
System.exit(1);
}
}
} else {
System.out.println("\r\nError: Unexpected entry in logfile: " + entry);
System.exit(1);
}
}
return sortedSessionsByQuitReason;
}
/**
* Sessions terminated with "parts" messages instead of "quits" are filtered
* out.
*/
private ArrayList sortSessionsByTime(ArrayList log) {
ArrayList sortedSessionsByTime = new ArrayList();
mainLoop:
while (log.size() > 0) {
String entry = (String) log.get(0);
String[] entryFields = entry.split(" ");
if (entryFields[1].equals("quits") && !entryFields[1].equals("joins")) {
/*
* Discard entry. The specified log either doesn't contain
* the corresponding "joins" time for this quit entry or the
* entry is a "parts" or unknown message, and in both cases
* the entry's data is useless.
*/
log.remove(0);
continue;
}
for (int i = 1; i < log.size(); i++) { // Find corresponding "quits" entry.
String tempEntry = (String) log.get(i);
String[] tempEntryFields = tempEntry.split(" ");
if (tempEntryFields[2].equals(entryFields[2])) { // Check if the nick fields for the two entries match.
if (!tempEntryFields[1].equals("quits")) {
if (tempEntryFields[1].equals("joins")) { // Don't discard a subsequent "joins" entry.
log.remove(0);
continue mainLoop;
}
log.remove(i);
continue;
}
sortedSessionsByTime.add(entry);
sortedSessionsByTime.add(tempEntry);
log.remove(i);
break;
}
}
/*
* Discard "joins" entry. The specified log doesn't contain the
* corresponding "quits" time for this entry so the entry's
* data is useless.
*/
log.remove(0);
}
return sortedSessionsByTime;
}
}

View File

@ -1,48 +0,0 @@
/*
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
*
* Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by the Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "log4j" and "Apache Software Foundation" must not be used to
* endorse or promote products derived from this software without prior
* written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache", nor may
* "Apache" appear in their name, without prior written permission of the
* Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the
* Apache Software Foundation, please see <http://www.apache.org/>.
*
*/

View File

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -1 +0,0 @@
java -cp .;log4j-1.2.8.jar;pircbot.jar Bogobot

View File

@ -1,101 +0,0 @@
#####
# Bogobot user configuration
#####
###
# The bot's nick and backup nick. You will probably want to register these with
# the IRC server's NickServ.(a NickServ interface is forthcoming).
#
botPrimaryNick=somebot
botSecondaryNick=somebot_
###
# The bot's password required by Nickserv service's identify command.
# You have to register the nickname yourself first, the bot will not.
#
botNickservPassword=
###
# The bot's username. Appears in the whois replies
#
botUsername=somebot
#####
# The bot owner's nick and backup nick. One of these must match the owner's
# currently-used nick or else remote shutdown will not be possible. You will
# probably want to register these with the IRC server's NickServ.
#
ownerPrimaryNick=somenick
ownerSecondaryNick=somenick_
###
# The bot will disconnect and shut down when sent this password via private
# message (aka query) from either of the owner nicks specified above. DO NOT USE
# THIS DEFAULT VALUE!
#
botShutdownPassword=take off eh
###
# The server, channel, and port the bot will connect to.
#
ircChannel=#i2p-chat
ircServer=irc.duck.i2p
ircServerPort=6668
###
# Set to "true" to enable logging, else "false" (but don't use quotation marks).
#
isLoggerEnabled=true
###
# Restrict logging of joins and parts on the user hostname.
# Leave empty to log all of them
# Prepend with a @ for a perfect match
# Otherwise, specify the required end of the user hostname
#
loggedHostnamePattern=@free.duck.i2p
###
# The prefix to be used for the filenames of logs.
#
logFilePrefix=irc.duck.i2p.i2p-chat
###
# How often the logs should be rotated. Either "daily", "weekly", or "monthly"
# (but don't use quotation marks).
#
logFileRotationInterval=daily
###
# Set to "true" to enable the regular round-trip delay computation,
# else "false" (but don't use quotation marks).
#
isRoundTripDelayEnabled=false
###
# How often should the round-trip delay be recorded.
# (in seconds)
#
roundTripDelayPeriod=300
###
# Set to "true" to enable the userlist command, else "false" (but don't use
# quotation marks).
#
isUserlistCommandEnabled=true
###
# The userlist trigger command to listen for. It is a good idea to prefix
# triggers with some non-alphanumeric character in order to avoid accidental
# trigger use during normal channel conversation. In most cases you will
# probably want to choose a unique trigger here that no other bots in the
# channel will respond to.
#
userlistCommandTrigger=!who
###
# The number of seconds to rest after replying to a userlist command issued by
# a user in the channel. The bot will ignore subsequent userlist commands during
# this period. This helps prevent flooding.
#
commandAntiFloodInterval=60

View File

@ -1,2 +0,0 @@
#!/bin/sh
java -cp .:log4j-1.2.8.jar:pircbot.jar Bogobot

View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************** -->
<!-- bogobot - A simple join/part stats logger bot for I2P IRC. -->
<!-- -->
<!-- build-eclipse.xml -->
<!-- 2004 The I2P Project -->
<!-- http://www.i2p.net -->
<!-- This code is public domain. -->
<!-- -->
<!-- authors: hypercubus, oOo -->
<!-- version 0.4 -->
<!-- ********************************************************** -->
<project basedir="." default="dist" name="Bogobot">
<!-- init:
Create distribution directory if missing and initialize time stamp for
archive naming -->
<target name="init">
<mkdir dir="dist" />
<tstamp>
<format pattern="yyyy-MM-dd" property="DSTAMP" />
</tstamp>
</target>
<!-- dist.bin:
Create the binary distribution archive -->
<target depends="init" description="Create the binary distribution archive" name="dist.bin">
<zip destfile="dist/Bogobot_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>
<!-- dist.source:
Create the source distribution archive -->
<target depends="init" description="Create the source distribution archive" name="dist.source">
<zip destfile="dist/Bogobot_source_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>
<!-- dist:
Create both the binary and source distribution archives -->
<target depends="dist.bin,dist.source" description="Create both the binary and source distribution archives" name="dist">
<echo message="Successfully created binary and source distribution archives in directory &apos;dist&apos;." />
</target>
<!-- clean:
Delete all class files and temporary directories -->
<target description="Delete all class files and temporary directories" name="clean">
<delete>
<fileset dir="${basedir}" includes="**/*.class" />
</delete>
<echo message="Clean successful." />
</target>
</project>

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************** -->
<!-- bogobot - A simple join/part stats logger bot for I2P IRC. -->
<!-- -->
<!-- build.xml -->
<!-- 2004 The I2P Project -->
<!-- http://www.i2p.net -->
<!-- This code is public domain. -->
<!-- -->
<!-- authors: hypercubus, oOo -->
<!-- version 0.4 -->
<!-- ********************************************************** -->
<project basedir="." default="compile" name="Bogobot">
<!-- init:
Create distribution directory if missing and initialize time stamp for
archive naming -->
<target name="init">
<mkdir dir="dist" />
<tstamp>
<format pattern="yyyy-MM-dd" property="DSTAMP" />
</tstamp>
</target>
<!-- compile:
Compile source code -->
<target depends="init" description="Compile source code" name="compile">
<javac classpath="${basedir};log4j-1.2.8.jar;pircbot.jar" source="1.4" srcdir="." />
</target>
<!-- dist.bin:
Create the binary distribution archive -->
<target depends="init,compile" description="Create the binary distribution archive" name="dist.bin">
<zip destfile="dist/Bogobot_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.class Bogobot$BogobotTickTask.class bogobot.sh Bogoparser.class LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>
<!-- dist.source:
Create the source distribution archive -->
<target depends="init" description="Create the source distribution archive" name="dist.source">
<zip destfile="dist/Bogobot_source_${DSTAMP}.zip">
<zipfileset dir="${basedir}" includes="bogobot.bat bogobot.config Bogobot.java bogobot.sh Bogoparser.java build.xml build_eclipse.xml LICENSE_log4j.txt LICENSE_pircbot.txt log4j-1.2.8.jar pircbot.jar" />
</zip>
</target>
<!-- dist:
Create both the binary and source distribution archives -->
<target depends="dist.bin,dist.source" description="Create both the binary and source distribution archives" name="dist">
<echo message="Successfully created binary and source distribution archives in directory &apos;dist&apos;." />
</target>
<!-- clean:
Delete all class files and temporary directories -->
<target description="Delete all class files and temporary directories" name="clean">
<delete>
<fileset dir="${basedir}" includes="**/*.class" />
</delete>
<echo message="Clean successful." />
</target>
</project>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
i2psnark.dir=i2psnark

View File

@ -7,12 +7,30 @@
<ant dir="../../streaming/java/" target="build" />
<!-- streaming will build ministreaming and core -->
</target>
<target name="compile">
<condition property="depend.available">
<typefound name="depend" />
</condition>
<target name="depend" if="depend.available">
<depend
cache="../../../build"
srcdir="./src"
destdir="./build/obj" >
<!-- Depend on classes instead of jars where available -->
<classpath>
<pathelement location="../../../core/java/build/obj" />
<pathelement location="../../../router/java/build/obj" />
<pathelement location="../../ministreaming/java/build/obj" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
</classpath>
</depend>
</target>
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true" deprecation="on" source="1.3" target="1.3"
debug="true" deprecation="on" source="1.5" target="1.5"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../../router/java/build/router.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>
@ -36,7 +54,7 @@
</zip>
</target>
<target name="standalone_prep" depends="war">
<javac debug="true" deprecation="on" source="1.3" target="1.3"
<javac debug="true" deprecation="on" source="1.5" target="1.5"
destdir="./build" srcdir="src/" includes="org/klomp/snark/web/RunStandalone.java" >
<classpath>
<pathelement location="../../jetty/jettylib/commons-logging.jar" />

View File

@ -28,7 +28,7 @@ import java.io.OutputStream;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -36,17 +36,16 @@ import net.i2p.util.Log;
*/
public class ConnectionAcceptor implements Runnable
{
private static final ConnectionAcceptor _instance = new ConnectionAcceptor();
public static final ConnectionAcceptor instance() { return _instance; }
private Log _log = new Log(ConnectionAcceptor.class);
private I2PServerSocket serverSocket;
private PeerAcceptor peeracceptor;
private Thread thread;
private I2PSnarkUtil _util;
private boolean stop;
private boolean socketChanged;
private ConnectionAcceptor() {}
public ConnectionAcceptor(I2PSnarkUtil util) { _util = util; }
public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) {
if (serverSocket != socket) {
@ -56,29 +55,30 @@ public class ConnectionAcceptor implements Runnable
stop = false;
socketChanged = true;
if (thread == null) {
thread = new I2PThread(this, "I2PSnark acceptor");
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
}
}
}
public ConnectionAcceptor(I2PServerSocket serverSocket,
public ConnectionAcceptor(I2PSnarkUtil util, I2PServerSocket serverSocket,
PeerAcceptor peeracceptor)
{
this.serverSocket = serverSocket;
this.peeracceptor = peeracceptor;
_util = util;
socketChanged = false;
stop = false;
thread = new I2PThread(this, "I2PSnark acceptor");
thread = new I2PAppThread(this, "I2PSnark acceptor");
thread.setDaemon(true);
thread.start();
}
public void halt()
{
if (true) throw new RuntimeException("wtf");
if (stop) return;
stop = true;
I2PServerSocket ss = serverSocket;
@ -95,7 +95,7 @@ public class ConnectionAcceptor implements Runnable
}
public void restart() {
serverSocket = I2PSnarkUtil.instance().getServerSocket();
serverSocket = _util.getServerSocket();
socketChanged = true;
Thread t = thread;
if (t != null)
@ -116,10 +116,12 @@ public class ConnectionAcceptor implements Runnable
socketChanged = false;
}
while ( (serverSocket == null) && (!stop)) {
serverSocket = I2PSnarkUtil.instance().getServerSocket();
serverSocket = _util.getServerSocket();
if (serverSocket == null)
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
}
if(stop)
break;
try
{
I2PSocket socket = serverSocket.accept();
@ -127,27 +129,27 @@ public class ConnectionAcceptor implements Runnable
if (socketChanged) {
continue;
} else {
I2PServerSocket ss = I2PSnarkUtil.instance().getServerSocket();
I2PServerSocket ss = _util.getServerSocket();
if (ss != serverSocket) {
serverSocket = ss;
socketChanged = true;
}
}
} else {
Thread t = new I2PThread(new Handler(socket), "Connection-" + socket);
Thread t = new I2PAppThread(new Handler(socket), "Connection-" + socket);
t.start();
}
}
catch (I2PException ioe)
{
if (!socketChanged) {
Snark.debug("Error while accepting: " + ioe, Snark.ERROR);
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
stop = true;
}
}
catch (IOException ioe)
{
Snark.debug("Error while accepting: " + ioe, Snark.ERROR);
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
stop = true;
}
}
@ -159,7 +161,6 @@ public class ConnectionAcceptor implements Runnable
}
catch (I2PException ignored) { }
throw new RuntimeException("wtf");
}
private class Handler implements Runnable {

View File

@ -30,4 +30,8 @@ public interface CoordinatorListener
* Called when the PeerCoordinator notices a change in the state of a peer.
*/
void peerChange(PeerCoordinator coordinator, Peer peer);
public boolean overUploadLimit(int uploaders);
public boolean overUpBWLimit();
public boolean overUpBWLimit(long total);
}

View File

@ -2,12 +2,15 @@ package org.klomp.snark;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@ -25,12 +28,13 @@ import net.i2p.util.SimpleTimer;
/**
* I2P specific helpers for I2PSnark
* We use this class as a sort of context for i2psnark
* so we can run multiple instances of single Snarks
* (but not multiple SnarkManagers, it is still static)
*/
public class I2PSnarkUtil {
private I2PAppContext _context;
private Log _log;
private static I2PSnarkUtil _instance = new I2PSnarkUtil();
public static I2PSnarkUtil instance() { return _instance; }
private boolean _shouldProxy;
private String _proxyHost;
@ -43,9 +47,17 @@ public class I2PSnarkUtil {
private Set _shitlist;
private int _maxUploaders;
private int _maxUpBW;
private int _maxConnections;
private I2PSnarkUtil() {
_context = I2PAppContext.getGlobalContext();
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
public static final int MAX_CONNECTIONS = 16; // per torrent
public I2PSnarkUtil(I2PAppContext ctx) {
_context = ctx;
_log = _context.logManager().getLog(Snark.class);
_opts = new HashMap();
setProxy("127.0.0.1", 4444);
@ -53,6 +65,8 @@ public class I2PSnarkUtil {
_shitlist = new HashSet(64);
_configured = false;
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
_maxUpBW = DEFAULT_MAX_UP_BW;
_maxConnections = MAX_CONNECTIONS;
}
/**
@ -76,8 +90,10 @@ public class I2PSnarkUtil {
public boolean configured() { return _configured; }
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
_i2cpHost = i2cpHost;
_i2cpPort = i2cpPort;
if (i2cpHost != null)
_i2cpHost = i2cpHost;
if (i2cpPort > 0)
_i2cpPort = i2cpPort;
if (opts != null)
_opts.putAll(opts);
_configured = true;
@ -93,6 +109,11 @@ public class I2PSnarkUtil {
_configured = true;
}
public void setMaxConnections(int limit) {
_maxConnections = limit;
_configured = true;
}
public String getI2CPHost() { return _i2cpHost; }
public int getI2CPPort() { return _i2cpPort; }
public Map getI2CPOptions() { return _opts; }
@ -101,6 +122,7 @@ public class I2PSnarkUtil {
public boolean getEepProxySet() { return _shouldProxy; }
public int getMaxUploaders() { return _maxUploaders; }
public int getMaxUpBW() { return _maxUpBW; }
public int getMaxConnections() { return _maxConnections; }
/**
* Connect to the router, if we aren't already
@ -185,9 +207,11 @@ public class I2PSnarkUtil {
out = File.createTempFile("i2psnark", "url", new File("."));
} catch (IOException ioe) {
ioe.printStackTrace();
out.delete();
if (out != null)
out.delete();
return null;
}
out.deleteOnExit();
String fetchURL = url;
if (rewrite)
fetchURL = rewriteAnnounce(url);
@ -222,6 +246,28 @@ public class I2PSnarkUtil {
}
return "unknown";
}
/** Base64 only - static (no naming service) */
static Destination getDestinationFromBase64(String ip) {
if (ip == null) return null;
if (ip.endsWith(".i2p")) {
if (ip.length() < 520)
return null;
try {
return new Destination(ip.substring(0, ip.length()-4)); // sans .i2p
} catch (DataFormatException dfe) {
return null;
}
} else {
try {
return new Destination(ip);
} catch (DataFormatException dfe) {
return null;
}
}
}
/** Base64 Hash or Hash.i2p or name.i2p using naming service */
Destination getDestination(String ip) {
if (ip == null) return null;
if (ip.endsWith(".i2p")) {
@ -266,7 +312,40 @@ public class I2PSnarkUtil {
return rv;
}
public String getOpenTrackerString() {
String rv = (String) _opts.get(PROP_OPENTRACKERS);
if (rv == null)
return DEFAULT_OPENTRACKERS;
return rv;
}
/** comma delimited list open trackers to use as backups */
/** sorted map of name to announceURL=baseURL */
public List getOpenTrackers() {
if (!shouldUseOpenTrackers())
return null;
List rv = new ArrayList(1);
String trackers = getOpenTrackerString();
StringTokenizer tok = new StringTokenizer(trackers, ", ");
while (tok.hasMoreTokens())
rv.add(tok.nextToken());
if (rv.size() <= 0)
return null;
return rv;
}
public boolean shouldUseOpenTrackers() {
String rv = (String) _opts.get(PROP_USE_OPENTRACKERS);
if (rv == null)
return DEFAULT_USE_OPENTRACKERS;
return Boolean.valueOf(rv).booleanValue();
}
/** hook between snark's logger and an i2p log */
void debug(String msg, int snarkDebugLevel) {
debug(msg, snarkDebugLevel, null);
}
void debug(String msg, int snarkDebugLevel, Throwable t) {
if (t instanceof OutOfMemoryError) {
try { Thread.sleep(100); } catch (InterruptedException ie) {}

View File

@ -408,7 +408,7 @@ public class MetaInfo
info.put("name", name);
if (name_utf8 != null)
info.put("name.utf-8", name_utf8);
info.put("piece length", new Integer(piece_length));
info.put("piece length", Integer.valueOf(piece_length));
info.put("pieces", piece_hashes);
if (files == null)
info.put("length", new Long(length));
@ -434,9 +434,10 @@ public class MetaInfo
Map info = createInfoMap();
StringBuffer buf = new StringBuffer(128);
buf.append("info: ");
for (Iterator iter = info.keySet().iterator(); iter.hasNext(); ) {
String key = (String)iter.next();
Object val = info.get(key);
for (Iterator iter = info.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
Object val = entry.getValue();
buf.append(key).append('=');
if (val instanceof byte[])
buf.append(Base64.encode((byte[])val, true));

View File

@ -173,7 +173,7 @@ public class Peer implements Comparable
* If the given BitField is non-null it is send to the peer as first
* message.
*/
public void runConnection(PeerListener listener, BitField bitfield)
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield)
{
if (state != null)
throw new IllegalStateException("Peer already started");
@ -184,7 +184,7 @@ public class Peer implements Comparable
// Do we need to handshake?
if (din == null)
{
sock = I2PSnarkUtil.instance().connect(peerID);
sock = util.connect(peerID);
_log.debug("Connected to " + peerID + ": " + sock);
if ((sock == null) || (sock.isClosed())) {
throw new IOException("Unable to reach " + peerID);

View File

@ -32,12 +32,14 @@ import java.util.TimerTask;
*/
class PeerCheckerTask extends TimerTask
{
private final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
private final PeerCoordinator coordinator;
public I2PSnarkUtil _util;
PeerCheckerTask(PeerCoordinator coordinator)
PeerCheckerTask(I2PSnarkUtil util, PeerCoordinator coordinator)
{
_util = util;
this.coordinator = coordinator;
}
@ -102,8 +104,8 @@ class PeerCheckerTask extends TimerTask
peer.setRateHistory(upload, download);
peer.resetCounters();
Snark.debug(peer + ":", Snark.DEBUG);
Snark.debug(" ul: " + upload/KILOPERSECOND
_util.debug(peer + ":", Snark.DEBUG);
_util.debug(" ul: " + upload/KILOPERSECOND
+ " dl: " + download/KILOPERSECOND
+ " i: " + peer.isInterested()
+ " I: " + peer.isInteresting()
@ -129,7 +131,7 @@ class PeerCheckerTask extends TimerTask
// Check if it still wants pieces from us.
if (!peer.isInterested())
{
Snark.debug("Choke uninterested peer: " + peer,
_util.debug("Choke uninterested peer: " + peer,
Snark.INFO);
peer.setChoking(true);
uploaders--;
@ -141,7 +143,7 @@ class PeerCheckerTask extends TimerTask
}
else if (overBWLimitChoke)
{
Snark.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
_util.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
Snark.INFO);
peer.setChoking(true);
uploaders--;
@ -155,7 +157,7 @@ class PeerCheckerTask extends TimerTask
else if (peer.isInteresting() && peer.isChoked())
{
// If they are choking us make someone else a downloader
Snark.debug("Choke choking peer: " + peer, Snark.DEBUG);
_util.debug("Choke choking peer: " + peer, Snark.DEBUG);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -168,7 +170,7 @@ class PeerCheckerTask extends TimerTask
else if (!peer.isInteresting() && !coordinator.completed())
{
// If they aren't interesting make someone else a downloader
Snark.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
_util.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
peer.setChoking(true);
uploaders--;
coordinator.uploaders--;
@ -183,7 +185,7 @@ class PeerCheckerTask extends TimerTask
&& download == 0)
{
// We are downloading but didn't receive anything...
Snark.debug("Choke downloader that doesn't deliver:"
_util.debug("Choke downloader that doesn't deliver:"
+ peer, Snark.DEBUG);
peer.setChoking(true);
uploaders--;
@ -222,7 +224,7 @@ class PeerCheckerTask extends TimerTask
|| uploaders > uploadLimit)
&& worstDownloader != null)
{
Snark.debug("Choke worst downloader: " + worstDownloader,
_util.debug("Choke worst downloader: " + worstDownloader,
Snark.DEBUG);
worstDownloader.setChoking(true);
@ -247,6 +249,10 @@ class PeerCheckerTask extends TimerTask
// store the rates
coordinator.setRateHistory(uploaded, downloaded);
// close out unused files, but we don't need to do it every time
if (random.nextInt(4) == 0)
coordinator.getStorage().cleanRAFs();
}
}
}

View File

@ -26,7 +26,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer;
@ -58,7 +58,7 @@ class PeerConnectionOut implements Runnable
}
public void startup() {
thread = new I2PThread(this, "Snark sender " + _id + ": " + peer);
thread = new I2PAppThread(this, "Snark sender " + _id + ": " + peer);
thread.start();
}

View File

@ -29,7 +29,7 @@ import java.util.List;
import java.util.Random;
import java.util.Timer;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -44,7 +44,6 @@ public class PeerCoordinator implements PeerListener
// package local for access by CheckDownLoadersTask
final static long CHECK_PERIOD = 40*1000; // 40 seconds
final static int MAX_CONNECTIONS = 16;
final static int MAX_UPLOADERS = 6;
// Approximation of the number of current uploaders.
@ -77,13 +76,15 @@ public class PeerCoordinator implements PeerListener
private boolean halted = false;
private final CoordinatorListener listener;
public I2PSnarkUtil _util;
public String trackerProblems = null;
public int trackerSeenPeers = 0;
public PeerCoordinator(byte[] id, MetaInfo metainfo, Storage storage,
public PeerCoordinator(I2PSnarkUtil util, byte[] id, MetaInfo metainfo, Storage storage,
CoordinatorListener listener, Snark torrent)
{
_util = util;
this.id = id;
this.metainfo = metainfo;
this.storage = storage;
@ -96,7 +97,7 @@ public class PeerCoordinator implements PeerListener
// Randomize the first start time so multiple tasks are spread out,
// this will help the behavior with global limits
Random r = new Random();
timer.schedule(new PeerCheckerTask(this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
}
// only called externally from Storage after the double-check fails
@ -235,7 +236,7 @@ public class PeerCoordinator implements PeerListener
{
synchronized(peers)
{
return !halted && peers.size() < MAX_CONNECTIONS;
return !halted && peers.size() < _util.getMaxConnections();
}
}
@ -293,7 +294,7 @@ public class PeerCoordinator implements PeerListener
peer.disconnect(false); // Don't deregister this connection/peer.
}
// This is already checked in addPeer() but we could have gone over the limit since then
else if (peers.size() >= MAX_CONNECTIONS)
else if (peers.size() >= _util.getMaxConnections())
{
if (_log.shouldLog(Log.WARN))
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
@ -349,7 +350,7 @@ public class PeerCoordinator implements PeerListener
peersize = peers.size();
// This isn't a strict limit, as we may have several pending connections;
// thus there is an additional check in connected()
need_more = (!peer.isConnected()) && peersize < MAX_CONNECTIONS;
need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
// Check if we already have this peer before we build the connection
Peer old = peerIDInList(peer.getPeerID(), peers);
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
@ -366,18 +367,18 @@ public class PeerCoordinator implements PeerListener
{
public void run()
{
peer.runConnection(listener, bitfield);
peer.runConnection(_util, listener, bitfield);
}
};
String threadName = peer.toString();
new I2PThread(r, threadName).start();
new I2PAppThread(r, threadName).start();
return true;
}
if (_log.shouldLog(Log.DEBUG)) {
if (peer.isConnected())
_log.info("Add peer already connected: " + peer);
else
_log.info("Connections: " + peersize + "/" + MAX_CONNECTIONS
_log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
+ " not accepting extra peer: " + peer);
}
return false;
@ -846,7 +847,7 @@ public class PeerCoordinator implements PeerListener
*/
public int allowedUploaders()
{
if (Snark.overUploadLimit(uploaders)) {
if (listener != null && listener.overUploadLimit(uploaders)) {
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Over limit, uploaders was: " + uploaders);
return uploaders - 1;
@ -858,12 +859,16 @@ public class PeerCoordinator implements PeerListener
public boolean overUpBWLimit()
{
return Snark.overUpBWLimit();
if (listener != null)
return listener.overUpBWLimit();
return false;
}
public boolean overUpBWLimit(long total)
{
return Snark.overUpBWLimit(total * 1000 / CHECK_PERIOD);
if (listener != null)
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
return false;
}
}

View File

@ -12,11 +12,9 @@ import java.util.Set;
* from it there too)
*/
public class PeerCoordinatorSet {
private static final PeerCoordinatorSet _instance = new PeerCoordinatorSet();
public static final PeerCoordinatorSet instance() { return _instance; }
private Set _coordinators;
private PeerCoordinatorSet() {
public PeerCoordinatorSet() {
_coordinators = new HashSet();
}

View File

@ -72,7 +72,7 @@ public class PeerID implements Comparable
bevalue = (BEValue)m.get("ip");
if (bevalue == null)
throw new InvalidBEncodingException("ip missing");
address = I2PSnarkUtil.instance().getDestination(bevalue.getString());
address = I2PSnarkUtil.getDestinationFromBase64(bevalue.getString());
if (address == null)
throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]");

View File

@ -30,7 +30,7 @@ import java.util.TimerTask;
class PeerMonitorTask extends TimerTask
{
final static long MONITOR_PERIOD = 10 * 1000; // Ten seconds.
private final long KILOPERSECOND = 1024 * (MONITOR_PERIOD / 1000);
private static final long KILOPERSECOND = 1024 * (MONITOR_PERIOD / 1000);
private final PeerCoordinator coordinator;

View File

@ -28,12 +28,15 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;
import net.i2p.I2PAppContext;
import net.i2p.router.client.ClientManagerFacadeImpl;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
@ -102,7 +105,7 @@ public class Snark
public void outOfMemory(OutOfMemoryError err) {
try {
err.printStackTrace();
I2PSnarkUtil.instance().debug("OOM in the snark", Snark.ERROR, err);
System.out.println("OOM in the snark" + err);
} catch (Throwable t) {
System.out.println("OOM in the OOM");
}
@ -225,7 +228,7 @@ public class Snark
}
catch(IOException ioe)
{
debug("ERROR while reading stdin: " + ioe, ERROR);
System.out.println("ERROR while reading stdin: " + ioe);
}
// Explicit shutdown.
@ -234,6 +237,7 @@ public class Snark
}
}
public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections";
public String torrent;
public MetaInfo meta;
public Storage storage;
@ -244,19 +248,59 @@ public class Snark
public CompleteListener completeListener;
public boolean stopped;
byte[] id;
public I2PSnarkUtil _util;
private PeerCoordinatorSet _peerCoordinatorSet;
Snark(String torrent, String ip, int user_port,
/** from main() via parseArguments() single torrent */
Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
StorageListener slistener, CoordinatorListener clistener) {
this(torrent, ip, user_port, slistener, clistener, true, ".");
this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
}
Snark(String torrent, String ip, int user_port,
StorageListener slistener, CoordinatorListener clistener, boolean start, String rootDir)
/** single torrent - via router */
public Snark(I2PAppContext ctx, Properties opts, String torrent,
StorageListener slistener, boolean start, String rootDir) {
this(new I2PSnarkUtil(ctx), torrent, null, -1, slistener, null, null, null, null, false, rootDir);
String host = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_HOST);
int port = 0;
String s = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT);
if (s != null) {
try {
port = Integer.parseInt(s);
} catch (NumberFormatException nfe) {}
}
_util.setI2CPConfig(host, port, opts);
s = opts.getProperty(SnarkManager.PROP_UPBW_MAX);
if (s != null) {
try {
int v = Integer.parseInt(s);
_util.setMaxUpBW(v);
} catch (NumberFormatException nfe) {}
}
s = opts.getProperty(PROP_MAX_CONNECTIONS);
if (s != null) {
try {
int v = Integer.parseInt(s);
_util.setMaxConnections(v);
} catch (NumberFormatException nfe) {}
}
if (start)
this.startTorrent();
}
/** multitorrent */
public Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
StorageListener slistener, CoordinatorListener clistener,
CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet,
ConnectionAcceptor connectionAcceptor, boolean start, String rootDir)
{
if (slistener == null)
slistener = this;
if (clistener == null)
clistener = this;
completeListener = complistener;
_util = util;
_peerCoordinatorSet = peerCoordinatorSet;
acceptor = connectionAcceptor;
this.torrent = torrent;
this.rootDataDir = rootDir;
@ -289,7 +333,7 @@ public class Snark
while (i < 20)
id[i++] = (byte)random.nextInt(256);
Snark.debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
int port;
IOException lastException = null;
@ -298,9 +342,9 @@ public class Snark
* If we are starting,
* startTorrent() will force a connect.
*
boolean ok = I2PSnarkUtil.instance().connect();
boolean ok = util.connect();
if (!ok) fatal("Unable to connect to I2P");
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket();
I2PServerSocket serversocket = util.getServerSocket();
if (serversocket == null)
fatal("Unable to listen for I2P connections");
else {
@ -312,16 +356,16 @@ public class Snark
// Figure out what the torrent argument represents.
meta = null;
File f = null;
InputStream in = null;
try
{
InputStream in = null;
f = new File(torrent);
if (f.exists())
in = new FileInputStream(f);
else
{
activity = "Getting torrent";
File torrentFile = I2PSnarkUtil.instance().get(torrent, 3);
File torrentFile = _util.get(torrent, 3);
if (torrentFile == null) {
fatal("Unable to fetch " + torrent);
if (false) return; // never reached - fatal(..) throws
@ -345,7 +389,7 @@ public class Snark
/*
{
// Try to create a new metainfo file
Snark.debug
debug
("Trying to create metainfo torrent for '" + torrent + "'",
NOTICE);
try
@ -364,8 +408,11 @@ public class Snark
*/
else
fatal("Cannot open '" + torrent + "'", ioe);
}
} finally {
if (in != null)
try { in.close(); } catch (IOException ioe) {}
}
debug(meta.toString(), INFO);
// When the metainfo torrent was created from an existing file/dir
@ -375,8 +422,14 @@ public class Snark
try
{
activity = "Checking storage";
storage = new Storage(meta, slistener);
storage.check(rootDataDir);
storage = new Storage(_util, meta, slistener);
if (completeListener != null) {
storage.check(rootDataDir,
completeListener.getSavedTorrentTime(this),
completeListener.getSavedTorrentBitField(this));
} else {
storage.check(rootDataDir);
}
// have to figure out when to reopen
// if (!start)
// storage.close();
@ -410,10 +463,10 @@ public class Snark
* Start up contacting peers and querying the tracker
*/
public void startTorrent() {
boolean ok = I2PSnarkUtil.instance().connect();
boolean ok = _util.connect();
if (!ok) fatal("Unable to connect to I2P");
if (coordinator == null) {
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket();
I2PServerSocket serversocket = _util.getServerSocket();
if (serversocket == null)
fatal("Unable to listen for I2P connections");
else {
@ -422,12 +475,20 @@ public class Snark
}
debug("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient", NOTICE);
activity = "Collecting pieces";
coordinator = new PeerCoordinator(id, meta, storage, this, this);
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
set.add(coordinator);
ConnectionAcceptor acceptor = ConnectionAcceptor.instance();
acceptor.startAccepting(set, serversocket);
trackerclient = new TrackerClient(meta, coordinator);
coordinator = new PeerCoordinator(_util, id, meta, storage, this, this);
if (_peerCoordinatorSet != null) {
// multitorrent
_peerCoordinatorSet.add(coordinator);
if (acceptor != null) {
acceptor.startAccepting(_peerCoordinatorSet, serversocket);
} else {
// error
}
} else {
// single torrent
acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator));
}
trackerclient = new TrackerClient(_util, meta, coordinator);
}
stopped = false;
@ -435,11 +496,12 @@ public class Snark
if (coordinator.halted()) {
// ok, we have already started and stopped, but the coordinator seems a bit annoying to
// restart safely, so lets build a new one to replace the old
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
set.remove(coordinator);
PeerCoordinator newCoord = new PeerCoordinator(coordinator.getID(), coordinator.getMetaInfo(),
if (_peerCoordinatorSet != null)
_peerCoordinatorSet.remove(coordinator);
PeerCoordinator newCoord = new PeerCoordinator(_util, coordinator.getID(), coordinator.getMetaInfo(),
coordinator.getStorage(), coordinator.getListener(), this);
set.add(newCoord);
if (_peerCoordinatorSet != null)
_peerCoordinatorSet.add(newCoord);
coordinator = newCoord;
coordinatorChanged = true;
}
@ -457,7 +519,7 @@ public class Snark
}
fatal("Could not reopen storage", ioe);
}
TrackerClient newClient = new TrackerClient(coordinator.getMetaInfo(), coordinator);
TrackerClient newClient = new TrackerClient(_util, coordinator.getMetaInfo(), coordinator);
if (!trackerclient.halted())
trackerclient.halt();
trackerclient = newClient;
@ -477,17 +539,20 @@ public class Snark
pc.halt();
Storage st = storage;
if (st != null) {
if (storage.changed)
SnarkManager.instance().saveTorrentStatus(storage.getMetaInfo(), storage.getBitField());
boolean changed = storage.changed;
try {
storage.close();
} catch (IOException ioe) {
System.out.println("Error closing " + torrent);
ioe.printStackTrace();
}
if (changed && completeListener != null)
completeListener.updateStatus(this);
}
if (pc != null)
PeerCoordinatorSet.instance().remove(pc);
if (pc != null && _peerCoordinatorSet != null)
_peerCoordinatorSet.remove(pc);
if (_peerCoordinatorSet == null)
_util.disconnect();
}
static Snark parseArguments(String[] args)
@ -509,7 +574,8 @@ public class Snark
String ip = null;
String torrent = null;
boolean configured = I2PSnarkUtil.instance().configured();
I2PSnarkUtil util = new I2PSnarkUtil(I2PAppContext.getGlobalContext());
boolean configured = util.configured();
int i = 0;
while (i < args.length)
@ -559,7 +625,7 @@ public class Snark
String proxyHost = args[i+1];
String proxyPort = args[i+2];
if (!configured)
I2PSnarkUtil.instance().setProxy(proxyHost, Integer.parseInt(proxyPort));
util.setProxy(proxyHost, Integer.parseInt(proxyPort));
i += 3;
}
else if (args[i].equals("--i2cp"))
@ -581,7 +647,7 @@ public class Snark
}
}
if (!configured)
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
util.setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
i += 3 + (opts != null ? 1 : 0);
}
else
@ -598,7 +664,7 @@ public class Snark
else
usage("Need exactly one <url>, <file> or <dir>.");
return new Snark(torrent, ip, user_port, slistener, clistener);
return new Snark(util, torrent, ip, user_port, slistener, clistener);
}
private static void usage(String s)
@ -665,7 +731,7 @@ public class Snark
*/
public void fatal(String s, Throwable t)
{
I2PSnarkUtil.instance().debug(s, ERROR, t);
_util.debug(s, ERROR, t);
//System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
//if (debug >= INFO && t != null)
// t.printStackTrace();
@ -676,13 +742,12 @@ public class Snark
/**
* Show debug info if debug is true.
*/
public static void debug(String s, int level)
private void debug(String s, int level)
{
I2PSnarkUtil.instance().debug(s, level, null);
//if (debug >= level)
// System.out.println(s);
_util.debug(s, level, null);
}
/** coordinatorListener */
public void peerChange(PeerCoordinator coordinator, Peer peer)
{
// System.out.println(peer.toString());
@ -721,7 +786,7 @@ public class Snark
{
// Use the MetaInfo from the storage since our own might not
// yet be setup correctly.
MetaInfo meta = storage.getMetaInfo();
//MetaInfo meta = storage.getMetaInfo();
//if (meta != null)
// System.out.print("Checking existing "
// + meta.getPieces()
@ -729,7 +794,7 @@ public class Snark
checking = true;
}
if (!checking)
Snark.debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
Snark.INFO);
}
@ -740,11 +805,13 @@ public class Snark
allChecked = true;
checking = false;
if (storage.changed && completeListener != null)
completeListener.updateStatus(this);
}
public void storageCompleted(Storage storage)
{
Snark.debug("Completely received " + torrent, Snark.INFO);
debug("Completely received " + torrent, Snark.INFO);
//storage.close();
//System.out.println("Completely received: " + torrent);
if (completeListener != null)
@ -765,44 +832,47 @@ public class Snark
public interface CompleteListener {
public void torrentComplete(Snark snark);
public void updateStatus(Snark snark);
// not really listeners but the easiest way to get back to an optional SnarkManager
public long getSavedTorrentTime(Snark snark);
public BitField getSavedTorrentBitField(Snark snark);
}
/** Maintain a configurable total uploader cap
* coordinatorListener
*/
final static int MIN_TOTAL_UPLOADERS = 4;
final static int MAX_TOTAL_UPLOADERS = 10;
public static boolean overUploadLimit(int uploaders) {
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
if (coordinators == null || uploaders <= 0)
public boolean overUploadLimit(int uploaders) {
if (_peerCoordinatorSet == null || uploaders <= 0)
return false;
int totalUploaders = 0;
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next();
if (!c.halted())
totalUploaders += c.uploaders;
}
int limit = I2PSnarkUtil.instance().getMaxUploaders();
// Snark.debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
int limit = _util.getMaxUploaders();
// debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
return totalUploaders > limit;
}
public static boolean overUpBWLimit() {
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
if (coordinators == null)
public boolean overUpBWLimit() {
if (_peerCoordinatorSet == null)
return false;
long total = 0;
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next();
if (!c.halted())
total += c.getCurrentUploadRate();
}
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW();
Snark.debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
long limit = 1024l * _util.getMaxUpBW();
debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
return total > limit;
}
public static boolean overUpBWLimit(long total) {
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW();
public boolean overUpBWLimit(long total) {
long limit = 1024l * _util.getMaxUpBW();
return total > limit;
}
}

View File

@ -19,7 +19,7 @@ import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -32,11 +32,14 @@ public class SnarkManager implements Snark.CompleteListener {
/** map of (canonical) filename to Snark instance (unsynchronized) */
private Map _snarks;
private Object _addSnarkLock;
private String _configFile;
private String _configFile = "i2psnark.config";
private Properties _config;
private I2PAppContext _context;
private Log _log;
private List _messages;
private I2PSnarkUtil _util;
private PeerCoordinatorSet _peerCoordinatorSet;
private ConnectionAcceptor _connectionAcceptor;
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
@ -51,10 +54,6 @@ public class SnarkManager implements Snark.CompleteListener {
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
public static final String DEFAULT_AUTO_START = "false";
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
public static final String DEFAULT_USE_OPENTRACKERS = "true";
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
public static final String DEFAULT_LINK_PREFIX = "file:///";
@ -67,16 +66,28 @@ public class SnarkManager implements Snark.CompleteListener {
_context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(SnarkManager.class);
_messages = new ArrayList(16);
loadConfig("i2psnark.config");
_util = new I2PSnarkUtil(_context);
loadConfig(null);
}
/** Caller _must_ call loadConfig(file) before this if setting new values
* for i2cp host/port or i2psnark.dir
*/
public void start() {
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util);
int minutes = getStartupDelayMinutes();
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
I2PThread monitor = new I2PThread(new DirMonitor(), "Snark DirMonitor");
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
monitor.setDaemon(true);
monitor.start();
if (_context instanceof RouterContext)
((RouterContext)_context).router().addShutdownTask(new SnarkManagerShutdown());
}
/** hook to I2PSnarkUtil for the servlet */
public I2PSnarkUtil util() { return _util; }
private static final int MAX_MESSAGES = 5;
public void addMessage(String message) {
synchronized (_messages) {
@ -98,9 +109,6 @@ public class SnarkManager implements Snark.CompleteListener {
public boolean shouldAutoStart() {
return Boolean.valueOf(_config.getProperty(PROP_AUTO_START, DEFAULT_AUTO_START+"")).booleanValue();
}
public boolean shouldUseOpenTrackers() {
return Boolean.valueOf(_config.getProperty(PROP_USE_OPENTRACKERS, DEFAULT_USE_OPENTRACKERS)).booleanValue();
}
public String linkPrefix() {
return _config.getProperty(PROP_LINK_PREFIX, DEFAULT_LINK_PREFIX + getDataDir().getAbsolutePath() + File.separatorChar);
}
@ -112,17 +120,20 @@ public class SnarkManager implements Snark.CompleteListener {
return new File(dir);
}
/** null to set initial defaults */
public void loadConfig(String filename) {
_configFile = filename;
if (_config == null)
_config = new Properties();
File cfg = new File(filename);
if (cfg.exists()) {
try {
DataHelper.loadProps(_config, cfg);
} catch (IOException ioe) {
_log.error("Error loading I2PSnark config '" + filename + "'", ioe);
}
if (filename != null) {
_configFile = filename;
File cfg = new File(filename);
if (cfg.exists()) {
try {
DataHelper.loadProps(_config, cfg);
} catch (IOException ioe) {
_log.error("Error loading I2PSnark config '" + filename + "'", ioe);
}
}
}
// now add sane defaults
if (!_config.containsKey(PROP_I2CP_HOST))
@ -130,7 +141,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (!_config.containsKey(PROP_I2CP_PORT))
_config.setProperty(PROP_I2CP_PORT, "7654");
if (!_config.containsKey(PROP_I2CP_OPTS))
_config.setProperty(PROP_I2CP_OPTS, "inbound.length=1 inbound.lengthVariance=1 outbound.length=1 outbound.lengthVariance=1");
_config.setProperty(PROP_I2CP_OPTS, "inbound.length=2 inbound.lengthVariance=0 outbound.length=2 outbound.lengthVariance=0");
if (!_config.containsKey(PROP_EEP_HOST))
_config.setProperty(PROP_EEP_HOST, "localhost");
if (!_config.containsKey(PROP_EEP_PORT))
@ -169,16 +180,16 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
if (i2cpHost != null) {
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
_util.setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
_log.debug("Configuring with I2CP options " + i2cpOpts);
}
//I2PSnarkUtil.instance().setI2CPConfig("66.111.51.110", 7654, new Properties());
String eepHost = _config.getProperty(PROP_EEP_HOST);
int eepPort = getInt(PROP_EEP_PORT, 4444);
if (eepHost != null)
I2PSnarkUtil.instance().setProxy(eepHost, eepPort);
I2PSnarkUtil.instance().setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
I2PSnarkUtil.instance().setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
_util.setProxy(eepHost, eepPort);
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
getDataDir().mkdirs();
}
@ -198,12 +209,12 @@ public class SnarkManager implements Snark.CompleteListener {
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) {
boolean changed = false;
if (eepHost != null) {
int port = I2PSnarkUtil.instance().getEepProxyPort();
int port = _util.getEepProxyPort();
try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
String host = I2PSnarkUtil.instance().getEepProxyHost();
String host = _util.getEepProxyHost();
if ( (eepHost.trim().length() > 0) && (port > 0) &&
((!host.equals(eepHost) || (port != I2PSnarkUtil.instance().getEepProxyPort()) )) ) {
I2PSnarkUtil.instance().setProxy(eepHost, port);
((!host.equals(eepHost) || (port != _util.getEepProxyPort()) )) ) {
_util.setProxy(eepHost, port);
changed = true;
_config.setProperty(PROP_EEP_HOST, eepHost);
_config.setProperty(PROP_EEP_PORT, eepPort+"");
@ -211,11 +222,11 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
if (upLimit != null) {
int limit = I2PSnarkUtil.instance().getMaxUploaders();
int limit = _util.getMaxUploaders();
try { limit = Integer.parseInt(upLimit); } catch (NumberFormatException nfe) {}
if ( limit != I2PSnarkUtil.instance().getMaxUploaders()) {
if ( limit != _util.getMaxUploaders()) {
if ( limit >= Snark.MIN_TOTAL_UPLOADERS ) {
I2PSnarkUtil.instance().setMaxUploaders(limit);
_util.setMaxUploaders(limit);
changed = true;
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit);
addMessage("Total uploaders limit changed to " + limit);
@ -225,11 +236,11 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
if (upBW != null) {
int limit = I2PSnarkUtil.instance().getMaxUpBW();
int limit = _util.getMaxUpBW();
try { limit = Integer.parseInt(upBW); } catch (NumberFormatException nfe) {}
if ( limit != I2PSnarkUtil.instance().getMaxUpBW()) {
if ( limit != _util.getMaxUpBW()) {
if ( limit >= MIN_UP_BW ) {
I2PSnarkUtil.instance().setMaxUpBW(limit);
_util.setMaxUpBW(limit);
changed = true;
_config.setProperty(PROP_UPBW_MAX, "" + limit);
addMessage("Up BW limit changed to " + limit + "KBps");
@ -239,8 +250,8 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
if (i2cpHost != null) {
int oldI2CPPort = I2PSnarkUtil.instance().getI2CPPort();
String oldI2CPHost = I2PSnarkUtil.instance().getI2CPHost();
int oldI2CPPort = _util.getI2CPPort();
String oldI2CPHost = _util.getI2CPHost();
int port = oldI2CPPort;
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
String host = oldI2CPHost;
@ -266,7 +277,7 @@ public class SnarkManager implements Snark.CompleteListener {
if ( (i2cpHost.trim().length() > 0) && (port > 0) &&
((!host.equals(i2cpHost) ||
(port != I2PSnarkUtil.instance().getI2CPPort()) ||
(port != _util.getI2CPPort()) ||
(!oldOpts.equals(opts)))) ) {
boolean snarksActive = false;
Set names = listTorrentFiles();
@ -282,19 +293,19 @@ public class SnarkManager implements Snark.CompleteListener {
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
+ "] oldOpts [" + oldOpts + "]");
} else {
if (I2PSnarkUtil.instance().connected()) {
I2PSnarkUtil.instance().disconnect();
if (_util.connected()) {
_util.disconnect();
addMessage("Disconnecting old I2CP destination");
}
Properties p = new Properties();
p.putAll(opts);
addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")");
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, port, p);
boolean ok = I2PSnarkUtil.instance().connect();
_util.setI2CPConfig(i2cpHost, port, p);
boolean ok = _util.connect();
if (!ok) {
addMessage("Unable to connect with the new settings, reverting to the old I2CP settings");
I2PSnarkUtil.instance().setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
ok = I2PSnarkUtil.instance().connect();
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
ok = _util.connect();
if (!ok)
addMessage("Unable to reconnect with the old settings!");
} else {
@ -322,14 +333,14 @@ public class SnarkManager implements Snark.CompleteListener {
addMessage("Adjusted autostart to " + autoStart);
changed = true;
}
if (shouldUseOpenTrackers() != useOpenTrackers) {
_config.setProperty(PROP_USE_OPENTRACKERS, useOpenTrackers + "");
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect");
changed = true;
}
if (openTrackers != null) {
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(getOpenTrackerString())) {
_config.setProperty(PROP_OPENTRACKERS, openTrackers.trim());
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
addMessage("Open Tracker list changed - torrent restart required to take effect");
changed = true;
}
@ -354,7 +365,7 @@ public class SnarkManager implements Snark.CompleteListener {
public Properties getConfig() { return _config; }
/** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */
private static final int MAX_FILES_PER_TORRENT = 128;
private static final int MAX_FILES_PER_TORRENT = 256;
/** set of filenames that we are dealing with */
public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } }
@ -364,9 +375,9 @@ public class SnarkManager implements Snark.CompleteListener {
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
public void addTorrent(String filename) { addTorrent(filename, false); }
public void addTorrent(String filename, boolean dontAutoStart) {
if ((!dontAutoStart) && !I2PSnarkUtil.instance().connected()) {
if ((!dontAutoStart) && !_util.connected()) {
addMessage("Connecting to I2P");
boolean ok = I2PSnarkUtil.instance().connect();
boolean ok = _util.connect();
if (!ok) {
addMessage("Error connecting to I2P - check your I2CP settings");
return;
@ -407,7 +418,9 @@ public class SnarkManager implements Snark.CompleteListener {
addMessage(rejectMessage);
return;
} else {
torrent = new Snark(filename, null, -1, null, null, false, dataDir.getPath());
torrent = new Snark(_util, filename, null, -1, null, null, this,
_peerCoordinatorSet, _connectionAcceptor,
false, dataDir.getPath());
torrent.completeListener = this;
synchronized (_snarks) {
_snarks.put(filename, torrent);
@ -438,7 +451,8 @@ public class SnarkManager implements Snark.CompleteListener {
/**
* Get the timestamp for a torrent from the config file
*/
public long getSavedTorrentTime(MetaInfo metainfo) {
public long getSavedTorrentTime(Snark snark) {
MetaInfo metainfo = snark.meta;
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
@ -457,7 +471,8 @@ public class SnarkManager implements Snark.CompleteListener {
* Get the saved bitfield for a torrent from the config file.
* Convert "." to a full bitfield.
*/
public BitField getSavedTorrentBitField(MetaInfo metainfo) {
public BitField getSavedTorrentBitField(Snark snark) {
MetaInfo metainfo = snark.meta;
byte[] ih = metainfo.getInfoHash();
String infohash = Base64.encode(ih);
infohash = infohash.replace('=', '$');
@ -574,7 +589,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (remaining == 0) {
// should we disconnect/reconnect here (taking care to deal with the other thread's
// I2PServerSocket.accept() call properly?)
////I2PSnarkUtil.instance().
////_util.
}
if (!wasStopped)
addMessage("Torrent stopped: '" + sfile.getName() + "'");
@ -618,11 +633,17 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
/** two listeners */
public void torrentComplete(Snark snark) {
File f = new File(snark.torrent);
long len = snark.meta.getTotalLength();
addMessage("Download complete of " + f.getName()
+ (len < 5*1024*1024 ? " (size: " + (len/1024) + "KB)" : " (size: " + (len/(1024*1024l)) + "MB)"));
updateStatus(snark);
}
public void updateStatus(Snark snark) {
saveTorrentStatus(snark.meta, snark.storage.getBitField());
}
private void monitorTorrents(File dir) {
@ -644,7 +665,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (existingNames.contains(foundNames.get(i))) {
// already known. noop
} else {
if (shouldAutoStart() && !I2PSnarkUtil.instance().connect())
if (shouldAutoStart() && !_util.connect())
addMessage("Unable to connect to I2P");
addTorrent((String)foundNames.get(i), !shouldAutoStart());
}
@ -672,6 +693,7 @@ public class SnarkManager implements Snark.CompleteListener {
, "welterde", "http://BGKmlDOoH3RzFbPRfRpZV2FjpVj8~3moFftw5-dZfDf2070TOe8Tf2~DAVeaM6ZRLdmFEt~9wyFL8YMLMoLoiwGEH6IGW6rc45tstN68KsBDWZqkTohV1q9XFgK9JnCwE~Oi89xLBHsLMTHOabowWM6dkC8nI6QqJC2JODqLPIRfOVrDdkjLwtCrsckzLybNdFmgfoqF05UITDyczPsFVaHtpF1sRggOVmdvCM66otyonlzNcJbn59PA-R808vUrCPMGU~O9Wys0i-NoqtIbtWfOKnjCRFMNw5ex4n9m5Sxm9e20UkpKG6qzEuvKZWi8vTLe1NW~CBrj~vG7I3Ok4wybUFflBFOaBabxYJLlx4xTE1zJIVxlsekmAjckB4v-cQwulFeikR4LxPQ6mCQknW2HZ4JQIq6hL9AMabxjOlYnzh7kjOfRGkck8YgeozcyTvcDUcUsOuSTk06L4kdrv8h2Cozjbloi5zl6KTbj5ZTciKCxi73Pn9grICn-HQqEAAAA.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
// , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
// , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
, "crstrack", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
};
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
@ -706,26 +728,6 @@ public class SnarkManager implements Snark.CompleteListener {
return trackerMap;
}
public String getOpenTrackerString() {
return _config.getProperty(PROP_OPENTRACKERS, DEFAULT_OPENTRACKERS);
}
/** comma delimited list open trackers to use as backups */
/** sorted map of name to announceURL=baseURL */
public List getOpenTrackers() {
if (!shouldUseOpenTrackers())
return null;
List rv = new ArrayList(1);
String trackers = getOpenTrackerString();
StringTokenizer tok = new StringTokenizer(trackers, ", ");
while (tok.hasMoreTokens())
rv.add(tok.nextToken());
if (rv.size() <= 0)
return null;
return rv;
}
private static class TorrentFilenameFilter implements FilenameFilter {
private static final TorrentFilenameFilter _filter = new TorrentFilenameFilter();
public static TorrentFilenameFilter instance() { return _filter; }
@ -734,7 +736,7 @@ public class SnarkManager implements Snark.CompleteListener {
}
}
public class SnarkManagerShutdown extends I2PThread {
public class SnarkManagerShutdown extends I2PAppThread {
public void run() {
Set names = listTorrentFiles();
for (Iterator iter = names.iterator(); iter.hasNext(); ) {

View File

@ -22,12 +22,12 @@ package org.klomp.snark;
import java.io.IOException;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
/**
* Makes sure everything ends correctly when shutting down.
*/
public class SnarkShutdown extends I2PThread
public class SnarkShutdown extends I2PAppThread
{
private final Storage storage;
private final PeerCoordinator coordinator;
@ -51,21 +51,21 @@ public class SnarkShutdown extends I2PThread
public void run()
{
Snark.debug("Shutting down...", Snark.NOTICE);
//Snark.debug("Shutting down...", Snark.NOTICE);
Snark.debug("Halting ConnectionAcceptor...", Snark.INFO);
//Snark.debug("Halting ConnectionAcceptor...", Snark.INFO);
if (acceptor != null)
acceptor.halt();
Snark.debug("Halting TrackerClient...", Snark.INFO);
//Snark.debug("Halting TrackerClient...", Snark.INFO);
if (trackerclient != null)
trackerclient.halt();
Snark.debug("Halting PeerCoordinator...", Snark.INFO);
//Snark.debug("Halting PeerCoordinator...", Snark.INFO);
if (coordinator != null)
coordinator.halt();
Snark.debug("Closing Storage...", Snark.INFO);
//Snark.debug("Closing Storage...", Snark.INFO);
if (storage != null)
{
try
@ -74,7 +74,7 @@ public class SnarkShutdown extends I2PThread
}
catch(IOException ioe)
{
I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
//I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
throw new RuntimeException("b0rking");
}
}
@ -82,7 +82,7 @@ public class SnarkShutdown extends I2PThread
// XXX - Should actually wait till done...
try
{
Snark.debug("Waiting 5 seconds...", Snark.INFO);
//Snark.debug("Waiting 5 seconds...", Snark.INFO);
Thread.sleep(5*1000);
}
catch (InterruptedException ie) { /* ignored */ }

View File

@ -39,11 +39,16 @@ public class Storage
private long[] lengths;
private RandomAccessFile[] rafs;
private String[] names;
private Object[] RAFlock; // lock on RAF access
private long[] RAFtime; // when was RAF last accessed, or 0 if closed
private File[] RAFfile; // File to make it easier to reopen
private final StorageListener listener;
private I2PSnarkUtil _util;
private BitField bitfield; // BitField to represent the pieces
private int needed; // Number of pieces needed
private boolean _probablyComplete; // use this to decide whether to open files RO
// XXX - Not always set correctly
int piece_size;
@ -62,12 +67,14 @@ public class Storage
*
* @exception IOException when creating and/or checking files fails.
*/
public Storage(MetaInfo metainfo, StorageListener listener)
public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener)
throws IOException
{
_util = util;
this.metainfo = metainfo;
this.listener = listener;
needed = metainfo.getPieces();
_probablyComplete = false;
bitfield = new BitField(needed);
}
@ -76,9 +83,10 @@ public class Storage
* with an appropriate MetaInfo file as can be announced on the
* given announce String location.
*/
public Storage(File baseFile, String announce, StorageListener listener)
public Storage(I2PSnarkUtil util, File baseFile, String announce, StorageListener listener)
throws IOException
{
_util = util;
this.listener = listener;
// Create names, rafs and lengths arrays.
getFiles(baseFile);
@ -119,7 +127,6 @@ public class Storage
files.add(file);
}
String name = baseFile.getName();
if (files.size() == 1) // FIXME: ...and if base file not a directory or should this be the only check?
// this makes a bad metainfo if the directory has only one file in it
{
@ -133,7 +140,8 @@ public class Storage
}
// Creates piece hases for a new storage.
// Creates piece hashes for a new storage.
// This does NOT create the files, just the hashes
public void create() throws IOException
{
// if (true) {
@ -197,14 +205,8 @@ public class Storage
piece_hashes[20 * i + j] = hash[j];
bitfield.set(i);
if (listener != null)
listener.storageChecked(this, i, true);
}
if (listener != null)
listener.storageAllChecked(this);
// Reannounce to force recalculating the info_hash.
metainfo = metainfo.reannounce(metainfo.getAnnounce());
}
@ -218,6 +220,9 @@ public class Storage
names = new String[size];
lengths = new long[size];
rafs = new RandomAccessFile[size];
RAFlock = new Object[size];
RAFtime = new long[size];
RAFfile = new File[size];
int i = 0;
Iterator it = files.iterator();
@ -228,12 +233,13 @@ public class Storage
if (base.isDirectory() && names[i].startsWith(base.getPath()))
names[i] = names[i].substring(base.getPath().length() + 1);
lengths[i] = f.length();
rafs[i] = new RandomAccessFile(f, "r");
RAFlock[i] = new Object();
RAFfile[i] = f;
i++;
}
}
private static void addFiles(List l, File f)
private void addFiles(List l, File f)
{
if (!f.isDirectory())
l.add(f);
@ -242,7 +248,7 @@ public class Storage
File[] files = f.listFiles();
if (files == null)
{
Snark.debug("WARNING: Skipping '" + f
_util.debug("WARNING: Skipping '" + f
+ "' not a normal file.", Snark.WARNING);
return;
}
@ -288,40 +294,44 @@ public class Storage
* Creates (and/or checks) all files from the metainfo file list.
*/
public void check(String rootDir) throws IOException
{
check(rootDir, 0, null);
}
/** use a saved bitfield and timestamp from a config file */
public void check(String rootDir, long savedTime, BitField savedBitField) throws IOException
{
File base = new File(rootDir, filterName(metainfo.getName()));
// look for saved bitfield and timestamp in the config file
long savedTime = SnarkManager.instance().getSavedTorrentTime(metainfo);
BitField savedBitField = SnarkManager.instance().getSavedTorrentBitField(metainfo);
boolean useSavedBitField = savedTime > 0 && savedBitField != null;
List files = metainfo.getFiles();
if (files == null)
{
// Create base as file.
Snark.debug("Creating/Checking file: " + base, Snark.NOTICE);
_util.debug("Creating/Checking file: " + base, Snark.NOTICE);
if (!base.createNewFile() && !base.exists())
throw new IOException("Could not create file " + base);
lengths = new long[1];
rafs = new RandomAccessFile[1];
names = new String[1];
RAFlock = new Object[1];
RAFtime = new long[1];
RAFfile = new File[1];
lengths[0] = metainfo.getTotalLength();
RAFlock[0] = new Object();
RAFfile[0] = base;
if (useSavedBitField) {
long lm = base.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
}
if (base.exists() && ((useSavedBitField && savedBitField.complete()) || !base.canWrite()))
rafs[0] = new RandomAccessFile(base, "r");
else
rafs[0] = new RandomAccessFile(base, "rw");
names[0] = base.getName();
}
else
{
// Create base as dir.
Snark.debug("Creating/Checking directory: " + base, Snark.NOTICE);
_util.debug("Creating/Checking directory: " + base, Snark.NOTICE);
if (!base.mkdir() && !base.isDirectory())
throw new IOException("Could not create directory " + base);
@ -331,20 +341,21 @@ public class Storage
lengths = new long[size];
rafs = new RandomAccessFile[size];
names = new String[size];
RAFlock = new Object[size];
RAFtime = new long[size];
RAFfile = new File[size];
for (int i = 0; i < size; i++)
{
File f = createFileFromNames(base, (List)files.get(i));
lengths[i] = ((Long)ls.get(i)).longValue();
RAFlock[i] = new Object();
RAFfile[i] = f;
total += lengths[i];
if (useSavedBitField) {
long lm = base.lastModified();
if (lm <= 0 || lm > savedTime)
useSavedBitField = false;
}
if (f.exists() && ((useSavedBitField && savedBitField.complete()) || !f.canWrite()))
rafs[i] = new RandomAccessFile(f, "r");
else
rafs[i] = new RandomAccessFile(f, "rw");
names[i] = f.getName();
}
@ -357,11 +368,17 @@ public class Storage
if (useSavedBitField) {
bitfield = savedBitField;
needed = metainfo.getPieces() - bitfield.count();
Snark.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
_probablyComplete = complete();
_util.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
} else {
// the following sets the needed variable
changed = true;
checkCreateFiles();
SnarkManager.instance().saveTorrentStatus(metainfo, bitfield);
}
if (complete())
_util.debug("Torrent is complete", Snark.NOTICE);
else
_util.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE);
}
/**
@ -376,19 +393,14 @@ public class Storage
if (files == null)
{
// Reopen base as file.
Snark.debug("Reopening file: " + base, Snark.NOTICE);
_util.debug("Reopening file: " + base, Snark.NOTICE);
if (!base.exists())
throw new IOException("Could not reopen file " + base);
if (complete() || !base.canWrite()) // hope we can get away with this, if we are only seeding...
rafs[0] = new RandomAccessFile(base, "r");
else
rafs[0] = new RandomAccessFile(base, "rw");
}
else
{
// Reopen base as dir.
Snark.debug("Reopening directory: " + base, Snark.NOTICE);
_util.debug("Reopening directory: " + base, Snark.NOTICE);
if (!base.isDirectory())
throw new IOException("Could not reopen directory " + base);
@ -398,10 +410,6 @@ public class Storage
File f = getFileFromNames(base, (List)files.get(i));
if (!f.exists())
throw new IOException("Could not reopen file " + f);
if (complete() || !f.canWrite()) // see above re: only seeding
rafs[i] = new RandomAccessFile(f, "r");
else
rafs[i] = new RandomAccessFile(f, "rw");
}
}
@ -453,27 +461,43 @@ public class Storage
return base;
}
/**
* This is called at the beginning, and at presumed completion,
* so we have to be careful about locking.
*/
private void checkCreateFiles() throws IOException
{
// Whether we are resuming or not,
// if any of the files already exists we assume we are resuming.
boolean resume = false;
_probablyComplete = true;
needed = metainfo.getPieces();
// Make sure all files are available and of correct length
for (int i = 0; i < rafs.length; i++)
{
long length = rafs[i].length();
if(length == lengths[i])
long length = RAFfile[i].length();
if(RAFfile[i].exists() && length == lengths[i])
{
if (listener != null)
listener.storageAllocated(this, length);
resume = true; // XXX Could dynamicly check
}
else if (length == 0)
allocateFile(i);
else {
Snark.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
rafs[i].setLength(lengths[i]);
else if (length == 0) {
changed = true;
synchronized(RAFlock[i]) {
allocateFile(i);
}
} else {
_util.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
changed = true;
_probablyComplete = false; // to force RW
synchronized(RAFlock[i]) {
checkRAF(i);
rafs[i].setLength(lengths[i]);
}
// will be closed below
}
}
@ -497,6 +521,17 @@ public class Storage
}
}
_probablyComplete = complete();
// close all the files so we don't end up with a zillion open ones;
// we will reopen as needed
for (int i = 0; i < rafs.length; i++) {
synchronized(RAFlock[i]) {
try {
closeRAF(i);
} catch (IOException ioe) {}
}
}
if (listener != null) {
listener.storageAllChecked(this);
if (needed <= 0)
@ -506,6 +541,8 @@ public class Storage
private void allocateFile(int nr) throws IOException
{
// caller synchronized
openRAF(nr, false); // RW
// XXX - Is this the best way to make sure we have enough space for
// the whole file?
listener.storageCreateFile(this, names[nr], lengths[nr]);
@ -520,6 +557,7 @@ public class Storage
}
int size = (int)(lengths[nr] - i*ZEROBLOCKSIZE);
rafs[nr].write(zeros, 0, size);
// caller will close rafs[nr]
if (listener != null)
listener.storageAllocated(this, size);
}
@ -535,12 +573,11 @@ public class Storage
for (int i = 0; i < rafs.length; i++)
{
try {
synchronized(rafs[i])
{
rafs[i].close();
}
synchronized(RAFlock[i]) {
closeRAF(i);
}
} catch (IOException ioe) {
I2PSnarkUtil.instance().debug("Error closing " + rafs[i], Snark.ERROR, ioe);
_util.debug("Error closing " + RAFfile[i], Snark.ERROR, ioe);
// gobble gobble
}
}
@ -561,7 +598,7 @@ public class Storage
try {
bs = new byte[len];
} catch (OutOfMemoryError oom) {
I2PSnarkUtil.instance().debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
_util.debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
return null;
}
getUncheckedPiece(piece, bs, off, len);
@ -587,18 +624,10 @@ public class Storage
if (!correctHash)
return false;
boolean complete;
synchronized(bitfield)
{
if (bitfield.get(piece))
return true; // No need to store twice.
else
{
bitfield.set(piece);
needed--;
complete = needed == 0;
}
}
// Early typecast, avoid possibly overflowing a temp integer
@ -618,8 +647,9 @@ public class Storage
{
int need = length - written;
int len = (start + need < raflen) ? need : (int)(raflen - start);
synchronized(rafs[i])
synchronized(RAFlock[i])
{
checkRAF(i);
rafs[i].seek(start);
rafs[i].write(bs, off + written, len);
}
@ -633,8 +663,21 @@ public class Storage
}
changed = true;
// do this after the write, so we know it succeeded, and we don't set the
// needed count to zero, which would cause checkRAF() to open the file readonly.
boolean complete = false;
synchronized(bitfield)
{
if (!bitfield.get(piece))
{
bitfield.set(piece);
needed--;
complete = needed == 0;
}
}
if (complete) {
// listener.storageCompleted(this);
// do we also need to close all of the files and reopen
// them readonly?
@ -649,11 +692,10 @@ public class Storage
bitfield = new BitField(needed);
checkCreateFiles();
if (needed > 0) {
listener.setWantedPieces(this);
Snark.debug("WARNING: Not really done, missing " + needed
if (listener != null)
listener.setWantedPieces(this);
_util.debug("WARNING: Not really done, missing " + needed
+ " pieces", Snark.WARNING);
} else {
SnarkManager.instance().saveTorrentStatus(metainfo, bitfield);
}
}
@ -688,8 +730,9 @@ public class Storage
{
int need = length - read;
int len = (start + need < raflen) ? need : (int)(raflen - start);
synchronized(rafs[i])
synchronized(RAFlock[i])
{
checkRAF(i);
rafs[i].seek(start);
rafs[i].readFully(bs, read, len);
}
@ -704,4 +747,59 @@ public class Storage
return length;
}
/**
* Close unused RAFs - call periodically
*/
private static final long RAFCloseDelay = 7*60*1000;
public void cleanRAFs() {
long cutoff = System.currentTimeMillis() - RAFCloseDelay;
for (int i = 0; i < RAFlock.length; i++) {
synchronized(RAFlock[i]) {
if (RAFtime[i] > 0 && RAFtime[i] < cutoff) {
try {
closeRAF(i);
} catch (IOException ioe) {}
}
}
}
}
/*
* For each of the following,
* caller must synchronize on RAFlock[i]
* ... except at the beginning if you're careful
*/
/**
* This must be called before using the RAF to ensure it is open
*/
private void checkRAF(int i) throws IOException {
if (RAFtime[i] > 0) {
RAFtime[i] = System.currentTimeMillis();
return;
}
openRAF(i);
}
private void openRAF(int i) throws IOException {
openRAF(i, _probablyComplete);
}
private void openRAF(int i, boolean readonly) throws IOException {
rafs[i] = new RandomAccessFile(RAFfile[i], (readonly || !RAFfile[i].canWrite()) ? "r" : "rw");
RAFtime[i] = System.currentTimeMillis();
}
/**
* Can be called even if not open
*/
private void closeRAF(int i) throws IOException {
RAFtime[i] = 0;
if (rafs[i] == null)
return;
rafs[i].close();
rafs[i] = null;
}
}

View File

@ -59,7 +59,6 @@ public interface StorageListener
/** Reset the peer's wanted pieces table
* Call after the storage double-check fails
*
* @param peer the peer
*/
void setWantedPieces(Storage storage);
}

View File

@ -31,7 +31,7 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/**
@ -40,7 +40,7 @@ import net.i2p.util.Log;
*
* @author Mark Wielaard (mark@klomp.org)
*/
public class TrackerClient extends I2PThread
public class TrackerClient extends I2PAppThread
{
private static final Log _log = new Log(TrackerClient.class);
private static final String NO_EVENT = "";
@ -57,6 +57,7 @@ public class TrackerClient extends I2PThread
private final static int MAX_CONSEC_FAILS = 5; // slow down after this
private final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails
private I2PSnarkUtil _util;
private final MetaInfo meta;
private final PeerCoordinator coordinator;
private final int port;
@ -66,10 +67,11 @@ public class TrackerClient extends I2PThread
private List trackers;
public TrackerClient(MetaInfo meta, PeerCoordinator coordinator)
public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator)
{
// Set unique name.
super("TrackerClient-" + urlencode(coordinator.getID()));
_util = util;
this.meta = meta;
this.coordinator = coordinator;
@ -98,13 +100,13 @@ public class TrackerClient extends I2PThread
}
private boolean verifyConnected() {
while (!stop && !I2PSnarkUtil.instance().connected()) {
boolean ok = I2PSnarkUtil.instance().connect();
while (!stop && !_util.connected()) {
boolean ok = _util.connect();
if (!ok) {
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
}
}
return !stop && I2PSnarkUtil.instance().connected();
return !stop && _util.connected();
}
public void run()
@ -121,7 +123,7 @@ public class TrackerClient extends I2PThread
// the primary tracker, that we don't add it twice.
trackers = new ArrayList(2);
trackers.add(new Tracker(meta.getAnnounce(), true));
List tlist = SnarkManager.instance().getOpenTrackers();
List tlist = _util.getOpenTrackers();
if (tlist != null) {
for (int i = 0; i < tlist.size(); i++) {
String url = (String)tlist.get(i);
@ -136,7 +138,7 @@ public class TrackerClient extends I2PThread
}
if (meta.getAnnounce().startsWith(url.substring(0, slash)))
continue;
String dest = I2PSnarkUtil.instance().lookup(url.substring(7, slash));
String dest = _util.lookup(url.substring(7, slash));
if (dest == null) {
_log.error("Announce host unknown: [" + url + "]");
continue;
@ -264,7 +266,7 @@ public class TrackerClient extends I2PThread
catch (IOException ioe)
{
// Probably not fatal (if it doesn't last to long...)
Snark.debug
_util.debug
("WARNING: Could not contact tracker at '"
+ tr.announce + "': " + ioe, Snark.WARNING);
tr.trackerProblems = ioe.getMessage();
@ -295,12 +297,12 @@ public class TrackerClient extends I2PThread
// we could try and total the unique peers but that's too hard for now
coordinator.trackerSeenPeers = maxSeenPeers;
if (!started)
Snark.debug(" Retrying in one minute...", Snark.DEBUG);
_util.debug(" Retrying in one minute...", Snark.DEBUG);
} // *** end of while loop
} // try
catch (Throwable t)
{
I2PSnarkUtil.instance().debug("TrackerClient: " + t, Snark.ERROR, t);
_util.debug("TrackerClient: " + t, Snark.ERROR, t);
if (t instanceof OutOfMemoryError)
throw (OutOfMemoryError)t;
}
@ -332,19 +334,18 @@ public class TrackerClient extends I2PThread
+ "?info_hash=" + infoHash
+ "&peer_id=" + peerID
+ "&port=" + port
+ "&ip=" + I2PSnarkUtil.instance().getOurIPString() + ".i2p"
+ "&ip=" + _util.getOurIPString() + ".i2p"
+ "&uploaded=" + uploaded
+ "&downloaded=" + downloaded
+ "&left=" + left
+ ((event != NO_EVENT) ? ("&event=" + event) : "");
Snark.debug("Sending TrackerClient request: " + s, Snark.INFO);
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
tr.lastRequestTime = System.currentTimeMillis();
File fetched = I2PSnarkUtil.instance().get(s);
File fetched = _util.get(s);
if (fetched == null) {
throw new IOException("Error fetching " + s);
}
fetched.deleteOnExit();
InputStream in = null;
try {
@ -352,7 +353,7 @@ public class TrackerClient extends I2PThread
TrackerInfo info = new TrackerInfo(in, coordinator.getID(),
coordinator.getMetaInfo());
Snark.debug("TrackerClient response: " + info, Snark.INFO);
_util.debug("TrackerClient response: " + info, Snark.INFO);
String failure = info.getFailureReason();
if (failure != null)

View File

@ -101,7 +101,7 @@ public class TrackerInfo
peerID = new PeerID(((BEValue)it.next()).getMap());
} catch (InvalidBEncodingException ibe) {
// don't let one bad entry spoil the whole list
Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
//Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
continue;
}
peers.add(new Peer(peerID, my_id, metainfo));

View File

@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -23,7 +24,7 @@ import net.i2p.I2PAppContext;
import net.i2p.data.Base64;
import net.i2p.data.DataHelper;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PThread;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import org.klomp.snark.I2PSnarkUtil;
@ -55,6 +56,7 @@ public class I2PSnarkServlet extends HttpServlet {
if ( (configFile == null) || (configFile.trim().length() <= 0) )
configFile = "i2psnark.config";
_manager.loadConfig(configFile);
_manager.start();
}
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
@ -87,12 +89,12 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("<table border=\"0\" width=\"100%\">\n");
out.write("<tr><td><a href=\"" + req.getRequestURI() + peerString + "\" class=\"snarkRefresh\">Refresh</a>\n");
out.write("<td><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\">Forum</a>\n");
out.write("<tr><td><a href=\"http://codevoid.i2p/forums/5\" class=\"snarkRefresh\">Wishlist</a>\n");
int count = 1;
int count = 0;
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String baseURL = (String)trackers.get(name);
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String name = (String)entry.getKey();
String baseURL = (String)entry.getValue();
int e = baseURL.indexOf('=');
if (e < 0)
continue;
@ -115,7 +117,7 @@ public class I2PSnarkServlet extends HttpServlet {
List snarks = getSortedSnarks(req);
String uri = req.getRequestURI();
out.write(TABLE_HEADER);
if (I2PSnarkUtil.instance().connected() && snarks.size() > 0) {
if (_manager.util().connected() && snarks.size() > 0) {
if (peerParam != null)
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n");
else
@ -123,7 +125,7 @@ public class I2PSnarkServlet extends HttpServlet {
}
out.write(TABLE_HEADER2);
out.write("<th align=\"left\" valign=\"top\">");
if (I2PSnarkUtil.instance().connected())
if (_manager.util().connected())
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
"\" title=\"Stop all torrents and the i2p tunnel\">Stop All</a>");
else if (snarks.size() > 0)
@ -200,7 +202,7 @@ public class I2PSnarkServlet extends HttpServlet {
}
} else if ( (newURL != null) && (newURL.trim().length() > "http://.i2p/".length()) ) {
_manager.addMessage("Fetching " + newURL);
I2PThread fetch = new I2PThread(new FetchAndAdd(_manager, newURL), "Fetch and add");
I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add");
fetch.start();
} else {
// no file or URL specified
@ -329,7 +331,7 @@ public class I2PSnarkServlet extends HttpServlet {
_manager.addMessage("Error creating torrent - you must select a tracker");
else if (baseFile.exists()) {
try {
Storage s = new Storage(baseFile, announceURL, null);
Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
s.create();
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
MetaInfo info = s.getMetaInfo();
@ -360,8 +362,8 @@ public class I2PSnarkServlet extends HttpServlet {
if (!snark.stopped)
_manager.stopTorrent(snark.torrent, false);
}
if (I2PSnarkUtil.instance().connected()) {
I2PSnarkUtil.instance().disconnect();
if (_manager.util().connected()) {
_manager.util().disconnect();
_manager.addMessage("I2P tunnel closed");
}
} else if ("StartAll".equals(action)) {
@ -377,7 +379,8 @@ public class I2PSnarkServlet extends HttpServlet {
private List getSortedSnarks(HttpServletRequest req) {
Set files = _manager.listTorrentFiles();
TreeSet fileNames = new TreeSet(files); // sorts it alphabetically
TreeSet fileNames = new TreeSet(Collator.getInstance()); // sorts it alphabetically
fileNames.addAll(files);
ArrayList rv = new ArrayList(fileNames.size());
for (Iterator iter = fileNames.iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
@ -496,9 +499,10 @@ public class I2PSnarkServlet extends HttpServlet {
String announce = snark.meta.getAnnounce();
if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr")) {
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String baseURL = (String)trackers.get(name);
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String name = (String)entry.getKey();
String baseURL = (String)entry.getValue();
if (!baseURL.startsWith(announce))
continue;
int e = baseURL.indexOf('=');
@ -571,6 +575,10 @@ public class I2PSnarkServlet extends HttpServlet {
client = "I2P-BT";
else if ("LUFa".equals(ch))
client = "Azureus";
else if ("CwsL".equals(ch))
client = "I2PSnarkXL";
else if ("AUZV".equals(ch) || "AkZV".equals(ch) || "A0ZV".equals(ch))
client = "Robert";
else
client = "Unknown";
out.write("<font size=-1>" + client + "</font>&nbsp;&nbsp;<tt>" + peer.toString().substring(5, 9) + "</tt>");
@ -668,9 +676,10 @@ public class I2PSnarkServlet extends HttpServlet {
+ "\" title=\"File to seed (must be within the specified path)\" /><br />\n");
out.write("Tracker: <select name=\"announceURL\"><option value=\"\">Select a tracker</option>\n");
Map trackers = _manager.getTrackers();
for (Iterator iter = trackers.keySet().iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
String announceURL = (String)trackers.get(name);
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String name = (String)entry.getKey();
String announceURL = (String)entry.getValue();
int e = announceURL.indexOf('=');
if (e > 0)
announceURL = announceURL.substring(0, e);
@ -687,8 +696,8 @@ public class I2PSnarkServlet extends HttpServlet {
String uri = req.getRequestURI();
String dataDir = _manager.getDataDir().getAbsolutePath();
boolean autoStart = _manager.shouldAutoStart();
boolean useOpenTrackers = _manager.shouldUseOpenTrackers();
String openTrackers = _manager.getOpenTrackerString();
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
String openTrackers = _manager.util().getOpenTrackerString();
//int seedPct = 0;
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
@ -720,9 +729,9 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("</select><br />\n");
*/
out.write("Total uploader limit: <input type=\"text\" name=\"upLimit\" value=\""
+ I2PSnarkUtil.instance().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
out.write("Up bandwidth limit: <input type=\"text\" name=\"upBW\" value=\""
+ I2PSnarkUtil.instance().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Router Up BW / 2 recommended)</i><br />\n");
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Router Up BW / 2 recommended)</i><br />\n");
out.write("Use open trackers also: <input type=\"checkbox\" name=\"useOpenTrackers\" value=\"true\" "
+ (useOpenTrackers ? "checked " : "")
@ -732,18 +741,19 @@ public class I2PSnarkServlet extends HttpServlet {
//out.write("<hr />\n");
out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\""
+ I2PSnarkUtil.instance().getEepProxyHost() + "\" size=\"15\" /> ");
+ _manager.util().getEepProxyHost() + "\" size=\"15\" /> ");
out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
+ I2PSnarkUtil.instance().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
+ _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
out.write("I2CP host: <input type=\"text\" name=\"i2cpHost\" value=\""
+ I2PSnarkUtil.instance().getI2CPHost() + "\" size=\"15\" /> ");
+ _manager.util().getI2CPHost() + "\" size=\"15\" /> ");
out.write("port: <input type=\"text\" name=\"i2cpPort\" value=\"" +
+ I2PSnarkUtil.instance().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
StringBuffer opts = new StringBuffer(64);
Map options = new TreeMap(I2PSnarkUtil.instance().getI2CPOptions());
for (Iterator iter = options.keySet().iterator(); iter.hasNext(); ) {
String key = (String)iter.next();
String val = (String)options.get(key);
Map options = new TreeMap(_manager.util().getI2CPOptions());
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
String val = (String)entry.getValue();
opts.append(key).append('=').append(val).append(' ');
}
out.write("I2CP opts: <input type=\"text\" name=\"i2cpOpts\" size=\"80\" value=\""
@ -873,7 +883,7 @@ class FetchAndAdd implements Runnable {
public void run() {
_url = _url.trim();
// 3 retries
File file = I2PSnarkUtil.instance().get(_url, false, 3);
File file = _manager.util().get(_url, false, 3);
try {
if ( (file != null) && (file.exists()) && (file.length() > 0) ) {
_manager.addMessage("Torrent fetched from " + _url);

View File

@ -7,12 +7,27 @@
<ant dir="../../jetty/" target="build" />
<!-- ministreaming will build core -->
</target>
<target name="compile">
<condition property="depend.available">
<typefound name="depend" />
</condition>
<target name="depend" if="depend.available">
<depend
cache="../../../build"
srcdir="./src"
destdir="./build/obj" >
<!-- Depend on classes instead of jars where available -->
<classpath>
<pathelement location="../../../core/java/build/obj" />
<pathelement location="../../ministreaming/java/build/obj" />
</classpath>
</depend>
</target>
<target name="compile" depends="depend">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true" deprecation="on" source="1.3" target="1.3"
debug="true" deprecation="on" source="1.5" target="1.5"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>
@ -30,7 +45,7 @@
basedir="../jsp/" excludes="web.xml, *.java, *.jsp">
</war>
</target>
<target name="precompilejsp">
<target name="precompilejsp" unless="precompilejsp.uptodate">
<delete dir="../jsp/WEB-INF/" />
<delete file="../jsp/web-fragment.xml" />
<delete file="../jsp/web-out.xml" />
@ -56,7 +71,7 @@
<arg value="-webapp" />
<arg value="../jsp/" />
</java>
<javac debug="true" deprecation="on" source="1.3" target="1.3"
<javac debug="true" deprecation="on" source="1.5" target="1.5"
destdir="../jsp/WEB-INF/classes/" srcdir="../jsp/WEB-INF/classes" includes="**/*.java">
<classpath>
<pathelement location="../../jetty/jettylib/jasper-runtime.jar" />
@ -72,6 +87,11 @@
<replacefilter token="&lt;!-- precompiled servlets --&gt;" value="${jspc.web.fragment}" />
</replace>
</target>
<uptodate property="precompilejsp.uptodate" targetfile="../jsp/web-out.xml">
<srcfiles dir= "../jsp" includes="*.jsp, *.html, web.xml"/>
</uptodate>
<target name="javadoc">
<mkdir dir="./build" />
<mkdir dir="./build/javadoc" />
@ -84,6 +104,9 @@
</target>
<target name="clean">
<delete dir="./build" />
<delete dir="../jsp/WEB-INF/" />
<delete file="../jsp/web-fragment.xml" />
<delete file="../jsp/web-out.xml" />
</target>
<target name="cleandep" depends="clean">
<!-- ministreaming will clean core -->

View File

@ -47,9 +47,9 @@ class HTTPResponseOutputStream extends FilterOutputStream {
public HTTPResponseOutputStream(OutputStream raw) {
super(raw);
_context = I2PAppContext.getGlobalContext();
_context.statManager().createRateStat("i2ptunnel.httpCompressionRatio", "ratio of compressed size to decompressed size after transfer", "i2ptunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "i2ptunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "i2ptunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpCompressionRatio", "ratio of compressed size to decompressed size after transfer", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpCompressed", "compressed size transferred", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
_context.statManager().createRateStat("i2ptunnel.httpExpanded", "size transferred after expansion", "I2PTunnel", new long[] { 60*1000, 30*60*1000 });
_log = _context.logManager().getLog(getClass());
_cache = ByteCache.getInstance(8, CACHE_SIZE);
_headerBuffer = _cache.acquire();
@ -395,4 +395,4 @@ class HTTPResponseOutputStream extends FilterOutputStream {
System.out.println("Properly fails with " + e.getMessage());
}
}
}
}

View File

@ -284,6 +284,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("Command list:");
l.log("config <i2phost> <i2pport>");
l.log("listen_on <ip>");
l.log("clientoptions[ key=value]*");
l.log("read_timeout <msecs>");
l.log("owndest yes|no");
l.log("ping <args>");
@ -346,7 +347,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
@ -355,7 +356,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
@ -363,19 +364,19 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
notifyEvent("serverTaskId", new Integer(serv.getId()));
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("server <host> <port> <privkeyfile>");
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
}
@ -401,7 +402,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
@ -410,7 +411,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
@ -420,21 +421,21 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
I2PTunnelHTTPServer serv = new I2PTunnelHTTPServer(serverHost, portNum, privKeyFile, args[3], spoofedHost, l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
notifyEvent("serverTaskId", new Integer(serv.getId()));
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
return;
} else {
l.log("httpserver <host> <port> <spoofedhost> <privkeyfile>");
l.log(" creates an HTTP server that sends all incoming data\n"
+ " of its destination to host:port., filtering the HTTP\n"
+ " headers so it looks like the request is to the spoofed host.");
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
}
}
@ -458,7 +459,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
@ -467,7 +468,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", new Integer(-1));
notifyEvent("serverTaskId", Integer.valueOf(-1));
return;
}
@ -475,11 +476,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
notifyEvent("serverTaskId", new Integer(serv.getId()));
notifyEvent("serverTaskId", Integer.valueOf(serv.getId()));
} else {
l.log("textserver <host> <port> <privkey>");
l.log(" creates a server that sends all incoming data\n" + " of its destination to host:port.");
notifyEvent("textserverTaskId", new Integer(-1));
notifyEvent("textserverTaskId", Integer.valueOf(-1));
}
}
@ -507,7 +508,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("clientTaskId", new Integer(-1));
notifyEvent("clientTaskId", Integer.valueOf(-1));
return;
}
I2PTunnelTask task;
@ -515,11 +516,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
try {
task = new I2PTunnelClient(portNum, args[1], l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("clientTaskId", new Integer(task.getId()));
notifyEvent("clientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create a client [" + host + ":"+ port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
notifyEvent("clientTaskId", new Integer(-1));
notifyEvent("clientTaskId", Integer.valueOf(-1));
}
} else {
l.log("client <port> <pubkey>[,<pubkey>]|file:<pubkeyfile>[ <sharedClient>]");
@ -528,7 +529,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
+ " a comma delimited list of pubkeys, it will rotate among them\n"
+ " randomlyl. sharedClient indicates if this client shares \n"
+ " with other clients (true of false)");
notifyEvent("clientTaskId", new Integer(-1));
notifyEvent("clientTaskId", Integer.valueOf(-1));
}
}
@ -550,7 +551,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("httpclientTaskId", new Integer(-1));
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
return;
}
@ -582,11 +583,11 @@ public class I2PTunnel implements Logging, EventDispatcher {
try {
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this, this);
addtask(task);
notifyEvent("httpclientTaskId", new Integer(task.getId()));
notifyEvent("httpclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an httpclient [" + host + ":"+ port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
notifyEvent("httpclientTaskId", new Integer(-1));
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
}
} else {
l.log("httpclient <port> [<sharedClient>] [<proxy>]");
@ -595,7 +596,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log(" <proxy> (optional) indicates a proxy server to be used");
l.log(" when trying to access an address out of the .i2p domain");
l.log(" (the default proxy is squid.i2p).");
notifyEvent("httpclientTaskId", new Integer(-1));
notifyEvent("httpclientTaskId", Integer.valueOf(-1));
}
}
@ -617,7 +618,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("ircclientTaskId", new Integer(-1));
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
return;
}
@ -639,17 +640,17 @@ public class I2PTunnel implements Logging, EventDispatcher {
try {
task = new I2PTunnelIRCClient(port, args[1],l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("ircclientTaskId", new Integer(task.getId()));
notifyEvent("ircclientTaskId", Integer.valueOf(task.getId()));
} catch (IllegalArgumentException iae) {
_log.error(getPrefix() + "Invalid I2PTunnel config to create an ircclient [" + host + ":"+ port + "]", iae);
l.log("Invalid I2PTunnel configuration [" + host + ":" + port + "]");
notifyEvent("ircclientTaskId", new Integer(-1));
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
}
} else {
l.log("ircclient <port> [<sharedClient>]");
l.log(" creates a client that filter IRC protocol.");
l.log(" <sharedClient> (optional) indicates if this client shares tunnels with other clients (true of false)");
notifyEvent("ircclientTaskId", new Integer(-1));
notifyEvent("ircclientTaskId", Integer.valueOf(-1));
}
}
@ -672,18 +673,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("sockstunnelTaskId", new Integer(-1));
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
return;
}
I2PTunnelTask task;
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("sockstunnelTaskId", new Integer(task.getId()));
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} else {
l.log("sockstunnel <port>");
l.log(" creates a tunnel that distributes SOCKS requests.");
notifyEvent("sockstunnelTaskId", new Integer(-1));
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
}
}
@ -967,7 +968,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log(" try to resolve the name into a destination key");
notifyEvent("lookupResult", "invalidUsage");
} else {
String target = args[0];
try {
Destination dest = destFromName(args[0]);
if (dest == null) {
@ -998,13 +998,18 @@ public class I2PTunnel implements Logging, EventDispatcher {
// pings always use the main destination
task = new I2Ping(allargs, l, false, (EventDispatcher) this, this);
addtask(task);
notifyEvent("pingTaskId", new Integer(task.getId()));
notifyEvent("pingTaskId", Integer.valueOf(task.getId()));
} else {
l.log("ping <opts> <dest>");
l.log("ping <opts> -h");
l.log("ping <opts> -l <destlistfile>");
l.log(" Tests communication with peers.\n" + " opts can be -ns (nosync) or not.");
notifyEvent("pingTaskId", new Integer(-1));
l.log("ping <opts> -h (pings all hosts in hosts.txt)");
l.log("ping <opts> -l <destlistfile> (pings a list of hosts in a file)");
l.log(" Options:\n" +
" -c (require 5 consecutive pings to report success)\n" +
" -m maxSimultaneousPings (default 10)\n" +
" -n numberOfPings (default 3)\n" +
" -t timeout (ms, default 5000)\n");
l.log(" Tests communication with peers.\n");
notifyEvent("pingTaskId", Integer.valueOf(-1));
}
}
@ -1083,7 +1088,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
public static void makeKey(OutputStream writeTo, OutputStream pubDest, Logging l) {
try {
l.log("Generating new keys...");
ByteArrayOutputStream priv = new ByteArrayOutputStream(), pub = new ByteArrayOutputStream();
I2PClient client = I2PClientFactory.createClient();
Destination d = client.createDestination(writeTo);
l.log("Secret key saved.");
@ -1107,7 +1111,6 @@ public class I2PTunnel implements Logging, EventDispatcher {
*/
public static void showKey(InputStream readFrom, OutputStream pubDest, Logging l) {
try {
I2PClient client = I2PClientFactory.createClient();
Destination d = new Destination();
d.readBytes(readFrom);
l.log("Public key: " + d.toBase64());

View File

@ -217,10 +217,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
Properties props = new Properties();
if (tunnel == null)
props.putAll(System.getProperties());
else
props.putAll(tunnel.getClientOptions());
props.putAll(tunnel.getClientOptions());
int portNum = 7654;
if (tunnel.port != null) {
try {

View File

@ -225,6 +225,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private static final boolean DEFAULT_GZIP = true;
// all default to false
public static final String PROP_REFERER = "i2ptunnel.httpclient.sendReferer";
public static final String PROP_USER_AGENT = "i2ptunnel.httpclient.sendUserAgent";
public static final String PROP_VIA = "i2ptunnel.httpclient.sendVia";
private static long __requestId = 0;
protected void clientConnectionRun(Socket s) {
@ -465,8 +469,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
line = "Host: " + host;
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix(requestId) + "Setting host = " + host);
} else if (lowercaseLine.startsWith("user-agent: ")) {
// always stripped, added back at the end
} else if (lowercaseLine.startsWith("user-agent: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue()) {
line = null;
continue;
} else if (lowercaseLine.startsWith("accept")) {
@ -474,12 +478,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
// browser to browser
line = null;
continue;
} else if (lowercaseLine.startsWith("referer: ")) {
} else if (lowercaseLine.startsWith("referer: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_REFERER)).booleanValue()) {
// Shouldn't we be more specific, like accepting in-site referers ?
//line = "Referer: i2p";
line = null;
continue; // completely strip the line
} else if (lowercaseLine.startsWith("via: ")) {
} else if (lowercaseLine.startsWith("via: ") &&
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_VIA)).booleanValue()) {
//line = "Via: i2p";
line = null;
continue; // completely strip the line
@ -492,7 +498,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (line.length() == 0) {
String ok = getTunnel().getContext().getProperty("i2ptunnel.gzip");
String ok = getTunnel().getClientOptions().getProperty("i2ptunnel.gzip");
boolean gzip = DEFAULT_GZIP;
if (ok != null)
gzip = Boolean.valueOf(ok).booleanValue();
@ -503,7 +509,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
newRequest.append("Accept-Encoding: \r\n");
newRequest.append("X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n");
}
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
if (!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_USER_AGENT)).booleanValue())
newRequest.append("User-Agent: MYOB/6.66 (AN/ON)\r\n");
newRequest.append("Connection: close\r\n\r\n");
break;
} else {

View File

@ -32,12 +32,13 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
private final static Log _log = new Log(I2PTunnelHTTPServer.class);
/** what Host: should we seem to be to the webserver? */
private String _spoofHost;
private static final String HASH_HEADER = "X-I2P-DestHash";
public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, l, notifyThis, tunnel);
_spoofHost = spoofHost;
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel.HTTPServer", new long[] { 60*1000, 10*60*1000 });
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpserver.blockingHandleTime", "how long the blocking handle takes to complete", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 3*60*60*1000 });
getTunnel().getContext().statManager().createRateStat("i2ptunnel.httpNullWorkaround", "How often an http server works around a streaming lib or i2ptunnel bug", "I2PTunnel", new long[] { 60*1000, 10*60*1000 });
}
public I2PTunnelHTTPServer(InetAddress host, int port, File privkey, String privkeyname, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
@ -71,6 +72,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
StringBuffer command = new StringBuffer(128);
Properties headers = readHeaders(in, command);
headers.setProperty(HASH_HEADER, socket.getPeerDestination().calculateHash().toBase64());
if ( (_spoofHost != null) && (_spoofHost.trim().length() > 0) )
headers.setProperty("Host", _spoofHost);
headers.setProperty("Connection", "close");
@ -327,6 +329,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
name = "Accept-encoding";
else if ("X-Accept-encoding".equalsIgnoreCase(name))
name = "X-Accept-encoding";
else if (HASH_HEADER.equalsIgnoreCase(name))
continue; // Prevent spoofing
headers.setProperty(name, value);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read the header [" + name + "] = [" + value + "]");

View File

@ -216,9 +216,7 @@ public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorL
private void removeRef() {
if (sockList != null) {
synchronized (slock) {
boolean removed = sockList.remove(i2ps);
//System.out.println("Removal of i2psocket " + i2ps + " successful? "
// + removed + " remaining: " + sockList.size());
sockList.remove(i2ps);
}
}
}

View File

@ -12,6 +12,7 @@ import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Properties;
@ -69,11 +70,16 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
FileInputStream fis = null;
try {
init(host, port, new FileInputStream(privkey), privkeyname, l);
fis = new FileInputStream(privkey);
init(host, port, fis, privkeyname, l);
} catch (IOException ioe) {
_log.error("Error starting server", ioe);
notifyEvent("openServerResult", "error");
} finally {
if (fis != null)
try { fis.close(); } catch (IOException ioe) {}
}
}
@ -91,7 +97,6 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
this.l = l;
this.remoteHost = host;
this.remotePort = port;
I2PClient client = I2PClientFactory.createClient();
Properties props = new Properties();
props.putAll(getTunnel().getClientOptions());
int portNum = 7654;
@ -219,6 +224,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);
// not killing the server..
} catch(SocketTimeoutException ste) {
// ignored, we never set the timeout
}
}
}

View File

@ -20,7 +20,7 @@ import net.i2p.util.Log;
public class I2Ping extends I2PTunnelTask implements Runnable {
private final static Log _log = new Log(I2Ping.class);
private static final int PING_COUNT = 3;
private int PING_COUNT = 3;
private static final int CPING_COUNT = 5;
private static final int PING_TIMEOUT = 5000;
@ -29,6 +29,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
private int MAX_SIMUL_PINGS = 10; // not really final...
private boolean countPing = false;
private boolean reportTimes = true;
private I2PSocketManager sockMgr;
private Logging l;
@ -82,6 +83,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
}
public void runCommand(String cmd) throws InterruptedException, IOException {
while (true) {
if (cmd.startsWith("-t ")) { // timeout
cmd = cmd.substring(3);
int pos = cmd.indexOf(" ");
@ -92,8 +94,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
timeout = Long.parseLong(cmd.substring(0, pos));
cmd = cmd.substring(pos + 1);
}
}
if (cmd.startsWith("-m ")) { // max simultaneous pings
} else if (cmd.startsWith("-m ")) { // max simultaneous pings
cmd = cmd.substring(3);
int pos = cmd.indexOf(" ");
if (pos == -1) {
@ -103,18 +104,26 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
MAX_SIMUL_PINGS = Integer.parseInt(cmd.substring(0, pos));
cmd = cmd.substring(pos + 1);
}
}
if (cmd.startsWith("-c ")) { // "count" ping
} else if (cmd.startsWith("-n ")) { // number of pings
cmd = cmd.substring(3);
int pos = cmd.indexOf(" ");
if (pos == -1) {
l.log("Syntax error");
return;
} else {
PING_COUNT = Integer.parseInt(cmd.substring(0, pos));
cmd = cmd.substring(pos + 1);
}
} else if (cmd.startsWith("-c ")) { // "count" ping
countPing = true;
cmd = cmd.substring(3);
}
if (cmd.equals("-h")) { // ping all hosts
} else if (cmd.equals("-h")) { // ping all hosts
cmd = "-l hosts.txt";
}
if (cmd.startsWith("-l ")) { // ping a list of hosts
} else if (cmd.startsWith("-l ")) { // ping a list of hosts
BufferedReader br = new BufferedReader(new FileReader(cmd.substring(3)));
String line;
List pingHandlers = new ArrayList();
int i = 0;
while ((line = br.readLine()) != null) {
if (line.startsWith("#")) continue; // comments
if (line.startsWith(";")) continue;
@ -123,17 +132,21 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
line = line.substring(0, line.indexOf("="));
}
pingHandlers.add(new PingHandler(line));
if (++i > 1)
reportTimes = false;
}
br.close();
for (Iterator it = pingHandlers.iterator(); it.hasNext();) {
Thread t = (Thread) it.next();
t.join();
}
return;
} else {
Thread t = new PingHandler(cmd);
t.join();
return;
}
}
}
public boolean close(boolean forced) {
@ -163,7 +176,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
}
lastPingTime = System.currentTimeMillis();
}
boolean sent = sockMgr.ping(dest, PING_TIMEOUT);
boolean sent = sockMgr.ping(dest, timeout);
synchronized (simulLock) {
simulPings--;
simulLock.notifyAll();
@ -193,6 +206,9 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
}
return;
}
int pass = 0;
int fail = 0;
long totalTime = 0;
int cnt = countPing ? CPING_COUNT : PING_COUNT;
StringBuffer pingResults = new StringBuffer(2 * cnt + destination.length() + 3);
for (int i = 0; i < cnt; i++) {
@ -206,10 +222,28 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
pingResults.append("+ ");
}
} else {
pingResults.append(sent ? "+ " : "- ");
if (reportTimes) {
if (sent) {
pass++;
long rtt = System.currentTimeMillis() - lastPingTime;
totalTime += rtt;
l.log((i+1) + ": + " + rtt + " ms");
} else {
fail++;
l.log((i+1) + ": -");
}
} else {
pingResults.append(sent ? "+ " : "- ");
}
}
// System.out.println(sent+" -> "+destination);
}
if (reportTimes) {
pingResults.append(" ").append(pass).append(" received ");
if (pass > 0)
pingResults.append("(average time ").append(totalTime/pass).append(" ms) ");
pingResults.append("and ").append(fail).append(" lost for destination: ");
}
pingResults.append(" ").append(destination);
synchronized (lock) { // Logger is not thread safe
l.log(pingResults.toString());
@ -219,4 +253,4 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
}
}
}
}
}

View File

@ -14,6 +14,7 @@ import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
import net.i2p.data.Base32;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
@ -361,6 +362,19 @@ public class TunnelController implements Logging {
return null;
}
public String getMyDestHashBase32() {
if (_tunnel != null) {
List sessions = _tunnel.getSessions();
for (int i = 0; i < sessions.size(); i++) {
I2PSession session = (I2PSession)sessions.get(i);
Destination dest = session.getMyDestination();
if (dest != null)
return Base32.encode(dest.calculateHash().getData());
}
}
return null;
}
public boolean getIsRunning() { return _running; }
public boolean getIsStarting() { return _starting; }

View File

@ -41,11 +41,11 @@ public class EditBean extends IndexBean {
if (tun != null)
return tun.getTargetHost();
else
return "";
return "127.0.0.1";
}
public String getTargetPort(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
if (tun != null && tun.getTargetPort() != null)
return tun.getTargetPort();
else
return "";
@ -59,7 +59,7 @@ public class EditBean extends IndexBean {
}
public String getPrivateKeyFile(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
if (tun != null && tun.getPrivKeyFile() != null)
return tun.getPrivKeyFile();
else
return "";
@ -266,4 +266,4 @@ public class EditBean extends IndexBean {
}
return props;
}
}
}

View File

@ -96,6 +96,7 @@ public class IndexBean {
_curNonce = -1;
}
}
public void setPassphrase(String phrase) {
_passphrase = phrase;
}
@ -332,15 +333,15 @@ public class IndexBean {
public String getTunnelName(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
if (tun != null && tun.getName() != null)
return tun.getName();
else
return "";
return "New Tunnel";
}
public String getClientPort(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
if (tun != null && tun.getListenPort() != null)
return tun.getListenPort();
else
return "";
@ -389,7 +390,7 @@ public class IndexBean {
public String getTunnelDescription(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null)
if (tun != null && tun.getDescription() != null)
return tun.getDescription();
else
return "";
@ -406,7 +407,12 @@ public class IndexBean {
public String getClientDestination(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun == null) return "";
if ("client".equals(tun.getType())||"ircclient".equals(tun.getType())) return tun.getTargetDestination();
if ("client".equals(tun.getType())||"ircclient".equals(tun.getType())) {
if (tun.getTargetDestination() != null)
return tun.getTargetDestination();
else
return "";
}
else return tun.getProxyList();
}
@ -431,6 +437,19 @@ public class IndexBean {
}
}
public String getDestHashBase32(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null) {
String rv = tun.getMyDestHashBase32();
if (rv != null)
return rv;
else
return "";
} else {
return "";
}
}
///
/// bean props for form submission
///
@ -707,7 +726,11 @@ public class IndexBean {
}
}
if ("interactive".equals(_profile))
config.setProperty("option.i2p.streaming.maxWindowSize", "1");
// This was 1 which doesn't make much sense
// The real way to make it interactive is to make the streaming lib
// MessageInputStream flush faster but there's no option for that yet,
// Setting it to 16 instead of the default but not sure what good that is either.
config.setProperty("option.i2p.streaming.maxWindowSize", "16");
else
config.remove("option.i2p.streaming.maxWindowSize");
}
@ -737,4 +760,4 @@ public class IndexBean {
buf.append((String)msgs.get(i)).append("\n");
}
}
}
}

View File

@ -80,6 +80,10 @@
<div id="portField" class="rowItem">
<label for="port" accesskey="P">
<span class="accessKey">P</span>ort:
<% String value = editBean.getClientPort(curTunnel);
if (value == null || "".equals(value.trim()))
out.write(" <font color=\"red\">(required)</font>");
%>
</label>
<input type="text" size="6" maxlength="5" id="port" name="port" title="Access Port Number" value="<%=editBean.getClientPort(curTunnel)%>" class="freetext" />
</div>
@ -123,6 +127,10 @@
%><div id="destinationField" class="rowItem">
<label for="targetDestination" accesskey="T">
<span class="accessKey">T</span>unnel Destination:
<% String value2 = editBean.getClientDestination(curTunnel);
if (value2 == null || "".equals(value2.trim()))
out.write(" <font color=\"red\">(required)</font>");
%>
</label>
<input type="text" size="30" id="targetDestination" name="targetDestination" title="Destination of the Tunnel" value="<%=editBean.getClientDestination(curTunnel)%>" class="freetext" />
<span class="comment">(name or destination)</span>

View File

@ -93,6 +93,10 @@
<div id="portField" class="rowItem">
<label for="targetPort" accesskey="P">
<span class="accessKey">P</span>ort:
<% String value = editBean.getTargetPort(curTunnel);
if (value == null || "".equals(value.trim()))
out.write(" <font color=\"red\">(required)</font>");
%>
</label>
<input type="text" size="6" maxlength="5" id="targetPort" name="targetPort" title="Target Port Number" value="<%=editBean.getTargetPort(curTunnel)%>" class="freetext" />
</div>
@ -112,6 +116,10 @@
%><div id="privKeyField" class="rowItem">
<label for="privKeyFile" accesskey="k">
Private <span class="accessKey">k</span>ey file:
<% String value2 = editBean.getPrivateKeyFile(curTunnel);
if (value2 == null || "".equals(value2.trim()))
out.write(" <font color=\"red\">(required)</font>");
%>
</label>
<input type="text" size="30" id="privKeyFile" name="privKeyFile" title="Path to Private Key File" value="<%=editBean.getPrivateKeyFile(curTunnel)%>" class="freetext" />
</div>
@ -129,7 +137,7 @@
<label for="localDestination" accesskey="L">
<span class="accessKey">L</span>ocal destination:
</label>
<input type="text" size="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" value="<%=editBean.getDestinationBase64(curTunnel)%>" class="freetext" />
<textarea rows="1" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off"><%=editBean.getDestinationBase64(curTunnel)%></textarea>
<span class="comment">(if known)</span>
</div>

Some files were not shown because too many files have changed in this diff Show More