Compare commits

..

154 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
jrandom
d70c5df5a0 0.3.1.3 (not backwards compatible, yadda yadda yadda) 2004-05-20 11:32:32 +00:00
jrandom
b2799d198c add (commented out) router.shutdownPassword 2004-05-20 11:27:49 +00:00
jrandom
f2fa2038b1 * made dbStore use a pessimistic algorithm - requiring confirmation of a store, rather than optimistically considering all store messages successful (NOT BACKWARDS COMPATIBLE)
* when allocating tunnels for a client, make sure it has a good amount of time left in it (using default values, this means at least 7.5 minutes)
* allow overriding the profile organizer's thresholds so as to enforce a minimum number of fast and reliable peers, allowing a base level of tunnel diversification.  this is done through the "profileOrganizer.minFastPeers" router.config / context property (default minimum = 4 fast and reliable peers)
* don't be so harsh with the isFailing calculator regarding db lookup responses, since we've decreased the timeout.  however, include "participated in a failed tunnel" as part of the criteria
* more logging than god
* for dropped messages, if it is a DeliveryStatusMessage its not an error, its just lag / congestion (keep the average delay as the new stat "inNetPool.droppedDeliveryStatusDelay")
2004-05-20 11:06:25 +00:00
jrandom
bfd59e64ea refactored the cleanup job
logging
2004-05-20 10:53:31 +00:00
jrandom
60e05e270a cleaned up slice processing
reduced max queued messages per connection to 10 (additional ones are immediately marked as failed)
update the I2P_FLAG byte to '*' making this NOT BACKWARDS COMPATIBLE
formatting
2004-05-20 10:51:22 +00:00
jrandom
242b9a6af9 fix the reread short circuiting algorithm 2004-05-20 10:44:31 +00:00
jrandom
e7e8ad9bdc add the socketErrorListener interface (sorry duck) 2004-05-19 22:30:52 +00:00
jrandom
0e5d164a8a support shutting down the router from the web console:
specify a "router.shutdownPassword" value in the router.config (or in the environment [ala -D]),
  then specify that password on the shutdown form in the web console and hit submit.  after 30 seconds, it'll kill the router (and unless you're running the sim, it'll kill the JVM too, including clientApp.* started tunnels / etc)
if we had some sort of ACL for accessing the web console, we could avoid the password field altogether, but we dont, so we cant.
2004-05-19 22:00:32 +00:00
jrandom
7293a8d3c0 more logging than your mom 2004-05-19 15:24:25 +00:00
jrandom
097a4647a8 handle i2ptunnel server connection .accept()s asynchronously so we don't refuse lots of requests, causing intermittent "failures"
use the new async error listening interface of the ministreaming lib
truckloads of logging
2004-05-19 15:20:55 +00:00
jrandom
0942a7f3ff truckloads of logging
new async interface for error notification (e.g. you can get notified of an error prior to it throwing the IOException).
This async is useful since the IOException can be delayed for up to a minute while waiting for the close packet to be delivered.
The alternative is to fire off a new thread to do the closing, and we may want to go there later, but i'm not sure.
2004-05-19 15:14:30 +00:00
brianr
2df4370477 Some changes to make the SAM module never block if called on a socket
which select() says is safe to read/write or called in any case on a socket
which is O_NONBLOCK

