Compare commits

...

115 Commits

Author SHA1 Message Date
806d598a04 _context/getContext()
(missed one)
2004-07-15 05:23:18 +00:00
e737e5c950 * work around the disagreement between different versions of sun's compiler and JVM:
Some of them think that its ok for an inner class of a subclass to access protected data of the
outer class's parent when the parent is in another package.
Others do not.
Kaffe doesn't care (but thats because Kaffe doesn't do much for verification ;)
The JLS is aparently confusing, but it doesnt matter whether its a code or javac bug, we've got to change the code.
The simplest change would be to just make the JobImpl._context public, but I loath public data, so we make it private and add an accessor
(and change dozens of files)
whee
2004-07-15 05:12:37 +00:00
bbcde2f52b 0.3.2.2 (a lil installation testing and then i'll push) 2004-07-15 01:08:54 +00:00
f6ef77429c some boundary cases for the queue pumper's wait time 2004-07-15 01:04:13 +00:00
44491c1514 added nickster2.i2p and irc.nickster.i2p (pointing at iip) 2004-07-14 22:12:43 +00:00
71a6cf4ee6 * adjust the algorithm to deal with IO bound requests:
if more tokens become available while the first pending request is still blocked on
  read/write (aka after allocation and before next .waitForAllocation()), give the tokens
  to the next request
* refactor the satisfy{In,Out}boundRequests methods into smaller logical units
2004-07-14 21:07:57 +00:00
744ce6966f add a new throttle (and stats) based on send processing time
high send processing time and low job lag means the latency is coming from outside the jobQueue - aka bandwidth throttling
2004-07-14 20:01:40 +00:00
d25cec02c2 clean up sorting for peer reliability
increase penalties for tunnel rejection, and keep track of the 10 minute rate as well as 1 and 60
2004-07-14 19:56:38 +00:00
f02bf37fd3 stats and stats and stats
track the total allocated bytes correctly (even if we're throttled)
2004-07-14 19:54:04 +00:00
304b9d41d7 on kaffe i've periodically seen some hangs in the jobqueue, so lets try being a bit more conservative with the synchroniation, and include some debugging output in the router console to help track it down (if this doesnt fix it) 2004-07-13 20:19:28 +00:00
2d6af89f60 safer operation (for use in the sim where some things aren't always availble) 2004-07-13 20:17:15 +00:00
d6425973e2 include an objectId flag for use in the logging 2004-07-13 20:16:05 +00:00
d5ad56c4de use smaller writes to make it look more normal 2004-07-13 20:14:18 +00:00
4f1f2cc99e since people are using small buckets, the 10s replenish frequency is a really really bad idea (so default to 1s) 2004-07-13 05:49:16 +00:00
da439dd127 sanity checking for a kooky race condition 2004-07-12 21:33:32 +00:00
1375d01bdf new bandwidth allocation policy and usage to include support for partial allocations (and in turn, partial write(...)) while still keeping the FIFO ordering
this will give a much smoother traffic pattern, as instead of waiting 6 seconds to write a 32KB message under a 6KB rate, it'll write 6KB for each of the first 5 seconds, and 2KB the next
this also allows people to have small buckets (but again, bucket sizes smaller than the rate just don't make sense)
2004-07-12 21:09:05 +00:00
7b9db07f13 target=1.3 and source=1.3, not target=1.1 and source=1.3
(this is what caused the runtime errors on sun jvms but not on kaffe)
((aka i slacked and didn't test sufficiently.  off with my head))
this now builds and runs fine in sun 1.3-1.5 jvms, as well as kaffe
2004-07-12 16:39:22 +00:00
f2f26136c1 Minior cleanups -- removed commented out debugging code, wrote better
comments.
(ugha)
2004-07-12 05:12:22 +00:00
0f60ac5acf 0.3.2.1 (backwards compatible blah blah blah) 2004-07-11 18:57:01 +00:00
c28f19fe8a less painful and/or redundant penalties for failures 2004-07-11 18:50:23 +00:00
mpc
09a6dbc755 FreeBSD port 2004-07-11 13:22:37 +00:00
3bc0e0fc8a added source and target declarations for the javac commands so we can build with the 1.5^W5.0 JDK
(also added deprecation, since, well, we can :)
2004-07-11 04:16:59 +00:00
eb0e187a54 throttle tunnel participation based on whether we've had to throttle our network connection > some number of times in the last 10-20 minutes (rather than a simple "are we throttled *right now*?") 2004-07-10 22:28:34 +00:00
a788d30f34 added support for new 'clientoptions' command which alters the properties passed when creating subsequent I2CP connections
e.g.: -e "clientoptions tunnels.depthInbound=0" -e "httpclient 6666"
this updates so many files because they all need a reference to an I2PTunnel object on construction so they query tunnel.getClientOptions() instead of System.getProperties
2004-07-10 16:59:49 +00:00
591dfc961e give the reliability more positive influence so it doesn't go negative so easily
update the peerProfile's CLI to make the resulting stats easier to read
2004-07-10 04:15:51 +00:00
809e12b034 logging 2004-07-10 04:13:42 +00:00
1669d174e1 use mihi's template engine to set a random timestamper password so people dont need to think about that stuff
don't use the dyndns anymore for seeding (use dev.i2p.net/i2pdb)
2004-07-10 02:36:27 +00:00
3cfd28de43 add a new unit test for repeated fast reconnections 2004-07-10 01:58:05 +00:00
4888207eca if a client reconnects, we always want to get a new leaseSet ASAP (even if the pool hadn't been marked as stopped yet)
logging
2004-07-10 01:46:57 +00:00
294cb96107 if the job's startAfter is changed, tell the jobQueue to go through the timed jobs again in case the new time changes the scheduling 2004-07-10 01:44:27 +00:00
b648fa2b70 send the stats page out in chunks (more mem efficient, blah blah blah) 2004-07-10 01:39:54 +00:00
ab99122211 render status HTML in pieces (continued) 2004-07-09 05:33:19 +00:00
dd014fee88 send the router console out bit by bit rather than building it all up and sending it (thereby reducing its memory footprint dramatically) 2004-07-09 05:29:02 +00:00
c81f864de3 reduce the throttle threshold from 5s lag to 2s lag 2004-07-09 05:22:29 +00:00
90fe7dceec include the expiration in the error message if its dropped 2004-07-09 05:20:26 +00:00
3a568096f2 new throttling code which rejects tunnel create requests, networkDb lookup requests, and even tells the I2NP components to stop reading from the network (it doesnt affect writing to the network)
the simple RouterThrottleImpl bases its decision entirely on how congested the jobQueue is - if there are jobs that have been waiting 5+ seconds, reject everything and stop reading from the network
(each i2npMessageReader randomly waits .5-1s when throttled before rechecking it)
minor adjustments in the stats published - removing a few useless ones and adding the router.throttleNetworkCause (which is the average ms lag in the jobQueue when an I2NP reader is throttled)
2004-07-09 03:56:22 +00:00
94e694fc61 reduce the job pipeline to send a message by fetching the bids and adding the message to the connection queue synchronously
these had been broken out into seperate jobs before to reduce thread and lock contention, but that isn't as serious an issue anymore (in these cases) and the non-contention-related delays of these mini-jobs are trivial
2004-07-09 03:48:12 +00:00
bdfa6e4af5 dont penalize send failures (beyond what we already do for comm errors)
keep a rate for tunnel rejection, rather than a simple 'last' occurrance, and penalize the reliability with it
2004-07-09 03:45:11 +00:00
8e64ffb4f6 keep the relay message size rate data for the 10 minute period (so we can throttle on logical periods) 2004-07-09 03:43:07 +00:00
6c162643cb expose stat for throttling (# tunnels we're currently participating in) 2004-07-09 03:41:27 +00:00
ff7742bca3 expose some stats useful for throttling (# ready & waiting jobs and the max lag of those jobs) 2004-07-09 03:39:38 +00:00
9685884279 deal with null peer (used by the SubmitMessageHistoryJob to bw limit the history)
current 0.3.2 throws an NPE which causes the submitMessageHistory functionality to fail, which isn't really a loss since i send that data to /dev/null at the moment ;)
(but you'll want to router.keepHistory=false and router.submitHistory=false)
this'll go into the next rev, whenever it comes out
(thanks ugha!)
2004-07-07 22:23:25 +00:00
a8b0d7f999 pull out no longer relevent config parameters
start the irc proxy by default within the router
dont package up the startIrcProxy script
2004-07-07 18:06:46 +00:00
dd84233085 0.3.2 for release later today 2004-07-07 17:58:37 +00:00
fe3eac07f4 migrate the queue pumper thread to scheduled activity (instead of waking up every 500ms, check the job timings to see when we should next wake up. we also wake up whenever a new timed job is added, or the clock skew changes)
pull out some of the old unused vars/flags
2004-07-07 16:16:36 +00:00
0948686989 don't mark failing due to sendFailed (since that can be caused by a message that was about to expire anyway) 2004-07-07 16:11:46 +00:00
4c82970319 get rid of the whole slice concept
dont time out for too many messages (just time out individual ones)
however, if any of the messages that time out have been there for a minute, kill the con (since its hung)
kaffe workaround for fast closing sockets
2004-07-07 16:10:57 +00:00
fe2fede8ed removed maxWaitingJobs param 2004-07-06 18:26:04 +00:00
b23b1e5f1f instead of the maxQueuedMessages limit, use the rule 'if any of the messages time out on the queue, its going too slowly'
(this helps in situations where we've got a flash flood of small messages to send)
2004-07-06 18:24:59 +00:00
dca66c8de8 leave all threads at base priority (except the client runner, where we push at max)
don't consider a connection valid until it has been up for 30 seconds (so people who are simply establishing connections but whose nats are still messed up get the error)
when dealing with expired after accepted, dont drop unless it expired outside the fudge factor
increase the default maxWaitingJobs to 100, since we can get lots at once (and we dont gobble as much memory as we used to)
also, don't wake up the jobQueueRunner in getNext once a second, instead just let the threads updating the queue notify
2004-07-06 14:38:35 +00:00
49090014cc placeholder for overload detection 2004-07-06 14:30:52 +00:00
fa4f100705 new limiter, pull slow and not too useful tests (uncomment 'em to run 'em) 2004-07-04 04:35:16 +00:00
bbf68cd9a8 implemented the FIFO bandwidth limiter which, suprisingly, chokes read/write operations
if they would exceed the currently available # of tokens, letting through those operations
in the order they are called.  like the old trivial bandwidth limiter, this uses a token
bucket approach (keeping a pool of 'available' bytes, decrementing on their use and
periodically refilling it [up to a max limit, to prevent absurd bursts]).  on the other
hand, it doesn't have the starvation issues the old one had, which would continue to let
small operations go through (e.g. 8 byte write) and potentially block large operations
indefinitely (e.g. 32KB write).  However, this new version is, how shall I put it, context
switch heavy?  :)  We'll revise with a scheduling / queueing algorithm once we're away
from transports that require threads per connection
The two directions (input and output) are managed on their own queues, and if/when things
are backed up, you can see the details of what operations have been requested on the
router console.
Since we still need better router throttling code (to reject tunnels and back off more
accurately), I've included a minimum KBps on the limiter, currently set to 6KBps both
ways.  Once there is good throttling code, we can drop that to 1-2KBps, and maybe even
less after we do some bandwidth usage tuning.
There were also a few minor touch ups to handle message data being discarded earlier
than it had been before (since write/read operations can now take a long period of time
in the face of contention)
The five config properties for the bandwidth limiter are:
* i2np.bandwidth.inboundKBytesPerSecond
* i2np.bandwidth.outboundKBytesPerSecond
  (you can guess what those are)
* i2np.bandwidth.inboundBurstKBytes
* i2np.bandwidth.outboundBurstKBytes
  the burst KBytes specify how many bytes we'll let accumulate in the bucket, allowing
  us to burst after a period of inactivity.  excess tokens greater than this limit are
  discarded.
* i2np.bandwidth.replenishFrequencyMs
  this is an internal setting, used to specify how frequently to refil the buckets (min
  value of 1s, which is the default)
You may want to hold off on using these parameters though until the next release,
leaving it to the default of unlimited.  They are read periodically from the config file
however, so you can update them without restart / etc.  (if you want to have no limit on
the bandwidth, set the KBytesPerSecond to  a value <= 0)
2004-07-04 04:33:17 +00:00
mpc
bbc5f6588a *** empty log message *** 2004-07-04 01:53:35 +00:00
mpc
b3632a6a35 duh 2004-07-04 01:00:04 +00:00
mpc
3943c51bb4 Hmm 2004-07-04 00:57:14 +00:00
mpc
4c19ddde69 a couple locking changes 2004-07-03 22:03:49 +00:00
mpc
d8f0f1a1d3 Added test for Logger and debugged it 2004-07-03 21:53:10 +00:00
mpc
121c0d89f2 Fixed test 2004-07-03 20:58:42 +00:00
badfb9088e logging / debugging and formatting (no functional changes) 2004-07-03 19:42:34 +00:00
ff392fee14 properly fake-encrypt the data (this class is only used by the simulator or anything else w/ -Di2p.encryption=off) 2004-07-03 19:41:41 +00:00
mpc
a13693161a http://www.kirstenfan.com/galleries/magazines/fhm2002100sexy/002.jpg -- studies show charming women love computer programmers...... 2004-07-03 11:05:23 +00:00
4b8ac81669 minor refactoring, javadoc
dont add an arbitrary extra Router.CLOCK_FUDGE_FACTOR to the expiration
2004-07-02 18:57:42 +00:00
219a704ee0 bugger it, for consistency, always include the reply leaseSet with a message (later, when we want to optimize the bandwidth requirements, we can revisit) 2004-07-02 16:59:37 +00:00
3996cd1f08 make the client writer thread run at max priority, since it is very time sensitive and only executes for very brief periods 2004-07-02 16:53:49 +00:00
c636b0a0ec minor rewrite to make timing more precise (keeping a map of message add times, not just the 'last' add time) 2004-07-02 15:12:35 +00:00
aae9f671f0 added jdot.i2p (duck) 2004-07-02 13:31:09 +00:00
aec6e901ee And I thought I was dyslectic. (duck) 2004-07-02 13:18:00 +00:00
mpc
f49be25288 <Nightblade> hmm 2004-07-02 09:54:27 +00:00
mpc
f9a96126e1 I don't know how I missed this stuff before 2004-07-02 09:37:54 +00:00
8c9f58b939 Misc. stuff: javadoc, UNUSED...
shendaras
2004-07-02 02:54:04 +00:00
8a7e787f42 logging 2004-07-01 22:33:51 +00:00
148dcc084d factor out the clientWriterRunner and have it deal with multiple i2cp messages being enqueued really fast (at least, more efficiently, by pulling them all off at once and handling them in one pass) 2004-07-01 15:21:32 +00:00
15b1cbd762 synchronize the available() call, and made explicit some other synchronization 2004-07-01 15:11:34 +00:00
e9b7ca3697 dont accept outrageously long delays when building a tunnel (aka now each peer only gets the timeout to respond, instead of the full # peers * timeout to respond)
this will cause more dropped messages to show up, but in turn it will avoid slower peers (since they'll be marked down as rejecting the tunnel)
2004-07-01 15:08:18 +00:00
mpc
1b03e9a3ee Who was the idiot who came up with the idea that booleans should be numbers? 2004-07-01 09:30:52 +00:00
mpc
2b951e3f61 Change throws to asserts. If any of this stuff happens it means a code logic error or a retarded computer, so throwing it is just a waste of time. 2004-07-01 09:17:17 +00:00
mpc
f51e064cf6 *** empty log message *** 2004-07-01 02:23:59 +00:00
9640e93895 imports
shendaras
2004-06-30 13:21:15 +00:00
d5bd22040c Crappy fix for incorrect Total Bytes Sent/Total Bytes Received via BandwidthLimiter.... ah.. just read the FIXME there.
shendaras
2004-06-30 13:16:05 +00:00
dcdcb7521a dont kill the context, we may need it when tearing down the runner (e.g. to get the time) 2004-06-30 04:11:59 +00:00
4058c63884 dont be such a prude 2004-06-30 03:02:39 +00:00
dd34548cc6 publish the tunnel congestion stat 2004-06-29 22:32:31 +00:00
a6b5211fa7 congestion is only a warning, not an error 2004-06-29 22:30:14 +00:00
4e89b9c363 reliability threshold = median of active and nonfailing (inactive nonfailing can be a large number of 0 reliability peers) 2004-06-29 20:32:36 +00:00
f3e267d2d0 active peer testing - every minute, grab two reliable peers, throw a db store at them, and measure their response time
the db store sent is their own, and we use tunnels both ways, so they wont know who we are.  we also mark the
success/failure of the tunnels accordingly
2004-06-29 19:45:26 +00:00
2fd87dc1f1 when we select peers to test, lets use all of the reliable peers, not just well integrated peers 2004-06-29 19:41:30 +00:00
40b6b77cfa use the median reliability value of nonfailing peers for the reliabilty threshold, and simplify determining them for the speed and integration 2004-06-29 19:40:08 +00:00
d0c61dbf4d use the explicit max ID values (I2NPMessage.MAX_ID_VALUE and TunnelId.MAX_ID_VALUE)
logging
2004-06-29 19:32:46 +00:00
1cd5a3fcf7 include the "addedBy" if we're debugging the job, not if we're debugging JobImpl 2004-06-29 19:29:57 +00:00
af81cf2c50 explcitly define the max I2NP message ID value and validate against it 2004-06-29 19:28:40 +00:00
04373c5d1b just to be explicit about the max tunnel id 2004-06-29 19:25:23 +00:00
mpc
e9cdb0f78d new library 2004-06-29 02:55:53 +00:00
mpc
021b933ad3 new library 2004-06-28 23:55:07 +00:00
mpc
9fd067c9da Putting socks/threads/logger/misc in a separate library 2004-06-28 23:24:50 +00:00
d3f3f3bdf7 use the socketManager's new setName function (to let us log more easily) 2004-06-28 13:23:24 +00:00
72727dacd8 javadoc 2004-06-28 13:22:03 +00:00
caeb2bc4e3 the actual fix for the local eepsite problem (if getRemoteID was called *after* the remoteID was set, it would wait for 60s then fail. now we check for that)
synchronization cleanup (never get two locks)
logging
2004-06-28 13:21:18 +00:00
13974b601f added some stats (viewable on the router stat page when the i2ptunnel is run in the router's VM)
lots of logging
2004-06-28 13:18:18 +00:00
cbc6aea8b4 logging 2004-06-27 21:20:31 +00:00
290a2f7ccd (ok this is a little silly) 2004-06-27 21:08:19 +00:00
349e80f206 allow sending ASAP and remove any artificial delays 2004-06-27 20:53:32 +00:00
5c1e001a73 logging 2004-06-27 19:39:45 +00:00
mpc
f312318fab Finished winsock code cleanup 2004-06-27 13:07:06 +00:00
mpc
dc04b7cf09 Some winsock improvements 2004-06-27 09:12:05 +00:00
77a8a46d8e lets try to reduce creating new objects during finalization 2004-06-26 21:15:51 +00:00
95c7cd55c2 logging 2004-06-26 21:15:16 +00:00
5f0ef5e0e8 lets not crap on the secondary tunnel too (even though doing so isn't wrong)
this helps avoid catastrophic failures, at least a little, since a failure doesnt kill two sets of tunnels
2004-06-26 21:13:52 +00:00
1f26c603e0 for now, lets disable the tunnel pool persistance. this means that after a router crashes, tunnels it was participating in will fail even if the router comes back up before they expire.
disabling this saves us some IO contention (though this may only be relevent on my kaffe box... dunno)
2004-06-26 21:11:22 +00:00
7e2227ad42 lets keep track of how many messages die on our queue due to us being slow 2004-06-26 21:07:07 +00:00
9b4899da07 always use the cached host/port rather than grabbing the socket's InetAddress (in case it disconnects and throws NPEs)
use the NativeBigInteger as part of the session key negotiation (oops, forgot this one last time)
logging
2004-06-26 21:05:02 +00:00
mpc
83c88ac0c6 minor fixes 2004-06-26 02:26:37 +00:00
mpc
44623065b4 Threads (untested) 2004-06-26 02:16:54 +00:00
mpc
47c7c8177d Mutex code (untested) 2004-06-25 22:22:48 +00:00
mpc
bde7a5ff59 Mutex code (untested) 2004-06-25 22:19:18 +00:00
214 changed files with 6154 additions and 2565 deletions

View File

@ -0,0 +1,87 @@
#
# This Makefile is compatible with GNU Make and should work on Cygwin
#
#
# Your operating environment
#
OS = CYGWIN
#
# 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
CFLAGS += -DOS=$(OS)
#
# Libraries
#
CFLAGS += -I$(SAMINCDIR) -I$(TOMCRYPTDIR)
LDFLAGS = -L$(SAMLIBDIR) -L$(TOMCRYPTDIR)
LIBS = -lsam -ltomcrypt -lpthread
#
# Object files
#
OBJS = $(OBJDIR)/bigint.o \
$(OBJDIR)/chk.o \
$(OBJDIR)/config.o \
$(OBJDIR)/logger.o \
$(OBJDIR)/main.o \
$(OBJDIR)/mutex.o \
$(OBJDIR)/peers.o \
$(OBJDIR)/random.o \
$(OBJDIR)/rpc.o \
$(OBJDIR)/sam.o \
$(OBJDIR)/sha1.o \
$(OBJDIR)/thread.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

@ -1,8 +1,13 @@
#
# This Makefile is compatible with GNU Make and should work on Linux
# (Tested on Debian 3.0)
# This Makefile is compatible with GNU Make and should work on Linux (generic)
#
#
# Your operating environment
#
OS = LINUX
#
# Directories
#
@ -27,6 +32,7 @@ CC = g++
#
CFLAGS = -g -march=i486 -pipe -Wall
CFLAGS += -DOS=$(OS)
#
# Libraries
@ -34,7 +40,7 @@ CFLAGS = -g -march=i486 -pipe -Wall
CFLAGS += -I$(SAMINCDIR) -I$(TOMCRYPTDIR)
LDFLAGS = -L$(SAMLIBDIR) -L$(TOMCRYPTDIR)
LIBS = -lsam -ltomcrypt
LIBS = -lsam -ltomcrypt -lpthread
#
# Object files
@ -45,11 +51,13 @@ OBJS = $(OBJDIR)/bigint.o \
$(OBJDIR)/config.o \
$(OBJDIR)/logger.o \
$(OBJDIR)/main.o \
$(OBJDIR)/mutex.o \
$(OBJDIR)/peers.o \
$(OBJDIR)/random.o \
$(OBJDIR)/rpc.o \
$(OBJDIR)/sam.o \
$(OBJDIR)/sha1.o
$(OBJDIR)/sha1.o \
$(OBJDIR)/thread.o
#
# Build rules

View File

@ -0,0 +1,87 @@
#
# This Makefile is compatible with GNU Make and should work on Windows (Mingw)
#
#
# Your operating environment
#
OS = MINGW
#
# Directories
#
BINDIR = bin
LOGDIR = log
OBJDIR = obj
SRCDIR = src
SAMINCDIR = C:\cygwin\home\Administrator\cvs\i2p\apps\sam\c\inc
SAMLIBDIR = C:\cygwin\home\Administrator\cvs\i2p\apps\sam\c\lib
TOMCRYPTDIR = C:\cygwin\home\Administrator\libtomcrypt-0.96
#
# Programs
#
CC = C:\Dev-Cpp\bin\g++
#
# Flags
#
CFLAGS = -g -march=i486 -pipe -Wall
CFLAGS += -DOS=$(OS)
#
# 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)/mutex.o \
$(OBJDIR)/peers.o \
$(OBJDIR)/random.o \
$(OBJDIR)/rpc.o \
$(OBJDIR)/sam.o \
$(OBJDIR)/sha1.o \
$(OBJDIR)/thread.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,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,163 @@
/*
* 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 <cstdarg>
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
#include "mutex.hpp"
#include "time.hpp"
#include "logger.hpp"
using namespace Libsockthread;
/*
* Closes the log file
*/
void Logger::close(void)
{
logf_m.lock();
if (logf == 0) {
logf_m.unlock();
return;
}
if (fclose(logf) == EOF) {
cerr_m.lock();
cerr << "fclose() failed: " << strerror(errno) << '\n';
cerr_m.unlock();
}
logf = 0;
logf_m.unlock();
}
/*
* Sends a line to the log file. Uses variable arguments just like printf().
*/
void Logger::log(priority_t priority, const char* format, ...)
{
if (priority < get_loglevel())
return;
char ll;
switch (priority) {
case Logger::DEBUG:
ll = 'D';
break;
case Logger::MINOR:
ll = 'M';
break;
case Logger::INFO:
ll = 'I';
break;
case Logger::WARN:
ll = 'W';
break;
case Logger::ERROR:
ll = 'E';
break;
default:
ll = '?';
}
va_list ap;
va_start(ap, format);
string s;
Time t;
logf_m.lock();
if (logf != 0) {
/*
* Remember! If you change the format here, change it in the else too
*/
fprintf(logf, "%c %s ", ll, t.utc(s).c_str());
vfprintf(logf, format, ap);
fputc('\n', logf);
if (fflush(logf) == EOF) {
cerr_m.lock();
cerr << "fflush() failed: " << strerror(errno) << '\n';
cerr_m.unlock();
}
} else {
// if they don't have an open log file, just use stderr
fprintf(stderr, "%c %s ", ll, t.utc(s).c_str());
vfprintf(stderr, format, ap);
fputc('\n', stderr);
}
va_end(ap);
logf_m.unlock();
return;
}
/*
* Opens a log file for appending. If there already is an open log file, then
* it is closed and the new one is opened.
*
* file - file location to open
*/
bool Logger::open(const string& file)
{
close();
logf_m.lock();
logf = fopen(file.c_str(), "a");
if (logf != NULL) {
logf_m.unlock();
return true;
} else {
logf_m.unlock();
cerr_m.lock();
cerr << "fopen() failed (" << file << "): " << strerror(errno) << '\n';
cerr_m.unlock();
return false;
}
}
#ifdef UNIT_TEST
// g++ -Wall -c thread.cpp -o thread.o
// g++ -Wall -c mutex.cpp -o mutex.o
// g++ -Wall -c time.cpp -o time.o
// g++ -Wall -DUNIT_TEST -c logger.cpp -o logger.o
// g++ -Wall -DUNIT_TEST logger.o mutex.o thread.o time.o -o logger -lpthread
int main(void)
{
Logger logger;
logger.open("delete.me");
logger.set_loglevel(Logger::MINOR);
logger.close();
LWARNS("This should appear on stderr");
logger.open("delete.me.also");
LINFO("%s\n", "hey it works");
LDEBUGS("This shouldn't be saved in the file.");
return 0;
}
#endif // UNIT_TEST

View File

@ -0,0 +1,96 @@
/*
* 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 LIBSOCKTHREAD_LOGGER_HPP
#define LIBSOCKTHREAD_LOGGER_HPP
/*
* Some helpful macros:
*
* LDEBUG - debugging messages
* LMINOR - unimportant messages
* LINFO - informational messages
* LWARN - errors we automatically recover from
* LERROR - major, important errors
*
* Obviously, these only work if your Logger object is called "logger" and is
* global
*/
// Prints out the file name, function name, and line number before the message
#define LDEBUG(format, ...) logger.log(Logger::DEBUG, "%s:%s:%d:" \
format, __FILE__, __func__, __LINE__, __VA_ARGS__)
// This is the same as above, except it doesn't accept varargs
#define LDEBUGS(str) logger.log(Logger::DEBUG, "%s:%s:%d:" \
str, __FILE__, __func__, __LINE__);
#define LMINOR(format, ...) logger.log(Logger::MINOR, "%s:%s:%d:" \
format, __FILE__, __func__, __LINE__, __VA_ARGS__)
#define LMINORS(str) logger.log(Logger::MINOR, "%s:%s:%d:" \
str, __FILE__, __func__, __LINE__);
#define LINFO(format, ...) logger.log(Logger::INFO, "%s:%s:%d:" \
format, __FILE__, __func__, __LINE__, __VA_ARGS__)
#define LINFOS(str) logger.log(Logger::INFO, "%s:%s:%d:" \
str, __FILE__, __func__, __LINE__);
#define LWARN(format, ...) logger.log(Logger::WARN, "%s:%s:%d:" \
format, __FILE__, __func__, __LINE__, __VA_ARGS__)
#define LWARNS(str) logger.log(Logger::WARN, "%s:%s:%d:" \
str, __FILE__, __func__, __LINE__);
#define LERROR(format, ...) logger.log(Logger::ERROR, "%s:%s:%d:" \
format, __FILE__, __func__, __LINE__, __VA_ARGS__)
#define LERRORS(str) logger.log(Logger::ERROR, "%s:%s:%d:" \
str, __FILE__, __func__, __LINE__);
namespace Libsockthread {
class Logger {
public:
typedef enum {DEBUG = 0, MINOR = 1, INFO = 2, WARN = 3, ERROR = 4}
priority_t;
Logger(void)
: logf(0), loglevel(Logger::DEBUG) { }
~Logger(void) { close(); }
void close(void);
void log(priority_t priority, const char* format, ...);
priority_t get_loglevel(void)
{ loglevel_m.lock(); priority_t ll = loglevel;
loglevel_m.unlock(); return ll; }
bool open(const string& file);
void set_loglevel(priority_t priority)
{ loglevel_m.lock(); loglevel = priority; loglevel_m.unlock(); }
private:
Mutex cerr_m;
FILE* logf;
Mutex logf_m;
priority_t loglevel;
Mutex loglevel_m;
};
}
#endif // LIBSOCKTHREAD_LOGGER_HPP

View File

@ -0,0 +1,136 @@
/*
* 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.
*/
// Modelled after JThread by Jori Liesenborgs
#include <cassert>
#include "platform.hpp"
#ifdef WINTHREAD
#include <windows.h>
#else
#include <pthread.h>
#endif
using namespace std;
#include "mutex.hpp"
using namespace Libsockthread;
/*
* Creates a mutex
*/
Mutex::Mutex(void)
{
#ifdef WINTHREAD
mutex = CreateMutex(0, false, 0);
assert(mutex != 0);
#else
int rc = pthread_mutex_init(&mutex, 0);
assert(rc == 0);
#endif
}
/*
* Destroys a mutex
*/
Mutex::~Mutex(void)
{
#ifdef WINTHREAD
BOOL rc = CloseHandle(mutex);
assert(rc);
#else
int rc = pthread_mutex_destroy(&mutex);
assert(rc == 0);
#endif
}
/*
* Locks the mutex
*/
void Mutex::lock(void)
{
#ifdef WINTHREAD
DWORD rc = WaitForSingleObject(mutex, INFINITE);
assert(rc != WAIT_FAILED);
#else
int rc = pthread_mutex_lock(&mutex);
assert(rc == 0);
#endif
}
/*
* Unlocks the mutex
*/
void Mutex::unlock(void)
{
#ifdef WINTHREAD
BOOL rc = ReleaseMutex(mutex);
assert(rc);
#else
int rc = pthread_mutex_unlock(&mutex);
assert(rc == 0);
#endif
}
#ifdef UNIT_TEST
// g++ -Wall -c thread.cpp -o thread.o
// g++ -Wall -DUNIT_TEST -c mutex.cpp -o mutex.o
// g++ -Wall -DUNIT_TEST mutex.o thread.o -o mutex -lpthread
#include <iostream>
#include "thread.hpp"
Mutex widget;
int main(void)
{
class Mutex_test : public Thread
{
public:
Mutex_test(int n)
: testval(n) {}
void* thread(void)
{
widget.lock();
cout << "I got it! thread #" << testval << '\n';
// If this works, only one thread should be able to lock the
// widget, since it is never unlocked
return 0;
}
private:
int testval;
};
Mutex_test t1(1);
Mutex_test t2(2);
Mutex_test t3(3);
t1.start(); t2.start(); t3.start();
while (true);
return 0;
}
#endif // UNIT_TEST

View File

@ -0,0 +1,53 @@
/*
* 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.
*/
// Modelled after JThread by Jori Liesenborgs
#ifndef LIBSOCKTHREAD_MUTEX_HPP
#define LIBSOCKTHREAD_MUTEX_HPP
namespace Libsockthread {
class Mutex {
public:
Mutex(void);
~Mutex(void);
void lock(void);
void unlock(void);
private:
#ifdef WINTHREAD
HANDLE mutex;
#else
pthread_mutex_t mutex;
#endif
};
}
#endif // LIBSOCKTHREAD_MUTEX_HPP

View File

@ -0,0 +1,63 @@
/*
* 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 LIBSOCKTHREAD_PLATFORM_HPP
#define LIBSOCKTHREAD_PLATFORM_HPP
/*
* 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 WINSOCK
#define WINTHREAD
#endif
#if OS == LINUX
#define NO_GETHOSTBYNAME2
#endif
#if OS == CYGWIN
#define FAST32_IS_LONG
#define INET_ADDRSTRLEN 16
#define NO_GETHOSTBYNAME2
#define NO_INET_NTOP
#define NO_INET_PTON
#endif
#endif // LIBSOCKTHREAD_PLATFORM_HPP

View File

@ -0,0 +1,277 @@
/*
* 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 <cassert>
using namespace std;
#include "platform.hpp"
#include "socket.hpp"
using namespace Libsockthread;
size_t Socket::total = 0; // the total number of sockets in use
/*
* Constructs an IPv4 TCP socket
*/
Socket::Socket(void)
{
++total;
try {
#ifdef WINSOCK
if (total == 1)
winsock_startup();
#endif
create_socket(PF_INET, SOCK_STREAM);
} catch (const Socket_error& x) {
--total;
throw;
}
}
/*
* Constructs the socket
*
* domain - either PF_INET or PF_INET6
* type - either SOCK_STREAM or SOCK_DGRAM
*/
Socket::Socket(int domain, int type)
{
++total;
try {
#ifdef WINSOCK
if (total == 1)
winsock_startup();
#endif
create_socket(domain, type);
} catch {const Socket_error& x) {
--total;
throw;
}
}
/*
* Destroys the socket
*/
Socket::~Socket(void)
{
close();
--total;
assert(total >= 0);
#ifdef WINSOCK
if (total == 0)
winsock_cleanup();
#endif
}
/*
* Closes the socket
*/
void Socket::close(void)
{
#ifdef WINSOCK
if (closesocket(sock) == SOCKET_ERROR) {
LERROR("closesocket() failed: %s", winsock_strerror(WSAGetLastError()));
}
#else
if (close(sock) == -1) {
LERROR("close() failed: %s", strerror(errno));
}
#endif
}
/*
* Creates the socket
*
* domain - either PF_INET or PF_INET6
* type - either SOCK_STREAM or SOCK_DGRAM
*/
void Socket::create_socket(int domain, int type)
{
assert((domain == PF_INET || domain == PF_INET6) &&
(type == SOCK_STREAM || type == SOCK_DGRAM));
sock = socket(domain, type, 0);
#ifdef WINSOCK
if (sock == INVALID_SOCKET)
throw Socket_error(sam_winsock_strerror(WSAGetLastError()));
#else
if (sock == -1)
throw Socket_error(strerror(errno));
#endif
}
#ifdef WINSOCK
/*
* Unloads the Winsock network subsystem
*/
void Socket::winsock_cleanup(void)
{
int rc = WSACleanup();
assert(rc != SOCKET_ERROR);
}
/*
* Loads the Winsock network sucksystem
*/
void Socket::winsock_startup(void)
{
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
int rc = WSAStartup(wVersionRequested, &wsaData);
if (rc != 0)
throw Socket_error(winsock_strerror(rc));
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
winsock_cleanup();
throw Socket_error("Bad Winsock version");
}
}
/*
* Apparently Winsock does not have a strerror() equivalent for its functions
*
* code - code from WSAGetLastError()
*
* Returns: error string (from http://msdn.microsoft.com/library/default.asp?
* url=/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp)
*/
const char* Socket::winsock_strerror(int code)
{
switch (code) {
case WSAEINTR:
return "Interrupted function call";
case WSAEACCES: // yes, that is the correct spelling
return "Permission denied";
case WSAEFAULT:
return "Bad address";
case WSAEINVAL:
return "Invalid argument";
case WSAEMFILE:
return "Too many open files";
case WSAEWOULDBLOCK:
return "Resource temporarily unavailable";
case WSAEINPROGRESS:
return "Operation now in progress";
case WSAEALREADY:
return "Operation already in progress";
case WSAENOTSOCK:
return "Socket operations on nonsocket";
case WSAEDESTADDRREQ:
return "Destination address required";
case WSAEMSGSIZE:
return "Message too long";
case WSAEPROTOTYPE:
return "Protocol wrong type for socket";
case WSAENOPROTOOPT:
return "Bad protocol option";
case WSAEPROTONOSUPPORT:
return "Protocol not supported";
case WSAESOCKTNOSUPPORT:
return "Socket type not supported";
case WSAEOPNOTSUPP:
return "Operation not supported";
case WSAEPFNOSUPPORT:
return "Protocol family not supported";
case WSAEAFNOSUPPORT:
return "Address family not supported by protocol family";
case WSAEADDRINUSE:
return "Address already in use";
case WSAEADDRNOTAVAIL:
return "Cannot assign requested address";
case WSAENETDOWN:
return "Network is down";
case WSAENETUNREACH:
return "Network is unreachable";
case WSAENETRESET:
return "Network dropped connection on reset";
case WSAECONNABORTED:
return "Software caused connection abort";
case WSAECONNRESET:
return "Connection reset by peer";
case WSAENOBUFS:
return "No buffer space available";
case WSAEISCONN:
return "Socket is already connected";
case WSAENOTCONN:
return "Socket is not connected";
case WSAESHUTDOWN:
return "Cannot send after socket shutdown";
case WSAETIMEDOUT:
return "Connection timed out";
case WSAECONNREFUSED:
return "Connection refused";
case WSAEHOSTDOWN:
return "Host is down";
case WSAEHOSTUNREACH:
return "No route to host";
case WSAEPROCLIM:
return "Too many processes";
case WSASYSNOTREADY:
return "Network subsystem is unavailable";
case WSAVERNOTSUPPORTED:
return "Winsock.dll version out of range";
case WSANOTINITIALISED:
return "Successful WSAStartup not yet performed";
case WSAEDISCON:
return "Graceful shutdown in progress";
case WSATYPE_NOT_FOUND:
return "Class type not found";
case WSAHOST_NOT_FOUND:
return "Host not found";
case WSATRY_AGAIN:
return "Nonauthoritative host not found";
case WSANO_RECOVERY:
return "This is a nonrecoverable error";
case WSANO_DATA:
return "Valid name, no data record of requested type";
/* None of this shit compiles under Mingw - who knows why...
case WSA_INVALID_HANDLE:
return "Specified event object handle is invalid";
case WSA_INVALID_PARAMETER:
return "One or more parameters are invalid";
case WSA_IO_INCOMPLETE:
return "Overlapped I/O event object not in signaled state";
case WSA_IO_PENDING:
return "Overlapped operations will complete later";
case WSA_NOT_ENOUGH_MEMORY:
return "Insufficient memory available";
case WSA_OPERATION_ABORTED:
return "Overlapped operation aborted";
case WSAINVALIDPROCTABLE:
return "Invalid procedure table from service provider";
case WSAINVALIDPROVIDER:
return "Invalid service provider version number";
case WSAPROVIDERFAILEDINIT:
return "Unable to initialize a service provider";
*/
case WSASYSCALLFAILURE:
return "System call failure";
default:
return "Unknown error";
}
}
#endif // WINSOCK

View File

@ -0,0 +1,64 @@
/*
* 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 LIBSOCKTHREAD_SOCKET_HPP
#define LIBSOCKTHREAD_SOCKET_HPP
namespace Libsockthread {
class Socket_error : public runtime_error {
public:
Socket_error(const string& s)
: runtime_error(s) { }
};
class Socket {
public:
Socket(void); // throws Socket_error
Socket(int domain, int type); // throws Socket_error
~Socket(void);
void close(void);
private:
#ifdef WINSOCK
typedef SOCKET socket_t;
void winsock_cleanup(void);
void winsock_startup(void); // throws Socket_error
const char* winsock_strerror(int code);
#else
typedef int socket_t;
#endif
void create_socket(int domain, int type); // throws Socket_error
socket_t sock;
static size_t total; // the total number of sockets in memory
};
}
#endif // LIBSOCKTHREAD_SOCKET_HPP

View File

@ -0,0 +1,83 @@
/*
* 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 <arpa/inet.h>
#include <cassert>
using namespace std;
#include "platform.hpp"
#include "socket.hpp"
#include "socket_addr.hpp"
using namespace Libsockthread;
Socket_addr::Socket_addr(int domain, const string& host, uint16_t port)
: domain(domain), host(host), port(port)
{
memset(&hostaddr, 0, sizeof hostaddr);
hostaddr.sin_family = domain;
hostaddr.sin_port = htons(port);
resolve(host.c_str(), ipaddr);
int rc;
#ifdef NO_INET_ATON
rc = hostaddr.sin_addr.s_addr = inet_addr(ipaddr);
#elif defined NO_INET_PTON
rc = inet_aton(ipaddr, &hostaddr.sin_addr);
#else
rc = inet_pton(AF_INET, ipaddr, &hostaddr.sin_addr);
#endif
assert(rc != 0 && rc != -1);
}
/*
* Performs a DNS lookup on `hostname' and puts the result in `ipaddr'
*/
bool Socket::resolve(const char* hostname, char* ipaddr)
{
struct hostent *h;
#ifdef NO_GETHOSTBYNAME2
h = gethostbyname(hostname);
#else
h = gethostbyname2(hostname, domain);
#endif
if (h == 0) {
LWARN("DNS resolution failed for %s", hostname);
throw Socket_error("DNS resolution failed");
}
struct in_addr a;
a.s_addr = ((struct in_addr *)h->h_addr)->s_addr;
#ifdef NO_INET_NTOP
char *tmp;
tmp = inet_ntoa(a);
assert(tmp != 0);
strlcpy(ipaddr, tmp, INET_ADDRSTRLEN); // inet_ntoa() was very poorly designed
#else
int rc = inet_ntop(domain, &a, ipaddr, INET_ADDRSTRLEN);
assert(rc != 0);
#endif
}

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.
*/
#ifndef LIBSOCKTHREAD_SOCKET_ADDR_HPP
#define LIBSOCKTHREAD_SOCKET_ADDR_HPP
namespace Libsockthread {
class Socket_addr {
public:
Socket_addr(int domain, const string& host, uint16_t port);
private:
bool resolve(const char* hostname, char* ipaddr);
int domain; // PF_INET or PF_INET6
string host;
char ipaddr[INET_ADDRSTRLEN];
struct sockaddr_in hostaddr;
uint16_t port;
};
}
#endif // LIBSOCKTHREAD_SOCKET_ADDR_HPP

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

@ -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 LIBSOCKTHREAD_STRL_H
#define LIBSOCKTHREAD_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 /* LIBSOCKTHREAD_STRL_H */

View File

@ -0,0 +1,199 @@
/*
* 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.
*/
// Modelled after JThread by Jori Liesenborgs
#include <cassert>
#include "platform.hpp"
#ifdef WINTHREAD
#include <windows.h>
#else
#include <pthread.h>
#endif
using namespace std;
#include "mutex.hpp"
#include "thread.hpp"
using namespace Libsockthread;
/*
* Gets the return value of a finished thread
*/
void* Thread::get_retval(void)
{
void* val;
running_m.lock();
if (running)
val = 0;
else
val = retval;
running_m.unlock();
return val;
}
/*
* Checks whether the thread is running
*/
bool Thread::is_running(void)
{
running_m.lock();
bool r = running;
running_m.unlock();
return r;
}
/*
* Stops the thread
* Generally NOT a good idea
*/
void Thread::kill(void)
{
running_m.lock();
#ifndef NDEBUG
// make sure it as actually running first
if (!running) {
running_m.unlock();
assert(false);
}
#endif
#ifdef WINTHREAD
BOOL rc = TerminateThread(handle, 0);
assert(rc);
#else
int rc = pthread_cancel(id);
assert(rc == 0);
#endif
running = false;
running_m.unlock();
}
/*
* Starts the thread
*/
void Thread::start(void)
{
#ifndef NDEBUG
// check whether the thread is already running
running_m.lock();
assert(!running);
running_m.unlock();
#endif
continue_m.lock();
#ifdef WINTHREAD
handle = CreateThread(0, 0, &the_thread, this, 0, &id);
assert(handle != 0);
#else
int rc = pthread_create(&id, 0, &the_thread, this);
assert(rc == 0);
#endif
// Wait until `running' is set
running_m.lock();
while (!running) {
running_m.unlock();
running_m.lock();
}
running_m.unlock();
continue_m.unlock();
}
/*
* Wrapper for the thread
*/
void* Thread::the_thread(void *param)
{
Thread* t = static_cast<Thread*>(param);
t->running_m.lock();
t->running = true;
t->running_m.unlock();
// wait until we can continue
t->continue_m.lock();
t->continue_m.unlock();
void* ret = t->thread();
t->running_m.lock();
t->running = false;
t->retval = ret;
t->running_m.unlock();
return 0;
}
#ifdef UNIT_TEST
// g++ -Wall -c mutex.cpp -o mutex.o
// g++ -Wall -DUNIT_TEST -c thread.cpp -o thread.o
// g++ -Wall -DUNIT_TEST mutex.o thread.o -o thread -lpthread
#include <iostream>
int main(void)
{
class Thread_test : public Thread
{
public:
Thread_test(int testval)
: testval(testval) { }
int get_testval(void)
{
testval_m.lock();
int rc = testval;
testval_m.unlock();
return rc;
}
void *thread(void)
{
// just do something
while (true) {
testval_m.lock();
++testval;
testval_m.unlock();
}
return 0;
}
private:
int testval;
Mutex testval_m;
};
Thread_test t1(1);
t1.start();
Thread_test t2(1000000);
t2.start();
Thread_test t3(-1000000);
t3.start();
while (true) {
if (t1.is_running())
cout << "t1 is running..." << t1.get_testval() << '\n';
if (t2.is_running())
cout << "t2 is running..." << t2.get_testval() << '\n';
if (t3.is_running())
cout << "t3 is running..." << t3.get_testval() << '\n';
}
return 0;
}
#endif // UNIT_TEST

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.
*/
// Modelled after JThread by Jori Liesenborgs
#ifndef LIBSOCKTHREAD_THREAD_HPP
#define LIBSOCKTHREAD_THREAD_HPP
namespace Libsockthread {
class Thread {
public:
Thread(void)
: retval(0), running(false) { }
virtual ~Thread(void)
{ kill(); }
void* get_retval(void);
bool is_running(void);
void kill(void);
void start(void);
virtual void *thread(void) = 0;
private:
#ifdef WINTHREAD
static DWORD WINAPI the_thread(void* param);
HANDLE handle;
DWORD id;
#else
static void* the_thread(void* param);
pthread_t id;
#endif
Mutex continue_m;
void *retval;
bool running;
Mutex running_m;
};
}
#endif // LIBSOCKTHREAD_THREAD_HPP

View File

@ -0,0 +1,94 @@
/*
* 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 <ctime>
#include <string>
using namespace std;
#include "time.hpp"
using namespace Libsockthread;
/*
* Converts the time to an ISO 8601 standard time and date and puts it in a
* string
* Example: 2004-07-01T19:03:47Z
*/
string& Time::utc(string &s) const
{
struct tm* tm;
tm = gmtime(&unixtime);
char t[21];
strftime(t, sizeof t, "%Y-%m-%dT%H:%M:%SZ", tm);
return s = t;
}
/*
* Converts the time to an ISO 8601 standard date and puts it in a string
* Example: 2004-07-01Z
*/
string& Time::utc_date(string &s) const
{
struct tm* tm;
tm = gmtime(&unixtime);
char t[12];
strftime(t, sizeof t, "%Y-%m-%dZ", tm);
return s = t;
}
/*
* Converts the time to an ISO 8601 standard time and puts it in a string
* Example: 19:03:47Z
*/
string& Time::utc_time(string &s) const
{
struct tm* tm;
tm = gmtime(&unixtime);
char t[10];
strftime(t, sizeof t, "%H:%M:%SZ", tm);
return s = t;
}
#ifdef UNIT_TEST
// g++ -Wall -DUNIT_TEST time.cpp -o time
#include <iostream>
int main(void)
{
Time t;
string s;
cout << "Current date and time is " << t.utc(s) << '\n';
cout << "Current date is " << t.utc_date(s) << '\n';
cout << "Current time is " << t.utc_time(s) << '\n';
return 0;
}
#endif // UNIT_TEST

View File

@ -0,0 +1,48 @@
/*
* 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 LIBSOCKTHREAD_TIME_HPP
#define LIBSOCKTHREAD_TIME_HPP
namespace Libsockthread {
class Time {
public:
Time(void) { now(); }
void now(void) { unixtime = time(0); }
string& utc(string &s) const;
string& utc_date(string &s) const;
string& utc_time(string &s) const;
private:
time_t unixtime;
};
}
#endif // LIBSOCKTHREAD_TIME_HPP

View File

@ -42,3 +42,20 @@ Logger::Logger(const string& file)
throw runtime_error("Error opening log file");
}
}
#ifdef WIN_STRERROR
/*
* strerror() for primitive operating systems
*/
TCHAR* win_strerror(TCHAR* str, size_t size)
{
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf,
0, NULL);
snprintf(str, size, "%s", lpMsgBuf);
LocalFree(lpMsgBuf);
return str;
}
#endif

View File

@ -81,4 +81,8 @@ class Logger {
ofstream logf;
};
#ifdef WIN_STRERROR
TCHAR* win_strerror(TCHAR* str, size_t size);
#endif
#endif // LOGGER_HPP

View File

@ -39,6 +39,13 @@
#define LINUX 2 // Linux
#define CYGWIN 3 // Cygwin
#if OS == MINGW
#define NO_SSIZE_T
#define WIN_STRERROR
#define WINSOCK
#define WINTHREADS
#endif
/*
* System includes
*/
@ -49,6 +56,11 @@
#include <iostream>
#include <list>
#include <map>
#ifdef WINTHREADS
#include <windows.h>
#else
#include <pthread.h>
#endif
#include <stdexcept>
#include <stdint.h>
#include <string>
@ -56,6 +68,10 @@
using namespace std;
#ifdef NO_SSIZE_T
typedef signed long ssize_t;
#endif
/*
* 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.
@ -71,6 +87,8 @@ using namespace std;
/*
* Local includes
*/
#include "mutex.hpp" // Mutex (for thread.hpp)
#include "thread.hpp" // Thread
#include "logger.hpp" // Logger
#include "config.hpp" // Config
#include "sam_error.hpp" // for sam.hpp

View File

@ -71,7 +71,7 @@ Sam::Sam(const string& samhost, uint16_t samport, const string& destname,
Sam::~Sam(void)
{
delete peers; // this must be before set_connected(false)!
if (get_connected()) {
if (is_connected()) {
sam_close();
set_connected(false);
}
@ -89,7 +89,7 @@ Sam::~Sam(void)
void Sam::connect(const char* samhost, uint16_t samport, const char* destname,
uint_t tunneldepth)
{
assert(!get_connected());
assert(!is_connected());
LMINOR << "Connecting to SAM as '" << destname << "'\n";
samerr_t rc = sam_connect(samhost, samport, destname, SAM_DGRAM, tunneldepth);
if (rc == SAM_OK)
@ -114,7 +114,7 @@ void Sam::load_peers(void)
*/
void Sam::naming_lookup(const string& name) const
{
assert(get_connected());
assert(is_connected());
sam_naming_lookup(name.c_str());
}
@ -127,7 +127,7 @@ void Sam::naming_lookup(const string& name) const
*/
void Sam::parse_dgram(const string& dest, void* data, size_t size)
{
assert(get_connected());
assert(is_connected());
Peer* peer = peers->new_peer(dest);
Rpc rpc(peer);
rpc.parse(data, size);
@ -140,7 +140,7 @@ void Sam::parse_dgram(const string& dest, void* data, size_t size)
*/
void Sam::read_buffer(void)
{
assert(get_connected());
assert(is_connected());
sam_read_buffer();
}
@ -153,6 +153,7 @@ void Sam::read_buffer(void)
*/
void Sam::send_dgram(const string& dest, uchar_t *data, size_t size)
{
assert(is_connected());
samerr_t rc = sam_dgram_send(dest.c_str(), data, size);
assert(rc == SAM_OK); // i.e. not SAM_TOO_BIG
}
@ -189,10 +190,10 @@ 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;
if (dest.substr(512, 4) == "AAAA") // Note this AAAA signifies a null
return true; // certificate and doesn't actually have
else // any bearing on validity, but we'll
return false; // keep this check here for now anyway
}
/*

View File

@ -55,7 +55,7 @@ class Sam {
private:
void connect(const char* samhost, uint16_t samport,
const char* destname, uint_t tunneldepth);
bool get_connected(void) const { return connected; }
bool is_connected(void) const { return connected; }
bool connected;
static bool exists;

View File

@ -9,12 +9,12 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" deprecation="on" source="1.3" target="1.3" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="compileGUI">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac debug="true" destdir="./build/obj">
<javac debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj">
<src path="src/" />
<classpath path="../../../core/java/build/i2p.jar" />
<classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />

View File

@ -358,7 +358,7 @@ public class ClientConfig {
int sendFreq = getInt(sendFrequencyVal);
int sendSize = getInt(sendSizeVal);
if ((duration <= 0) || (statFreq <= 0) || (sendFreq <= 0) || (sendSize <= 0)) {
if ((duration <= 0) || (statFreq <= 0) || (sendFreq < 0) || (sendSize <= 0)) {
if (_log.shouldLog(Log.WARN)) {
_log.warn("Invalid client config: duration [" + statDurationVal + "] stat frequency ["
+ statFrequencyVal + "] send frequency [" + sendFrequencyVal + "] send size ["
@ -424,7 +424,7 @@ public class ClientConfig {
* @return true if it was stored correctly, false if there were errors
*/
public boolean store(Properties clientConfig, int peerNum) {
if ((_peer == null) || (_sendFrequency <= 0) || (_sendSize <= 0) || (_statDuration <= 0)
if ((_peer == null) || (_sendFrequency < 0) || (_sendSize <= 0) || (_statDuration <= 0)
|| (_statFrequency <= 0) || (_statFile == null)) { return false; }
String comment = _comment;

View File

@ -90,7 +90,7 @@ class ClientEngine {
/** our actual heartbeat pumper - this drives the test */
private class ClientRunner implements Runnable {
/* (non-Javadoc)
/**
* @see java.lang.Runnable#run()
*/
public void run() {
@ -120,9 +120,12 @@ class ClientEngine {
_data.cleanup();
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
long timeToWait = nextSend - Clock.getInstance().now();
if (timeToWait > 0) {
try {
Thread.sleep(timeToWait);
} catch (InterruptedException ie) {
}
}
}
}

View File

@ -157,7 +157,7 @@ public class Heartbeat {
}
/** disconnect from the network */
private void disconnect() {
private void disconnect() { /* UNUSED */
_adapter.disconnect();
}

View File

@ -6,12 +6,11 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.Properties;
import net.i2p.I2PException;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PClientFactory;
import net.i2p.client.I2PSession;
@ -47,7 +46,7 @@ class I2PAdapter {
/** how do we talk to the router */
private I2PSession _session;
/** object that receives our i2cp notifications from the session and tells us */
private I2PListener _i2pListener;
private I2PListener _i2pListener; /* UNUSED */
/**
* This config property tells us where the private destination data for our
@ -579,14 +578,14 @@ class I2PAdapter {
* @see net.i2p.client.I2PSessionListener#errorOccurred(net.i2p.client.I2PSession, java.lang.String, java.lang.Throwable)
*/
public void errorOccurred(I2PSession session, String message, Throwable error) {
if (_log.shouldLog(Log.ERROR)) _log.error("Error occurred", error);
if (_log.shouldLog(Log.ERROR)) _log.error("Error occurred: " + message, error);
}
/* (non-Javadoc)
* @see net.i2p.client.I2PSessionListener#reportAbuse(net.i2p.client.I2PSession, int)
*/
public void reportAbuse(I2PSession session, int severity) {
if (_log.shouldLog(Log.ERROR)) _log.error("Abuse reported");
if (_log.shouldLog(Log.ERROR)) _log.error("Abuse reported with severity " + String.valueOf(severity));
}
/* (non-Javadoc)

View File

@ -103,6 +103,11 @@ public class PeerData {
* @return when the test began
*/
public long getSessionStart() { return _sessionStart; }
/**
* sets when the test began
* @param when when it began
*/
public void setSessionStart(long when) { _sessionStart = when; }
/**
@ -332,6 +337,11 @@ public class PeerData {
* @return the time the ping was sent
*/
public long getPingSent() { return _pingSent; }
/**
* sets when we sent this ping
* @param when when we sent the ping
*/
public void setPingSent(long when) { _pingSent = when; }
/**

View File

@ -114,7 +114,7 @@ public class PeerDataWriter {
return buf.toString();
}
private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
private final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
/**
* Converts a time (long) to text
@ -127,7 +127,7 @@ public class PeerDataWriter {
}
}
private static final DecimalFormat _numFmt = new DecimalFormat("#0", new DecimalFormatSymbols(Locale.UK));
private final DecimalFormat _numFmt = new DecimalFormat("#0", new DecimalFormatSymbols(Locale.UK));
/**
* Converts a number (double) to text

View File

@ -21,7 +21,7 @@ class HeartbeatControlPane extends JPanel {
private HeartbeatMonitorGUI _gui;
private JTabbedPane _configPane;
private final static Color WHITE = new Color(255, 255, 255);
private final static Color LIGHT_BLUE = new Color(180, 180, 255);
private final static Color LIGHT_BLUE = new Color(180, 180, 255); /* UNUSED */
private final static Color BLACK = new Color(0, 0, 0);
private Color _background = WHITE;
private Color _foreground = BLACK;

View File

@ -88,7 +88,9 @@ public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor
_gui.stateUpdated();
}
/** store the config defining what peer tests we are monitoring (and how to render) */
/**
* store the config defining what peer tests we are monitoring (and how to render)
*/
void storeConfig() {}
/**
@ -103,6 +105,10 @@ public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor
new HeartbeatMonitor().runMonitor();
}
/**
* Called when the config is updated
* @param config the updated config
*/
public void configUpdated(PeerPlotConfig config) {
_log.debug("Config updated, revamping the gui");
_gui.stateUpdated();

View File

@ -19,7 +19,7 @@ import net.i2p.heartbeat.PeerData;
import net.i2p.util.Log;
class JFreeChartAdapter {
private final static Log _log = new Log(JFreeChartAdapter.class);
private final static Log _log = new Log(JFreeChartAdapter.class); /* UNUSED */
private final static Color WHITE = new Color(255, 255, 255);
ChartPanel createPanel(HeartbeatMonitorState state) {
@ -45,7 +45,7 @@ class JFreeChartAdapter {
updateLines(plot, state);
}
private long getFirst(HeartbeatMonitorState state) {
private long getFirst(HeartbeatMonitorState state) { /* UNUSED */
long first = -1;
for (int i = 0; i < state.getTestCount(); i++) {
List dataPoints = state.getTest(i).getCurrentData().getDataPoints();
@ -116,6 +116,7 @@ class JFreeChartAdapter {
}
/**
* @param col the collection of xy series to add to
* @param config preferences for how to display this test
* @param lineName minimal name of the test (e.g. "jxHa.32KB.60s")
* @param data List of PeerData.EventDataPoint describing all of the events in the test
@ -144,6 +145,7 @@ class JFreeChartAdapter {
/**
* Add a data series for each average that we're configured to render
*
* @param col the collection of xy series to add to
* @param config preferences for how to display this test
* @param lineName minimal name of the test (e.g. "jxHa.32KB.60s")
* @param data List of PeerData.EventDataPoint describing all of the events in the test

View File

@ -14,14 +14,21 @@ import net.i2p.util.Log;
*
*/
class JFreeChartHeartbeatPlotPane extends HeartbeatPlotPane {
private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class);
private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class); /* UNUSED */
private ChartPanel _panel;
private JFreeChartAdapter _adapter;
/**
* Creates a JFreeChart plot pane for the given gui
* @param gui the heartbeat monitor gui
*/
public JFreeChartHeartbeatPlotPane(HeartbeatMonitorGUI gui) {
super(gui);
}
/**
* Called when the state is updated
*/
public void stateUpdated() {
if (_panel == null) {
remove(0); // remove the dummy

View File

@ -18,7 +18,7 @@ import net.i2p.util.Log;
* Configure how we want to render a particular clientConfig in the GUI
*/
class PeerPlotConfig {
private final static Log _log = new Log(PeerPlotConfig.class);
private final static Log _log = new Log(PeerPlotConfig.class); /* UNUSED */
/** where can we find the current state/data (either as a filename or a URL)? */
private String _location;
/** what test are we defining the plot data for? */
@ -170,8 +170,8 @@ class PeerPlotConfig {
Destination peer = getClientConfig().getPeer();
if (peer == null)
return "????";
else
return peer.calculateHash().toBase64().substring(0, 4);
return peer.calculateHash().toBase64().substring(0, 4);
}
/**
@ -196,8 +196,8 @@ class PeerPlotConfig {
int bytes = getClientConfig().getSendSize();
if (bytes < 1024)
return bytes + "b";
else
return bytes/1024 + "kb";
return bytes/1024 + "kb";
}
/**

View File

@ -243,6 +243,7 @@ class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener
_minutes = minutes;
_button = button;
}
/* (non-Javadoc)
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/

View File

@ -326,7 +326,7 @@ class PeerPlotStateFetcher {
}
}
private void fakeRun() {
private void fakeRun() { /* UNUSED */
try {
Destination peer = new Destination();
Destination us = new Destination();

View File

@ -94,8 +94,8 @@ class StaticPeerData extends PeerData {
Integer i = (Integer)_averageSendTimes.get(new Integer(period));
if (i == null)
return -1;
else
return i.doubleValue();
return i.doubleValue();
}
@ -109,8 +109,8 @@ class StaticPeerData extends PeerData {
Integer i = (Integer)_averageReceiveTimes.get(new Integer(period));
if (i == null)
return -1;
else
return i.doubleValue();
return i.doubleValue();
}
/**
@ -123,8 +123,8 @@ class StaticPeerData extends PeerData {
Integer i = (Integer)_lostMessages.get(new Integer(period));
if (i == null)
return -1;
else
return i.doubleValue();
return i.doubleValue();
}
/* (non-Javadoc)

View File

@ -11,7 +11,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
debug="true" deprecation="on" source="1.3" target="1.3"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>

View File

@ -57,14 +57,14 @@ public class HTTPListener extends Thread {
* @return Whether this is the first proxy use, no doubt.
*/
public boolean firstProxyUse() {
// FIXME: check a config option here
if (true) return false;
if (true) return false; // FIXME: check a config option here
if (proxyUsed) {
return false;
} else {
proxyUsed = true;
return true;
}
proxyUsed = true;
return true;
}
/**

View File

@ -12,7 +12,7 @@ import net.i2p.util.Log;
*/
public class ErrorHandler {
private static final Log _log = new Log(ErrorHandler.class);
private static final Log _log = new Log(ErrorHandler.class); /* UNUSED */
/* package private */ErrorHandler() {

View File

@ -13,7 +13,7 @@ import net.i2p.util.Log;
*/
public class LocalHandler {
private static final Log _log = new Log(LocalHandler.class);
private static final Log _log = new Log(LocalHandler.class); /* UNUSED */
/* package private */LocalHandler() {
}

View File

@ -18,7 +18,7 @@ import net.i2p.util.Log;
*/
public class ProxyHandler extends EepHandler {
private static final Log _log = new Log(ErrorHandler.class);
private static final Log _log = new Log(ErrorHandler.class); /* UNUSED */
private static I2PAppContext _context = new I2PAppContext();
/* package private */ProxyHandler(ErrorHandler eh) {

View File

@ -12,7 +12,7 @@ import net.i2p.util.Log;
*/
public class RootHandler {
private static final Log _log = new Log(RootHandler.class);
private static final Log _log = new Log(RootHandler.class); /* UNUSED */
private RootHandler() {
errorHandler = new ErrorHandler();
@ -60,26 +60,24 @@ public class RootHandler {
url = url.substring(7);
pos = url.indexOf("/");
String host;
String rest;
if (pos == -1) {
errorHandler.handle(req, httpl, out, "No host end in URL");
return;
}
host = url.substring(0, pos);
url = url.substring(pos);
if ("i2p".equals(host) || "i2p.i2p".equals(host)) {
// normal request; go on below...
} else if (host.endsWith(".i2p")) {
// "old" service request, send a redirect...
out.write(("HTTP/1.1 302 Moved\r\nLocation: " + "http://i2p.i2p/" + host + url + "\r\n\r\n").getBytes("ISO-8859-1"));
return;
} else {
host = url.substring(0, pos);
url = url.substring(pos);
if ("i2p".equals(host) || "i2p.i2p".equals(host)) {
// normal request; go on below...
} else if (host.endsWith(".i2p")) {
// "old" service request, send a redirect...
out
.write(("HTTP/1.1 302 Moved\r\nLocation: " + "http://i2p.i2p/" + host + url + "\r\n\r\n")
.getBytes("ISO-8859-1"));
return;
} else {
// this is for proxying to the real web
proxyHandler.handle(req, httpl, out /*, true */);
return;
}
// this is for proxying to the real web
proxyHandler.handle(req, httpl, out /*, true */);
return;
}
}
if (url.equals("/")) { // main page

View File

@ -11,7 +11,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
debug="true" deprecation="on" source="1.3" target="1.3"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>

View File

@ -17,6 +17,9 @@ class BufferLogger implements Logging {
private ByteArrayOutputStream _baos;
private boolean _ignore;
/**
* Constructs a buffered logger.
*/
public BufferLogger() {
_baos = new ByteArrayOutputStream(512);
_ignore = false;
@ -24,11 +27,15 @@ class BufferLogger implements Logging {
private final static String EMPTY = "";
/**
* Retrieves the buffer
* @return the buffer
*/
public String getBuffer() {
if (_ignore)
return EMPTY;
else
return new String(_baos.toByteArray());
return new String(_baos.toByteArray());
}
/**

View File

@ -46,6 +46,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
@ -69,6 +70,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
private I2PAppContext _context;
private static long __tunnelId = 0;
private long _tunnelId;
private Properties _clientOptions;
public static final int PACKET_DELAY = 100;
@ -104,6 +106,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
_tunnelId = ++__tunnelId;
_log = _context.logManager().getLog(I2PTunnel.class);
_event = new EventDispatcherImpl();
_clientOptions = new Properties();
_clientOptions.putAll(System.getProperties());
addConnectionEventListener(lsnr);
boolean gui = true;
boolean checkRunByE = true;
@ -167,6 +172,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
public Properties getClientOptions() { return _clientOptions; }
private void addtask(I2PTunnelTask tsk) {
tsk.setTunnel(this);
if (tsk.isOpen()) {
@ -197,6 +204,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
if ("help".equals(cmdname)) {
runHelp(l);
} else if ("clientoptions".equals(cmdname)) {
runClientOptions(args, l);
} else if ("server".equals(cmdname)) {
runServer(args, l);
} else if ("textserver".equals(cmdname)) {
@ -262,6 +271,29 @@ public class I2PTunnel implements Logging, EventDispatcher {
l.log("list");
l.log("run <commandfile>");
}
/**
* Configure the extra I2CP options to use in any subsequent I2CP sessions.
* Usage: "clientoptions[ key=value]*" .
*
* Sets the event "clientoptions_onResult" = "ok" after completion.
*
* @param args each args[i] is a key=value pair to add to the options
* @param l logger to receive events and output
*/
public void runClientOptions(String args[], Logging l) {
_clientOptions.clear();
if (args != null) {
for (int i = 0; i < args.length; i++) {
int index = args[i].indexOf('=');
if (index <= 0) continue;
String key = args[i].substring(0, index);
String val = args[i].substring(index+1);
_clientOptions.setProperty(key, val);
}
}
notifyEvent("clientoptions_onResult", "ok");
}
/**
* Run the server pointing at the host and port specified using the private i2p
@ -304,7 +336,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
notifyEvent("serverTaskId", new Integer(-1));
return;
}
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this);
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
@ -350,7 +382,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
return;
}
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this);
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this, this);
serv.setReadTimeout(readTimeout);
serv.startRunning();
addtask(serv);
@ -386,7 +418,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
return;
}
I2PTunnelTask task;
task = new I2PTunnelClient(port, args[1], l, ownDest, (EventDispatcher) this);
task = new I2PTunnelClient(port, args[1], l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("clientTaskId", new Integer(task.getId()));
} else {
@ -423,7 +455,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
proxy = args[1];
}
I2PTunnelTask task;
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this);
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this, this);
addtask(task);
notifyEvent("httpclientTaskId", new Integer(task.getId()));
} else {
@ -460,7 +492,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
I2PTunnelTask task;
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this);
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("sockstunnelTaskId", new Integer(task.getId()));
} else {
@ -779,7 +811,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
if (allargs.length() != 0) {
I2PTunnelTask task;
// pings always use the main destination
task = new I2Ping(allargs, l, false, (EventDispatcher) this);
task = new I2Ping(allargs, l, false, (EventDispatcher) this, this);
addtask(task);
notifyEvent("pingTaskId", new Integer(task.getId()));
} else {

View File

@ -19,8 +19,8 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1
protected long readTimeout = DEFAULT_READ_TIMEOUT;
public I2PTunnelClient(int localPort, String destination, Logging l, boolean ownDest, EventDispatcher notifyThis) {
super(localPort, ownDest, l, notifyThis, "SynSender");
public I2PTunnelClient(int localPort, String destination, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openClientResult", "error");

View File

@ -60,8 +60,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
//}
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName) {
super(localPort + " (uninitialized)", notifyThis);
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel) {
super(localPort + " (uninitialized)", notifyThis, tunnel);
_clientId = ++__clientId;
this.localPort = localPort;
this.l = l;
@ -103,17 +103,28 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private static I2PSocketManager socketManager;
protected static synchronized I2PSocketManager getSocketManager() {
protected synchronized I2PSocketManager getSocketManager() {
return getSocketManager(getTunnel());
}
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
if (socketManager == null) {
socketManager = buildSocketManager();
socketManager = buildSocketManager(tunnel);
}
return socketManager;
}
protected static I2PSocketManager buildSocketManager() {
protected I2PSocketManager buildSocketManager() {
return buildSocketManager(getTunnel());
}
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
Properties props = new Properties();
props.putAll(System.getProperties());
return I2PSocketManagerFactory.createManager(I2PTunnel.host, Integer.parseInt(I2PTunnel.port), props);
if (tunnel == null)
props.putAll(System.getProperties());
else
props.putAll(tunnel.getClientOptions());
I2PSocketManager sockManager = I2PSocketManagerFactory.createManager(I2PTunnel.host, Integer.parseInt(I2PTunnel.port), props);
sockManager.setName("Client");
return sockManager;
}
public final int getLocalPort() {

View File

@ -81,8 +81,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest, String wwwProxy, EventDispatcher notifyThis) {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId));
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest, String wwwProxy, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openHTTPClientResult", "error");
@ -127,7 +127,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (pos == -1) break;
method = line.substring(0, pos);
String request = line.substring(pos + 1);
if (request.startsWith("/") && System.getProperty("i2ptunnel.noproxy") != null) {
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
request = "http://i2p" + request;
}
pos = request.indexOf("//");
@ -226,6 +226,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
Destination dest = I2PTunnel.destFromName(destination);
if (dest == null) {
l.log("Could not resolve " + destination + ".");
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to resolve " + destination + " (proxy? " + usingWWWProxy + ", request: " + targetRequest);
writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, destination);
s.close();
return;
@ -365,6 +367,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
private void handleHTTPClientException(Exception ex, OutputStream out, String targetRequest,
boolean usingWWWProxy, String wwwProxy) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error sending to " + wwwProxy + " (proxy? " + usingWWWProxy + ", request: " + targetRequest, ex);
if (out != null) {
try {
writeErrorMessage(ERR_DESTINATION_UNKNOWN, out, targetRequest, usingWWWProxy, wwwProxy);

View File

@ -45,15 +45,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
/** default timeout to 3 minutes - override if desired */
private long readTimeout = DEFAULT_READ_TIMEOUT;
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis) {
super(host + ":" + port + " <- " + privData, notifyThis);
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privData, notifyThis, tunnel);
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
init(host, port, bais, privData, l);
}
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis) {
super(host + ":" + port + " <- " + privkeyname, notifyThis);
EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
try {
init(host, port, new FileInputStream(privkey), privkeyname, l);
} catch (IOException ioe) {
@ -62,8 +62,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
}
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis) {
super(host + ":" + port + " <- " + privkeyname, notifyThis);
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
init(host, port, privData, privkeyname, l);
}
@ -73,12 +73,13 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
this.remotePort = port;
I2PClient client = I2PClientFactory.createClient();
Properties props = new Properties();
props.putAll(System.getProperties());
props.putAll(getTunnel().getClientOptions());
synchronized (slock) {
sockMgr = I2PSocketManagerFactory.createManager(privData, I2PTunnel.host, Integer.parseInt(I2PTunnel.port),
props);
}
sockMgr.setName("Server");
l.log("Ready!");
notifyEvent("openServerResult", "ok");
open = true;

View File

@ -26,16 +26,19 @@ public abstract class I2PTunnelTask implements EventDispatcher {
// I2PTunnelTask(name, (EventDispatcher)null);
//}
protected I2PTunnelTask(String name, EventDispatcher notifyThis) {
protected I2PTunnelTask(String name, EventDispatcher notifyThis, I2PTunnel tunnel) {
attachEventDispatcher(notifyThis);
this.name = name;
this.id = -1;
this.tunnel = tunnel;
}
/** for apps that use multiple I2PTunnel instances */
public void setTunnel(I2PTunnel pTunnel) {
tunnel = pTunnel;
}
public I2PTunnel getTunnel() { return tunnel; }
public int getId() {
return this.id;

View File

@ -47,15 +47,15 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
// I2Ping(cmd, l, (EventDispatcher)null);
//}
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis) {
super("I2Ping [" + cmd + "]", notifyThis);
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("I2Ping [" + cmd + "]", notifyThis, tunnel);
this.l = l;
command = cmd;
synchronized (slock) {
if (ownDest) {
sockMgr = I2PTunnelClient.buildSocketManager();
sockMgr = I2PTunnelClient.buildSocketManager(tunnel);
} else {
sockMgr = I2PTunnelClient.getSocketManager();
sockMgr = I2PTunnelClient.getSocketManager(tunnel);
}
}
Thread t = new I2PThread(this);

View File

@ -10,6 +10,7 @@ import java.net.Socket;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelClientBase;
import net.i2p.i2ptunnel.I2PTunnelRunner;
import net.i2p.i2ptunnel.Logging;
@ -26,8 +27,8 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
// I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null);
//}
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler");
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel);
if (waitEventValue("openBaseClientResult").equals("error")) {
notifyEvent("openSOCKSTunnelResult", "error");

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" deprecation="on" source="1.3" target="1.3" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" />

View File

@ -1,31 +1,71 @@
package net.i2p.client.streaming;
/** Like a StringBuffer, but for bytes */
/**
* Like a StringBuffer, but for bytes. This class is not internally synchronized,
* so care should be taken when using in a multithreaded environment.
*
*/
public class ByteCollector {
byte[] contents;
int size;
private static final int INITIAL_CAPACITY = 1024;
private static final int SHORT_CAPACITY = 80;
/**
* New collector with the default initial capacity
*
*/
public ByteCollector() {
contents = new byte[1024];
this(INITIAL_CAPACITY);
}
/**
* New collector with an initial capacity as specified
*
*/
public ByteCollector(int capacity) {
contents = new byte[capacity];
size = 0;
}
/**
* New collector containing the specified bytes
*
*/
public ByteCollector(byte[] b) {
this();
append(b);
}
/**
* New collector with the specified byte
*
*/
public ByteCollector(byte b) {
this();
append(b);
}
/**
* Add a new byte to the collector (extending the buffer if necessary)
*
* @param b byte to add
* @return this object
*/
public ByteCollector append(byte b) {
ensureCapacity(size + 1);
contents[size++] = b;
return this;
}
/**
* Add new bytes to the collector (extending the buffer if necessary)
*
* @param b bytes to add
* @return this object
*/
public ByteCollector append(byte[] b) {
ensureCapacity(size + b.length);
System.arraycopy(b, 0, contents, size, b.length);
@ -33,10 +73,25 @@ public class ByteCollector {
return this;
}
/**
* Add new bytes to the collector (extending the buffer if necessary)
*
* @param b byte array to add from
* @param len number of bytes in the array to add
* @return this object
*/
public ByteCollector append(byte[] b, int len) {
return append(b, 0, len);
}
/**
* Add new bytes to the collector (extending the buffer if necessary)
*
* @param b byte array to add from
* @param off offset into the array to begin adding from
* @param len number of bytes in the array to add
* @return this object
*/
public ByteCollector append(byte[] b, int off, int len) {
ensureCapacity(size + len);
System.arraycopy(b, off, contents, size, len);
@ -44,17 +99,36 @@ public class ByteCollector {
return this;
}
/**
* Add the contents of the byte collector to the current collector (extending the buffer if necessary)
*
* @param bc collector to copy
* @return this object
*/
public ByteCollector append(ByteCollector bc) {
// optimieren?
return append(bc.toByteArray());
}
/**
* Copy the contents of the collector into a new array and return it
*
* @return new array containing a copy of the current collector's data
*/
public byte[] toByteArray() {
byte[] result = new byte[size];
System.arraycopy(contents, 0, result, 0, size);
return result;
}
/**
* Pull off the first $maxlen bytes from the collector, shifting the remaining
* bytes into the beginning of the collector's array.
*
* @param maxlen max number of bytes we want to pull from the collector (we will get
* less if the collector doesnt have that many bytes yet)
* @return copy of the bytes pulled from the collector
*/
public byte[] startToByteArray(int maxlen) {
if (size < maxlen) {
byte[] res = toByteArray();
@ -69,10 +143,22 @@ public class ByteCollector {
}
}
/**
* How many bytes are available for retrieval?
*
* @return number of bytes
*/
public int getCurrentSize() {
return size;
}
/**
* Make sure we have sufficient storage space.
*
* @param cap minimum number of bytes that the buffer should contain
* @return true if the the collector was expanded to meet the minimum,
* false if it was already large enough
*/
public boolean ensureCapacity(int cap) {
if (contents.length < cap) {
int l = contents.length;
@ -87,20 +173,46 @@ public class ByteCollector {
return false;
}
/**
* Does the collector have meaningful data or is it empty?
*
* @return true if it has no data
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Search through the collector for the first occurrence of the sequence of
* bytes contained within the specified collector
*
* @param bc bytes that will be searched for
* @return index into the current collector, or -1 if it isn't found
*/
public int indexOf(ByteCollector bc) {
// optimieren?
return indexOf(bc.toByteArray());
}
/**
* Search through the collector for the first occurrence of the specified
* byte
*
* @param b byte that will be searched for
* @return index into the current collector, or -1 if it isn't found
*/
public int indexOf(byte b) {
// optimieren?
return indexOf(new byte[] { b});
}
/**
* Search through the collector for the first occurrence of the sequence of
* bytes
*
* @param ba bytes that will be searched for
* @return index into the current collector, or -1 if it isn't found
*/
public int indexOf(byte[] ba) {
loop: for (int i = 0; i < size - ba.length + 1; i++) {
for (int j = 0; j < ba.length; j++) {
@ -111,15 +223,28 @@ public class ByteCollector {
return -1;
}
/**
* Empty the collector. This does not affect its capacity.
*
*/
public void clear() {
size = 0;
}
/**
* Empty the collector and reduce its capacity.
*
*/
public void clearAndShorten() {
size = 0;
contents = new byte[80];
contents = new byte[SHORT_CAPACITY];
}
/**
* Render the bytes as a string
*
* @return the, uh, string
*/
public String toString() {
return new String(toByteArray());
}
@ -132,6 +257,12 @@ public class ByteCollector {
return h;
}
/**
* Compare the collectors.
*
* @return true if and only if both are the same size and the
* byte arrays they contain are equal.
*/
public boolean equals(Object o) {
if (o instanceof ByteCollector) {
ByteCollector by = (ByteCollector) o;
@ -145,7 +276,13 @@ public class ByteCollector {
}
}
public byte removeFirst() {
/**
* Remove the first byte from the collector, shifting its contents accordingly.
*
* @return byte removed
* @throws IllegalArgumentException if the collector is empty
*/
public byte removeFirst() throws IllegalArgumentException {
byte bb = contents[0];
if (size == 0) throw new IllegalArgumentException("ByteCollector is empty");
if (size > 1)

View File

@ -5,12 +5,14 @@ import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PSessionException;
import net.i2p.data.Destination;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
/**
* Initial stub implementation for the socket
*
@ -35,6 +37,9 @@ class I2PSocketImpl implements I2PSocket {
private static long __socketId = 0;
private long _bytesRead = 0;
private long _bytesWritten = 0;
private long _createdOn;
private long _closedOn;
private long _remoteIdSetTime;
private Object flagLock = new Object();
/**
@ -73,6 +78,9 @@ class I2PSocketImpl implements I2PSocket {
out = new I2POutputStream(pin);
new I2PSocketRunner(pin);
this.localID = localID;
_createdOn = I2PAppContext.getGlobalContext().clock().now();
_remoteIdSetTime = -1;
_closedOn = -1;
}
/**
@ -89,6 +97,7 @@ class I2PSocketImpl implements I2PSocket {
public void setRemoteID(String id) {
synchronized (remoteIDWaiter) {
remoteID = id;
_remoteIdSetTime = System.currentTimeMillis();
remoteIDWaiter.notifyAll();
}
}
@ -123,16 +132,23 @@ class I2PSocketImpl implements I2PSocket {
long dieAfter = System.currentTimeMillis() + maxWait;
synchronized (remoteIDWaiter) {
if (wait) {
try {
if (maxWait >= 0)
remoteIDWaiter.wait(maxWait);
else
remoteIDWaiter.wait();
} catch (InterruptedException ex) {
if (remoteID == null) {
try {
if (maxWait >= 0)
remoteIDWaiter.wait(maxWait);
else
remoteIDWaiter.wait();
} catch (InterruptedException ex) {
}
}
if ((maxWait >= 0) && (System.currentTimeMillis() >= dieAfter))
throw new InterruptedIOException("Timed out waiting for remote ID");
long now = System.currentTimeMillis();
if ((maxWait >= 0) && (now >= dieAfter)) {
long waitedExcess = now - dieAfter;
throw new InterruptedIOException("Timed out waiting for remote ID (waited " + waitedExcess
+ "ms too long [" + maxWait + "ms, remId " + remoteID
+ ", remId set " + (now-_remoteIdSetTime) + "ms ago])");
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("TIMING: RemoteID set to "
@ -199,8 +215,10 @@ class I2PSocketImpl implements I2PSocket {
*/
public void close() throws IOException {
synchronized (flagLock) {
_log.debug("Closing connection");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Closing connection");
closed = true;
_closedOn = I2PAppContext.getGlobalContext().clock().now();
}
out.close();
in.notifyClosed();
@ -214,6 +232,7 @@ class I2PSocketImpl implements I2PSocket {
closed = true;
closed2 = true;
sendClose = false;
_closedOn = I2PAppContext.getGlobalContext().clock().now();
}
out.close();
in.notifyClosed();
@ -248,6 +267,12 @@ class I2PSocketImpl implements I2PSocket {
_socketErrorListener.errorOccurred();
}
public long getBytesSent() { return _bytesWritten; }
public long getBytesReceived() { return _bytesRead; }
public long getCreatedOn() { return _createdOn; }
public long getClosedOn() { return _closedOn; }
private String getPrefix() { return "[" + _socketId + "]: "; }
//--------------------------------------------------
@ -273,12 +298,15 @@ class I2PSocketImpl implements I2PSocket {
throw new RuntimeException("Incorrect read() result");
}
public synchronized int read(byte[] b, int off, int len) throws IOException {
public int read(byte[] b, int off, int len) throws IOException {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Read called: " + this.hashCode());
_log.debug(getPrefix() + "Read called for " + len + " bytes (avail=" + bc.getCurrentSize() + "): " + this.hashCode());
if (len == 0) return 0;
long dieAfter = System.currentTimeMillis() + readTimeout;
byte[] read = bc.startToByteArray(len);
byte[] read = null;
synchronized (bc) {
read = bc.startToByteArray(len);
}
boolean timedOut = false;
while (read.length == 0) {
@ -290,10 +318,12 @@ class I2PSocketImpl implements I2PSocket {
}
}
try {
if (readTimeout >= 0) {
wait(readTimeout);
} else {
wait();
synchronized (I2PSocketImpl.I2PInputStream.this) {
if (readTimeout >= 0) {
wait(readTimeout);
} else {
wait();
}
}
} catch (InterruptedException ex) {}
@ -302,7 +332,9 @@ class I2PSocketImpl implements I2PSocket {
throw new InterruptedIOException(getPrefix() + "Timeout reading from I2PSocket (" + readTimeout + " msecs)");
}
read = bc.startToByteArray(len);
synchronized (bc) {
read = bc.startToByteArray(len);
}
}
if (read.length > len) throw new RuntimeException("BUG");
System.arraycopy(read, 0, b, off, read.length);
@ -320,22 +352,30 @@ class I2PSocketImpl implements I2PSocket {
}
public int available() {
return bc.getCurrentSize();
synchronized (bc) {
return bc.getCurrentSize();
}
}
public void queueData(byte[] data) {
queueData(data, 0, data.length);
}
public synchronized void queueData(byte[] data, int off, int len) {
public void queueData(byte[] data, int off, int len) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Insert " + len + " bytes into queue: " + hashCode());
bc.append(data, off, len);
notifyAll();
synchronized (bc) {
bc.append(data, off, len);
}
synchronized (I2PInputStream.this) {
I2PInputStream.this.notifyAll();
}
}
public synchronized void notifyClosed() {
I2PInputStream.this.notifyAll();
public void notifyClosed() {
synchronized (I2PInputStream.this) {
I2PInputStream.this.notifyAll();
}
}
public void close() throws IOException {

View File

@ -15,6 +15,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
import net.i2p.client.I2PSession;
import net.i2p.client.I2PSessionException;
@ -24,6 +25,7 @@ import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
import net.i2p.util.Log;
/**
* Centralize the coordination and multiplexing of the local client's streaming.
* There should be one I2PSocketManager for each I2PSession, and if an application
@ -33,7 +35,8 @@ import net.i2p.util.Log;
*
*/
public class I2PSocketManager implements I2PSessionListener {
private final static Log _log = new Log(I2PSocketManager.class);
private I2PAppContext _context;
private Log _log;
private I2PSession _session;
private I2PServerSocketImpl _serverSocket = null;
private Object lock = new Object(); // for locking socket lists
@ -41,6 +44,8 @@ public class I2PSocketManager implements I2PSessionListener {
private HashMap _inSockets;
private I2PSocketOptions _defaultOptions;
private long _acceptTimeout;
private String _name;
private static int __managerId = 0;
public static final short ACK = 0x51;
public static final short CLOSE_OUT = 0x52;
@ -57,10 +62,24 @@ public class I2PSocketManager implements I2PSessionListener {
private static final long ACCEPT_TIMEOUT_DEFAULT = 5*1000;
public I2PSocketManager() {
this("SocketManager " + (++__managerId));
}
public I2PSocketManager(String name) {
_name = name;
_session = null;
_inSockets = new HashMap(16);
_outSockets = new HashMap(16);
_acceptTimeout = ACCEPT_TIMEOUT_DEFAULT;
_context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(I2PSocketManager.class);
_context.statManager().createRateStat("streaming.lifetime", "How long before the socket is closed?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.sent", "How many bytes are sent in the stream?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.received", "How many bytes are received in the stream?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.transferBalance", "How many streams send more than they receive (positive means more sent, negative means more received)?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.synNoAck", "How many times have we sent a SYN but not received an ACK?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.ackSendFailed", "How many times have we tried to send an ACK to a SYN and failed?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.nackSent", "How many times have we refused a SYN with a NACK?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("streaming.nackReceived", "How many times have we received a NACK to our SYN?", "streaming", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
}
public I2PSession getSession() {
@ -82,12 +101,12 @@ public class I2PSocketManager implements I2PSessionListener {
public long getAcceptTimeout() { return _acceptTimeout; }
public void disconnected(I2PSession session) {
_log.info("Disconnected from the session");
_log.info(getName() + ": Disconnected from the session");
destroySocketManager();
}
public void errorOccurred(I2PSession session, String message, Throwable error) {
_log.error("Error occurred: [" + message + "]", error);
_log.error(getName() + ": Error occurred: [" + message + "]", error);
}
public void messageAvailable(I2PSession session, int msgId, long size) {
@ -95,11 +114,11 @@ public class I2PSocketManager implements I2PSessionListener {
I2PSocketImpl s;
byte msg[] = session.receiveMessage(msgId);
if (msg.length == 1 && msg[0] == -1) {
_log.debug("Ping received");
_log.debug(getName() + ": Ping received");
return;
}
if (msg.length < 4) {
_log.error("==== packet too short ====");
_log.error(getName() + ": ==== packet too short ====");
return;
}
int type = msg[0] & 0xff;
@ -107,7 +126,7 @@ public class I2PSocketManager implements I2PSessionListener {
byte[] payload = new byte[msg.length - 4];
System.arraycopy(msg, 4, payload, 0, payload.length);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Message read: type = [" + Integer.toHexString(type)
_log.debug(getName() + ": Message read: type = [" + Integer.toHexString(type)
+ "] id = [" + getReadableForm(id)
+ "] payload length: [" + payload.length + "]");
switch (type) {
@ -136,9 +155,9 @@ public class I2PSocketManager implements I2PSessionListener {
return;
}
} catch (I2PException ise) {
_log.error("Error processing", ise);
_log.error(getName() + ": Error processing", ise);
} catch (IllegalStateException ise) {
_log.debug("Error processing", ise);
_log.debug(getName() + ": Error processing", ise);
}
}
@ -150,30 +169,45 @@ public class I2PSocketManager implements I2PSessionListener {
*
*/
private void ackAvailable(String id, byte payload[]) {
long begin = _context.clock().now();
I2PSocketImpl s = null;
synchronized (lock) {
s = (I2PSocketImpl) _outSockets.get(id);
}
if (s == null) {
_log.warn("No socket responsible for ACK packet");
_log.warn(getName() + ": No socket responsible for ACK packet");
return;
}
long socketRetrieved = _context.clock().now();
String remoteId = null;
remoteId = s.getRemoteID(false);
if ( (payload.length == 3) && (remoteId == null) ) {
String newID = toString(payload);
long beforeSetRemId = _context.clock().now();
s.setRemoteID(newID);
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(getName() + ": ackAvailable - socket retrieval took "
+ (socketRetrieved-begin) + "ms, getRemoteId took "
+ (beforeSetRemId-socketRetrieved) + "ms, setRemoteId took "
+ (_context.clock().now()-beforeSetRemId) + "ms");
}
return;
} else {
// (payload.length != 3 || getRemoteId != null)
if (_log.shouldLog(Log.WARN)) {
if (payload.length != 3)
_log.warn("Ack packet had " + payload.length + " bytes");
_log.warn(getName() + ": Ack packet had " + payload.length + " bytes");
else
_log.warn("Remote ID already exists? " + remoteId);
_log.warn(getName() + ": Remote ID already exists? " + remoteId);
}
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(getName() + ": invalid ack - socket retrieval took "
+ (socketRetrieved-begin) + "ms, overall took "
+ (_context.clock().now()-begin) + "ms");
}
return;
}
@ -189,11 +223,11 @@ public class I2PSocketManager implements I2PSessionListener {
s = (I2PSocketImpl) _outSockets.get(id);
}
_log.debug("*Disconnect outgoing for socket " + s);
_log.debug(getName() + ": *Disconnect outgoing for socket " + s);
try {
if (s != null) {
if (payload.length > 0) {
_log.debug("Disconnect packet had "
_log.debug(getName() + ": Disconnect packet had "
+ payload.length + " bytes");
}
if (s.getRemoteID(false) == null) {
@ -207,7 +241,7 @@ public class I2PSocketManager implements I2PSessionListener {
}
return;
} catch (Exception t) {
_log.error("Ignoring error on disconnect for socket " + s, t);
_log.error(getName() + ": Ignoring error on disconnect for socket " + s, t);
}
}
@ -225,12 +259,12 @@ public class I2PSocketManager implements I2PSessionListener {
// packet send outgoing
if (_log.shouldLog(Log.DEBUG))
_log.debug("*Packet send outgoing [" + payload.length + "] for socket " + s);
_log.debug(getName() + ": *Packet send outgoing [" + payload.length + "] for socket " + s);
if (s != null) {
s.queueData(payload);
return;
} else {
_log.error("Null socket with data available");
_log.error(getName() + ": Null socket with data available");
throw new IllegalStateException("Null socket with data available");
}
}
@ -258,7 +292,7 @@ public class I2PSocketManager implements I2PSessionListener {
s.setRemoteID(id);
}
}
_log.debug("*Syn! for socket " + s);
_log.debug(getName() + ": *Syn! for socket " + s);
if (!acceptConnections) {
// The app did not instantiate an I2PServerSocket
@ -268,10 +302,11 @@ public class I2PSocketManager implements I2PSessionListener {
replySentOk = _session.sendMessage(d, packet);
}
if (!replySentOk) {
_log.error("Error sending close to " + d.calculateHash().toBase64()
_log.error(getName() + ": Error sending close to " + d.calculateHash().toBase64()
+ " in response to a new con message",
new Exception("Failed creation"));
}
_context.statManager().addRateData("streaming.nackSent", 1, 1);
return;
}
@ -282,10 +317,11 @@ public class I2PSocketManager implements I2PSessionListener {
replySentOk = _session.sendMessage(d, packet);
if (!replySentOk) {
if (_log.shouldLog(Log.WARN))
_log.warn("Error sending reply to " + d.calculateHash().toBase64()
_log.warn(getName() + ": Error sending reply to " + d.calculateHash().toBase64()
+ " in response to a new con message for socket " + s,
new Exception("Failed creation"));
s.internalClose();
_context.statManager().addRateData("streaming.ackSendFailed", 1, 1);
}
} else {
// timed out or serverSocket closed
@ -293,9 +329,10 @@ 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 for socket " + s);
_log.warn(getName() + ": Error sending NACK for session creation for socket " + s);
}
s.internalClose();
_context.statManager().addRateData("streaming,nackSent", 1, 1);
}
return;
}
@ -314,7 +351,7 @@ public class I2PSocketManager implements I2PSessionListener {
}
}
_log.debug("*Disconnect incoming for socket " + s);
_log.debug(getName() + ": *Disconnect incoming for socket " + s);
try {
if (payload.length == 0 && s != null) {
@ -322,13 +359,13 @@ public class I2PSocketManager implements I2PSessionListener {
return;
} else {
if ( (payload.length > 0) && (_log.shouldLog(Log.ERROR)) )
_log.error("Disconnect packet had " + payload.length + " bytes");
_log.error(getName() + ": Disconnect packet had " + payload.length + " bytes");
if (s != null)
s.internalClose();
return;
}
} catch (Exception t) {
_log.error("Ignoring error on disconnect", t);
_log.error(getName() + ": Ignoring error on disconnect", t);
return;
}
}
@ -346,13 +383,13 @@ public class I2PSocketManager implements I2PSessionListener {
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("*Packet send incoming [" + payload.length + "] for socket " + s);
_log.debug(getName() + ": *Packet send incoming [" + payload.length + "] for socket " + s);
if (s != null) {
s.queueData(payload);
return;
} else {
_log.info("Null socket with data available");
_log.info(getName() + ": Null socket with data available");
throw new IllegalStateException("Null socket with data available");
}
}
@ -362,7 +399,7 @@ public class I2PSocketManager implements I2PSessionListener {
*
*/
private void handleUnknown(int type, String id, byte payload[]) {
_log.error("\n\n=============== Unknown packet! " + "============"
_log.error(getName() + ": \n\n=============== Unknown packet! " + "============"
+ "\nType: " + (int) type
+ "\nID: " + getReadableForm(id)
+ "\nBase64'ed Data: " + Base64.encode(payload)
@ -376,7 +413,7 @@ public class I2PSocketManager implements I2PSessionListener {
}
public void reportAbuse(I2PSession session, int severity) {
_log.error("Abuse reported [" + severity + "]");
_log.error(getName() + ": Abuse reported [" + severity + "]");
}
public void setDefaultOptions(I2PSocketOptions options) {
@ -424,31 +461,37 @@ 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 for socket " + s);
_log.info(getName() + ": Unable to send & receive ack for SYN packet for socket " + s);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
_context.statManager().addRateData("streaming.synNoAck", 1, 1);
throw new I2PException("Error sending through I2P network");
}
remoteID = s.getRemoteID(true, options.getConnectTimeout());
if (remoteID == null)
if (remoteID == null) {
_context.statManager().addRateData("streaming.nackReceived", 1, 1);
throw new ConnectException("Connection refused by peer for socket " + s);
if ("".equals(remoteID))
}
if ("".equals(remoteID)) {
_context.statManager().addRateData("streaming.synNoAck", 1, 1);
throw new NoRouteToHostException("Unable to reach peer for socket " + s);
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("TIMING: s given out for remoteID "
_log.debug(getName() + ": TIMING: s given out for 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 "
_log.error(getName() + ": Timeout waiting for ack from syn for id "
+ getReadableForm(lcID) + " for socket " + s, ioe);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
s.internalClose();
_context.statManager().addRateData("streaming.synNoAck", 1, 1);
throw new InterruptedIOException("Timeout waiting for ack");
} catch (ConnectException ex) {
s.internalClose();
@ -458,7 +501,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) + " for socket " + s, ex);
_log.error(getName() + ": Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
@ -466,7 +509,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) + " for socket " + s, ex);
_log.info(getName() + ": Error sending syn on id " + getReadableForm(lcID) + " for socket " + s, ex);
synchronized (lock) {
_outSockets.remove(s.getLocalID());
}
@ -474,7 +517,7 @@ public class I2PSocketManager implements I2PSessionListener {
throw ex;
} catch (Exception e) {
s.internalClose();
_log.error("Unhandled error connecting", e);
_log.error(getName() + ": Unhandled error connecting", e);
throw new ConnectException("Unhandled error connecting: " + e.getMessage());
}
}
@ -515,7 +558,7 @@ public class I2PSocketManager implements I2PSessionListener {
id = (String)iter.next();
sock = (I2PSocketImpl)_inSockets.get(id);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Closing inSocket \""
_log.debug(getName() + ": Closing inSocket \""
+ getReadableForm(sock.getLocalID()) + "\"");
sock.internalClose();
}
@ -525,13 +568,13 @@ public class I2PSocketManager implements I2PSessionListener {
id = (String)iter.next();
sock = (I2PSocketImpl)_outSockets.get(id);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Closing outSocket \""
_log.debug(getName() + ": Closing outSocket \""
+ getReadableForm(sock.getLocalID()) + "\"");
sock.internalClose();
}
}
_log.debug("Waiting for all open sockets to really close...");
_log.debug(getName() + ": Waiting for all open sockets to really close...");
synchronized (lock) {
while ((_inSockets.size() != 0) || (_outSockets.size() != 0)) {
try {
@ -541,11 +584,11 @@ public class I2PSocketManager implements I2PSessionListener {
}
try {
_log.debug("Destroying I2P session...");
_log.debug(getName() + ": Destroying I2P session...");
_session.destroySession();
_log.debug("I2P session destroyed");
_log.debug(getName() + ": I2P session destroyed");
} catch (I2PSessionException e) {
_log.error("Error destroying I2P session", e);
_log.error(getName() + ": Error destroying I2P session", e);
}
}
@ -571,21 +614,47 @@ public class I2PSocketManager implements I2PSessionListener {
try {
return _session.sendMessage(peer, new byte[] { (byte) CHAFF});
} catch (I2PException ex) {
_log.error("I2PException:", ex);
_log.error(getName() + ": I2PException:", ex);
return false;
}
}
public void removeSocket(I2PSocketImpl sock) {
synchronized (lock) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Removing socket \"" + getReadableForm(sock.getLocalID()) + "\" [" + sock + "]");
_inSockets.remove(sock.getLocalID());
_outSockets.remove(sock.getLocalID());
lock.notify();
}
long now = _context.clock().now();
long lifetime = now - sock.getCreatedOn();
long timeSinceClose = now - sock.getClosedOn();
long sent = sock.getBytesSent();
long recv = sock.getBytesReceived();
if (_log.shouldLog(Log.DEBUG)) {
_log.debug(getName() + ": Removing socket \"" + getReadableForm(sock.getLocalID()) + "\" [" + sock
+ ", send: " + sent + ", recv: " + recv
+ ", lifetime: " + lifetime + "ms, time since close: " + timeSinceClose + ")]",
new Exception("removeSocket called"));
}
_context.statManager().addRateData("streaming.lifetime", lifetime, lifetime);
_context.statManager().addRateData("streaming.sent", sent, lifetime);
_context.statManager().addRateData("streaming.received", recv, lifetime);
if (sent > recv) {
_context.statManager().addRateData("streaming.transferBalance", 1, lifetime);
} else if (recv > sent) {
_context.statManager().addRateData("streaming.transferBalance", -1, lifetime);
} else {
// noop
}
}
public String getName() { return _name; }
public void setName(String name) { _name = name; }
public static String getReadableForm(String id) {
if (id == null) return "(null)";
if (id.length() != 3) return "Bogus";

View File

@ -9,13 +9,13 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="compileGUI" depends="builddep">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac debug="true" destdir="./build/obj">
<javac debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj">
<src path="src/" />
<classpath path="../../../core/java/build/i2p.jar" />
<classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
</target>
<target name="jar" depends="compile">
<war destfile="./build/phttprelay.war" webxml="web.xml">

View File

@ -3,7 +3,7 @@
#
#
# Your operating system
# Your operating environment
#
OS = CYGWIN

View File

@ -0,0 +1,63 @@
#
# This Makefile is compatible with GNU Make (gmake) and should work on FreeBSD
#
#
# Your operating system
#
OS = FREEBSD
#
# 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
#
# 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

@ -1,3 +1,8 @@
v1.20 2004-07-11
* Ported to FreeBSD (Makefile.freebsd)
* Full winsock compatibility - all Windows functions now return appropriate
error strings
v1.15 2004-06-23
* Added a new example program, warhammer-dgram (use with caution)
* Fixed some fatal bugs in datagram handling

View File

@ -34,7 +34,7 @@
/*
* Operating system
*/
#define FREEBSD 0 // FreeBSD (untested)
#define FREEBSD 0 // FreeBSD
#define MINGW 1 // Windows native (Mingw)
#define LINUX 2 // Linux
#define CYGWIN 3 // Cygwin
@ -44,6 +44,7 @@
#define NO_GETHOSTBYNAME2
#define NO_INET_ATON /* implies NO_INET_PTON */
#define NO_INET_NTOP
#define NO_SSIZE_T
#define NO_STRL
#define NO_Z_FORMAT
#define WINSOCK
@ -82,9 +83,10 @@
#include <winsock.h>
#else
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#endif
#include <assert.h>
#include <errno.h>
@ -112,10 +114,12 @@
*/
#ifdef WINSOCK
typedef SOCKET socket_t;
typedef signed long ssize_t;
#else
typedef int socket_t;
#endif
#ifdef NO_SSIZE_T
typedef signed long ssize_t;
#endif
/*
* Prints out the file name, line number, and function name before log message

View File

@ -86,7 +86,7 @@ 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);
extern const char *sam_strerror(samerr_t code);
/* SAM controls - callbacks */
extern void (*sam_diedback)(void);
extern void (*sam_logback)(char *str);

View File

@ -41,6 +41,11 @@ static samerr_t sam_session_create(const char *destname, sam_conn_t style,
uint_t tunneldepth);
static bool sam_socket_connect(const char *host, uint16_t port);
static bool sam_socket_resolve(const char *hostname, char *ipaddr);
#ifdef WINSOCK
static samerr_t sam_winsock_cleanup(void);
static samerr_t sam_winsock_startup(void);
static const char *sam_winsock_strerror(int code);
#endif
static ssize_t sam_write(const void *buf, size_t n);
/*
@ -80,18 +85,25 @@ bool sam_close(void)
return true;
#ifdef WINSOCK
if (closesocket(samd) == 0) {
samd_connected = false;
if (closesocket(samd) == SOCKET_ERROR) {
SAMLOG("Failed closing the SAM connection (%s)",
sam_winsock_strerror(WSAGetLastError()));
return false;
}
samd_connected = false;
if (sam_winsock_cleanup() == SAM_OK)
return true;
else
return false;
#else
if (close(samd) == 0) {
samd_connected = false;
return true;
#endif
} else {
SAMLOG("Failed closing the SAM connection (%s)", strerror(errno));
return false;
}
#endif
}
/*
@ -132,28 +144,19 @@ samerr_t sam_connect(const char *samhost, uint16_t samport,
}
#ifdef WINSOCK
/*
* Is Windows retarded or what?
*/
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
SAMLOGS("WSAStartup() failed");
return SAM_SOCKET_ERROR;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1 ) {
SAMLOGS("Bad WinSock version");
return SAM_SOCKET_ERROR;
}
rc = sam_winsock_startup();
if (rc != SAM_OK)
return rc;
#endif
if (!sam_socket_connect(samhost, samport)) {
#ifdef WINSOCK
SAMLOG("Couldn't connect to SAM at %s:%u (%s)",
samhost, samport, sam_winsock_strerror(WSAGetLastError()));
#else
SAMLOG("Couldn't connect to SAM at %s:%u (%s)",
samhost, samport, strerror(errno));
#endif
SAMLOGS("Is your I2P router running?");
return SAM_SOCKET_ERROR;
}
@ -186,7 +189,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
#ifdef NO_Z_FORMAT
SAMLOG("Invalid data send size (%u bytes)", size);
#else
SAMLOG("Invalid data send size (%z bytes)", size);
SAMLOG("Invalid data send size (%dz bytes)", size);
#endif
return SAM_TOO_BIG;
}
@ -194,7 +197,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%u\n",
dest, size);
#else
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%z\n",
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%dz\n",
dest, size);
#endif
sam_write(cmd, strlen(cmd));
@ -540,7 +543,12 @@ static ssize_t sam_read1(char *buf, size_t n)
if (errno == EINTR) /* see Unix Network Pgming vol 1, Sec. 5.9 */
continue;
else {
#ifdef WINSOCK
SAMLOG("recv() failed: %s",
sam_winsock_strerror(WSAGetLastError()));
#else
SAMLOG("recv() failed: %s", strerror(errno));
#endif
sam_close();
sam_diedback();
return -1;
@ -600,7 +608,12 @@ static ssize_t sam_read2(void *buf, size_t n)
if (errno == EINTR) /* see Unix Network Pgming vol 1, Sec. 5.9 */
continue;
else {
#ifdef WINSOCK
SAMLOG("recv() failed: %s",
sam_winsock_strerror(WSAGetLastError()));
#else
SAMLOG("recv() failed: %s", strerror(errno));
#endif
sam_close();
sam_diedback();
return -1;
@ -648,7 +661,11 @@ static bool sam_readable(void)
else if (rc > 0)
return true;
else {
#ifdef WINSOCK
SAMLOG("select() failed: %s", sam_winsock_strerror(WSAGetLastError()));
#else
SAMLOG("select() failed: %s", strerror(errno));
#endif
return false;
}
}
@ -781,11 +798,15 @@ bool sam_socket_connect(const char *host, uint16_t port)
samd = socket(AF_INET, SOCK_STREAM, 0);
#ifdef WINSOCK
if (samd == INVALID_SOCKET)
if (samd == INVALID_SOCKET) {
SAMLOG("socket() failed: %s", sam_winsock_strerror(WSAGetLastError()));
return false;
}
#else
if (samd == -1)
if (samd == -1) {
SAMLOG("socket() failed: %s", strerror(errno));
return false;
}
#endif
memset(&hostaddr, 0, sizeof hostaddr);
hostaddr.sin_family = AF_INET;
@ -805,8 +826,15 @@ bool sam_socket_connect(const char *host, uint16_t port)
} else if (rc == -1)
return false;
if (connect(samd, (struct sockaddr *)&hostaddr, sizeof hostaddr) == -1)
rc = connect(samd, (struct sockaddr *)&hostaddr, sizeof hostaddr);
if (rc == -1) {
#ifdef WINSOCK
SAMLOG("connect() failed: %s", sam_winsock_strerror(WSAGetLastError()));
#else
SAMLOG("connect() failed: %s", strerror(errno));
#endif
return false;
}
samd_connected = true;
return true;
@ -832,16 +860,21 @@ retry:
h = gethostbyname2(hostname, AF_INET);
#endif
if (h == NULL) {
if (h_errno == TRY_AGAIN) {
#ifdef WINSOCK
if (WSAGetLastError() == WSATRY_AGAIN) {
Sleep(1000);
#else
if (h_errno == TRY_AGAIN) {
sleep(1);
#endif
goto retry;
} else {
SAMLOG("DNS resolution failed for %s", hostname);
#ifdef WINSOCK
WSASetLastError(WSAHOST_NOT_FOUND);
#else
errno = ENOENT;
#endif
return false;
}
}
@ -849,6 +882,7 @@ retry:
#ifdef NO_INET_NTOP
char *tmp;
tmp = inet_ntoa(a);
assert(tmp != NULL);
strlcpy(ipaddr, tmp, INET_ADDRSTRLEN); /* inet_ntoa() was very poorly designed */
return true;
#else
@ -923,7 +957,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
SAMLOG("Invalid data send size (%u bytes) for stream %d",
size, stream_id);
#else
SAMLOG("Invalid data send size (%z bytes) for stream %d",
SAMLOG("Invalid data send size (%dz bytes) for stream %d",
size, stream_id);
#endif
return SAM_TOO_BIG;
@ -937,7 +971,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
stream_id, size);
#endif
#else
snprintf(cmd, sizeof cmd, "STREAM SEND ID=%d SIZE=%z\n",
snprintf(cmd, sizeof cmd, "STREAM SEND ID=%d SIZE=%dz\n",
stream_id, size);
#endif
sam_write(cmd, strlen(cmd));
@ -953,7 +987,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
*
* Returns: error string
*/
char *sam_strerror(samerr_t code)
const char *sam_strerror(samerr_t code)
{
switch (code) {
case SAM_OK: /* Operation completed succesfully */
@ -994,6 +1028,177 @@ char *sam_strerror(samerr_t code)
}
}
#ifdef WINSOCK
/*
* Unloads the Winsock network subsystem
*
* Returns: SAM error code
*/
samerr_t sam_winsock_cleanup(void)
{
if (WSACleanup() == SOCKET_ERROR) {
SAMLOG("WSACleanup() failed: %s",
sam_winsock_strerror(WSAGetLastError()));
return SAM_SOCKET_ERROR;
}
return SAM_OK;
}
/*
* Loads the Winsock network sucksystem
*
* Returns: SAM error code
*/
samerr_t sam_winsock_startup(void)
{
/*
* Is Windows retarded or what?
*/
WORD wVersionRequested;
WSADATA wsaData;
int rc;
wVersionRequested = MAKEWORD(2, 2);
rc = WSAStartup(wVersionRequested, &wsaData);
if (rc != 0) {
SAMLOG("WSAStartup() failed: %s", sam_winsock_strerror(rc));
return SAM_SOCKET_ERROR;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
SAMLOGS("Bad Winsock version");
sam_winsock_cleanup();
return SAM_SOCKET_ERROR;
}
return SAM_OK;
}
/*
* Apparently Winsock does not have a strerror() equivalent for its functions
*
* code - code from WSAGetLastError()
*
* Returns: error string (from http://msdn.microsoft.com/library/default.asp?
* url=/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp)
*/
const char *sam_winsock_strerror(int code)
{
switch (code) {
case WSAEINTR:
return "Interrupted function call";
case WSAEACCES: // yes, that is the correct spelling
return "Permission denied";
case WSAEFAULT:
return "Bad address";
case WSAEINVAL:
return "Invalid argument";
case WSAEMFILE:
return "Too many open files";
case WSAEWOULDBLOCK:
return "Resource temporarily unavailable";
case WSAEINPROGRESS:
return "Operation now in progress";
case WSAEALREADY:
return "Operation already in progress";
case WSAENOTSOCK:
return "Socket operations on nonsocket";
case WSAEDESTADDRREQ:
return "Destination address required";
case WSAEMSGSIZE:
return "Message too long";
case WSAEPROTOTYPE:
return "Protocol wrong type for socket";
case WSAENOPROTOOPT:
return "Bad protocol option";
case WSAEPROTONOSUPPORT:
return "Protocol not supported";
case WSAESOCKTNOSUPPORT:
return "Socket type not supported";
case WSAEOPNOTSUPP:
return "Operation not supported";
case WSAEPFNOSUPPORT:
return "Protocol family not supported";
case WSAEAFNOSUPPORT:
return "Address family not supported by protocol family";
case WSAEADDRINUSE:
return "Address already in use";
case WSAEADDRNOTAVAIL:
return "Cannot assign requested address";
case WSAENETDOWN:
return "Network is down";
case WSAENETUNREACH:
return "Network is unreachable";
case WSAENETRESET:
return "Network dropped connection on reset";
case WSAECONNABORTED:
return "Software caused connection abort";
case WSAECONNRESET:
return "Connection reset by peer";
case WSAENOBUFS:
return "No buffer space available";
case WSAEISCONN:
return "Socket is already connected";
case WSAENOTCONN:
return "Socket is not connected";
case WSAESHUTDOWN:
return "Cannot send after socket shutdown";
case WSAETIMEDOUT:
return "Connection timed out";
case WSAECONNREFUSED:
return "Connection refused";
case WSAEHOSTDOWN:
return "Host is down";
case WSAEHOSTUNREACH:
return "No route to host";
case WSAEPROCLIM:
return "Too many processes";
case WSASYSNOTREADY:
return "Network subsystem is unavailable";
case WSAVERNOTSUPPORTED:
return "Winsock.dll version out of range";
case WSANOTINITIALISED:
return "Successful WSAStartup not yet performed";
case WSAEDISCON:
return "Graceful shutdown in progress";
case WSATYPE_NOT_FOUND:
return "Class type not found";
case WSAHOST_NOT_FOUND:
return "Host not found";
case WSATRY_AGAIN:
return "Nonauthoritative host not found";
case WSANO_RECOVERY:
return "This is a nonrecoverable error";
case WSANO_DATA:
return "Valid name, no data record of requested type";
/* None of this shit compiles under Mingw - who knows why...
case WSA_INVALID_HANDLE:
return "Specified event object handle is invalid";
case WSA_INVALID_PARAMETER:
return "One or more parameters are invalid";
case WSA_IO_INCOMPLETE:
return "Overlapped I/O event object not in signaled state";
case WSA_IO_PENDING:
return "Overlapped operations will complete later";
case WSA_NOT_ENOUGH_MEMORY:
return "Insufficient memory available";
case WSA_OPERATION_ABORTED:
return "Overlapped operation aborted";
case WSAINVALIDPROCTABLE:
return "Invalid procedure table from service provider";
case WSAINVALIDPROVIDER:
return "Invalid service provider version number";
case WSAPROVIDERFAILEDINIT:
return "Unable to initialize a service provider";
*/
case WSASYSCALLFAILURE:
return "System call failure";
default:
return "Unknown error";
}
}
#endif
/*
* Sends `n' bytes to the SAM host
*
@ -1031,7 +1236,12 @@ static ssize_t sam_write(const void *buf, size_t n)
if (errno == EINTR) /* see Unix Network Pgming vol 1, Sec. 5.9 */
continue;
else {
#ifdef WINSOCK
SAMLOG("send() failed: %s",
sam_winsock_strerror(WSAGetLastError()));
#else
SAMLOG("send() failed: %s", strerror(errno));
#endif
sam_close();
sam_diedback();
return -1;

View File

@ -11,7 +11,7 @@
<mkdir dir="./build/obj" />
<javac
srcdir="./src"
debug="true"
debug="true" deprecation="on" source="1.3" target="1.3"
destdir="./build/obj"
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
</target>

View File

@ -7,6 +7,7 @@ import java.io.OutputStream;
import java.net.Socket;
import net.i2p.util.Log;
import net.i2p.util.Clock;
public class TestCreateSessionRaw {
private static Log _log = new Log(TestCreateSessionRaw.class);
@ -15,6 +16,7 @@ public class TestCreateSessionRaw {
testTransient(samHost, samPort, conOptions);
testNewDest(samHost, samPort, conOptions);
testOldDest(samHost, samPort, conOptions);
testFast(samHost, samPort, conOptions);
}
private static void testTransient(String host, int port, String conOptions) {
@ -36,21 +38,34 @@ public class TestCreateSessionRaw {
_log.debug("\n\nTest of subsequent contact complete\n\n");
}
private static void testFast(String host, int port, String conOptions) {
String destName = "Alice" + Math.random();
long totalTime = 0;
for (int i = 0; i < 10; i++) {
long before = Clock.getInstance().now();
testDest(host, port, conOptions, destName);
long after = Clock.getInstance().now();
long difference = after-before;
_log.debug("Time to test destination: " + difference + " \n\n");
totalTime += difference;
}
_log.debug("\n\nTime to test fast reconnection: " + totalTime + " over 10 runs");
}
private static void testDest(String host, int port, String conOptions, String destName) {
_log.info("\n\nTesting creating a new destination (should come back with 'SESSION STATUS RESULT=OK DESTINATION=someName)\n\n\n");
//_log.info("\n\nTesting creating a new destination (should come back with 'SESSION STATUS RESULT=OK DESTINATION=someName)\n\n\n");
try {
Socket s = new Socket(host, port);
OutputStream out = s.getOutputStream();
out.write("HELLO VERSION MIN=1.0 MAX=1.0\n".getBytes());
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = reader.readLine();
_log.debug("line read for valid version: " + line);
//_log.debug("line read for valid version: " + line);
String req = "SESSION CREATE STYLE=RAW DESTINATION=" + destName + " " + conOptions + "\n";
out.write(req.getBytes());
line = reader.readLine();
_log.info("Response to creating the session with destination " + destName + ": " + line);
_log.debug("The above should contain SESSION STATUS RESULT=OK\n\n\n");
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
_log.debug("The above should contain SESSION STATUS RESULT=OK");
s.close();
} catch (Exception e) {
_log.error("Error testing for valid version", e);
@ -60,7 +75,7 @@ public class TestCreateSessionRaw {
public static void main(String args[]) {
// "i2cp.tcp.host=www.i2p.net i2cp.tcp.port=7765";
// "i2cp.tcp.host=localhost i2cp.tcp.port=7654 tunnels.inboundDepth=0";
String conOptions = "i2cp.tcp.host=dev.i2p.net i2cp.tcp.port=7002 tunnels.inboundDepth=0";
String conOptions = "i2cp.tcp.host=dev.i2p.net i2cp.tcp.port=7002 tunnels.depthInbound=0 tunnels.depthOutbound=0";
if (args.length > 0) {
conOptions = "";
for (int i = 0; i < args.length; i++)

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="**/*.java" classpath="../../../core/java/build/i2p.jar" />
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" includes="**/*.java" classpath="../../../core/java/build/i2p.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/timestamper.jar" basedir="./build/obj" includes="**/*.class">

View File

@ -2,15 +2,12 @@
#include <gmp.h>
#include "jbigi.h"
/********/
//function prototypes
//FIXME: should these go into jbigi.h? -- ughabugha
/******** prototypes */
void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue);
void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue);
/********/
/******** nativeModPow() */
/*
* Class: net_i2p_util_NativeBigInteger
* Method: nativeModPow
@ -27,47 +24,41 @@ void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue);
JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPow
(JNIEnv* env, jclass cls, jbyteArray jbase, jbyteArray jexp, jbyteArray jmod) {
// convert base, exponent, modulus into the format libgmp understands
// call libgmp's modPow
// convert libgmp's result into a big endian twos complement number
/* 1) Convert base, exponent, modulus into the format libgmp understands
* 2) Call libgmp's modPow.
* 3) Convert libgmp's result into a big endian twos complement number.
*
* Luckily we can use GMP's mpz_import() and mpz_export() functions.
*/
mpz_t mbase;
mpz_t mexp;
mpz_t mmod;
//mpz_t mresult;
jbyteArray jresult;
convert_j2mp(env, jbase, &mbase);
convert_j2mp(env, jexp, &mexp);
convert_j2mp(env, jmod, &mmod);
//gmp_printf("mbase =%Zd\n", mbase);
//gmp_printf("mexp =%Zd\n", mexp);
//gmp_printf("mmod =%Zd\n", mmod);
/* Perform the actual powmod. We use mmod for the result because it is
* always at least as big as the result.
*/
mpz_powm(mmod, mbase, mexp, mmod);
//we use mod for the result because it is always at least as big
//gmp_printf("mresult=%Zd\n", mmod);
convert_mp2j(env, mmod, &jresult);
//convert_j2mp(env, jresult, &mresult);
//gmp_printf("", mpz_cmp(mmod, mresult) == 0 ? "true" : "false");
mpz_clear(mbase);
mpz_clear(mexp);
mpz_clear(mmod);
//mpz_clear(mresult);
return jresult;
}
/********/
/******** convert_j2mp() */
/*
* Initializes the GMP value with enough preallocated size, and converts the
* Java value into the GMP value. The value that mvalue is pointint to
* should be uninitialized
* Java value into the GMP value. The value that mvalue points to should be
* uninitialized
*/
void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue)
@ -81,18 +72,29 @@ void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue)
mpz_init2(*mvalue, sizeof(jbyte) * 8 * size); //preallocate the size
/*
* void mpz_import (mpz_t rop, size_t count, int order, int size, int endian, size_t nails, const void *op)
* order = 1 - order can be 1 for most significant word first or -1 for least significant first.
* endian = 1 - Within each word endian can be 1 for most significant byte first, -1 for least significant first
* nails = 0 - The most significant nails bits of each word are skipped, this can be 0 to use the full words
* void mpz_import(
* mpz_t rop, size_t count, int order, int size, int endian,
* size_t nails, const void *op);
*
* order = 1
* order can be 1 for most significant word first or -1 for least
* significant first.
* endian = 1
* Within each word endian can be 1 for most significant byte first,
* -1 for least significant first.
* nails = 0
* The most significant nails bits of each word are skipped, this can
* be 0 to use the full words.
*/
mpz_import(*mvalue, size, 1, sizeof(jbyte), 1, 0, (void*)jbuffer);
(*env)->ReleaseByteArrayElements(env, jvalue, jbuffer, JNI_ABORT);
}
/********/
/******** convert_mp2j() */
/*
* Converts the GMP value into the Java value; Doesn't do anything else.
* Pads the resulting jbyte array with 0, so the twos complement value is always
* positive.
*/
void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue)
@ -103,21 +105,25 @@ void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue)
copy = JNI_FALSE;
size = (mpz_sizeinbase(mvalue, 2) + 7) / 8 + sizeof(jbyte); //+7 => ceil division
/* sizeinbase() + 7 => Ceil division */
size = (mpz_sizeinbase(mvalue, 2) + 7) / 8 + sizeof(jbyte);
*jvalue = (*env)->NewByteArray(env, size);
buffer = (*env)->GetByteArrayElements(env, *jvalue, &copy);
buffer[0] = 0;
buffer[0] = 0x00;
/*
* void *mpz_export (void *rop, size_t *count, int order, int size, int endian, size_t nails, mpz_t op)
* void *mpz_export(
* void *rop, size_t *count, int order, int size,
* int endian, size_t nails, mpz_t op);
*/
mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
/* mode has (supposedly) no effect if elems is not a copy of the
* elements in array
*/
(*env)->ReleaseByteArrayElements(env, *jvalue, buffer, 0);
//mode has (supposedly) no effect if elems is not a copy of the elements in array
}
/********/
/******** eof */

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src:./test" debug="true" destdir="./build/obj" />
<javac srcdir="./src:./test" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/i2p.jar" basedir="./build/obj" includes="**/*.class" />

View File

@ -14,8 +14,8 @@ package net.i2p;
*
*/
public class CoreVersion {
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 final static String ID = "$Revision: 1.11 $ $Date: 2004/07/11 13:57:02 $";
public final static String VERSION = "0.3.2.2";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);

View File

@ -135,7 +135,7 @@ class ConnectionRunner implements I2CPMessageReader.I2CPMessageEventListener {
}
/**
* Recieve notifiation that the peer disconnected
* Receive notifiation that the peer disconnected
*/
public void disconnected(I2CPMessageReader reader) {
_log.info("Disconnected");
@ -146,7 +146,7 @@ class ConnectionRunner implements I2CPMessageReader.I2CPMessageEventListener {
*
*/
public void messageReceived(I2CPMessageReader reader, I2CPMessage message) {
_log.info("Message recieved: \n" + message);
_log.info("Message received: \n" + message);
switch (message.getType()) {
case CreateSessionMessage.MESSAGE_TYPE:
handleCreateSession(reader, (CreateSessionMessage) message);
@ -240,7 +240,7 @@ class ConnectionRunner implements I2CPMessageReader.I2CPMessageEventListener {
Destination dest = message.getDestination();
MessageId id = new MessageId();
id.setMessageId(getNextMessageId());
_log.debug("** Recieving message [" + id.getMessageId() + "] with payload: " + "[" + payload + "]");
_log.debug("** Receiving message [" + id.getMessageId() + "] with payload: " + "[" + payload + "]");
_messages.put(id, payload);
MessageStatusMessage status = new MessageStatusMessage();
status.setMessageId(id);
@ -318,7 +318,7 @@ class ConnectionRunner implements I2CPMessageReader.I2CPMessageEventListener {
*
*/
public void handleReceiveBegin(I2CPMessageReader reader, ReceiveMessageBeginMessage message) {
_log.debug("Handling recieve begin: id = " + message.getMessageId());
_log.debug("Handling receive begin: id = " + message.getMessageId());
MessagePayloadMessage msg = new MessagePayloadMessage();
msg.setMessageId(message.getMessageId());
msg.setSessionId(_sessionId);
@ -344,7 +344,7 @@ class ConnectionRunner implements I2CPMessageReader.I2CPMessageEventListener {
}
/**
* The client told us that the message has been recieved completely. This currently
* The client told us that the message has been received completely. This currently
* does not do any security checking prior to removing the message from the
* pending queue, though it should.
*
@ -392,4 +392,4 @@ class ConnectionRunner implements I2CPMessageReader.I2CPMessageEventListener {
_out.flush();
}
}
}
}

View File

@ -89,7 +89,7 @@ public interface I2PSession {
public void destroySession() throws I2PSessionException;
/**
* Actually connect the session and start recieving/sending messages
* Actually connect the session and start receiving/sending messages
*
*/
public void connect() throws I2PSessionException;
@ -111,4 +111,4 @@ public interface I2PSession {
* Retrieve the signing SigningPrivateKey associated with the Destination
*/
public SigningPrivateKey getPrivateKey();
}
}

View File

@ -419,17 +419,25 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
void sendMessage(I2CPMessage message) throws I2PSessionException {
if (isClosed()) throw new I2PSessionException("Already closed");
long beforeSync = _context.clock().now();
long inSync = 0;
try {
synchronized (_out) {
inSync = _context.clock().now();
message.writeMessage(_out);
_out.flush();
}
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Message written out and flushed");
} catch (I2CPMessageException ime) {
throw new I2PSessionException(getPrefix() + "Error writing out the message", ime);
} catch (IOException ioe) {
throw new I2PSessionException(getPrefix() + "Error writing out the message", ioe);
}
long afterSync = _context.clock().now();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Message written out and flushed w/ "
+ (inSync-beforeSync) + "ms to sync and "
+ (afterSync-inSync) + "ms to send");;
}
/**

View File

@ -9,8 +9,8 @@ package net.i2p.client;
*
*/
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
@ -62,7 +62,6 @@ class I2PSessionImpl2 extends I2PSessionImpl {
}
public boolean sendMessage(Destination dest, byte[] payload) throws I2PSessionException {
return sendMessage(dest, payload, new SessionKey(), new HashSet(64));
}
@ -137,18 +136,29 @@ class I2PSessionImpl2 extends I2PSessionImpl {
}
}
long beforeSendingSync = _context.clock().now();
long inSendingSync = 0;
synchronized (_sendingStates) {
inSendingSync = _context.clock().now();
_sendingStates.add(state);
}
long afterSendingSync = _context.clock().now();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Adding sending state " + state.getMessageId() + " / "
+ state.getNonce());
+ state.getNonce()
+ " sync took " + (inSendingSync-beforeSendingSync)
+ " add took " + (afterSendingSync-inSendingSync));
_producer.sendMessage(this, dest, nonce, payload, tag, key, sentTags, newKey);
long beforeWaitFor = _context.clock().now();
state.waitFor(MessageStatusMessage.STATUS_SEND_ACCEPTED,
_context.clock().now() + getTimeout());
long afterWaitFor = _context.clock().now();
long inRemovingSync = 0;
synchronized (_sendingStates) {
inRemovingSync = _context.clock().now();
_sendingStates.remove(state);
}
long afterRemovingSync = _context.clock().now();
boolean found = state.received(MessageStatusMessage.STATUS_SEND_ACCEPTED);
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "After waitFor sending state " + state.getMessageId().getMessageId()
@ -206,22 +216,34 @@ class I2PSessionImpl2 extends I2PSessionImpl {
}
}
long beforeSendingSync = _context.clock().now();
long inSendingSync = 0;
synchronized (_sendingStates) {
inSendingSync = _context.clock().now();
_sendingStates.add(state);
}
long afterSendingSync = _context.clock().now();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Adding sending state " + state.getMessageId() + " / "
+ state.getNonce());
+ state.getNonce()
+ " sync took " + (inSendingSync-beforeSendingSync)
+ " add took " + (afterSendingSync-inSendingSync));
_producer.sendMessage(this, dest, nonce, payload, tag, key, sentTags, newKey);
long beforeWaitFor = _context.clock().now();
if (isGuaranteed())
state.waitFor(MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS,
_context.clock().now() + SEND_TIMEOUT);
else
state.waitFor(MessageStatusMessage.STATUS_SEND_ACCEPTED,
_context.clock().now() + SEND_TIMEOUT);
long afterWaitFor = _context.clock().now();
long inRemovingSync = 0;
synchronized (_sendingStates) {
inRemovingSync = _context.clock().now();
_sendingStates.remove(state);
}
long afterRemovingSync = _context.clock().now();
boolean found = state.received(MessageStatusMessage.STATUS_SEND_GUARANTEED_SUCCESS);
boolean accepted = state.received(MessageStatusMessage.STATUS_SEND_ACCEPTED);
@ -229,7 +251,12 @@ class I2PSessionImpl2 extends I2PSessionImpl {
if (_log.shouldLog(Log.CRIT))
_log.log(Log.CRIT, getPrefix() + "State with nonce " + state.getNonce()
+ " was not accepted? (no messageId!! found=" + found
+ " msgId=" + state.getMessageId() + ")");
+ " msgId=" + state.getMessageId()
+ ", sendingSync=" + (afterSendingSync-beforeSendingSync)
+ ", sendMessage=" + (beforeWaitFor-afterSendingSync)
+ ", waitFor=" + (afterWaitFor-beforeWaitFor)
+ ", removingSync=" + (afterRemovingSync-afterWaitFor)
+ ")");
//if (true)
// throw new OutOfMemoryError("not really an OOM, but more of jr fucking shit up");
nackTags(state);
@ -280,7 +307,10 @@ class I2PSessionImpl2 extends I2PSessionImpl {
public void receiveStatus(int msgId, long nonce, int status) {
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Received status " + status + " for msgId " + msgId + " / " + nonce);
MessageState state = null;
long beforeSync = _context.clock().now();
long inSync = 0;
synchronized (_sendingStates) {
inSync = _context.clock().now();
for (Iterator iter = _sendingStates.iterator(); iter.hasNext();) {
state = (MessageState) iter.next();
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "State " + state.getMessageId() + " / " + state.getNonce());
@ -296,7 +326,12 @@ class I2PSessionImpl2 extends I2PSessionImpl {
}
}
}
long afterSync = _context.clock().now();
if (_log.shouldLog(Log.DEBUG))
_log.debug("receiveStatus(" + msgId + ", " + nonce + ", " + status+ "): sync: "
+ (inSync-beforeSync) + "ms, check: " + (afterSync-inSync));
if (state != null) {
if (state.getMessageId() == null) {
MessageId id = new MessageId();

View File

@ -31,9 +31,13 @@ class MessageState {
private long _created;
private Object _lock = new Object();
private static long __stateId = 0;
private long _stateId;
public MessageState(long nonce, String prefix) {
_stateId = ++__stateId;
_nonce = nonce;
_prefix = prefix;
_prefix = prefix + "[" + _stateId + "]: ";
_id = null;
_receivedStatus = new HashSet();
_cancelled = false;

View File

@ -45,7 +45,11 @@ public class AESEngine {
if ((initializationVector == null) || (payload == null) || (sessionKey == null)
|| (initializationVector.length != 16)) return null;
byte cyphertext[] = new byte[payload.length + (16 - (payload.length % 16))];
byte cyphertext[] = null;
if ((payload.length % 16) == 0)
cyphertext = new byte[payload.length];
else
cyphertext = new byte[payload.length + (16 - (payload.length % 16))];
System.arraycopy(payload, 0, cyphertext, 0, payload.length);
return cyphertext;
}

View File

@ -74,7 +74,8 @@ public class AESInputStream extends FilterInputStream {
if (nval != null) {
return nval.intValue();
} else {
//_log.debug("No byte available. eof? " + _eofFound);
if (_log.shouldLog(Log.DEBUG))
_log.debug("No byte available. eof? " + _eofFound);
if (_eofFound)
return -1;
else {
@ -97,7 +98,8 @@ public class AESInputStream extends FilterInputStream {
dest[i] = (byte) val;
}
}
_log.debug("Read the full buffer of size " + dest.length);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Read the full buffer of size " + dest.length);
return dest.length;
}
@ -133,9 +135,10 @@ public class AESInputStream extends FilterInputStream {
_readyBuf.clear();
_encryptedBuf.reset();
in.close();
_log.debug("Cumulative bytes read from source/decrypted/stripped: " + _cumulativeRead + "/"
+ _cumulativePrepared + "/" + _cumulativePaddingStripped + "] remaining [" + ready + " ready, "
+ encrypted + " still encrypted]");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Cumulative bytes read from source/decrypted/stripped: " + _cumulativeRead + "/"
+ _cumulativePrepared + "/" + _cumulativePaddingStripped + "] remaining [" + ready + " ready, "
+ encrypted + " still encrypted]");
}
public void mark(int readLimit) {
@ -182,15 +185,20 @@ public class AESInputStream extends FilterInputStream {
if (false) return; // true to keep the data for decrypt/display on close
if (_encryptedBuf.size() > 0) {
if (_encryptedBuf.size() >= DECRYPT_SIZE) {
//_log.debug("We have " + _encryptedBuf.size() + " available to decrypt... doing so");
if (_log.shouldLog(Log.DEBUG))
_log.debug("We have " + _encryptedBuf.size() + " available to decrypt... doing so");
decrypt();
//if (_encryptedBuf.size() > 0)
// _log.debug("Bytes left in the encrypted buffer after decrypt: " + _encryptedBuf.size());
if ( (_encryptedBuf.size() > 0) && (_log.shouldLog(Log.DEBUG)) )
_log.debug("Bytes left in the encrypted buffer after decrypt: " + _encryptedBuf.size());
} else {
if (_eofFound) {
//_log.debug("EOF and not enough bytes to decrypt [size = " + _encryptedBuf.size() + " totalCumulative: " + _cumulativeRead + "/"+_cumulativePrepared +"]!");
if (_log.shouldLog(Log.DEBUG))
_log.debug("EOF and not enough bytes to decrypt [size = " + _encryptedBuf.size()
+ " totalCumulative: " + _cumulativeRead + "/"+_cumulativePrepared +"]!");
} else {
//_log.debug("Not enough bytes to decrypt [size = " + _encryptedBuf.size() + " totalCumulative: " + _cumulativeRead + "/"+_cumulativePrepared +"]");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Not enough bytes to decrypt [size = " + _encryptedBuf.size()
+ " totalCumulative: " + _cumulativeRead + "/"+_cumulativePrepared +"]");
}
}
}
@ -217,10 +225,12 @@ public class AESInputStream extends FilterInputStream {
byte nencrypted[] = new byte[encrypted.length - trailing];
System.arraycopy(encrypted, 0, nencrypted, 0, nencrypted.length);
encrypted = nencrypted;
_log.warn("Decrypt got odd segment - " + trailing
+ " bytes pushed back for later decryption - corrupted or slow data stream perhaps?");
if (_log.shouldLog(Log.WARN))
_log.warn("Decrypt got odd segment - " + trailing
+ " bytes pushed back for later decryption - corrupted or slow data stream perhaps?");
} else {
//_log.info(encrypted.length + " bytes makes up " + numBlocks + " blocks to decrypt normally");
if (_log.shouldLog(Log.INFO))
_log.info(encrypted.length + " bytes makes up " + numBlocks + " blocks to decrypt normally");
}
byte block[] = new byte[BLOCK_SIZE];
@ -244,9 +254,7 @@ public class AESInputStream extends FilterInputStream {
int remaining = encrypted.length % BLOCK_SIZE;
if (remaining != 0) {
_encryptedBuf.write(encrypted, encrypted.length - remaining, remaining);
_log
.debug("After pushing "
+ remaining
_log.debug("After pushing " + remaining
+ " bytes back onto the buffer, lets delay 1s our action so we don't fast busy until the net transfers data");
try {
Thread.sleep(1000);
@ -273,13 +281,22 @@ public class AESInputStream extends FilterInputStream {
*/
private int[] stripPadding(byte data[]) throws IOException {
int numPadBytes = (int) data[data.length - 1];
if ((numPadBytes >= data.length) || (numPadBytes <= 0)) throw new IOException("Invalid number of pad bytes");
if ((numPadBytes >= data.length) || (numPadBytes <= 0)) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("stripPadding from block " + DataHelper.toHexString(data) + " (" + data.length + "bytes): "
+ numPadBytes + " is an invalid # of pad bytes");
throw new IOException("Invalid number of pad bytes (" + numPadBytes
+ ") for " + data.length + " bytes");
}
int rv[] = new int[data.length - numPadBytes];
// optional, but a really good idea: verify the padding
if (true) {
for (int i = data.length - numPadBytes; i < data.length; i++) {
if (data[i] != (byte) numPadBytes) { throw new IOException("Incorrect padding on decryption: data[" + i
+ "] = " + data[i] + " not " + numPadBytes); }
if (data[i] != (byte) numPadBytes) {
throw new IOException("Incorrect padding on decryption: data[" + i
+ "] = " + data[i] + " not " + numPadBytes);
}
}
}
for (int i = 0; i < rv.length; i++)

View File

@ -76,8 +76,9 @@ public class AESOutputStream extends FilterOutputStream {
flush();
out.close();
_inBuf.reset();
_log.debug("Cumulative bytes provided to this stream / written out / padded: " + _cumulativeProvided + "/"
+ _cumulativeWritten + "/" + _cumulativePadding);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Cumulative bytes provided to this stream / written out / padded: "
+ _cumulativeProvided + "/" + _cumulativeWritten + "/" + _cumulativePadding);
}
public void flush() throws IOException {
@ -111,6 +112,10 @@ public class AESOutputStream extends FilterOutputStream {
byte data[] = DataHelper.xor(block, _lastBlock);
byte encrypted[] = _context.AESEngine().encrypt(data, _key, _lastBlock);
_cumulativeWritten += encrypted.length;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Padding block " + i + " of " + numBlocks + " with 1 byte. orig= "
+ DataHelper.toHexString(data) + " (size=" + data.length + ") encrypted= "
+ DataHelper.toHexString(encrypted) + " (size=" + encrypted.length + ")");
out.write(encrypted);
System.arraycopy(encrypted, encrypted.length - BLOCK_SIZE, _lastBlock, 0, BLOCK_SIZE);
_cumulativePadding++;
@ -120,6 +125,8 @@ public class AESOutputStream extends FilterOutputStream {
// we need to do non trivial padding
int remainingBytes = src.length - numBlocks * 15;
int paddingBytes = BLOCK_SIZE - remainingBytes;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Padding " + src.length + " with " + paddingBytes + " bytes in " + numBlocks + " blocks");
System.arraycopy(src, numBlocks * 15, block, 0, remainingBytes);
Arrays.fill(block, remainingBytes, BLOCK_SIZE, (byte) paddingBytes);
byte data[] = DataHelper.xor(block, _lastBlock);

View File

@ -1,12 +1,9 @@
package net.i2p.crypto;
import net.i2p.I2PAppContext;
import net.i2p.data.Hash;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.data.SigningPublicKey;
import net.i2p.util.Log;
import net.i2p.util.NativeBigInteger;
/**
* Stub that offers no authentication.

View File

@ -12,14 +12,13 @@ package net.i2p.data;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import net.i2p.util.Log;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.i2p.util.Log;
/**
* Defines the hash as defined by the I2P data structure spec.

View File

@ -27,6 +27,8 @@ public class TunnelId extends DataStructureImpl {
private long _tunnelId;
private int _type;
public static final long MAX_ID_VALUE = (1l<<32l)-1l;
public final static int TYPE_UNSPECIFIED = 0;
public final static int TYPE_INBOUND = 1;
public final static int TYPE_OUTBOUND = 2;

View File

@ -8,18 +8,17 @@ package net.i2p.util;
*
*/
import java.math.BigInteger;
import java.util.Random;
import java.security.SecureRandom;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.URL;
import java.security.SecureRandom;
import java.util.Random;
/**
* <p>BigInteger that takes advantage of the jbigi library for the modPow operation,

View File

@ -1,6 +1,8 @@
; TC's hosts.txt guaranteed freshness
; $Id: hosts.txt,v 1.11 2004/06/09 15:06:17 duck Exp $
; $Id: hosts.txt,v 1.13 2004/07/02 08:31:09 duck Exp $
; changelog:
; (1.40) added nickster2.i2p and irc.nickster.i2p (pointing at iip)
; (1.39) added jdot.i2p
; (1.38) added forum.i2p
; (1.36) added ferret.i2p
; (1.36) added anonynanny.i2p
@ -100,4 +102,7 @@ hypercubus.i2p=F4I0cx7eSRGDfHXEnjq673~8Nxizu3xopKjfwKCyBRqRgQEv241IJ6PXIH7xs1Yhe
anonynanny.i2p=U-xjIR-MQZ7iLKViaaIpfMzOWthI8jSMyougGi6catC4fmBJjkmo18SZ1Vyy1mXZVhXae~Aqgwlvo-3svus9pzmjykY4ejJWwEuIsL5A3Kk2R6y4h96RuRhvMulH4FBO9Mw4GOsRAhfHYA1ifzQYvs7ZbOwwYMgJ0Y8kDBRtgXNSZPBq59VFUCjg9ON1bca7lGFhgTxzihgZF5MksZKuuX7IAJmUqAZziI9cqRQw4aWTaAfKteOnNp~r7vrjHbfUNezW~OLBj69FXZzEY7uBaoBJut42I4JpQ9ms0cgk~15ExdYACxgjyPNJXX-qrKNLIe7OqOIDqaMFtBTEA4TZpR5nVU7uAXC~XkLggoFMMwqm24rXU1VsGTikGaVtwJNEuCd~KI-711fQ2YDKMkzp7ragbzYGJJKdJUwuJQkTgN-LHUrx1Rccqe5Bz-OMkVkC7KvN1367xywXSrKsXijyy1vBY1BiacB8jT83Kq2LcYjFdy467ny63tlhNvuHp79MAAAA
ferret.i2p=P9EUYEBRkuA6R4nqLHrJzcqA64KjOpnQahDeb2SJZdGywI7E70Rf2TzXguryTmNLJb9riDiFouAzsb30FwF0I93Qx8iMq9ADVH6NowUgcXUaBJWoFh6dEnwwCcSbVsn1CvqoEgl-9GA2nm4NSqQv8RU4g3qrr~bfMP-gZLU4lroHb6LqCF3JNz8dege100n994nqxqdUaX1JpxDacq8jG4W5p3bUhlovQNj3cLcHG5K5PVB4jGqjkq-7UHvh0-blHoBhnYLABCe8IM2GAxgGEmS0zjQIXinsUu1wtLVmVMXF6Iy7bVf4~q80ngVNA7M~MVyNzNAocVkgb4bfhAX8WAuAA17XwsG3thWMJFYrWqKKq0hN5cDdbUNYjgx-ue~D~Sm0oJvUGjJVJnPfkbu-mO2bEQvGZaYml7kKF2kxmdmcFWAa-1HKnUXf35kKwYFWx10i8mSmLWhIx~Wvk~RIzNqjqVSy3Nbc6OkfCLvGcTQOtK-5b-BcU8HiZJJH2XOLAAAA
forum.i2p=XaZscxXGaXxuIkZDX87dfN0dcEG1xwSXktDbMX9YBOQ1LWbf0j6Kzde37j8dlPUhUK9kqVRZWpDtP7a2QBRl3aT~t~bYRj5bgTOIf9hTW46iViKdKObR-wPPjej~Px8OSYrXbFv2KUekS4baXcqHS7aJMy4rcbC1hsJm3qcXtut~7VFwEhg9w-HrHhsT5aYtcr4u79HvNvUva38NQ4NJn7vI9OPhPVgb5gxkefgM1tF0QC6QO1b~RADN~BW~X2S-YRPyKKxv6xx9mfqEbl5lVA1nBTaoFsN5ZfLZoJOFIVNpNoXxCrCQhvG2zjS-pJD2NF6g0bCcT4cKBWPYtJenLiK3L6fKJuVJ-og5ootLdJNBXGsO~FSwdabvDUaPDbTKmqS-ibFjmq1C7vEde3TGo3cRZgqG0YZi3S3BpBTYN9kGhYHrThGH69ECViUJnUWlUsWux5FI4pZL5Du7TwDYT0BwnX2kTdZQ8WGSFlflXgVQIh1n0XpElShWrOQPR0jGAAAA
jdot.i2p=yUqfBnnApqi3gcDlh8cafqd6T0Btw2yT8AA97Qtadu~wDbNd4znyrHnitrSCqGNk3KBAq~-Y5wxQ933NMQXyqgxQ-6U-2nNCS6EbH01dJfwCsoa1WayQR9k~LheSW7Vu6L12-STuNP~qhgaquSFOohpRuFEWwEzQ71zVcCpOYfAgkxD1zdIa8Dz-9ZcbPP5Nr4xCq08ls5CCROWyP0EKiB45GxPOfDTZmZxLGGcRly0NoU9uAB441GKJyPtuhrk-XhR~UhlH~BB9kaGfv09saQaEV~KsHOPU3u02O6uweE2EqzJ7oPrVM40L9OHsrrVKLZlUBwoReiwHxSjAZJlZfg4LkXGH~i7cczDaVQFOwBdj3MuzYuMhnnoIZu2I-Kg2J7aLM1vH1piO8-IH9mzItLOVUXS1gExAcflp9lmoXnGzojkn6~so6cL-iXHj7LY~~301o4-JnfqB65B4keZF4v2Fc4TKBnIERcAmx6adVOwjPXLL9nYBQNreoUFVxULsAAAA
irc.nickster.i2p=4xIbFi15l6BFLkKCPDEVcb23aQia4Ry1pQeC5C0RGzqy5IednmnDQqG5l8mDID8vL831rUmCrj~sC537iQiUXlkKFJvdiuI0HEL4c6a7NCYz3cPncc2Uz~gnlG1YOPv-CkxcXSHxxGrv0-HA281a87hrEc7uQ7hBLPybMl6-Z4k-qsyABDdaZwbqEJDWxJKWNfEWfhj2fHSuYB9c6CJgkPektLdMEIxIO4fWgRaIvyr0jt7ObBcB9QhvZAUnP5~iD9gnl~sxfSg~Zi7UW2sB0ewrb63KLZtRDXmnb-Gc3Cn-6oqvqt~YeNXW2OKiEMggkonLJR8RmdTsgMSwbHvXhyp0utqwgIIP7W0if0IIcDg7t38JzSo67uKs3m9aBf1kJWL~d31v6enPjIpgeLllJB6OaJVtKojn~Yi7Sje~5DJnLxiZVGf~Dn3a9IynFCQ6KXiPo-6418Wl2-vkrq0~cWjmlYMASR9AMILZMr1rOQUf748e92~oYwX2W5saRVnoAAAA
nickster2.i2p=aVMk7wdk-ebssXJmuthnwIy8IdAWLiNiftdNHVvqQCmbJUC1fSVuEkUPkAEW2Hdhzzv9M8t1-MH5Ip2UnTIe5XWjwLvfyg0skX4QouLWX~EZIMq6SrTpIBguYuG9pV5XKfVslwnYyYU-S-lL82S98YJDRWw4eGO~Alg2Sisp8x8iuvLrWwXX61hOcQp6e5OVM5Al3kHcVBFwIGfgIglXy6d7lPZHBRDj7W4jTKKj4OUOaJ84vdRtMZaVXbM~xHZJTZxRo99SmVQpxr4j2n0f4RfYDQxjz2eMPLfhl1IF4svBGbQ1d0PGQlTy0vftRqMjxrS4XoGdlYGyACpDE5eMjIgRhnAyAXbZ4OY7htXKvLgpM6VBQ0JjBwQITsI~MO1IUJXvc3yEg~rLnBtv01YNspiGyE8v0~Va6rps3KjEc6E-C4ZN6pNHBqtKajFPLz4kgrJ-E6P2bXoHMadbNIkEEM5vKSPTFAf~y1ElBH9RD5yaxOxGEzyS076vJ6phK~w2AAAA

View File

@ -15,7 +15,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src" debug="true" destdir="./build/obj" />
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" />
</target>
<target name="jar" depends="installer, guiinstaller" />
<target name="fetchseeds" depends="compile">

View File

@ -79,7 +79,7 @@ public class FetchSeeds {
public static void main(String[] args) {
switch (args.length) {
case 1:
fetchSeeds(new File(args[0]), "http://i2p.dnsalias.net/i2pdb/");
fetchSeeds(new File(args[0]), "http://dev.i2p.net/i2pdb/");
return;
case 2:
fetchSeeds(new File(args[0]), args[1]);
@ -93,7 +93,7 @@ public class FetchSeeds {
System.out.println("Usage: FetchSeeds <outDir>");
System.out.println(" or FetchSeeds <outDir> <seedURL>");
System.out.println(" or FetchSeeds <outDir> <seedURL> <secondsBetweenFetch>");
System.out.println("The default seedURL is http://i2p.dnsalias.net/i2pdb/");
System.out.println("The default seedURL is http://dev.i2p.net/i2pdb/");
return;
}
}

View File

@ -114,7 +114,7 @@ public abstract class Install {
createLoggerConfig();
createStartScript();
createReseedScript();
createScripts("startIrcProxy.sh", "startIrcProxy.bat", 6668, "irc.duck.i2p", "log-irc-#.txt", "IRC Proxy", "IRC proxying scripts written to startIrcProxy", "Starting IRC proxy (when you see Ready! you can connect your IRC client to localhost:6668)");
//createScripts("startIrcProxy.sh", "startIrcProxy.bat", 6668, "irc.duck.i2p", "log-irc-#.txt", "IRC Proxy", "IRC proxying scripts written to startIrcProxy", "Starting IRC proxy (when you see Ready! you can connect your IRC client to localhost:6668)");
//createScripts("startI2PCVSProxy.sh", "startI2PCVSProxy.bat", 2401, "i2pcvs.i2p", "log-i2pcvs-#.txt", "CVS Proxy", "Proxying scripts for I2P's CVS server written to startCVSProxy");
// only pulling them temporarily, duck, until the network is
// reliable enough
@ -325,6 +325,10 @@ public abstract class Install {
_i2cpPort = ((Integer)_answers.get("i2cpPort")).intValue();
_inBPS = ((Integer)_answers.get("inBPS")).intValue();
_outBPS = ((Integer)_answers.get("outBPS")).intValue();
long num = new java.util.Random().nextLong();
if (num < 0)
num = 0 - num;
_answers.put("timestamperPassword", new Long(num));
}
private void useTemplate(String templateName, File destFile) {

View File

@ -1,3 +1,3 @@
cd ##_scripts_installdir##
java -jar lib\fetchseeds.jar netDb
java -jar lib\fetchseeds.jar netDb http://dev.i2p.net/i2pdb/
pause

View File

@ -1,4 +1,4 @@
#!/bin/sh
cd ##_scripts_installdir##
java -jar lib/fetchseeds.jar netDb
java -jar lib/fetchseeds.jar netDb http://dev.i2p.net/i2pdb/
echo Router network database reseeded

View File

@ -55,33 +55,6 @@ router.keepHistory=false
# Again, this is entirely optional, but would be greatly appreciated as it should help
# out the development process
router.submitHistory=false
# If your router is really slow, you'll need to update the following job parameters
# limit the maximum number of concurrent operations
router.maxJobRunners=1
# if a job waits more than this amount of time (in
# milliseconds) before running, spit out a warning
router.jobLagWarning=8000
# if a job waits more than this amount of time (in
# milliseconds) before running, kill the router
router.jobLagFatal=30000
# if a job takes more than this amount of time (in
# milliseconds) to run, spit out a warning
router.jobRunWarning=8000
# if a job takes more than this amount of time (in
# milliseconds) to run, kill the router
router.jobRunFatal=30000
# wait until the router has been up for this long
# (in milliseconds) before honoring any fatalities
# since during startup, jobs are run sequentially
# and CPU intensive tasks are needed
router.jobWarmupTime=600000
# Target clients
# How many concurrent clients the router should prepare for
@ -103,13 +76,12 @@ tunnels.numInbound=2
# XXX Not currently enforced - ignore this setting
tunnels.numOutbound=2
# Depth of inbound tunnels
# This determines the length of inbound tunnels created - how many remote routers to
# include (0 means no remote routers, 3 means a total of four routers, including
# the local one, etc). This is a key factor in the reliability and anonymity
# provided by I2P
# Users should simply leave this as 2 for now, at least until the tunnels are more reliable (post 0.3)
# Users should simply leave this as 2 for now
tunnels.depthInbound=2
# Depth of outbound tunnels
@ -127,27 +99,12 @@ tunnels.depthOutbound=2
# You should not change this setting unless you really know what you're doing
tunnels.tunnelDuration=600000
# Max waiting jobs
# If your router is getting heavily overloaded (due to slow CPU or excess network
# activity), your router's performance will seriously degrade, increasing its
# load further and delaying any messages sent through your router. The max waiting
# jobs configuration parameter is a throttle, saying that if there are more than
# that many 'jobs' that want to run ASAP at any given time, additional jobs may
# be summarily dropped. That will reduce your load and cause others to reduce
# their dependence on you (further reducing your load). The default value of 40
# should be sufficient, but may be increased if desired. Less than 20 is not
# recommended, as certain normal events can queue up 10 or so jobs at a time
# (all of which only take a few milliseconds). Leave this alone unless you know
# what you're doing
router.maxWaitingJobs=40
# shutdown password
# uncomment the following (after changing the value) to allow shutting down the
# router through the web interface (using the form provided, or directly via
# http://localhost:7655/shutdown?password=thisIsASecret)
#router.shutdownPassword=thisIsASecret
#
# the remaining lines describe how you can get your router to fire up client
# applications it is up and running, all within the router's JVM. Uncomment the
@ -168,13 +125,13 @@ router.maxWaitingJobs=40
clientApp.0.main=net.i2p.time.Timestamper
clientApp.0.name=Timestamper
clientApp.0.onBoot=true
clientApp.0.args=http://localhost:7655/setTime?putTheValueFromBelowHere pool.ntp.org pool.ntp.org pool.ntp.org
clientApp.0.args=http://localhost:7655/setTime?##timestamperPassword## pool.ntp.org pool.ntp.org pool.ntp.org
# The admin time passphrase, used to prevent unauthorized people from updating your
# routers time. The value should be included in the timestamper's args above,
# otherwise it wont honor timestamp updates. You shouldnt include any spaces or funky
# characters - just pick some random numbers.
adminTimePassphrase=pleaseSetSomeValueHere
adminTimePassphrase=##timestamperPassword##
# SAM bridge (a simplified socket based protocol for using I2P - listens on port 7656. see
# the specs at http://www.i2p.net/node/view/144 for more info)
@ -182,10 +139,11 @@ clientApp.1.main=net.i2p.sam.SAMBridge
clientApp.1.name=SAMBridge
clientApp.1.args=sam.keys 0.0.0.0 7656 i2cp.tcp.host=localhost i2cp.tcp.port=##_router_i2cp_port##
# EepProxy (HTTP proxy that lets you browse both eepsites and the normal web via squid.i2p)
# The eepProxy (HTTP proxy that lets you browse both eepsites and the normal web via squid.i2p) and
# the ircProxy (which connects to the anonymously hosted ircd at irc.duck.i2p)
clientApp.2.main=net.i2p.i2ptunnel.I2PTunnel
clientApp.2.name=EepProxy
clientApp.2.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclient 4444"
clientApp.2.name=Tunnels
clientApp.2.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclient 4444" -e "client 6668 irc.duck.i2p"
# Network monitor (harvests data from the network database and stores it under
# monitorData/, and with the netviewer GUI you can browse through its results)

View File

@ -8,7 +8,7 @@
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac srcdir="./src:./test" debug="true" destdir="./build/obj" classpath="../../core/java/build/i2p.jar" />
<javac srcdir="./src:./test" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" classpath="../../core/java/build/i2p.jar" />
</target>
<target name="jar" depends="compile">
<jar destfile="./build/router.jar" basedir="./build/obj" includes="**/*.class" />

View File

@ -98,7 +98,18 @@ public class DatabaseStoreMessage extends I2NPMessageImpl {
* @return positive reply token ID, or 0 if no reply is necessary.
*/
public long getReplyToken() { return _replyToken; }
public void setReplyToken(long token) { _replyToken = token; }
/**
* Update the reply token.
*
* @throws IllegalArgumentException if the token is out of range (min=0, max=I2NPMessage.MAX_ID_VALUE)
*/
public void setReplyToken(long token) throws IllegalArgumentException {
if (token > I2NPMessage.MAX_ID_VALUE)
throw new IllegalArgumentException("Token too large: " + token + " (max=" + I2NPMessage.MAX_ID_VALUE + ")");
else if (token < 0)
throw new IllegalArgumentException("Token too small: " + token);
_replyToken = token;
}
public TunnelId getReplyTunnel() { return _replyTunnel; }
public void setReplyTunnel(TunnelId id) { _replyTunnel = id; }

View File

@ -20,6 +20,8 @@ import net.i2p.data.DataStructure;
* @author jrandom
*/
public interface I2NPMessage extends DataStructure {
final long MAX_ID_VALUE = (1l<<32l)-1l;
/**
* Read the body into the data structures, after the initial type byte, using
* the current class's format as defined by the I2NP specification

View File

@ -36,7 +36,7 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
_context = context;
_log = context.logManager().getLog(I2NPMessageImpl.class);
_expiration = new Date(_context.clock().now() + DEFAULT_EXPIRATION_MS);
_uniqueId = _context.random().nextInt(Integer.MAX_VALUE);
_uniqueId = _context.random().nextLong(MAX_ID_VALUE);
}
/**

View File

@ -114,6 +114,9 @@ public class I2NPMessageReader {
public void run() {
while (_stayAlive) {
while (_doRun) {
while (!_context.throttle().acceptNetworkMessage()) {
try { Thread.sleep(500 + _context.random().nextInt(512)); } catch (InterruptedException ie) {}
}
// do read
try {
I2NPMessage msg = _handler.readMessage(_stream);

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
@ -67,7 +70,7 @@ public abstract class ClientManagerFacade implements Service {
*
*/
public abstract SessionConfig getClientSessionConfig(Destination dest);
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) throws IOException { }
}
class DummyClientManagerFacade extends ClientManagerFacade {

View File

@ -8,6 +8,9 @@ package net.i2p.router;
*
*/
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;
@ -19,7 +22,7 @@ import java.util.Set;
public abstract class CommSystemFacade implements Service {
public abstract void processMessage(OutNetMessage msg);
public String renderStatusHTML() { return ""; }
public void renderStatusHTML(OutputStream out) throws IOException { }
/** Create the set of RouterAddress structures based on the router's config */
public Set createAddresses() { return new HashSet(); }

View File

@ -131,8 +131,10 @@ public class InNetMessagePool {
_log.info("Dropping unhandled delivery status message created " + timeSinceSent + "ms ago: " + msg);
_context.statManager().addRateData("inNetPool.droppedDeliveryStatusDelay", timeSinceSent, timeSinceSent);
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Message " + messageBody + " was not handled by a HandlerJobBuilder - DROPPING: "
if (_log.shouldLog(Log.WARN))
_log.warn("Message " + messageBody + " expiring on "
+ (messageBody != null ? (messageBody.getMessageExpiration()+"") : " [unknown]")
+ " was not handled by a HandlerJobBuilder - DROPPING: "
+ msg, new Exception("DROPPED MESSAGE"));
_context.statManager().addRateData("inNetPool.dropped", 1, 0);
}

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