Compare commits

..

133 Commits

Author SHA1 Message Date
jrandom
a8ad8644c8 0.3.1.5 (backwards compatible)
lots of bugfixes.  still no rate limiting, but, uh, lots of bugfixes
(release will be packaged and deployed later today)
2004-06-25 19:25:33 +00:00
jrandom
4e91bb88a5 workaround an aggressively up-to-spec kaffe implementation (the spec says Socket.getInetAddress() is null if not connected,
but sun lets the getInetAddress() return a value if it had connected then disconnected, while kaffe buggers off and NPEs)
2004-06-25 19:21:11 +00:00
jrandom
f60a90e2da added forum.i2p 2004-06-25 18:48:33 +00:00
jrandom
784dc0f6a7 boot up quicker 2004-06-25 18:42:27 +00:00
jrandom
e80e627fba more tests with the real TCP transport, not just the VM comm system (and for larger sims, dont keepHistory) 2004-06-25 18:41:50 +00:00
jrandom
d5987c51c9 yet another deployment option - the user can define a jbigi.ref environmental variable to specify a file from which the name of the resource to be loaded should be found (default is "jbigi.cfg")
if that file exists, the NativeBigInteger will act as if jbigi.impl was set to the contents of that file.
For instance, a jbigi.cfg containing "win-p4" would have the NativeBigInteger search the classpath for the "win-p4" file and use it as a native library.
The jbigi.ref preempts the jbigi.impl property (only if the file exists and is not empty), but the external platform specific jbigi
preempts this (e.g. jbigi.dll or libjbigi.so), as does the jbigi.enable flag.
This option lets us have the admin console write to a file to choose which jbigi to use, rather than have to parse some shell script, etc
2004-06-25 18:32:17 +00:00
jrandom
5ced441b17 dont fail the peer based on tunnel activity (it may not be their fault)
we *do* still penalize the peer based on tunnel failures, but thats in the reliability calculator, not this one.
2004-06-25 18:15:32 +00:00
jrandom
57801202fd flush the protocol flag explicitly
make the tcp connection handler nonblocking by adding another (very short lived) thread - this prevents a peer connecting to us that is very slow (or unconnectable) from forcing other cons to timeout
completely ripped out the fscking bandwidth limiter until i get it more reliable
gave threads more explicit names (for the sim)
logging
2004-06-25 18:14:12 +00:00
jrandom
a019399c3c reduce synchronization on static (instead use per context objects, for large sims) 2004-06-25 17:21:41 +00:00
jrandom
e6f610a86c dont synchronize on statics, instead use a seperate format object per context (so large sims dont get bogged down on synchronization) 2004-06-25 17:20:08 +00:00
jrandom
7ef528bbde add some minimal security to the admin console, requiring a passphrase to be entered when updating the clock offset
this works by a simple substring match of the URL - if the router.config contains the adminTimePassphrase=blah, the time update will only succeed if the URL contains "blah" in it
if the router.config does NOT contain an adminTimePassphrase, the time update WILL BE REFUSED.
aka to use the timestamper, you MUST set adminTimePassphrase AND update the clientApp.0.args= line to include the passphrase in the URL!
e.g.
 clientApp.0.args=http://localhost:7655/setTime?blah pool.ntp.org pool.ntp.org pool.ntp.org
2004-06-25 17:18:21 +00:00
jrandom
a351a29bf3 if it expired waiting on the queue for processing, kill 'er 2004-06-25 17:12:01 +00:00
jrandom
983d258bce logging 2004-06-25 17:09:55 +00:00
jrandom
f6d38dd5e0 reduce SimpleDateFormat usage (implicit in Date.toString()) 2004-06-25 17:03:13 +00:00
jrandom
d51245aada logging 2004-06-25 17:02:22 +00:00
mpc
56cf51f0f9 New configuration system 2004-06-25 01:31:02 +00:00
mpc
eb40fb9c5d typo 2004-06-24 11:51:24 +00:00
mpc
085da0cea7 Started work on a configuration options object 2004-06-24 11:47:01 +00:00
mpc
5539b19938 Added a new example program (which actually works) 2004-06-23 23:35:39 +00:00
jrandom
94feb762ca keep detailed info for the sim 2004-06-23 19:55:52 +00:00
jrandom
40b59d5a5a more valid display of bw usage (but not as fresh) 2004-06-23 19:54:12 +00:00
jrandom
9ffd147470 handle writing the stats before the period has been reached 2004-06-23 19:53:20 +00:00
jrandom
3fea4ad2ba we dont need to use this fudge in this fashion (its done on the receiving end) 2004-06-23 19:51:58 +00:00
jrandom
1ab5536879 la la la
(yeah, this is what broke cvs HEAD, causing transmission failures, disconnects, encryption errors, etc.  oops)
2004-06-23 19:50:41 +00:00
jrandom
9690a89a6d sliices are only too slow if there's something pending
logging mods
i really need to rewrite the tcp transport - the code is all functional, but the design sucks.
with the FIFO bandwidth limiter we could get away with a single 'send' thread rather than each TCPConnection having its own writer thread (but we'd still need the per-con reader thread, at least until nio is solid enough)
but maybe the rewrite can hold off until the AMOC implementation.  we'll see
2004-06-23 19:48:25 +00:00
mpc
8f895f4349 just starting this (backup) 2004-06-23 12:34:50 +00:00
mpc
980c0aa1d7 Added PRNG code 2004-06-23 11:56:53 +00:00
mpc
52fd6ca513 Get rid of Debian-specific Makefile -- gcc < 3.0 is obsolete 2004-06-22 22:49:59 +00:00
mpc
eb5dd2ff2e Now it compiles on Cygwin 2004-06-22 22:48:32 +00:00
jrandom
7ca35452eb new target - buildclean (== distclean build)
useful for my ide so i dont have to run two targets sequentially (and 'dist' goes one step further to include javadoc, which i dont need)
2004-06-22 04:56:44 +00:00
jrandom
dd781e256c new constructor 2004-06-22 04:53:22 +00:00
jrandom
551a7ab82f benchmarking large messages doesnt make much sense when we can compress the payload really really well, now does it? 2004-06-22 04:52:06 +00:00
jrandom
2901287d9e new command line flags to harvest from an explicit file list rather than using all files in a single directory
(this lets us specify lots of my.info references to make sure we harvest fresh data, rather than depending upon stat propogation)
usage: NetMonitor [configFilename] [--routers filename[,filename]*]
2004-06-22 04:50:43 +00:00
jrandom
2b714967aa 14yyp error 2004-06-22 04:44:17 +00:00
jrandom
e8734ef1e7 more logging for shutdown info 2004-06-22 04:42:27 +00:00
jrandom
14b9f9509f * allow the client subsystem to tell the clientMessagePool that a message is definitely remote (since the client subsystem should know). this reduces the churn of the message pool asking all over again
* add a new ClientWriterRunner thread (1 per I2CP connection) so that a client application that hangs or otherwise doesn't read from its i2cp socket quickly doesn't hang the whole router (since we've previously used the jobQueue for pushing I2CP messages).  This may or may not clear the intermittent eepsite bug, but I'm not counting on it to (yet).
* update various points to deal with the client writer's operation (aka doSend won't throw IOException)
* logging
* lots and lots of metrics (yeah i know some of them vary based on the compiler)
2004-06-22 04:41:31 +00:00
jrandom
b1f973d304 during initial router startup, we may try to publish "my.info" before the netDb/ dir is created, so lets make sure 2004-06-22 04:31:25 +00:00
jrandom
2f17bfd71c minor refactoring. i hate how large that method is, but beyond the essential stuff, its pretty much just logging and benchmarking.
plus, yeah, this method still takes too long in some situations.  working on identifying why...
2004-06-22 04:29:28 +00:00
jrandom
b6670ee23a lets see how fast this can theoretically go (leaving simulated delays to other components) 2004-06-22 04:26:56 +00:00
jrandom
f1036df1f6 new debugging data point 2004-06-22 04:25:24 +00:00
jrandom
5c3e815757 dummy DSA (for sim - dont run on live net) 2004-06-22 04:23:19 +00:00
jrandom
55e780d885 logging and doc of a todo (wrt bestEffort) 2004-06-22 04:16:17 +00:00
mpc
d502df7d56 Make this compile straight out of CVS (you have to have libtomcrypt compiled in a libtomcrypt-0.96 directory in your home directory) 2004-06-21 08:21:17 +00:00
mpc
beb6cc8c0f the journey of a thousand miles begins with a single step :-) 2004-06-21 07:57:11 +00:00
mpc
c99db5e75c change preprocessor conditional to check for 1/0 instead of true/false 2004-06-21 07:50:33 +00:00
mpc
65cd70a85b LibSAM 2004-06-20 11:44:53 +00:00
jrandom
5166eab5ee replaced double check locking (http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html) with the actual logic
- prepare the cache prior to use if you want to have the hash cache.
also fix the ejection policy to not clear the cache, but merely to remove sufficient values.
though maybe clearing the cache is the right thing to do so as to avoid ejection churn... hmm.
both of these fixes brought to you by the keen eyes of the one called mihi
2004-06-20 04:27:58 +00:00
jrandom
232f6f158d removed (likely already ignored by the compiler) op. force of habit from dealing with stream.read() i suppose.
thanks mihi
2004-06-20 03:48:16 +00:00
jrandom
2a07ceba62 a message send failure is no reason to drop the SAM session
for style=stream, tell the client the stream failed, and kill the virtual connection..
for raw and repliable datagrams, just carry on our merry way
2004-06-20 01:49:07 +00:00
jrandom
3e4b8c7dd4 more stats 2004-06-20 01:45:25 +00:00
jrandom
26138e213f new method - processingComplete(), which functions much just like OutNetMessage's discardData()
so drop the data when called, updating the MessageStateMonitor (and also telling the monitor on finalization, just cuz)
2004-06-20 01:40:12 +00:00
jrandom
d82796e3ad note that we've successfully processed a message (and as such drop its payload) ASAP, and only use safely cached snippets of it afterwards 2004-06-20 01:37:01 +00:00
jrandom
cdcb81c867 dont be so aggressive about waking up more jobs, since this just causes excess locking when we dont need it 2004-06-20 01:34:16 +00:00
jrandom
5669e8f060 deal with discarded payloads and use the cached version 2004-06-20 01:31:23 +00:00
jrandom
d84a40b4dc add some randomization to the startup time, so we're not too synchronous
also don't shut down so quickly, as the routers may dump some useful stats when they die a horrible death
2004-06-20 01:29:00 +00:00
jrandom
591be43763 default to building more tunnels, because tunnels r k00l
(and fix the arg parsing)
2004-06-20 01:26:59 +00:00
jrandom
97d0686354 new method: discardData() to be called as soon as we dont need the payload of a message anymore (but may still need the associated jobs/etc)
check in with the MessageStateMonitor, and cache some key attributes from the message (type, unique id, size, etc)
2004-06-20 01:21:24 +00:00
jrandom
e2da05b197 more accurrate (but less lively) bandwidth rate calculation (since we dont necessarily calculate exactly on the edge of a measurement period, we use the data from the last full period)
logging on OOM
2004-06-20 01:18:31 +00:00
jrandom
4f0052043d /me waves to our new friend, the MessageStateMonitor, which keeps track of how many messages we're dealing with in memory (and whether they've been processed & discarded yet) 2004-06-20 01:15:01 +00:00
jrandom
cfc1d1a2db publish some new stats, including the bandwidth usage (as always, routers can chose not to publish these stats) 2004-06-20 01:12:14 +00:00
jrandom
9957e6ef17 keep track of how many messages are processed in the tunnel 2004-06-20 01:09:04 +00:00
jrandom
6a02c8383c the data is hopefully discarded by now, so dont try to get at it 2004-06-20 01:02:03 +00:00
jrandom
bc0a4ee68d discard the data ASAP, and make sure we access only the safely cached snippets of it as necessary 2004-06-20 00:59:33 +00:00
jrandom
1ca615da77 InNetMessage gets a context 2004-06-20 00:57:02 +00:00
jrandom
7da0cee29a turned BandwidthLimiter into an interface, removed some of its teeth, and cleaned up TrivialBandwidthLimiter 2004-06-20 00:56:04 +00:00
jrandom
f25bccd19f add some stats for the simulator (data doesnt seem that interesting, so i havent moved them to the CommSystemImpl)
use the .discardData() functionality
2004-06-20 00:53:19 +00:00
jrandom
4e5a2e012c update since bw limiter interface changed (but dont bother to use it anymore here)
i wonder if i should remove the phttp transport now or keep it around in case it gets revived...
2004-06-20 00:50:38 +00:00
jrandom
c9ee2a92a3 dont buffer the reads, since we dont want that buffer to interfere with either the bandwidth limiting or the AES decryption
logging
2004-06-20 00:46:57 +00:00
jrandom
95a7938328 reduce the max slice time (aka max time to pump out a message + some cleanup) to 60 seconds
close connections to peers who are so slow that they leave messages on the queue to expire
reduce the default max queue size per connection to 10 messages
(as always, this is a configurable param, via "i2np.tcp.maxQueuedMessages" in router.config)
2004-06-20 00:44:43 +00:00
jrandom
baedcdb2c1 handle situations where people dont specify a client name for a client app 2004-06-20 00:40:16 +00:00
jrandom
bc06b3671a whenever a tunnel completes, log how many messages we passed through it in the stats:
tunnel.inboundMessagesProcessed
tunnel.outboundMessagesProcessed
tunnel.participatingMessagesProcessed
(for the various tunnel types)
2004-06-20 00:35:52 +00:00
jrandom
a9172811ca reduce the grace period from 5 to 2 minutes, which will cause us to test peers more often
also add some logging (log level == debug will display why we mark a peer as failing)
2004-06-20 00:31:20 +00:00
jrandom
91b1fd6d07 InNetMessage now needs a reference to a context, so give it one 2004-06-20 00:26:05 +00:00
jrandom
bab7b8b9ed discard the payload of a message ASAP (even though we may need to hang on to the message for a while, for its replyJob, etc)
take note of the fact that the tunnel had activity
minor logging and formatting updates
2004-06-20 00:24:06 +00:00
jrandom
1b7fb96ca8 dont expose a method we dont need to expose 2004-06-20 00:19:38 +00:00
jrandom
6d84b8c02f 1) use cachedXor to cut down on the, uh, xor-ing (which involves at least one new byte[32])
2) implement an optimized 'should contain' algorithm, rather than being a wuss and building + comparing a BigInteger of the xor.
3) more unit tests
this stuff is called a *lot*, since we need to pick what bucket things go in all the time.
2004-06-20 00:18:28 +00:00
jrandom
3e3749f011 added some unit tests (adding the local key (delta == 0x00) and adding 1000 random keys, all making sure nothing b0rks) 2004-06-20 00:13:05 +00:00
jrandom
52384fb3a5 persist the local router's info @ netDb/my.info in addition to under netDb/routerInfo-$hash.dat
this makes it easy for harvesting with simulations
2004-06-20 00:11:23 +00:00
jrandom
e401670087 i like logging, dont you like logging? 2004-06-20 00:08:59 +00:00
jrandom
ae0b4c59cc include the port # in the thread name, and logging 2004-06-20 00:07:37 +00:00
jrandom
0a8dc8afcc logging, its whats for dinner 2004-06-20 00:06:33 +00:00
jrandom
d59b94df66 logging, deal with times when a client doesnt have a destination yet 2004-06-20 00:05:30 +00:00
jrandom
e28502454b include the port in the thread name (useful for the sim) 2004-06-20 00:03:45 +00:00
jrandom
bbf73f0937 enforce some sanity checks on the payload size. see recent rant in DatabaseSearchReplyMessage commit for why
this is necessary.
2004-06-19 23:58:24 +00:00
jrandom
592519c45c somehow some people are getting situations where the payload doesnt decompress. wtf?
do i need to wrap the Input/Output streams we use to pipe data over the net with a verification wrapper for the messages?
e.g. prefix the serialization of all I2NPMessages sent on the wire with the SHA256 of that serialization and verify on read?
Ho hum, dunno.  maybe its something else, but the ElG/AES+SessionTag already has integrity verification so the only thing I can
think of is a checksum error that got past TCP's checking and corrupted the AES stream.
2004-06-19 23:56:41 +00:00
jrandom
cc904ba9dc use new SessionConfig constructor 2004-06-19 23:46:08 +00:00
jrandom
1679ba6719 so this String.getBytes(), its inefficient? you don't say...
(yeah, i know, this optimization takes advantage of the fact that the data in question uses single byte charsets)
2004-06-19 23:41:55 +00:00
jrandom
07fadd4a6c avoid string.getBytes like the plague 2004-06-19 23:40:03 +00:00
jrandom
57e1ff39e0 new method: cachedXor which, suprisingly, determines the xor of a hash against another hash, caching up to a certain number of values
currently uses an essentially random ejection policy, but this saves a lot of temporarly memory churn, since we xor many hashes against a router/destination's key
2004-06-19 23:35:43 +00:00
jrandom
51e259c198 avoiding the String.getBytes() since its a bitch on gc (measured for this situation) 2004-06-19 23:32:41 +00:00
jrandom
de334b003d for safety, always create a session config with a destination 2004-06-19 23:30:57 +00:00
jrandom
a61ff12390 more microoptimizations, whee! 2004-06-19 23:28:12 +00:00
jrandom
f4697be159 just a simple catch all for OOM while handling an OOM (naw, we dont recurse too much (just a little)) 2004-06-19 23:25:47 +00:00
jrandom
3835fe3960 give the shutdown hook thread a name 2004-06-19 23:13:09 +00:00
jrandom
76c374ef06 more accurate memory usage to reduce gc churn 2004-06-19 23:11:42 +00:00
jrandom
57d24bd948 read the logger.config when its been updated, even if we dont have any log messages to write out (duh)
also, a micro-optimization for charset handling identified through profiling
2004-06-19 23:02:59 +00:00
jrandom
deff14dfd8 lets see if this fixes bug 66 (http://dev.i2p.net/bugzilla/show_bug.cgi?id=66) 2004-06-13 20:27:44 +00:00
jrandom
0a479be370 include NAME=val in failed lookup replies (per spec - thanks nightblade)
fixes http://dev.i2p.net/bugzilla/show_bug.cgi?id=79
2004-06-13 20:19:16 +00:00
jrandom
ba6a2e3fd2 unit test for the bandwidth limiting functionality (TrivialBandwidthLimiter, BandwidthLimiter, BandwidthLimited{In,Out}putStream) 2004-06-13 20:03:21 +00:00
jrandom
c3a395a41e update the bandwidth limiter config properties 2004-06-13 19:59:44 +00:00
jrandom
a3136a19e9 big ol' rewrite, requiring new config settings and, er, it works pretty well.
see router.config.template mods and the new unit tests.
this implementation can cause starvation -
  e.g. lots of 1KB writes will go through before a 32KB write if the queue is low and the bwlimiter only replenishes say, 16KBps
  another impl would enforce a FIFO through thread wait/notify, etc, but would have the related overhead.
i dont know whether starvation situations will be the norm or the exception.  i'm running this on a few routers so we'll see.
2004-06-13 19:56:57 +00:00
jrandom
b631568003 deal with null routers 2004-06-13 19:48:23 +00:00
jrandom
1d0c03eca4 use the router context's properties (which now include the config settings) 2004-06-13 19:47:44 +00:00
jrandom
eb30525a26 deal with null routers (useful for testing) 2004-06-13 19:47:02 +00:00
jrandom
3e66ea3f56 include the router's config in the property settings 2004-06-13 19:45:53 +00:00
jrandom
9f1189e606 use a bandwidth limited stream instead of asking for the allocation of the entire buffer at once (since, uh, its not likely that the bandwidth limiter will ever have hundreds of KBytes available for use) 2004-06-13 19:39:42 +00:00
jrandom
698927bed4 logging 2004-06-13 19:37:18 +00:00
jrandom
8fd02ee8dd allow the stream to optionally pull from the output stream's bandwidth limit queue (useful in very strange situations) 2004-06-13 19:36:41 +00:00
jrandom
f3154e8f5e buffer between the bandwidth limiter and the raw stream 2004-06-13 19:34:46 +00:00
jrandom
878af163a9 handle null boolean value (legal, but not in this context), fixes bug reported by nickster 2004-06-13 19:32:58 +00:00
jrandom
da8341d014 reduced buffer size and updated domain name reference (dev.i2p.net, not i2p.dyndns.net) 2004-06-13 19:31:22 +00:00
jrandom
95c33e88ed handle decompress error by propogating the IOE (thanks nickster for bug report) 2004-06-13 19:30:31 +00:00
jrandom
fed8369a5f big rewrite of how we load the native implementation:
- the old method is default: it looks for jbigi.dll / libjbigi.so in the current dir (and library path)
- otherwise, you can specify -Djbigi.impl=blah and if there is a file called "blah" in the classpath (including any jar file), it will load that file as a native implementation
there are lots more javadocs now as well, and the dependency upon Log was removed (so anyone else who wants to use this just needs NativeBigInteger.java and the jbigi implementation)
2004-06-12 20:08:32 +00:00
duck
d85806e3d5 added ferret.i2p
(duck)
2004-06-09 20:06:17 +00:00
duck
097660ce53 Round-robin DNS NTP pool makes sense as default
Discussed at http://www.i2p.net/node/view/226 (thanks Nightblade)
(duck)
2004-06-09 14:30:26 +00:00
duck
b08cfbbb35 we now have a website & eepproxy is launched automatically
(duck)
2004-06-09 14:27:51 +00:00
duck
97ee3c47a0 added anonynanny.i2p
(duck)
2004-06-01 16:57:09 +00:00
duck
05918de6ab fix bug #75
the databuffer is reused so it might contain junk, therefore only use the
available amount of bytes
(duck)
2004-05-26 12:25:04 +00:00
jrandom
8d7abd8298 added hypercubus.i2p 2004-05-24 12:53:41 +00:00
brianr
727f4c3bb5 Another rfc2068 fix.
ERR_REQUEST_DENIED now returns a 403 status code. Note that I'm assuming
this error occurs because the proxy is configured to not allow connection
to non-i2p destinations. If it's issued for other reasons we might want
to consider using 503 instead.
2004-05-24 07:28:24 +00:00
brianr
7372ad0cc4 A few changes to make proxy return the proper rfc2068 status codes
instead of 404 for everything.

ERR_DESTINATION_UNKNOWN now returns 503 instead of 404 with a slightly
more clear error message.

ERR_TIMEOUT now returns 504 gateway timeout.
2004-05-24 07:08:02 +00:00
shendaras
ca6884dbca imports (sorry, includes alphabetizing, wee)
(shendaras)
2004-05-24 03:21:21 +00:00
jrandom
1ebb0ac5fb 0.3.1.4 (backwards compatible)
i'll package & push later this evening
2004-05-23 16:54:29 +00:00
jrandom
bf0e53f13b i'll swallow your soul!
er... make it queue up to 20 messages (in case of bursts), and do some more verbose logging
2004-05-23 16:52:56 +00:00
jrandom
8888a960c0 logging 2004-05-23 16:51:30 +00:00
jrandom
04be41aac5 if the send queue to the peer is too large, fail the message but also mark it as a comm error (since either their net con is insanely saturated, or disconnected)
logging
2004-05-22 12:05:34 +00:00
jrandom
fd1313d49f bugger the speed estimate - always use the measured values, and if there aren't enough measured values, use 0. 2004-05-22 12:03:38 +00:00
jrandom
3599dba5c3 javadoc 2004-05-22 12:02:51 +00:00
jrandom
67edc437d2 properly !LART on comm error, and initialize the log correctly 2004-05-22 12:02:18 +00:00
jrandom
7a39d9240c logging 2004-05-22 12:00:08 +00:00
jrandom
6d2d9aed7e correctly handle no reachable NTP servers 2004-05-22 01:51:07 +00:00
duck
3c2e5f22b6 added ogg.baffled.i2p
(duck)
2004-05-21 22:48:28 +00:00
jrandom
ddb6348bfd type safety? we dont need no stinkin' type safety!
(aka expiration vs timeoutMs, as shown by tunnel test messages that don't expire for another 30 years)
this'll leak memory for failed tunnels, so we'll push this in a new rev in the next day or two, or maybe later today if it gets really bad.
2004-05-20 13:43:09 +00:00
151 changed files with 8426 additions and 817 deletions

27
apps/enclave/LICENSE Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the author nor the names of any contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.

79
apps/enclave/Makefile Normal file
View File

@@ -0,0 +1,79 @@
#
# This Makefile is compatible with GNU Make and should work on Linux
# (Tested on Debian 3.0)
#
#
# Directories
#
BINDIR = bin
LOGDIR = log
OBJDIR = obj
SRCDIR = src
SAMINCDIR = ../sam/c/inc
SAMLIBDIR = ../sam/c/lib
TOMCRYPTDIR = $(HOME)/libtomcrypt-0.96
#
# Programs
#
CC = g++
#
# Flags
#
CFLAGS = -g -march=i486 -pipe -Wall
#
# Libraries
#
CFLAGS += -I$(SAMINCDIR) -I$(TOMCRYPTDIR)
LDFLAGS = -L$(SAMLIBDIR) -L$(TOMCRYPTDIR)
LIBS = -lsam -ltomcrypt
#
# Object files
#
OBJS = $(OBJDIR)/bigint.o \
$(OBJDIR)/chk.o \
$(OBJDIR)/config.o \
$(OBJDIR)/logger.o \
$(OBJDIR)/main.o \
$(OBJDIR)/peers.o \
$(OBJDIR)/random.o \
$(OBJDIR)/rpc.o \
$(OBJDIR)/sam.o \
$(OBJDIR)/sha1.o
#
# Build rules
#
all: depend enclave
depend:
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.cpp > .depend
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) $(CFLAGS) -o $@ -c $<
enclave: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(BINDIR)/enclave $(OBJS) $(LIBS)
#
# Cleanup rules
#
clean:
-rm -f $(BINDIR)/* $(OBJDIR)/* .depend
clean-logs:
-rm -f $(LOGDIR)/*
tidy: clean clean-logs

View File

@@ -0,0 +1,32 @@
#
# This is the Enclave configuration file. Lines starting with # and blank lines
# are ignored.
#
# The DNS name or IP address of the SAM server you will be using
samhost=localhost
# The TCP port the SAM server is listening on
samport=7656
# The destination name of this program. This can be anything. If you run
# multiple copies of Enclave off the same SAM server then each one has to have a
# unique name.
samname=enclave
# The depth used for incoming and outgoing I2P tunnels. Using a depth of 2 is
# the default and a good choice. You can set it to 0 if you don't care about
# anonymity and just want speed.
tunneldepth=0
# The location of the peer references file. You can use an absolute or relative
# path, but absolute paths are safer.
references=cfg/peers.ref
# Record every log message at or above this priority level
# debug = 0, minor = 1, info = 2, warn = 3, error = 4
loglevel=0
# The location of the Enclave log file. You can use an absolute or relative
# path, but absolute paths are safer.
logfile=log/enclave.log

View File

@@ -0,0 +1,2 @@
4KpEG0uUvTM~IZKuWZZifdmh5UU6evIPG0tE3ppoqy37AY2NJrsM8BU0EkT1SG-g18qSW9UHDp7qs7m~WzeWTXyYggEb6k6-e0GYC2Cj8ED8JV58-2~cFZumVNJ2d1hns-MGX7RZv2lz3Cz2ZVhfZxSIw9UnpV-kwVn7sQ7PBCvJYE4INbp5OlRQH1-3lXiUheoJfeZpegGTUSHUwIRWglX7w87YF~LCbJMYXDgMyA3SaxsZaun7Wc8ku4bqtbmG9u15XlmqimLUUmDG0cw77HJzqxnR1C1hx0wf-9zgH6u4jwTWk92w5tZJZSv1SHKejlPkIbRNAhZv5wroyZsn6T0koV~kTVCvbUEwILho-rHn4A6C2jLQifwE9aucziBTVq3YLK2urf1wI1jLh98iFNav40S~B2w-4xZFAQ49bOdWzY4KmVIjocVhfGi~RLl5bHD1TEJS7nOaDhI8qCSe7mR0XzZgQ~iROR~XowlwKXBzNPjKED7yN8GgV2pWRGNYAAAA
WiotuvEjGpSz7q14eZGYFpD0xNt3V~nxZdDDgKc~whkW-pardZyz~wZipHXLIOvniThDL2rxJ~OW7RxgUycCph4x--NL51kEJhMWZ~bgxPioxw-T4JGQ9LSNndt9xNOf6yhEqyokqyEOEeJjw6m2e7RX7mTRffmTlCdu6uH6rVEk22o4Uu5S26p6-LS2k9lRyMWitFd~t9cnOgLTZTE~h4d-UlAd1BGxpCTlGWcaynOQzKKtljZknZMF9Qv19MxT83t18~3IURb6aOLlC4oih9pMt1pHouZuOaStKA7cGLsXUAhSB31BvK8l4R7VhgcudwJ9EQZkZQee51hcng7K1Yqmd4lnjHHuf1mDk0YXBAWDZOM0-oEwkJWumGuYl0NUtLhNlFrBjenbjACx88qhfy6mkXfo8c-c2QqEXuD2xt4OVqrWxBTIrr1pR-E1NdIxzIvOlCbrRXaqxqu-wnrrG2vCO-1zu9NHacCVjXD7AR7p3T628wPdCUzj2~rZRcCkAAAA

169
apps/enclave/src/bigint.cpp Normal file
View File

@@ -0,0 +1,169 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "bigint.hpp"
/******************************************************************************/
// Note: All the const_casts below are necessary because libtomcrypt doesn't //
// have its arguments as const, even when they are not changed //
/******************************************************************************/
Bigint::Bigint(const Bigint& bigint)
{
init();
copyover_mp_int(bigint.mpi);
}
Bigint::Bigint(const uchar_t* data, size_t size)
{
init();
import_uraw(data, size);
}
Bigint::Bigint(uint16_t i)
{
init();
i = htons(i);
import_uraw(reinterpret_cast<uchar_t*>(&i), 2);
}
Bigint::Bigint(uint32_t i)
{
init();
i = htonl(i);
import_uraw(reinterpret_cast<uchar_t*>(&i), 4);
}
/*
* Replaces our current mp_int with another one
* (just a wrapper for mp_copy)
*/
void Bigint::copyover_mp_int(const mp_int& i)
{
int rc = mp_copy(const_cast<mp_int*>(&i), &mpi);
assert(rc == MP_OKAY);
}
/*
* Saves a Bigint to a raw unsigned big-endian integer
* Note that the result must be freed with delete[]
*
* size - filled with the size of the output
*
* Returns: binary data
*/
uchar_t* Bigint::export_uraw(size_t& size) const
{
uchar_t* out;
size = mp_unsigned_bin_size(const_cast<mp_int*>(&mpi));
if (size != 0) {
out = new uchar_t[size];
int rc = mp_to_unsigned_bin(const_cast<mp_int*>(&mpi), out);
assert(rc == MP_OKAY);
} else { // size == 0
size = 1;
out = new uchar_t[1];
out[0] = 0;
}
return out;
}
/*
* Loads a raw unsigned big-endian integer into Bigint
*
* data - binary data
* size - size of data
*/
void Bigint::import_uraw(const uchar_t* data, size_t size)
{
uchar_t tmp[size]; // mp_read_unsigned_bin() arg 2 is not const
memcpy(tmp, data, sizeof tmp); // I'm not taking any chances
int rc = mp_read_unsigned_bin(&mpi, tmp, sizeof tmp);
assert(rc == MP_OKAY);
}
/*
* Initialises the object
*/
void Bigint::init(void)
{
int rc = mp_init(&mpi);
assert(rc == MP_OKAY);
}
bool Bigint::operator<(const Bigint& rhs) const
{
int rc = mp_cmp(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi));
if (rc == MP_LT)
return true;
else
return false;
}
Bigint& Bigint::operator=(const Bigint& rhs)
{
if (this != &rhs) // check for self-assignment: a = a
copyover_mp_int(rhs.mpi);
return *this;
}
bool Bigint::operator==(const Bigint& rhs) const
{
int rc = mp_cmp(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi));
if (rc == MP_EQ)
return true;
else
return false;
}
bool Bigint::operator>(const Bigint& rhs) const
{
int rc = mp_cmp(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi));
if (rc == MP_GT)
return true;
else
return false;
}
/*
* Xors another Bigint with this Bigint and puts the result in Bigint `result'.
* We can't name it "xor" because that word is reserved in C++ (see Appendex C,
* section 3.1 in TC++PL).
*
* rhs - the bigint to xor with
* result - will be filled with the result of the xor
*/
void Bigint::x_or(const Bigint& rhs, Bigint& result) const
{
int rc = mp_xor(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi),
&result.mpi);
assert(rc == MP_OKAY);
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef BIGINT_HPP
#define BIGINT_HPP
class Bigint {
public:
Bigint(void) { init(); }
Bigint(const Bigint& bigint);
Bigint(const uchar_t* data, size_t size);
Bigint(uint16_t i);
Bigint(uint32_t i);
~Bigint(void) { mp_clear(&mpi); }
uchar_t* export_uraw(size_t& size) const;
const mp_int& get_mp_int(void) const { return mpi; }
void import_uraw(const uchar_t* data, size_t size);
bool operator<(const Bigint& rhs) const;
Bigint& operator=(const Bigint& rhs);
bool operator==(const Bigint& rhs) const;
bool operator>(const Bigint& rhs) const;
void x_or(const Bigint& rhs, Bigint& result) const;
protected:
mp_int mpi;
private:
void copyover_mp_int(const mp_int& i);
void init(void);
};
#endif // BIGINT_HPP