Significant work is still required.
2004-05-19 01:26:02 +00:00
jrandom
7243963106 removed the insane explicit GC 2004-05-18 18:39:43 +00:00
jrandom
9f17654052 tuned to avoid expensive biginteger operation (well, not "expensive", but a lot more expensive than a few shifts)
when we need to debug, essentially assert the validity of the new tuned op, losing the performance benefit by duplicating the effort (to verify)
2004-05-18 18:33:37 +00:00
jrandom
1a65d7061d added morph.i2p 2004-05-17 05:46:06 +00:00
shendaras
292363eb65 imports (sorry, includes alphabetizing, wee)
(shendaras)
2004-05-17 03:38:53 +00:00
jrandom
07e79ce61a * do a db store after a successful db search (healing the netDb)
* timeout each peer in a db search after 10 seconds, not 30
* logging
2004-05-17 00:59:29 +00:00
brianr
1cf7dac82b test 2004-05-16 21:44:23 +00:00
brianr
6003b2902f Preliminary checkin of (mostly useless) Net::SAM perl module.
Net::SAM::StreamSession is currently unimplemented.
Net::Sam::[Datagram|Raw]Session block when they shouldn't and are buggy.
2004-05-16 21:35:46 +00:00
jrandom
ff0023a889 big ol' memory, cpu usage, and shutdown handling update. main changes include:
* rather than have all jobs created hooked into the clock for offset updates, have the jobQueue stay hooked up and update any active jobs accordingly (killing a memory leak of a JobTiming objects - one per job)
* dont go totally insane during shutdown and log like mad (though the clientApp things still log like mad, since they don't know the router is going down)
* adjust memory buffer sizes based on real world values so we don't have to expand/contract a lot
* dont display things that are completely useless (who cares what the first 32 bytes of a public key are?)
* reduce temporary object creation
* use more efficient collections at times
* on shutdown, log some state information (ready/timed jobs, pending messages, etc)
* explicit GC every 10 jobs.  yeah, not efficient, but just for now we'll keep 'er in there
* only reread the router config file if it changes (duh)
2004-05-16 04:54:50 +00:00
jrandom
8c6bf5a1cc added nickster.i2p 2004-05-16 04:42:17 +00:00
320 changed files with 10597 additions and 2392 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

@@ -2,11 +2,11 @@ package net.i2p.heartbeat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import net.i2p.stat.Rate;

View File

@@ -11,8 +11,8 @@ import java.util.Set;
import java.util.TreeMap;
import net.i2p.data.Destination;
import net.i2p.util.Log;
import net.i2p.heartbeat.ClientConfig;
import net.i2p.util.Log;
/**
* Configure how we want to render a particular clientConfig in the GUI

View File

@@ -7,8 +7,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.naming.NamingService;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketOptions;
@@ -19,7 +19,6 @@ import net.i2p.httptunnel.SocketManagerProducer;
import net.i2p.httptunnel.filter.Filter;
import net.i2p.httptunnel.filter.NullFilter;
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
/**
* Handler for browsing Eepsites.

View File

@@ -3,7 +3,7 @@ package net.i2p.httptunnel.handler;
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.client.naming.NamingService;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.data.Destination;
import net.i2p.httptunnel.HTTPListener;
@@ -12,7 +12,6 @@ import net.i2p.httptunnel.SocketManagerProducer;
import net.i2p.httptunnel.filter.Filter;
import net.i2p.httptunnel.filter.NullFilter;
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
/**
* Handler for proxying "normal" HTTP requests.

View File

@@ -67,6 +67,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
private Log _log;
private EventDispatcherImpl _event;
private I2PAppContext _context;
private static long __tunnelId = 0;
private long _tunnelId;
public static final int PACKET_DELAY = 100;
@@ -98,7 +100,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
public I2PTunnel(String[] args, ConnectionEventListener lsnr) {
_context = new I2PAppContext();
_context = I2PAppContext.getGlobalContext(); // new I2PAppContext();
_tunnelId = ++__tunnelId;
_log = _context.logManager().getLog(I2PTunnel.class);
_event = new EventDispatcherImpl();
addConnectionEventListener(lsnr);
@@ -114,7 +117,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
checkRunByE = false;
} else if (args[i].equals("-nogui")) {
gui = false;
_log.warn("The `-nogui' option of I2PTunnel is deprecated.\n"
_log.warn(getPrefix() + "The `-nogui' option of I2PTunnel is deprecated.\n"
+ "Use `-cli', `-nocli' (aka `-wait') or `-die' instead.");
} else if (args[i].equals("-cli")) {
gui = false;
@@ -280,7 +283,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
serverHost = InetAddress.getByName(args[0]);
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error("Error resolving " + args[0], uhe);
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", new Integer(-1));
return;
}
@@ -289,7 +292,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
portNum = Integer.parseInt(args[1]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error("Port specified is not valid: " + args[1], nfe);
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", new Integer(-1));
return;
}
@@ -297,7 +300,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
privKeyFile = new File(args[2]);
if (!privKeyFile.canRead()) {
l.log("private key file does not exist");
_log.error("Private key file does not exist or is not readable: " + args[2]);
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
notifyEvent("serverTaskId", new Integer(-1));
return;
}
@@ -333,7 +336,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
serverHost = InetAddress.getByName(args[0]);
} catch (UnknownHostException uhe) {
l.log("unknown host");
_log.error("Error resolving " + args[0], uhe);
_log.error(getPrefix() + "Error resolving " + args[0], uhe);
notifyEvent("serverTaskId", new Integer(-1));
return;
}
@@ -342,7 +345,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
portNum = Integer.parseInt(args[1]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error("Port specified is not valid: " + args[1], nfe);
_log.error(getPrefix() + "Port specified is not valid: " + args[1], nfe);
notifyEvent("serverTaskId", new Integer(-1));
return;
}
@@ -378,7 +381,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error("Port specified is not valid: " + args[0], nfe);
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("clientTaskId", new Integer(-1));
return;
}
@@ -410,7 +413,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error("Port specified is not valid: " + args[0], nfe);
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("httpclientTaskId", new Integer(-1));
return;
}
@@ -451,7 +454,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error("Port specified is not valid: " + args[0], nfe);
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("sockstunnelTaskId", new Integer(-1));
return;
}
@@ -565,7 +568,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
pubdest = new FileOutputStream(args[1]);
} catch (IOException ioe) {
l.log("Error opening output stream");
_log.error("Error generating keys to out", ioe);
_log.error(getPrefix() + "Error generating keys to out", ioe);
notifyEvent("genkeysResult", "error");
return;
}
@@ -588,7 +591,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
} catch (IOException ioe) {
l.log("Error generating keys - " + ioe.getMessage());
notifyEvent("genkeysResult", "error");
_log.error("Error generating keys", ioe);
_log.error(getPrefix() + "Error generating keys", ioe);
}
}
@@ -722,7 +725,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("runResult", "ok");
} catch (IOException ioe) {
l.log("IO error running the file");
_log.error("Error running the file", ioe);
_log.error(getPrefix() + "Error running the file", ioe);
notifyEvent("runResult", "error");
}
} else {
@@ -796,12 +799,12 @@ public class I2PTunnel implements Logging, EventDispatcher {
private boolean closetask(int num, boolean forced, Logging l) {
boolean closed = false;
_log.debug("closetask(): looking for task " + num);
_log.debug(getPrefix() + "closetask(): looking for task " + num);
synchronized (tasks) {
for (Iterator it = tasks.iterator(); it.hasNext();) {
I2PTunnelTask t = (I2PTunnelTask) it.next();
int id = t.getId();
_log.debug("closetask(): parsing task " + id + " (" + t.toString() + ")");
_log.debug(getPrefix() + "closetask(): parsing task " + id + " (" + t.toString() + ")");
if (id == num) {
closed = closetask(t, forced, l);
break;
@@ -836,7 +839,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
for (Iterator it = tasks.iterator(); it.hasNext();) {
I2PTunnelTask t = (I2PTunnelTask) it.next();
if (!t.isOpen()) {
_log.debug("Purging inactive tunnel: [" + t.getId() + "] " + t.toString());
_log.debug(getPrefix() + "Purging inactive tunnel: [" + t.getId() + "] " + t.toString());
it.remove();
}
}
@@ -849,7 +852,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*/
public void log(String s) {
System.out.println(s);
_log.info("Display: " + s);
_log.info(getPrefix() + "Display: " + s);
}
/**
@@ -982,6 +985,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
listeners.remove(lsnr);
}
}
private String getPrefix() { return '[' + _tunnelId + "]: "; }
/**
* Call this whenever we lose touch with the router involuntarily (aka the router
@@ -989,7 +994,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
*
*/
void routerDisconnected() {
_log.error("Router disconnected - firing notification events");
_log.error(getPrefix() + "Router disconnected - firing notification events");
synchronized (listeners) {
for (Iterator iter = listeners.iterator(); iter.hasNext();) {
ConnectionEventListener lsnr = (ConnectionEventListener) iter.next();

View File

@@ -5,7 +5,6 @@ package net.i2p.i2ptunnel;
import java.net.Socket;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;

View File

@@ -34,7 +34,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static final long DEFAULT_CONNECT_TIMEOUT = 60 * 1000;
private static volatile long __clientId = 0;
private long _clientId;
protected long _clientId;
protected Object sockLock = new Object(); // Guards sockMgr and mySockets
private I2PSocketManager sockMgr;
private List mySockets = new ArrayList();

View File

@@ -10,9 +10,6 @@ import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.StringTokenizer;
import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocket;
@@ -48,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"+
@@ -57,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>"+
@@ -101,6 +98,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
notifyEvent("openHTTPClientResult", "ok");
}
private String getPrefix() { return "Client[" + _clientId + "]: "; }
protected void clientConnectionRun(Socket s) {
OutputStream out = null;
String targetRequest = null;
@@ -113,7 +112,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
StringBuffer newRequest = new StringBuffer();
while ((line = br.readLine()) != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Line=[" + line + "]");
_log.debug(getPrefix() + "Line=[" + line + "]");
if (line.startsWith("Connection: ") ||
line.startsWith("Keep-Alive: ") ||
@@ -122,7 +121,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (method == null) { // first line (GET /base64/realaddr)
if (_log.shouldLog(Log.DEBUG))
_log.debug("Method is null for [" + line + "]");
_log.debug(getPrefix() + "Method is null for [" + line + "]");
int pos = line.indexOf(" ");
if (pos == -1) break;
@@ -158,7 +157,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
destination = wwwProxy;
usingWWWProxy = true;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
_log.debug(getPrefix() + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
} else {
request = request.substring(pos + 1);
pos = request.indexOf("/");
@@ -168,27 +167,27 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
boolean isValid = usingWWWProxy || isSupportedAddress(host, protocol);
if (!isValid) {
if (_log.shouldLog(Log.INFO)) _log.info("notValid(" + host + ")");
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "notValid(" + host + ")");
method = null;
destination = null;
break;
} else if (!usingWWWProxy) {
if (_log.shouldLog(Log.INFO)) _log.info("host=getHostName(" + destination + ")");
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "host=getHostName(" + destination + ")");
host = getHostName(destination); // hide original host
}
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("METHOD:" + method + ":");
_log.debug("PROTOC:" + protocol + ":");
_log.debug("HOST :" + host + ":");
_log.debug("DEST :" + destination + ":");
_log.debug(getPrefix() + "METHOD:" + method + ":");
_log.debug(getPrefix() + "PROTOC:" + protocol + ":");
_log.debug(getPrefix() + "HOST :" + host + ":");
_log.debug(getPrefix() + "DEST :" + destination + ":");
}
} else {
if (line.startsWith("Host: ") && !usingWWWProxy) {
line = "Host: " + host;
if (_log.shouldLog(Log.INFO))
_log.info("Setting host = " + host);
_log.info(getPrefix() + "Setting host = " + host);
}
}
@@ -200,7 +199,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("NewRequest header: [" + newRequest.toString() + "]");
_log.debug(getPrefix() + "NewRequest header: [" + newRequest.toString() + "]");
while (br.ready()) { // empty the buffer (POST requests)
int i = br.read();
@@ -222,7 +221,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Destination: " + destination);
_log.debug(getPrefix() + "Destination: " + destination);
Destination dest = I2PTunnel.destFromName(destination);
if (dest == null) {
@@ -239,19 +238,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
timeoutThread.start();
} catch (SocketException ex) {
if (timeoutThread != null) timeoutThread.disable();
_log.info("Error trying to connect", ex);
_log.info(getPrefix() + "Error trying to connect", ex);
l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, wwwProxy);
closeSocket(s);
} catch (IOException ex) {
if (timeoutThread != null) timeoutThread.disable();
_log.info("Error trying to connect", ex);
_log.info(getPrefix() + "Error trying to connect", ex);
l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, wwwProxy);
closeSocket(s);
} catch (I2PException ex) {
if (timeoutThread != null) timeoutThread.disable();
_log.info("Error trying to connect", ex);
_log.info("getPrefix() + Error trying to connect", ex);
l.log(ex.getMessage());
handleHTTPClientException(ex, out, targetRequest, usingWWWProxy, wwwProxy);
closeSocket(s);
@@ -280,7 +279,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
_useWWWProxy = useWWWProxy;
_disabled = false;
long timeoutId = ++__timeoutId;
setName("InactivityThread " + timeoutId);
setName("InactivityThread " + getPrefix() + timeoutId);
}
public void disable() {
@@ -293,15 +292,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
public void run() {
while (!_disabled) {
if (_runner.isFinished()) {
if (_log.shouldLog(Log.INFO)) _log.info("HTTP client request completed prior to timeout");
if (_log.shouldLog(Log.INFO)) _log.info(getPrefix() + "HTTP client request completed prior to timeout");
return;
}
if (_runner.getLastActivityOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) {
if (_runner.getStartedOn() < Clock.getInstance().now() - INACTIVITY_TIMEOUT) {
if (_log.shouldLog(Log.WARN))
_log.warn("HTTP client request timed out (lastActivity: "
_log.warn(getPrefix() + "HTTP client request timed out (lastActivity: "
+ new Date(_runner.getLastActivityOn()) + ", startedOn: "
+ new Date(_runner.getLastActivityOn()) + ")");
+ new Date(_runner.getStartedOn()) + ")");
timeout();
return;
} else {
@@ -320,7 +319,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
private void timeout() {
_log.info("Inactivity timeout reached");
_log.info(getPrefix() + "Inactivity timeout reached");
l.log("Inactivity timeout reached");
if (_out != null) {
try {
@@ -330,10 +329,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
writeErrorMessage(ERR_TIMEOUT, _out, _targetRequest, _useWWWProxy, wwwProxy);
}
} catch (IOException ioe) {
_log.warn("Error writing out the 'timeout' message", ioe);
_log.warn(getPrefix() + "Error writing out the 'timeout' message", ioe);
}
} else {
_log.warn("Client disconnected before we could say we timed out");
_log.warn(getPrefix() + "Client disconnected before we could say we timed out");
}
closeSocket(s);
}
@@ -364,16 +363,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
}
}
private static void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
private void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy) {
if (out != null) {
try {
writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, wwwProxy);
} catch (IOException ioe) {
_log.warn("Error writing out the 'destination was unknown' " + "message", ioe);
_log.warn(getPrefix() + "Error writing out the 'destination was unknown' " + "message", ioe);
}
} else {
_log.warn("Client disconnected before we could say that destination " + "was unknown", ex);
_log.warn(getPrefix() + "Client disconnected before we could say that destination " + "was unknown", ex);
}
}

View File

@@ -18,7 +18,7 @@ import net.i2p.util.Clock;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
public class I2PTunnelRunner extends I2PThread {
public class I2PTunnelRunner extends I2PThread implements I2PSocket.SocketErrorListener {
private final static Log _log = new Log(I2PTunnelRunner.class);
private static volatile long __runnerId;
@@ -51,8 +51,9 @@ public class I2PTunnelRunner extends I2PThread {
this.slock = slock;
this.initialData = initialData;
lastActivityOn = -1;
startedOn = -1;
_log.info("I2PTunnelRunner started");
startedOn = Clock.getInstance().now();
if (_log.shouldLog(Log.INFO))
_log.info("I2PTunnelRunner started");
_runnerId = ++__runnerId;
setName("I2PTunnelRunner " + _runnerId);
start();
@@ -90,10 +91,10 @@ public class I2PTunnelRunner extends I2PThread {
}
public void run() {
startedOn = Clock.getInstance().now();
try {
InputStream in = s.getInputStream();
OutputStream out = new BufferedOutputStream(s.getOutputStream(), NETWORK_BUFFER_SIZE);
i2ps.setSocketErrorListener(this);
InputStream i2pin = i2ps.getInputStream();
OutputStream i2pout = new BufferedOutputStream(i2ps.getOutputStream(), MAX_PACKET_SIZE);
if (initialData != null) {
@@ -121,6 +122,8 @@ public class I2PTunnelRunner extends I2PThread {
} catch (IOException ex) {
ex.printStackTrace();
_log.debug("Error forwarding", ex);
} catch (Exception e) {
_log.error("Internal error", e);
} finally {
try {
if (s != null) s.close();
@@ -132,6 +135,13 @@ public class I2PTunnelRunner extends I2PThread {
}
}
public void errorOccurred() {
synchronized (finishLock) {
finished = true;
finishLock.notifyAll();
}
}
private volatile long __forwarderId = 0;
private class StreamForwarder extends I2PThread {
@@ -187,7 +197,8 @@ public class I2PTunnelRunner extends I2PThread {
out.close();
in.close();
} catch (IOException ex) {
_log.error("Error closing streams", ex);
if (_log.shouldLog(Log.WARN))
_log.warn("Error closing streams", ex);
}
synchronized (finishLock) {
finished = true;

View File

@@ -14,6 +14,7 @@ import java.net.SocketException;
import java.util.Iterator;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
@@ -144,15 +145,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
I2PServerSocket i2pss = sockMgr.getServerSocket();
while (true) {
I2PSocket i2ps = i2pss.accept();
//local is fast, so synchronously. Does not need that many
//threads.
try {
i2ps.setReadTimeout(readTimeout);
Socket s = new Socket(remoteHost, remotePort);
new I2PTunnelRunner(s, i2ps, slock, null);
} catch (SocketException ex) {
i2ps.close();
}
I2PThread t = new I2PThread(new Handler(i2ps));
t.start();
}
} catch (I2PException ex) {
_log.error("Error while waiting for I2PConnections", ex);
@@ -160,5 +154,43 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
_log.error("Error while waiting for I2PConnections", ex);
}
}
/**
* Async handler to keep .accept() from blocking too long.
* todo: replace with a thread pool so we dont get overrun by threads if/when
* receiving a lot of connection requests concurrently.
*
*/
private class Handler implements Runnable {
private I2PSocket _handleSocket;
public Handler(I2PSocket socket) {
_handleSocket = socket;
}
public void run() {
long afterAccept = I2PAppContext.getGlobalContext().clock().now();
long afterSocket = -1;
//local is fast, so synchronously. Does not need that many
//threads.
try {
_handleSocket.setReadTimeout(readTimeout);
Socket s = new Socket(remoteHost, remotePort);
afterSocket = I2PAppContext.getGlobalContext().clock().now();
new I2PTunnelRunner(s, _handleSocket, slock, null);
} catch (SocketException ex) {
try {
_handleSocket.close();
} catch (IOException ioe) {
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ex) {
_log.error("Error while waiting for I2PConnections", ex);
}
long afterHandle = I2PAppContext.getGlobalContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
if (timeToHandle > 1000)
_log.warn("Took a while to handle the request [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
}
}
}

View File

@@ -6,7 +6,7 @@ public class ByteCollector {
int size;
public ByteCollector() {
contents = new byte[80];
contents = new byte[1024];
size = 0;
}

View File

@@ -1,15 +1,14 @@
package net.i2p.client.streaming;
import java.net.ConnectException;
import net.i2p.I2PException;
import net.i2p.util.Log;
import net.i2p.util.Clock;
import net.i2p.I2PAppContext;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* Server socket implementation, allowing multiple threads to accept I2PSockets
@@ -90,7 +89,7 @@ class I2PServerSocketImpl implements I2PServerSocket {
*/
public boolean addWaitForAccept(I2PSocket s, long timeoutMs) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("addWaitForAccept [new socket arrived, pending: " + pendingSockets.size());
_log.debug("addWaitForAccept [new socket arrived [" + s.toString() + "], pending: " + pendingSockets.size());
if (closing) {
if (_log.shouldLog(Log.WARN))
@@ -112,7 +111,7 @@ class I2PServerSocketImpl implements I2PServerSocket {
long now = clock.now();
if (now >= end) {
if (_log.shouldLog(Log.INFO))
_log.info("Expired while waiting for accept (time elapsed =" + (now - start) + "ms");
_log.info("Expired while waiting for accept (time elapsed =" + (now - start) + "ms) for socket " + s.toString());
pendingSockets.remove(s);
return false;
}
@@ -131,7 +130,7 @@ class I2PServerSocketImpl implements I2PServerSocket {
}
long now = clock.now();
if (_log.shouldLog(Log.DEBUG))
_log.info("Socket accepted after " + (now-start) + "ms");
_log.info("Socket accepted after " + (now-start) + "ms for socket " + s.toString());
return true;
}

View File

@@ -50,4 +50,21 @@ public interface I2PSocket {
* Closes the socket if not closed yet
*/
public void close() throws IOException;
public void setSocketErrorListener(SocketErrorListener lsnr);
/**
* Allow notification of underlying errors communicating across I2P without
* waiting for any sort of cleanup process. For example, if some data could
* not be sent, this listener is notified immediately, and while the input/output
* streams are notified through IOExceptions, they are told only after the
* TCP-like stream is closed (which may be a minute later, if the close message
* times out as well). This is not fired on normal close() activity.
*
*/
public interface SocketErrorListener {
/**
* An error occurred communicating with the peer.
*/
void errorOccurred();
}
}

View File

@@ -29,7 +29,12 @@ class I2PSocketImpl implements I2PSocket {
private Object remoteIDWaiter = new Object();
private I2PInputStream in;
private I2POutputStream out;
private SocketErrorListener _socketErrorListener;
private boolean outgoing;
private long _socketId;
private static long __socketId = 0;
private long _bytesRead = 0;
private long _bytesWritten = 0;
private Object flagLock = new Object();
/**
@@ -61,6 +66,7 @@ class I2PSocketImpl implements I2PSocket {
this.outgoing = outgoing;
manager = mgr;
remote = peer;
_socketId = ++__socketId;
local = mgr.getSession().getMyDestination();
in = new I2PInputStream();
I2PInputStream pin = new I2PInputStream();
@@ -153,6 +159,7 @@ class I2PSocketImpl implements I2PSocket {
* @param data the data to inject into our local inputStream
*/
public void queueData(byte[] data) {
_bytesRead += data.length;
in.queueData(data);
}
@@ -232,6 +239,17 @@ class I2PSocketImpl implements I2PSocket {
in.setReadTimeout(ms);
}
public void setSocketErrorListener(SocketErrorListener lsnr) {
_socketErrorListener = lsnr;
}
void errorOccurred() {
if (_socketErrorListener != null)
_socketErrorListener.errorOccurred();
}
private String getPrefix() { return "[" + _socketId + "]: "; }
//--------------------------------------------------
private class I2PInputStream extends InputStream {
@@ -256,7 +274,8 @@ class I2PSocketImpl implements I2PSocket {
}
public synchronized int read(byte[] b, int off, int len) throws IOException {
_log.debug("Read called: " + this.hashCode());
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Read called: " + this.hashCode());
if (len == 0) return 0;
long dieAfter = System.currentTimeMillis() + readTimeout;
byte[] read = bc.startToByteArray(len);
@@ -265,7 +284,8 @@ class I2PSocketImpl implements I2PSocket {
while (read.length == 0) {
synchronized (flagLock) {
if (closed) {
_log.debug("Closed is set, so closing stream: " + hashCode());
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Closed is set after reading " + _bytesRead + " and writing " + _bytesWritten + ", so closing stream: " + hashCode());
return -1;
}
}
@@ -279,7 +299,7 @@ class I2PSocketImpl implements I2PSocket {
if ((readTimeout >= 0)
&& (System.currentTimeMillis() >= dieAfter)) {
throw new InterruptedIOException("Timeout reading from I2PSocket (" + readTimeout + " msecs)");
throw new InterruptedIOException(getPrefix() + "Timeout reading from I2PSocket (" + readTimeout + " msecs)");
}
read = bc.startToByteArray(len);
@@ -288,7 +308,7 @@ class I2PSocketImpl implements I2PSocket {
System.arraycopy(read, 0, b, off, read.length);
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("Read from I2PInputStream " + hashCode() + " returned "
_log.debug(getPrefix() + "Read from I2PInputStream " + hashCode() + " returned "
+ read.length + " bytes");
}
//if (_log.shouldLog(Log.DEBUG)) {
@@ -309,7 +329,7 @@ class I2PSocketImpl implements I2PSocket {
public synchronized void queueData(byte[] data, int off, int len) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Insert " + len + " bytes into queue: " + hashCode());
_log.debug(getPrefix() + "Insert " + len + " bytes into queue: " + hashCode());
bc.append(data, off, len);
notifyAll();
}
@@ -338,6 +358,7 @@ class I2PSocketImpl implements I2PSocket {
}
public void write(byte[] b, int off, int len) throws IOException {
_bytesWritten += len;
sendTo.queueData(b, off, len);
}
@@ -353,10 +374,10 @@ class I2PSocketImpl implements I2PSocket {
public I2PSocketRunner(InputStream in) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Runner's input stream is: " + in.hashCode());
_log.debug(getPrefix() + "Runner's input stream is: " + in.hashCode());
this.in = in;
String peer = I2PSocketImpl.this.remote.calculateHash().toBase64();
setName("SocketRunner " + (++__runnerId) + " " + peer.substring(0, 4));
setName("SocketRunner " + (++__runnerId) + "/" + _socketId + " " + peer.substring(0, 4));
start();
}
@@ -378,7 +399,7 @@ class I2PSocketImpl implements I2PSocket {
}
if ((bcsize < MAX_PACKET_SIZE) && (in.available() == 0)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Runner Point d: " + hashCode());
_log.debug(getPrefix() + "Runner Point d: " + hashCode());
try {
Thread.sleep(PACKET_DELAY);
@@ -390,10 +411,11 @@ class I2PSocketImpl implements I2PSocket {
byte[] data = bc.startToByteArray(MAX_PACKET_SIZE);
if (data.length > 0) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Message size is: " + data.length);
_log.debug(getPrefix() + "Message size is: " + data.length);
boolean sent = sendBlock(data);
if (!sent) {
_log.error("Error sending message to peer. Killing socket runner");
_log.error(getPrefix() + "Error sending message to peer. Killing socket runner");
errorOccurred();
return false;
}
}
@@ -413,7 +435,7 @@ class I2PSocketImpl implements I2PSocket {
packetsHandled++;
}
if ((bc.getCurrentSize() > 0) && (packetsHandled > 1)) {
_log.error("A SCARY MONSTER HAS EATEN SOME DATA! " + "(input stream: "
_log.error(getPrefix() + "A SCARY MONSTER HAS EATEN SOME DATA! " + "(input stream: "
+ in.hashCode() + "; "
+ "queue size: " + bc.getCurrentSize() + ")");
}
@@ -426,32 +448,33 @@ class I2PSocketImpl implements I2PSocket {
} // FIXME: Race here?
if (sc) {
if (_log.shouldLog(Log.INFO))
_log.info("Sending close packet: " + outgoing);
_log.info(getPrefix() + "Sending close packet: (we started? " + outgoing + ") after reading " + _bytesRead + " and writing " + _bytesWritten);
byte[] packet = I2PSocketManager.makePacket(getMask(0x02), remoteID, new byte[0]);
boolean sent = manager.getSession().sendMessage(remote, packet);
if (!sent) {
_log.error("Error sending close packet to peer");
_log.error(getPrefix() + "Error sending close packet to peer");
errorOccurred();
}
}
manager.removeSocket(I2PSocketImpl.this);
} catch (InterruptedIOException ex) {
_log.error("BUG! read() operations should not timeout!", ex);
_log.error(getPrefix() + "BUG! read() operations should not timeout!", ex);
} catch (IOException ex) {
// WHOEVER removes this event on inconsistent
// state before fixing the inconsistent state (a
// reference on the socket in the socket manager
// etc.) will get hanged by me personally -- mihi
_log.error("Error running - **INCONSISTENT STATE!!!**", ex);
_log.error(getPrefix() + "Error running - **INCONSISTENT STATE!!!**", ex);
} catch (I2PException ex) {
_log.error("Error running - **INCONSISTENT STATE!!!**", ex);
_log.error(getPrefix() + "Error running - **INCONSISTENT STATE!!!**", ex);
}
}
private boolean sendBlock(byte data[]) throws I2PSessionException {
if (_log.shouldLog(Log.DEBUG))
_log.debug("TIMING: Block to send for " + I2PSocketImpl.this.hashCode());
_log.debug(getPrefix() + "TIMING: Block to send for " + I2PSocketImpl.this.hashCode());
if (remoteID == null) {
_log.error("NULL REMOTEID");
_log.error(getPrefix() + "NULL REMOTEID");
return false;
}
byte[] packet = I2PSocketManager.makePacket(getMask(0x00), remoteID, data);
@@ -463,4 +486,6 @@ class I2PSocketImpl implements I2PSocket {
return sent;
}
}
public String toString() { return "" + hashCode(); }
}

View File

@@ -4,7 +4,6 @@
*/
package net.i2p.client.streaming;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
@@ -21,8 +20,8 @@ import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PSessionListener;
import net.i2p.data.Base64;
import net.i2p.data.Destination;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Log;
/**
@@ -190,7 +189,7 @@ public class I2PSocketManager implements I2PSessionListener {
s = (I2PSocketImpl) _outSockets.get(id);
}
_log.debug("*Disconnect outgoing!");
_log.debug("*Disconnect outgoing for socket " + s);
try {
if (s != null) {
if (payload.length > 0) {
@@ -208,7 +207,7 @@ public class I2PSocketManager implements I2PSessionListener {
}
return;
} catch (Exception t) {
_log.error("Ignoring error on disconnect", t);
_log.error("Ignoring error on disconnect for socket " + s, t);
}
}
@@ -226,7 +225,7 @@ public class I2PSocketManager implements I2PSessionListener {
// packet send outgoing
if (_log.shouldLog(Log.DEBUG))
_log.debug("*Packet send outgoing [" + payload.length + "]");
_log.debug("*Packet send outgoing [" + payload.length + "] for socket " + s);
if (s != null) {
s.queueData(payload);
return;
@@ -246,7 +245,6 @@ public class I2PSocketManager implements I2PSessionListener {
*/
private void synIncomingAvailable(String id, byte payload[], I2PSession session)
throws DataFormatException, I2PSessionException {
_log.debug("*Syn!");
Destination d = new Destination();
d.fromByteArray(payload);
@@ -260,6 +258,7 @@ public class I2PSocketManager implements I2PSessionListener {
s.setRemoteID(id);
}
}
_log.debug("*Syn! for socket " + s);
if (!acceptConnections) {
// The app did not instantiate an I2PServerSocket
@@ -284,7 +283,7 @@ public class I2PSocketManager implements I2PSessionListener {
if (!replySentOk) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error sending reply to " + d.calculateHash().toBase64()
+ " in response to a new con message",
+ " in response to a new con message for socket " + s,
new Exception("Failed creation"));
s.internalClose();
}
@@ -294,7 +293,7 @@ public class I2PSocketManager implements I2PSessionListener {
packet[0] = CLOSE_OUT;
boolean nackSent = session.sendMessage(d, packet);
if (!nackSent) {
_log.warn("Error sending NACK for session creation");
_log.warn("Error sending NACK for session creation for socket " + s);
}
s.internalClose();
}
@@ -307,7 +306,6 @@ public class I2PSocketManager implements I2PSessionListener {
*
*/
private void disconnectIncoming(String id, byte payload[]) {
_log.debug("*Disconnect incoming!");
I2PSocketImpl s = null;
synchronized (lock) {
s = (I2PSocketImpl) _inSockets.get(id);
@@ -316,6 +314,8 @@ public class I2PSocketManager implements I2PSessionListener {
}
}
_log.debug("*Disconnect incoming for socket " + s);
try {
if (payload.length == 0 && s != null) {
s.internalClose();
@@ -340,12 +340,13 @@ public class I2PSocketManager implements I2PSessionListener {
* @throws IllegalStateException if the socket isn't open or isn't known
*/
private void sendIncoming(String id, byte payload[]) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("*Packet send incoming [" + payload.length + "]");
I2PSocketImpl s = null;
synchronized (lock) {
s = (I2PSocketImpl) _inSockets.get(id);
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("*Packet send incoming [" + payload.length + "] for socket " + s);
if (s != null) {
s.queueData(payload);
@@ -423,7 +424,7 @@ public class I2PSocketManager implements I2PSessionListener {
boolean sent = false;
sent = _session.sendMessage(peer, packet);
if (!sent) {
_log.info("Unable to send & receive ack for SYN packet");
_log.info("Unable to send & receive ack for SYN packet for socket " + s);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
@@ -432,18 +433,18 @@ public class I2PSocketManager implements I2PSessionListener {
remoteID = s.getRemoteID(true, options.getConnectTimeout());
if (remoteID == null)
throw new ConnectException("Connection refused by peer");
throw new ConnectException("Connection refused by peer for socket " + s);
if ("".equals(remoteID))
throw new NoRouteToHostException("Unable to reach peer");
throw new NoRouteToHostException("Unable to reach peer for socket " + s);
if (_log.shouldLog(Log.DEBUG))
_log.debug("TIMING: s given out for remoteID "
+ getReadableForm(remoteID));
+ getReadableForm(remoteID) + " for socket " + s);
return s;
} catch (InterruptedIOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Timeout waiting for ack from syn for id "
+ getReadableForm(lcID), ioe);
+ getReadableForm(lcID) + " for socket " + s, ioe);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
@@ -457,7 +458,7 @@ public class I2PSocketManager implements I2PSessionListener {
throw ex;
} catch (IOException ex) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error sending syn on id " + getReadableForm(lcID), ex);
_log.error("Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
@@ -465,7 +466,7 @@ public class I2PSocketManager implements I2PSessionListener {
throw new I2PException("Unhandled IOException occurred");
} catch (I2PException ex) {
if (_log.shouldLog(Log.INFO))
_log.info("Error sending syn on id " + getReadableForm(lcID), ex);
_log.info("Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
@@ -578,7 +579,7 @@ public class I2PSocketManager implements I2PSessionListener {
public void removeSocket(I2PSocketImpl sock) {
synchronized (lock) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Removing socket \"" + getReadableForm(sock.getLocalID()) + "\"");
_log.debug("Removing socket \"" + getReadableForm(sock.getLocalID()) + "\" [" + sock + "]");
_inSockets.remove(sock.getLocalID());
_outSockets.remove(sock.getLocalID());
lock.notify();

View File

@@ -1,17 +1,18 @@
package net.i2p.netmonitor;
import net.i2p.data.RouterInfo;
import net.i2p.util.Log;
import net.i2p.util.Clock;
import java.util.Properties;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Locale;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.data.RouterInfo;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* Pull out important data from the published routerInfo and stash it away

View File

@@ -1,24 +1,24 @@
package net.i2p.netmonitor;
import net.i2p.util.Log;
import net.i2p.util.I2PThread;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import net.i2p.util.I2PThread;
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

@@ -1,19 +1,18 @@
package net.i2p.netmonitor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.i2p.util.Clock;
import net.i2p.util.Log;
import net.i2p.data.DataFormatException;
import net.i2p.data.RouterInfo;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* Active process that drives the monitoring by periodically rading the
@@ -130,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;
}
@@ -148,4 +170,4 @@ class NetMonitorRunner implements Runnable {
Thread.sleep(_monitor.getHarvestDelay());
} catch (InterruptedException ie) {}
}
}
}

View File

@@ -1,16 +1,16 @@
package net.i2p.netmonitor;
import net.i2p.util.Clock;
import net.i2p.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Set;
import java.util.TreeMap;
import net.i2p.util.Clock;
import net.i2p.util.Log;
/**
* coordinate the data points summarizing the performance of a particular peer

View File

@@ -1,20 +1,17 @@
package net.i2p.netmonitor;
import net.i2p.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.TreeSet;
import java.util.Set;
import java.util.Locale;
import java.util.Date;
import java.util.StringTokenizer;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import net.i2p.util.Log;
/**
* Load up the peer summary

View File

@@ -1,15 +1,15 @@
package net.i2p.netmonitor;
import net.i2p.util.Log;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import java.util.Set;
import java.util.Locale;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.TreeSet;
import net.i2p.util.Log;
/**
* Dump various peer summaries to disk (so external apps (or good ol' vi) can

View File

@@ -1,14 +1,15 @@
package net.i2p.netmonitor;
import net.i2p.util.Log;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import net.i2p.util.Log;
/**
* Load up the StatGroups from the location specified to configure the data harvester.
* The stat groups are formatted in a simple properties file style, e.g.: <pre>

View File

@@ -1,28 +1,24 @@
package net.i2p.netmonitor.gui;
import net.i2p.netmonitor.PeerSummary;
import net.i2p.netmonitor.PeerStat;
import net.i2p.util.Log;
import org.jfree.data.XYSeries;
import org.jfree.data.XYSeriesCollection;
import org.jfree.data.MovingAverage;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.renderer.XYLineAndShapeRenderer;
import org.jfree.chart.renderer.XYItemRenderer;
import org.jfree.chart.renderer.XYDotRenderer;
import java.awt.Color;
import java.awt.Font;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Iterator;
import javax.swing.JPanel;
import java.awt.Font;
import java.awt.Color;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.XYItemRenderer;
import org.jfree.chart.renderer.XYLineAndShapeRenderer;
import org.jfree.data.XYSeries;
import org.jfree.data.XYSeriesCollection;
import net.i2p.netmonitor.PeerStat;
import net.i2p.util.Log;
class JFreeChartAdapter {
private final static Log _log = new Log(JFreeChartAdapter.class);

View File

@@ -1,20 +1,15 @@
package net.i2p.netmonitor.gui;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import net.i2p.util.Log;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import org.jfree.chart.ChartPanel;
import net.i2p.util.Log;
/**
* Render the graph and legend
*

View File

@@ -1,14 +1,13 @@
package net.i2p.netmonitor.gui;
import net.i2p.netmonitor.NetMonitor;
import net.i2p.netmonitor.PeerSummary;
import net.i2p.netmonitor.PeerStat;
import net.i2p.util.Log;
import net.i2p.util.I2PThread;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import net.i2p.netmonitor.NetMonitor;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Coordinate the visualization of the network monitor. <p />

View File

@@ -5,7 +5,6 @@ import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import java.awt.Dimension;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

View File

@@ -1,9 +1,5 @@
package net.i2p.netmonitor.gui;
import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JTextArea;

View File

@@ -1,20 +1,15 @@
package net.i2p.netmonitor.gui;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import net.i2p.data.Destination;
import net.i2p.util.Log;
import net.i2p.netmonitor.PeerSummary;
import net.i2p.util.Log;
/**
* Configure how we want to render a particular peerSummary in the GUI

View File

@@ -5,25 +5,21 @@ import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.TreeMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import net.i2p.util.Log;
import net.i2p.netmonitor.PeerStat;
import net.i2p.netmonitor.PeerSummary;
import net.i2p.util.Log;
class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener {
private final static Log _log = new Log(PeerPlotConfigPane.class);

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

@@ -8,29 +8,25 @@ package net.i2p.sam;
*
*/
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import net.i2p.data.Destination;
import net.i2p.data.DataFormatException;
import net.i2p.data.PrivateKey;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
/**
* SAM bridge implementation.

View File

@@ -8,16 +8,14 @@ package net.i2p.sam;
*
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import net.i2p.client.I2PSessionException;
import net.i2p.client.datagram.I2PDatagramDissector;
import net.i2p.client.datagram.I2PDatagramMaker;
import net.i2p.client.datagram.I2PInvalidDatagramException;
import net.i2p.client.I2PSessionException;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Log;

View File

@@ -12,7 +12,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Properties;
import net.i2p.util.I2PThread;

View File

@@ -9,8 +9,8 @@ package net.i2p.sam;
*/
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;

View File

@@ -9,9 +9,8 @@ package net.i2p.sam;
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import net.i2p.client.I2PClient;

View File

@@ -8,10 +8,8 @@ package net.i2p.sam;
*
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import net.i2p.client.I2PSessionException;

View File

@@ -9,29 +9,27 @@ package net.i2p.sam;
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.HashMap;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.streaming.I2PServerSocket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.client.streaming.I2PSocketOptions;
import net.i2p.client.I2PClient;
import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.I2PException;
import net.i2p.util.HexDump;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;

View File

@@ -8,22 +8,20 @@ package net.i2p.sam;
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.naming.NamingService;
import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
/**
* Miscellaneous utility methods used by SAM protocol handlers.

View File

@@ -8,27 +8,24 @@ package net.i2p.sam;
*
*/
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.util.Enumeration;
import java.net.Socket;
import java.util.Properties;
import java.util.StringTokenizer;
import net.i2p.I2PException;
import net.i2p.client.I2PSessionException;
import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.I2PException;
import net.i2p.util.Log;
/**
@@ -333,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
@@ -395,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;
@@ -466,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;
@@ -559,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;
@@ -761,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());
}

321
apps/sam/perl/Net/SAM.pm Normal file
View File

@@ -0,0 +1,321 @@
#!/usr/bin/perl
## Copyright 2004 Brian Ristuccia. This program is Free Software;
## You can redistribute it and/or modify it under the same terms as
## Perl itself.
package Net::SAM;
@ISA = ( "IO::Socket::INET" );
use strict;
use POSIX;
use Switch;
use IO::Socket;
use IO::Select;
#use Net::SAM::StreamSession;
#use Net::SAM::DatagramSession;
#use Net::SAM::RawSession;
sub new {
my ($class) = shift;
my $type = ref($class) || $class;
my $self = $type->SUPER::new("127.0.0.1:7656");
${*$self}->{incomingraw} = [];
# Connect us to the local SAM proxy.
# my $samsock = IO::Socket::INET->new('127.0.0.1:7657');
#$self->{samsock}=$samsock;
# Say hello, read response.
$self->SUPER::send("HELLO VERSION MIN=1.0 MAX=1.0\n");
while (! ${*$self}->{greeted}) {
$self->readprocess();
}
print "Created SAM object\n";
return $self;
}
sub lookup {
my $self = shift;
my $name= shift;
$self->SUPER::send("NAMING LOOKUP NAME=$name\n");
undef ${*$self}->{RESULT};
while (! ${*$self}->{RESULT}) {
$self->readprocess();
}
if ( ${*$self}->{RESULT} == "OK" ) {
return ${*$self}->{VALUE};
} else {
return undef;
}
}
#sub createsession {
# my ($self) = shift;
# my ($sesstype) = shift;
# print $self->{samsock} "SESSION CREATE STYLE=$SESSTYPE DESTINATION=$DEST, DIRECTION=
#}
#sub waitfor {
# my ($self) = shift;
# my ($prefix) = shift;
# my ($response) = <$samsock>;#
# if $response =~
#}
sub readprocesswrite {
my $self = shift;
$self->readprocess();
$self->dowrite();
}
sub doread {
my $self = shift;
my $rv;
my $data;
$rv = $self->recv($data, $POSIX::BUFSIZE, 0);
if ( defined($rv) && ( length($data) >= 1 ) ) {
# We received some data. Put it in our buffer.
${*$self}->{inbuffer} += $data;
} else {
# No data. Either we're on a non-blocking socket, or there
# was an error or EOF
if ( $!{EAGAIN} ) {
return 1;
} else {
# I suppose caller can look at $! for details
return undef;
}
}
}
sub dowrite {
my $self = shift;
my $rv;
my $data;
$rv = $self->send(${*$self}->{outbuffer}, 0);
if ( ! defined($rv) ) {
warn "SAM::dowrite - Couldn't write for no apparent reason.\n";
return undef;
}
if ( $rv == length(${*$self}->{outbuffer}) || $!{EWOULDBLOCK} ) {
substr(${*$self}->{outbuffer},0, $rv) = ''; # Remove from buffer
# Nuke buffer if empty
delete ${*$self}->{outbuffer} unless length(${*$self}->{outbuffer});
} else {
# Socket closed on us or something?
return undef;
}
}
sub messages {
my $self = shift;
return @{ ${*$self}->{messages} };
}
sub queuemessage {
my $self = shift;
my $message = shift;
push @{ ${*$self}->{messages} } , $message;
}
sub unqueuemessage {
my $self = shift;
return unshift(@{ ${*$self}->{messages} } );
}
sub readprocess {
my $self = shift;
$self->doread();
$self->process();
}
sub process {
my $self = shift;
my %tvhash;
my $payload;
# Before we can read any new messages, if an existing message has payload
# we must read it in. Otherwise we'll create garbage messages containing
# the payload of previous messages.
if ( ${*$self}->{payloadrequired} >= 1 ) {
if ( length( ${*$self}->{inbuffer} ) >= ${*$self}->{payloadrequired} ) {
# Scarf payload from inbuffer into $payload
$payload = substr(${*$self}->{inbuffer}, 0,
${*$self}->{payloadrequired});
# Nuke payload from inbuffer
substr(${*$self}->{inbuffer}, 0,
${*$self}->{payloadrequired} ) = '';
# Put message with payload into spool
push @{ ${*$self}->{messages} } ,
${*$self}->{messagerequiringpayload}.$payload;
# Delete the saved message requiring payload
delete ${*$self}->{messagerequiringpayload};
} else {
# Insufficient payload in inbuffer. Try again later.
return 1;
}
}
if ( ${*$self}->{inbuffer} =~ s/(.*\n)// ) {
%tvhash = $self->_hashtv($1); # Returns a tag/value hash
if ( $tvhash{SIZE} ) {
# We've got a message with payload on our hands. :(
${*$self}->{payloadrequired} = $tvhash{SIZE};
${*$self}->{messagerequiringpayload} = $1;
return 1; # Could call ourself here, but we'll get called again.
} else {
push @{ ${*$self}->{messages} } , $1;
}
}
return 1;
}
# sub junk {
# print "readprocess: " . $self->connected() . "\n";
# # May block if the SAM bridge gets hosed
# my $response = <$self>;
# print "readprocess: $!" . $self->connected() . "\n";
# chomp $response;
# my ($primative, $more, $extra) = split (' ', $response, 3);
# $primative = uc($primative);
# print "readprocess: " . $self->connected() . " -- $primative -- $more -- $extra\n";
# switch ($primative) {
# case "HELLO" {
# if ($more !~ m/REPLY/ ) { die ("Bogus HELLO response") }
# if ($extra =~ m/NOVERSION/ ) {
# die("SAM Bridge Doesn't support my version") ;
# }
# $self->_hashtv($extra);
# ${*$self}->{greeted} = 1;
# };
# case "SESSION" {
# if ( $more !~ m/STATUS/ ) {
# die("Bogus SESSION response");
# }
# $self->_hashtv($extra);
# }
# case "STREAM" {};
# case "DATAGRAM" {
# if ( $more !~ m/RECEIVE/ ) {
# die("Bogus DATAGRAM response.");
# }
# $self->_hashtv($extra);
# push @{ ${*$self}->{incomingdatagram } },
# [ ${*$self}->{DESTINATION},
# $self->_readblock(${*$self}->{SIZE}) ];
# };
# case "RAW" {
# if ( $more !~ m/RECEIVE/ ) {
# die("Bogus RAW response.");
# }
# $self->_hashtv($extra);
# push @{ $self->{incomingraw} }, $self->_readblock($self->{SIZE});
# };
# case "NAMING" {
# if ( $more !~ m/REPLY/ ) {
# die("Bogus NAMING response");
# }
# $self->_hashtv($extra);
# };
# case "DEST" {};
# }
# return 1;
# }
sub getfh {
# Return the FH of the SAM socket so apps can select() or poll() on it
my $self = shift;
return $self->{samsock};
}
sub _readblock {
my $self = shift;
my $size = shift;
my $chunk;
my $payload;
while ( $size > 1 ) {
# XXX: May block. No error checking.
print "readblock: $size\n";
$size -= $self->SUPER::recv($chunk, $size);
$payload .= $chunk;
}
return $payload;
}
sub _hashtv {
my $self = shift;
my $tvstring = shift;
my $tvhash;
while ( $tvstring =~ m/(\S+)=(\S+)/sg ) {
$tvhash->{$1}=$2;
print "hashtv: $1=$2\n"
}
return $tvhash;
}
sub DESTROY {
# Do nothing yet.
}
#sub StreamSession {
# my $self = shift;
# return Net::SAM::StreamSession->new($self);
#}
#sub DatagramSession {
# return Net::SAM::DatagramSession->new($self);
#}
#sub RawSession {
# return Net::SAM::RawSession->new($self);
#}
1;

View File

@@ -0,0 +1,48 @@
#!/usr/bin/perl
package Net::SAM::DatagramSession;
use Net::SAM;
@ISA = ("Net::SAM");
sub new {
my ($class) = shift;
my ($dest , $direction, $options) = shift;
my $self = $class->SUPER::new(@_);
$self->SUPER::send("SESSION CREATE STYLE=DATAGRAM DESTINATION=$dest DIRECTION=$direction $options\n");
undef ${*$self}->{RESULT};
while ( ! ${*$self}->{RESULT} ) {
$self->readprocess() || return undef;
}
if ( ${*$self}->{RESULT} == "OK" ) {
return $self;
} else {
return undef; # sorry.
}
}
sub send {
my $self = shift;
my $destination = shift;
my $message = shift;
my $size = length($message);
$self->SUPER::send("DATAGRAM SEND DESTINATION=$destination SIZE=$size\n$message");
}
sub receive {
my $self = shift;
# Shift one off the fifo array. Returns undef if none wait.
return shift @{ $self->{incomingdatagram} };
}
1;

View File

@@ -0,0 +1,45 @@
#!/usr/bin/perl
package Net::SAM::RawSession;
use Net::SAM;
@ISA = ("Net::SAM");
sub new {
my ($class) = shift;
my ($dest , $direction, $options) = shift;
my $self = $class->SUPER::new(@_);
$self->send("SESSION CREATE STYLE=RAW DESTINATION=$dest DIRECTION=$direction $options\n");
undef $self->{result};
while ( ! $self->{RESULT} ) {
$self->readprocess();
}
if ( $self->{RESULT} == "OK" ) {
return $self;
} else {
return 0; # sorry.
}
}
sub send {
my $self = shift;
my $destination = shift;
my $message = shift;
my $samsock = $self->{samsock};
my $size = length($message);
print $samsock "RAW SEND DESTINATION=$destination SIZE=$size\n$message";
}
sub receive {
my $self = shift;
# Shift one off the fifo array. Returns undef if none wait.
return shift @{ $self->{incomingraw} };
}
1;

View File

@@ -0,0 +1,3 @@
#!/usr/bin/perl
1;

18
apps/sam/perl/samcat.pl Normal file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/perl
use Net::SAM::RawSession;
use Net::SAM::DatagramSession;
$sam=Net::SAM::DatagramSession->new($ARGV[0], "BOTH", "tunnels.depthInbound=0");
print "Connected? " . $sam->connected() . "\n";
$me = $sam->lookup("ME");
print "Sending to $me.\n";
$sam->send($me,"fooquux");
$sam->readprocess();
($source, $message) = @{ $sam->receive() };
print "$source -- $message";

View File

@@ -5,7 +5,6 @@ import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.DecimalFormat;
/**

View File

@@ -1,15 +1,14 @@
package net.i2p.time;
import net.i2p.util.Log;
import net.i2p.util.I2PThread;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.IOException;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Periodically query a series of NTP servers and post the offset
@@ -51,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.5 $ $Date: 2004/05/07 12:52:49 $";
public final static String VERSION = "0.3.1.2";
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

@@ -1,26 +1,27 @@
package net.i2p;
import net.i2p.stat.StatManager;
import net.i2p.crypto.SessionKeyManager;
import net.i2p.crypto.PersistentSessionKeyManager;
import net.i2p.crypto.ElGamalAESEngine;
import net.i2p.crypto.ElGamalEngine;
import net.i2p.crypto.DummyElGamalEngine;
import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.HMACSHA256Generator;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import net.i2p.client.naming.NamingService;
import net.i2p.crypto.AESEngine;
import net.i2p.crypto.CryptixAESEngine;
import net.i2p.crypto.DSAEngine;
import net.i2p.client.naming.NamingService;
import net.i2p.util.LogManager;
import net.i2p.util.Clock;
import net.i2p.util.RandomSource;
import net.i2p.data.RoutingKeyGenerator;
import net.i2p.crypto.DummyDSAEngine;
import net.i2p.crypto.DummyElGamalEngine;
import net.i2p.crypto.ElGamalAESEngine;
import net.i2p.crypto.ElGamalEngine;
import net.i2p.crypto.HMACSHA256Generator;
import net.i2p.crypto.KeyGenerator;
import java.util.Properties;
import java.util.HashSet;
import java.util.Set;
import net.i2p.crypto.PersistentSessionKeyManager;
import net.i2p.crypto.SHA256Generator;
import net.i2p.crypto.SessionKeyManager;
import net.i2p.data.RoutingKeyGenerator;
import net.i2p.stat.StatManager;
import net.i2p.util.Clock;
import net.i2p.util.LogManager;
import net.i2p.util.RandomSource;
/**
* <p>Provide a base scope for accessing singletons that I2P exposes. Rather than
@@ -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

@@ -24,14 +24,13 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Clock;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.util.LogManager;
import net.i2p.I2PAppContext;
/**
* ATalk - anonymous talk, demonstrating a trivial I2P usage scenario.

View File

@@ -9,9 +9,9 @@ package net.i2p.client;
*
*/
import net.i2p.I2PAppContext;
import net.i2p.data.i2cp.DisconnectMessage;
import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.I2PAppContext;
/**
* Handle I2CP disconnect messages from the router

View File

@@ -9,8 +9,8 @@ package net.i2p.client;
*
*/
import net.i2p.util.Log;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
/**
* Base class for handling I2CP messages

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