56
apps/enclave/src/chk.cpp Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "chk.hpp"
Chk::Chk(const uchar_t* plaintext, size_t size, const string& mime_type)
: data_size(size), mime_type(mime_type)
{
encrypt(plaintext);
}
void Chk::encrypt(const uchar_t *pt)
{
int rc = register_cipher(&twofish_desc);
assert(rc != -1);
uchar_t key[CRYPT_KEY_SIZE], iv[CRYPT_BLOCK_SIZE];
prng->get_bytes(key, CRYPT_KEY_SIZE);
prng->get_bytes(iv, CRYPT_BLOCK_SIZE);
symmetric_CTR ctr;
rc = ctr_start(find_cipher("twofish"), iv, key, CRYPT_KEY_SIZE, 0, &ctr);
assert(rc == CRYPT_OK);
ct = new uchar_t[data_size];
rc = ctr_encrypt(pt, ct, data_size, &ctr);
assert(rc == CRYPT_OK);
}

51
apps/enclave/src/chk.hpp Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef CHK_HPP
#define CHK_HPP
class Chk {
public:
//Chk(const uchar_t* cypertext, size_t size);
Chk(const uchar_t* plaintext, size_t size, const string& mime_type);
~Chk(void) { delete[] ct; }
private:
static const size_t CRYPT_BLOCK_SIZE = 16;
static const size_t CRYPT_KEY_SIZE = 32;
void encrypt(const uchar_t *pt);
uchar_t* ct; // cyphertext
const size_t data_size;
const string& mime_type; // I hate mimes.
};
#endif // CHK_HPP

148
apps/enclave/src/config.cpp Normal file
View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "bigint.hpp"
Config::Config(const string& file)
: file(file)
{
set_defaults();
parse();
configf.close();
}
/*
* Looks up a configuration option in the table and returns a constant value.
* This is the same as get_property() except the value returned is a constant.
*
* key - key to lookup
*
* Returns the value associated with the key
*/
const string& Config::get_cproperty(const string& key) const
{
for (cfgmap_ci i = cfgmap.begin(); i != cfgmap.end(); i++) {
const string s = i->first;
if (s == key)
return i->second;
}
LERROR << "Tried to lookup an invalid property: " << key << '\n';
assert(false);
// this should never occur, it's just to silence a compiler warning
string* s = new string;
return *s;
}
/*
* Gets a property as an integer (they are all stored as strings)
*
* key - key to lookup
*
* Returns an integer of the value associated with the key
*/
int Config::get_iproperty(const string& key) const
{
for (cfgmap_ci i = cfgmap.begin(); i != cfgmap.end(); i++) {
const string s = i->first;
if (s == key)
return atoi(i->second.c_str());
}
LERROR << "Tried to lookup an invalid property: " << key << '\n';
assert(false);
return 0;
}
/*
* Looks up a configuration option in the table and returns the value
*
* key - key to lookup
*
* Returns the value associated with the key
*/
string& Config::get_property(const string& key)
{
for (cfgmap_i i = cfgmap.begin(); i != cfgmap.end(); i++) {
const string s = i->first;
if (s == key)
return i->second;
}
LERROR << "Tried to lookup an invalid property: " << key << '\n';
assert(false);
// this should never occur, it's just to silence a compiler warning
string* s = new string;
return *s;
}
/*
* Parses the configuration file, replacing default values with user defined
* values
*/
void Config::parse(void)
{
configf.open(file.c_str());
if (!configf) {
cerr << "Error opening configuration file (" << file.c_str() << ")\n";
throw runtime_error("Error opening configuration file");
}
size_t line = 0;
string s;
for (getline(configf, s); configf; getline(configf, s)) {
line++;
if (s.size() == 0 || s[0] == '#') // blank line or comment
continue;
size_t eqpos = s.find("=");
if (eqpos == string::npos) {
cerr << "Error parsing line #" << line << " in " << file << ": "
<< s << '\n';
continue;
}
string key = s.substr(0, eqpos);
string value = s.substr(eqpos + 1);
//cout << "Inserting key = " << key << " value = " << value << '\n';
cfgmap.erase(key); // erase the default value created by set_defaults()
cfgmap.insert(make_pair(key, value));
}
}
/*
* If you (the programmer) add something to the config file you should also add
* it here, and vice versa
*/
void Config::set_defaults(void)
{
cfgmap.insert(make_pair("samhost", "localhost"));
cfgmap.insert(make_pair("samport", "7656"));
cfgmap.insert(make_pair("samname", "enclave"));
cfgmap.insert(make_pair("tunneldepth", "2"));
cfgmap.insert(make_pair("references", "cfg/peers.ref"));
cfgmap.insert(make_pair("loglevel", "1"));
cfgmap.insert(make_pair("logfile", "log/enclave.log"));
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef CONFIG_HPP
#define CONFIG_HPP
class Config {
public:
Config(const string& file);
const string& get_cproperty(const string& key) const;
int get_iproperty(const string& key) const;
string& get_property(const string& key);
private:
typedef map<const string, string>::const_iterator cfgmap_ci;
typedef map<const string, string>::iterator cfgmap_i;
void parse(void);
void set_defaults(void);
ifstream configf;
const string file;
map<const string, string> cfgmap;
};
#endif // CONFIG_HPP

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "logger.hpp"
Logger::Logger(const string& file)
: file(file)
{
set_pri(debug);
set_loglevel(static_cast<priority_t>(config->get_iproperty("loglevel")));
logf.open(file.c_str(), ios::app);
if (!logf) {
cerr << "Error opening log file (" << file.c_str() << ")\n";
throw runtime_error("Error opening log file");
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef LOGGER_HPP
#define LOGGER_HPP
/*
* LDEBUG - debugging messages
* LMINOR - unimportant messages
* LINFO - informational messages
* LWARN - errors we automatically recover from
* LERROR - major, important errors
*/
#if VERBOSE_LOGS
#define LDEBUG logger->set_pri(Logger::debug); (*logger) << "(D)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
#define LMINOR logger->set_pri(Logger::minor); (*logger) << "(M)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
#define LINFO logger->set_pri(Logger::info); (*logger) << "(I)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
#define LWARN logger->set_pri(Logger::warn); (*logger) << "(W)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
#define LERROR logger->set_pri(Logger::error); (*logger) << "(E)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
#else
#define LDEBUG logger->set_pri(Logger::debug); (*logger) << "(D)"
#define LMINOR logger->set_pri(Logger::minor); (*logger) << "(M)"
#define LINFO logger->set_pri(Logger::info); (*logger) << "(I)"
#define LWARN logger->set_pri(Logger::warn); (*logger) << "(W)"
#define LERROR logger->set_pri(Logger::error); (*logger) << "(E)"
#endif
class Logger {
public:
typedef enum {debug = 0, minor = 1, info = 2, warn = 3, error = 4}
priority_t;
Logger(const string& file);
void flush(void) { logf.flush(); }
priority_t get_loglevel(void) const { return loglevel; }
void set_loglevel(priority_t priority) { loglevel = priority; }
Logger& operator<<(char c)
{ if (priority >= loglevel) { logf << c; flush(); } return *this; }
Logger& operator<<(const char* c)
{ if (priority >= loglevel) { logf << c; flush(); } return *this; }
Logger& operator<<(int i)
{ if (priority >= loglevel) { logf << i; flush(); } return *this; }
Logger& operator<<(const string& s)
{ if (priority >= loglevel) { logf << s; flush(); } return *this; }
Logger& operator<<(unsigned int i)
{ if (priority >= loglevel) { logf << i; flush(); } return *this; }
void set_pri(priority_t priority) { this->priority = priority; }
private:
priority_t priority; // importance of the following log message(s)
string file;
priority_t loglevel; // write log messsages at or above this priority
ofstream logf;
};
#endif // LOGGER_HPP

84
apps/enclave/src/main.cpp Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "main.hpp"
Config *config; // Configuration options
Logger *logger; // Logging mechanism
Random *prng; // Random number generator
Sam *sam; // SAM connection
int main(int argc, char* argv[])
{
if (argc != 2) { // put some getopts stuff in here later
cerr << "Please specify the configuration file location.\n" \
"e.g. 'bin/enclave cfg/enclave.cfg'\n";
return 1;
}
try {
config = new Config(argv[1]);
} catch (const runtime_error& x) {
return 0;
}
logger = new Logger(config->get_cproperty("logfile"));
LINFO << "Enclave DHT - Built on " << __DATE__ << ' ' << __TIME__ << '\n';
prng = new Random;
try {
sam = new Sam(config->get_cproperty("samhost"),
config->get_iproperty("samport"), config->get_cproperty("samname"),
config->get_iproperty("tunneldepth"));
} catch (const Sam_error& x) {
LERROR << "SAM error: " << x.what() << '\n';
cerr << "SAM error: " << x.what() << '\n';
if (x.code() == SAM_SOCKET_ERROR) {
LERROR << "Check whether you have specified the correct SAM host " \
"and port number, and that I2P is running.\n";
cerr << "Check whether you have specified the correct SAM host " \
"and port number, and that\nI2P is running.\n";
}
return 1;
}
sam->naming_lookup();
while (sam->get_my_dest() == "")
sam->read_buffer(); // wait until we get our own dest back from lookup
sam->peers->advertise_self();
while (true)
sam->read_buffer();
delete sam;
delete prng;
delete logger;
delete config;
return 0;
}

36
apps/enclave/src/main.hpp Normal file
View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef MAIN_HPP
#define MAIN_HPP
// intentionally left blank
#endif // MAIN_HPP

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef NEAR_PEER_HPP
#define NEAR_PEER_HPP
//
// Used for finding the closest peers to a sha1
//
class Near_peer {
public:
Near_peer(const Bigint& distance, Peer* peer)
: distance(distance), peer(peer) {}
Peer* get_peer(void) const { return peer; }
bool operator<(const Near_peer& rhs) const
{ if (distance < rhs.distance) return true; else return false; }
protected:
const Bigint distance;
private:
Peer* peer;
};
#endif // NEAR_PEER_HPP

52
apps/enclave/src/peer.hpp Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef PEER_HPP
#define PEER_HPP
class Peer {
public:
Peer(const string& dest, const Sha1& kaddr)
: dest(dest), kaddr(kaddr), lag(-1) {}
const string& get_b64kaddr(void) const { return kaddr.b64hash(); }
const uchar_t* get_binkaddr(void) const { return kaddr.binhash(); }
const string& get_dest(void) const { return dest; }
int get_lag(void) const { return lag; }
const string get_sdest(void) const { return dest.substr(0, 8); }
void set_lag(int lag) { this->lag = lag; }
private:
const string dest;
const Sha1 kaddr;
int lag; // if -1, then it is unknown
};
#endif // PEER_HPP

220
apps/enclave/src/peers.cpp Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "near_peer.hpp"
#include "rpc.hpp"
#include "sha1.hpp"
#include "peers.hpp"
/*
* Inform other peers of our existence and collect the destination addresses of
* nearby peers
*/
void Peers::advertise_self(void)
{
list<Near_peer> near_peers;
get_nearest(sam->get_my_sha1(), PAR_RPCS, near_peers);
for (list<Near_peer>::const_iterator i = near_peers.begin();
i != near_peers.end(); i++) {
Rpc rpc(i->get_peer());
rpc.find_peers(sam->get_my_sha1());
}
}
/*
* Find the `n' nearest peers by xoring a sha1 with a kaddr
*
* sha1 - sha1 to find nearness to
* n - number of peers to find
* near_peers - a list to put the found peers in
*/
void Peers::get_nearest(const Sha1& sha1, size_t n, list<Near_peer>& near_peers)
{
near_peers.clear(); // prevents duplicate peers in the list
for (peersmap_i i = peersmap.begin(); i != peersmap.end(); i++) {
const Sha1& kaddr = i->first;
Bigint distance;
sha1.x_or(kaddr, distance);
Near_peer np(distance, &(i->second));
near_peers.insert(near_peers.end(), np);
}
near_peers.sort();
while (near_peers.size() > n)
near_peers.pop_back();
}
Peer* Peers::get_peer_by_dest(const sam_pubkey_t dest)
{
const string s = dest;
return get_peer_by_dest(s);
}
/*
* Gets a peer by its base 64 destination address
*
* dest - destination
*
* Returns: pointer to peer, or 0 if the peer wasn't found
*/
Peer* Peers::get_peer_by_dest(const string& dest)
{
for (peersmap_i i = peersmap.begin(); i != peersmap.end(); i++) {
Peer& tmp = i->second;
if (tmp.get_dest() == dest)
return &(i->second);
}
return 0;
}
/*
* Gets a peer by its Kademlia address
*
* kaddr - Kademlia adddress
*
* Returns: pointer to peer, or 0 if the peer wasn't found
*/
Peer* Peers::get_peer_by_kaddr(const Sha1& kaddr)
{
peersmap_i i = peersmap.find(kaddr);
if (i != peersmap.end())
return &(i->second);
else
return 0;
}
/*
* Loads peer addresses from a file
*/
void Peers::load(void)
{
string dest;
ifstream peersf(file.c_str());
if (!peersf) {
LERROR << "Couldn't load peers reference file (" << file.c_str()
<< ")\n";
if (peersmap.size() > 0)
return;
else
throw runtime_error("No peer references in memory");
}
for (getline(peersf, dest); peersf; getline(peersf, dest))
new_peer(dest);
if (peersmap.size() > 0) {
LMINOR << peersmap.size() << " peer references in memory\n";
} else
throw runtime_error("No peer references in memory");
}
Peer* Peers::new_peer(const sam_pubkey_t dest)
{
const string s = dest;
return new_peer(s);
}
/*
* Adds a newly discovered peer to the peers map
*
* dest - destination address of the peer
*
* Returns: pointer to the peer
*/
Peer* Peers::new_peer(const string& dest)
{
// Check the destination address
if (!sam->valid_dest(dest)) {
LWARN << "Bad format in peer reference: " << dest.substr(0, 8) << '\n';
return 0;
}
// Never add our own peer to the peers we can connect to
if (dest == sam->get_my_dest()) {
LDEBUG << "Not adding my own peer reference: " << dest.substr(0, 8)
<< '\n';
return 0;
}
// Be sure that the peer is not already known to us
Peer *peer = get_peer_by_dest(dest);
if (peer != 0) {
LDEBUG << "Redundant peer reference: " << dest.substr(0, 8) << '\n';
return peer;
}
// Tests passed, add it
Sha1 sha1(dest);
pair<peersmap_i, bool> p = peersmap.insert(
make_pair(sha1, Peer(dest, sha1)));
assert(p.second);
LMINOR << "New peer reference: " << dest.substr(0, 8)
<< " (Kaddr: " << sha1.b64hash() << ")\n";
peer = &(p.first->second);
return peer;
}
/*
* Saves peer destinations to a file
*
* file - the file to save to
*/
void Peers::save(void)
{
ofstream peersf(file.c_str());
if (!peersf) {
LERROR << "Error opening peers reference file (" << file.c_str()
<< ")\n";
return;
}
LDEBUG << "Saving " << peersmap.size() + 1 << " peer references\n";
peersf << sam->get_my_dest() << '\n';
for (peersmap_ci i = peersmap.begin(); i != peersmap.end(); i++) {
const Peer& tmp = i->second;
peersf << tmp.get_dest() << '\n';
}
}
/*
* Stores data on some peers
*
* sha1 - the sha1 value for the data
* data - the data
*/
void Peers::store(const Sha1& sha1)
{
list<Near_peer> near_peers;
get_nearest(sam->get_my_sha1(), PAR_RPCS, near_peers);
for (list<Near_peer>::const_iterator i = near_peers.begin();
i != near_peers.end(); i++) {
Rpc rpc(i->get_peer());
rpc.store(sha1);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef PEERS_HPP
#define PEERS_HPP
class Peers {
public:
static const int PAR_RPCS = 3; // The number of parallel RPCs to send
static const int RET_REFS = 20; // The number of peer refs to return on
// failed requests
Peers(const string& file)
: file(file)
{ load(); }
~Peers(void) { save(); }
void advertise_self(void);
void get_nearest(const Sha1& sha1, size_t n,
list<Near_peer>& near_peers);
Peer* get_peer_by_dest(const sam_pubkey_t dest);
Peer* get_peer_by_dest(const string& dest);
Peer* get_peer_by_kaddr(const Sha1& kaddr);
Peer* new_peer(const sam_pubkey_t dest);
Peer* new_peer(const string& dest);
void store(const Sha1& sha1);
private:
typedef map<const Sha1, Peer>::const_iterator peersmap_ci;
typedef map<const Sha1, Peer>::iterator peersmap_i;
void load(void);
void save(void);
const string file;
map<const Sha1, Peer> peersmap;
};
#endif // PEERS_HPP

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef PLATFORM_HPP
#define PLATFORM_HPP
/*
* Operating system
*/
#define FREEBSD 0 // FreeBSD (untested)
#define MINGW 1 // Windows native (Mingw)
#define LINUX 2 // Linux
#define CYGWIN 3 // Cygwin
/*
* System includes
*/
#include <arpa/inet.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <time.h>
using namespace std;
/*
* Define this to '1' to cause the printing of source code file and line number
* information with each log message. Set it to '0' for simple logging.
*/
#define VERBOSE_LOGS 0
/*
* Library includes
*/
#include "mycrypt.h" // LibTomCrypt
#include "sam.h" // LibSAM
/*
* Local includes
*/
#include "logger.hpp" // Logger
#include "config.hpp" // Config
#include "sam_error.hpp" // for sam.hpp
#include "bigint.hpp" // for sha1.hpp
#include "sha1.hpp" // for peers.hpp
#include "peer.hpp" // for peers.hpp
#include "near_peer.hpp" // for peers.hpp
#include "peers.hpp" // for sam.hpp
#include "sam.hpp" // SAM
#include "random.hpp" // Random
/*
* Global variables
*/
extern Config *config; // Configuration options
extern Logger *logger; // Logging mechanism
extern Random *prng; // Random number generator
extern Sam *sam; // Sam connection
#endif // PLATFORM_HPP

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "random.hpp"
/*
* Prepares the Yarrow PRNG for use
*/
Random::Random(void)
{
LMINOR << "Initalising PRNG\n";
int rc = yarrow_start(&prng);
assert(rc == CRYPT_OK);
uchar_t entropy[ENTROPY_SIZE];
size_t sz = rng_get_bytes(entropy, ENTROPY_SIZE, NULL);
assert(sz == ENTROPY_SIZE);
rc = yarrow_add_entropy(entropy, ENTROPY_SIZE, &prng);
assert(rc == CRYPT_OK);
rc = yarrow_ready(&prng);
assert(rc == CRYPT_OK);
}
/*
* Gets `size' random bytes from the PRNG
*
* random - space to fill with random bytes
* size - size of `random'
*/
void Random::get_bytes(uchar_t* random, size_t size)
{
size_t sz = yarrow_read(random, size, &prng);
assert(sz == size);
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef RANDOM_HPP
#define RANDOM_HPP
class Random {
public:
Random(void);
void get_bytes(uchar_t* random, size_t size);
private:
static const size_t ENTROPY_SIZE = 32;
prng_state prng;
};
#endif // RNG_HPP

233
apps/enclave/src/rpc.cpp Normal file
View File

@@ -0,0 +1,233 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "rpc.hpp"
// These can't be 'const' because I have to make them big-endian first
uint16_t Rpc::VERSION = htons(1);
uint16_t Rpc::OLDEST_GOOD_VERSION = htons(1);
/*
* Requests a peer to find the addresses of the closest peers to the specified
* sha1 and return them
*
* sha1 - closeness to this sha1
*/
void Rpc::find_peers(const Sha1& sha1)
{
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: FIND_PEERS\n";
// VERSION + command + bin sha1
const size_t len = sizeof VERSION + 1 + Sha1::SHA1BIN_LEN;
uchar_t buf[len];
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
p += sizeof VERSION;
*p = FIND_PEERS;
p++;
memcpy(p, sha1.binhash(), Sha1::SHA1BIN_LEN);
sam->send_dgram(peer->get_dest(), buf, len);
}
/*
* Returns the closest peer references to a Sha1
*
* sha1 - sha1 to test nearness to
*/
void Rpc::found_peers(const Sha1& sha1)
{
list<Near_peer> near_peers;
sam->peers->get_nearest(sha1, Peers::RET_REFS, near_peers);
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: FOUND_PEERS (" << near_peers.size() << " peers)\n";
// VERSION + command + number of sha1s (0-255) + bin sha1s
const size_t len = sizeof VERSION + 1 + 1 +
(near_peers.size() * (SAM_PUBKEY_LEN - 1));
assert(near_peers.size() <= 255);
uchar_t buf[len];
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
p += sizeof VERSION;
*p = FOUND_PEERS;
p++;
*p = near_peers.size();
p++;
for (list<Near_peer>::const_iterator i = near_peers.begin();
i != near_peers.end(); i++) {
const Peer* peer = i->get_peer();
memcpy(p, peer->get_dest().c_str(), (SAM_PUBKEY_LEN - 1));
p += SAM_PUBKEY_LEN - 1;
}
sam->send_dgram(peer->get_dest(), buf, len);
}
/*
* Parse incoming data and invoke the appropriate RPC
*
* data - the data
* size - the size of `data'
*/
void Rpc::parse(const void* data, size_t size)
{
uint16_t his_ver;
memcpy(&his_ver, data, sizeof VERSION);
if (ntohs(his_ver) < ntohs(VERSION)) {
LMINOR << "Ignored RPC from " << peer->get_sdest() << " ["
<< peer->get_b64kaddr() << "] using obsolete protocol version "
<< ntohs(his_ver) << '\n';
return;
} else if (size <= 4) {
LWARN << "RPC too small from " << peer->get_sdest() << " ["
<< peer->get_b64kaddr() << "]\n";
return;
}
const uchar_t* p = static_cast<const uchar_t*>(data);
if (p[2] == PING) { //-----------------------------------------------------
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: PING\n";
uint32_t ptime;
if (size != sizeof VERSION + 1 + sizeof ptime) {
LWARN << "Malformed PING RPC from " << peer->get_sdest()
<< " [" << peer->get_b64kaddr() << "]\n";
return;
}
p += sizeof VERSION + 1;
memcpy(&ptime, p, sizeof ptime);
pong(ptime); // no need to ntohl() it here because we're just copying it
return;
} else if (p[2] == PONG) { //----------------------------------------------
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: PONG\n";
uint32_t ptime;
if (size != sizeof VERSION + 1 + sizeof ptime) {
LWARN << "Malformed PONG RPC from " << peer->get_sdest()
<< " [" << peer->get_b64kaddr() << "]\n";
return;
}
p += sizeof VERSION + 1;
memcpy(&ptime, p, sizeof ptime);
ptime = ntohl(ptime);
uint32_t now = time(NULL);
peer->set_lag(now - ptime);
LDEBUG << "Lag is " << peer->get_lag() << " seconds\n";
return;
} else if (p[2] == FIND_PEERS) { //----------------------------------------
if (size != sizeof VERSION + 1 + Sha1::SHA1BIN_LEN) {
LWARN << "Malformed FIND_PEERS RPC from " << peer->get_sdest()
<< " [" << peer->get_b64kaddr() << "]\n";
return;
}
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: FIND_PEERS\n";
found_peers(Sha1(p + 4));
return;
} else if (p[2] == FOUND_PEERS) { //---------------------------------------
const size_t refs = p[3];
if (size != sizeof VERSION + 1 + 1 + (refs * (SAM_PUBKEY_LEN - 1))) {
LWARN << "Malformed FOUND_PEERS RPC from " << peer->get_sdest()
<< " [" << peer->get_b64kaddr() << "]\n";
return;
}
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: FOUND_PEERS (" << refs << " peers)\n";
p += sizeof VERSION + 1 + 1;
for (size_t i = 1; i <= refs; i++) {
sam_pubkey_t dest;
memcpy(dest, p, SAM_PUBKEY_LEN - 1); // - 1 == no NUL in RPC
dest[SAM_PUBKEY_LEN - 1] = '\0';
//LDEBUG << "Message had: " << dest << '\n';
sam->peers->new_peer(dest);
p += SAM_PUBKEY_LEN - 1;
}
return;
} else //------------------------------------------------------------------
LWARN << "Unknown RPC #" << static_cast<int>(p[2]) << " from "
<< peer->get_sdest() << " [" << peer->get_b64kaddr() << "]\n";
}
/*
* Sends a ping to someone
*/
void Rpc::ping(void)
{
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: PING\n";
uint32_t now = htonl(time(NULL));
// VERSION + command + seconds since 1970
const size_t len = sizeof VERSION + 1 + sizeof now;
uchar_t buf[len];
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
p += sizeof VERSION;
*p = PING;
p++;
memcpy(p, &now, sizeof now);
sam->send_dgram(peer->get_dest(), buf, len);
}
/*
* Sends a ping reply to someone
*
* ptime - the time the peer sent us (we echo the same time back)
*/
void Rpc::pong(uint32_t ptime)
{
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: PONG\n";
// VERSION + command + pinger's seconds since 1970 echoed back
const size_t len = sizeof VERSION + 1 + sizeof ptime;
uchar_t buf[len];
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
p += sizeof VERSION;
*p = PONG;
p++;
memcpy(p, &ptime, sizeof ptime);
sam->send_dgram(peer->get_dest(), buf, len);
}
/*
* Tells a peer to store some data
*
* sha1 - sha1 value for the data
* data - the data
*/
void Rpc::store(const Sha1& sha1)
{
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
<< "] Msg: STORE\n";
}

65
apps/enclave/src/rpc.hpp Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef RPC_HPP
#define RPC_HPP
class Rpc {
public:
// The PROTOCOL version we are using
static uint16_t VERSION;
// The oldest version we will talk to
static uint16_t OLDEST_GOOD_VERSION;
// RPC identifiers (0-255)
typedef enum {
PING = 0,
PONG = 1,
FIND_PEERS = 2,
FOUND_PEERS = 3,
STORE = 4
} rpc_t;
Rpc(Peer* peer)
: peer(peer) {};
void find_peers(const Sha1& sha1);
void parse(const void* data, size_t size);
void ping(void);
void store(const Sha1& sha1);
private:
void found_peers(const Sha1& sha1);
void pong(uint32_t ptime);
Peer* peer;
basic_string<uchar_t> data;
};
#endif // RPC_HPP

248
apps/enclave/src/sam.cpp Normal file
View File

@@ -0,0 +1,248 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "rpc.hpp"
#include "sam.hpp"
extern "C" {
/*
* Assorted callbacks required by LibSAM - ugly, but it works
*/
static void dgramback(sam_pubkey_t dest, void* data, size_t size);
static void diedback(void);
static void logback(char* str);
static void namingback(char* name, sam_pubkey_t pubkey, samerr_t result);
}
/*
* Prevents more than one Sam object from existing in the program at a time
* (LibSAM limitation)
*/
bool Sam::exists = false;
Sam::Sam(const string& samhost, uint16_t samport, const string& destname,
uint_t tunneldepth)
{
// Only allow one Sam object to exist at a time
assert(!exists);
exists = true;
// hook up callbacks
sam_dgramback = &dgramback;
sam_diedback = &diedback;
sam_logback = &logback;
sam_namingback = &namingback;
// we haven't connected to SAM yet
set_connected(false);
// now try to connect to SAM
connect(samhost.c_str(), samport, destname.c_str(), tunneldepth);
}
Sam::~Sam(void)
{
delete peers; // this must be before set_connected(false)!
if (get_connected()) {
sam_close();
set_connected(false);
}
exists = false;
}
/*
* Connects to the SAM host
*
* samhost - host that SAM is running on (hostname or IP address)
* samport - port number that SAM is running own
* destname - the destination name of this program
* tunneldepth - how long the tunnels should be
*/
void Sam::connect(const char* samhost, uint16_t samport, const char* destname,
uint_t tunneldepth)
{
assert(!get_connected());
LMINOR << "Connecting to SAM as '" << destname << "'\n";
samerr_t rc = sam_connect(samhost, samport, destname, SAM_DGRAM, tunneldepth);
if (rc == SAM_OK)
set_connected(true);
else
throw Sam_error(rc);
}
/*
* Loads peer references from disk
* Note: this can only be called after my_dest has been set
*/
void Sam::load_peers(void)
{
peers = new Peers(config->get_cproperty("references"));
}
/*
* Converts `name' to a base 64 destination
*
* name - name to lookup
*/
void Sam::naming_lookup(const string& name) const
{
assert(get_connected());
sam_naming_lookup(name.c_str());
}
/*
* Parses an incoming datagram
*
* dest - source destination address
* data - datagram payload
* size - size of `data'
*/
void Sam::parse_dgram(const string& dest, void* data, size_t size)
{
assert(get_connected());
Peer* peer = peers->new_peer(dest);
Rpc rpc(peer);
rpc.parse(data, size);
rpc.ping();
free(data);
}
/*
* Checks the SAM connection for incoming commands and invokes callbacks
*/
void Sam::read_buffer(void)
{
assert(get_connected());
sam_read_buffer();
}
/*
* Sends a datagram to a destination
*
* dest - destination to send to
* data - data to send
* size - size of `data'
*/
void Sam::send_dgram(const string& dest, uchar_t *data, size_t size)
{
samerr_t rc = sam_dgram_send(dest.c_str(), data, size);
assert(rc == SAM_OK); // i.e. not SAM_TOO_BIG
}
/*
* Sets the connection status
*
* connected - true for connected, false for disconnected
*/
void Sam::set_connected(bool connected)
{
if (!connected)
my_dest = "";
this->connected = connected;
}
/*
* Sets my destination address
*
* pubkey - the base 64 destination
*/
void Sam::set_my_dest(const sam_pubkey_t pubkey)
{
my_dest = pubkey;
my_sha1 = Sha1(my_dest);
}
/*
* Checks whether the destination specified is of a valid base 64 syntax
*
* Returns: true if it is valid, false if it isn't
*/
bool Sam::valid_dest(const string& dest)
{
if (dest.size() != 516)
return false;
if (dest.substr(512, 4) == "AAAA") // note this AAAA signifies a null
return true; // certificate - may not be true in the
else // future
return false;
}
/*
* * * * Callbacks * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Unfortunately these aren't part of the "Sam" object because they are function
* pointers to _C_ functions. As a hack, we just have them call the global Sam
* object.
*/
/*
* Callback: A datagram was received
*/
static void dgramback(sam_pubkey_t dest, void* data, size_t size)
{
sam->parse_dgram(dest, data, size);
}
/*
* Callback: The connection to SAM has failed
*/
static void diedback(void)
{
LERROR << "Connection to SAM lost!\n";
sam->set_connected(false);
throw Sam_error(SAM_SOCKET_ERROR);
}
/*
* Callback: A log message has been sent from LibSAM
*/
static void logback(char* str)
{
LINFO << "LibSAM: " << str << '\n';
}
/*
* Callback: A naming lookup has completed
*/
static void namingback(char* name, sam_pubkey_t pubkey, samerr_t result)
{
Sam_error res(result);
if (res.code() == SAM_OK) {
if (strcmp(name, "ME") == 0) {
sam->set_my_dest(pubkey);
sam->load_peers();
} else {
assert(false);
}
} else {
LERROR << "Naming look failed for '" << name << "': " << res.what()
<< '\n';
}
}

66
apps/enclave/src/sam.hpp Normal file
View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef SAM_HPP
#define SAM_HPP
class Sam {
public:
Sam(const string& samhost, uint16_t samport, const string& destname,
uint_t tunneldepth);
~Sam(void);
const string& get_my_dest(void) const { return my_dest; }
const Sha1& get_my_sha1(void) const { return my_sha1; }
void naming_lookup(const string& name = "ME") const;
void read_buffer(void);
void send_dgram(const string& dest, uchar_t *data, size_t size);
bool valid_dest(const string& dest);
Peers* peers;
//callback-private:
void load_peers(void);
void parse_dgram(const string& dest, void* data, size_t size);
void set_connected(bool connected);
void set_my_dest(const sam_pubkey_t pubkey);
private:
void connect(const char* samhost, uint16_t samport,
const char* destname, uint_t tunneldepth);
bool get_connected(void) const { return connected; }
bool connected;
static bool exists;
string my_dest;
Sha1 my_sha1;
};
#endif // SAM_HPP

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef SAM_ERROR_HPP
#define SAM_ERROR_HPP
class Sam_error {
public:
Sam_error(samerr_t error)
: errcode(error) {}
samerr_t code(void) const { return errcode; }
const char* what(void) const { return sam_strerror(errcode); }
private:
const samerr_t errcode;
};
#endif // SAM_ERROR_HPP

122
apps/enclave/src/sha1.cpp Normal file
View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include "platform.hpp"
#include "sha1.hpp"
Sha1::Sha1(void)
{
b64hashed = "No value!";
memset(binhashed, 0, sizeof binhashed);
}
Sha1::Sha1(const string& data)
{
/* Hash it */
hash_state md;
sha1_init(&md);
int rc = sha1_process(&md, reinterpret_cast<const uchar_t*>(data.c_str()),
data.size());
assert(rc == CRYPT_OK);
rc = sha1_done(&md, binhashed);
assert(rc == CRYPT_OK);
b64();
}
/*
* Initialises the Sha1 object from a binary hash
*/
Sha1::Sha1(const uchar_t binary[SHA1BIN_LEN])
{
memcpy(binhashed, binary, sizeof binhashed);
b64();
}
/*
* Base 64 the binary hash
*/
void Sha1::b64(void)
{
ulong_t outlen = 29;
char tmp[outlen];
// b64 FIXME: replace + with ~, and / with - to be like freenet
int rc = base64_encode(binhashed, sizeof binhashed, reinterpret_cast<uchar_t*>(tmp), &outlen);
assert(rc == CRYPT_OK);
b64hashed = tmp;
}
/*
* Compares two Sha1s, returning true if the this one is less than the right one
*/
bool Sha1::operator<(const Sha1& rhs) const
{
Bigint lhsnum(binhashed, SHA1BIN_LEN);
Bigint rhsnum(rhs.binhash(), SHA1BIN_LEN);
if (lhsnum < rhsnum)
return true;
else
return false;
}
/*
* Assigns a value from another Sha1 to this one
*/
Sha1& Sha1::operator=(const Sha1& rhs)
{
if (this != &rhs) { // check for self-assignment: a = a
b64hashed = rhs.b64hash();
memcpy(binhashed, rhs.binhash(), sizeof binhashed);
}
return *this;
}
/*
* Compares Sha1s for equality
*/
bool Sha1::operator==(const Sha1& rhs) const
{
if (memcmp(binhashed, rhs.binhash(), sizeof binhashed) == 0)
return true;
else
return false;
}
/*
* Xors this Sha1 with another, and stores the result in a Bigint
*
* rhs - sha1 to xor this one with
* result - will be filled with the result
*/
void Sha1::x_or(const Sha1& rhs, Bigint& result) const
{
Bigint lhsnum(binhashed, SHA1BIN_LEN);
Bigint rhsnum(rhs.binhash(), SHA1BIN_LEN);
lhsnum.x_or(rhsnum, result);
}

56
apps/enclave/src/sha1.hpp Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef SHA1_HPP
#define SHA1_HPP
class Sha1 {
public:
static const size_t SHA1BIN_LEN = 20;
Sha1(void);
Sha1(const string& data);
Sha1(const uchar_t binary[SHA1BIN_LEN]);
const string& b64hash(void) const { return b64hashed; }
const uchar_t* binhash(void) const { return binhashed; }
bool operator<(const Sha1& rhs) const;
Sha1& operator=(const Sha1& rhs);
bool operator==(const Sha1& rhs) const;
void x_or(const Sha1& rhs, Bigint& result) const;
private:
void b64(void);
string b64hashed; // base 64 of the hash
uchar_t binhashed[SHA1BIN_LEN]; // non-NUL terminated binary hash
};
#endif // SHA1_HPP

View File

@@ -11,6 +11,7 @@ import java.util.Date;
import java.util.Properties;
import net.i2p.I2PException;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
@@ -219,7 +220,8 @@ class I2PAdapter {
DataHelper.writeDate(baos, new Date(now));
int padding = size - baos.size();
byte paddingData[] = new byte[padding];
Arrays.fill(paddingData, (byte) 0x2A);
I2PAppContext.getGlobalContext().random().nextBytes(paddingData);
//Arrays.fill(paddingData, (byte) 0x2A);
DataHelper.writeLong(baos, 2, padding);
baos.write(paddingData);
boolean sent = _session.sendMessage(peer, baos.toByteArray());
@@ -600,4 +602,4 @@ class I2PAdapter {
}
}
}
}
}

View File

@@ -45,7 +45,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
private String wwwProxy;
private final static byte[] ERR_REQUEST_DENIED =
("HTTP/1.1 404 Not Found\r\n"+
("HTTP/1.1 403 Access Denied\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
@@ -54,20 +54,20 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
.getBytes();
private final static byte[] ERR_DESTINATION_UNKNOWN =
("HTTP/1.1 404 Not Found\r\n"+
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"\r\n"+
"<html><body><H1>I2P ERROR: NOT FOUND</H1>"+
"That Desitination was not found. Perhaps you pasted in the wrong "+
"BASE64 I2P Destination or the link you are following is bad. "+
"The host (or the WWW proxy, if you're using one) could also be "+
"temporarily offline. You may want to <b>retry</b>. "+
"<html><body><H1>I2P ERROR: DESTINATION NOT FOUND</H1>"+
"That I2P Desitination was not found. Perhaps you pasted in the "+
"wrong BASE64 I2P Destination or the link you are following is "+
"bad. The host (or the WWW proxy, if you're using one) could also "+
"be temporarily offline. You may want to <b>retry</b>. "+
"Could not find the following Destination:<BR><BR>")
.getBytes();
private final static byte[] ERR_TIMEOUT =
("HTTP/1.1 404 Not Found\r\n"+
("HTTP/1.1 504 Gateway Timeout\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n\r\n"+
"<html><body><H1>I2P ERROR: TIMEOUT</H1>"+

View File

@@ -14,8 +14,8 @@ import java.net.SocketException;
import java.util.Iterator;
import java.util.Properties;
import net.i2p.I2PException;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.streaming.I2PServerSocket;

View File

@@ -18,7 +18,7 @@ import net.i2p.util.Log;
* Main driver for the app that harvests data about the performance of the network,
* building summaries for each peer that change over time. <p />
*
* Usage: <code>NetMonitor [configFilename]</code> <p />
* Usage: <code>NetMonitor [configFilename] [--routers filename[,filename]*]</code> <p />
*
*
*
@@ -41,15 +41,20 @@ public class NetMonitor {
private int _exportDelay;
private String _exportDir;
private String _netDbDir;
private String _explicitRouters;
private int _summaryDurationHours;
private boolean _isRunning;
private Map _peerSummaries;
public NetMonitor() {
this(CONFIG_LOCATION_DEFAULT);
this(CONFIG_LOCATION_DEFAULT, null);
}
public NetMonitor(String configLocation) {
this(configLocation, null);
}
public NetMonitor(String configLocation, String explicitFilenames) {
_configLocation = configLocation;
_explicitRouters = explicitFilenames;
_peerSummaries = new HashMap(32);
loadConfig();
}
@@ -120,6 +125,8 @@ public class NetMonitor {
public int getSummaryDurationHours() { return _summaryDurationHours; }
/** where should we read the data from? */
public String getNetDbDir() { return _netDbDir; }
/** if specified, contains a set of filenames we want to harvest routerInfo data from */
public String getExplicitRouters() { return _explicitRouters; }
/**
* what peers are we keeping track of?
*
@@ -203,10 +210,30 @@ public class NetMonitor {
}
}
/**
* main driver for the netMonitor. the usage is:
* <code>NetMonitor [configFilename] [--routers filename[,filename]*]</code>
*/
public static final void main(String args[]) {
if (args.length == 1)
new NetMonitor(args[0]).startMonitor();
else
new NetMonitor(CONFIG_LOCATION_DEFAULT).startMonitor();
String cfgLocation = CONFIG_LOCATION_DEFAULT;
String explicitFilenames = null;
switch (args.length) {
case 0:
break;
case 1:
cfgLocation = args[0];
break;
case 2:
explicitFilenames = args[1];
break;
case 3:
cfgLocation = args[0];
explicitFilenames = args[2];
break;
default:
System.err.println("Usage: NetMonitor [configFilename] [--routers filename[,filename]*]");
return;
}
new NetMonitor(cfgLocation, explicitFilenames).startMonitor();
}
}
}

View File

@@ -7,6 +7,7 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.i2p.data.DataFormatException;
import net.i2p.data.RouterInfo;
@@ -128,12 +129,35 @@ class NetMonitorRunner implements Runnable {
* @return list of File objects pointing at the routers around
*/
private File[] listRouters() {
File dbDir = new File(_monitor.getNetDbDir());
File files[] = dbDir.listFiles(new FilenameFilter() {
public boolean accept(File f, String name) {
return name.startsWith("routerInfo-");
}
});
if (_monitor.getExplicitRouters() != null) {
return listRoutersExplicit();
} else {
File dbDir = new File(_monitor.getNetDbDir());
File files[] = dbDir.listFiles(new FilenameFilter() {
public boolean accept(File f, String name) {
return name.startsWith("routerInfo-");
}
});
return files;
}
}
/**
* Get a list of router files that were explicitly specified by the netMonitor
*
*/
private File[] listRoutersExplicit() {
StringTokenizer tok = new StringTokenizer(_monitor.getExplicitRouters().trim(), ",");
List rv = new ArrayList();
while (tok.hasMoreTokens()) {
String name = tok.nextToken();
File cur = new File(name);
if (cur.exists())
rv.add(cur);
}
File files[] = new File[rv.size()];
for (int i = 0; i < rv.size(); i++)
files[i] = (File)rv.get(i);
return files;
}
@@ -146,4 +170,4 @@ class NetMonitorRunner implements Runnable {
Thread.sleep(_monitor.getHarvestDelay());
} catch (InterruptedException ie) {}
}
}
}

27
apps/sam/c/LICENSE Normal file
View File

@@ -0,0 +1,27 @@
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the author nor the names of any contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.

View File

@@ -0,0 +1,65 @@
#
# This Makefile is compatible with GNU Make and should work on Cygwin
#
#
# Your operating system
#
OS = CYGWIN
#
# Directories
#
INCDIR = inc
LIBDIR = lib
OBJDIR = obj
SRCDIR = src
#
# Programs
#
AR = ar
CC = gcc
#
# Flags
#
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
CFLAGS += -DOS=$(OS)
CFLAGS += -I$(INCDIR)
#
# Object files
#
OBJS = $(OBJDIR)/sam.o \
$(OBJDIR)/snprintf.o \
$(OBJDIR)/strl.o
#
# Build rules
#
all: depend libsam
depend:
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -o $@ -c $<
libsam: $(OBJS)
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
#
# Cleanup rules
#
clean:
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
tidy: clean

64
apps/sam/c/Makefile.linux Normal file
View File

@@ -0,0 +1,64 @@
#
# This Makefile is compatible with GNU Make and should work on Linux (generic)
#
#
# Your operating system
#
OS = LINUX
#
# Directories
#
INCDIR = inc
LIBDIR = lib
OBJDIR = obj
SRCDIR = src
#
# Programs
#
AR = ar
CC = gcc
#
# Flags
#
CFLAGS = -g -O2 -pipe -std=c99 -Wall
CFLAGS += -DOS=$(OS)
CFLAGS += -I$(INCDIR)
#
# Object files
#
OBJS = $(OBJDIR)/sam.o \
$(OBJDIR)/strl.o
#
# Build rules
#
all: depend libsam
depend:
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -o $@ -c $<
libsam: $(OBJS)
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
#
# Cleanup rules
#
clean:
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
tidy: clean

64
apps/sam/c/Makefile.mingw Normal file
View File

@@ -0,0 +1,64 @@
#
# This Makefile is compatible with GNU Make and should work on Windows (MingW)
#
#
# Your operating system
#
OS = MINGW
#
# Directories
#
INCDIR = inc
LIBDIR = lib
OBJDIR = obj
SRCDIR = src
#
# Programs
#
AR = C:\Dev-Cpp\bin\ar
CC = C:\Dev-Cpp\bin\gcc
#
# Flags
#
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
CFLAGS += -DOS=$(OS)
CFLAGS += -I$(INCDIR)
#
# Object files
#
OBJS = $(OBJDIR)/sam.o \
$(OBJDIR)/strl.o
#
# Build rules
#
all: depend libsam
depend:
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -o $@ -c $<
libsam: $(OBJS)
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
#
# Cleanup rules
#
clean:
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
tidy: clean

View File

@@ -0,0 +1,7 @@
If you would like to make a donation to the author of this library, you can use
the following methods:
* E-Gold account number 1043280
* Paypal email mpc@innographx.com
If you want to use some other method, just ask.

View File

@@ -0,0 +1,27 @@
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the author nor the names of any contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.

9
apps/sam/c/doc/todo.txt Normal file
View File

@@ -0,0 +1,9 @@
I need to do these things:
* SAM raw support
* Write an instruction manual
Anyone can help with these things:
* Fix the example dgram-client.c
* Compile on as many platforms as possible

View File

@@ -0,0 +1,27 @@
v1.15 2004-06-23
* Added a new example program, warhammer-dgram (use with caution)
* Fixed some fatal bugs in datagram handling
* Added another error return type named SAM_TOO_BIG - some functions now
return samerr_t instead of bool
v1.10 2004-06-16
* Changed sam_strerror() to work the same as the standard library strerror()
* Ported to native MS Windows (uses the Mingw development environment)
* Fixed a probable bug in the Cygwin port
v1.05 2004-06-09
* Added an example datagram client/server program in the examples directory
* sam_read_buffer() now returns bool true if it read anything
* Added repliable datagram support - sam_connect() now has another argument
* Replaced strstr() with the more appropriate strncmp() in many places
* Fixed a parsing error for STREAM CLOSED
* Removed the old sam_naming_lookup() and renamed sam_naming_lookup_async()
to sam_naming_lookup() to replace it
* Fixed a bug in sam_stream_close() where a '\n' was not being sent after
the SAM command
* Fixed a bug where the stream ID was being improperly incremented in
sam_stream_connect()
* Added generic Linux Makefile for non-Debian distributions
v1.00 2004-06-02
* First public release

View File

@@ -0,0 +1,42 @@
#
# This Makefile is compatible with GNU Make
#
#
# Programs
#
CC = gcc
#
# Flags
#
CFLAGS = -g -O2 -pipe -std=c99 -Wall
CFLAGS += -I../inc -L../lib
LIBS = -lsam
#
# Build rules
#
all: dgram-client dgram-server warhammer-dgram
dgram-client:
$(CC) $(CFLAGS) -o dgram-client.o -c dgram-client.c
$(CC) $(CFLAGS) -o dgram-client dgram-client.o $(LIBS)
dgram-server:
$(CC) $(CFLAGS) -o dgram-server.o -c dgram-server.c
$(CC) $(CFLAGS) -o dgram-server dgram-server.o $(LIBS)
warhammer-dgram:
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
#
# Cleanup rules
#
clean:
-rm -f *.o *.exe dgram-client dgram-server warhammer-dgram

View File

@@ -0,0 +1,42 @@
#
# This Makefile is compatible with GNU Make and has Winsock linking
#
#
# Programs
#
CC = C:\Dev-Cpp\bin\gcc
#
# Flags
#
CFLAGS = -g -O2 -pipe -std=c99 -Wall
CFLAGS += -I../inc -L../lib
LIBS = -lsam -lwsock32
#
# Build rules
#
all: dgram-client dgram-server warhammer-dgram
dgram-client:
$(CC) $(CFLAGS) -o dgram-client.o -c dgram-client.c
$(CC) $(CFLAGS) -o dgram-client dgram-client.o $(LIBS)
dgram-server:
$(CC) $(CFLAGS) -o dgram-server.o -c dgram-server.c
$(CC) $(CFLAGS) -o dgram-server dgram-server.o $(LIBS)
warhammer-dgram:
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
#
# Cleanup rules
#
clean:
-rm -f *.o *.exe dgram-client dgram-server warhammer-dgram

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sam.h"
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
static void diedback(void);
static void logback(char *s);
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
/*
* This is an extremely simple echo client which shows you how LibSAM
* datagrams work. We lookup the name 'dgram-server' then send some data to
* him. If everything works, we should get the same data back.
*/
/*
* NOTE!!!!!!!! This is currently broken!
*/
int main(int argc, char* argv[])
{
samerr_t rc;
/* Hook up the callback functions */
sam_dgramback = &dgramback;
sam_diedback = &diedback;
sam_logback = &logback;
sam_namingback = &namingback;
/* Connect to the SAM server -- you can use either an IP or DNS name */
rc = sam_connect("localhost", 7656, "dgram-client", SAM_DGRAM, 0);
if (rc != SAM_OK) {
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
exit(1);
}
/*
* This is equivalent to doing a DNS lookup on the normal internet. Note
* that the dgram-server must already be running for this to work.
* When the lookup completes, we send them some data (see namingback()).
*/
sam_naming_lookup("dgram-server");
/*
* Wait for something to happen, then invoke the appropriate callback
*/
while (true)
sam_read_buffer();
return 0;
}
/*
* When we receive some data, print it out to the screen
*/
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
{
printf("Datagram received: %s\n", (char *)data);
free(data);
}
/*
* This is called whenever the SAM connection fails (like if the I2P router is
* shut down)
*/
static void diedback(void)
{
fprintf(stderr, "Lost SAM connection!\n");
exit(1);
}
/*
* The logging callback prints any logging messages from LibSAM
*/
static void logback(char *s)
{
fprintf(stderr, "LibSAM: %s\n", s);
}
/*
* When a name is resolved, send data to that destination address
*/
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
{
char *data = "Hello, invisible world!";
printf("I got %s's base 64 destination, so now I will send him some " \
"data...\n", name);
sam_dgram_send(pubkey, data, strlen(data));
/*
* ^^^ An extra NUL is appended to the data by LibSAM, so it is not
* necessary to send trailing NULs over the wire for strings. This doesn't
* cause problems with binary data, because the NUL isn't included in `size'
* in sam_dgramback().
* That is why we use strlen(data) instead of strlen(data) + 1.
*/
puts("Datagram sent");
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "sam.h"
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
static void diedback(void);
static void logback(char *s);
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
/*
* This is an extremely simple echo server which shows you how LibSAM
* datagrams work. We echo back every datagram that is sent to us.
*/
int main(int argc, char* argv[])
{
samerr_t rc;
/* Hook up the callback functions */
sam_dgramback = &dgramback;
sam_diedback = &diedback;
sam_logback = &logback;
sam_namingback = &namingback;
/* Connect to the SAM server -- you can use either an IP or DNS name */
rc = sam_connect("127.0.0.1", 7656, "dgram-server", SAM_DGRAM, 0);
if (rc != SAM_OK) {
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
exit(1);
}
/*
* At this point we just keep polling the buffer, which causes the
* appropriate callbacks to be called whenever something happens
*/
while (true)
sam_read_buffer();
return 0;
}
/*
* When we receive some data, we just ECHO the exact same data back to them
*/
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
{
puts("Echoing datagram");
sam_dgram_send(dest, data, size);
free(data);
}
/*
* This is called whenever the SAM connection fails (like if the I2P router is
* shut down)
*/
static void diedback(void)
{
fprintf(stderr, "Lost SAM connection!\n");
exit(1);
}
/*
* The logging callback prints any logging messages from LibSAM
*/
static void logback(char *s)
{
fprintf(stderr, "LibSAM: %s\n", s);
}
/*
* Not used, but the function has to be in the program anyway
*/
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
{
assert(false); /* we don't do any naming lookups in this program */
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
/*
* Warhammer-dgram: a simple denial of service tool which uses datagrams, and
* illustrates how LibSAM works.
* Use only with the utmost courtesy.
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sam.h"
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
static void diedback(void);
static void logback(char *s);
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
bool gotdest = false;
sam_pubkey_t dest;
int main(int argc, char* argv[])
{
if (argc != 2) {
fprintf(stderr, "Syntax: %s <b64dest|name>\n", argv[0]);
return 1;
}
sam_dgramback = &dgramback;
sam_diedback = &diedback;
sam_logback = &logback;
sam_namingback = &namingback;
/* a tunnel length of 2 is the default - adjust to your preference vv */
samerr_t rc = sam_connect("localhost", 7656, "TRANSIENT", SAM_DGRAM, 2);
if (rc != SAM_OK) {
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
exit(1);
}
if (strlen(argv[1]) == 516) {
memcpy(dest, argv[1], SAM_PUBKEY_LEN);
gotdest = true;
}
else
sam_naming_lookup(argv[1]);
while (!gotdest)
sam_read_buffer();
char data[SAM_DGRAM_PAYLOAD_MAX];
memset(data, '#', SAM_DGRAM_PAYLOAD_MAX);
size_t sentbytes = 0;
while (true) {
rc = sam_dgram_send(dest, data, SAM_DGRAM_PAYLOAD_MAX);
if (rc != SAM_OK) {
fprintf(stderr, "sam_dgram_send() failed: %s\n", sam_strerror(rc));
return 1;
}
sentbytes += SAM_DGRAM_PAYLOAD_MAX;
printf("Bombs away! (%u kbytes sent so far)\n", sentbytes / 1024);
sam_read_buffer();
}
return 0;
}
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
{
puts("Received a datagram (ignored)");
free(data);
}
static void diedback(void)
{
fprintf(stderr, "Lost SAM connection!\n");
exit(1);
}
static void logback(char *s)
{
fprintf(stderr, "LibSAM: %s\n", s);
}
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
{
if (result != SAM_OK) {
fprintf(stderr, "Naming lookup failed: %s\n", sam_strerror(result));
exit(1);
}
memcpy(dest, pubkey, SAM_PUBKEY_LEN);
gotdest = true;
}

140
apps/sam/c/inc/platform.h Normal file
View File

@@ -0,0 +1,140 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef PLATFORM_H
#define PLATFORM_H
/*
* Operating system
*/
#define FREEBSD 0 // FreeBSD (untested)
#define MINGW 1 // Windows native (Mingw)
#define LINUX 2 // Linux
#define CYGWIN 3 // Cygwin
#if OS == MINGW
#define INET_ADDRSTRLEN 16
#define NO_GETHOSTBYNAME2
#define NO_INET_ATON /* implies NO_INET_PTON */
#define NO_INET_NTOP
#define NO_STRL
#define NO_Z_FORMAT
#define WINSOCK
#endif
#if OS == LINUX
#define NO_GETHOSTBYNAME2
#define NO_STRL
#define NO_Z_FORMAT
#endif
#if OS == CYGWIN
#define FAST32_IS_LONG
#define INET_ADDRSTRLEN 16
#define NO_GETHOSTBYNAME2
#define NO_INET_NTOP
#define NO_INET_PTON
#define NO_SNPRINTF
#define NO_STRL
#define NO_VSNPRINTF
#define NO_Z_FORMAT
#endif
/*
* Standard C99 includes - if your compiler doesn't have these, it's time to
* upgrade
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/*
* System includes
*/
#ifdef WINSOCK
#include <winsock.h>
#else
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include <assert.h>
#include <errno.h>
#ifndef WINSOCK
#include <netdb.h>
#endif
#if defined NO_SNPRINTF || defined NO_VSNPRINTF
#include "snprintf.h"
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef NO_STRL
#include "strl.h"
#endif
#ifdef WINSOCK
#include <windows.h>
#else
#include <unistd.h>
#endif
/*
* Platform-dependent variable types
*/
#ifdef WINSOCK
typedef SOCKET socket_t;
typedef signed long ssize_t;
#else
typedef int socket_t;
#endif
/*
* Prints out the file name, line number, and function name before log message
*/
#define SAMLOG(format, ...) sam_log("%s:%d:%s: " \
format, __FILE__, __LINE__, __func__, __VA_ARGS__)
/*
* This is the same as above, except that it doesn't accept any va args
*/
#define SAMLOGS(str) sam_log("%s:%d:%s: " str, __FILE__, __LINE__, __func__)
/*
* Set this to '1' if you want the raw SAM commands to be printed on stdout
* (useful for debugging). Otherwise, set it to '0'.
*/
#define SAM_WIRETAP 0
#if SAM_WIRETAP
#include <ctype.h>
#endif
#endif /* PLATFORM_H */

123
apps/sam/c/inc/sam.h Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
#ifndef SAM_H
#define SAM_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Lengths
*/
#define SAM_CMD_LEN 128 /* the maximum length a SAM command can be */
#define SAM_DGRAM_PAYLOAD_MAX ((31 * 1024) - 30) /* max size of a single datagram packet (-30 temporary bug fix for SAM) */
#define SAM_ERRMSG_LEN 23 /* the longest message returned from sam_strerror */
#define SAM_LOGMSG_LEN 256 /* the longest log message */
#define SAM_NAME_LEN 256 /* the longest `name' arg for naming lookup callback*/
#define SAM_STREAM_PAYLOAD_MAX 32768 /* max size of a single stream packet */
#define SAM_PKCMD_LEN (SAM_PUBKEY_LEN + SAM_CMD_LEN)/*a public key SAM command*/
#define SAM_PUBKEY_LEN 517 /* it's actually 516, but +1 for '\0' */
#define SAM_REPLY_LEN 1024 /* the maximum length a SAM non-data reply can be */
/*
* Shorten some standard variable types
*/
typedef signed char schar_t;
typedef unsigned char uchar_t;
typedef unsigned int uint_t;
typedef unsigned long ulong_t;
typedef unsigned short ushort_t;
typedef enum {SAM_STREAM, SAM_DGRAM, SAM_RAW} sam_conn_t; /* SAM connection */
typedef char sam_pubkey_t[SAM_PUBKEY_LEN]; /* base 64 public key */
typedef struct {
void *data;
size_t size;
} sam_sendq_t; /* sending queue to encourage large stream packet sizes */
typedef int_fast32_t sam_sid_t; /* stream id number */
typedef enum { /* see sam_strerror() for detailed descriptions of these */
/* error codes from SAM itself (SAM_OK is not an actual "error") */
SAM_OK, SAM_CANT_REACH_PEER, SAM_DUPLICATED_DEST, SAM_I2P_ERROR,
SAM_INVALID_KEY, SAM_KEY_NOT_FOUND, SAM_PEER_NOT_FOUND, SAM_TIMEOUT,
SAM_UNKNOWN,
/* error codes from libsam */
SAM_BAD_VERSION, SAM_CALLBACKS_UNSET, SAM_SOCKET_ERROR, SAM_TOO_BIG
} samerr_t;
/*
* Public functions
*/
/* SAM controls */
extern bool sam_close(void);
extern samerr_t sam_connect(const char *samhost, uint16_t samport,
const char *destname, sam_conn_t style, uint_t tunneldepth);
extern void sam_naming_lookup(const char *name);
extern bool sam_read_buffer(void);
extern char *sam_strerror(samerr_t code);
/* SAM controls - callbacks */
extern void (*sam_diedback)(void);
extern void (*sam_logback)(char *str);
extern void (*sam_namingback)(char *name, sam_pubkey_t pubkey,
samerr_t result);
/* Stream commands */
extern void sam_stream_close(sam_sid_t stream_id);
extern sam_sid_t sam_stream_connect(const sam_pubkey_t dest);
extern samerr_t sam_stream_send(sam_sid_t stream_id, const void *data,
size_t size);
/* Stream commands - callbacks */
extern void (*sam_closeback)(sam_sid_t stream_id, samerr_t reason);
extern void (*sam_connectback)(sam_sid_t stream_id, sam_pubkey_t dest);
extern void (*sam_databack)(sam_sid_t stream_id, void *data, size_t size);
extern void (*sam_statusback)(sam_sid_t stream_id, samerr_t result);
/* Stream send queue */
extern samerr_t sam_sendq_add(sam_sendq_t *sendq, const void *data,
size_t dsize);
extern sam_sendq_t *sam_sendq_create(void);
extern void sam_sendq_send(sam_sendq_t *sendq, sam_sid_t stream_id);
/* Datagram commands */
extern samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data,
size_t size);
/* Datagram commands - callbacks */
extern void (*sam_dgramback)(sam_pubkey_t dest, void *data, size_t size);
#ifdef __cplusplus
}
#endif
#endif /* SAM_H */

49
apps/sam/c/inc/snprintf.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
/*
* Note: The snprintf.c file retains its original license (at the top of
* snprintf.c)
*/
#ifndef SNPRINTF_H
#define SNPRINTF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h> /* for va_list */
int snprintf (char *str, size_t count, const char *fmt, ...);
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
#ifdef __cplusplus
}
#endif
#endif /* SNPRINTF_H */

47
apps/sam/c/inc/strl.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of the author nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
*/
/*
* Note: The strl.c file retains its original license (at the top of strl.c)
*/
#ifndef STRL_H
#define STRL_H
#ifdef __cplusplus
extern "C" {
#endif
extern size_t strlcat(char *dst, const char *src, size_t siz);
extern size_t strlcpy(char *dst, const char *src, size_t siz);
#ifdef __cplusplus
}
#endif
#endif /* STRL_H */

1048
apps/sam/c/src/sam.c Normal file

File diff suppressed because it is too large Load Diff

851
apps/sam/c/src/snprintf.c Normal file
View File

@@ -0,0 +1,851 @@
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.org) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
* Russ Allbery <rra@stanford.edu> 2000-08-26
* fixed return value to comply with C99
* fixed handling of snprintf(NULL, ...)
*
* Hrvoje Niksic <hniksic@arsdigita.com> 2000-11-04
* include <stdio.h> for NULL.
* added support for long long.
* don't declare argument types to (v)snprintf if stdarg is not used.
*
**************************************************************/
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#ifndef NULL
# define NULL 0
#endif
/* varargs declarations: */
#include <stdarg.h>
#define HAVE_STDARGS /* let's hope that works everywhere (mj) */
#define VA_LOCAL_DECL va_list ap
#define VA_START(f) va_start(ap, f)
#define VA_SHIFT(v,t) ; /* no-op for ANSI */
#define VA_END va_end(ap)
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
#ifdef HAVE_LONG_LONG
# define LLONG long long
#else
# define LLONG long
#endif
int snprintf (char *str, size_t count, const char *fmt, ...);
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
static int dopr (char *buffer, size_t maxlen, const char *format,
va_list args);
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
LLONG value, int base, int min, int max, int flags);
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_MOD_L 6
#define DP_S_CONV 7
#define DP_S_DONE 8
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
#define DP_C_LONG 2
#define DP_C_LLONG 3
#define DP_C_LDOUBLE 4
#define char_to_int(p) (p - '0')
#define MAX(p,q) ((p >= q) ? p : q)
#define MIN(p,q) ((p <= q) ? p : q)
static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
{
char ch;
LLONG value;
LDOUBLE fvalue;
char *strvalue;
int min;
int max;
int state;
int flags;
int cflags;
int total;
size_t currlen;
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
max = -1;
ch = *format++;
total = 0;
while (state != DP_S_DONE)
{
if (ch == '\0')
state = DP_S_DONE;
switch(state)
{
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
total += dopr_outch (buffer, &currlen, maxlen, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch)
{
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch))
{
min = 10*min + char_to_int (ch);
ch = *format++;
}
else if (ch == '*')
{
min = va_arg (args, int);
ch = *format++;
state = DP_S_DOT;
}
else
state = DP_S_DOT;
break;
case DP_S_DOT:
if (ch == '.')
{
state = DP_S_MAX;
ch = *format++;
}
else
state = DP_S_MOD;
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch))
{
if (max < 0)
max = 0;
max = 10*max + char_to_int (ch);
ch = *format++;
}
else if (ch == '*')
{
max = va_arg (args, int);
ch = *format++;
state = DP_S_MOD;
}
else
state = DP_S_MOD;
break;
case DP_S_MOD:
switch (ch)
{
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
if (cflags != DP_C_LONG)
state = DP_S_CONV;
else
state = DP_S_MOD_L;
break;
case DP_S_MOD_L:
switch (ch)
{
case 'l':
cflags = DP_C_LLONG;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch)
{
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
value = (short int) va_arg (args, int);
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, LLONG);
else
value = va_arg (args, int);
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = (unsigned short int) va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, unsigned LLONG);
else
value = va_arg (args, unsigned int);
total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = (unsigned short int) va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, unsigned LLONG);
else
value = va_arg (args, unsigned int);
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
case 'x':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = (unsigned short int) va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, unsigned LLONG);
else
value = va_arg (args, unsigned int);
total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
/* um, floating point? */
total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'E':
flags |= DP_F_UP;
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'G':
flags |= DP_F_UP;
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'c':
total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
break;
case 'p':
strvalue = va_arg (args, void *);
total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min,
max, flags);
break;
case 'n':
if (cflags == DP_C_SHORT)
{
short int *num;
num = va_arg (args, short int *);
*num = currlen;
}
else if (cflags == DP_C_LONG)
{
long int *num;
num = va_arg (args, long int *);
*num = currlen;
}
else if (cflags == DP_C_LLONG)
{
LLONG *num;
num = va_arg (args, LLONG *);
*num = currlen;
}
else
{
int *num;
num = va_arg (args, int *);
*num = currlen;
}
break;
case '%':
total += dopr_outch (buffer, &currlen, maxlen, ch);
break;
case 'w':
/* not supported yet, treat as next char */
ch = *format++;
break;
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
if (buffer != NULL)
{
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else
buffer[maxlen - 1] = '\0';
}
return total;
}
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
int total = 0;
char null[] = "<NULL>";
if (value == 0)
{
value = null;
}
for (strln = 0; value[strln]; ++strln); /* strlen */
if (max >= 0 && max < strln)
strln = max;
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while (padlen > 0)
{
total += dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
while (*value && ((max < 0) || (cnt < max)))
{
total += dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
while (padlen < 0)
{
total += dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
}
return total;
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
LLONG value, int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned LLONG uvalue;
char convert[24];
unsigned int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
const char *digits;
int total = 0;
if (max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED))
{
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
}
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else
if (flags & DP_F_SPACE)
signvalue = ' ';
}
if (flags & DP_F_UP)
/* Should characters be upper case? */
digits = "0123456789ABCDEF";
else
digits = "0123456789abcdef";
do {
convert[place++] = digits[uvalue % (unsigned)base];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < sizeof (convert)));
if (place == sizeof (convert)) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX ((unsigned int)max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0) zpadlen = 0;
if (spadlen < 0) spadlen = 0;
if (flags & DP_F_ZERO)
{
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place));
#endif
/* Spaces */
while (spadlen > 0)
{
total += dopr_outch (buffer, currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
total += dopr_outch (buffer, currlen, maxlen, signvalue);
/* Zeros */
if (zpadlen > 0)
{
while (zpadlen > 0)
{
total += dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while (place > 0)
total += dopr_outch (buffer, currlen, maxlen, convert[--place]);
/* Left Justified spaces */
while (spadlen < 0) {
total += dopr_outch (buffer, currlen, maxlen, ' ');
++spadlen;
}
return total;
}
static LDOUBLE abs_val (LDOUBLE value)
{
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE pow10 (int exp)
{
LDOUBLE result = 1;
while (exp)
{
result *= 10;
exp--;
}
return result;
}
static long round (LDOUBLE value)
{
long intpart;
intpart = value;
value = value - intpart;
if (value >= 0.5)
intpart++;
return intpart;
}
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
{
int signvalue = 0;
LDOUBLE ufvalue;
char iconvert[20];
char fconvert[20];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
int total = 0;
LLONG intpart;
LLONG fracpart;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (max < 0)
max = 6;
ufvalue = abs_val (fvalue);
if (fvalue < 0)
signvalue = '-';
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else
if (flags & DP_F_SPACE)
signvalue = ' ';
#if 0
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
intpart = ufvalue;
/*
* Sorry, we only support 9 digits past the decimal because of our
* conversion method
*/
if (max > 9)
max = 9;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
fracpart = round ((pow10 (max)) * (ufvalue - intpart));
if (fracpart >= pow10 (max))
{
intpart++;
fracpart -= pow10 (max);
}
#ifdef DEBUG_SNPRINTF
dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
#endif
/* Convert integer part */
do {
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
intpart = (intpart / 10);
} while(intpart && (iplace < 20));
if (iplace == 20) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
do {
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
fracpart = (fracpart / 10);
} while(fracpart && (fplace < 20));
if (fplace == 20) fplace--;
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0)
zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0))
{
if (signvalue)
{
total += dopr_outch (buffer, currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0)
{
total += dopr_outch (buffer, currlen, maxlen, '0');
--padlen;
}
}
while (padlen > 0)
{
total += dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
if (signvalue)
total += dopr_outch (buffer, currlen, maxlen, signvalue);
while (iplace > 0)
total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0)
{
total += dopr_outch (buffer, currlen, maxlen, '.');
while (fplace > 0)
total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
}
while (zpadlen > 0)
{
total += dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
while (padlen < 0)
{
total += dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
}
return total;
}
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
{
if (*currlen + 1 < maxlen)
buffer[(*currlen)++] = c;
return 1;
}
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
if (str != NULL)
str[0] = 0;
return dopr(str, count, fmt, args);
}
/* VARARGS3 */
#ifdef HAVE_STDARGS
int snprintf (char *str,size_t count,const char *fmt,...)
#else
int snprintf (va_alist) va_dcl
#endif
{
#ifndef HAVE_STDARGS
char *str;
size_t count;
char *fmt;
#endif
VA_LOCAL_DECL;
int total;
VA_START (fmt);
VA_SHIFT (str, char *);
VA_SHIFT (count, size_t );
VA_SHIFT (fmt, char *);
total = vsnprintf(str, count, fmt, ap);
VA_END;
return total;
}
#ifdef TEST_SNPRINTF
#ifndef LONG_STRING
#define LONG_STRING 1024
#endif
int main (void)
{
char buf1[LONG_STRING];
char buf2[LONG_STRING];
char *fp_fmt[] = {
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%.1f",
NULL
};
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
NULL
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
int x, y;
int fail = 0;
int num = 0;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] != NULL ; x++)
for (y = 0; fp_nums[y] != 0 ; y++)
{
snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
fp_fmt[x], buf1, buf2);
fail++;
}
num++;
}
for (x = 0; int_fmt[x] != NULL ; x++)
for (y = 0; int_nums[y] != 0 ; y++)
{
snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
int_fmt[x], buf1, buf2);
fail++;
}
num++;
}
printf ("%d tests failed out of %d.\n", fail, num);
}
#endif /* SNPRINTF_TEST */

84
apps/sam/c/src/strl.c Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stddef.h>
#include <string.h>
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
register char *d = dst;
register const char *s = src;
register size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}

View File

@@ -330,7 +330,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
}
if (dest == null) {
return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND\n");
return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND NAME=" + name + "\n");
}
return writeString("NAMING REPLY RESULT=OK NAME=" + name
@@ -392,7 +392,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
if (!datagramSession.sendBytes(dest, data)) {
_log.error("DATAGRAM SEND failed");
return false;
return true;
}
return true;
@@ -463,7 +463,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
if (!rawSession.sendBytes(dest, data)) {
_log.error("RAW SEND failed");
return false;
return true;
}
return true;
@@ -556,7 +556,9 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
if (!streamSession.sendBytes(id, data)) {
_log.error("STREAM SEND failed");
return false;
boolean rv = writeString("STREAM CLOSED RESULT=CANT_REACH_PEER ID=" + id + " MESSAGE=\"Send of " + size + " bytes failed\"\n");
streamSession.closeConnection(id);
return rv;
}
return true;
@@ -758,7 +760,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
msg.write(("STREAM RECEIVED ID=" + id
+" SIZE=" + len + "\n").getBytes("ISO-8859-1"));
msg.write(data);
msg.write(data, 0, len);
writeBytes(msg.toByteArray());
}

View File

@@ -50,13 +50,13 @@ public class Timestamper implements Runnable {
while (true) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Querying servers " + _serverList);
long now = NtpClient.currentTime(_serverList);
if (now < 0) {
_log.error("Unable to contact any of the NTP servers - network disconnect?");
} else {
try {
long now = NtpClient.currentTime(_serverList);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Stamp time");
stampTime(now);
} catch (IllegalArgumentException iae) {
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
}
try { Thread.sleep(DELAY_MS); } catch (InterruptedException ie) {}
}

View File

@@ -12,6 +12,7 @@
</target>
<target name="dist" depends="distclean, build, javadoc" />
<target name="build" depends="builddep, jar" />
<target name="buildclean" depends="distclean, builddep, jar" />
<target name="builddep">
<!-- build *everything* here, but only once -->
<ant dir="core/java/" target="jar" />

View File

@@ -14,8 +14,8 @@ package net.i2p;
*
*/
public class CoreVersion {
public final static String ID = "$Revision: 1.6 $ $Date: 2004/05/13 18:49:08 $";
public final static String VERSION = "0.3.1.3";
public final static String ID = "$Revision: 1.8 $ $Date: 2004/05/23 11:54:29 $";
public final static String VERSION = "0.3.1.5";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);

View File

@@ -8,6 +8,7 @@ import net.i2p.client.naming.NamingService;
import net.i2p.crypto.AESEngine;
import net.i2p.crypto.CryptixAESEngine;
import net.i2p.crypto.DSAEngine;
import net.i2p.crypto.DummyDSAEngine;
import net.i2p.crypto.DummyElGamalEngine;
import net.i2p.crypto.ElGamalAESEngine;
import net.i2p.crypto.ElGamalEngine;
@@ -373,8 +374,12 @@ public class I2PAppContext {
}
private void initializeDSA() {
synchronized (this) {
if (_dsa == null)
_dsa = new DSAEngine(this);
if (_dsa == null) {
if ("off".equals(getProperty("i2p.encryption", "on")))
_dsa = new DummyDSAEngine(this);
else
_dsa = new DSAEngine(this);
}
_dsaInitialized = true;
}
}

View File

@@ -53,8 +53,7 @@ class I2CPMessageProducer {
*/
public void connect(I2PSessionImpl session) throws I2PSessionException {
CreateSessionMessage msg = new CreateSessionMessage();
SessionConfig cfg = new SessionConfig();
cfg.setDestination(session.getMyDestination());
SessionConfig cfg = new SessionConfig(session.getMyDestination());
cfg.setOptions(session.getOptions());
try {
cfg.signSessionConfig(session.getPrivateKey());

View File

@@ -10,6 +10,7 @@ package net.i2p.client;
*/
import java.io.InputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
@@ -86,10 +87,17 @@ class I2PSessionImpl2 extends I2PSessionImpl {
*/
public byte[] receiveMessage(int msgId) throws I2PSessionException {
byte compressed[] = super.receiveMessage(msgId);
if (SHOULD_COMPRESS)
return DataHelper.decompress(compressed);
else
if (_log.shouldLog(Log.DEBUG))
_log.debug("receiving message " + msgId + " with " + compressed.length + " compressed bytes");
if (SHOULD_COMPRESS) {
try {
return DataHelper.decompress(compressed);
} catch (IOException ioe) {
throw new I2PSessionException("Error decompressing message", ioe);
}
} else {
return compressed;
}
}
private boolean sendBestEffort(Destination dest, byte payload[], SessionKey keyUsed, Set tagsSent)
@@ -218,21 +226,23 @@ class I2PSessionImpl2 extends I2PSessionImpl {
boolean accepted = state.received(MessageStatusMessage.STATUS_SEND_ACCEPTED);
if ((!accepted) || (state.getMessageId() == null)) {
if (_log.shouldLog(Log.ERROR))
_log.error(getPrefix() + "State with nonce " + state.getNonce()
if (_log.shouldLog(Log.CRIT))
_log.log(Log.CRIT, getPrefix() + "State with nonce " + state.getNonce()
+ " was not accepted? (no messageId!! found=" + found
+ " msgId=" + state.getMessageId() + ")",
new Exception("Race on accept/success status messages, or reconnected?"));
+ " msgId=" + state.getMessageId() + ")");
//if (true)
// throw new OutOfMemoryError("not really an OOM, but more of jr fucking shit up");
nackTags(state);
//if (_log.shouldLog(Log.CRIT))
// _log.log(Log.CRIT, "Disconnecting/reconnecting because we never were accepted!");
//disconnect();
return false;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "After waitFor sending state " + state.getMessageId().getMessageId()
+ " / " + state.getNonce() + " found = " + found);
// WARNING: this will always be false for mode=BestEffort, even though the message may go
// through, causing every datagram to be ElGamal encrypted!
// TODO: Fix this to include support for acks received after the sendMessage completes
if (found) {
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Message sent after " + state.getElapsed() + "ms with "

View File

@@ -0,0 +1,29 @@
package net.i2p.crypto;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.util.Log;
import net.i2p.util.NativeBigInteger;
/**
* Stub that offers no authentication.
*
*/
public class DummyDSAEngine extends DSAEngine {
public DummyDSAEngine(I2PAppContext context) {
super(context);
}
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
return true;
}
public Signature sign(byte data[], SigningPrivateKey signingKey) {
Signature sig = new Signature();
sig.setData(Signature.FAKE_SIGNATURE);
return sig;
}
}

View File

@@ -161,7 +161,8 @@ public class Base64 {
private static void encode(InputStream in, OutputStream out) throws IOException {
String encoded = encode(read(in));
out.write(encoded.getBytes());
for (int i = 0; i < encoded.length(); i++)
out.write((byte)(encoded.charAt(i) & 0xFF));
}
private static void decode(InputStream in, OutputStream out) throws IOException {
@@ -415,7 +416,10 @@ public class Base64 {
* @since 1.3
*/
private static String encodeString(String s, boolean breakLines) {
return encodeBytes(s.getBytes(), breakLines);
byte src[] = new byte[s.length()];
for (int i = 0; i < src.length; i++)
src[i] = (byte)(s.charAt(i) & 0xFF);
return encodeBytes(src, breakLines);
} // end encodeString
/* ******** D E C O D I N G M E T H O D S ******** */
@@ -526,7 +530,9 @@ public class Base64 {
* @since 1.4
*/
private static byte[] standardDecode(String s) {
byte[] bytes = s.getBytes();
byte[] bytes = new byte[s.length()];
for (int i = 0; i < bytes.length; i++)
bytes[i] = (byte)(s.charAt(i) & 0xFF);
return decode(bytes, 0, bytes.length);
} // end decode

View File

@@ -34,8 +34,8 @@ import net.i2p.util.OrderedProperties;
* @author jrandom
*/
public class DataHelper {
private final static String _equal = "="; // in UTF-8
private final static String _semicolon = ";"; // in UTF-8
private final static byte _equalBytes[] = "=".getBytes(); // in UTF-8
private final static byte _semicolonBytes[] = ";".getBytes(); // in UTF-8
/** Read a mapping from the stream, as defined by the I2P data structure spec,
* and store it into a Properties object.
@@ -62,17 +62,17 @@ public class DataHelper {
int read = read(rawStream, data);
if (read != size) throw new DataFormatException("Not enough data to read the properties");
ByteArrayInputStream in = new ByteArrayInputStream(data);
byte eqBuf[] = _equal.getBytes();
byte semiBuf[] = _semicolon.getBytes();
byte eqBuf[] = new byte[_equalBytes.length];
byte semiBuf[] = new byte[_semicolonBytes.length];
while (in.available() > 0) {
String key = readString(in);
read = read(in, eqBuf);
if ((read != eqBuf.length) || (!eq(new String(eqBuf), _equal))) {
if ((read != eqBuf.length) || (!eq(eqBuf, _equalBytes))) {
break;
}
String val = readString(in);
read = read(in, semiBuf);
if ((read != semiBuf.length) || (!eq(new String(semiBuf), _semicolon))) {
if ((read != semiBuf.length) || (!eq(semiBuf, _semicolonBytes))) {
break;
}
props.put(key, val);
@@ -98,12 +98,12 @@ public class DataHelper {
String key = (String) iter.next();
String val = p.getProperty(key);
// now make sure they're in UTF-8
key = new String(key.getBytes(), "UTF-8");
val = new String(val.getBytes(), "UTF-8");
//key = new String(key.getBytes(), "UTF-8");
//val = new String(val.getBytes(), "UTF-8");
writeString(baos, key);
baos.write(_equal.getBytes());
baos.write(_equalBytes);
writeString(baos, val);
baos.write(_semicolon.getBytes());
baos.write(_semicolonBytes);
}
baos.close();
byte propBytes[] = baos.toByteArray();
@@ -154,8 +154,10 @@ public class DataHelper {
return toString(buf, buf.length);
}
private static final byte[] EMPTY_BUFFER = "".getBytes();
public static String toString(byte buf[], int len) {
if (buf == null) buf = "".getBytes();
if (buf == null) buf = EMPTY_BUFFER;
StringBuffer out = new StringBuffer();
if (len > buf.length) {
for (int i = 0; i < len - buf.length; i++)
@@ -173,7 +175,7 @@ public class DataHelper {
}
public static String toDecimalString(byte buf[], int len) {
if (buf == null) buf = "".getBytes();
if (buf == null) buf = EMPTY_BUFFER;
BigInteger val = new BigInteger(1, buf);
return val.toString(10);
}
@@ -289,12 +291,13 @@ public class DataHelper {
if (string == null) {
writeLong(out, 1, 0);
} else {
if (string.length() > 255)
int len = string.length();
if (len > 255)
throw new DataFormatException("The I2P data spec limits strings to 255 bytes or less, but this is "
+ string.length() + " [" + string + "]");
byte raw[] = string.getBytes();
writeLong(out, 1, raw.length);
out.write(raw);
writeLong(out, 1, len);
for (int i = 0; i < len; i++)
out.write((byte)(string.charAt(i) & 0xFF));
}
}
@@ -552,25 +555,20 @@ public class DataHelper {
}
/** decompress the GZIP compressed data (returning null on error) */
public static byte[] decompress(byte orig[]) {
public static byte[] decompress(byte orig[]) throws IOException {
if ((orig == null) || (orig.length <= 0)) return orig;
try {
GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(orig), orig.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream(orig.length * 2);
byte buf[] = new byte[4 * 1024];
while (true) {
int read = in.read(buf);
if (read == -1) break;
baos.write(buf, 0, read);
}
byte rv[] = baos.toByteArray();
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Decompression of " + orig.length + " into " + rv.length + " (or " + 100.0d
// * (((double) rv.length) / ((double) orig.length)) + "% savings)");
return rv;
} catch (IOException ioe) {
//_log.error("Error decompressing?", ioe);
return null;
GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(orig), orig.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream(orig.length * 2);
byte buf[] = new byte[4 * 1024];
while (true) {
int read = in.read(buf);
if (read == -1) break;
baos.write(buf, 0, read);
}
byte rv[] = baos.toByteArray();
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Decompression of " + orig.length + " into " + rv.length + " (or " + 100.0d
// * (((double) rv.length) / ((double) orig.length)) + "% savings)");
return rv;
}
}
}

View File

@@ -15,6 +15,12 @@ import java.io.OutputStream;
import net.i2p.util.Log;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
/**
* Defines the hash as defined by the I2P data structure spec.
* AA hash is the SHA-256 of some data, taking up 32 bytes.
@@ -26,10 +32,13 @@ public class Hash extends DataStructureImpl {
private byte[] _data;
private volatile String _stringified;
private volatile String _base64ed;
private Map _xorCache;
public final static int HASH_LENGTH = 32;
public final static Hash FAKE_HASH = new Hash(new byte[HASH_LENGTH]);
private static final int MAX_CACHED_XOR = 1024;
public Hash() {
setData(null);
}
@@ -48,6 +57,77 @@ public class Hash extends DataStructureImpl {
_base64ed = null;
}
/**
* Prepare this hash's cache for xor values - very few hashes will need it,
* so we don't want to waste the memory, and lazy initialization would incur
* online overhead to verify the initialization.
*
*/
public void prepareCache() {
synchronized (this) {
if (_xorCache == null)
_xorCache = new HashMap(MAX_CACHED_XOR);
}
}
/**
* Calculate the xor with the current object and the specified hash,
* caching values where possible. Currently this keeps up to MAX_CACHED_XOR
* (1024) entries, and uses an essentially random ejection policy. Later
* perhaps go for an LRU or FIFO?
*
* @throws IllegalStateException if you try to use the cache without first
* preparing this object's cache via .prepareCache()
*/
public byte[] cachedXor(Hash key) throws IllegalStateException {
if (_xorCache == null)
throw new IllegalStateException("To use the cache, you must first prepare it");
byte[] distance = (byte[])_xorCache.get(key);
if (distance == null) {
// not cached, lets cache it
int cached = 0;
synchronized (_xorCache) {
int toRemove = _xorCache.size() + 1 - MAX_CACHED_XOR;
if (toRemove > 0) {
Set keys = new HashSet(toRemove);
// this removes essentially random keys - we dont maintain any sort
// of LRU or age. perhaps we should?
int removed = 0;
for (Iterator iter = _xorCache.keySet().iterator(); iter.hasNext() && removed < toRemove; removed++)
keys.add(iter.next());
for (Iterator iter = keys.iterator(); iter.hasNext(); )
_xorCache.remove(iter.next());
}
distance = DataHelper.xor(key.getData(), getData());
_xorCache.put(key, (Object)distance);
cached = _xorCache.size();
}
if (_log.shouldLog(Log.DEBUG)) {
// explicit buffer, since the compiler can't guess how long it'll be
StringBuffer buf = new StringBuffer(128);
buf.append("miss [").append(cached).append("] from ");
buf.append(DataHelper.toHexString(getData())).append(" to ");
buf.append(DataHelper.toHexString(key.getData()));
_log.debug(buf.toString(), new Exception());
}
} else {
if (_log.shouldLog(Log.DEBUG)) {
// explicit buffer, since the compiler can't guess how long it'll be
StringBuffer buf = new StringBuffer(128);
buf.append("hit from ");
buf.append(DataHelper.toHexString(getData())).append(" to ");
buf.append(DataHelper.toHexString(key.getData()));
_log.debug(buf.toString());
}
}
return distance;
}
public void clearXorCache() {
_xorCache = null;
}
public void readBytes(InputStream in) throws DataFormatException, IOException {
_data = new byte[HASH_LENGTH];
_stringified = null;
@@ -92,4 +172,96 @@ public class Hash extends DataStructureImpl {
}
return _base64ed;
}
public static void main(String args[]) {
testFill();
testOverflow();
testFillCheck();
}
private static void testFill() {
Hash local = new Hash(new byte[HASH_LENGTH]); // all zeroes
local.prepareCache();
for (int i = 0; i < MAX_CACHED_XOR; i++) {
byte t[] = new byte[HASH_LENGTH];
for (int j = 0; j < HASH_LENGTH; j++)
t[j] = (byte)((i >> j) & 0xFF);
Hash cur = new Hash(t);
local.cachedXor(cur);
if (local._xorCache.size() != i+1) {
_log.error("xor cache size where i=" + i + " isn't correct! size = "
+ local._xorCache.size());
return;
}
}
_log.debug("Fill test passed");
}
private static void testOverflow() {
Hash local = new Hash(new byte[HASH_LENGTH]); // all zeroes
local.prepareCache();
for (int i = 0; i < MAX_CACHED_XOR*2; i++) {
byte t[] = new byte[HASH_LENGTH];
for (int j = 0; j < HASH_LENGTH; j++)
t[j] = (byte)((i >> j) & 0xFF);
Hash cur = new Hash(t);
local.cachedXor(cur);
if (i < MAX_CACHED_XOR) {
if (local._xorCache.size() != i+1) {
_log.error("xor cache size where i=" + i + " isn't correct! size = "
+ local._xorCache.size());
return;
}
} else {
if (local._xorCache.size() > MAX_CACHED_XOR) {
_log.error("xor cache size where i=" + i + " isn't correct! size = "
+ local._xorCache.size());
return;
}
}
}
_log.debug("overflow test passed");
}
private static void testFillCheck() {
Set hashes = new HashSet();
Hash local = new Hash(new byte[HASH_LENGTH]); // all zeroes
local.prepareCache();
// fill 'er up
for (int i = 0; i < MAX_CACHED_XOR; i++) {
byte t[] = new byte[HASH_LENGTH];
for (int j = 0; j < HASH_LENGTH; j++)
t[j] = (byte)((i >> j) & 0xFF);
Hash cur = new Hash(t);
hashes.add(cur);
local.cachedXor(cur);
if (local._xorCache.size() != i+1) {
_log.error("xor cache size where i=" + i + " isn't correct! size = "
+ local._xorCache.size());
return;
}
}
// now lets recheck using those same hash objects
// and see if they're cached
for (Iterator iter = hashes.iterator(); iter.hasNext(); ) {
Hash cur = (Hash)iter.next();
if (!local._xorCache.containsKey(cur)) {
_log.error("checking the cache, we dont have "
+ DataHelper.toHexString(cur.getData()));
return;
}
}
// now lets recheck with new objects but the same values
// and see if they'return cached
for (int i = 0; i < MAX_CACHED_XOR; i++) {
byte t[] = new byte[HASH_LENGTH];
for (int j = 0; j < HASH_LENGTH; j++)
t[j] = (byte)((i >> j) & 0xFF);
Hash cur = new Hash(t);
if (!local._xorCache.containsKey(cur)) {
_log.error("checking the cache, we do NOT have "
+ DataHelper.toHexString(cur.getData()));
return;
}
}
_log.debug("Fill check test passed");
}
}

View File

@@ -80,10 +80,15 @@ public class RoutingKeyGenerator {
today = _cal.getTime();
}
byte mod[] = null;
String modVal = null;
synchronized (_fmt) {
mod = _fmt.format(today).getBytes();
modVal = _fmt.format(today);
}
_log.info("Routing modifier generated: " + new String(mod));
mod = new byte[modVal.length()];
for (int i = 0; i < modVal.length(); i++)
mod[i] = (byte)(modVal.charAt(i) & 0xFF);
if (_log.shouldLog(Log.INFO))
_log.info("Routing modifier generated: " + modVal);
setModData(mod);
}

View File

@@ -47,7 +47,10 @@ public class SessionConfig extends DataStructureImpl {
private final static long OFFSET_VALIDITY = 30 * 1000;
public SessionConfig() {
_destination = null;
this(null);
}
public SessionConfig(Destination dest) {
_destination = dest;
_signature = null;
_creationDate = new Date(Clock.getInstance().now());
_options = null;
@@ -61,14 +64,6 @@ public class SessionConfig extends DataStructureImpl {
return _destination;
}
/**
* Specify the destination for which this session is supposed to connect
*
*/
public void setDestination(Destination dest) {
_destination = dest;
}
/**
* Determine when this session was authorized by the destination (so we can
* prevent replay attacks)

View File

@@ -10,13 +10,13 @@ class PersistenceHelper {
private final static String NL = System.getProperty("line.separator");
public final static void add(StringBuffer buf, String prefix, String name, String description, double value) {
buf.append("# ").append(prefix.toUpperCase()).append(name.toUpperCase()).append(NL);
buf.append("# ").append(prefix).append(name).append(NL);
buf.append("# ").append(description).append(NL);
buf.append(prefix).append(name).append('=').append(value).append(NL).append(NL);
}
public final static void add(StringBuffer buf, String prefix, String name, String description, long value) {
buf.append("# ").append(prefix.toUpperCase()).append(name.toUpperCase()).append(NL);
buf.append("# ").append(prefix).append(name).append(NL);
buf.append("# ").append(description).append(NL);
buf.append(prefix).append(name).append('=').append(value).append(NL).append(NL);
}
@@ -27,7 +27,7 @@ class PersistenceHelper {
try {
return Long.parseLong(val);
} catch (NumberFormatException nfe) {
_log.error("Error formatting " + val + " into a long", nfe);
_log.warn("Error formatting " + val + " into a long", nfe);
}
} else {
_log.warn("Key " + prefix + name + " does not exist");
@@ -41,10 +41,10 @@ class PersistenceHelper {
try {
return Double.parseDouble(val);
} catch (NumberFormatException nfe) {
_log.error("Error formatting " + val + " into a double", nfe);
_log.warn("Error formatting " + val + " into a double", nfe);
}
} else {
_log.error("Key " + prefix + name + " does not exist");
_log.warn("Key " + prefix + name + " does not exist");
}
return 0;
}

View File

@@ -50,7 +50,7 @@ public class HTTPSendData {
con.setRequestProperty("Content-length", "" + length);
OutputStream out = con.getOutputStream();
byte buf[] = new byte[64 * 1024];
byte buf[] = new byte[1 * 1024];
int read;
long sent = 0;
GZIPOutputStream zipOut = new GZIPOutputStream(out);
@@ -79,7 +79,7 @@ public class HTTPSendData {
for (int i = 0; i < data.length; i++)
data[i] = (byte) ((i % 26) + 'a');
boolean sent = HTTPSendData.postData("http://i2p.dnsalias.net/cgi-bin/submitMessageHistory", data.length,
boolean sent = HTTPSendData.postData("http://dev.i2p.net/cgi-bin/submitMessageHistory", data.length,
new ByteArrayInputStream(data));
_log.debug("Sent? " + sent);
try {

View File

@@ -43,11 +43,16 @@ public class I2PThread extends Thread {
try {
super.run();
} catch (Throwable t) {
try {
// we cant assume log is created
if (_log == null) _log = new Log(I2PThread.class);
_log.log(Log.CRIT, "Killing thread " + getName(), t);
} catch (Throwable woof) {
System.err.println("Died within the OOM itself");
t.printStackTrace();
}
if (t instanceof OutOfMemoryError)
fireOOM((OutOfMemoryError)t);
// we cant assume log is created
if (_log == null) _log = new Log(I2PThread.class);
_log.log(Log.CRIT, "Killing thread " + getName(), t);
}
}

View File

@@ -438,8 +438,14 @@ public class LogManager {
_writer.flushRecords();
}
private static int __id = 0;
private class ShutdownHook extends Thread {
private int _id;
public ShutdownHook() {
_id = ++__id;
}
public void run() {
setName("Log " + _id + " shutdown ");
shutdown();
}
}

View File

@@ -27,7 +27,10 @@ class LogRecordFormatter {
private final static int MAX_PRIORITY_LENGTH = 5;
public static String formatRecord(LogManager manager, LogRecord rec) {
StringBuffer buf = new StringBuffer(1024);
int size = 64 + rec.getMessage().length();
if (rec.getThrowable() != null)
size += 512;
StringBuffer buf = new StringBuffer(size);
char format[] = manager._getFormat();
for (int i = 0; i < format.length; ++i) {
switch ((int) format[i]) {
@@ -53,7 +56,7 @@ class LogRecordFormatter {
}
buf.append(NL);
if (rec.getThrowable() != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
PrintWriter pw = new PrintWriter(baos, true);
rec.getThrowable().printStackTrace(pw);
try {

View File

@@ -47,6 +47,7 @@ class LogWriter implements Runnable {
rotateFile();
while (_write) {
flushRecords();
rereadConfig();
}
}
@@ -70,6 +71,9 @@ class LogWriter implements Runnable {
} finally {
try { Thread.sleep(100); } catch (InterruptedException ie) {}
}
}
private void rereadConfig() {
long now = Clock.getInstance().now();
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
_manager.rereadConfig();
@@ -94,7 +98,9 @@ class LogWriter implements Runnable {
if (val == null) return;
if (_currentOut == null) rotateFile();
byte b[] = val.getBytes();
byte b[] = new byte[val.length()];
for (int i = 0; i < b.length; i++)
b[i] = (byte)val.charAt(i);
try {
_currentOut.write(b);
_numBytesInCurrentFile += b.length;
@@ -185,4 +191,4 @@ class LogWriter implements Runnable {
}
return buf.toString();
}
}
}

View File

@@ -1,5 +1,4 @@
package net.i2p.util;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
@@ -11,26 +10,100 @@ package net.i2p.util;
import java.math.BigInteger;
import java.util.Random;
import java.security.SecureRandom;
import net.i2p.crypto.CryptoConstants;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
/**
* <p>BigInteger that takes advantage of the jbigi library for the modPow operation,
* which accounts for a massive segment of the processing cost of asymmetric
* crypto. The jbigi library itself is basically just a JNI wrapper around the
* GMP library - a collection of insanely efficient routines for dealing with
* big numbers.</p>
*
* There are three environmental properties for configuring this component: <ul>
* <li><b>jbigi.enable</b>: whether to use the native library (defaults to "true")</li>
* <li><b>jbigi.impl</b>: select which resource to use as the native implementation</li>
* <li><b>jbigi.ref</b>: the file specified in this parameter may contain a resource
* name to override jbigi.impl (defaults to "jbigi.cfg")</li>
* </ul>
*
* <p>If jbigi.enable is set to false, this class won't even attempt to use the
* native library, but if it is set to true (or is not specified), it will first
* check the platform specific library path for the "jbigi" library, as defined by
* {@link Runtime#loadLibrary} - e.g. C:\windows\jbigi.dll or /lib/libjbigi.so.
* If that fails, it reviews the jbigi.impl environment property - if that is set,
* it checks all of the components in the CLASSPATH for the file specified and
* attempts to load it as the native library. If jbigi.impl is not set, if there
* is no matching resource, or if that resource is not a valid OS/architecture
* specific library, the NativeBigInteger will revert to using the pure java
* implementation.</p>
*
* <p>That means <b>NativeBigInteger will not attempt to guess the correct
* platform/OS/whatever</b> - applications using this class should define that
* property prior to <i>referencing</i> the NativeBigInteger (or before loading
* the JVM, of course). Alternately, people with custom built jbigi implementations
* in their OS's standard search path (LD_LIBRARY_PATH, etc) needn't bother.</p>
*
* <p>One way to deploy the native library is to create a jbigi.jar file containing
* all of the native implementations with filenames such as "win-athlon", "linux-p2",
* "freebsd-sparcv4", where those files are the OS specific libraries (the contents of
* the DLL or .so file built for those OSes / architectures). The user would then
* simply specify -Djbigi.impl=win-athlon and this component would pick up that
* library.</p>
*
* <p>Another way is to create a seperate jbigi.jar file for each platform containing
* one file - "native", where that file is the OS / architecture specific library
* implementation, as above. This way the user would download the correct jbigi.jar
* (and not all of the libraries for platforms/OSes they don't need) and would specify
* -Djbigi.impl=native.</p>
*
* <p>Running this class by itself does a basic unit test and benchmarks the
* NativeBigInteger.modPow vs. the BigInteger.modPow by running a 2Kbit op 100
* times. At the end, if the native implementation is loaded this will output
* something like:</p>
* <pre>
* native run time: 6090ms (60ms each)
* java run time: 68067ms (673ms each)
* native = 8.947066860593239% of pure java time
* </pre>
*
* <p>If the native implementation is not loaded, it will start by saying:</p>
* <pre>
* WARN: Native BigInteger library jbigi not loaded - using pure java
* </pre>
* <p>Then go on to run the test, finally outputting:</p>
* <pre>
* java run time: 64653ms (640ms each)
* However, we couldn't load the native library, so this doesn't test much
* </pre>
*
*/
public class NativeBigInteger extends BigInteger {
private final static Log _log = new Log(NativeBigInteger.class);
/** did we load the native lib correctly? */
private static boolean _nativeOk = false;
/**
* do we want to dump some basic success/failure info to stderr during
* initialization? this would otherwise use the Log component, but this makes
* it easier for other systems to reuse this class
*/
private static final boolean _doLog = true;
private static String DEFAULT_REF_FILENAME = "jbigi.cfg";
static {
try {
System.loadLibrary("jbigi");
_nativeOk = true;
_log.info("Native BigInteger library jbigi loaded");
} catch (UnsatisfiedLinkError ule) {
_nativeOk = false;
_log.log(Log.CRIT, "Native BigInteger library jbigi not loaded - using pure java");
_log.warn("jbigi not loaded", ule);
}
loadNative();
}
/**
* calculate (base ^ exponent) % modulus.
* calculate (base ^ exponent) % modulus.
* @param base big endian twos complement representation of the base (but it must be positive)
* @param exponent big endian twos complement representation of the exponent
* @param modulus big endian twos complement representation of the modulus
@@ -68,34 +141,48 @@ public class NativeBigInteger extends BigInteger {
else
return super.modPow(exponent, m);
}
/**
* <p>Compare the BigInteger.modPow vs the NativeBigInteger.modPow of some
* really big (2Kbit) numbers 100 different times and benchmark the
* performance (or shit a brick if they don't match). </p>
*
*/
public static void main(String args[]) {
if (_nativeOk)
System.out.println("Native library loaded");
else
System.out.println("Native library NOT loaded");
System.out.println("Warming up the random number generator...");
RandomSource.getInstance().nextBoolean();
System.out.println("Random number generator warmed up");
runTest(100);
}
int numRuns = 100;
if (args.length == 1) {
try {
numRuns = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
}
}
BigInteger jg = new BigInteger(CryptoConstants.elgg.toByteArray());
BigInteger jp = new BigInteger(CryptoConstants.elgp.toByteArray());
/* the sample numbers are elG generator/prime so we can test with reasonable numbers */
private final static byte[] _sampleGenerator = new BigInteger("2").toByteArray();
private final static byte[] _samplePrime = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16).toByteArray();
private static void runTest(int numRuns) {
System.out.println("DEBUG: Warming up the random number generator...");
SecureRandom rand = new SecureRandom();
rand.nextBoolean();
System.out.println("DEBUG: Random number generator warmed up");
BigInteger jg = new BigInteger(_sampleGenerator);
BigInteger jp = new BigInteger(_samplePrime);
long totalTime = 0;
long javaTime = 0;
int runsProcessed = 0;
for (runsProcessed = 0; runsProcessed < numRuns; runsProcessed++) {
BigInteger bi = new BigInteger(2048, RandomSource.getInstance());
NativeBigInteger g = new NativeBigInteger(CryptoConstants.elgg.toByteArray());
NativeBigInteger p = new NativeBigInteger(CryptoConstants.elgp.toByteArray());
BigInteger bi = new BigInteger(2048, rand);
NativeBigInteger g = new NativeBigInteger(_sampleGenerator);
NativeBigInteger p = new NativeBigInteger(_samplePrime);
NativeBigInteger k = new NativeBigInteger(1, bi.toByteArray());
long beforeModPow = System.currentTimeMillis();
BigInteger myValue = g.modPow(k, p);
@@ -106,31 +193,168 @@ public class NativeBigInteger extends BigInteger {
totalTime += (afterModPow - beforeModPow);
javaTime += (afterJavaModPow - afterModPow);
if (!myValue.equals(jval)) {
_log.error("[" + runsProcessed + "]\tnative modPow != java modPow");
_log.error("native modPow value: " + myValue.toString());
_log.error("java modPow value: " + jval.toString());
_log.error("run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
System.err.println("[" + runsProcessed + "]\tnative modPow != java modPow");
System.err.println("ERROR: [" + runsProcessed + "]\tnative modPow != java modPow");
System.err.println("ERROR: native modPow value: " + myValue.toString());
System.err.println("ERROR: java modPow value: " + jval.toString());
System.err.println("ERROR: run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
break;
} else {
_log.debug("current run time: " + (afterModPow - beforeModPow) + "ms (total: " + totalTime + "ms, "
+ (totalTime / (runsProcessed + 1)) + "ms each)");
System.out.println("DEBUG: current run time: " + (afterModPow - beforeModPow) + "ms (total: "
+ totalTime + "ms, " + (totalTime / (runsProcessed + 1)) + "ms each)");
}
}
_log.info(numRuns + " runs complete without any errors");
_log.info("run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
System.out.println("INFO: run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
if (numRuns == runsProcessed)
System.out.println(runsProcessed + " runs complete without any errors");
System.out.println("INFO: " + runsProcessed + " runs complete without any errors");
else
System.out.println(runsProcessed + " runs until we got an error");
System.out.println("ERROR: " + runsProcessed + " runs until we got an error");
if (_nativeOk) {
System.out.println("native run time: \t" + totalTime + "ms (" + (totalTime / (runsProcessed + 1))
+ "ms each)");
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
System.out.println("native = " + ((totalTime * 100.0d) / (double) javaTime) + "% of pure java time");
} else {
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
System.out.println("However, we couldn't load the native library, so this doesn't test much");
}
}
/**
* <p>Do whatever we can to load up the native library backing this BigInteger's modPow.
* If it can find a custom built jbigi.dll / libjbigi.so, it'll use that. Otherwise
* it'll try to look in the classpath for the correct library (see loadFromResource).
* If the user specifies -Djbigi.enable=false it'll skip all of this.</p>
*
*/
private static final void loadNative() {
String wantedProp = System.getProperty("jbigi.enable", "true");
boolean wantNative = "true".equalsIgnoreCase(wantedProp);
if (wantNative) {
boolean loaded = loadGeneric();
if (loaded) {
_nativeOk = true;
if (_doLog)
System.err.println("INFO: Native BigInteger library jbigi loaded");
} else {
loaded = loadFromResource();
if (loaded) {
_nativeOk = true;
if (_doLog)
System.err.println("INFO: Native BigInteger library jbigi loaded from resource");
} else {
_nativeOk = false;
if (_doLog)
System.err.println("WARN: Native BigInteger library jbigi not loaded - using pure java");
}
}
} else {
if (_doLog)
System.err.println("INFO: Native BigInteger library jbigi not loaded - using pure java");
}
}
/**
* <p>Try loading it from an explictly build jbigi.dll / libjbigi.so first, before
* looking into a jbigi.jar for any other libraries.</p>
*
* @return true if it was loaded successfully, else false
*
*/
private static final boolean loadGeneric() {
try {
System.loadLibrary("jbigi");
return true;
} catch (UnsatisfiedLinkError ule) {
return false;
}
}
/**
* <p>Check all of the jars in the classpath for the file specified by the
* environmental property "jbigi.impl" and load it as the native library
* implementation. For instance, a windows user on a p4 would define
* -Djbigi.impl=win-686 if there is a jbigi.jar in the classpath containing the
* files "win-686", "win-athlon", "freebsd-p4", "linux-p3", where each
* of those files contain the correct binary file for a native library (e.g.
* windows DLL, or a *nix .so). </p>
*
* <p>This is a pretty ugly hack, using the general technique illustrated by the
* onion FEC libraries. It works by pulling the resource, writing out the
* byte stream to a temporary file, loading the native library from that file,
* then deleting the file.</p>
*
* @return true if it was loaded successfully, else false
*
*/
private static final boolean loadFromResource() {
String resourceName = getResourceName();
if (resourceName == null) return false;
URL resource = NativeBigInteger.class.getClassLoader().getResource(resourceName);
if (resource == null) {
if (_doLog)
System.err.println("ERROR: Resource name [" + resourceName + "] was not found");
return false;
}
File outFile = null;
try {
InputStream libStream = resource.openStream();
outFile = File.createTempFile("jbigi", "lib.tmp");
FileOutputStream fos = new FileOutputStream(outFile);
byte buf[] = new byte[4096*1024];
while (true) {
int read = libStream.read(buf);
if (read < 0) break;
fos.write(buf, 0, read);
}
fos.close();
System.load(outFile.getPath());
return true;
} catch (UnsatisfiedLinkError ule) {
if (_doLog) {
System.err.println("ERROR: The resource " + resourceName
+ " was not a valid library for this platform");
ule.printStackTrace();
}
return false;
} catch (IOException ioe) {
if (_doLog) {
System.err.println("ERROR: Problem writing out the temporary native library data");
ioe.printStackTrace();
}
return false;
} finally {
if (outFile != null) {
outFile.deleteOnExit();
}
}
}
private static final String getResourceName() {
String jbigiRefFile = System.getProperty("jbigi.ref");
if (jbigiRefFile == null)
jbigiRefFile = DEFAULT_REF_FILENAME;
File refFile = new File(jbigiRefFile);
if (refFile.exists()) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(refFile)));
String resourceName = in.readLine();
if ( (resourceName != null) || (resourceName.trim().length() <= 0) )
return resourceName;
} catch (IOException ioe) {
if (_doLog) {
System.err.println("WARN: Unable to read the jbigi reference file " + jbigiRefFile);
ioe.printStackTrace();
}
} finally {
if (in != null) try { in.close(); } catch (IOException ioe) {}
}
}
// the file doesnt exist, or it is empty, so use the jbigi.impl system env
return System.getProperty("jbigi.impl");
}
}

View File

@@ -27,8 +27,7 @@ class SessionConfigTest extends StructureTest {
TestData.registerTest(new SessionConfigTest(), "SessionConfig");
}
public DataStructure createDataStructure() throws DataFormatException {
SessionConfig cfg = new SessionConfig();
cfg.setDestination((Destination)(new DestinationTest()).createDataStructure());
SessionConfig cfg = new SessionConfig((Destination)(new DestinationTest()).createDataStructure());
cfg.setSignature((Signature)(new SignatureTest()).createDataStructure());
Properties options = new Properties();
options.setProperty("routerHost", "localhost");

View File

@@ -1,6 +1,11 @@
; TC's hosts.txt guaranteed freshness
; $Id: hosts.txt,v 1.6 2004/05/15 23:42:17 jrandom Exp $
; $Id: hosts.txt,v 1.11 2004/06/09 15:06:17 duck Exp $
; changelog:
; (1.38) added forum.i2p
; (1.36) added ferret.i2p
; (1.36) added anonynanny.i2p
; (1.35) added hypercubus.i2p
; (1.34) added ogg.baffled.i2p
; (1.33) added morph.i2p
; (1.32) added nickster.i2p
; (1.31) added mush.zeit.i2p (i2p's first eepMUSH)
@@ -90,4 +95,9 @@ xilog.i2p=yHOthRzTaowYM0dH0H8LfHeBpNzfVnBL9TtVSPF1bAImcm0tI1jyw4dERfijVunXviLGQ0
mush.zeit.i2p=3mYATMQg83VtUln0eEi9-LZYJ-0wCuhFu5PnDV6mYWFnLwbPf2rG22jyhOBw2h1fXcj3lJg7VnLRx-PGYQIWsIle~z1FBrOyT9ydqGrjbQYJ0bqBYUnWSR-xuHOGWiJ8lH34uqZ~j~owvhH-NAKs332BkSCl36HsjJF46i00ICS4qxJQ9l7YBtGYAvoliMN4rz0FETPsvwroyQ7JptfovHe1yviF5bfjeZ9ITP5EpYpyOVtfR7ELpvjYN3mH087TrgvJWL5Sz4qjAc122luTHDZ~Z01Ti3d0GluOF0Fh8cugcMXZTcSZLLcoo1UX8Iv~azxYoYw4MB-w9o4ftxZGawHnkzNCX9LXvQb9IHtURGu4p~eKQKT3YBDEM1qIZL-AdOeoUJ87wLke-ukLBTErYrszIiBgCr22pAHbH12ygH63UAKgzChg4eYfQ0Ku-I6PukG3QQhn029cYz8KO9LG5cT6QzeMbGIQ0cVgkbxM6028DXQaChA6Ul8lCOR56ZDPAAAA
nickster.i2p=03EPxP9pVIchR0LIyekAgPivoiSe~9HG8EusGNApSpOyfOgiWS-7JY8XZ0UVRExfRJSi4eQIqp2ViK0iQu69cMLdNQjqNVIFAxgMRyIicLijU163GttbX6OKkruMQ1jBsvzOd2glbQCTKjEcxU979aBDMRNXHOdz-baG3aDKvm75LJA4-whBiuS2ywS15xotHPRrBnNBTPoPY8-1GJa3fXELybWlRroSsvHwhsPvBb4eCSjUkNbXpStingnIXLJYdzMUTbYkJejERO~zyB9MriUDR8lYO9rnc3rlZWed1QO5Io0q4VOq4hnYagxwYcTxmHW5gIQ74cfZMEF3hHC2EH-YVwDXhsb3mOE-Z9PoC4hcLrk0wttYvsMJWHfgh8ju5nzH2eIlUQ0wYO5zhvMAeZMTThSqkj8offt5eOxafINRMkten598bU4LI~pgWWdxTkj7hCWaI7FHfa2cBETp0hq5xqSmL0wQZmZCSDmjXhxwNh0mRtCgnz3e1UhWLFzRAAAA
morph.i2p=NSooB7Q~AEYQejfZgmG7edN5gsphur-YUhsmzmaznqwyDe1hPEjPwGOtvygZBRqiTL3GNtAeFSJQ7fWYW7BAEGJgGR~z0HkpTHpyiBTVYZsaaNWFV7yR4MVCo6T2cEs5obvMwpEBEfdNU26kLWPqRS1wZdx7U~d04sz5kOTsNELqdHi-54~OPWdKWSCHM24PvIVo28IL9y1S58LNQVW-IOjLP4edOyKw0zrcal0T5SKRyDY7XnDGdE0drPG91vDLWWbSMnV3aFZE97YeYlUhmv7Bh6jNHzE2n9kZygVsMcSOoMZ8HENQLxo9CQwn4CxMZ33uk1o4PV2JpLHWaX075UY9YroHsNJRAuV6LGm-3guKH~P3k7j4wlwLLFzMjeMrhrNsUGrYyx8n4d6kU6EvhiJOA0suVud1cDUkAuxoAZv04CvSvJ5-cgIDvjZFb1jCQpwKvgmWYhJNSs8dhrm2f~EdgFAvPHfjHLz2c7~opMMK-6dXSH1tR~mtIYmnPip5AAAA
ogg.baffled.i2p=~FkFF79EA9udRvT740pj07ffO9D5j7kPCih0qj4JvS5tNJdpEMj~D9l-K4J3SKC11T-lwduq9H2j6Ax5dvZXo2TRaSMH0QugGscam2FylydhmxQdST8KiTPtV3kipF5I0~Fwl5TO-~wz4kpQTrR0UwliVwBBz2NfhD2-wTJN43LE-11xH45QvQ0Hl666tkOadXhcy9IKABJuiXj6mfNLdiRsGg0ds3LQYPvWUloUCR0ZOwdJ3wxOJSYf6oSH0sbGX9Lh6-sOgDFbCkwKmo7ftyr0n-kMbvjyvtPGYx0EKz-5-2bOlpQ9OFU7fgrqCmvWqQmLMgonddNz0DWzggigB5msYnKEuKrcwqJ53NMEyT1KUNW29vtSriglSLeoFRPGtAN5D5nzH2EWXBG8l~3eGANDnj~rVBhk2SP4oNrxjII6stdz25pKyK9zXUErp7R2J9U6jGzBOm0hYdRl0jNR4DyqaHE8t0qGimJX82~3QVA6hmB09E21Grqqp2noZvoEAAAA
hypercubus.i2p=F4I0cx7eSRGDfHXEnjq673~8Nxizu3xopKjfwKCyBRqRgQEv241IJ6PXIH7xs1YheutNKiM2hYW9z279UMnr6i0dLUhoh98whzbjTeykEvTbCRjCpHzJq6U6VMuwygLDyNohoPvyZZb8u8l8ljpdV7idicgo7gIEQCsNzTEA7E3AG2X06uxBr1RRkfaU2zDueVvxoi7kkvjKm2iJ455Dr8KBCeAWgq1X~OuFnwXWWgtrNEu-UaBuADZ1q6oMrPFOhdQW3J-8LlMq20BblCLLMxIvkJuZC4F7K0krK1~KFdlchQIj2MOxpRfD8TTXTfISpC05NlgDMY4xpFdv-ziFjSjljNm0NYJABQ~yqIcVXXNyDV8TY7Ya5jtG8~UibyWKq6bSYyWgQbsegGCpLzov6BH9MvBGuG8HRhTx-HLSLcBiPBjqYmfMsK31FllnUVeYLShSPgJ1IRrmTADe52ADqCNh37BnQJT0VQePw93spm8ci~Kz3-MsQssX8kl3e4aXAAAA
anonynanny.i2p=U-xjIR-MQZ7iLKViaaIpfMzOWthI8jSMyougGi6catC4fmBJjkmo18SZ1Vyy1mXZVhXae~Aqgwlvo-3svus9pzmjykY4ejJWwEuIsL5A3Kk2R6y4h96RuRhvMulH4FBO9Mw4GOsRAhfHYA1ifzQYvs7ZbOwwYMgJ0Y8kDBRtgXNSZPBq59VFUCjg9ON1bca7lGFhgTxzihgZF5MksZKuuX7IAJmUqAZziI9cqRQw4aWTaAfKteOnNp~r7vrjHbfUNezW~OLBj69FXZzEY7uBaoBJut42I4JpQ9ms0cgk~15ExdYACxgjyPNJXX-qrKNLIe7OqOIDqaMFtBTEA4TZpR5nVU7uAXC~XkLggoFMMwqm24rXU1VsGTikGaVtwJNEuCd~KI-711fQ2YDKMkzp7ragbzYGJJKdJUwuJQkTgN-LHUrx1Rccqe5Bz-OMkVkC7KvN1367xywXSrKsXijyy1vBY1BiacB8jT83Kq2LcYjFdy467ny63tlhNvuHp79MAAAA
ferret.i2p=P9EUYEBRkuA6R4nqLHrJzcqA64KjOpnQahDeb2SJZdGywI7E70Rf2TzXguryTmNLJb9riDiFouAzsb30FwF0I93Qx8iMq9ADVH6NowUgcXUaBJWoFh6dEnwwCcSbVsn1CvqoEgl-9GA2nm4NSqQv8RU4g3qrr~bfMP-gZLU4lroHb6LqCF3JNz8dege100n994nqxqdUaX1JpxDacq8jG4W5p3bUhlovQNj3cLcHG5K5PVB4jGqjkq-7UHvh0-blHoBhnYLABCe8IM2GAxgGEmS0zjQIXinsUu1wtLVmVMXF6Iy7bVf4~q80ngVNA7M~MVyNzNAocVkgb4bfhAX8WAuAA17XwsG3thWMJFYrWqKKq0hN5cDdbUNYjgx-ue~D~Sm0oJvUGjJVJnPfkbu-mO2bEQvGZaYml7kKF2kxmdmcFWAa-1HKnUXf35kKwYFWx10i8mSmLWhIx~Wvk~RIzNqjqVSy3Nbc6OkfCLvGcTQOtK-5b-BcU8HiZJJH2XOLAAAA
forum.i2p=XaZscxXGaXxuIkZDX87dfN0dcEG1xwSXktDbMX9YBOQ1LWbf0j6Kzde37j8dlPUhUK9kqVRZWpDtP7a2QBRl3aT~t~bYRj5bgTOIf9hTW46iViKdKObR-wPPjej~Px8OSYrXbFv2KUekS4baXcqHS7aJMy4rcbC1hsJm3qcXtut~7VFwEhg9w-HrHhsT5aYtcr4u79HvNvUva38NQ4NJn7vI9OPhPVgb5gxkefgM1tF0QC6QO1b~RADN~BW~X2S-YRPyKKxv6xx9mfqEbl5lVA1nBTaoFsN5ZfLZoJOFIVNpNoXxCrCQhvG2zjS-pJD2NF6g0bCcT4cKBWPYtJenLiK3L6fKJuVJ-og5ootLdJNBXGsO~FSwdabvDUaPDbTKmqS-ibFjmq1C7vEde3TGo3cRZgqG0YZi3S3BpBTYN9kGhYHrThGH69ECViUJnUWlUsWux5FI4pZL5Du7TwDYT0BwnX2kTdZQ8WGSFlflXgVQIh1n0XpElShWrOQPR0jGAAAA

View File

@@ -101,6 +101,24 @@ statGroup.4.detail.8.field=0
statGroup.4.detail.9.name=tunnel test time (day)
statGroup.4.detail.9.option=stat_tunnel.testSuccessTime.24h
statGroup.4.detail.9.field=0
statGroup.4.detail.10.name=avg messages per inbound tunnel (10 minutes)
statGroup.4.detail.10.option=stat_tunnel.inboundMessagesProcessed.10m
statGroup.4.detail.10.field=0
statGroup.4.detail.11.name=avg messages per inbound tunnel (60 minutes)
statGroup.4.detail.11.option=stat_tunnel.inboundMessagesProcessed.60m
statGroup.4.detail.11.field=0
statGroup.4.detail.12.name=avg messages per outbound tunnel (10 minutes)
statGroup.4.detail.12.option=stat_tunnel.outboundMessagesProcessed.10m
statGroup.4.detail.12.field=0
statGroup.4.detail.13.name=avg messages per outbound tunnel (60 minutes)
statGroup.4.detail.13.option=stat_tunnel.outboundMessagesProcessed.60m
statGroup.4.detail.13.field=0
statGroup.4.detail.14.name=avg messages per participating tunnel (10 minutes)
statGroup.4.detail.14.option=stat_tunnel.participatingMessagesProcessed.10m
statGroup.4.detail.14.field=0
statGroup.4.detail.15.name=avg messages per participating tunnel (60 minutes)
statGroup.4.detail.15.option=stat_tunnel.participatingMessagesProcessed.60m
statGroup.4.detail.15.field=0
#
statGroup.5.name=transfer
statGroup.5.detail.0.name=messages sent (5 minutes)
@@ -128,39 +146,109 @@ statGroup.5.detail.7.name=receive message size avg (hour)
statGroup.5.detail.7.option=stat_transport.receiveMessageSize.60m
statGroup.5.detail.7.field=0
#
statGroup.6.name=networkDbHandling
statGroup.6.detail.0.name=lookups received (5 minutes)
statGroup.6.detail.0.option=stat_netDb.lookupsReceived.5m
statGroup.6.detail.0.field=3
statGroup.6.detail.1.name=lookups handled (5 minutes)
statGroup.6.detail.1.option=stat_netDb.lookupsHandled.5m
statGroup.6.detail.1.field=3
statGroup.6.detail.2.name=lookups matched (5 minutes)
statGroup.6.detail.2.option=stat_netDb.lookupsMatched.5m
statGroup.6.detail.2.field=3
statGroup.6.detail.3.name=lookups received (hour)
statGroup.6.detail.3.option=stat_netDb.lookupsReceived.60m
statGroup.6.detail.3.field=3
statGroup.6.detail.4.name=lookups handled (hour)
statGroup.6.detail.4.option=stat_netDb.lookupsHandled.60m
statGroup.6.detail.4.field=3
statGroup.6.detail.5.name=lookups matched (hour)
statGroup.6.detail.5.option=stat_netDb.lookupsMatched.60m
statGroup.6.detail.5.field=3
statGroup.6.name=transferSmall
statGroup.6.detail.0.name=small messages sent (5 minutes)
statGroup.6.detail.0.option=stat_transport.sendMessageSmall.5m
statGroup.6.detail.0.field=7
statGroup.6.detail.1.name=small messages sent (hour)
statGroup.6.detail.1.option=stat_transport.sendMessageSmall.60m
statGroup.6.detail.1.field=7
statGroup.6.detail.2.name=small messages received (5 minutes)
statGroup.6.detail.2.option=stat_transport.receiveMessageSmall.5m
statGroup.6.detail.2.field=7
statGroup.6.detail.3.name=small messages received (hour)
statGroup.6.detail.3.option=stat_transport.receiveMessageSmall.60m
statGroup.6.detail.3.field=7
#
statGroup.7.name=networkDbActivity
statGroup.7.detail.0.name=lookups sent (hour)
statGroup.7.detail.0.option=stat_netDb.successPeers.60m
statGroup.7.name=transferMedium
statGroup.7.detail.0.name=medium messages sent (5 minutes)
statGroup.7.detail.0.option=stat_transport.sendMessageMedium.5m
statGroup.7.detail.0.field=7
statGroup.7.detail.1.name=lookup peers (hour)
statGroup.7.detail.1.option=stat_netDb.successPeers.60m
statGroup.7.detail.1.field=0
statGroup.7.detail.2.name=db store sent (5 minutes)
statGroup.7.detail.2.option=stat_netDb.storeSent.5m
statGroup.7.detail.2.field=3
statGroup.7.detail.3.name=db store sent (hour)
statGroup.7.detail.3.option=stat_netDb.storeSent.60m
statGroup.7.detail.3.field=3
statGroup.7.detail.4.name=failed db lookups (hour)
statGroup.7.detail.3.option=stat_netDb.failedPeers.60m
statGroup.7.detail.3.field=3
statGroup.7.detail.1.name=medium messages sent (hour)
statGroup.7.detail.1.option=stat_transport.sendMessageMedium.60m
statGroup.7.detail.1.field=7
statGroup.7.detail.2.name=medium messages received (5 minutes)
statGroup.7.detail.2.option=stat_transport.receiveMessageMedium.5m
statGroup.7.detail.2.field=7
statGroup.7.detail.3.name=medium messages received (hour)
statGroup.7.detail.3.option=stat_transport.receiveMessageMedium.60m
statGroup.7.detail.3.field=7
#
statGroup.8.name=transferLarge
statGroup.8.detail.0.name=large messages sent (5 minutes)
statGroup.8.detail.0.option=stat_transport.sendMessageLarge.5m
statGroup.8.detail.0.field=7
statGroup.8.detail.1.name=large messages sent (hour)
statGroup.8.detail.1.option=stat_transport.sendMessageLarge.60m
statGroup.8.detail.1.field=7
statGroup.8.detail.2.name=large messages received (5 minutes)
statGroup.8.detail.2.option=stat_transport.receiveMessageLarge.5m
statGroup.8.detail.2.field=7
statGroup.8.detail.3.name=large messages received (hour)
statGroup.8.detail.3.option=stat_transport.receiveMessageLarge.60m
statGroup.8.detail.3.field=7
#
statGroup.9.name=networkDbHandling
statGroup.9.detail.0.name=lookups received (5 minutes)
statGroup.9.detail.0.option=stat_netDb.lookupsReceived.5m
statGroup.9.detail.0.field=3
statGroup.9.detail.1.name=lookups handled (5 minutes)
statGroup.9.detail.1.option=stat_netDb.lookupsHandled.5m
statGroup.9.detail.1.field=3
statGroup.9.detail.2.name=lookups matched (5 minutes)
statGroup.9.detail.2.option=stat_netDb.lookupsMatched.5m
statGroup.9.detail.2.field=3
statGroup.9.detail.3.name=lookups received (hour)
statGroup.9.detail.3.option=stat_netDb.lookupsReceived.60m
statGroup.9.detail.3.field=3
statGroup.9.detail.4.name=lookups handled (hour)
statGroup.9.detail.4.option=stat_netDb.lookupsHandled.60m
statGroup.9.detail.4.field=3
statGroup.9.detail.5.name=lookups matched (hour)
statGroup.9.detail.5.option=stat_netDb.lookupsMatched.60m
statGroup.9.detail.5.field=3
#
statGroup.10.name=networkDbActivity
statGroup.10.detail.0.name=lookups sent (hour)
statGroup.10.detail.0.option=stat_netDb.successPeers.60m
statGroup.10.detail.0.field=7
statGroup.10.detail.1.name=lookup peers (hour)
statGroup.10.detail.1.option=stat_netDb.successPeers.60m
statGroup.10.detail.1.field=0
statGroup.10.detail.2.name=db store sent (5 minutes)
statGroup.10.detail.2.option=stat_netDb.storeSent.5m
statGroup.10.detail.2.field=3
statGroup.10.detail.3.name=db store sent (hour)
statGroup.10.detail.3.option=stat_netDb.storeSent.60m
statGroup.10.detail.3.field=3
statGroup.10.detail.4.name=failed db lookups (hour)
statGroup.10.detail.3.option=stat_netDb.failedPeers.60m
statGroup.10.detail.3.field=3
#
statGroup.11.name=bandwidth
statGroup.11.detail.0.name=send rate (5 minutes)
statGroup.11.detail.0.option=stat_bandwidthSendBps.5m
statGroup.11.detail.0.field=0
statGroup.11.detail.1.name=send rate (60 minutes)
statGroup.11.detail.1.option=stat_bandwidthSendBps.60m
statGroup.11.detail.1.field=0
statGroup.11.detail.2.name=receive rate (5 minutes)
statGroup.11.detail.2.option=stat_bandwidthReceiveBps.5m
statGroup.11.detail.2.field=0
statGroup.11.detail.3.name=receive rate (60 minutes)
statGroup.11.detail.3.option=stat_bandwidthReceiveBps.60m
statGroup.11.detail.3.field=0
#
statGroup.12.name=queueing
statGroup.12.detail.0.name=time to process inbound (5 minutes)
statGroup.12.detail.0.option=stat_inNetMessage.timeToDiscard.5m
statGroup.12.detail.0.field=0
statGroup.12.detail.1.name=time to process inbound (60 minutes)
statGroup.12.detail.1.option=stat_inNetMessage.timeToDiscard.60m
statGroup.12.detail.1.field=0
statGroup.12.detail.2.name=time to process outbound (5 minutes)
statGroup.12.detail.2.option=stat_outNetMessage.timeToDiscard.5m
statGroup.12.detail.2.field=0
statGroup.12.detail.3.name=time to process outbound (60 minutes)
statGroup.12.detail.3.option=stat_outNetMessage.timeToDiscard.60m
statGroup.12.detail.3.field=0

View File

@@ -16,12 +16,15 @@ i2cp.port=##_router_i2cp_port##
# I2P router administrative web port (currently only responds to /routerConsole.html)
router.adminPort=7655
# Bandwidth limits
# These limits are for all i2np connections - tcp or whatever
# They are hard enforced with no smoothing.
# XXX Until the 0.3.2 release, these should NOT BE USED. Their values will be ignored!!!
i2np.bandwidth.inboundBytesPerMinute=##_router_inbps##
i2np.bandwidth.outboundBytesPerMinute=##_router_outbps##
# These limits are for all i2np connections - tcp or whatever to all peers.
# They are hard enforced with no smoothing. If they are <= 0, no limits are enforced.
i2np.bandwidth.inboundKBytesPerSecond=-1
i2np.bandwidth.outboundKBytesPerSecond=-1
# How many bytes will we let accumulate due to inactivity (allowing bursts)?
i2np.bandwidth.inboundBurstKBytes=-1
i2np.bandwidth.outboundBurstKBytes=-1
# Publish peer rankings
# If true, include the current liveliness and reliability rankings in one's published RouterInfo data
@@ -152,6 +155,7 @@ router.maxWaitingJobs=40
# Keep the router's clock in sync by querying one of the specified NTP servers once
# a minute (uses UDP port 123)
# This defaults to the DNS round-robin ntp pool - see http://www.pool.ntp.org/
# Please change the NTP server specified to include ones closer to you - see
# http://www.eecis.udel.edu/~mills/ntp/clock2a.html for a list (you can specify as
# many as you want on the args= line - they'll be tried in order until one answers).
@@ -164,7 +168,13 @@ router.maxWaitingJobs=40
clientApp.0.main=net.i2p.time.Timestamper
clientApp.0.name=Timestamper
clientApp.0.onBoot=true
clientApp.0.args=http://localhost:7655/setTime?k=v clock.fmt.he.net ntp2.belbone.be
clientApp.0.args=http://localhost:7655/setTime?putTheValueFromBelowHere pool.ntp.org pool.ntp.org pool.ntp.org
# The admin time passphrase, used to prevent unauthorized people from updating your
# routers time. The value should be included in the timestamper's args above,
# otherwise it wont honor timestamp updates. You shouldnt include any spaces or funky
# characters - just pick some random numbers.
adminTimePassphrase=pleaseSetSomeValueHere
# SAM bridge (a simplified socket based protocol for using I2P - listens on port 7656. see
# the specs at http://www.i2p.net/node/view/144 for more info)

View File

@@ -1,4 +1,4 @@
$Id: readme.txt,v 1.5 2004/03/21 20:03:54 jrandom Exp $
$Id: readme.txt,v 1.1.1.1 2004/04/07 23:41:54 jrandom Exp $
I2P Router 0.3
You have installed a development release of I2P - a variable latency secure
@@ -25,8 +25,9 @@ windows), and its management console can be seen via http://localhost:7655/
Once your router has started up, it may take a few minutes to get integrated
with the network (you'll see a few TCP connections listed on the management
console). At that point, you can start up any of the various proxies:
* startEepProxy: starts an HTTP proxy to access eepsites. Set your browser's
console). At that point, you can use any of the various proxies:
* eepProxy: this proxy is launched automatically 2 minutes after you start
your router, it starts an HTTP proxy to access eepsites. Set your browser's
HTTP proxy to localhost:4444 and you can browse various anonymously hosted
sites, ala http://duck.i2p/. In addition, the default proxy is set up to
tunnel any HTTP requests that don't point at an eepsite (e.g. http://i2p.net/)
@@ -53,13 +54,11 @@ If you still have problems, get in touch with the I2P team (contact info below)
=== Resources / contact info
I2P is currently revamping our website, so the two main resources are
http://i2p.net/ and http://wiki.invisiblenet.net/iip-wiki?I2P (our website's
work-in-progress location is http://drupal.i2p.net/ for those who want to see
whats coming down the pipe). The development and user community hangs out on
a few different linked irc chats - IIP's #i2p, freenode.net's #i2p, and the
in-I2P irc network's #i2p (both irc.baffled.i2p and irc.duck.i2p). All of those
channels are hooked together, so join whichever one meets your needs.
Our website can be found at http://www.i2p.net/
The development and user community hangs out on a few different linked irc
chats - IIP's #i2p, freenode.net's #i2p, and the in-I2P irc network's #i2p
(both irc.baffled.i2p and irc.duck.i2p). All of those channels are hooked
together, so join whichever one meets your needs.
There is also a relatively low traffic mailing list:
http://i2p.net/mailman/listinfo/i2p with archives at
@@ -78,11 +77,11 @@ The password is "anoncvs".
We are a small group of volunteers spread around several continents, working to
advance different aspects of the project and discussing the design of the
network. For a current list of team members, please see
http://drupal.i2p.net/team
http://www.i2p.net/team
=== Licenses
All code included here is released under an open source license. To review
the I2P license policy, please see http://drupal.i2p.net/node/view/66.
the I2P license policy, please see http://www.i2p.net/node/view/66.
If there is any confusion, please see the source code or contact the
developers on the i2p list.

View File

@@ -27,6 +27,8 @@ public class DataMessage extends I2NPMessageImpl {
public final static int MESSAGE_TYPE = 20;
private byte _data[];
private static final int MAX_SIZE = 64*1024;
public DataMessage(I2PAppContext context) {
super(context);
_data = null;
@@ -41,6 +43,8 @@ public class DataMessage extends I2NPMessageImpl {
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
try {
int size = (int)DataHelper.readLong(in, 4);
if ( (size <= 0) || (size > MAX_SIZE) )
throw new I2NPMessageException("wtf, size out of range? " + size);
_data = new byte[size];
int read = read(in, _data);
if (read != size)

View File

@@ -84,7 +84,10 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
_key.readBytes(in);
_from = new RouterInfo();
_from.readBytes(in);
boolean tunnelSpecified = DataHelper.readBoolean(in).booleanValue();
Boolean val = DataHelper.readBoolean(in);
if (val == null)
throw new I2NPMessageException("Tunnel must be explicitly specified (or not)");
boolean tunnelSpecified = val.booleanValue();
if (tunnelSpecified) {
_replyTunnel = new TunnelId();
_replyTunnel.readBytes(in);

View File

@@ -70,6 +70,8 @@ public class DatabaseSearchReplyMessage extends I2NPMessageImpl {
if (read != compressedLength)
throw new IOException("Not enough data to decompress");
byte decompressedData[] = DataHelper.decompress(compressedData);
if (decompressedData == null)
throw new I2NPMessageException("Could not decompress the " + compressedLength + "bytes of data");
ByteArrayInputStream bais = new ByteArrayInputStream(decompressedData);
int num = (int)DataHelper.readLong(bais, 1);
_routerInfoStructures.clear();

View File

@@ -86,7 +86,8 @@ public class DeliveryStatusMessage extends I2NPMessageImpl {
StringBuffer buf = new StringBuffer();
buf.append("[DeliveryStatusMessage: ");
buf.append("\n\tMessage ID: ").append(getMessageId());
buf.append("\n\tArrival: ").append(getArrival());
buf.append("\n\tArrival: ").append(_context.clock().now() - _arrival.getTime());
buf.append("ms in the past");
buf.append("]");
return buf.toString();
}

View File

@@ -122,12 +122,14 @@ public class I2NPMessageReader {
_listener.messageReceived(I2NPMessageReader.this, msg, msToRead);
}
} catch (I2NPMessageException ime) {
//_log.warn("Error handling message", ime);
if (_log.shouldLog(Log.WARN))
_log.warn("Error handling message", ime);
_listener.readError(I2NPMessageReader.this, ime);
_listener.disconnected(I2NPMessageReader.this);
cancelRunner();
} catch (IOException ioe) {
_log.warn("IO Error handling message", ioe);
if (_log.shouldLog(Log.WARN))
_log.warn("IO Error handling message", ioe);
_listener.disconnected(I2NPMessageReader.this);
cancelRunner();
}

View File

@@ -35,12 +35,26 @@ public class ClientMessagePool {
*
*/
public void add(ClientMessage msg) {
if ( (_context.clientManager().isLocal(msg.getDestination())) ||
add(msg, false);
}
/**
* If we're coming from the client subsystem itself, we already know whether
* the target is definitely remote and as such don't need to recheck
* ourselves, but if we aren't certain, we want it to check for us.
*
* @param isDefinitelyRemote true if we know for sure that the target is not local
*
*/
public void add(ClientMessage msg, boolean isDefinitelyRemote) {
if ( !isDefinitelyRemote ||
(_context.clientManager().isLocal(msg.getDestination())) ||
(_context.clientManager().isLocal(msg.getDestinationHash())) ) {
_log.debug("Adding message for local delivery");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Adding message for local delivery");
_context.clientManager().messageReceived(msg);
} else {
_log.debug("Adding message for remote delivery");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Adding message for remote delivery");
_context.jobQueue().addJob(new OutboundClientMessageJob(_context, msg));
}
}

View File

@@ -1,9 +1,9 @@
package net.i2p.router;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
@@ -18,16 +18,24 @@ import net.i2p.data.i2np.SourceRouteBlock;
*
*/
public class InNetMessage {
private RouterContext _context;
private I2NPMessage _message;
private RouterIdentity _fromRouter;
private Hash _fromRouterHash;
private SourceRouteBlock _replyBlock;
private long _created;
public InNetMessage() {
setMessage(null);
setFromRouter(null);
setFromRouterHash(null);
setReplyBlock(null);
public InNetMessage(RouterContext context) {
_context = context;
setMessage(null);
setFromRouter(null);
setFromRouterHash(null);
setReplyBlock(null);
context.messageStateMonitor().inboundMessageAdded();
_created = context.clock().now();
_context.statManager().createRateStat("inNetMessage.timeToDiscard",
"How long until we discard an inbound msg?",
"InNetMessage", new long[] { 5*60*1000, 30*60*1000, 60*60*1000 });
}
/**
@@ -60,9 +68,28 @@ public class InNetMessage {
public SourceRouteBlock getReplyBlock() { return _replyBlock; }
public void setReplyBlock(SourceRouteBlock block) { _replyBlock = block; }
/**
* Call this after we're done dealing with this message (when we no
* longer need its data)
*
*/
public void processingComplete() {
_message = null;
_context.messageStateMonitor().inboundMessageRead();
long timeToDiscard = _context.clock().now() - _created;
_context.statManager().addRateData("inNetMessage.timeToDiscard",
timeToDiscard, timeToDiscard);
}
public void finalize() {
_context.messageStateMonitor().inboundMessageFinalized();
}
public String toString() {
StringBuffer buf = new StringBuffer(512);
buf.append("InNetMessage: from [").append(getFromRouter()).append("] aka [").append(getFromRouterHash()).append("] message: ").append(getMessage());
return buf.toString();
StringBuffer buf = new StringBuffer(512);
buf.append("InNetMessage: from [").append(getFromRouter());
buf.append("] aka [").append(getFromRouterHash());
buf.append("] message: ").append(getMessage());
return buf.toString();
}
}

View File

@@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map;
import net.i2p.data.i2np.DeliveryStatusMessage;
import net.i2p.data.i2np.I2NPMessage;
import net.i2p.util.Log;
/**
@@ -56,35 +57,37 @@ public class InNetMessagePool {
*
*/
public int add(InNetMessage msg) {
Date exp = msg.getMessage().getMessageExpiration();
boolean valid = _context.messageValidator().validateMessage(msg.getMessage().getUniqueId(), exp.getTime());
I2NPMessage messageBody = msg.getMessage();
msg.processingComplete();
Date exp = messageBody.getMessageExpiration();
boolean valid = _context.messageValidator().validateMessage(messageBody.getUniqueId(), exp.getTime());
if (!valid) {
if (_log.shouldLog(Log.WARN))
_log.warn("Duplicate message received [" + msg.getMessage().getUniqueId()
+ " expiring on " + exp + "]: " + msg.getMessage().getClass().getName());
_log.warn("Duplicate message received [" + messageBody.getUniqueId()
+ " expiring on " + exp + "]: " + messageBody.getClass().getName());
_context.statManager().addRateData("inNetPool.dropped", 1, 0);
_context.statManager().addRateData("inNetPool.duplicate", 1, 0);
_context.messageHistory().droppedOtherMessage(msg.getMessage());
_context.messageHistory().messageProcessingError(msg.getMessage().getUniqueId(),
msg.getMessage().getClass().getName(),
_context.messageHistory().droppedOtherMessage(messageBody);
_context.messageHistory().messageProcessingError(messageBody.getUniqueId(),
messageBody.getClass().getName(),
"Duplicate/expired");
return -1;
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Message received [" + msg.getMessage().getUniqueId()
_log.debug("Message received [" + messageBody.getUniqueId()
+ " expiring on " + exp + "] is NOT a duplicate or exipired");
}
int size = -1;
int type = msg.getMessage().getType();
int type = messageBody.getType();
HandlerJobBuilder builder = (HandlerJobBuilder)_handlerJobBuilders.get(new Integer(type));
if (_log.shouldLog(Log.DEBUG))
_log.debug("Add message to the inNetMessage pool - builder: " + builder
+ " message class: " + msg.getMessage().getClass().getName());
+ " message class: " + messageBody.getClass().getName());
if (builder != null) {
Job job = builder.createJob(msg.getMessage(), msg.getFromRouter(),
Job job = builder.createJob(messageBody, msg.getFromRouter(),
msg.getFromRouterHash(), msg.getReplyBlock());
if (job != null) {
_context.jobQueue().addJob(job);
@@ -94,7 +97,7 @@ public class InNetMessagePool {
}
}
List origMessages = _context.messageRegistry().getOriginalMessages(msg.getMessage());
List origMessages = _context.messageRegistry().getOriginalMessages(messageBody);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Original messages for inbound message: " + origMessages.size());
if (origMessages.size() > 1) {
@@ -111,7 +114,7 @@ public class InNetMessagePool {
+ " : " + omsg + ": reply job: " + job);
if (job != null) {
job.setMessage(msg.getMessage());
job.setMessage(messageBody);
_context.jobQueue().addJob(job);
}
}
@@ -120,31 +123,31 @@ public class InNetMessagePool {
// not handled as a reply
if (size == -1) {
// was not handled via HandlerJobBuilder
_context.messageHistory().droppedOtherMessage(msg.getMessage());
if (msg.getMessage().getType() == DeliveryStatusMessage.MESSAGE_TYPE) {
_context.messageHistory().droppedOtherMessage(messageBody);
if (type == DeliveryStatusMessage.MESSAGE_TYPE) {
long timeSinceSent = _context.clock().now() -
((DeliveryStatusMessage)msg.getMessage()).getArrival().getTime();
((DeliveryStatusMessage)messageBody).getArrival().getTime();
if (_log.shouldLog(Log.INFO))
_log.info("Dropping unhandled delivery status message created " + timeSinceSent + "ms ago: " + msg);
_context.statManager().addRateData("inNetPool.droppedDeliveryStatusDelay", timeSinceSent, timeSinceSent);
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Message " + msg.getMessage() + " was not handled by a HandlerJobBuilder - DROPPING: "
_log.error("Message " + messageBody + " was not handled by a HandlerJobBuilder - DROPPING: "
+ msg, new Exception("DROPPED MESSAGE"));
_context.statManager().addRateData("inNetPool.dropped", 1, 0);
}
} else {
String mtype = msg.getMessage().getClass().getName();
_context.messageHistory().receiveMessage(mtype, msg.getMessage().getUniqueId(),
msg.getMessage().getMessageExpiration(),
String mtype = messageBody.getClass().getName();
_context.messageHistory().receiveMessage(mtype, messageBody.getUniqueId(),
messageBody.getMessageExpiration(),
msg.getFromRouterHash(), true);
return size;
}
}
String mtype = msg.getMessage().getClass().getName();
_context.messageHistory().receiveMessage(mtype, msg.getMessage().getUniqueId(),
msg.getMessage().getMessageExpiration(),
String mtype = messageBody.getClass().getName();
_context.messageHistory().receiveMessage(mtype, messageBody.getUniqueId(),
messageBody.getMessageExpiration(),
msg.getFromRouterHash(), true);
return size;
}

View File

@@ -228,7 +228,32 @@ public class JobQueue {
void shutdown() {
_alive = false;
StringBuffer buf = new StringBuffer(1024);
buf.append("jobs: \nready jobs: ").append(_readyJobs.size()).append("\n\t");
buf.append("current jobs: \n");
for (Iterator iter = _queueRunners.values().iterator(); iter.hasNext(); ) {
JobQueueRunner runner = (JobQueueRunner)iter.next();
Job j = runner.getCurrentJob();
buf.append("Runner ").append(runner.getRunnerId()).append(": ");
if (j == null) {
buf.append("no current job ");
} else {
buf.append(j.toString());
buf.append(" started ").append(_context.clock().now() - j.getTiming().getActualStart());
buf.append("ms ago");
}
j = runner.getLastJob();
if (j == null) {
buf.append("no last job");
} else {
buf.append(j.toString());
buf.append(" started ").append(_context.clock().now() - j.getTiming().getActualStart());
buf.append("ms ago and finished ");
buf.append(_context.clock().now() - j.getTiming().getActualEnd());
buf.append("ms ago");
}
}
buf.append("\nready jobs: ").append(_readyJobs.size()).append("\n\t");
for (int i = 0; i < _readyJobs.size(); i++)
buf.append(_readyJobs.get(i).toString()).append("\n\t");
buf.append("\n\ntimed jobs: ").append(_timedJobs.size()).append("\n\t");
@@ -254,9 +279,10 @@ public class JobQueue {
if (rv != null) {
// we found one, but there may be more, so wake up enough
// other runners
if (_log.shouldLog(Log.DEBUG))
_log.debug("Waking up " + (ready-1) + " job runners (and running one)");
awaken(ready-1);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Waking up " + (ready-1) + " job runners (and running one)");
//awaken(ready-1);
return rv;
} else {
if (_log.shouldLog(Log.DEBUG))
@@ -452,6 +478,7 @@ public class JobQueue {
* a warning (and if its really excessive, kill the router)
*/
void updateStats(Job job, long doStart, long origStartAfter, long duration) {
if (_context.router() == null) return;
String key = job.getName();
long lag = doStart - origStartAfter; // how long were we ready and waiting?
MessageHistory hist = _context.messageHistory();
@@ -511,6 +538,10 @@ public class JobQueue {
*
*/
private void updateMaxLimit() {
if (_context.router() == null) {
_maxRunners = DEFAULT_MAX_RUNNERS;
return;
}
String str = _context.router().getConfigSetting(PROP_MAX_RUNNERS);
if (str != null) {
try {
@@ -531,6 +562,15 @@ public class JobQueue {
*
*/
private void updateTimingLimits() {
if (_context.router() == null) {
_lagWarning = DEFAULT_LAG_WARNING;
_lagFatal = DEFAULT_LAG_FATAL;
_runWarning = DEFAULT_RUN_WARNING;
_runFatal = DEFAULT_RUN_FATAL;
_warmupTime = DEFAULT_WARMUP_TIME;
_maxWaitingJobs = DEFAULT_MAX_WAITING_JOBS;
return;
}
String str = _context.router().getConfigSetting(PROP_LAG_WARNING);
if (str != null) {
try {

View File

@@ -133,7 +133,7 @@ public class KeyManager {
super(KeyManager.this._context);
}
public void runJob() {
String keyDir = KeyManager.this._context.router().getConfigSetting(PROP_KEYDIR);
String keyDir = KeyManager.this._context.getProperty(PROP_KEYDIR);
if (keyDir == null)
keyDir = DEFAULT_KEYDIR;
File dir = new File(keyDir);

View File

@@ -42,9 +42,13 @@ public class MessageHistory {
/** config property determining where we want to log the message history, if we're keeping one */
public final static String PROP_MESSAGE_HISTORY_FILENAME = "router.historyFilename";
public final static String DEFAULT_MESSAGE_HISTORY_FILENAME = "messageHistory.txt";
private final SimpleDateFormat _fmt;
public MessageHistory(RouterContext context) {
_context = context;
_fmt = new SimpleDateFormat("yy/MM/dd.HH:mm:ss.SSS");
_fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
_reinitializeJob = new ReinitializeJob();
_writeJob = new WriteJob();
_submitMessageHistoryJob = new SubmitMessageHistoryJob(_context);
@@ -81,6 +85,8 @@ public class MessageHistory {
public void initialize(boolean forceReinitialize) {
if (!forceReinitialize) return;
if (_context.router() == null) return;
if (_context.router().getRouterInfo() == null) {
_reinitializeJob.getTiming().setStartAfter(_context.clock().now()+5000);
_context.jobQueue().addJob(_reinitializeJob);
@@ -302,8 +308,8 @@ public class MessageHistory {
if (sentMessage == null) return;
StringBuffer buf = new StringBuffer(512);
buf.append(getPrefix());
buf.append("timed out waiting for a reply to [").append(sentMessage.getMessage().getClass().getName());
buf.append("] [").append(sentMessage.getMessage().getUniqueId()).append("] expiring on [");
buf.append("timed out waiting for a reply to [").append(sentMessage.getMessageType());
buf.append("] [").append(sentMessage.getMessageId()).append("] expiring on [");
if (sentMessage != null)
buf.append(getTime(new Date(sentMessage.getReplySelector().getExpiration())));
buf.append("] ").append(sentMessage.getReplySelector().toString());
@@ -439,11 +445,7 @@ public class MessageHistory {
return buf.toString();
}
private final static SimpleDateFormat _fmt = new SimpleDateFormat("yy/MM/dd.HH:mm:ss.SSS");
static {
_fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
}
private final static String getTime(Date when) {
private final String getTime(Date when) {
synchronized (_fmt) {
return _fmt.format(when);
}

View File

@@ -0,0 +1,72 @@
package net.i2p.router;
import net.i2p.util.Log;
/**
* Keep track of the inbound and outbound messages in memory.
*
*/
public class MessageStateMonitor {
private Log _log;
private RouterContext _context;
private volatile int _inboundLiveCount;
private volatile int _inboundReadCount;
private volatile int _inboundFinalizedCount;
private volatile int _outboundLiveCount;
private volatile int _outboundDiscardedCount;
public MessageStateMonitor(RouterContext context) {
_context = context;
_log = context.logManager().getLog(MessageStateMonitor.class);
_inboundLiveCount = 0;
_inboundReadCount = 0;
_inboundFinalizedCount = 0;
_outboundLiveCount = 0;
_outboundDiscardedCount = 0;
}
public void inboundMessageAdded() {
_inboundLiveCount++;
logStatus("inboundAdded ");
}
public void inboundMessageRead() {
_inboundReadCount++;
_inboundLiveCount--;
logStatus("inboundRead ");
}
public void inboundMessageFinalized() {
_inboundReadCount--;
_inboundFinalizedCount++;
logStatus("inboundFinalized ");
}
public void outboundMessageAdded() {
_outboundLiveCount++;
logStatus("outboundAdded ");
}
public void outboundMessageDiscarded() {
_outboundDiscardedCount++;
_outboundLiveCount--;
logStatus("outboundDiscarded");
}
public void outboundMessageFinalized() {
_outboundDiscardedCount--;
logStatus("outboundFinalized");
}
private void logStatus(String event) {
if (false || (_log.shouldLog(Log.DEBUG)))
_log.debug(event + ": outbound (live: " + _outboundLiveCount
+ " discarded:" + _outboundDiscardedCount + ")"
+ " inbound (live: " + (_inboundLiveCount)
//+ " inbound (live: " + (_inboundLiveCount-_inboundFinalizedCount)
+ " read: " + (_inboundReadCount)
//+ " completed: " + _inboundFinalizedCount
+ ")");
}
public int getInboundLiveCount() { return _inboundLiveCount; }
public int getInboundReadCount() { return _inboundReadCount; }
public int getOutboundLiveCount() { return _outboundLiveCount; }
public int getOutboundDiscardedCount() { return _outboundDiscardedCount; }
}

View File

@@ -56,7 +56,8 @@ public class MultiRouter {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try { Thread.sleep(15*1000); } catch (InterruptedException ie) {}
Thread.currentThread().setName("Router* Shutdown");
try { Thread.sleep(120*1000); } catch (InterruptedException ie) {}
Runtime.getRuntime().halt(-1);
}
});
@@ -66,12 +67,13 @@ public class MultiRouter {
router.setKillVMOnEnd(false);
_routers.add(router);
_log.info("Router " + i + " created from " + args[i]);
try { Thread.sleep(1*1000); } catch (InterruptedException ie) {}
try { Thread.sleep(2*1000); } catch (InterruptedException ie) {}
}
for (int i = 0; i < _routers.size(); i++) {
((Router)_routers.get(i)).runRouter();
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
_log.info("Router " + i + " started");
try { Thread.sleep(2*1000 + new java.util.Random().nextInt(2)*1000); } catch (InterruptedException ie) {}
}
_log.info("All " + _routers.size() + " routers started up");
waitForCompletion();
@@ -115,4 +117,4 @@ public class MultiRouter {
System.err.println(" to load into the given context. In addition, each routerContextFile");
System.err.println(" in turn is used to boot a router");
}
}
}

View File

@@ -43,7 +43,7 @@ import java.io.IOException;
*/
public class MultiRouterBuilder {
public static void main(String args[]) {
if (args.length <= 2) {
if (args.length < 2) {
usage();
return;
}
@@ -128,7 +128,7 @@ public class MultiRouterBuilder {
buf.append("i2np.bandwidth.inboundBytesPerMinute=-60\n");
buf.append("i2np.bandwidth.outboundBytesPerMinute=-60\n");
buf.append("router.publishPeerRankings=true\n");
buf.append("router.keepHistory=true\n");
buf.append("router.keepHistory=false\n");
buf.append("router.submitHistory=false\n");
buf.append("router.maxJobRunners=1\n");
buf.append("router.jobLagWarning=10000\n");
@@ -136,9 +136,9 @@ public class MultiRouterBuilder {
buf.append("router.jobRunWarning=10000\n");
buf.append("router.jobRunFatal=30000\n");
buf.append("router.jobWarmupTime=600000\n");
buf.append("router.targetClients=2\n");
buf.append("tunnels.numInbound=2\n");
buf.append("tunnels.numOutbound=2\n");
buf.append("router.targetClients=1\n");
buf.append("tunnels.numInbound=6\n");
buf.append("tunnels.numOutbound=6\n");
buf.append("tunnels.depthInbound=2\n");
buf.append("tunnels.depthOutbound=2\n");
buf.append("tunnels.tunnelDuration=600000\n");
@@ -152,6 +152,7 @@ public class MultiRouterBuilder {
buf.append("router.tunnelPoolFile=").append(baseDir.getPath()).append("/tunnelPool.dat\n");
buf.append("router.keyBackupDir=").append(baseDir.getPath()).append("/keyBackup\n");
buf.append("i2np.tcp.port=").append(basePort).append('\n');
buf.append("i2np.tcp.hostname=localhost\n");
buf.append("i2cp.port=").append(basePort+1).append('\n');
buf.append("router.adminPort=").append(basePort+2).append('\n');
buf.append("#clientApp.0.main=net.i2p.sam.SAMBridge\n");
@@ -184,7 +185,7 @@ public class MultiRouterBuilder {
fos = new FileOutputStream(envFile);
fos.write(("loggerFilenameOverride="+baseDir+ "/logs/log-router-#.txt\n").getBytes());
fos.write(("router.configLocation="+baseDir+"/router.config\n").getBytes());
fos.write(("i2p.vmCommSystem=true\n").getBytes());
//fos.write(("i2p.vmCommSystem=true\n").getBytes());
fos.write(("i2p.encryption=off\n").getBytes());
fos.close();
@@ -198,4 +199,4 @@ public class MultiRouterBuilder {
private static void usage() {
System.err.println("Usage: MultiRouterBuilder [routerDir routerPortStart]*");
}
}
}

View File

@@ -35,6 +35,10 @@ public class OutNetMessage {
private RouterContext _context;
private RouterInfo _target;
private I2NPMessage _message;
/** cached message class name, for use after we discard the message */
private String _messageType;
/** cached message ID, for use after we discard the message */
private long _messageId;
private long _messageSize;
private int _priority;
private long _expiration;
@@ -75,6 +79,10 @@ public class OutNetMessage {
_createdBy = new Exception("Created by");
_created = context.clock().now();
timestamp("Created");
_context.messageStateMonitor().outboundMessageAdded();
_context.statManager().createRateStat("outNetMessage.timeToDiscard",
"How long until we discard an outbound msg?",
"OutNetMessage", new long[] { 5*60*1000, 30*60*1000, 60*60*1000 });
}
public void timestamp(String eventName) {
@@ -109,8 +117,15 @@ public class OutNetMessage {
public I2NPMessage getMessage() { return _message; }
public void setMessage(I2NPMessage msg) {
_message = msg;
if (msg != null) {
_messageType = msg.getClass().getName();
_messageId = msg.getUniqueId();
}
}
public String getMessageType() { return _messageType; }
public long getMessageId() { return _messageId; }
public long getMessageSize() {
if (_messageSize <= 0) {
try {
@@ -132,7 +147,7 @@ public class OutNetMessage {
return null;
} else {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); // large enough to hold most messages
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); // large enough to hold most messages
_message.writeBytes(baos);
byte data[] = baos.toByteArray();
_messageSize = data.length;
@@ -206,6 +221,36 @@ public class OutNetMessage {
public long getCreated() { return _created; }
public long getLifetime() { return _context.clock().now() - _created; }
/**
* We've done what we need to do with the data from this message, though
* we may keep the object around for a while to use its ID, jobs, etc.
*/
public void discardData() {
long timeToDiscard = _context.clock().now() - _created;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Discard " + _messageSize + "byte " + _messageType + " message after "
+ timeToDiscard);
_message = null;
_context.statManager().addRateData("outNetMessage.timeToDiscard", timeToDiscard, timeToDiscard);
_context.messageStateMonitor().outboundMessageDiscarded();
}
public void finalize() throws Throwable {
if (_message != null) {
StringBuffer buf = new StringBuffer(1024);
buf.append("Undiscarded ").append(_messageSize).append("byte ");
buf.append(_messageType).append(" message created ");
buf.append((_context.clock().now() - _created)).append("ms ago: ");
buf.append(_messageId).append(" to ").append(_target.calculateHash().toBase64());
buf.append(", timing - \n");
renderTimestamps(buf);
_log.error(buf.toString(), _createdBy);
_context.messageStateMonitor().outboundMessageDiscarded();
}
_context.messageStateMonitor().outboundMessageFinalized();
super.finalize();
}
public String toString() {
StringBuffer buf = new StringBuffer(128);
buf.append("[OutNetMessage contains ");
@@ -230,6 +275,13 @@ public class OutNetMessage {
if (_onFailedSend != null)
buf.append(" with onFailedSend job: ").append(_onFailedSend);
buf.append(" {timestamps: \n");
renderTimestamps(buf);
buf.append("}");
buf.append("]");
return buf.toString();
}
private void renderTimestamps(StringBuffer buf) {
synchronized (_timestamps) {
long lastWhen = -1;
for (int i = 0; i < _timestampOrder.size(); i++) {
@@ -243,13 +295,12 @@ public class OutNetMessage {
buf.append(diff);
else
buf.append(0);
buf.append("ms: \t").append(name).append('=').append(formatDate(when.longValue())).append("]\n");
buf.append("ms: \t").append(name);
buf.append('=').append(formatDate(when.longValue()));
buf.append("]\n");
lastWhen = when.longValue();
}
}
buf.append("}");
buf.append("]");
return buf.toString();
}
private final static SimpleDateFormat _fmt = new SimpleDateFormat("HH:mm:ss.SSS");

View File

@@ -93,6 +93,15 @@ public class Router {
_oomListener = new I2PThread.OOMEventListener() {
public void outOfMemory(OutOfMemoryError oom) {
_log.log(Log.CRIT, "Thread ran out of memory", oom);
for (int i = 0; i < 5; i++) { // try this 5 times, in case it OOMs
try {
_log.log(Log.CRIT, "free mem: " + Runtime.getRuntime().freeMemory() +
" total mem: " + Runtime.getRuntime().totalMemory());
break; // w00t
} catch (OutOfMemoryError oome) {
// gobble
}
}
shutdown();
}
};
@@ -276,7 +285,7 @@ public class Router {
RateStat sendRate = _context.statManager().getRate("transport.sendMessageSize");
for (int i = 0; i < sendRate.getPeriods().length; i++) {
Rate rate = sendRate.getRate(sendRate.getPeriods()[i]);
double bytes = rate.getLastTotalValue() + rate.getCurrentTotalValue();
double bytes = rate.getLastTotalValue();
long ms = rate.getLastTotalEventTime() + rate.getLastTotalEventTime();
if (ms <= 0) {
bytes = 0;
@@ -294,9 +303,7 @@ public class Router {
buf.append(" over ").append((long)bytes).append(" bytes");
buf.append("</li><li>");
buf.append(DataHelper.formatDuration(rate.getPeriod())).append(" period send avg: ");
// we include lastPeriod + current *partial* period, and jrandom is too lazy to calculate how
// much of that partial is contained here, so 2*period it is.
bps = bytes*1000.0d/(2*rate.getPeriod());
bps = bytes*1000.0d/(rate.getPeriod());
if (bps > 2048) {
bps /= 1024.0d;
buf.append(fmt.format(bps)).append(" KBps");
@@ -310,8 +317,8 @@ public class Router {
RateStat receiveRate = _context.statManager().getRate("transport.receiveMessageSize");
for (int i = 0; i < receiveRate.getPeriods().length; i++) {
Rate rate = receiveRate.getRate(receiveRate.getPeriods()[i]);
double bytes = rate.getLastTotalValue() + rate.getCurrentTotalValue();
long ms = rate.getLastTotalEventTime() + rate.getLastTotalEventTime();
double bytes = rate.getLastTotalValue();
long ms = rate.getLastTotalEventTime();
if (ms <= 0) {
bytes = 0;
ms = 1;
@@ -328,9 +335,7 @@ public class Router {
buf.append(" over ").append((long)bytes).append(" bytes");
buf.append("</li><li>");
buf.append(DataHelper.formatDuration(rate.getPeriod())).append(" period receive avg: ");
// we include lastPeriod + current *partial* period, and jrandom is too lazy to calculate how
// much of that partial is contained here, so 2*period it is.
bps = bytes*1000.0d/(2*rate.getPeriod());
bps = bytes*1000.0d/(rate.getPeriod());
if (bps > 2048) {
bps /= 1024.0d;
buf.append(fmt.format(bps)).append(" KBps");
@@ -407,8 +412,15 @@ public class Router {
r.runRouter();
}
private static int __id = 0;
private class ShutdownHook extends Thread {
private int _id;
public ShutdownHook() {
_id = ++__id;
}
public void run() {
setName("Router " + _id + " shutdown");
_log.log(Log.CRIT, "Shutting down the router...");
shutdown();
}

View File

@@ -49,6 +49,7 @@ public class RouterContext extends I2PAppContext {
private StatisticsManager _statPublisher;
private Shitlist _shitlist;
private MessageValidator _messageValidator;
private MessageStateMonitor _messageStateMonitor;
private Calculator _isFailingCalc;
private Calculator _integrationCalc;
private Calculator _speedCalc;
@@ -68,6 +69,7 @@ public class RouterContext extends I2PAppContext {
_outNetMessagePool = new OutNetMessagePool(this);
_messageHistory = new MessageHistory(this);
_messageRegistry = new OutboundMessageRegistry(this);
_messageStateMonitor = new MessageStateMonitor(this);
_netDb = new KademliaNetworkDatabaseFacade(this);
_keyManager = new KeyManager(this);
if ("false".equals(getProperty("i2p.vmCommSystem", "false")))
@@ -123,6 +125,13 @@ public class RouterContext extends I2PAppContext {
* The registry is used by outbound messages to wait for replies.
*/
public OutboundMessageRegistry messageRegistry() { return _messageRegistry; }
/**
* The monitor keeps track of inbound and outbound messages currently held in
* memory / queued for processing. We'll use this to throttle the router so
* we don't overflow.
*
*/
public MessageStateMonitor messageStateMonitor() { return _messageStateMonitor; }
/**
* Our db cache
*/
@@ -218,4 +227,29 @@ public class RouterContext extends I2PAppContext {
buf.append(_reliabilityCalc).append('\n');
return buf.toString();
}
/**
* Tie in the router's config as properties, as well as whatever the
* I2PAppContext says.
*
*/
public String getProperty(String propName) {
if (_router != null) {
String val = _router.getConfigSetting(propName);
if (val != null) return val;
}
return super.getProperty(propName);
}
/**
* Tie in the router's config as properties, as well as whatever the
* I2PAppContext says.
*
*/
public String getProperty(String propName, String defaultVal) {
if (_router != null) {
String val = _router.getConfigSetting(propName);
if (val != null) return val;
}
return super.getProperty(propName, defaultVal);
}
}

View File

@@ -15,8 +15,8 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.5 $ $Date: 2004/05/13 18:49:09 $";
public final static String VERSION = "0.3.1.3";
public final static String ID = "$Revision: 1.7 $ $Date: 2004/05/23 11:54:30 $";
public final static String VERSION = "0.3.1.5";
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@@ -33,9 +33,14 @@ public class StatisticsManager implements Service {
public final static String DEFAULT_PROP_PUBLISH_RANKINGS = "false";
public final static String PROP_MAX_PUBLISHED_PEERS = "router.publishPeerMax";
public final static int DEFAULT_MAX_PUBLISHED_PEERS = 20;
private final DecimalFormat _fmt;
private final DecimalFormat _pct;
public StatisticsManager(RouterContext context) {
_context = context;
_fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));
_pct = new DecimalFormat("#0.00%", new DecimalFormatSymbols(Locale.UK));
_log = context.logManager().getLog(StatisticsManager.class);
_includePeerRankings = false;
}
@@ -92,6 +97,7 @@ public class StatisticsManager implements Service {
if (_includePeerRankings) {
stats.putAll(_context.profileManager().summarizePeers(_publishedStats));
includeThroughput(stats);
includeRate("transport.sendProcessingTime", stats, new long[] { 60*1000, 60*60*1000 });
//includeRate("tcp.queueSize", stats);
includeRate("jobQueue.jobLag", stats, new long[] { 60*1000, 60*60*1000 });
@@ -104,6 +110,9 @@ public class StatisticsManager implements Service {
includeRate("inNetPool.dropped", stats, new long[] { 60*60*1000, 24*60*60*1000 });
includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("tunnel.testSuccessTime", stats, new long[] { 60*60*1000l, 24*60*60*1000l });
includeRate("tunnel.outboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("tunnel.inboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("tunnel.participatingMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
includeRate("netDb.lookupsReceived", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.lookupsHandled", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("netDb.lookupsMatched", stats, new long[] { 5*60*1000, 60*60*1000 });
@@ -111,8 +120,16 @@ public class StatisticsManager implements Service {
includeRate("netDb.successPeers", stats, new long[] { 60*60*1000 });
includeRate("netDb.failedPeers", stats, new long[] { 60*60*1000 });
includeRate("netDb.searchCount", stats, new long[] { 3*60*60*1000});
includeRate("inNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
includeRate("outNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.sendMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("transport.receiveMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
includeRate("client.sendAckTime", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
stats.setProperty("stat_uptime", DataHelper.formatDuration(_context.router().getUptime()));
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
@@ -160,7 +177,7 @@ public class StatisticsManager implements Service {
}
}
private static String renderRate(Rate rate, boolean fudgeQuantity) {
private String renderRate(Rate rate, boolean fudgeQuantity) {
StringBuffer buf = new StringBuffer(128);
buf.append(num(rate.getAverageValue())).append(';');
buf.append(num(rate.getExtremeAverageValue())).append(';');
@@ -189,15 +206,55 @@ public class StatisticsManager implements Service {
}
return buf.toString();
}
private static String getPeriod(Rate rate) { return DataHelper.formatDuration(rate.getPeriod()); }
// TODO: get this to use some random locale, not the user's default (since its published)
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));
private final static String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private String renderThroughput(double bytes, long ms) {
if (bytes <= 0)
return "0;0;0;0;";
else
return num(bytes/(ms/1000)) + ";0;0;0;";
}
private final static DecimalFormat _pct = new DecimalFormat("#0.00%", new DecimalFormatSymbols(Locale.UK));
private final static String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
private void includeThroughput(Properties stats) {
double sendBytes5m = 0;
double sendBytes60m = 0;
double recvBytes5m = 0;
double recvBytes60m = 0;
RateStat sendRate = _context.statManager().getRate("transport.sendMessageSize");
if (sendRate != null) {
Rate r = sendRate.getRate(5*60*1000);
if (r != null)
sendBytes5m = r.getLastTotalValue();
r = sendRate.getRate(60*60*1000);
if (r != null)
sendBytes60m = r.getLastTotalValue();
}
RateStat recvRate = _context.statManager().getRate("transport.receiveMessageSize");
if (recvRate != null) {
Rate r = recvRate.getRate(5*60*1000);
if (r != null)
recvBytes5m = r.getLastTotalValue();
r = recvRate.getRate(60*60*1000);
if (r != null)
recvBytes60m = r.getLastTotalValue();
}
String throughputRate = renderThroughput(sendBytes5m, 5*60*1000);
stats.setProperty("stat_bandwidthSendBps.5m", throughputRate);
throughputRate = renderThroughput(sendBytes60m, 60*60*1000);
stats.setProperty("stat_bandwidthSendBps.60m", throughputRate);
throughputRate = renderThroughput(recvBytes5m, 5*60*1000);
stats.setProperty("stat_bandwidthReceiveBps.5m", throughputRate);
throughputRate = renderThroughput(recvBytes60m, 60*60*1000);
stats.setProperty("stat_bandwidthReceiveBps.60m", throughputRate);
}
private String getPeriod(Rate rate) { return DataHelper.formatDuration(rate.getPeriod()); }
private final String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private final String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
public String renderStatusHTML() { return ""; }
}

View File

@@ -8,6 +8,8 @@ import net.i2p.util.HTTPSendData;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.router.transport.BandwidthLimitedInputStream;
/**
* Job that, if its allowed to, will submit the data gathered by the MessageHistory
* component to some URL so that the network can be debugged more easily. By default
@@ -87,8 +89,8 @@ public class SubmitMessageHistoryJob extends JobImpl {
if (size > 0)
expectedSend += (int)size/10; // compression
FileInputStream fin = new FileInputStream(dataFile);
_context.bandwidthLimiter().delayOutbound(null, expectedSend);
boolean sent = HTTPSendData.postData(url, size, fin);
BandwidthLimitedInputStream in = new BandwidthLimitedInputStream(_context, fin, null, true);
boolean sent = HTTPSendData.postData(url, size, in);
fin.close();
boolean deleted = dataFile.delete();
_log.debug("Submitted " + size + " bytes? " + sent + " and deleted? " + deleted);

View File

@@ -31,11 +31,14 @@ import net.i2p.data.i2np.TunnelSessionKey;
import net.i2p.data.i2np.TunnelSigningPrivateKey;
import net.i2p.data.i2np.TunnelSigningPublicKey;
import net.i2p.util.Log;
/**
* Defines the information associated with a tunnel
*/
public class TunnelInfo extends DataStructureImpl {
private I2PAppContext _context;
private static Log _log;
private TunnelId _id;
private Hash _nextHop;
private Hash _thisHop;
@@ -51,9 +54,12 @@ public class TunnelInfo extends DataStructureImpl {
private long _lastTested;
private boolean _ready;
private boolean _wasEverReady;
private int _messagesProcessed;
public TunnelInfo(I2PAppContext context) {
_context = context;
if (_log == null)
_log = context.logManager().getLog(TunnelInfo.class);
setTunnelId(null);
setThisHop(null);
setNextHop(null);
@@ -69,6 +75,7 @@ public class TunnelInfo extends DataStructureImpl {
_wasEverReady = false;
_created = _context.clock().now();
_lastTested = -1;
_messagesProcessed = 0;
}
public TunnelId getTunnelId() { return _id; }
@@ -162,6 +169,15 @@ public class TunnelInfo extends DataStructureImpl {
return len;
}
/** how many messages have passed through this tunnel in its lifetime? */
public int getMessagesProcessed() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Tunnel " + _id.getTunnelId() + " processed " + _messagesProcessed + " messages");
return _messagesProcessed;
}
/** we have just processed a message for this tunnel */
public void messageProcessed() { _messagesProcessed++; }
public void readBytes(InputStream in) throws DataFormatException, IOException {
_options = DataHelper.readProperties(in);
Boolean includeDest = DataHelper.readBoolean(in);

View File

@@ -46,7 +46,7 @@ public class AdminManager implements Service {
private void startup(int port) {
_listener = new AdminListener(_context, port);
I2PThread t = new I2PThread(_listener);
t.setName("Admin Listener");
t.setName("Admin Listener:" + port);
t.setDaemon(true);
t.setPriority(Thread.MIN_PRIORITY);
t.start();

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