forked from I2P_Developers/i2p.i2p
Compare commits
133 Commits
i2p_0_3_1_
...
i2p_0_3_1_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a8ad8644c8 | ||
![]() |
4e91bb88a5 | ||
![]() |
f60a90e2da | ||
![]() |
784dc0f6a7 | ||
![]() |
e80e627fba | ||
![]() |
d5987c51c9 | ||
![]() |
5ced441b17 | ||
![]() |
57801202fd | ||
![]() |
a019399c3c | ||
![]() |
e6f610a86c | ||
![]() |
7ef528bbde | ||
![]() |
a351a29bf3 | ||
![]() |
983d258bce | ||
![]() |
f6d38dd5e0 | ||
![]() |
d51245aada | ||
![]() |
56cf51f0f9 | ||
![]() |
eb40fb9c5d | ||
![]() |
085da0cea7 | ||
![]() |
5539b19938 | ||
![]() |
94feb762ca | ||
![]() |
40b59d5a5a | ||
![]() |
9ffd147470 | ||
![]() |
3fea4ad2ba | ||
![]() |
1ab5536879 | ||
![]() |
9690a89a6d | ||
![]() |
8f895f4349 | ||
![]() |
980c0aa1d7 | ||
![]() |
52fd6ca513 | ||
![]() |
eb5dd2ff2e | ||
![]() |
7ca35452eb | ||
![]() |
dd781e256c | ||
![]() |
551a7ab82f | ||
![]() |
2901287d9e | ||
![]() |
2b714967aa | ||
![]() |
e8734ef1e7 | ||
![]() |
14b9f9509f | ||
![]() |
b1f973d304 | ||
![]() |
2f17bfd71c | ||
![]() |
b6670ee23a | ||
![]() |
f1036df1f6 | ||
![]() |
5c3e815757 | ||
![]() |
55e780d885 | ||
![]() |
d502df7d56 | ||
![]() |
beb6cc8c0f | ||
![]() |
c99db5e75c | ||
![]() |
65cd70a85b | ||
![]() |
5166eab5ee | ||
![]() |
232f6f158d | ||
![]() |
2a07ceba62 | ||
![]() |
3e4b8c7dd4 | ||
![]() |
26138e213f | ||
![]() |
d82796e3ad | ||
![]() |
cdcb81c867 | ||
![]() |
5669e8f060 | ||
![]() |
d84a40b4dc | ||
![]() |
591be43763 | ||
![]() |
97d0686354 | ||
![]() |
e2da05b197 | ||
![]() |
4f0052043d | ||
![]() |
cfc1d1a2db | ||
![]() |
9957e6ef17 | ||
![]() |
6a02c8383c | ||
![]() |
bc0a4ee68d | ||
![]() |
1ca615da77 | ||
![]() |
7da0cee29a | ||
![]() |
f25bccd19f | ||
![]() |
4e5a2e012c | ||
![]() |
c9ee2a92a3 | ||
![]() |
95a7938328 | ||
![]() |
baedcdb2c1 | ||
![]() |
bc06b3671a | ||
![]() |
a9172811ca | ||
![]() |
91b1fd6d07 | ||
![]() |
bab7b8b9ed | ||
![]() |
1b7fb96ca8 | ||
![]() |
6d84b8c02f | ||
![]() |
3e3749f011 | ||
![]() |
52384fb3a5 | ||
![]() |
e401670087 | ||
![]() |
ae0b4c59cc | ||
![]() |
0a8dc8afcc | ||
![]() |
d59b94df66 | ||
![]() |
e28502454b | ||
![]() |
bbf73f0937 | ||
![]() |
592519c45c | ||
![]() |
cc904ba9dc | ||
![]() |
1679ba6719 | ||
![]() |
07fadd4a6c | ||
![]() |
57e1ff39e0 | ||
![]() |
51e259c198 | ||
![]() |
de334b003d | ||
![]() |
a61ff12390 | ||
![]() |
f4697be159 | ||
![]() |
3835fe3960 | ||
![]() |
76c374ef06 | ||
![]() |
57d24bd948 | ||
![]() |
deff14dfd8 | ||
![]() |
0a479be370 | ||
![]() |
ba6a2e3fd2 | ||
![]() |
c3a395a41e | ||
![]() |
a3136a19e9 | ||
![]() |
b631568003 | ||
![]() |
1d0c03eca4 | ||
![]() |
eb30525a26 | ||
![]() |
3e66ea3f56 | ||
![]() |
9f1189e606 | ||
![]() |
698927bed4 | ||
![]() |
8fd02ee8dd | ||
![]() |
f3154e8f5e | ||
![]() |
878af163a9 | ||
![]() |
da8341d014 | ||
![]() |
95c33e88ed | ||
![]() |
fed8369a5f | ||
![]() |
d85806e3d5 | ||
![]() |
097660ce53 | ||
![]() |
b08cfbbb35 | ||
![]() |
97ee3c47a0 | ||
![]() |
05918de6ab | ||
![]() |
8d7abd8298 | ||
![]() |
727f4c3bb5 | ||
![]() |
7372ad0cc4 | ||
![]() |
ca6884dbca | ||
![]() |
1ebb0ac5fb | ||
![]() |
bf0e53f13b | ||
![]() |
8888a960c0 | ||
![]() |
04be41aac5 | ||
![]() |
fd1313d49f | ||
![]() |
3599dba5c3 | ||
![]() |
67edc437d2 | ||
![]() |
7a39d9240c | ||
![]() |
6d2d9aed7e | ||
![]() |
3c2e5f22b6 | ||
![]() |
ddb6348bfd |
27
apps/enclave/LICENSE
Normal file
27
apps/enclave/LICENSE
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
79
apps/enclave/Makefile
Normal file
79
apps/enclave/Makefile
Normal file
@@ -0,0 +1,79 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make and should work on Linux
|
||||
# (Tested on Debian 3.0)
|
||||
#
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
BINDIR = bin
|
||||
LOGDIR = log
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
SAMINCDIR = ../sam/c/inc
|
||||
SAMLIBDIR = ../sam/c/lib
|
||||
TOMCRYPTDIR = $(HOME)/libtomcrypt-0.96
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
CC = g++
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -march=i486 -pipe -Wall
|
||||
|
||||
#
|
||||
# Libraries
|
||||
#
|
||||
|
||||
CFLAGS += -I$(SAMINCDIR) -I$(TOMCRYPTDIR)
|
||||
LDFLAGS = -L$(SAMLIBDIR) -L$(TOMCRYPTDIR)
|
||||
LIBS = -lsam -ltomcrypt
|
||||
|
||||
#
|
||||
# Object files
|
||||
#
|
||||
|
||||
OBJS = $(OBJDIR)/bigint.o \
|
||||
$(OBJDIR)/chk.o \
|
||||
$(OBJDIR)/config.o \
|
||||
$(OBJDIR)/logger.o \
|
||||
$(OBJDIR)/main.o \
|
||||
$(OBJDIR)/peers.o \
|
||||
$(OBJDIR)/random.o \
|
||||
$(OBJDIR)/rpc.o \
|
||||
$(OBJDIR)/sam.o \
|
||||
$(OBJDIR)/sha1.o
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: depend enclave
|
||||
|
||||
depend:
|
||||
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.cpp > .depend
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
enclave: $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $(BINDIR)/enclave $(OBJS) $(LIBS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f $(BINDIR)/* $(OBJDIR)/* .depend
|
||||
|
||||
clean-logs:
|
||||
-rm -f $(LOGDIR)/*
|
||||
|
||||
tidy: clean clean-logs
|
32
apps/enclave/cfg/enclave.cfg
Normal file
32
apps/enclave/cfg/enclave.cfg
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# This is the Enclave configuration file. Lines starting with # and blank lines
|
||||
# are ignored.
|
||||
#
|
||||
|
||||
# The DNS name or IP address of the SAM server you will be using
|
||||
samhost=localhost
|
||||
|
||||
# The TCP port the SAM server is listening on
|
||||
samport=7656
|
||||
|
||||
# The destination name of this program. This can be anything. If you run
|
||||
# multiple copies of Enclave off the same SAM server then each one has to have a
|
||||
# unique name.
|
||||
samname=enclave
|
||||
|
||||
# The depth used for incoming and outgoing I2P tunnels. Using a depth of 2 is
|
||||
# the default and a good choice. You can set it to 0 if you don't care about
|
||||
# anonymity and just want speed.
|
||||
tunneldepth=0
|
||||
|
||||
# The location of the peer references file. You can use an absolute or relative
|
||||
# path, but absolute paths are safer.
|
||||
references=cfg/peers.ref
|
||||
|
||||
# Record every log message at or above this priority level
|
||||
# debug = 0, minor = 1, info = 2, warn = 3, error = 4
|
||||
loglevel=0
|
||||
|
||||
# The location of the Enclave log file. You can use an absolute or relative
|
||||
# path, but absolute paths are safer.
|
||||
logfile=log/enclave.log
|
2
apps/enclave/cfg/peers.ref
Normal file
2
apps/enclave/cfg/peers.ref
Normal file
@@ -0,0 +1,2 @@
|
||||
4KpEG0uUvTM~IZKuWZZifdmh5UU6evIPG0tE3ppoqy37AY2NJrsM8BU0EkT1SG-g18qSW9UHDp7qs7m~WzeWTXyYggEb6k6-e0GYC2Cj8ED8JV58-2~cFZumVNJ2d1hns-MGX7RZv2lz3Cz2ZVhfZxSIw9UnpV-kwVn7sQ7PBCvJYE4INbp5OlRQH1-3lXiUheoJfeZpegGTUSHUwIRWglX7w87YF~LCbJMYXDgMyA3SaxsZaun7Wc8ku4bqtbmG9u15XlmqimLUUmDG0cw77HJzqxnR1C1hx0wf-9zgH6u4jwTWk92w5tZJZSv1SHKejlPkIbRNAhZv5wroyZsn6T0koV~kTVCvbUEwILho-rHn4A6C2jLQifwE9aucziBTVq3YLK2urf1wI1jLh98iFNav40S~B2w-4xZFAQ49bOdWzY4KmVIjocVhfGi~RLl5bHD1TEJS7nOaDhI8qCSe7mR0XzZgQ~iROR~XowlwKXBzNPjKED7yN8GgV2pWRGNYAAAA
|
||||
WiotuvEjGpSz7q14eZGYFpD0xNt3V~nxZdDDgKc~whkW-pardZyz~wZipHXLIOvniThDL2rxJ~OW7RxgUycCph4x--NL51kEJhMWZ~bgxPioxw-T4JGQ9LSNndt9xNOf6yhEqyokqyEOEeJjw6m2e7RX7mTRffmTlCdu6uH6rVEk22o4Uu5S26p6-LS2k9lRyMWitFd~t9cnOgLTZTE~h4d-UlAd1BGxpCTlGWcaynOQzKKtljZknZMF9Qv19MxT83t18~3IURb6aOLlC4oih9pMt1pHouZuOaStKA7cGLsXUAhSB31BvK8l4R7VhgcudwJ9EQZkZQee51hcng7K1Yqmd4lnjHHuf1mDk0YXBAWDZOM0-oEwkJWumGuYl0NUtLhNlFrBjenbjACx88qhfy6mkXfo8c-c2QqEXuD2xt4OVqrWxBTIrr1pR-E1NdIxzIvOlCbrRXaqxqu-wnrrG2vCO-1zu9NHacCVjXD7AR7p3T628wPdCUzj2~rZRcCkAAAA
|
169
apps/enclave/src/bigint.cpp
Normal file
169
apps/enclave/src/bigint.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "bigint.hpp"
|
||||
|
||||
/******************************************************************************/
|
||||
// Note: All the const_casts below are necessary because libtomcrypt doesn't //
|
||||
// have its arguments as const, even when they are not changed //
|
||||
/******************************************************************************/
|
||||
|
||||
Bigint::Bigint(const Bigint& bigint)
|
||||
{
|
||||
init();
|
||||
copyover_mp_int(bigint.mpi);
|
||||
}
|
||||
|
||||
Bigint::Bigint(const uchar_t* data, size_t size)
|
||||
{
|
||||
init();
|
||||
import_uraw(data, size);
|
||||
}
|
||||
|
||||
Bigint::Bigint(uint16_t i)
|
||||
{
|
||||
init();
|
||||
i = htons(i);
|
||||
import_uraw(reinterpret_cast<uchar_t*>(&i), 2);
|
||||
}
|
||||
|
||||
Bigint::Bigint(uint32_t i)
|
||||
{
|
||||
init();
|
||||
i = htonl(i);
|
||||
import_uraw(reinterpret_cast<uchar_t*>(&i), 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Replaces our current mp_int with another one
|
||||
* (just a wrapper for mp_copy)
|
||||
*/
|
||||
void Bigint::copyover_mp_int(const mp_int& i)
|
||||
{
|
||||
int rc = mp_copy(const_cast<mp_int*>(&i), &mpi);
|
||||
assert(rc == MP_OKAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Saves a Bigint to a raw unsigned big-endian integer
|
||||
* Note that the result must be freed with delete[]
|
||||
*
|
||||
* size - filled with the size of the output
|
||||
*
|
||||
* Returns: binary data
|
||||
*/
|
||||
uchar_t* Bigint::export_uraw(size_t& size) const
|
||||
{
|
||||
uchar_t* out;
|
||||
size = mp_unsigned_bin_size(const_cast<mp_int*>(&mpi));
|
||||
if (size != 0) {
|
||||
out = new uchar_t[size];
|
||||
int rc = mp_to_unsigned_bin(const_cast<mp_int*>(&mpi), out);
|
||||
assert(rc == MP_OKAY);
|
||||
} else { // size == 0
|
||||
size = 1;
|
||||
out = new uchar_t[1];
|
||||
out[0] = 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads a raw unsigned big-endian integer into Bigint
|
||||
*
|
||||
* data - binary data
|
||||
* size - size of data
|
||||
*/
|
||||
void Bigint::import_uraw(const uchar_t* data, size_t size)
|
||||
{
|
||||
uchar_t tmp[size]; // mp_read_unsigned_bin() arg 2 is not const
|
||||
memcpy(tmp, data, sizeof tmp); // I'm not taking any chances
|
||||
int rc = mp_read_unsigned_bin(&mpi, tmp, sizeof tmp);
|
||||
assert(rc == MP_OKAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialises the object
|
||||
*/
|
||||
void Bigint::init(void)
|
||||
{
|
||||
int rc = mp_init(&mpi);
|
||||
assert(rc == MP_OKAY);
|
||||
}
|
||||
|
||||
bool Bigint::operator<(const Bigint& rhs) const
|
||||
{
|
||||
int rc = mp_cmp(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi));
|
||||
if (rc == MP_LT)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
Bigint& Bigint::operator=(const Bigint& rhs)
|
||||
{
|
||||
if (this != &rhs) // check for self-assignment: a = a
|
||||
copyover_mp_int(rhs.mpi);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Bigint::operator==(const Bigint& rhs) const
|
||||
{
|
||||
int rc = mp_cmp(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi));
|
||||
if (rc == MP_EQ)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bigint::operator>(const Bigint& rhs) const
|
||||
{
|
||||
int rc = mp_cmp(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi));
|
||||
if (rc == MP_GT)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Xors another Bigint with this Bigint and puts the result in Bigint `result'.
|
||||
* We can't name it "xor" because that word is reserved in C++ (see Appendex C,
|
||||
* section 3.1 in TC++PL).
|
||||
*
|
||||
* rhs - the bigint to xor with
|
||||
* result - will be filled with the result of the xor
|
||||
*/
|
||||
void Bigint::x_or(const Bigint& rhs, Bigint& result) const
|
||||
{
|
||||
int rc = mp_xor(const_cast<mp_int*>(&mpi), const_cast<mp_int*>(&rhs.mpi),
|
||||
&result.mpi);
|
||||
assert(rc == MP_OKAY);
|
||||
}
|
60
apps/enclave/src/bigint.hpp
Normal file
60
apps/enclave/src/bigint.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BIGINT_HPP
|
||||
#define BIGINT_HPP
|
||||
|
||||
class Bigint {
|
||||
public:
|
||||
Bigint(void) { init(); }
|
||||
Bigint(const Bigint& bigint);
|
||||
Bigint(const uchar_t* data, size_t size);
|
||||
Bigint(uint16_t i);
|
||||
Bigint(uint32_t i);
|
||||
~Bigint(void) { mp_clear(&mpi); }
|
||||
|
||||
uchar_t* export_uraw(size_t& size) const;
|
||||
const mp_int& get_mp_int(void) const { return mpi; }
|
||||
void import_uraw(const uchar_t* data, size_t size);
|
||||
bool operator<(const Bigint& rhs) const;
|
||||
Bigint& operator=(const Bigint& rhs);
|
||||
bool operator==(const Bigint& rhs) const;
|
||||
bool operator>(const Bigint& rhs) const;
|
||||
void x_or(const Bigint& rhs, Bigint& result) const;
|
||||
|
||||
protected:
|
||||
mp_int mpi;
|
||||
|
||||
private:
|
||||
void copyover_mp_int(const mp_int& i);
|
||||
void init(void);
|
||||
};
|
||||
|
||||
#endif // BIGINT_HPP
|
56
apps/enclave/src/chk.cpp
Normal file
56
apps/enclave/src/chk.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "chk.hpp"
|
||||
|
||||
Chk::Chk(const uchar_t* plaintext, size_t size, const string& mime_type)
|
||||
: data_size(size), mime_type(mime_type)
|
||||
{
|
||||
encrypt(plaintext);
|
||||
}
|
||||
|
||||
void Chk::encrypt(const uchar_t *pt)
|
||||
{
|
||||
int rc = register_cipher(&twofish_desc);
|
||||
assert(rc != -1);
|
||||
|
||||
uchar_t key[CRYPT_KEY_SIZE], iv[CRYPT_BLOCK_SIZE];
|
||||
prng->get_bytes(key, CRYPT_KEY_SIZE);
|
||||
prng->get_bytes(iv, CRYPT_BLOCK_SIZE);
|
||||
|
||||
symmetric_CTR ctr;
|
||||
rc = ctr_start(find_cipher("twofish"), iv, key, CRYPT_KEY_SIZE, 0, &ctr);
|
||||
assert(rc == CRYPT_OK);
|
||||
|
||||
ct = new uchar_t[data_size];
|
||||
rc = ctr_encrypt(pt, ct, data_size, &ctr);
|
||||
assert(rc == CRYPT_OK);
|
||||
}
|
51
apps/enclave/src/chk.hpp
Normal file
51
apps/enclave/src/chk.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CHK_HPP
|
||||
#define CHK_HPP
|
||||
|
||||
class Chk {
|
||||
public:
|
||||
//Chk(const uchar_t* cypertext, size_t size);
|
||||
Chk(const uchar_t* plaintext, size_t size, const string& mime_type);
|
||||
~Chk(void) { delete[] ct; }
|
||||
|
||||
private:
|
||||
static const size_t CRYPT_BLOCK_SIZE = 16;
|
||||
static const size_t CRYPT_KEY_SIZE = 32;
|
||||
|
||||
void encrypt(const uchar_t *pt);
|
||||
|
||||
uchar_t* ct; // cyphertext
|
||||
const size_t data_size;
|
||||
const string& mime_type; // I hate mimes.
|
||||
};
|
||||
|
||||
#endif // CHK_HPP
|
148
apps/enclave/src/config.cpp
Normal file
148
apps/enclave/src/config.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "bigint.hpp"
|
||||
|
||||
Config::Config(const string& file)
|
||||
: file(file)
|
||||
{
|
||||
set_defaults();
|
||||
parse();
|
||||
configf.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks up a configuration option in the table and returns a constant value.
|
||||
* This is the same as get_property() except the value returned is a constant.
|
||||
*
|
||||
* key - key to lookup
|
||||
*
|
||||
* Returns the value associated with the key
|
||||
*/
|
||||
const string& Config::get_cproperty(const string& key) const
|
||||
{
|
||||
for (cfgmap_ci i = cfgmap.begin(); i != cfgmap.end(); i++) {
|
||||
const string s = i->first;
|
||||
if (s == key)
|
||||
return i->second;
|
||||
}
|
||||
LERROR << "Tried to lookup an invalid property: " << key << '\n';
|
||||
assert(false);
|
||||
// this should never occur, it's just to silence a compiler warning
|
||||
string* s = new string;
|
||||
return *s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a property as an integer (they are all stored as strings)
|
||||
*
|
||||
* key - key to lookup
|
||||
*
|
||||
* Returns an integer of the value associated with the key
|
||||
*/
|
||||
int Config::get_iproperty(const string& key) const
|
||||
{
|
||||
for (cfgmap_ci i = cfgmap.begin(); i != cfgmap.end(); i++) {
|
||||
const string s = i->first;
|
||||
if (s == key)
|
||||
return atoi(i->second.c_str());
|
||||
}
|
||||
LERROR << "Tried to lookup an invalid property: " << key << '\n';
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks up a configuration option in the table and returns the value
|
||||
*
|
||||
* key - key to lookup
|
||||
*
|
||||
* Returns the value associated with the key
|
||||
*/
|
||||
string& Config::get_property(const string& key)
|
||||
{
|
||||
for (cfgmap_i i = cfgmap.begin(); i != cfgmap.end(); i++) {
|
||||
const string s = i->first;
|
||||
if (s == key)
|
||||
return i->second;
|
||||
}
|
||||
LERROR << "Tried to lookup an invalid property: " << key << '\n';
|
||||
assert(false);
|
||||
// this should never occur, it's just to silence a compiler warning
|
||||
string* s = new string;
|
||||
return *s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses the configuration file, replacing default values with user defined
|
||||
* values
|
||||
*/
|
||||
void Config::parse(void)
|
||||
{
|
||||
configf.open(file.c_str());
|
||||
if (!configf) {
|
||||
cerr << "Error opening configuration file (" << file.c_str() << ")\n";
|
||||
throw runtime_error("Error opening configuration file");
|
||||
}
|
||||
size_t line = 0;
|
||||
string s;
|
||||
for (getline(configf, s); configf; getline(configf, s)) {
|
||||
line++;
|
||||
if (s.size() == 0 || s[0] == '#') // blank line or comment
|
||||
continue;
|
||||
size_t eqpos = s.find("=");
|
||||
if (eqpos == string::npos) {
|
||||
cerr << "Error parsing line #" << line << " in " << file << ": "
|
||||
<< s << '\n';
|
||||
continue;
|
||||
}
|
||||
string key = s.substr(0, eqpos);
|
||||
string value = s.substr(eqpos + 1);
|
||||
//cout << "Inserting key = " << key << " value = " << value << '\n';
|
||||
cfgmap.erase(key); // erase the default value created by set_defaults()
|
||||
cfgmap.insert(make_pair(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If you (the programmer) add something to the config file you should also add
|
||||
* it here, and vice versa
|
||||
*/
|
||||
void Config::set_defaults(void)
|
||||
{
|
||||
cfgmap.insert(make_pair("samhost", "localhost"));
|
||||
cfgmap.insert(make_pair("samport", "7656"));
|
||||
cfgmap.insert(make_pair("samname", "enclave"));
|
||||
cfgmap.insert(make_pair("tunneldepth", "2"));
|
||||
cfgmap.insert(make_pair("references", "cfg/peers.ref"));
|
||||
cfgmap.insert(make_pair("loglevel", "1"));
|
||||
cfgmap.insert(make_pair("logfile", "log/enclave.log"));
|
||||
}
|
54
apps/enclave/src/config.hpp
Normal file
54
apps/enclave/src/config.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_HPP
|
||||
#define CONFIG_HPP
|
||||
|
||||
class Config {
|
||||
public:
|
||||
Config(const string& file);
|
||||
|
||||
const string& get_cproperty(const string& key) const;
|
||||
int get_iproperty(const string& key) const;
|
||||
string& get_property(const string& key);
|
||||
|
||||
private:
|
||||
typedef map<const string, string>::const_iterator cfgmap_ci;
|
||||
typedef map<const string, string>::iterator cfgmap_i;
|
||||
|
||||
void parse(void);
|
||||
void set_defaults(void);
|
||||
|
||||
ifstream configf;
|
||||
const string file;
|
||||
map<const string, string> cfgmap;
|
||||
};
|
||||
|
||||
#endif // CONFIG_HPP
|
44
apps/enclave/src/logger.cpp
Normal file
44
apps/enclave/src/logger.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
Logger::Logger(const string& file)
|
||||
: file(file)
|
||||
{
|
||||
set_pri(debug);
|
||||
set_loglevel(static_cast<priority_t>(config->get_iproperty("loglevel")));
|
||||
logf.open(file.c_str(), ios::app);
|
||||
if (!logf) {
|
||||
cerr << "Error opening log file (" << file.c_str() << ")\n";
|
||||
throw runtime_error("Error opening log file");
|
||||
}
|
||||
}
|
84
apps/enclave/src/logger.hpp
Normal file
84
apps/enclave/src/logger.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_HPP
|
||||
#define LOGGER_HPP
|
||||
|
||||
/*
|
||||
* LDEBUG - debugging messages
|
||||
* LMINOR - unimportant messages
|
||||
* LINFO - informational messages
|
||||
* LWARN - errors we automatically recover from
|
||||
* LERROR - major, important errors
|
||||
*/
|
||||
#if VERBOSE_LOGS
|
||||
#define LDEBUG logger->set_pri(Logger::debug); (*logger) << "(D)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
|
||||
#define LMINOR logger->set_pri(Logger::minor); (*logger) << "(M)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
|
||||
#define LINFO logger->set_pri(Logger::info); (*logger) << "(I)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
|
||||
#define LWARN logger->set_pri(Logger::warn); (*logger) << "(W)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
|
||||
#define LERROR logger->set_pri(Logger::error); (*logger) << "(E)" << __FILE__ << ':' << __LINE__ << ':' << __func__ << ": "
|
||||
#else
|
||||
#define LDEBUG logger->set_pri(Logger::debug); (*logger) << "(D)"
|
||||
#define LMINOR logger->set_pri(Logger::minor); (*logger) << "(M)"
|
||||
#define LINFO logger->set_pri(Logger::info); (*logger) << "(I)"
|
||||
#define LWARN logger->set_pri(Logger::warn); (*logger) << "(W)"
|
||||
#define LERROR logger->set_pri(Logger::error); (*logger) << "(E)"
|
||||
#endif
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
typedef enum {debug = 0, minor = 1, info = 2, warn = 3, error = 4}
|
||||
priority_t;
|
||||
|
||||
Logger(const string& file);
|
||||
|
||||
void flush(void) { logf.flush(); }
|
||||
priority_t get_loglevel(void) const { return loglevel; }
|
||||
void set_loglevel(priority_t priority) { loglevel = priority; }
|
||||
Logger& operator<<(char c)
|
||||
{ if (priority >= loglevel) { logf << c; flush(); } return *this; }
|
||||
Logger& operator<<(const char* c)
|
||||
{ if (priority >= loglevel) { logf << c; flush(); } return *this; }
|
||||
Logger& operator<<(int i)
|
||||
{ if (priority >= loglevel) { logf << i; flush(); } return *this; }
|
||||
Logger& operator<<(const string& s)
|
||||
{ if (priority >= loglevel) { logf << s; flush(); } return *this; }
|
||||
Logger& operator<<(unsigned int i)
|
||||
{ if (priority >= loglevel) { logf << i; flush(); } return *this; }
|
||||
void set_pri(priority_t priority) { this->priority = priority; }
|
||||
|
||||
private:
|
||||
priority_t priority; // importance of the following log message(s)
|
||||
string file;
|
||||
priority_t loglevel; // write log messsages at or above this priority
|
||||
ofstream logf;
|
||||
};
|
||||
|
||||
#endif // LOGGER_HPP
|
84
apps/enclave/src/main.cpp
Normal file
84
apps/enclave/src/main.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "main.hpp"
|
||||
|
||||
Config *config; // Configuration options
|
||||
Logger *logger; // Logging mechanism
|
||||
Random *prng; // Random number generator
|
||||
Sam *sam; // SAM connection
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc != 2) { // put some getopts stuff in here later
|
||||
cerr << "Please specify the configuration file location.\n" \
|
||||
"e.g. 'bin/enclave cfg/enclave.cfg'\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
config = new Config(argv[1]);
|
||||
} catch (const runtime_error& x) {
|
||||
return 0;
|
||||
}
|
||||
logger = new Logger(config->get_cproperty("logfile"));
|
||||
LINFO << "Enclave DHT - Built on " << __DATE__ << ' ' << __TIME__ << '\n';
|
||||
prng = new Random;
|
||||
try {
|
||||
sam = new Sam(config->get_cproperty("samhost"),
|
||||
config->get_iproperty("samport"), config->get_cproperty("samname"),
|
||||
config->get_iproperty("tunneldepth"));
|
||||
} catch (const Sam_error& x) {
|
||||
LERROR << "SAM error: " << x.what() << '\n';
|
||||
cerr << "SAM error: " << x.what() << '\n';
|
||||
if (x.code() == SAM_SOCKET_ERROR) {
|
||||
LERROR << "Check whether you have specified the correct SAM host " \
|
||||
"and port number, and that I2P is running.\n";
|
||||
cerr << "Check whether you have specified the correct SAM host " \
|
||||
"and port number, and that\nI2P is running.\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
sam->naming_lookup();
|
||||
while (sam->get_my_dest() == "")
|
||||
sam->read_buffer(); // wait until we get our own dest back from lookup
|
||||
|
||||
sam->peers->advertise_self();
|
||||
|
||||
while (true)
|
||||
sam->read_buffer();
|
||||
|
||||
delete sam;
|
||||
delete prng;
|
||||
delete logger;
|
||||
delete config;
|
||||
return 0;
|
||||
}
|
36
apps/enclave/src/main.hpp
Normal file
36
apps/enclave/src/main.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MAIN_HPP
|
||||
#define MAIN_HPP
|
||||
|
||||
// intentionally left blank
|
||||
|
||||
#endif // MAIN_HPP
|
54
apps/enclave/src/near_peer.hpp
Normal file
54
apps/enclave/src/near_peer.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NEAR_PEER_HPP
|
||||
#define NEAR_PEER_HPP
|
||||
|
||||
//
|
||||
// Used for finding the closest peers to a sha1
|
||||
//
|
||||
|
||||
class Near_peer {
|
||||
public:
|
||||
Near_peer(const Bigint& distance, Peer* peer)
|
||||
: distance(distance), peer(peer) {}
|
||||
|
||||
Peer* get_peer(void) const { return peer; }
|
||||
bool operator<(const Near_peer& rhs) const
|
||||
{ if (distance < rhs.distance) return true; else return false; }
|
||||
|
||||
protected:
|
||||
const Bigint distance;
|
||||
|
||||
private:
|
||||
Peer* peer;
|
||||
};
|
||||
|
||||
#endif // NEAR_PEER_HPP
|
52
apps/enclave/src/peer.hpp
Normal file
52
apps/enclave/src/peer.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PEER_HPP
|
||||
#define PEER_HPP
|
||||
|
||||
class Peer {
|
||||
public:
|
||||
Peer(const string& dest, const Sha1& kaddr)
|
||||
: dest(dest), kaddr(kaddr), lag(-1) {}
|
||||
|
||||
const string& get_b64kaddr(void) const { return kaddr.b64hash(); }
|
||||
const uchar_t* get_binkaddr(void) const { return kaddr.binhash(); }
|
||||
const string& get_dest(void) const { return dest; }
|
||||
int get_lag(void) const { return lag; }
|
||||
const string get_sdest(void) const { return dest.substr(0, 8); }
|
||||
void set_lag(int lag) { this->lag = lag; }
|
||||
|
||||
private:
|
||||
const string dest;
|
||||
const Sha1 kaddr;
|
||||
int lag; // if -1, then it is unknown
|
||||
};
|
||||
|
||||
#endif // PEER_HPP
|
220
apps/enclave/src/peers.cpp
Normal file
220
apps/enclave/src/peers.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "near_peer.hpp"
|
||||
#include "rpc.hpp"
|
||||
#include "sha1.hpp"
|
||||
#include "peers.hpp"
|
||||
|
||||
/*
|
||||
* Inform other peers of our existence and collect the destination addresses of
|
||||
* nearby peers
|
||||
*/
|
||||
void Peers::advertise_self(void)
|
||||
{
|
||||
list<Near_peer> near_peers;
|
||||
get_nearest(sam->get_my_sha1(), PAR_RPCS, near_peers);
|
||||
for (list<Near_peer>::const_iterator i = near_peers.begin();
|
||||
i != near_peers.end(); i++) {
|
||||
Rpc rpc(i->get_peer());
|
||||
rpc.find_peers(sam->get_my_sha1());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the `n' nearest peers by xoring a sha1 with a kaddr
|
||||
*
|
||||
* sha1 - sha1 to find nearness to
|
||||
* n - number of peers to find
|
||||
* near_peers - a list to put the found peers in
|
||||
*/
|
||||
void Peers::get_nearest(const Sha1& sha1, size_t n, list<Near_peer>& near_peers)
|
||||
{
|
||||
near_peers.clear(); // prevents duplicate peers in the list
|
||||
for (peersmap_i i = peersmap.begin(); i != peersmap.end(); i++) {
|
||||
const Sha1& kaddr = i->first;
|
||||
Bigint distance;
|
||||
sha1.x_or(kaddr, distance);
|
||||
Near_peer np(distance, &(i->second));
|
||||
near_peers.insert(near_peers.end(), np);
|
||||
}
|
||||
near_peers.sort();
|
||||
while (near_peers.size() > n)
|
||||
near_peers.pop_back();
|
||||
}
|
||||
|
||||
Peer* Peers::get_peer_by_dest(const sam_pubkey_t dest)
|
||||
{
|
||||
const string s = dest;
|
||||
return get_peer_by_dest(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a peer by its base 64 destination address
|
||||
*
|
||||
* dest - destination
|
||||
*
|
||||
* Returns: pointer to peer, or 0 if the peer wasn't found
|
||||
*/
|
||||
Peer* Peers::get_peer_by_dest(const string& dest)
|
||||
{
|
||||
for (peersmap_i i = peersmap.begin(); i != peersmap.end(); i++) {
|
||||
Peer& tmp = i->second;
|
||||
if (tmp.get_dest() == dest)
|
||||
return &(i->second);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets a peer by its Kademlia address
|
||||
*
|
||||
* kaddr - Kademlia adddress
|
||||
*
|
||||
* Returns: pointer to peer, or 0 if the peer wasn't found
|
||||
*/
|
||||
Peer* Peers::get_peer_by_kaddr(const Sha1& kaddr)
|
||||
{
|
||||
peersmap_i i = peersmap.find(kaddr);
|
||||
if (i != peersmap.end())
|
||||
return &(i->second);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads peer addresses from a file
|
||||
*/
|
||||
void Peers::load(void)
|
||||
{
|
||||
string dest;
|
||||
|
||||
ifstream peersf(file.c_str());
|
||||
if (!peersf) {
|
||||
LERROR << "Couldn't load peers reference file (" << file.c_str()
|
||||
<< ")\n";
|
||||
if (peersmap.size() > 0)
|
||||
return;
|
||||
else
|
||||
throw runtime_error("No peer references in memory");
|
||||
}
|
||||
|
||||
for (getline(peersf, dest); peersf; getline(peersf, dest))
|
||||
new_peer(dest);
|
||||
|
||||
if (peersmap.size() > 0) {
|
||||
LMINOR << peersmap.size() << " peer references in memory\n";
|
||||
} else
|
||||
throw runtime_error("No peer references in memory");
|
||||
}
|
||||
|
||||
Peer* Peers::new_peer(const sam_pubkey_t dest)
|
||||
{
|
||||
const string s = dest;
|
||||
return new_peer(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a newly discovered peer to the peers map
|
||||
*
|
||||
* dest - destination address of the peer
|
||||
*
|
||||
* Returns: pointer to the peer
|
||||
*/
|
||||
Peer* Peers::new_peer(const string& dest)
|
||||
{
|
||||
// Check the destination address
|
||||
if (!sam->valid_dest(dest)) {
|
||||
LWARN << "Bad format in peer reference: " << dest.substr(0, 8) << '\n';
|
||||
return 0;
|
||||
}
|
||||
// Never add our own peer to the peers we can connect to
|
||||
if (dest == sam->get_my_dest()) {
|
||||
LDEBUG << "Not adding my own peer reference: " << dest.substr(0, 8)
|
||||
<< '\n';
|
||||
return 0;
|
||||
}
|
||||
// Be sure that the peer is not already known to us
|
||||
Peer *peer = get_peer_by_dest(dest);
|
||||
if (peer != 0) {
|
||||
LDEBUG << "Redundant peer reference: " << dest.substr(0, 8) << '\n';
|
||||
return peer;
|
||||
}
|
||||
|
||||
// Tests passed, add it
|
||||
Sha1 sha1(dest);
|
||||
pair<peersmap_i, bool> p = peersmap.insert(
|
||||
make_pair(sha1, Peer(dest, sha1)));
|
||||
assert(p.second);
|
||||
LMINOR << "New peer reference: " << dest.substr(0, 8)
|
||||
<< " (Kaddr: " << sha1.b64hash() << ")\n";
|
||||
peer = &(p.first->second);
|
||||
return peer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Saves peer destinations to a file
|
||||
*
|
||||
* file - the file to save to
|
||||
*/
|
||||
void Peers::save(void)
|
||||
{
|
||||
ofstream peersf(file.c_str());
|
||||
if (!peersf) {
|
||||
LERROR << "Error opening peers reference file (" << file.c_str()
|
||||
<< ")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
LDEBUG << "Saving " << peersmap.size() + 1 << " peer references\n";
|
||||
peersf << sam->get_my_dest() << '\n';
|
||||
for (peersmap_ci i = peersmap.begin(); i != peersmap.end(); i++) {
|
||||
const Peer& tmp = i->second;
|
||||
peersf << tmp.get_dest() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stores data on some peers
|
||||
*
|
||||
* sha1 - the sha1 value for the data
|
||||
* data - the data
|
||||
*/
|
||||
void Peers::store(const Sha1& sha1)
|
||||
{
|
||||
list<Near_peer> near_peers;
|
||||
get_nearest(sam->get_my_sha1(), PAR_RPCS, near_peers);
|
||||
for (list<Near_peer>::const_iterator i = near_peers.begin();
|
||||
i != near_peers.end(); i++) {
|
||||
Rpc rpc(i->get_peer());
|
||||
rpc.store(sha1);
|
||||
}
|
||||
}
|
65
apps/enclave/src/peers.hpp
Normal file
65
apps/enclave/src/peers.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PEERS_HPP
|
||||
#define PEERS_HPP
|
||||
|
||||
class Peers {
|
||||
public:
|
||||
static const int PAR_RPCS = 3; // The number of parallel RPCs to send
|
||||
static const int RET_REFS = 20; // The number of peer refs to return on
|
||||
// failed requests
|
||||
Peers(const string& file)
|
||||
: file(file)
|
||||
{ load(); }
|
||||
~Peers(void) { save(); }
|
||||
|
||||
void advertise_self(void);
|
||||
void get_nearest(const Sha1& sha1, size_t n,
|
||||
list<Near_peer>& near_peers);
|
||||
Peer* get_peer_by_dest(const sam_pubkey_t dest);
|
||||
Peer* get_peer_by_dest(const string& dest);
|
||||
Peer* get_peer_by_kaddr(const Sha1& kaddr);
|
||||
Peer* new_peer(const sam_pubkey_t dest);
|
||||
Peer* new_peer(const string& dest);
|
||||
void store(const Sha1& sha1);
|
||||
|
||||
private:
|
||||
typedef map<const Sha1, Peer>::const_iterator peersmap_ci;
|
||||
typedef map<const Sha1, Peer>::iterator peersmap_i;
|
||||
|
||||
void load(void);
|
||||
void save(void);
|
||||
|
||||
const string file;
|
||||
map<const Sha1, Peer> peersmap;
|
||||
};
|
||||
|
||||
#endif // PEERS_HPP
|
93
apps/enclave/src/platform.hpp
Normal file
93
apps/enclave/src/platform.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_HPP
|
||||
#define PLATFORM_HPP
|
||||
|
||||
/*
|
||||
* Operating system
|
||||
*/
|
||||
#define FREEBSD 0 // FreeBSD (untested)
|
||||
#define MINGW 1 // Windows native (Mingw)
|
||||
#define LINUX 2 // Linux
|
||||
#define CYGWIN 3 // Cygwin
|
||||
|
||||
/*
|
||||
* System includes
|
||||
*/
|
||||
#include <arpa/inet.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Define this to '1' to cause the printing of source code file and line number
|
||||
* information with each log message. Set it to '0' for simple logging.
|
||||
*/
|
||||
#define VERBOSE_LOGS 0
|
||||
|
||||
/*
|
||||
* Library includes
|
||||
*/
|
||||
#include "mycrypt.h" // LibTomCrypt
|
||||
#include "sam.h" // LibSAM
|
||||
|
||||
/*
|
||||
* Local includes
|
||||
*/
|
||||
#include "logger.hpp" // Logger
|
||||
#include "config.hpp" // Config
|
||||
#include "sam_error.hpp" // for sam.hpp
|
||||
#include "bigint.hpp" // for sha1.hpp
|
||||
#include "sha1.hpp" // for peers.hpp
|
||||
#include "peer.hpp" // for peers.hpp
|
||||
#include "near_peer.hpp" // for peers.hpp
|
||||
#include "peers.hpp" // for sam.hpp
|
||||
#include "sam.hpp" // SAM
|
||||
#include "random.hpp" // Random
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
extern Config *config; // Configuration options
|
||||
extern Logger *logger; // Logging mechanism
|
||||
extern Random *prng; // Random number generator
|
||||
extern Sam *sam; // Sam connection
|
||||
|
||||
#endif // PLATFORM_HPP
|
65
apps/enclave/src/random.cpp
Normal file
65
apps/enclave/src/random.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "random.hpp"
|
||||
|
||||
/*
|
||||
* Prepares the Yarrow PRNG for use
|
||||
*/
|
||||
Random::Random(void)
|
||||
{
|
||||
LMINOR << "Initalising PRNG\n";
|
||||
|
||||
int rc = yarrow_start(&prng);
|
||||
assert(rc == CRYPT_OK);
|
||||
|
||||
uchar_t entropy[ENTROPY_SIZE];
|
||||
size_t sz = rng_get_bytes(entropy, ENTROPY_SIZE, NULL);
|
||||
assert(sz == ENTROPY_SIZE);
|
||||
|
||||
rc = yarrow_add_entropy(entropy, ENTROPY_SIZE, &prng);
|
||||
assert(rc == CRYPT_OK);
|
||||
|
||||
rc = yarrow_ready(&prng);
|
||||
assert(rc == CRYPT_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets `size' random bytes from the PRNG
|
||||
*
|
||||
* random - space to fill with random bytes
|
||||
* size - size of `random'
|
||||
*/
|
||||
void Random::get_bytes(uchar_t* random, size_t size)
|
||||
{
|
||||
size_t sz = yarrow_read(random, size, &prng);
|
||||
assert(sz == size);
|
||||
}
|
45
apps/enclave/src/random.hpp
Normal file
45
apps/enclave/src/random.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RANDOM_HPP
|
||||
#define RANDOM_HPP
|
||||
|
||||
class Random {
|
||||
public:
|
||||
Random(void);
|
||||
|
||||
void get_bytes(uchar_t* random, size_t size);
|
||||
|
||||
private:
|
||||
static const size_t ENTROPY_SIZE = 32;
|
||||
prng_state prng;
|
||||
};
|
||||
|
||||
#endif // RNG_HPP
|
233
apps/enclave/src/rpc.cpp
Normal file
233
apps/enclave/src/rpc.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "rpc.hpp"
|
||||
|
||||
// These can't be 'const' because I have to make them big-endian first
|
||||
uint16_t Rpc::VERSION = htons(1);
|
||||
uint16_t Rpc::OLDEST_GOOD_VERSION = htons(1);
|
||||
|
||||
/*
|
||||
* Requests a peer to find the addresses of the closest peers to the specified
|
||||
* sha1 and return them
|
||||
*
|
||||
* sha1 - closeness to this sha1
|
||||
*/
|
||||
void Rpc::find_peers(const Sha1& sha1)
|
||||
{
|
||||
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: FIND_PEERS\n";
|
||||
|
||||
// VERSION + command + bin sha1
|
||||
const size_t len = sizeof VERSION + 1 + Sha1::SHA1BIN_LEN;
|
||||
uchar_t buf[len];
|
||||
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
|
||||
p += sizeof VERSION;
|
||||
*p = FIND_PEERS;
|
||||
p++;
|
||||
memcpy(p, sha1.binhash(), Sha1::SHA1BIN_LEN);
|
||||
sam->send_dgram(peer->get_dest(), buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the closest peer references to a Sha1
|
||||
*
|
||||
* sha1 - sha1 to test nearness to
|
||||
*/
|
||||
void Rpc::found_peers(const Sha1& sha1)
|
||||
{
|
||||
list<Near_peer> near_peers;
|
||||
sam->peers->get_nearest(sha1, Peers::RET_REFS, near_peers);
|
||||
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: FOUND_PEERS (" << near_peers.size() << " peers)\n";
|
||||
|
||||
// VERSION + command + number of sha1s (0-255) + bin sha1s
|
||||
const size_t len = sizeof VERSION + 1 + 1 +
|
||||
(near_peers.size() * (SAM_PUBKEY_LEN - 1));
|
||||
assert(near_peers.size() <= 255);
|
||||
uchar_t buf[len];
|
||||
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
|
||||
p += sizeof VERSION;
|
||||
*p = FOUND_PEERS;
|
||||
p++;
|
||||
*p = near_peers.size();
|
||||
p++;
|
||||
for (list<Near_peer>::const_iterator i = near_peers.begin();
|
||||
i != near_peers.end(); i++) {
|
||||
const Peer* peer = i->get_peer();
|
||||
memcpy(p, peer->get_dest().c_str(), (SAM_PUBKEY_LEN - 1));
|
||||
p += SAM_PUBKEY_LEN - 1;
|
||||
}
|
||||
sam->send_dgram(peer->get_dest(), buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse incoming data and invoke the appropriate RPC
|
||||
*
|
||||
* data - the data
|
||||
* size - the size of `data'
|
||||
*/
|
||||
void Rpc::parse(const void* data, size_t size)
|
||||
{
|
||||
uint16_t his_ver;
|
||||
|
||||
memcpy(&his_ver, data, sizeof VERSION);
|
||||
if (ntohs(his_ver) < ntohs(VERSION)) {
|
||||
LMINOR << "Ignored RPC from " << peer->get_sdest() << " ["
|
||||
<< peer->get_b64kaddr() << "] using obsolete protocol version "
|
||||
<< ntohs(his_ver) << '\n';
|
||||
return;
|
||||
} else if (size <= 4) {
|
||||
LWARN << "RPC too small from " << peer->get_sdest() << " ["
|
||||
<< peer->get_b64kaddr() << "]\n";
|
||||
return;
|
||||
}
|
||||
const uchar_t* p = static_cast<const uchar_t*>(data);
|
||||
|
||||
if (p[2] == PING) { //-----------------------------------------------------
|
||||
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: PING\n";
|
||||
uint32_t ptime;
|
||||
if (size != sizeof VERSION + 1 + sizeof ptime) {
|
||||
LWARN << "Malformed PING RPC from " << peer->get_sdest()
|
||||
<< " [" << peer->get_b64kaddr() << "]\n";
|
||||
return;
|
||||
}
|
||||
p += sizeof VERSION + 1;
|
||||
memcpy(&ptime, p, sizeof ptime);
|
||||
pong(ptime); // no need to ntohl() it here because we're just copying it
|
||||
return;
|
||||
|
||||
} else if (p[2] == PONG) { //----------------------------------------------
|
||||
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: PONG\n";
|
||||
uint32_t ptime;
|
||||
if (size != sizeof VERSION + 1 + sizeof ptime) {
|
||||
LWARN << "Malformed PONG RPC from " << peer->get_sdest()
|
||||
<< " [" << peer->get_b64kaddr() << "]\n";
|
||||
return;
|
||||
}
|
||||
p += sizeof VERSION + 1;
|
||||
memcpy(&ptime, p, sizeof ptime);
|
||||
ptime = ntohl(ptime);
|
||||
uint32_t now = time(NULL);
|
||||
peer->set_lag(now - ptime);
|
||||
LDEBUG << "Lag is " << peer->get_lag() << " seconds\n";
|
||||
return;
|
||||
|
||||
} else if (p[2] == FIND_PEERS) { //----------------------------------------
|
||||
if (size != sizeof VERSION + 1 + Sha1::SHA1BIN_LEN) {
|
||||
LWARN << "Malformed FIND_PEERS RPC from " << peer->get_sdest()
|
||||
<< " [" << peer->get_b64kaddr() << "]\n";
|
||||
return;
|
||||
}
|
||||
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: FIND_PEERS\n";
|
||||
found_peers(Sha1(p + 4));
|
||||
return;
|
||||
|
||||
} else if (p[2] == FOUND_PEERS) { //---------------------------------------
|
||||
const size_t refs = p[3];
|
||||
if (size != sizeof VERSION + 1 + 1 + (refs * (SAM_PUBKEY_LEN - 1))) {
|
||||
LWARN << "Malformed FOUND_PEERS RPC from " << peer->get_sdest()
|
||||
<< " [" << peer->get_b64kaddr() << "]\n";
|
||||
return;
|
||||
}
|
||||
LDEBUG << "From: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: FOUND_PEERS (" << refs << " peers)\n";
|
||||
p += sizeof VERSION + 1 + 1;
|
||||
for (size_t i = 1; i <= refs; i++) {
|
||||
sam_pubkey_t dest;
|
||||
memcpy(dest, p, SAM_PUBKEY_LEN - 1); // - 1 == no NUL in RPC
|
||||
dest[SAM_PUBKEY_LEN - 1] = '\0';
|
||||
//LDEBUG << "Message had: " << dest << '\n';
|
||||
sam->peers->new_peer(dest);
|
||||
p += SAM_PUBKEY_LEN - 1;
|
||||
}
|
||||
return;
|
||||
|
||||
} else //------------------------------------------------------------------
|
||||
LWARN << "Unknown RPC #" << static_cast<int>(p[2]) << " from "
|
||||
<< peer->get_sdest() << " [" << peer->get_b64kaddr() << "]\n";
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a ping to someone
|
||||
*/
|
||||
void Rpc::ping(void)
|
||||
{
|
||||
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: PING\n";
|
||||
|
||||
uint32_t now = htonl(time(NULL));
|
||||
// VERSION + command + seconds since 1970
|
||||
const size_t len = sizeof VERSION + 1 + sizeof now;
|
||||
uchar_t buf[len];
|
||||
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
|
||||
p += sizeof VERSION;
|
||||
*p = PING;
|
||||
p++;
|
||||
memcpy(p, &now, sizeof now);
|
||||
sam->send_dgram(peer->get_dest(), buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a ping reply to someone
|
||||
*
|
||||
* ptime - the time the peer sent us (we echo the same time back)
|
||||
*/
|
||||
void Rpc::pong(uint32_t ptime)
|
||||
{
|
||||
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: PONG\n";
|
||||
|
||||
// VERSION + command + pinger's seconds since 1970 echoed back
|
||||
const size_t len = sizeof VERSION + 1 + sizeof ptime;
|
||||
uchar_t buf[len];
|
||||
uchar_t* p = static_cast<uchar_t*>(memcpy(buf, &VERSION, sizeof VERSION));
|
||||
p += sizeof VERSION;
|
||||
*p = PONG;
|
||||
p++;
|
||||
memcpy(p, &ptime, sizeof ptime);
|
||||
sam->send_dgram(peer->get_dest(), buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tells a peer to store some data
|
||||
*
|
||||
* sha1 - sha1 value for the data
|
||||
* data - the data
|
||||
*/
|
||||
void Rpc::store(const Sha1& sha1)
|
||||
{
|
||||
LDEBUG << "To: " << peer->get_sdest() << " [" << peer->get_b64kaddr()
|
||||
<< "] Msg: STORE\n";
|
||||
}
|
65
apps/enclave/src/rpc.hpp
Normal file
65
apps/enclave/src/rpc.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RPC_HPP
|
||||
#define RPC_HPP
|
||||
|
||||
class Rpc {
|
||||
public:
|
||||
// The PROTOCOL version we are using
|
||||
static uint16_t VERSION;
|
||||
// The oldest version we will talk to
|
||||
static uint16_t OLDEST_GOOD_VERSION;
|
||||
// RPC identifiers (0-255)
|
||||
typedef enum {
|
||||
PING = 0,
|
||||
PONG = 1,
|
||||
FIND_PEERS = 2,
|
||||
FOUND_PEERS = 3,
|
||||
STORE = 4
|
||||
} rpc_t;
|
||||
|
||||
Rpc(Peer* peer)
|
||||
: peer(peer) {};
|
||||
|
||||
void find_peers(const Sha1& sha1);
|
||||
void parse(const void* data, size_t size);
|
||||
void ping(void);
|
||||
void store(const Sha1& sha1);
|
||||
|
||||
private:
|
||||
void found_peers(const Sha1& sha1);
|
||||
void pong(uint32_t ptime);
|
||||
|
||||
Peer* peer;
|
||||
basic_string<uchar_t> data;
|
||||
};
|
||||
|
||||
#endif // RPC_HPP
|
248
apps/enclave/src/sam.cpp
Normal file
248
apps/enclave/src/sam.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "rpc.hpp"
|
||||
#include "sam.hpp"
|
||||
|
||||
extern "C" {
|
||||
/*
|
||||
* Assorted callbacks required by LibSAM - ugly, but it works
|
||||
*/
|
||||
static void dgramback(sam_pubkey_t dest, void* data, size_t size);
|
||||
static void diedback(void);
|
||||
static void logback(char* str);
|
||||
static void namingback(char* name, sam_pubkey_t pubkey, samerr_t result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prevents more than one Sam object from existing in the program at a time
|
||||
* (LibSAM limitation)
|
||||
*/
|
||||
bool Sam::exists = false;
|
||||
|
||||
Sam::Sam(const string& samhost, uint16_t samport, const string& destname,
|
||||
uint_t tunneldepth)
|
||||
{
|
||||
// Only allow one Sam object to exist at a time
|
||||
assert(!exists);
|
||||
exists = true;
|
||||
|
||||
// hook up callbacks
|
||||
sam_dgramback = &dgramback;
|
||||
sam_diedback = &diedback;
|
||||
sam_logback = &logback;
|
||||
sam_namingback = &namingback;
|
||||
|
||||
// we haven't connected to SAM yet
|
||||
set_connected(false);
|
||||
|
||||
// now try to connect to SAM
|
||||
connect(samhost.c_str(), samport, destname.c_str(), tunneldepth);
|
||||
}
|
||||
|
||||
Sam::~Sam(void)
|
||||
{
|
||||
delete peers; // this must be before set_connected(false)!
|
||||
if (get_connected()) {
|
||||
sam_close();
|
||||
set_connected(false);
|
||||
}
|
||||
exists = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connects to the SAM host
|
||||
*
|
||||
* samhost - host that SAM is running on (hostname or IP address)
|
||||
* samport - port number that SAM is running own
|
||||
* destname - the destination name of this program
|
||||
* tunneldepth - how long the tunnels should be
|
||||
*/
|
||||
void Sam::connect(const char* samhost, uint16_t samport, const char* destname,
|
||||
uint_t tunneldepth)
|
||||
{
|
||||
assert(!get_connected());
|
||||
LMINOR << "Connecting to SAM as '" << destname << "'\n";
|
||||
samerr_t rc = sam_connect(samhost, samport, destname, SAM_DGRAM, tunneldepth);
|
||||
if (rc == SAM_OK)
|
||||
set_connected(true);
|
||||
else
|
||||
throw Sam_error(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads peer references from disk
|
||||
* Note: this can only be called after my_dest has been set
|
||||
*/
|
||||
void Sam::load_peers(void)
|
||||
{
|
||||
peers = new Peers(config->get_cproperty("references"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts `name' to a base 64 destination
|
||||
*
|
||||
* name - name to lookup
|
||||
*/
|
||||
void Sam::naming_lookup(const string& name) const
|
||||
{
|
||||
assert(get_connected());
|
||||
sam_naming_lookup(name.c_str());
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses an incoming datagram
|
||||
*
|
||||
* dest - source destination address
|
||||
* data - datagram payload
|
||||
* size - size of `data'
|
||||
*/
|
||||
void Sam::parse_dgram(const string& dest, void* data, size_t size)
|
||||
{
|
||||
assert(get_connected());
|
||||
Peer* peer = peers->new_peer(dest);
|
||||
Rpc rpc(peer);
|
||||
rpc.parse(data, size);
|
||||
rpc.ping();
|
||||
free(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks the SAM connection for incoming commands and invokes callbacks
|
||||
*/
|
||||
void Sam::read_buffer(void)
|
||||
{
|
||||
assert(get_connected());
|
||||
sam_read_buffer();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a datagram to a destination
|
||||
*
|
||||
* dest - destination to send to
|
||||
* data - data to send
|
||||
* size - size of `data'
|
||||
*/
|
||||
void Sam::send_dgram(const string& dest, uchar_t *data, size_t size)
|
||||
{
|
||||
samerr_t rc = sam_dgram_send(dest.c_str(), data, size);
|
||||
assert(rc == SAM_OK); // i.e. not SAM_TOO_BIG
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the connection status
|
||||
*
|
||||
* connected - true for connected, false for disconnected
|
||||
*/
|
||||
void Sam::set_connected(bool connected)
|
||||
{
|
||||
if (!connected)
|
||||
my_dest = "";
|
||||
this->connected = connected;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets my destination address
|
||||
*
|
||||
* pubkey - the base 64 destination
|
||||
*/
|
||||
void Sam::set_my_dest(const sam_pubkey_t pubkey)
|
||||
{
|
||||
my_dest = pubkey;
|
||||
my_sha1 = Sha1(my_dest);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the destination specified is of a valid base 64 syntax
|
||||
*
|
||||
* Returns: true if it is valid, false if it isn't
|
||||
*/
|
||||
bool Sam::valid_dest(const string& dest)
|
||||
{
|
||||
if (dest.size() != 516)
|
||||
return false;
|
||||
if (dest.substr(512, 4) == "AAAA") // note this AAAA signifies a null
|
||||
return true; // certificate - may not be true in the
|
||||
else // future
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* * * * Callbacks * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Unfortunately these aren't part of the "Sam" object because they are function
|
||||
* pointers to _C_ functions. As a hack, we just have them call the global Sam
|
||||
* object.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Callback: A datagram was received
|
||||
*/
|
||||
static void dgramback(sam_pubkey_t dest, void* data, size_t size)
|
||||
{
|
||||
sam->parse_dgram(dest, data, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback: The connection to SAM has failed
|
||||
*/
|
||||
static void diedback(void)
|
||||
{
|
||||
LERROR << "Connection to SAM lost!\n";
|
||||
sam->set_connected(false);
|
||||
throw Sam_error(SAM_SOCKET_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback: A log message has been sent from LibSAM
|
||||
*/
|
||||
static void logback(char* str)
|
||||
{
|
||||
LINFO << "LibSAM: " << str << '\n';
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback: A naming lookup has completed
|
||||
*/
|
||||
static void namingback(char* name, sam_pubkey_t pubkey, samerr_t result)
|
||||
{
|
||||
Sam_error res(result);
|
||||
if (res.code() == SAM_OK) {
|
||||
if (strcmp(name, "ME") == 0) {
|
||||
sam->set_my_dest(pubkey);
|
||||
sam->load_peers();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
} else {
|
||||
LERROR << "Naming look failed for '" << name << "': " << res.what()
|
||||
<< '\n';
|
||||
}
|
||||
}
|
66
apps/enclave/src/sam.hpp
Normal file
66
apps/enclave/src/sam.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SAM_HPP
|
||||
#define SAM_HPP
|
||||
|
||||
class Sam {
|
||||
public:
|
||||
Sam(const string& samhost, uint16_t samport, const string& destname,
|
||||
uint_t tunneldepth);
|
||||
~Sam(void);
|
||||
|
||||
const string& get_my_dest(void) const { return my_dest; }
|
||||
const Sha1& get_my_sha1(void) const { return my_sha1; }
|
||||
void naming_lookup(const string& name = "ME") const;
|
||||
void read_buffer(void);
|
||||
void send_dgram(const string& dest, uchar_t *data, size_t size);
|
||||
bool valid_dest(const string& dest);
|
||||
|
||||
Peers* peers;
|
||||
|
||||
//callback-private:
|
||||
void load_peers(void);
|
||||
void parse_dgram(const string& dest, void* data, size_t size);
|
||||
void set_connected(bool connected);
|
||||
void set_my_dest(const sam_pubkey_t pubkey);
|
||||
|
||||
private:
|
||||
void connect(const char* samhost, uint16_t samport,
|
||||
const char* destname, uint_t tunneldepth);
|
||||
bool get_connected(void) const { return connected; }
|
||||
|
||||
bool connected;
|
||||
static bool exists;
|
||||
string my_dest;
|
||||
Sha1 my_sha1;
|
||||
};
|
||||
|
||||
#endif // SAM_HPP
|
46
apps/enclave/src/sam_error.hpp
Normal file
46
apps/enclave/src/sam_error.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SAM_ERROR_HPP
|
||||
#define SAM_ERROR_HPP
|
||||
|
||||
class Sam_error {
|
||||
public:
|
||||
Sam_error(samerr_t error)
|
||||
: errcode(error) {}
|
||||
|
||||
samerr_t code(void) const { return errcode; }
|
||||
const char* what(void) const { return sam_strerror(errcode); }
|
||||
|
||||
private:
|
||||
const samerr_t errcode;
|
||||
};
|
||||
|
||||
#endif // SAM_ERROR_HPP
|
122
apps/enclave/src/sha1.cpp
Normal file
122
apps/enclave/src/sha1.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "sha1.hpp"
|
||||
|
||||
Sha1::Sha1(void)
|
||||
{
|
||||
b64hashed = "No value!";
|
||||
memset(binhashed, 0, sizeof binhashed);
|
||||
}
|
||||
|
||||
Sha1::Sha1(const string& data)
|
||||
{
|
||||
/* Hash it */
|
||||
hash_state md;
|
||||
sha1_init(&md);
|
||||
int rc = sha1_process(&md, reinterpret_cast<const uchar_t*>(data.c_str()),
|
||||
data.size());
|
||||
assert(rc == CRYPT_OK);
|
||||
rc = sha1_done(&md, binhashed);
|
||||
assert(rc == CRYPT_OK);
|
||||
b64();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialises the Sha1 object from a binary hash
|
||||
*/
|
||||
Sha1::Sha1(const uchar_t binary[SHA1BIN_LEN])
|
||||
{
|
||||
memcpy(binhashed, binary, sizeof binhashed);
|
||||
b64();
|
||||
}
|
||||
|
||||
/*
|
||||
* Base 64 the binary hash
|
||||
*/
|
||||
void Sha1::b64(void)
|
||||
{
|
||||
ulong_t outlen = 29;
|
||||
char tmp[outlen];
|
||||
// b64 FIXME: replace + with ~, and / with - to be like freenet
|
||||
int rc = base64_encode(binhashed, sizeof binhashed, reinterpret_cast<uchar_t*>(tmp), &outlen);
|
||||
assert(rc == CRYPT_OK);
|
||||
b64hashed = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares two Sha1s, returning true if the this one is less than the right one
|
||||
*/
|
||||
bool Sha1::operator<(const Sha1& rhs) const
|
||||
{
|
||||
Bigint lhsnum(binhashed, SHA1BIN_LEN);
|
||||
Bigint rhsnum(rhs.binhash(), SHA1BIN_LEN);
|
||||
if (lhsnum < rhsnum)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assigns a value from another Sha1 to this one
|
||||
*/
|
||||
Sha1& Sha1::operator=(const Sha1& rhs)
|
||||
{
|
||||
if (this != &rhs) { // check for self-assignment: a = a
|
||||
b64hashed = rhs.b64hash();
|
||||
memcpy(binhashed, rhs.binhash(), sizeof binhashed);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares Sha1s for equality
|
||||
*/
|
||||
bool Sha1::operator==(const Sha1& rhs) const
|
||||
{
|
||||
if (memcmp(binhashed, rhs.binhash(), sizeof binhashed) == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Xors this Sha1 with another, and stores the result in a Bigint
|
||||
*
|
||||
* rhs - sha1 to xor this one with
|
||||
* result - will be filled with the result
|
||||
*/
|
||||
void Sha1::x_or(const Sha1& rhs, Bigint& result) const
|
||||
{
|
||||
Bigint lhsnum(binhashed, SHA1BIN_LEN);
|
||||
Bigint rhsnum(rhs.binhash(), SHA1BIN_LEN);
|
||||
lhsnum.x_or(rhsnum, result);
|
||||
}
|
56
apps/enclave/src/sha1.hpp
Normal file
56
apps/enclave/src/sha1.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_HPP
|
||||
#define SHA1_HPP
|
||||
|
||||
class Sha1 {
|
||||
public:
|
||||
static const size_t SHA1BIN_LEN = 20;
|
||||
|
||||
Sha1(void);
|
||||
Sha1(const string& data);
|
||||
Sha1(const uchar_t binary[SHA1BIN_LEN]);
|
||||
|
||||
const string& b64hash(void) const { return b64hashed; }
|
||||
const uchar_t* binhash(void) const { return binhashed; }
|
||||
bool operator<(const Sha1& rhs) const;
|
||||
Sha1& operator=(const Sha1& rhs);
|
||||
bool operator==(const Sha1& rhs) const;
|
||||
void x_or(const Sha1& rhs, Bigint& result) const;
|
||||
|
||||
private:
|
||||
void b64(void);
|
||||
|
||||
string b64hashed; // base 64 of the hash
|
||||
uchar_t binhashed[SHA1BIN_LEN]; // non-NUL terminated binary hash
|
||||
};
|
||||
|
||||
#endif // SHA1_HPP
|
@@ -11,6 +11,7 @@ import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.client.I2PSession;
|
||||
@@ -219,7 +220,8 @@ class I2PAdapter {
|
||||
DataHelper.writeDate(baos, new Date(now));
|
||||
int padding = size - baos.size();
|
||||
byte paddingData[] = new byte[padding];
|
||||
Arrays.fill(paddingData, (byte) 0x2A);
|
||||
I2PAppContext.getGlobalContext().random().nextBytes(paddingData);
|
||||
//Arrays.fill(paddingData, (byte) 0x2A);
|
||||
DataHelper.writeLong(baos, 2, padding);
|
||||
baos.write(paddingData);
|
||||
boolean sent = _session.sendMessage(peer, baos.toByteArray());
|
||||
@@ -600,4 +602,4 @@ class I2PAdapter {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
private String wwwProxy;
|
||||
|
||||
private final static byte[] ERR_REQUEST_DENIED =
|
||||
("HTTP/1.1 404 Not Found\r\n"+
|
||||
("HTTP/1.1 403 Access Denied\r\n"+
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"+
|
||||
"Cache-control: no-cache\r\n"+
|
||||
"\r\n"+
|
||||
@@ -54,20 +54,20 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
.getBytes();
|
||||
|
||||
private final static byte[] ERR_DESTINATION_UNKNOWN =
|
||||
("HTTP/1.1 404 Not Found\r\n"+
|
||||
("HTTP/1.1 503 Service Unavailable\r\n"+
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"+
|
||||
"Cache-control: no-cache\r\n"+
|
||||
"\r\n"+
|
||||
"<html><body><H1>I2P ERROR: NOT FOUND</H1>"+
|
||||
"That Desitination was not found. Perhaps you pasted in the wrong "+
|
||||
"BASE64 I2P Destination or the link you are following is bad. "+
|
||||
"The host (or the WWW proxy, if you're using one) could also be "+
|
||||
"temporarily offline. You may want to <b>retry</b>. "+
|
||||
"<html><body><H1>I2P ERROR: DESTINATION NOT FOUND</H1>"+
|
||||
"That I2P Desitination was not found. Perhaps you pasted in the "+
|
||||
"wrong BASE64 I2P Destination or the link you are following is "+
|
||||
"bad. The host (or the WWW proxy, if you're using one) could also "+
|
||||
"be temporarily offline. You may want to <b>retry</b>. "+
|
||||
"Could not find the following Destination:<BR><BR>")
|
||||
.getBytes();
|
||||
|
||||
private final static byte[] ERR_TIMEOUT =
|
||||
("HTTP/1.1 404 Not Found\r\n"+
|
||||
("HTTP/1.1 504 Gateway Timeout\r\n"+
|
||||
"Content-Type: text/html; charset=iso-8859-1\r\n"+
|
||||
"Cache-control: no-cache\r\n\r\n"+
|
||||
"<html><body><H1>I2P ERROR: TIMEOUT</H1>"+
|
||||
|
@@ -14,8 +14,8 @@ import java.net.SocketException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.I2PClientFactory;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
|
@@ -18,7 +18,7 @@ import net.i2p.util.Log;
|
||||
* Main driver for the app that harvests data about the performance of the network,
|
||||
* building summaries for each peer that change over time. <p />
|
||||
*
|
||||
* Usage: <code>NetMonitor [configFilename]</code> <p />
|
||||
* Usage: <code>NetMonitor [configFilename] [--routers filename[,filename]*]</code> <p />
|
||||
*
|
||||
*
|
||||
*
|
||||
@@ -41,15 +41,20 @@ public class NetMonitor {
|
||||
private int _exportDelay;
|
||||
private String _exportDir;
|
||||
private String _netDbDir;
|
||||
private String _explicitRouters;
|
||||
private int _summaryDurationHours;
|
||||
private boolean _isRunning;
|
||||
private Map _peerSummaries;
|
||||
|
||||
public NetMonitor() {
|
||||
this(CONFIG_LOCATION_DEFAULT);
|
||||
this(CONFIG_LOCATION_DEFAULT, null);
|
||||
}
|
||||
public NetMonitor(String configLocation) {
|
||||
this(configLocation, null);
|
||||
}
|
||||
public NetMonitor(String configLocation, String explicitFilenames) {
|
||||
_configLocation = configLocation;
|
||||
_explicitRouters = explicitFilenames;
|
||||
_peerSummaries = new HashMap(32);
|
||||
loadConfig();
|
||||
}
|
||||
@@ -120,6 +125,8 @@ public class NetMonitor {
|
||||
public int getSummaryDurationHours() { return _summaryDurationHours; }
|
||||
/** where should we read the data from? */
|
||||
public String getNetDbDir() { return _netDbDir; }
|
||||
/** if specified, contains a set of filenames we want to harvest routerInfo data from */
|
||||
public String getExplicitRouters() { return _explicitRouters; }
|
||||
/**
|
||||
* what peers are we keeping track of?
|
||||
*
|
||||
@@ -203,10 +210,30 @@ public class NetMonitor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* main driver for the netMonitor. the usage is:
|
||||
* <code>NetMonitor [configFilename] [--routers filename[,filename]*]</code>
|
||||
*/
|
||||
public static final void main(String args[]) {
|
||||
if (args.length == 1)
|
||||
new NetMonitor(args[0]).startMonitor();
|
||||
else
|
||||
new NetMonitor(CONFIG_LOCATION_DEFAULT).startMonitor();
|
||||
String cfgLocation = CONFIG_LOCATION_DEFAULT;
|
||||
String explicitFilenames = null;
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
cfgLocation = args[0];
|
||||
break;
|
||||
case 2:
|
||||
explicitFilenames = args[1];
|
||||
break;
|
||||
case 3:
|
||||
cfgLocation = args[0];
|
||||
explicitFilenames = args[2];
|
||||
break;
|
||||
default:
|
||||
System.err.println("Usage: NetMonitor [configFilename] [--routers filename[,filename]*]");
|
||||
return;
|
||||
}
|
||||
new NetMonitor(cfgLocation, explicitFilenames).startMonitor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.RouterInfo;
|
||||
@@ -128,12 +129,35 @@ class NetMonitorRunner implements Runnable {
|
||||
* @return list of File objects pointing at the routers around
|
||||
*/
|
||||
private File[] listRouters() {
|
||||
File dbDir = new File(_monitor.getNetDbDir());
|
||||
File files[] = dbDir.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File f, String name) {
|
||||
return name.startsWith("routerInfo-");
|
||||
}
|
||||
});
|
||||
if (_monitor.getExplicitRouters() != null) {
|
||||
return listRoutersExplicit();
|
||||
} else {
|
||||
File dbDir = new File(_monitor.getNetDbDir());
|
||||
File files[] = dbDir.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File f, String name) {
|
||||
return name.startsWith("routerInfo-");
|
||||
}
|
||||
});
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of router files that were explicitly specified by the netMonitor
|
||||
*
|
||||
*/
|
||||
private File[] listRoutersExplicit() {
|
||||
StringTokenizer tok = new StringTokenizer(_monitor.getExplicitRouters().trim(), ",");
|
||||
List rv = new ArrayList();
|
||||
while (tok.hasMoreTokens()) {
|
||||
String name = tok.nextToken();
|
||||
File cur = new File(name);
|
||||
if (cur.exists())
|
||||
rv.add(cur);
|
||||
}
|
||||
File files[] = new File[rv.size()];
|
||||
for (int i = 0; i < rv.size(); i++)
|
||||
files[i] = (File)rv.get(i);
|
||||
return files;
|
||||
}
|
||||
|
||||
@@ -146,4 +170,4 @@ class NetMonitorRunner implements Runnable {
|
||||
Thread.sleep(_monitor.getHarvestDelay());
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
apps/sam/c/LICENSE
Normal file
27
apps/sam/c/LICENSE
Normal 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.
|
65
apps/sam/c/Makefile.cygwin
Normal file
65
apps/sam/c/Makefile.cygwin
Normal file
@@ -0,0 +1,65 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make and should work on Cygwin
|
||||
#
|
||||
|
||||
#
|
||||
# Your operating system
|
||||
#
|
||||
|
||||
OS = CYGWIN
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
INCDIR = inc
|
||||
LIBDIR = lib
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
AR = ar
|
||||
CC = gcc
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
|
||||
CFLAGS += -DOS=$(OS)
|
||||
CFLAGS += -I$(INCDIR)
|
||||
|
||||
#
|
||||
# Object files
|
||||
#
|
||||
|
||||
OBJS = $(OBJDIR)/sam.o \
|
||||
$(OBJDIR)/snprintf.o \
|
||||
$(OBJDIR)/strl.o
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: depend libsam
|
||||
|
||||
depend:
|
||||
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
libsam: $(OBJS)
|
||||
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||
|
||||
tidy: clean
|
64
apps/sam/c/Makefile.linux
Normal file
64
apps/sam/c/Makefile.linux
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make and should work on Linux (generic)
|
||||
#
|
||||
|
||||
#
|
||||
# Your operating system
|
||||
#
|
||||
|
||||
OS = LINUX
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
INCDIR = inc
|
||||
LIBDIR = lib
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
AR = ar
|
||||
CC = gcc
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -O2 -pipe -std=c99 -Wall
|
||||
CFLAGS += -DOS=$(OS)
|
||||
CFLAGS += -I$(INCDIR)
|
||||
|
||||
#
|
||||
# Object files
|
||||
#
|
||||
|
||||
OBJS = $(OBJDIR)/sam.o \
|
||||
$(OBJDIR)/strl.o
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: depend libsam
|
||||
|
||||
depend:
|
||||
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
libsam: $(OBJS)
|
||||
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||
|
||||
tidy: clean
|
64
apps/sam/c/Makefile.mingw
Normal file
64
apps/sam/c/Makefile.mingw
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make and should work on Windows (MingW)
|
||||
#
|
||||
|
||||
#
|
||||
# Your operating system
|
||||
#
|
||||
|
||||
OS = MINGW
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
INCDIR = inc
|
||||
LIBDIR = lib
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
AR = C:\Dev-Cpp\bin\ar
|
||||
CC = C:\Dev-Cpp\bin\gcc
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
|
||||
CFLAGS += -DOS=$(OS)
|
||||
CFLAGS += -I$(INCDIR)
|
||||
|
||||
#
|
||||
# Object files
|
||||
#
|
||||
|
||||
OBJS = $(OBJDIR)/sam.o \
|
||||
$(OBJDIR)/strl.o
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: depend libsam
|
||||
|
||||
depend:
|
||||
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
libsam: $(OBJS)
|
||||
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||
|
||||
tidy: clean
|
7
apps/sam/c/doc/donate.txt
Normal file
7
apps/sam/c/doc/donate.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
If you would like to make a donation to the author of this library, you can use
|
||||
the following methods:
|
||||
|
||||
* E-Gold account number 1043280
|
||||
* Paypal email mpc@innographx.com
|
||||
|
||||
If you want to use some other method, just ask.
|
27
apps/sam/c/doc/license.txt
Normal file
27
apps/sam/c/doc/license.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of any contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
9
apps/sam/c/doc/todo.txt
Normal file
9
apps/sam/c/doc/todo.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
I need to do these things:
|
||||
|
||||
* SAM raw support
|
||||
* Write an instruction manual
|
||||
|
||||
Anyone can help with these things:
|
||||
|
||||
* Fix the example dgram-client.c
|
||||
* Compile on as many platforms as possible
|
27
apps/sam/c/doc/whatsnew.txt
Normal file
27
apps/sam/c/doc/whatsnew.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
v1.15 2004-06-23
|
||||
* Added a new example program, warhammer-dgram (use with caution)
|
||||
* Fixed some fatal bugs in datagram handling
|
||||
* Added another error return type named SAM_TOO_BIG - some functions now
|
||||
return samerr_t instead of bool
|
||||
|
||||
v1.10 2004-06-16
|
||||
* Changed sam_strerror() to work the same as the standard library strerror()
|
||||
* Ported to native MS Windows (uses the Mingw development environment)
|
||||
* Fixed a probable bug in the Cygwin port
|
||||
|
||||
v1.05 2004-06-09
|
||||
* Added an example datagram client/server program in the examples directory
|
||||
* sam_read_buffer() now returns bool true if it read anything
|
||||
* Added repliable datagram support - sam_connect() now has another argument
|
||||
* Replaced strstr() with the more appropriate strncmp() in many places
|
||||
* Fixed a parsing error for STREAM CLOSED
|
||||
* Removed the old sam_naming_lookup() and renamed sam_naming_lookup_async()
|
||||
to sam_naming_lookup() to replace it
|
||||
* Fixed a bug in sam_stream_close() where a '\n' was not being sent after
|
||||
the SAM command
|
||||
* Fixed a bug where the stream ID was being improperly incremented in
|
||||
sam_stream_connect()
|
||||
* Added generic Linux Makefile for non-Debian distributions
|
||||
|
||||
v1.00 2004-06-02
|
||||
* First public release
|
42
apps/sam/c/examples/Makefile
Normal file
42
apps/sam/c/examples/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make
|
||||
#
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -O2 -pipe -std=c99 -Wall
|
||||
CFLAGS += -I../inc -L../lib
|
||||
LIBS = -lsam
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: dgram-client dgram-server warhammer-dgram
|
||||
|
||||
dgram-client:
|
||||
$(CC) $(CFLAGS) -o dgram-client.o -c dgram-client.c
|
||||
$(CC) $(CFLAGS) -o dgram-client dgram-client.o $(LIBS)
|
||||
|
||||
dgram-server:
|
||||
$(CC) $(CFLAGS) -o dgram-server.o -c dgram-server.c
|
||||
$(CC) $(CFLAGS) -o dgram-server dgram-server.o $(LIBS)
|
||||
|
||||
warhammer-dgram:
|
||||
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
|
||||
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f *.o *.exe dgram-client dgram-server warhammer-dgram
|
42
apps/sam/c/examples/Makefile.mingw
Normal file
42
apps/sam/c/examples/Makefile.mingw
Normal file
@@ -0,0 +1,42 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make and has Winsock linking
|
||||
#
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
CC = C:\Dev-Cpp\bin\gcc
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -O2 -pipe -std=c99 -Wall
|
||||
CFLAGS += -I../inc -L../lib
|
||||
LIBS = -lsam -lwsock32
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: dgram-client dgram-server warhammer-dgram
|
||||
|
||||
dgram-client:
|
||||
$(CC) $(CFLAGS) -o dgram-client.o -c dgram-client.c
|
||||
$(CC) $(CFLAGS) -o dgram-client dgram-client.o $(LIBS)
|
||||
|
||||
dgram-server:
|
||||
$(CC) $(CFLAGS) -o dgram-server.o -c dgram-server.c
|
||||
$(CC) $(CFLAGS) -o dgram-server dgram-server.o $(LIBS)
|
||||
|
||||
warhammer-dgram:
|
||||
$(CC) $(CFLAGS) -o warhammer-dgram.o -c warhammer-dgram.c
|
||||
$(CC) $(CFLAGS) -o warhammer-dgram warhammer-dgram.o $(LIBS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f *.o *.exe dgram-client dgram-server warhammer-dgram
|
130
apps/sam/c/examples/dgram-client.c
Normal file
130
apps/sam/c/examples/dgram-client.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sam.h"
|
||||
|
||||
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
|
||||
static void diedback(void);
|
||||
static void logback(char *s);
|
||||
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
|
||||
|
||||
/*
|
||||
* This is an extremely simple echo client which shows you how LibSAM
|
||||
* datagrams work. We lookup the name 'dgram-server' then send some data to
|
||||
* him. If everything works, we should get the same data back.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE!!!!!!!! This is currently broken!
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
samerr_t rc;
|
||||
|
||||
/* Hook up the callback functions */
|
||||
sam_dgramback = &dgramback;
|
||||
sam_diedback = &diedback;
|
||||
sam_logback = &logback;
|
||||
sam_namingback = &namingback;
|
||||
|
||||
/* Connect to the SAM server -- you can use either an IP or DNS name */
|
||||
rc = sam_connect("localhost", 7656, "dgram-client", SAM_DGRAM, 0);
|
||||
if (rc != SAM_OK) {
|
||||
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* This is equivalent to doing a DNS lookup on the normal internet. Note
|
||||
* that the dgram-server must already be running for this to work.
|
||||
* When the lookup completes, we send them some data (see namingback()).
|
||||
*/
|
||||
sam_naming_lookup("dgram-server");
|
||||
|
||||
/*
|
||||
* Wait for something to happen, then invoke the appropriate callback
|
||||
*/
|
||||
while (true)
|
||||
sam_read_buffer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we receive some data, print it out to the screen
|
||||
*/
|
||||
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
|
||||
{
|
||||
printf("Datagram received: %s\n", (char *)data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called whenever the SAM connection fails (like if the I2P router is
|
||||
* shut down)
|
||||
*/
|
||||
static void diedback(void)
|
||||
{
|
||||
fprintf(stderr, "Lost SAM connection!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The logging callback prints any logging messages from LibSAM
|
||||
*/
|
||||
static void logback(char *s)
|
||||
{
|
||||
fprintf(stderr, "LibSAM: %s\n", s);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a name is resolved, send data to that destination address
|
||||
*/
|
||||
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
|
||||
{
|
||||
char *data = "Hello, invisible world!";
|
||||
|
||||
printf("I got %s's base 64 destination, so now I will send him some " \
|
||||
"data...\n", name);
|
||||
sam_dgram_send(pubkey, data, strlen(data));
|
||||
/*
|
||||
* ^^^ An extra NUL is appended to the data by LibSAM, so it is not
|
||||
* necessary to send trailing NULs over the wire for strings. This doesn't
|
||||
* cause problems with binary data, because the NUL isn't included in `size'
|
||||
* in sam_dgramback().
|
||||
* That is why we use strlen(data) instead of strlen(data) + 1.
|
||||
*/
|
||||
puts("Datagram sent");
|
||||
}
|
108
apps/sam/c/examples/dgram-server.c
Normal file
108
apps/sam/c/examples/dgram-server.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "sam.h"
|
||||
|
||||
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
|
||||
static void diedback(void);
|
||||
static void logback(char *s);
|
||||
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
|
||||
|
||||
/*
|
||||
* This is an extremely simple echo server which shows you how LibSAM
|
||||
* datagrams work. We echo back every datagram that is sent to us.
|
||||
*/
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
samerr_t rc;
|
||||
|
||||
/* Hook up the callback functions */
|
||||
sam_dgramback = &dgramback;
|
||||
sam_diedback = &diedback;
|
||||
sam_logback = &logback;
|
||||
sam_namingback = &namingback;
|
||||
|
||||
/* Connect to the SAM server -- you can use either an IP or DNS name */
|
||||
rc = sam_connect("127.0.0.1", 7656, "dgram-server", SAM_DGRAM, 0);
|
||||
if (rc != SAM_OK) {
|
||||
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we just keep polling the buffer, which causes the
|
||||
* appropriate callbacks to be called whenever something happens
|
||||
*/
|
||||
while (true)
|
||||
sam_read_buffer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we receive some data, we just ECHO the exact same data back to them
|
||||
*/
|
||||
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
|
||||
{
|
||||
puts("Echoing datagram");
|
||||
sam_dgram_send(dest, data, size);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called whenever the SAM connection fails (like if the I2P router is
|
||||
* shut down)
|
||||
*/
|
||||
static void diedback(void)
|
||||
{
|
||||
fprintf(stderr, "Lost SAM connection!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The logging callback prints any logging messages from LibSAM
|
||||
*/
|
||||
static void logback(char *s)
|
||||
{
|
||||
fprintf(stderr, "LibSAM: %s\n", s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Not used, but the function has to be in the program anyway
|
||||
*/
|
||||
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
|
||||
{
|
||||
assert(false); /* we don't do any naming lookups in this program */
|
||||
}
|
123
apps/sam/c/examples/warhammer-dgram.c
Normal file
123
apps/sam/c/examples/warhammer-dgram.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Warhammer-dgram: a simple denial of service tool which uses datagrams, and
|
||||
* illustrates how LibSAM works.
|
||||
* Use only with the utmost courtesy.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sam.h"
|
||||
|
||||
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
|
||||
static void diedback(void);
|
||||
static void logback(char *s);
|
||||
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
|
||||
|
||||
bool gotdest = false;
|
||||
sam_pubkey_t dest;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Syntax: %s <b64dest|name>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sam_dgramback = &dgramback;
|
||||
sam_diedback = &diedback;
|
||||
sam_logback = &logback;
|
||||
sam_namingback = &namingback;
|
||||
|
||||
/* a tunnel length of 2 is the default - adjust to your preference vv */
|
||||
samerr_t rc = sam_connect("localhost", 7656, "TRANSIENT", SAM_DGRAM, 2);
|
||||
if (rc != SAM_OK) {
|
||||
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) == 516) {
|
||||
memcpy(dest, argv[1], SAM_PUBKEY_LEN);
|
||||
gotdest = true;
|
||||
}
|
||||
else
|
||||
sam_naming_lookup(argv[1]);
|
||||
|
||||
while (!gotdest)
|
||||
sam_read_buffer();
|
||||
|
||||
char data[SAM_DGRAM_PAYLOAD_MAX];
|
||||
memset(data, '#', SAM_DGRAM_PAYLOAD_MAX);
|
||||
size_t sentbytes = 0;
|
||||
while (true) {
|
||||
rc = sam_dgram_send(dest, data, SAM_DGRAM_PAYLOAD_MAX);
|
||||
if (rc != SAM_OK) {
|
||||
fprintf(stderr, "sam_dgram_send() failed: %s\n", sam_strerror(rc));
|
||||
return 1;
|
||||
}
|
||||
sentbytes += SAM_DGRAM_PAYLOAD_MAX;
|
||||
printf("Bombs away! (%u kbytes sent so far)\n", sentbytes / 1024);
|
||||
sam_read_buffer();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
|
||||
{
|
||||
puts("Received a datagram (ignored)");
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void diedback(void)
|
||||
{
|
||||
fprintf(stderr, "Lost SAM connection!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void logback(char *s)
|
||||
{
|
||||
fprintf(stderr, "LibSAM: %s\n", s);
|
||||
}
|
||||
|
||||
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
|
||||
{
|
||||
if (result != SAM_OK) {
|
||||
fprintf(stderr, "Naming lookup failed: %s\n", sam_strerror(result));
|
||||
exit(1);
|
||||
}
|
||||
memcpy(dest, pubkey, SAM_PUBKEY_LEN);
|
||||
gotdest = true;
|
||||
}
|
140
apps/sam/c/inc/platform.h
Normal file
140
apps/sam/c/inc/platform.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
/*
|
||||
* Operating system
|
||||
*/
|
||||
#define FREEBSD 0 // FreeBSD (untested)
|
||||
#define MINGW 1 // Windows native (Mingw)
|
||||
#define LINUX 2 // Linux
|
||||
#define CYGWIN 3 // Cygwin
|
||||
|
||||
#if OS == MINGW
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#define NO_GETHOSTBYNAME2
|
||||
#define NO_INET_ATON /* implies NO_INET_PTON */
|
||||
#define NO_INET_NTOP
|
||||
#define NO_STRL
|
||||
#define NO_Z_FORMAT
|
||||
#define WINSOCK
|
||||
#endif
|
||||
|
||||
#if OS == LINUX
|
||||
#define NO_GETHOSTBYNAME2
|
||||
#define NO_STRL
|
||||
#define NO_Z_FORMAT
|
||||
#endif
|
||||
|
||||
#if OS == CYGWIN
|
||||
#define FAST32_IS_LONG
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#define NO_GETHOSTBYNAME2
|
||||
#define NO_INET_NTOP
|
||||
#define NO_INET_PTON
|
||||
#define NO_SNPRINTF
|
||||
#define NO_STRL
|
||||
#define NO_VSNPRINTF
|
||||
#define NO_Z_FORMAT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Standard C99 includes - if your compiler doesn't have these, it's time to
|
||||
* upgrade
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* System includes
|
||||
*/
|
||||
#ifdef WINSOCK
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#ifndef WINSOCK
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#if defined NO_SNPRINTF || defined NO_VSNPRINTF
|
||||
#include "snprintf.h"
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef NO_STRL
|
||||
#include "strl.h"
|
||||
#endif
|
||||
#ifdef WINSOCK
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Platform-dependent variable types
|
||||
*/
|
||||
#ifdef WINSOCK
|
||||
typedef SOCKET socket_t;
|
||||
typedef signed long ssize_t;
|
||||
#else
|
||||
typedef int socket_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prints out the file name, line number, and function name before log message
|
||||
*/
|
||||
#define SAMLOG(format, ...) sam_log("%s:%d:%s: " \
|
||||
format, __FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* This is the same as above, except that it doesn't accept any va args
|
||||
*/
|
||||
#define SAMLOGS(str) sam_log("%s:%d:%s: " str, __FILE__, __LINE__, __func__)
|
||||
|
||||
/*
|
||||
* Set this to '1' if you want the raw SAM commands to be printed on stdout
|
||||
* (useful for debugging). Otherwise, set it to '0'.
|
||||
*/
|
||||
#define SAM_WIRETAP 0
|
||||
#if SAM_WIRETAP
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#endif /* PLATFORM_H */
|
123
apps/sam/c/inc/sam.h
Normal file
123
apps/sam/c/inc/sam.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SAM_H
|
||||
#define SAM_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Lengths
|
||||
*/
|
||||
#define SAM_CMD_LEN 128 /* the maximum length a SAM command can be */
|
||||
#define SAM_DGRAM_PAYLOAD_MAX ((31 * 1024) - 30) /* max size of a single datagram packet (-30 temporary bug fix for SAM) */
|
||||
#define SAM_ERRMSG_LEN 23 /* the longest message returned from sam_strerror */
|
||||
#define SAM_LOGMSG_LEN 256 /* the longest log message */
|
||||
#define SAM_NAME_LEN 256 /* the longest `name' arg for naming lookup callback*/
|
||||
#define SAM_STREAM_PAYLOAD_MAX 32768 /* max size of a single stream packet */
|
||||
#define SAM_PKCMD_LEN (SAM_PUBKEY_LEN + SAM_CMD_LEN)/*a public key SAM command*/
|
||||
#define SAM_PUBKEY_LEN 517 /* it's actually 516, but +1 for '\0' */
|
||||
#define SAM_REPLY_LEN 1024 /* the maximum length a SAM non-data reply can be */
|
||||
|
||||
/*
|
||||
* Shorten some standard variable types
|
||||
*/
|
||||
typedef signed char schar_t;
|
||||
typedef unsigned char uchar_t;
|
||||
typedef unsigned int uint_t;
|
||||
typedef unsigned long ulong_t;
|
||||
typedef unsigned short ushort_t;
|
||||
|
||||
typedef enum {SAM_STREAM, SAM_DGRAM, SAM_RAW} sam_conn_t; /* SAM connection */
|
||||
|
||||
typedef char sam_pubkey_t[SAM_PUBKEY_LEN]; /* base 64 public key */
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
size_t size;
|
||||
} sam_sendq_t; /* sending queue to encourage large stream packet sizes */
|
||||
|
||||
typedef int_fast32_t sam_sid_t; /* stream id number */
|
||||
|
||||
typedef enum { /* see sam_strerror() for detailed descriptions of these */
|
||||
/* error codes from SAM itself (SAM_OK is not an actual "error") */
|
||||
SAM_OK, SAM_CANT_REACH_PEER, SAM_DUPLICATED_DEST, SAM_I2P_ERROR,
|
||||
SAM_INVALID_KEY, SAM_KEY_NOT_FOUND, SAM_PEER_NOT_FOUND, SAM_TIMEOUT,
|
||||
SAM_UNKNOWN,
|
||||
/* error codes from libsam */
|
||||
SAM_BAD_VERSION, SAM_CALLBACKS_UNSET, SAM_SOCKET_ERROR, SAM_TOO_BIG
|
||||
} samerr_t;
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/* SAM controls */
|
||||
extern bool sam_close(void);
|
||||
extern samerr_t sam_connect(const char *samhost, uint16_t samport,
|
||||
const char *destname, sam_conn_t style, uint_t tunneldepth);
|
||||
extern void sam_naming_lookup(const char *name);
|
||||
extern bool sam_read_buffer(void);
|
||||
extern char *sam_strerror(samerr_t code);
|
||||
/* SAM controls - callbacks */
|
||||
extern void (*sam_diedback)(void);
|
||||
extern void (*sam_logback)(char *str);
|
||||
extern void (*sam_namingback)(char *name, sam_pubkey_t pubkey,
|
||||
samerr_t result);
|
||||
|
||||
/* Stream commands */
|
||||
extern void sam_stream_close(sam_sid_t stream_id);
|
||||
extern sam_sid_t sam_stream_connect(const sam_pubkey_t dest);
|
||||
extern samerr_t sam_stream_send(sam_sid_t stream_id, const void *data,
|
||||
size_t size);
|
||||
/* Stream commands - callbacks */
|
||||
extern void (*sam_closeback)(sam_sid_t stream_id, samerr_t reason);
|
||||
extern void (*sam_connectback)(sam_sid_t stream_id, sam_pubkey_t dest);
|
||||
extern void (*sam_databack)(sam_sid_t stream_id, void *data, size_t size);
|
||||
extern void (*sam_statusback)(sam_sid_t stream_id, samerr_t result);
|
||||
|
||||
/* Stream send queue */
|
||||
extern samerr_t sam_sendq_add(sam_sendq_t *sendq, const void *data,
|
||||
size_t dsize);
|
||||
extern sam_sendq_t *sam_sendq_create(void);
|
||||
extern void sam_sendq_send(sam_sendq_t *sendq, sam_sid_t stream_id);
|
||||
|
||||
/* Datagram commands */
|
||||
extern samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data,
|
||||
size_t size);
|
||||
|
||||
/* Datagram commands - callbacks */
|
||||
extern void (*sam_dgramback)(sam_pubkey_t dest, void *data, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* SAM_H */
|
49
apps/sam/c/inc/snprintf.h
Normal file
49
apps/sam/c/inc/snprintf.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: The snprintf.c file retains its original license (at the top of
|
||||
* snprintf.c)
|
||||
*/
|
||||
|
||||
#ifndef SNPRINTF_H
|
||||
#define SNPRINTF_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h> /* for va_list */
|
||||
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* SNPRINTF_H */
|
47
apps/sam/c/inc/strl.h
Normal file
47
apps/sam/c/inc/strl.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the author nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: The strl.c file retains its original license (at the top of strl.c)
|
||||
*/
|
||||
|
||||
#ifndef STRL_H
|
||||
#define STRL_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
extern size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* STRL_H */
|
1048
apps/sam/c/src/sam.c
Normal file
1048
apps/sam/c/src/sam.c
Normal file
File diff suppressed because it is too large
Load Diff
851
apps/sam/c/src/snprintf.c
Normal file
851
apps/sam/c/src/snprintf.c
Normal file
@@ -0,0 +1,851 @@
|
||||
/*
|
||||
* Copyright Patrick Powell 1995
|
||||
* This code is based on code written by Patrick Powell (papowell@astart.com)
|
||||
* It may be used for any purpose as long as this notice remains intact
|
||||
* on all source code distributions
|
||||
*/
|
||||
|
||||
/**************************************************************
|
||||
* Original:
|
||||
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
|
||||
* A bombproof version of doprnt (dopr) included.
|
||||
* Sigh. This sort of thing is always nasty do deal with. Note that
|
||||
* the version here does not include floating point...
|
||||
*
|
||||
* snprintf() is used instead of sprintf() as it does limit checks
|
||||
* for string length. This covers a nasty loophole.
|
||||
*
|
||||
* The other functions are there to prevent NULL pointers from
|
||||
* causing nast effects.
|
||||
*
|
||||
* More Recently:
|
||||
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
|
||||
* This was ugly. It is still ugly. I opted out of floating point
|
||||
* numbers, but the formatter understands just about everything
|
||||
* from the normal C string format, at least as far as I can tell from
|
||||
* the Solaris 2.5 printf(3S) man page.
|
||||
*
|
||||
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
|
||||
* Ok, added some minimal floating point support, which means this
|
||||
* probably requires libm on most operating systems. Don't yet
|
||||
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
|
||||
* was pretty badly broken, it just wasn't being exercised in ways
|
||||
* which showed it, so that's been fixed. Also, formated the code
|
||||
* to mutt conventions, and removed dead code left over from the
|
||||
* original. Also, there is now a builtin-test, just compile with:
|
||||
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
|
||||
* and run snprintf for results.
|
||||
*
|
||||
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
|
||||
* The PGP code was using unsigned hexadecimal formats.
|
||||
* Unfortunately, unsigned formats simply didn't work.
|
||||
*
|
||||
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
|
||||
* The original code assumed that both snprintf() and vsnprintf() were
|
||||
* missing. Some systems only have snprintf() but not vsnprintf(), so
|
||||
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
|
||||
*
|
||||
* Andrew Tridgell (tridge@samba.org) Oct 1998
|
||||
* fixed handling of %.0f
|
||||
* added test for HAVE_LONG_DOUBLE
|
||||
*
|
||||
* Russ Allbery <rra@stanford.edu> 2000-08-26
|
||||
* fixed return value to comply with C99
|
||||
* fixed handling of snprintf(NULL, ...)
|
||||
*
|
||||
* Hrvoje Niksic <hniksic@arsdigita.com> 2000-11-04
|
||||
* include <stdio.h> for NULL.
|
||||
* added support for long long.
|
||||
* don't declare argument types to (v)snprintf if stdarg is not used.
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
/* varargs declarations: */
|
||||
|
||||
#include <stdarg.h>
|
||||
#define HAVE_STDARGS /* let's hope that works everywhere (mj) */
|
||||
#define VA_LOCAL_DECL va_list ap
|
||||
#define VA_START(f) va_start(ap, f)
|
||||
#define VA_SHIFT(v,t) ; /* no-op for ANSI */
|
||||
#define VA_END va_end(ap)
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
#define LDOUBLE long double
|
||||
#else
|
||||
#define LDOUBLE double
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
# define LLONG long long
|
||||
#else
|
||||
# define LLONG long
|
||||
#endif
|
||||
|
||||
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||
|
||||
static int dopr (char *buffer, size_t maxlen, const char *format,
|
||||
va_list args);
|
||||
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||
char *value, int flags, int min, int max);
|
||||
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||
LLONG value, int base, int min, int max, int flags);
|
||||
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
LDOUBLE fvalue, int min, int max, int flags);
|
||||
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
|
||||
|
||||
/*
|
||||
* dopr(): poor man's version of doprintf
|
||||
*/
|
||||
|
||||
/* format read states */
|
||||
#define DP_S_DEFAULT 0
|
||||
#define DP_S_FLAGS 1
|
||||
#define DP_S_MIN 2
|
||||
#define DP_S_DOT 3
|
||||
#define DP_S_MAX 4
|
||||
#define DP_S_MOD 5
|
||||
#define DP_S_MOD_L 6
|
||||
#define DP_S_CONV 7
|
||||
#define DP_S_DONE 8
|
||||
|
||||
/* format flags - Bits */
|
||||
#define DP_F_MINUS (1 << 0)
|
||||
#define DP_F_PLUS (1 << 1)
|
||||
#define DP_F_SPACE (1 << 2)
|
||||
#define DP_F_NUM (1 << 3)
|
||||
#define DP_F_ZERO (1 << 4)
|
||||
#define DP_F_UP (1 << 5)
|
||||
#define DP_F_UNSIGNED (1 << 6)
|
||||
|
||||
/* Conversion Flags */
|
||||
#define DP_C_SHORT 1
|
||||
#define DP_C_LONG 2
|
||||
#define DP_C_LLONG 3
|
||||
#define DP_C_LDOUBLE 4
|
||||
|
||||
#define char_to_int(p) (p - '0')
|
||||
#define MAX(p,q) ((p >= q) ? p : q)
|
||||
#define MIN(p,q) ((p <= q) ? p : q)
|
||||
|
||||
static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
{
|
||||
char ch;
|
||||
LLONG value;
|
||||
LDOUBLE fvalue;
|
||||
char *strvalue;
|
||||
int min;
|
||||
int max;
|
||||
int state;
|
||||
int flags;
|
||||
int cflags;
|
||||
int total;
|
||||
size_t currlen;
|
||||
|
||||
state = DP_S_DEFAULT;
|
||||
currlen = flags = cflags = min = 0;
|
||||
max = -1;
|
||||
ch = *format++;
|
||||
total = 0;
|
||||
|
||||
while (state != DP_S_DONE)
|
||||
{
|
||||
if (ch == '\0')
|
||||
state = DP_S_DONE;
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case DP_S_DEFAULT:
|
||||
if (ch == '%')
|
||||
state = DP_S_FLAGS;
|
||||
else
|
||||
total += dopr_outch (buffer, &currlen, maxlen, ch);
|
||||
ch = *format++;
|
||||
break;
|
||||
case DP_S_FLAGS:
|
||||
switch (ch)
|
||||
{
|
||||
case '-':
|
||||
flags |= DP_F_MINUS;
|
||||
ch = *format++;
|
||||
break;
|
||||
case '+':
|
||||
flags |= DP_F_PLUS;
|
||||
ch = *format++;
|
||||
break;
|
||||
case ' ':
|
||||
flags |= DP_F_SPACE;
|
||||
ch = *format++;
|
||||
break;
|
||||
case '#':
|
||||
flags |= DP_F_NUM;
|
||||
ch = *format++;
|
||||
break;
|
||||
case '0':
|
||||
flags |= DP_F_ZERO;
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
state = DP_S_MIN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DP_S_MIN:
|
||||
if (isdigit((unsigned char)ch))
|
||||
{
|
||||
min = 10*min + char_to_int (ch);
|
||||
ch = *format++;
|
||||
}
|
||||
else if (ch == '*')
|
||||
{
|
||||
min = va_arg (args, int);
|
||||
ch = *format++;
|
||||
state = DP_S_DOT;
|
||||
}
|
||||
else
|
||||
state = DP_S_DOT;
|
||||
break;
|
||||
case DP_S_DOT:
|
||||
if (ch == '.')
|
||||
{
|
||||
state = DP_S_MAX;
|
||||
ch = *format++;
|
||||
}
|
||||
else
|
||||
state = DP_S_MOD;
|
||||
break;
|
||||
case DP_S_MAX:
|
||||
if (isdigit((unsigned char)ch))
|
||||
{
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
max = 10*max + char_to_int (ch);
|
||||
ch = *format++;
|
||||
}
|
||||
else if (ch == '*')
|
||||
{
|
||||
max = va_arg (args, int);
|
||||
ch = *format++;
|
||||
state = DP_S_MOD;
|
||||
}
|
||||
else
|
||||
state = DP_S_MOD;
|
||||
break;
|
||||
case DP_S_MOD:
|
||||
switch (ch)
|
||||
{
|
||||
case 'h':
|
||||
cflags = DP_C_SHORT;
|
||||
ch = *format++;
|
||||
break;
|
||||
case 'l':
|
||||
cflags = DP_C_LONG;
|
||||
ch = *format++;
|
||||
break;
|
||||
case 'L':
|
||||
cflags = DP_C_LDOUBLE;
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (cflags != DP_C_LONG)
|
||||
state = DP_S_CONV;
|
||||
else
|
||||
state = DP_S_MOD_L;
|
||||
break;
|
||||
case DP_S_MOD_L:
|
||||
switch (ch)
|
||||
{
|
||||
case 'l':
|
||||
cflags = DP_C_LLONG;
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = DP_S_CONV;
|
||||
break;
|
||||
case DP_S_CONV:
|
||||
switch (ch)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
if (cflags == DP_C_SHORT)
|
||||
value = (short int) va_arg (args, int);
|
||||
else if (cflags == DP_C_LONG)
|
||||
value = va_arg (args, long int);
|
||||
else if (cflags == DP_C_LLONG)
|
||||
value = va_arg (args, LLONG);
|
||||
else
|
||||
value = va_arg (args, int);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
|
||||
break;
|
||||
case 'o':
|
||||
flags |= DP_F_UNSIGNED;
|
||||
if (cflags == DP_C_SHORT)
|
||||
value = (unsigned short int) va_arg (args, unsigned int);
|
||||
else if (cflags == DP_C_LONG)
|
||||
value = va_arg (args, unsigned long int);
|
||||
else if (cflags == DP_C_LLONG)
|
||||
value = va_arg (args, unsigned LLONG);
|
||||
else
|
||||
value = va_arg (args, unsigned int);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
|
||||
break;
|
||||
case 'u':
|
||||
flags |= DP_F_UNSIGNED;
|
||||
if (cflags == DP_C_SHORT)
|
||||
value = (unsigned short int) va_arg (args, unsigned int);
|
||||
else if (cflags == DP_C_LONG)
|
||||
value = va_arg (args, unsigned long int);
|
||||
else if (cflags == DP_C_LLONG)
|
||||
value = va_arg (args, unsigned LLONG);
|
||||
else
|
||||
value = va_arg (args, unsigned int);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
|
||||
break;
|
||||
case 'X':
|
||||
flags |= DP_F_UP;
|
||||
case 'x':
|
||||
flags |= DP_F_UNSIGNED;
|
||||
if (cflags == DP_C_SHORT)
|
||||
value = (unsigned short int) va_arg (args, unsigned int);
|
||||
else if (cflags == DP_C_LONG)
|
||||
value = va_arg (args, unsigned long int);
|
||||
else if (cflags == DP_C_LLONG)
|
||||
value = va_arg (args, unsigned LLONG);
|
||||
else
|
||||
value = va_arg (args, unsigned int);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
|
||||
break;
|
||||
case 'f':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
fvalue = va_arg (args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
/* um, floating point? */
|
||||
total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||
break;
|
||||
case 'E':
|
||||
flags |= DP_F_UP;
|
||||
case 'e':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
fvalue = va_arg (args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
break;
|
||||
case 'G':
|
||||
flags |= DP_F_UP;
|
||||
case 'g':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
fvalue = va_arg (args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
break;
|
||||
case 'c':
|
||||
total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
|
||||
break;
|
||||
case 's':
|
||||
strvalue = va_arg (args, char *);
|
||||
total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
|
||||
break;
|
||||
case 'p':
|
||||
strvalue = va_arg (args, void *);
|
||||
total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min,
|
||||
max, flags);
|
||||
break;
|
||||
case 'n':
|
||||
if (cflags == DP_C_SHORT)
|
||||
{
|
||||
short int *num;
|
||||
num = va_arg (args, short int *);
|
||||
*num = currlen;
|
||||
}
|
||||
else if (cflags == DP_C_LONG)
|
||||
{
|
||||
long int *num;
|
||||
num = va_arg (args, long int *);
|
||||
*num = currlen;
|
||||
}
|
||||
else if (cflags == DP_C_LLONG)
|
||||
{
|
||||
LLONG *num;
|
||||
num = va_arg (args, LLONG *);
|
||||
*num = currlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
int *num;
|
||||
num = va_arg (args, int *);
|
||||
*num = currlen;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
total += dopr_outch (buffer, &currlen, maxlen, ch);
|
||||
break;
|
||||
case 'w':
|
||||
/* not supported yet, treat as next char */
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
/* Unknown, skip */
|
||||
break;
|
||||
}
|
||||
ch = *format++;
|
||||
state = DP_S_DEFAULT;
|
||||
flags = cflags = min = 0;
|
||||
max = -1;
|
||||
break;
|
||||
case DP_S_DONE:
|
||||
break;
|
||||
default:
|
||||
/* hmm? */
|
||||
break; /* some picky compilers need this */
|
||||
}
|
||||
}
|
||||
if (buffer != NULL)
|
||||
{
|
||||
if (currlen < maxlen - 1)
|
||||
buffer[currlen] = '\0';
|
||||
else
|
||||
buffer[maxlen - 1] = '\0';
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||
char *value, int flags, int min, int max)
|
||||
{
|
||||
int padlen, strln; /* amount to pad */
|
||||
int cnt = 0;
|
||||
int total = 0;
|
||||
char null[] = "<NULL>";
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
|
||||
for (strln = 0; value[strln]; ++strln); /* strlen */
|
||||
if (max >= 0 && max < strln)
|
||||
strln = max;
|
||||
padlen = min - strln;
|
||||
if (padlen < 0)
|
||||
padlen = 0;
|
||||
if (flags & DP_F_MINUS)
|
||||
padlen = -padlen; /* Left Justify */
|
||||
|
||||
while (padlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
--padlen;
|
||||
}
|
||||
while (*value && ((max < 0) || (cnt < max)))
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, *value++);
|
||||
++cnt;
|
||||
}
|
||||
while (padlen < 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++padlen;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
|
||||
|
||||
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||
LLONG value, int base, int min, int max, int flags)
|
||||
{
|
||||
int signvalue = 0;
|
||||
unsigned LLONG uvalue;
|
||||
char convert[24];
|
||||
unsigned int place = 0;
|
||||
int spadlen = 0; /* amount to space pad */
|
||||
int zpadlen = 0; /* amount to zero pad */
|
||||
const char *digits;
|
||||
int total = 0;
|
||||
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
|
||||
uvalue = value;
|
||||
|
||||
if(!(flags & DP_F_UNSIGNED))
|
||||
{
|
||||
if( value < 0 ) {
|
||||
signvalue = '-';
|
||||
uvalue = -value;
|
||||
}
|
||||
else
|
||||
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||
signvalue = '+';
|
||||
else
|
||||
if (flags & DP_F_SPACE)
|
||||
signvalue = ' ';
|
||||
}
|
||||
|
||||
if (flags & DP_F_UP)
|
||||
/* Should characters be upper case? */
|
||||
digits = "0123456789ABCDEF";
|
||||
else
|
||||
digits = "0123456789abcdef";
|
||||
|
||||
do {
|
||||
convert[place++] = digits[uvalue % (unsigned)base];
|
||||
uvalue = (uvalue / (unsigned)base );
|
||||
} while(uvalue && (place < sizeof (convert)));
|
||||
if (place == sizeof (convert)) place--;
|
||||
convert[place] = 0;
|
||||
|
||||
zpadlen = max - place;
|
||||
spadlen = min - MAX ((unsigned int)max, place) - (signvalue ? 1 : 0);
|
||||
if (zpadlen < 0) zpadlen = 0;
|
||||
if (spadlen < 0) spadlen = 0;
|
||||
if (flags & DP_F_ZERO)
|
||||
{
|
||||
zpadlen = MAX(zpadlen, spadlen);
|
||||
spadlen = 0;
|
||||
}
|
||||
if (flags & DP_F_MINUS)
|
||||
spadlen = -spadlen; /* Left Justifty */
|
||||
|
||||
#ifdef DEBUG_SNPRINTF
|
||||
dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
|
||||
zpadlen, spadlen, min, max, place));
|
||||
#endif
|
||||
|
||||
/* Spaces */
|
||||
while (spadlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
--spadlen;
|
||||
}
|
||||
|
||||
/* Sign */
|
||||
if (signvalue)
|
||||
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||
|
||||
/* Zeros */
|
||||
if (zpadlen > 0)
|
||||
{
|
||||
while (zpadlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Digits */
|
||||
while (place > 0)
|
||||
total += dopr_outch (buffer, currlen, maxlen, convert[--place]);
|
||||
|
||||
/* Left Justified spaces */
|
||||
while (spadlen < 0) {
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++spadlen;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static LDOUBLE abs_val (LDOUBLE value)
|
||||
{
|
||||
LDOUBLE result = value;
|
||||
|
||||
if (value < 0)
|
||||
result = -value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static LDOUBLE pow10 (int exp)
|
||||
{
|
||||
LDOUBLE result = 1;
|
||||
|
||||
while (exp)
|
||||
{
|
||||
result *= 10;
|
||||
exp--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static long round (LDOUBLE value)
|
||||
{
|
||||
long intpart;
|
||||
|
||||
intpart = value;
|
||||
value = value - intpart;
|
||||
if (value >= 0.5)
|
||||
intpart++;
|
||||
|
||||
return intpart;
|
||||
}
|
||||
|
||||
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
LDOUBLE fvalue, int min, int max, int flags)
|
||||
{
|
||||
int signvalue = 0;
|
||||
LDOUBLE ufvalue;
|
||||
char iconvert[20];
|
||||
char fconvert[20];
|
||||
int iplace = 0;
|
||||
int fplace = 0;
|
||||
int padlen = 0; /* amount to pad */
|
||||
int zpadlen = 0;
|
||||
int caps = 0;
|
||||
int total = 0;
|
||||
LLONG intpart;
|
||||
LLONG fracpart;
|
||||
|
||||
/*
|
||||
* AIX manpage says the default is 0, but Solaris says the default
|
||||
* is 6, and sprintf on AIX defaults to 6
|
||||
*/
|
||||
if (max < 0)
|
||||
max = 6;
|
||||
|
||||
ufvalue = abs_val (fvalue);
|
||||
|
||||
if (fvalue < 0)
|
||||
signvalue = '-';
|
||||
else
|
||||
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||
signvalue = '+';
|
||||
else
|
||||
if (flags & DP_F_SPACE)
|
||||
signvalue = ' ';
|
||||
|
||||
#if 0
|
||||
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
|
||||
#endif
|
||||
|
||||
intpart = ufvalue;
|
||||
|
||||
/*
|
||||
* Sorry, we only support 9 digits past the decimal because of our
|
||||
* conversion method
|
||||
*/
|
||||
if (max > 9)
|
||||
max = 9;
|
||||
|
||||
/* We "cheat" by converting the fractional part to integer by
|
||||
* multiplying by a factor of 10
|
||||
*/
|
||||
fracpart = round ((pow10 (max)) * (ufvalue - intpart));
|
||||
|
||||
if (fracpart >= pow10 (max))
|
||||
{
|
||||
intpart++;
|
||||
fracpart -= pow10 (max);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SNPRINTF
|
||||
dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
|
||||
#endif
|
||||
|
||||
/* Convert integer part */
|
||||
do {
|
||||
iconvert[iplace++] =
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
|
||||
intpart = (intpart / 10);
|
||||
} while(intpart && (iplace < 20));
|
||||
if (iplace == 20) iplace--;
|
||||
iconvert[iplace] = 0;
|
||||
|
||||
/* Convert fractional part */
|
||||
do {
|
||||
fconvert[fplace++] =
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
|
||||
fracpart = (fracpart / 10);
|
||||
} while(fracpart && (fplace < 20));
|
||||
if (fplace == 20) fplace--;
|
||||
fconvert[fplace] = 0;
|
||||
|
||||
/* -1 for decimal point, another -1 if we are printing a sign */
|
||||
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
|
||||
zpadlen = max - fplace;
|
||||
if (zpadlen < 0)
|
||||
zpadlen = 0;
|
||||
if (padlen < 0)
|
||||
padlen = 0;
|
||||
if (flags & DP_F_MINUS)
|
||||
padlen = -padlen; /* Left Justifty */
|
||||
|
||||
if ((flags & DP_F_ZERO) && (padlen > 0))
|
||||
{
|
||||
if (signvalue)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||
--padlen;
|
||||
signvalue = 0;
|
||||
}
|
||||
while (padlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--padlen;
|
||||
}
|
||||
}
|
||||
while (padlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
--padlen;
|
||||
}
|
||||
if (signvalue)
|
||||
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||
|
||||
while (iplace > 0)
|
||||
total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
|
||||
|
||||
/*
|
||||
* Decimal point. This should probably use locale to find the correct
|
||||
* char to print out.
|
||||
*/
|
||||
if (max > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '.');
|
||||
|
||||
while (fplace > 0)
|
||||
total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||
}
|
||||
|
||||
while (zpadlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
|
||||
while (padlen < 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++padlen;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||
{
|
||||
if (*currlen + 1 < maxlen)
|
||||
buffer[(*currlen)++] = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
|
||||
{
|
||||
if (str != NULL)
|
||||
str[0] = 0;
|
||||
return dopr(str, count, fmt, args);
|
||||
}
|
||||
|
||||
/* VARARGS3 */
|
||||
#ifdef HAVE_STDARGS
|
||||
int snprintf (char *str,size_t count,const char *fmt,...)
|
||||
#else
|
||||
int snprintf (va_alist) va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifndef HAVE_STDARGS
|
||||
char *str;
|
||||
size_t count;
|
||||
char *fmt;
|
||||
#endif
|
||||
VA_LOCAL_DECL;
|
||||
int total;
|
||||
|
||||
VA_START (fmt);
|
||||
VA_SHIFT (str, char *);
|
||||
VA_SHIFT (count, size_t );
|
||||
VA_SHIFT (fmt, char *);
|
||||
total = vsnprintf(str, count, fmt, ap);
|
||||
VA_END;
|
||||
return total;
|
||||
}
|
||||
|
||||
#ifdef TEST_SNPRINTF
|
||||
#ifndef LONG_STRING
|
||||
#define LONG_STRING 1024
|
||||
#endif
|
||||
int main (void)
|
||||
{
|
||||
char buf1[LONG_STRING];
|
||||
char buf2[LONG_STRING];
|
||||
char *fp_fmt[] = {
|
||||
"%-1.5f",
|
||||
"%1.5f",
|
||||
"%123.9f",
|
||||
"%10.5f",
|
||||
"% 10.5f",
|
||||
"%+22.9f",
|
||||
"%+4.9f",
|
||||
"%01.3f",
|
||||
"%4f",
|
||||
"%3.1f",
|
||||
"%3.2f",
|
||||
"%.0f",
|
||||
"%.1f",
|
||||
NULL
|
||||
};
|
||||
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
|
||||
0.9996, 1.996, 4.136, 0};
|
||||
char *int_fmt[] = {
|
||||
"%-1.5d",
|
||||
"%1.5d",
|
||||
"%123.9d",
|
||||
"%5.5d",
|
||||
"%10.5d",
|
||||
"% 10.5d",
|
||||
"%+22.33d",
|
||||
"%01.3d",
|
||||
"%4d",
|
||||
NULL
|
||||
};
|
||||
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
|
||||
int x, y;
|
||||
int fail = 0;
|
||||
int num = 0;
|
||||
|
||||
printf ("Testing snprintf format codes against system sprintf...\n");
|
||||
|
||||
for (x = 0; fp_fmt[x] != NULL ; x++)
|
||||
for (y = 0; fp_nums[y] != 0 ; y++)
|
||||
{
|
||||
snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
|
||||
sprintf (buf2, fp_fmt[x], fp_nums[y]);
|
||||
if (strcmp (buf1, buf2))
|
||||
{
|
||||
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
|
||||
fp_fmt[x], buf1, buf2);
|
||||
fail++;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
for (x = 0; int_fmt[x] != NULL ; x++)
|
||||
for (y = 0; int_nums[y] != 0 ; y++)
|
||||
{
|
||||
snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
|
||||
sprintf (buf2, int_fmt[x], int_nums[y]);
|
||||
if (strcmp (buf1, buf2))
|
||||
{
|
||||
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
|
||||
int_fmt[x], buf1, buf2);
|
||||
fail++;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
printf ("%d tests failed out of %d.\n", fail, num);
|
||||
}
|
||||
#endif /* SNPRINTF_TEST */
|
84
apps/sam/c/src/strl.c
Normal file
84
apps/sam/c/src/strl.c
Normal 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 */
|
||||
}
|
@@ -330,7 +330,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
}
|
||||
|
||||
if (dest == null) {
|
||||
return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND\n");
|
||||
return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND NAME=" + name + "\n");
|
||||
}
|
||||
|
||||
return writeString("NAMING REPLY RESULT=OK NAME=" + name
|
||||
@@ -392,7 +392,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
|
||||
if (!datagramSession.sendBytes(dest, data)) {
|
||||
_log.error("DATAGRAM SEND failed");
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -463,7 +463,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
|
||||
if (!rawSession.sendBytes(dest, data)) {
|
||||
_log.error("RAW SEND failed");
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -556,7 +556,9 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
|
||||
if (!streamSession.sendBytes(id, data)) {
|
||||
_log.error("STREAM SEND failed");
|
||||
return false;
|
||||
boolean rv = writeString("STREAM CLOSED RESULT=CANT_REACH_PEER ID=" + id + " MESSAGE=\"Send of " + size + " bytes failed\"\n");
|
||||
streamSession.closeConnection(id);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -758,7 +760,7 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
|
||||
msg.write(("STREAM RECEIVED ID=" + id
|
||||
+" SIZE=" + len + "\n").getBytes("ISO-8859-1"));
|
||||
msg.write(data);
|
||||
msg.write(data, 0, len);
|
||||
|
||||
writeBytes(msg.toByteArray());
|
||||
}
|
||||
|
@@ -50,13 +50,13 @@ public class Timestamper implements Runnable {
|
||||
while (true) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Querying servers " + _serverList);
|
||||
long now = NtpClient.currentTime(_serverList);
|
||||
if (now < 0) {
|
||||
_log.error("Unable to contact any of the NTP servers - network disconnect?");
|
||||
} else {
|
||||
try {
|
||||
long now = NtpClient.currentTime(_serverList);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Stamp time");
|
||||
stampTime(now);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
|
||||
}
|
||||
try { Thread.sleep(DELAY_MS); } catch (InterruptedException ie) {}
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
</target>
|
||||
<target name="dist" depends="distclean, build, javadoc" />
|
||||
<target name="build" depends="builddep, jar" />
|
||||
<target name="buildclean" depends="distclean, builddep, jar" />
|
||||
<target name="builddep">
|
||||
<!-- build *everything* here, but only once -->
|
||||
<ant dir="core/java/" target="jar" />
|
||||
|
@@ -14,8 +14,8 @@ package net.i2p;
|
||||
*
|
||||
*/
|
||||
public class CoreVersion {
|
||||
public final static String ID = "$Revision: 1.6 $ $Date: 2004/05/13 18:49:08 $";
|
||||
public final static String VERSION = "0.3.1.3";
|
||||
public final static String ID = "$Revision: 1.8 $ $Date: 2004/05/23 11:54:29 $";
|
||||
public final static String VERSION = "0.3.1.5";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Core version: " + VERSION);
|
||||
|
@@ -8,6 +8,7 @@ import net.i2p.client.naming.NamingService;
|
||||
import net.i2p.crypto.AESEngine;
|
||||
import net.i2p.crypto.CryptixAESEngine;
|
||||
import net.i2p.crypto.DSAEngine;
|
||||
import net.i2p.crypto.DummyDSAEngine;
|
||||
import net.i2p.crypto.DummyElGamalEngine;
|
||||
import net.i2p.crypto.ElGamalAESEngine;
|
||||
import net.i2p.crypto.ElGamalEngine;
|
||||
@@ -373,8 +374,12 @@ public class I2PAppContext {
|
||||
}
|
||||
private void initializeDSA() {
|
||||
synchronized (this) {
|
||||
if (_dsa == null)
|
||||
_dsa = new DSAEngine(this);
|
||||
if (_dsa == null) {
|
||||
if ("off".equals(getProperty("i2p.encryption", "on")))
|
||||
_dsa = new DummyDSAEngine(this);
|
||||
else
|
||||
_dsa = new DSAEngine(this);
|
||||
}
|
||||
_dsaInitialized = true;
|
||||
}
|
||||
}
|
||||
|
@@ -53,8 +53,7 @@ class I2CPMessageProducer {
|
||||
*/
|
||||
public void connect(I2PSessionImpl session) throws I2PSessionException {
|
||||
CreateSessionMessage msg = new CreateSessionMessage();
|
||||
SessionConfig cfg = new SessionConfig();
|
||||
cfg.setDestination(session.getMyDestination());
|
||||
SessionConfig cfg = new SessionConfig(session.getMyDestination());
|
||||
cfg.setOptions(session.getOptions());
|
||||
try {
|
||||
cfg.signSessionConfig(session.getPrivateKey());
|
||||
|
@@ -10,6 +10,7 @@ package net.i2p.client;
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
@@ -86,10 +87,17 @@ class I2PSessionImpl2 extends I2PSessionImpl {
|
||||
*/
|
||||
public byte[] receiveMessage(int msgId) throws I2PSessionException {
|
||||
byte compressed[] = super.receiveMessage(msgId);
|
||||
if (SHOULD_COMPRESS)
|
||||
return DataHelper.decompress(compressed);
|
||||
else
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("receiving message " + msgId + " with " + compressed.length + " compressed bytes");
|
||||
if (SHOULD_COMPRESS) {
|
||||
try {
|
||||
return DataHelper.decompress(compressed);
|
||||
} catch (IOException ioe) {
|
||||
throw new I2PSessionException("Error decompressing message", ioe);
|
||||
}
|
||||
} else {
|
||||
return compressed;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendBestEffort(Destination dest, byte payload[], SessionKey keyUsed, Set tagsSent)
|
||||
@@ -218,21 +226,23 @@ class I2PSessionImpl2 extends I2PSessionImpl {
|
||||
boolean accepted = state.received(MessageStatusMessage.STATUS_SEND_ACCEPTED);
|
||||
|
||||
if ((!accepted) || (state.getMessageId() == null)) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error(getPrefix() + "State with nonce " + state.getNonce()
|
||||
if (_log.shouldLog(Log.CRIT))
|
||||
_log.log(Log.CRIT, getPrefix() + "State with nonce " + state.getNonce()
|
||||
+ " was not accepted? (no messageId!! found=" + found
|
||||
+ " msgId=" + state.getMessageId() + ")",
|
||||
new Exception("Race on accept/success status messages, or reconnected?"));
|
||||
+ " msgId=" + state.getMessageId() + ")");
|
||||
//if (true)
|
||||
// throw new OutOfMemoryError("not really an OOM, but more of jr fucking shit up");
|
||||
nackTags(state);
|
||||
//if (_log.shouldLog(Log.CRIT))
|
||||
// _log.log(Log.CRIT, "Disconnecting/reconnecting because we never were accepted!");
|
||||
//disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getPrefix() + "After waitFor sending state " + state.getMessageId().getMessageId()
|
||||
+ " / " + state.getNonce() + " found = " + found);
|
||||
|
||||
// WARNING: this will always be false for mode=BestEffort, even though the message may go
|
||||
// through, causing every datagram to be ElGamal encrypted!
|
||||
// TODO: Fix this to include support for acks received after the sendMessage completes
|
||||
if (found) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(getPrefix() + "Message sent after " + state.getElapsed() + "ms with "
|
||||
|
29
core/java/src/net/i2p/crypto/DummyDSAEngine.java
Normal file
29
core/java/src/net/i2p/crypto/DummyDSAEngine.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package net.i2p.crypto;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.Signature;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.data.SigningPublicKey;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.NativeBigInteger;
|
||||
|
||||
/**
|
||||
* Stub that offers no authentication.
|
||||
*
|
||||
*/
|
||||
public class DummyDSAEngine extends DSAEngine {
|
||||
public DummyDSAEngine(I2PAppContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Signature sign(byte data[], SigningPrivateKey signingKey) {
|
||||
Signature sig = new Signature();
|
||||
sig.setData(Signature.FAKE_SIGNATURE);
|
||||
return sig;
|
||||
}
|
||||
}
|
@@ -161,7 +161,8 @@ public class Base64 {
|
||||
|
||||
private static void encode(InputStream in, OutputStream out) throws IOException {
|
||||
String encoded = encode(read(in));
|
||||
out.write(encoded.getBytes());
|
||||
for (int i = 0; i < encoded.length(); i++)
|
||||
out.write((byte)(encoded.charAt(i) & 0xFF));
|
||||
}
|
||||
|
||||
private static void decode(InputStream in, OutputStream out) throws IOException {
|
||||
@@ -415,7 +416,10 @@ public class Base64 {
|
||||
* @since 1.3
|
||||
*/
|
||||
private static String encodeString(String s, boolean breakLines) {
|
||||
return encodeBytes(s.getBytes(), breakLines);
|
||||
byte src[] = new byte[s.length()];
|
||||
for (int i = 0; i < src.length; i++)
|
||||
src[i] = (byte)(s.charAt(i) & 0xFF);
|
||||
return encodeBytes(src, breakLines);
|
||||
} // end encodeString
|
||||
|
||||
/* ******** D E C O D I N G M E T H O D S ******** */
|
||||
@@ -526,7 +530,9 @@ public class Base64 {
|
||||
* @since 1.4
|
||||
*/
|
||||
private static byte[] standardDecode(String s) {
|
||||
byte[] bytes = s.getBytes();
|
||||
byte[] bytes = new byte[s.length()];
|
||||
for (int i = 0; i < bytes.length; i++)
|
||||
bytes[i] = (byte)(s.charAt(i) & 0xFF);
|
||||
return decode(bytes, 0, bytes.length);
|
||||
} // end decode
|
||||
|
||||
|
@@ -34,8 +34,8 @@ import net.i2p.util.OrderedProperties;
|
||||
* @author jrandom
|
||||
*/
|
||||
public class DataHelper {
|
||||
private final static String _equal = "="; // in UTF-8
|
||||
private final static String _semicolon = ";"; // in UTF-8
|
||||
private final static byte _equalBytes[] = "=".getBytes(); // in UTF-8
|
||||
private final static byte _semicolonBytes[] = ";".getBytes(); // in UTF-8
|
||||
|
||||
/** Read a mapping from the stream, as defined by the I2P data structure spec,
|
||||
* and store it into a Properties object.
|
||||
@@ -62,17 +62,17 @@ public class DataHelper {
|
||||
int read = read(rawStream, data);
|
||||
if (read != size) throw new DataFormatException("Not enough data to read the properties");
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(data);
|
||||
byte eqBuf[] = _equal.getBytes();
|
||||
byte semiBuf[] = _semicolon.getBytes();
|
||||
byte eqBuf[] = new byte[_equalBytes.length];
|
||||
byte semiBuf[] = new byte[_semicolonBytes.length];
|
||||
while (in.available() > 0) {
|
||||
String key = readString(in);
|
||||
read = read(in, eqBuf);
|
||||
if ((read != eqBuf.length) || (!eq(new String(eqBuf), _equal))) {
|
||||
if ((read != eqBuf.length) || (!eq(eqBuf, _equalBytes))) {
|
||||
break;
|
||||
}
|
||||
String val = readString(in);
|
||||
read = read(in, semiBuf);
|
||||
if ((read != semiBuf.length) || (!eq(new String(semiBuf), _semicolon))) {
|
||||
if ((read != semiBuf.length) || (!eq(semiBuf, _semicolonBytes))) {
|
||||
break;
|
||||
}
|
||||
props.put(key, val);
|
||||
@@ -98,12 +98,12 @@ public class DataHelper {
|
||||
String key = (String) iter.next();
|
||||
String val = p.getProperty(key);
|
||||
// now make sure they're in UTF-8
|
||||
key = new String(key.getBytes(), "UTF-8");
|
||||
val = new String(val.getBytes(), "UTF-8");
|
||||
//key = new String(key.getBytes(), "UTF-8");
|
||||
//val = new String(val.getBytes(), "UTF-8");
|
||||
writeString(baos, key);
|
||||
baos.write(_equal.getBytes());
|
||||
baos.write(_equalBytes);
|
||||
writeString(baos, val);
|
||||
baos.write(_semicolon.getBytes());
|
||||
baos.write(_semicolonBytes);
|
||||
}
|
||||
baos.close();
|
||||
byte propBytes[] = baos.toByteArray();
|
||||
@@ -154,8 +154,10 @@ public class DataHelper {
|
||||
return toString(buf, buf.length);
|
||||
}
|
||||
|
||||
private static final byte[] EMPTY_BUFFER = "".getBytes();
|
||||
|
||||
public static String toString(byte buf[], int len) {
|
||||
if (buf == null) buf = "".getBytes();
|
||||
if (buf == null) buf = EMPTY_BUFFER;
|
||||
StringBuffer out = new StringBuffer();
|
||||
if (len > buf.length) {
|
||||
for (int i = 0; i < len - buf.length; i++)
|
||||
@@ -173,7 +175,7 @@ public class DataHelper {
|
||||
}
|
||||
|
||||
public static String toDecimalString(byte buf[], int len) {
|
||||
if (buf == null) buf = "".getBytes();
|
||||
if (buf == null) buf = EMPTY_BUFFER;
|
||||
BigInteger val = new BigInteger(1, buf);
|
||||
return val.toString(10);
|
||||
}
|
||||
@@ -289,12 +291,13 @@ public class DataHelper {
|
||||
if (string == null) {
|
||||
writeLong(out, 1, 0);
|
||||
} else {
|
||||
if (string.length() > 255)
|
||||
int len = string.length();
|
||||
if (len > 255)
|
||||
throw new DataFormatException("The I2P data spec limits strings to 255 bytes or less, but this is "
|
||||
+ string.length() + " [" + string + "]");
|
||||
byte raw[] = string.getBytes();
|
||||
writeLong(out, 1, raw.length);
|
||||
out.write(raw);
|
||||
writeLong(out, 1, len);
|
||||
for (int i = 0; i < len; i++)
|
||||
out.write((byte)(string.charAt(i) & 0xFF));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,25 +555,20 @@ public class DataHelper {
|
||||
}
|
||||
|
||||
/** decompress the GZIP compressed data (returning null on error) */
|
||||
public static byte[] decompress(byte orig[]) {
|
||||
public static byte[] decompress(byte orig[]) throws IOException {
|
||||
if ((orig == null) || (orig.length <= 0)) return orig;
|
||||
try {
|
||||
GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(orig), orig.length);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(orig.length * 2);
|
||||
byte buf[] = new byte[4 * 1024];
|
||||
while (true) {
|
||||
int read = in.read(buf);
|
||||
if (read == -1) break;
|
||||
baos.write(buf, 0, read);
|
||||
}
|
||||
byte rv[] = baos.toByteArray();
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Decompression of " + orig.length + " into " + rv.length + " (or " + 100.0d
|
||||
// * (((double) rv.length) / ((double) orig.length)) + "% savings)");
|
||||
return rv;
|
||||
} catch (IOException ioe) {
|
||||
//_log.error("Error decompressing?", ioe);
|
||||
return null;
|
||||
GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(orig), orig.length);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(orig.length * 2);
|
||||
byte buf[] = new byte[4 * 1024];
|
||||
while (true) {
|
||||
int read = in.read(buf);
|
||||
if (read == -1) break;
|
||||
baos.write(buf, 0, read);
|
||||
}
|
||||
byte rv[] = baos.toByteArray();
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Decompression of " + orig.length + " into " + rv.length + " (or " + 100.0d
|
||||
// * (((double) rv.length) / ((double) orig.length)) + "% savings)");
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,12 @@ import java.io.OutputStream;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Defines the hash as defined by the I2P data structure spec.
|
||||
* AA hash is the SHA-256 of some data, taking up 32 bytes.
|
||||
@@ -26,10 +32,13 @@ public class Hash extends DataStructureImpl {
|
||||
private byte[] _data;
|
||||
private volatile String _stringified;
|
||||
private volatile String _base64ed;
|
||||
private Map _xorCache;
|
||||
|
||||
public final static int HASH_LENGTH = 32;
|
||||
public final static Hash FAKE_HASH = new Hash(new byte[HASH_LENGTH]);
|
||||
|
||||
|
||||
private static final int MAX_CACHED_XOR = 1024;
|
||||
|
||||
public Hash() {
|
||||
setData(null);
|
||||
}
|
||||
@@ -48,6 +57,77 @@ public class Hash extends DataStructureImpl {
|
||||
_base64ed = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare this hash's cache for xor values - very few hashes will need it,
|
||||
* so we don't want to waste the memory, and lazy initialization would incur
|
||||
* online overhead to verify the initialization.
|
||||
*
|
||||
*/
|
||||
public void prepareCache() {
|
||||
synchronized (this) {
|
||||
if (_xorCache == null)
|
||||
_xorCache = new HashMap(MAX_CACHED_XOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the xor with the current object and the specified hash,
|
||||
* caching values where possible. Currently this keeps up to MAX_CACHED_XOR
|
||||
* (1024) entries, and uses an essentially random ejection policy. Later
|
||||
* perhaps go for an LRU or FIFO?
|
||||
*
|
||||
* @throws IllegalStateException if you try to use the cache without first
|
||||
* preparing this object's cache via .prepareCache()
|
||||
*/
|
||||
public byte[] cachedXor(Hash key) throws IllegalStateException {
|
||||
if (_xorCache == null)
|
||||
throw new IllegalStateException("To use the cache, you must first prepare it");
|
||||
byte[] distance = (byte[])_xorCache.get(key);
|
||||
|
||||
if (distance == null) {
|
||||
// not cached, lets cache it
|
||||
int cached = 0;
|
||||
synchronized (_xorCache) {
|
||||
int toRemove = _xorCache.size() + 1 - MAX_CACHED_XOR;
|
||||
if (toRemove > 0) {
|
||||
Set keys = new HashSet(toRemove);
|
||||
// this removes essentially random keys - we dont maintain any sort
|
||||
// of LRU or age. perhaps we should?
|
||||
int removed = 0;
|
||||
for (Iterator iter = _xorCache.keySet().iterator(); iter.hasNext() && removed < toRemove; removed++)
|
||||
keys.add(iter.next());
|
||||
for (Iterator iter = keys.iterator(); iter.hasNext(); )
|
||||
_xorCache.remove(iter.next());
|
||||
}
|
||||
distance = DataHelper.xor(key.getData(), getData());
|
||||
_xorCache.put(key, (Object)distance);
|
||||
cached = _xorCache.size();
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
// explicit buffer, since the compiler can't guess how long it'll be
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append("miss [").append(cached).append("] from ");
|
||||
buf.append(DataHelper.toHexString(getData())).append(" to ");
|
||||
buf.append(DataHelper.toHexString(key.getData()));
|
||||
_log.debug(buf.toString(), new Exception());
|
||||
}
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
// explicit buffer, since the compiler can't guess how long it'll be
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append("hit from ");
|
||||
buf.append(DataHelper.toHexString(getData())).append(" to ");
|
||||
buf.append(DataHelper.toHexString(key.getData()));
|
||||
_log.debug(buf.toString());
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
public void clearXorCache() {
|
||||
_xorCache = null;
|
||||
}
|
||||
|
||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||
_data = new byte[HASH_LENGTH];
|
||||
_stringified = null;
|
||||
@@ -92,4 +172,96 @@ public class Hash extends DataStructureImpl {
|
||||
}
|
||||
return _base64ed;
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
testFill();
|
||||
testOverflow();
|
||||
testFillCheck();
|
||||
}
|
||||
|
||||
private static void testFill() {
|
||||
Hash local = new Hash(new byte[HASH_LENGTH]); // all zeroes
|
||||
local.prepareCache();
|
||||
for (int i = 0; i < MAX_CACHED_XOR; i++) {
|
||||
byte t[] = new byte[HASH_LENGTH];
|
||||
for (int j = 0; j < HASH_LENGTH; j++)
|
||||
t[j] = (byte)((i >> j) & 0xFF);
|
||||
Hash cur = new Hash(t);
|
||||
local.cachedXor(cur);
|
||||
if (local._xorCache.size() != i+1) {
|
||||
_log.error("xor cache size where i=" + i + " isn't correct! size = "
|
||||
+ local._xorCache.size());
|
||||
return;
|
||||
}
|
||||
}
|
||||
_log.debug("Fill test passed");
|
||||
}
|
||||
private static void testOverflow() {
|
||||
Hash local = new Hash(new byte[HASH_LENGTH]); // all zeroes
|
||||
local.prepareCache();
|
||||
for (int i = 0; i < MAX_CACHED_XOR*2; i++) {
|
||||
byte t[] = new byte[HASH_LENGTH];
|
||||
for (int j = 0; j < HASH_LENGTH; j++)
|
||||
t[j] = (byte)((i >> j) & 0xFF);
|
||||
Hash cur = new Hash(t);
|
||||
local.cachedXor(cur);
|
||||
if (i < MAX_CACHED_XOR) {
|
||||
if (local._xorCache.size() != i+1) {
|
||||
_log.error("xor cache size where i=" + i + " isn't correct! size = "
|
||||
+ local._xorCache.size());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (local._xorCache.size() > MAX_CACHED_XOR) {
|
||||
_log.error("xor cache size where i=" + i + " isn't correct! size = "
|
||||
+ local._xorCache.size());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_log.debug("overflow test passed");
|
||||
}
|
||||
private static void testFillCheck() {
|
||||
Set hashes = new HashSet();
|
||||
Hash local = new Hash(new byte[HASH_LENGTH]); // all zeroes
|
||||
local.prepareCache();
|
||||
// fill 'er up
|
||||
for (int i = 0; i < MAX_CACHED_XOR; i++) {
|
||||
byte t[] = new byte[HASH_LENGTH];
|
||||
for (int j = 0; j < HASH_LENGTH; j++)
|
||||
t[j] = (byte)((i >> j) & 0xFF);
|
||||
Hash cur = new Hash(t);
|
||||
hashes.add(cur);
|
||||
local.cachedXor(cur);
|
||||
if (local._xorCache.size() != i+1) {
|
||||
_log.error("xor cache size where i=" + i + " isn't correct! size = "
|
||||
+ local._xorCache.size());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// now lets recheck using those same hash objects
|
||||
// and see if they're cached
|
||||
for (Iterator iter = hashes.iterator(); iter.hasNext(); ) {
|
||||
Hash cur = (Hash)iter.next();
|
||||
if (!local._xorCache.containsKey(cur)) {
|
||||
_log.error("checking the cache, we dont have "
|
||||
+ DataHelper.toHexString(cur.getData()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// now lets recheck with new objects but the same values
|
||||
// and see if they'return cached
|
||||
for (int i = 0; i < MAX_CACHED_XOR; i++) {
|
||||
byte t[] = new byte[HASH_LENGTH];
|
||||
for (int j = 0; j < HASH_LENGTH; j++)
|
||||
t[j] = (byte)((i >> j) & 0xFF);
|
||||
Hash cur = new Hash(t);
|
||||
if (!local._xorCache.containsKey(cur)) {
|
||||
_log.error("checking the cache, we do NOT have "
|
||||
+ DataHelper.toHexString(cur.getData()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
_log.debug("Fill check test passed");
|
||||
}
|
||||
}
|
@@ -80,10 +80,15 @@ public class RoutingKeyGenerator {
|
||||
today = _cal.getTime();
|
||||
}
|
||||
byte mod[] = null;
|
||||
String modVal = null;
|
||||
synchronized (_fmt) {
|
||||
mod = _fmt.format(today).getBytes();
|
||||
modVal = _fmt.format(today);
|
||||
}
|
||||
_log.info("Routing modifier generated: " + new String(mod));
|
||||
mod = new byte[modVal.length()];
|
||||
for (int i = 0; i < modVal.length(); i++)
|
||||
mod[i] = (byte)(modVal.charAt(i) & 0xFF);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Routing modifier generated: " + modVal);
|
||||
setModData(mod);
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,10 @@ public class SessionConfig extends DataStructureImpl {
|
||||
private final static long OFFSET_VALIDITY = 30 * 1000;
|
||||
|
||||
public SessionConfig() {
|
||||
_destination = null;
|
||||
this(null);
|
||||
}
|
||||
public SessionConfig(Destination dest) {
|
||||
_destination = dest;
|
||||
_signature = null;
|
||||
_creationDate = new Date(Clock.getInstance().now());
|
||||
_options = null;
|
||||
@@ -61,14 +64,6 @@ public class SessionConfig extends DataStructureImpl {
|
||||
return _destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the destination for which this session is supposed to connect
|
||||
*
|
||||
*/
|
||||
public void setDestination(Destination dest) {
|
||||
_destination = dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine when this session was authorized by the destination (so we can
|
||||
* prevent replay attacks)
|
||||
|
@@ -10,13 +10,13 @@ class PersistenceHelper {
|
||||
private final static String NL = System.getProperty("line.separator");
|
||||
|
||||
public final static void add(StringBuffer buf, String prefix, String name, String description, double value) {
|
||||
buf.append("# ").append(prefix.toUpperCase()).append(name.toUpperCase()).append(NL);
|
||||
buf.append("# ").append(prefix).append(name).append(NL);
|
||||
buf.append("# ").append(description).append(NL);
|
||||
buf.append(prefix).append(name).append('=').append(value).append(NL).append(NL);
|
||||
}
|
||||
|
||||
public final static void add(StringBuffer buf, String prefix, String name, String description, long value) {
|
||||
buf.append("# ").append(prefix.toUpperCase()).append(name.toUpperCase()).append(NL);
|
||||
buf.append("# ").append(prefix).append(name).append(NL);
|
||||
buf.append("# ").append(description).append(NL);
|
||||
buf.append(prefix).append(name).append('=').append(value).append(NL).append(NL);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ class PersistenceHelper {
|
||||
try {
|
||||
return Long.parseLong(val);
|
||||
} catch (NumberFormatException nfe) {
|
||||
_log.error("Error formatting " + val + " into a long", nfe);
|
||||
_log.warn("Error formatting " + val + " into a long", nfe);
|
||||
}
|
||||
} else {
|
||||
_log.warn("Key " + prefix + name + " does not exist");
|
||||
@@ -41,10 +41,10 @@ class PersistenceHelper {
|
||||
try {
|
||||
return Double.parseDouble(val);
|
||||
} catch (NumberFormatException nfe) {
|
||||
_log.error("Error formatting " + val + " into a double", nfe);
|
||||
_log.warn("Error formatting " + val + " into a double", nfe);
|
||||
}
|
||||
} else {
|
||||
_log.error("Key " + prefix + name + " does not exist");
|
||||
_log.warn("Key " + prefix + name + " does not exist");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ public class HTTPSendData {
|
||||
con.setRequestProperty("Content-length", "" + length);
|
||||
|
||||
OutputStream out = con.getOutputStream();
|
||||
byte buf[] = new byte[64 * 1024];
|
||||
byte buf[] = new byte[1 * 1024];
|
||||
int read;
|
||||
long sent = 0;
|
||||
GZIPOutputStream zipOut = new GZIPOutputStream(out);
|
||||
@@ -79,7 +79,7 @@ public class HTTPSendData {
|
||||
for (int i = 0; i < data.length; i++)
|
||||
data[i] = (byte) ((i % 26) + 'a');
|
||||
|
||||
boolean sent = HTTPSendData.postData("http://i2p.dnsalias.net/cgi-bin/submitMessageHistory", data.length,
|
||||
boolean sent = HTTPSendData.postData("http://dev.i2p.net/cgi-bin/submitMessageHistory", data.length,
|
||||
new ByteArrayInputStream(data));
|
||||
_log.debug("Sent? " + sent);
|
||||
try {
|
||||
|
@@ -43,11 +43,16 @@ public class I2PThread extends Thread {
|
||||
try {
|
||||
super.run();
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
// we cant assume log is created
|
||||
if (_log == null) _log = new Log(I2PThread.class);
|
||||
_log.log(Log.CRIT, "Killing thread " + getName(), t);
|
||||
} catch (Throwable woof) {
|
||||
System.err.println("Died within the OOM itself");
|
||||
t.printStackTrace();
|
||||
}
|
||||
if (t instanceof OutOfMemoryError)
|
||||
fireOOM((OutOfMemoryError)t);
|
||||
// we cant assume log is created
|
||||
if (_log == null) _log = new Log(I2PThread.class);
|
||||
_log.log(Log.CRIT, "Killing thread " + getName(), t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -438,8 +438,14 @@ public class LogManager {
|
||||
_writer.flushRecords();
|
||||
}
|
||||
|
||||
private static int __id = 0;
|
||||
private class ShutdownHook extends Thread {
|
||||
private int _id;
|
||||
public ShutdownHook() {
|
||||
_id = ++__id;
|
||||
}
|
||||
public void run() {
|
||||
setName("Log " + _id + " shutdown ");
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,10 @@ class LogRecordFormatter {
|
||||
private final static int MAX_PRIORITY_LENGTH = 5;
|
||||
|
||||
public static String formatRecord(LogManager manager, LogRecord rec) {
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
int size = 64 + rec.getMessage().length();
|
||||
if (rec.getThrowable() != null)
|
||||
size += 512;
|
||||
StringBuffer buf = new StringBuffer(size);
|
||||
char format[] = manager._getFormat();
|
||||
for (int i = 0; i < format.length; ++i) {
|
||||
switch ((int) format[i]) {
|
||||
@@ -53,7 +56,7 @@ class LogRecordFormatter {
|
||||
}
|
||||
buf.append(NL);
|
||||
if (rec.getThrowable() != null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
|
||||
PrintWriter pw = new PrintWriter(baos, true);
|
||||
rec.getThrowable().printStackTrace(pw);
|
||||
try {
|
||||
|
@@ -47,6 +47,7 @@ class LogWriter implements Runnable {
|
||||
rotateFile();
|
||||
while (_write) {
|
||||
flushRecords();
|
||||
rereadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +71,9 @@ class LogWriter implements Runnable {
|
||||
} finally {
|
||||
try { Thread.sleep(100); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
|
||||
private void rereadConfig() {
|
||||
long now = Clock.getInstance().now();
|
||||
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
|
||||
_manager.rereadConfig();
|
||||
@@ -94,7 +98,9 @@ class LogWriter implements Runnable {
|
||||
if (val == null) return;
|
||||
if (_currentOut == null) rotateFile();
|
||||
|
||||
byte b[] = val.getBytes();
|
||||
byte b[] = new byte[val.length()];
|
||||
for (int i = 0; i < b.length; i++)
|
||||
b[i] = (byte)val.charAt(i);
|
||||
try {
|
||||
_currentOut.write(b);
|
||||
_numBytesInCurrentFile += b.length;
|
||||
@@ -185,4 +191,4 @@ class LogWriter implements Runnable {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
package net.i2p.util;
|
||||
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
@@ -11,26 +10,100 @@ package net.i2p.util;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import net.i2p.crypto.CryptoConstants;
|
||||
import java.net.URL;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* <p>BigInteger that takes advantage of the jbigi library for the modPow operation,
|
||||
* which accounts for a massive segment of the processing cost of asymmetric
|
||||
* crypto. The jbigi library itself is basically just a JNI wrapper around the
|
||||
* GMP library - a collection of insanely efficient routines for dealing with
|
||||
* big numbers.</p>
|
||||
*
|
||||
* There are three environmental properties for configuring this component: <ul>
|
||||
* <li><b>jbigi.enable</b>: whether to use the native library (defaults to "true")</li>
|
||||
* <li><b>jbigi.impl</b>: select which resource to use as the native implementation</li>
|
||||
* <li><b>jbigi.ref</b>: the file specified in this parameter may contain a resource
|
||||
* name to override jbigi.impl (defaults to "jbigi.cfg")</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>If jbigi.enable is set to false, this class won't even attempt to use the
|
||||
* native library, but if it is set to true (or is not specified), it will first
|
||||
* check the platform specific library path for the "jbigi" library, as defined by
|
||||
* {@link Runtime#loadLibrary} - e.g. C:\windows\jbigi.dll or /lib/libjbigi.so.
|
||||
* If that fails, it reviews the jbigi.impl environment property - if that is set,
|
||||
* it checks all of the components in the CLASSPATH for the file specified and
|
||||
* attempts to load it as the native library. If jbigi.impl is not set, if there
|
||||
* is no matching resource, or if that resource is not a valid OS/architecture
|
||||
* specific library, the NativeBigInteger will revert to using the pure java
|
||||
* implementation.</p>
|
||||
*
|
||||
* <p>That means <b>NativeBigInteger will not attempt to guess the correct
|
||||
* platform/OS/whatever</b> - applications using this class should define that
|
||||
* property prior to <i>referencing</i> the NativeBigInteger (or before loading
|
||||
* the JVM, of course). Alternately, people with custom built jbigi implementations
|
||||
* in their OS's standard search path (LD_LIBRARY_PATH, etc) needn't bother.</p>
|
||||
*
|
||||
* <p>One way to deploy the native library is to create a jbigi.jar file containing
|
||||
* all of the native implementations with filenames such as "win-athlon", "linux-p2",
|
||||
* "freebsd-sparcv4", where those files are the OS specific libraries (the contents of
|
||||
* the DLL or .so file built for those OSes / architectures). The user would then
|
||||
* simply specify -Djbigi.impl=win-athlon and this component would pick up that
|
||||
* library.</p>
|
||||
*
|
||||
* <p>Another way is to create a seperate jbigi.jar file for each platform containing
|
||||
* one file - "native", where that file is the OS / architecture specific library
|
||||
* implementation, as above. This way the user would download the correct jbigi.jar
|
||||
* (and not all of the libraries for platforms/OSes they don't need) and would specify
|
||||
* -Djbigi.impl=native.</p>
|
||||
*
|
||||
* <p>Running this class by itself does a basic unit test and benchmarks the
|
||||
* NativeBigInteger.modPow vs. the BigInteger.modPow by running a 2Kbit op 100
|
||||
* times. At the end, if the native implementation is loaded this will output
|
||||
* something like:</p>
|
||||
* <pre>
|
||||
* native run time: 6090ms (60ms each)
|
||||
* java run time: 68067ms (673ms each)
|
||||
* native = 8.947066860593239% of pure java time
|
||||
* </pre>
|
||||
*
|
||||
* <p>If the native implementation is not loaded, it will start by saying:</p>
|
||||
* <pre>
|
||||
* WARN: Native BigInteger library jbigi not loaded - using pure java
|
||||
* </pre>
|
||||
* <p>Then go on to run the test, finally outputting:</p>
|
||||
* <pre>
|
||||
* java run time: 64653ms (640ms each)
|
||||
* However, we couldn't load the native library, so this doesn't test much
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class NativeBigInteger extends BigInteger {
|
||||
private final static Log _log = new Log(NativeBigInteger.class);
|
||||
/** did we load the native lib correctly? */
|
||||
private static boolean _nativeOk = false;
|
||||
/**
|
||||
* do we want to dump some basic success/failure info to stderr during
|
||||
* initialization? this would otherwise use the Log component, but this makes
|
||||
* it easier for other systems to reuse this class
|
||||
*/
|
||||
private static final boolean _doLog = true;
|
||||
|
||||
private static String DEFAULT_REF_FILENAME = "jbigi.cfg";
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("jbigi");
|
||||
_nativeOk = true;
|
||||
_log.info("Native BigInteger library jbigi loaded");
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
_nativeOk = false;
|
||||
_log.log(Log.CRIT, "Native BigInteger library jbigi not loaded - using pure java");
|
||||
_log.warn("jbigi not loaded", ule);
|
||||
}
|
||||
loadNative();
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate (base ^ exponent) % modulus.
|
||||
* calculate (base ^ exponent) % modulus.
|
||||
* @param base big endian twos complement representation of the base (but it must be positive)
|
||||
* @param exponent big endian twos complement representation of the exponent
|
||||
* @param modulus big endian twos complement representation of the modulus
|
||||
@@ -68,34 +141,48 @@ public class NativeBigInteger extends BigInteger {
|
||||
else
|
||||
return super.modPow(exponent, m);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Compare the BigInteger.modPow vs the NativeBigInteger.modPow of some
|
||||
* really big (2Kbit) numbers 100 different times and benchmark the
|
||||
* performance (or shit a brick if they don't match). </p>
|
||||
*
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
if (_nativeOk)
|
||||
System.out.println("Native library loaded");
|
||||
else
|
||||
System.out.println("Native library NOT loaded");
|
||||
System.out.println("Warming up the random number generator...");
|
||||
RandomSource.getInstance().nextBoolean();
|
||||
System.out.println("Random number generator warmed up");
|
||||
runTest(100);
|
||||
}
|
||||
|
||||
int numRuns = 100;
|
||||
if (args.length == 1) {
|
||||
try {
|
||||
numRuns = Integer.parseInt(args[0]);
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
BigInteger jg = new BigInteger(CryptoConstants.elgg.toByteArray());
|
||||
BigInteger jp = new BigInteger(CryptoConstants.elgp.toByteArray());
|
||||
/* the sample numbers are elG generator/prime so we can test with reasonable numbers */
|
||||
private final static byte[] _sampleGenerator = new BigInteger("2").toByteArray();
|
||||
private final static byte[] _samplePrime = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16).toByteArray();
|
||||
|
||||
private static void runTest(int numRuns) {
|
||||
System.out.println("DEBUG: Warming up the random number generator...");
|
||||
SecureRandom rand = new SecureRandom();
|
||||
rand.nextBoolean();
|
||||
System.out.println("DEBUG: Random number generator warmed up");
|
||||
|
||||
BigInteger jg = new BigInteger(_sampleGenerator);
|
||||
BigInteger jp = new BigInteger(_samplePrime);
|
||||
|
||||
long totalTime = 0;
|
||||
long javaTime = 0;
|
||||
|
||||
int runsProcessed = 0;
|
||||
for (runsProcessed = 0; runsProcessed < numRuns; runsProcessed++) {
|
||||
BigInteger bi = new BigInteger(2048, RandomSource.getInstance());
|
||||
NativeBigInteger g = new NativeBigInteger(CryptoConstants.elgg.toByteArray());
|
||||
NativeBigInteger p = new NativeBigInteger(CryptoConstants.elgp.toByteArray());
|
||||
BigInteger bi = new BigInteger(2048, rand);
|
||||
NativeBigInteger g = new NativeBigInteger(_sampleGenerator);
|
||||
NativeBigInteger p = new NativeBigInteger(_samplePrime);
|
||||
NativeBigInteger k = new NativeBigInteger(1, bi.toByteArray());
|
||||
long beforeModPow = System.currentTimeMillis();
|
||||
BigInteger myValue = g.modPow(k, p);
|
||||
@@ -106,31 +193,168 @@ public class NativeBigInteger extends BigInteger {
|
||||
totalTime += (afterModPow - beforeModPow);
|
||||
javaTime += (afterJavaModPow - afterModPow);
|
||||
if (!myValue.equals(jval)) {
|
||||
_log.error("[" + runsProcessed + "]\tnative modPow != java modPow");
|
||||
_log.error("native modPow value: " + myValue.toString());
|
||||
_log.error("java modPow value: " + jval.toString());
|
||||
_log.error("run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.err.println("[" + runsProcessed + "]\tnative modPow != java modPow");
|
||||
System.err.println("ERROR: [" + runsProcessed + "]\tnative modPow != java modPow");
|
||||
System.err.println("ERROR: native modPow value: " + myValue.toString());
|
||||
System.err.println("ERROR: java modPow value: " + jval.toString());
|
||||
System.err.println("ERROR: run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
break;
|
||||
} else {
|
||||
_log.debug("current run time: " + (afterModPow - beforeModPow) + "ms (total: " + totalTime + "ms, "
|
||||
+ (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println("DEBUG: current run time: " + (afterModPow - beforeModPow) + "ms (total: "
|
||||
+ totalTime + "ms, " + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
}
|
||||
}
|
||||
_log.info(numRuns + " runs complete without any errors");
|
||||
_log.info("run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println("INFO: run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
if (numRuns == runsProcessed)
|
||||
System.out.println(runsProcessed + " runs complete without any errors");
|
||||
System.out.println("INFO: " + runsProcessed + " runs complete without any errors");
|
||||
else
|
||||
System.out.println(runsProcessed + " runs until we got an error");
|
||||
System.out.println("ERROR: " + runsProcessed + " runs until we got an error");
|
||||
|
||||
if (_nativeOk) {
|
||||
System.out.println("native run time: \t" + totalTime + "ms (" + (totalTime / (runsProcessed + 1))
|
||||
+ "ms each)");
|
||||
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println("native = " + ((totalTime * 100.0d) / (double) javaTime) + "% of pure java time");
|
||||
} else {
|
||||
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println("However, we couldn't load the native library, so this doesn't test much");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Do whatever we can to load up the native library backing this BigInteger's modPow.
|
||||
* If it can find a custom built jbigi.dll / libjbigi.so, it'll use that. Otherwise
|
||||
* it'll try to look in the classpath for the correct library (see loadFromResource).
|
||||
* If the user specifies -Djbigi.enable=false it'll skip all of this.</p>
|
||||
*
|
||||
*/
|
||||
private static final void loadNative() {
|
||||
String wantedProp = System.getProperty("jbigi.enable", "true");
|
||||
boolean wantNative = "true".equalsIgnoreCase(wantedProp);
|
||||
if (wantNative) {
|
||||
boolean loaded = loadGeneric();
|
||||
if (loaded) {
|
||||
_nativeOk = true;
|
||||
if (_doLog)
|
||||
System.err.println("INFO: Native BigInteger library jbigi loaded");
|
||||
} else {
|
||||
loaded = loadFromResource();
|
||||
if (loaded) {
|
||||
_nativeOk = true;
|
||||
if (_doLog)
|
||||
System.err.println("INFO: Native BigInteger library jbigi loaded from resource");
|
||||
} else {
|
||||
_nativeOk = false;
|
||||
if (_doLog)
|
||||
System.err.println("WARN: Native BigInteger library jbigi not loaded - using pure java");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_doLog)
|
||||
System.err.println("INFO: Native BigInteger library jbigi not loaded - using pure java");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Try loading it from an explictly build jbigi.dll / libjbigi.so first, before
|
||||
* looking into a jbigi.jar for any other libraries.</p>
|
||||
*
|
||||
* @return true if it was loaded successfully, else false
|
||||
*
|
||||
*/
|
||||
private static final boolean loadGeneric() {
|
||||
try {
|
||||
System.loadLibrary("jbigi");
|
||||
return true;
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Check all of the jars in the classpath for the file specified by the
|
||||
* environmental property "jbigi.impl" and load it as the native library
|
||||
* implementation. For instance, a windows user on a p4 would define
|
||||
* -Djbigi.impl=win-686 if there is a jbigi.jar in the classpath containing the
|
||||
* files "win-686", "win-athlon", "freebsd-p4", "linux-p3", where each
|
||||
* of those files contain the correct binary file for a native library (e.g.
|
||||
* windows DLL, or a *nix .so). </p>
|
||||
*
|
||||
* <p>This is a pretty ugly hack, using the general technique illustrated by the
|
||||
* onion FEC libraries. It works by pulling the resource, writing out the
|
||||
* byte stream to a temporary file, loading the native library from that file,
|
||||
* then deleting the file.</p>
|
||||
*
|
||||
* @return true if it was loaded successfully, else false
|
||||
*
|
||||
*/
|
||||
private static final boolean loadFromResource() {
|
||||
String resourceName = getResourceName();
|
||||
if (resourceName == null) return false;
|
||||
URL resource = NativeBigInteger.class.getClassLoader().getResource(resourceName);
|
||||
if (resource == null) {
|
||||
if (_doLog)
|
||||
System.err.println("ERROR: Resource name [" + resourceName + "] was not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
File outFile = null;
|
||||
try {
|
||||
InputStream libStream = resource.openStream();
|
||||
outFile = File.createTempFile("jbigi", "lib.tmp");
|
||||
FileOutputStream fos = new FileOutputStream(outFile);
|
||||
byte buf[] = new byte[4096*1024];
|
||||
while (true) {
|
||||
int read = libStream.read(buf);
|
||||
if (read < 0) break;
|
||||
fos.write(buf, 0, read);
|
||||
}
|
||||
fos.close();
|
||||
System.load(outFile.getPath());
|
||||
return true;
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
if (_doLog) {
|
||||
System.err.println("ERROR: The resource " + resourceName
|
||||
+ " was not a valid library for this platform");
|
||||
ule.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} catch (IOException ioe) {
|
||||
if (_doLog) {
|
||||
System.err.println("ERROR: Problem writing out the temporary native library data");
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
if (outFile != null) {
|
||||
outFile.deleteOnExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String getResourceName() {
|
||||
String jbigiRefFile = System.getProperty("jbigi.ref");
|
||||
if (jbigiRefFile == null)
|
||||
jbigiRefFile = DEFAULT_REF_FILENAME;
|
||||
|
||||
File refFile = new File(jbigiRefFile);
|
||||
if (refFile.exists()) {
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(refFile)));
|
||||
String resourceName = in.readLine();
|
||||
if ( (resourceName != null) || (resourceName.trim().length() <= 0) )
|
||||
return resourceName;
|
||||
} catch (IOException ioe) {
|
||||
if (_doLog) {
|
||||
System.err.println("WARN: Unable to read the jbigi reference file " + jbigiRefFile);
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
||||
// the file doesnt exist, or it is empty, so use the jbigi.impl system env
|
||||
return System.getProperty("jbigi.impl");
|
||||
}
|
||||
}
|
@@ -27,8 +27,7 @@ class SessionConfigTest extends StructureTest {
|
||||
TestData.registerTest(new SessionConfigTest(), "SessionConfig");
|
||||
}
|
||||
public DataStructure createDataStructure() throws DataFormatException {
|
||||
SessionConfig cfg = new SessionConfig();
|
||||
cfg.setDestination((Destination)(new DestinationTest()).createDataStructure());
|
||||
SessionConfig cfg = new SessionConfig((Destination)(new DestinationTest()).createDataStructure());
|
||||
cfg.setSignature((Signature)(new SignatureTest()).createDataStructure());
|
||||
Properties options = new Properties();
|
||||
options.setProperty("routerHost", "localhost");
|
||||
|
12
hosts.txt
12
hosts.txt
@@ -1,6 +1,11 @@
|
||||
; TC's hosts.txt guaranteed freshness
|
||||
; $Id: hosts.txt,v 1.6 2004/05/15 23:42:17 jrandom Exp $
|
||||
; $Id: hosts.txt,v 1.11 2004/06/09 15:06:17 duck Exp $
|
||||
; changelog:
|
||||
; (1.38) added forum.i2p
|
||||
; (1.36) added ferret.i2p
|
||||
; (1.36) added anonynanny.i2p
|
||||
; (1.35) added hypercubus.i2p
|
||||
; (1.34) added ogg.baffled.i2p
|
||||
; (1.33) added morph.i2p
|
||||
; (1.32) added nickster.i2p
|
||||
; (1.31) added mush.zeit.i2p (i2p's first eepMUSH)
|
||||
@@ -90,4 +95,9 @@ xilog.i2p=yHOthRzTaowYM0dH0H8LfHeBpNzfVnBL9TtVSPF1bAImcm0tI1jyw4dERfijVunXviLGQ0
|
||||
mush.zeit.i2p=3mYATMQg83VtUln0eEi9-LZYJ-0wCuhFu5PnDV6mYWFnLwbPf2rG22jyhOBw2h1fXcj3lJg7VnLRx-PGYQIWsIle~z1FBrOyT9ydqGrjbQYJ0bqBYUnWSR-xuHOGWiJ8lH34uqZ~j~owvhH-NAKs332BkSCl36HsjJF46i00ICS4qxJQ9l7YBtGYAvoliMN4rz0FETPsvwroyQ7JptfovHe1yviF5bfjeZ9ITP5EpYpyOVtfR7ELpvjYN3mH087TrgvJWL5Sz4qjAc122luTHDZ~Z01Ti3d0GluOF0Fh8cugcMXZTcSZLLcoo1UX8Iv~azxYoYw4MB-w9o4ftxZGawHnkzNCX9LXvQb9IHtURGu4p~eKQKT3YBDEM1qIZL-AdOeoUJ87wLke-ukLBTErYrszIiBgCr22pAHbH12ygH63UAKgzChg4eYfQ0Ku-I6PukG3QQhn029cYz8KO9LG5cT6QzeMbGIQ0cVgkbxM6028DXQaChA6Ul8lCOR56ZDPAAAA
|
||||
nickster.i2p=03EPxP9pVIchR0LIyekAgPivoiSe~9HG8EusGNApSpOyfOgiWS-7JY8XZ0UVRExfRJSi4eQIqp2ViK0iQu69cMLdNQjqNVIFAxgMRyIicLijU163GttbX6OKkruMQ1jBsvzOd2glbQCTKjEcxU979aBDMRNXHOdz-baG3aDKvm75LJA4-whBiuS2ywS15xotHPRrBnNBTPoPY8-1GJa3fXELybWlRroSsvHwhsPvBb4eCSjUkNbXpStingnIXLJYdzMUTbYkJejERO~zyB9MriUDR8lYO9rnc3rlZWed1QO5Io0q4VOq4hnYagxwYcTxmHW5gIQ74cfZMEF3hHC2EH-YVwDXhsb3mOE-Z9PoC4hcLrk0wttYvsMJWHfgh8ju5nzH2eIlUQ0wYO5zhvMAeZMTThSqkj8offt5eOxafINRMkten598bU4LI~pgWWdxTkj7hCWaI7FHfa2cBETp0hq5xqSmL0wQZmZCSDmjXhxwNh0mRtCgnz3e1UhWLFzRAAAA
|
||||
morph.i2p=NSooB7Q~AEYQejfZgmG7edN5gsphur-YUhsmzmaznqwyDe1hPEjPwGOtvygZBRqiTL3GNtAeFSJQ7fWYW7BAEGJgGR~z0HkpTHpyiBTVYZsaaNWFV7yR4MVCo6T2cEs5obvMwpEBEfdNU26kLWPqRS1wZdx7U~d04sz5kOTsNELqdHi-54~OPWdKWSCHM24PvIVo28IL9y1S58LNQVW-IOjLP4edOyKw0zrcal0T5SKRyDY7XnDGdE0drPG91vDLWWbSMnV3aFZE97YeYlUhmv7Bh6jNHzE2n9kZygVsMcSOoMZ8HENQLxo9CQwn4CxMZ33uk1o4PV2JpLHWaX075UY9YroHsNJRAuV6LGm-3guKH~P3k7j4wlwLLFzMjeMrhrNsUGrYyx8n4d6kU6EvhiJOA0suVud1cDUkAuxoAZv04CvSvJ5-cgIDvjZFb1jCQpwKvgmWYhJNSs8dhrm2f~EdgFAvPHfjHLz2c7~opMMK-6dXSH1tR~mtIYmnPip5AAAA
|
||||
ogg.baffled.i2p=~FkFF79EA9udRvT740pj07ffO9D5j7kPCih0qj4JvS5tNJdpEMj~D9l-K4J3SKC11T-lwduq9H2j6Ax5dvZXo2TRaSMH0QugGscam2FylydhmxQdST8KiTPtV3kipF5I0~Fwl5TO-~wz4kpQTrR0UwliVwBBz2NfhD2-wTJN43LE-11xH45QvQ0Hl666tkOadXhcy9IKABJuiXj6mfNLdiRsGg0ds3LQYPvWUloUCR0ZOwdJ3wxOJSYf6oSH0sbGX9Lh6-sOgDFbCkwKmo7ftyr0n-kMbvjyvtPGYx0EKz-5-2bOlpQ9OFU7fgrqCmvWqQmLMgonddNz0DWzggigB5msYnKEuKrcwqJ53NMEyT1KUNW29vtSriglSLeoFRPGtAN5D5nzH2EWXBG8l~3eGANDnj~rVBhk2SP4oNrxjII6stdz25pKyK9zXUErp7R2J9U6jGzBOm0hYdRl0jNR4DyqaHE8t0qGimJX82~3QVA6hmB09E21Grqqp2noZvoEAAAA
|
||||
hypercubus.i2p=F4I0cx7eSRGDfHXEnjq673~8Nxizu3xopKjfwKCyBRqRgQEv241IJ6PXIH7xs1YheutNKiM2hYW9z279UMnr6i0dLUhoh98whzbjTeykEvTbCRjCpHzJq6U6VMuwygLDyNohoPvyZZb8u8l8ljpdV7idicgo7gIEQCsNzTEA7E3AG2X06uxBr1RRkfaU2zDueVvxoi7kkvjKm2iJ455Dr8KBCeAWgq1X~OuFnwXWWgtrNEu-UaBuADZ1q6oMrPFOhdQW3J-8LlMq20BblCLLMxIvkJuZC4F7K0krK1~KFdlchQIj2MOxpRfD8TTXTfISpC05NlgDMY4xpFdv-ziFjSjljNm0NYJABQ~yqIcVXXNyDV8TY7Ya5jtG8~UibyWKq6bSYyWgQbsegGCpLzov6BH9MvBGuG8HRhTx-HLSLcBiPBjqYmfMsK31FllnUVeYLShSPgJ1IRrmTADe52ADqCNh37BnQJT0VQePw93spm8ci~Kz3-MsQssX8kl3e4aXAAAA
|
||||
anonynanny.i2p=U-xjIR-MQZ7iLKViaaIpfMzOWthI8jSMyougGi6catC4fmBJjkmo18SZ1Vyy1mXZVhXae~Aqgwlvo-3svus9pzmjykY4ejJWwEuIsL5A3Kk2R6y4h96RuRhvMulH4FBO9Mw4GOsRAhfHYA1ifzQYvs7ZbOwwYMgJ0Y8kDBRtgXNSZPBq59VFUCjg9ON1bca7lGFhgTxzihgZF5MksZKuuX7IAJmUqAZziI9cqRQw4aWTaAfKteOnNp~r7vrjHbfUNezW~OLBj69FXZzEY7uBaoBJut42I4JpQ9ms0cgk~15ExdYACxgjyPNJXX-qrKNLIe7OqOIDqaMFtBTEA4TZpR5nVU7uAXC~XkLggoFMMwqm24rXU1VsGTikGaVtwJNEuCd~KI-711fQ2YDKMkzp7ragbzYGJJKdJUwuJQkTgN-LHUrx1Rccqe5Bz-OMkVkC7KvN1367xywXSrKsXijyy1vBY1BiacB8jT83Kq2LcYjFdy467ny63tlhNvuHp79MAAAA
|
||||
ferret.i2p=P9EUYEBRkuA6R4nqLHrJzcqA64KjOpnQahDeb2SJZdGywI7E70Rf2TzXguryTmNLJb9riDiFouAzsb30FwF0I93Qx8iMq9ADVH6NowUgcXUaBJWoFh6dEnwwCcSbVsn1CvqoEgl-9GA2nm4NSqQv8RU4g3qrr~bfMP-gZLU4lroHb6LqCF3JNz8dege100n994nqxqdUaX1JpxDacq8jG4W5p3bUhlovQNj3cLcHG5K5PVB4jGqjkq-7UHvh0-blHoBhnYLABCe8IM2GAxgGEmS0zjQIXinsUu1wtLVmVMXF6Iy7bVf4~q80ngVNA7M~MVyNzNAocVkgb4bfhAX8WAuAA17XwsG3thWMJFYrWqKKq0hN5cDdbUNYjgx-ue~D~Sm0oJvUGjJVJnPfkbu-mO2bEQvGZaYml7kKF2kxmdmcFWAa-1HKnUXf35kKwYFWx10i8mSmLWhIx~Wvk~RIzNqjqVSy3Nbc6OkfCLvGcTQOtK-5b-BcU8HiZJJH2XOLAAAA
|
||||
forum.i2p=XaZscxXGaXxuIkZDX87dfN0dcEG1xwSXktDbMX9YBOQ1LWbf0j6Kzde37j8dlPUhUK9kqVRZWpDtP7a2QBRl3aT~t~bYRj5bgTOIf9hTW46iViKdKObR-wPPjej~Px8OSYrXbFv2KUekS4baXcqHS7aJMy4rcbC1hsJm3qcXtut~7VFwEhg9w-HrHhsT5aYtcr4u79HvNvUva38NQ4NJn7vI9OPhPVgb5gxkefgM1tF0QC6QO1b~RADN~BW~X2S-YRPyKKxv6xx9mfqEbl5lVA1nBTaoFsN5ZfLZoJOFIVNpNoXxCrCQhvG2zjS-pJD2NF6g0bCcT4cKBWPYtJenLiK3L6fKJuVJ-og5ootLdJNBXGsO~FSwdabvDUaPDbTKmqS-ibFjmq1C7vEde3TGo3cRZgqG0YZi3S3BpBTYN9kGhYHrThGH69ECViUJnUWlUsWux5FI4pZL5Du7TwDYT0BwnX2kTdZQ8WGSFlflXgVQIh1n0XpElShWrOQPR0jGAAAA
|
||||
|
||||
|
@@ -101,6 +101,24 @@ statGroup.4.detail.8.field=0
|
||||
statGroup.4.detail.9.name=tunnel test time (day)
|
||||
statGroup.4.detail.9.option=stat_tunnel.testSuccessTime.24h
|
||||
statGroup.4.detail.9.field=0
|
||||
statGroup.4.detail.10.name=avg messages per inbound tunnel (10 minutes)
|
||||
statGroup.4.detail.10.option=stat_tunnel.inboundMessagesProcessed.10m
|
||||
statGroup.4.detail.10.field=0
|
||||
statGroup.4.detail.11.name=avg messages per inbound tunnel (60 minutes)
|
||||
statGroup.4.detail.11.option=stat_tunnel.inboundMessagesProcessed.60m
|
||||
statGroup.4.detail.11.field=0
|
||||
statGroup.4.detail.12.name=avg messages per outbound tunnel (10 minutes)
|
||||
statGroup.4.detail.12.option=stat_tunnel.outboundMessagesProcessed.10m
|
||||
statGroup.4.detail.12.field=0
|
||||
statGroup.4.detail.13.name=avg messages per outbound tunnel (60 minutes)
|
||||
statGroup.4.detail.13.option=stat_tunnel.outboundMessagesProcessed.60m
|
||||
statGroup.4.detail.13.field=0
|
||||
statGroup.4.detail.14.name=avg messages per participating tunnel (10 minutes)
|
||||
statGroup.4.detail.14.option=stat_tunnel.participatingMessagesProcessed.10m
|
||||
statGroup.4.detail.14.field=0
|
||||
statGroup.4.detail.15.name=avg messages per participating tunnel (60 minutes)
|
||||
statGroup.4.detail.15.option=stat_tunnel.participatingMessagesProcessed.60m
|
||||
statGroup.4.detail.15.field=0
|
||||
#
|
||||
statGroup.5.name=transfer
|
||||
statGroup.5.detail.0.name=messages sent (5 minutes)
|
||||
@@ -128,39 +146,109 @@ statGroup.5.detail.7.name=receive message size avg (hour)
|
||||
statGroup.5.detail.7.option=stat_transport.receiveMessageSize.60m
|
||||
statGroup.5.detail.7.field=0
|
||||
#
|
||||
statGroup.6.name=networkDbHandling
|
||||
statGroup.6.detail.0.name=lookups received (5 minutes)
|
||||
statGroup.6.detail.0.option=stat_netDb.lookupsReceived.5m
|
||||
statGroup.6.detail.0.field=3
|
||||
statGroup.6.detail.1.name=lookups handled (5 minutes)
|
||||
statGroup.6.detail.1.option=stat_netDb.lookupsHandled.5m
|
||||
statGroup.6.detail.1.field=3
|
||||
statGroup.6.detail.2.name=lookups matched (5 minutes)
|
||||
statGroup.6.detail.2.option=stat_netDb.lookupsMatched.5m
|
||||
statGroup.6.detail.2.field=3
|
||||
statGroup.6.detail.3.name=lookups received (hour)
|
||||
statGroup.6.detail.3.option=stat_netDb.lookupsReceived.60m
|
||||
statGroup.6.detail.3.field=3
|
||||
statGroup.6.detail.4.name=lookups handled (hour)
|
||||
statGroup.6.detail.4.option=stat_netDb.lookupsHandled.60m
|
||||
statGroup.6.detail.4.field=3
|
||||
statGroup.6.detail.5.name=lookups matched (hour)
|
||||
statGroup.6.detail.5.option=stat_netDb.lookupsMatched.60m
|
||||
statGroup.6.detail.5.field=3
|
||||
statGroup.6.name=transferSmall
|
||||
statGroup.6.detail.0.name=small messages sent (5 minutes)
|
||||
statGroup.6.detail.0.option=stat_transport.sendMessageSmall.5m
|
||||
statGroup.6.detail.0.field=7
|
||||
statGroup.6.detail.1.name=small messages sent (hour)
|
||||
statGroup.6.detail.1.option=stat_transport.sendMessageSmall.60m
|
||||
statGroup.6.detail.1.field=7
|
||||
statGroup.6.detail.2.name=small messages received (5 minutes)
|
||||
statGroup.6.detail.2.option=stat_transport.receiveMessageSmall.5m
|
||||
statGroup.6.detail.2.field=7
|
||||
statGroup.6.detail.3.name=small messages received (hour)
|
||||
statGroup.6.detail.3.option=stat_transport.receiveMessageSmall.60m
|
||||
statGroup.6.detail.3.field=7
|
||||
#
|
||||
statGroup.7.name=networkDbActivity
|
||||
statGroup.7.detail.0.name=lookups sent (hour)
|
||||
statGroup.7.detail.0.option=stat_netDb.successPeers.60m
|
||||
statGroup.7.name=transferMedium
|
||||
statGroup.7.detail.0.name=medium messages sent (5 minutes)
|
||||
statGroup.7.detail.0.option=stat_transport.sendMessageMedium.5m
|
||||
statGroup.7.detail.0.field=7
|
||||
statGroup.7.detail.1.name=lookup peers (hour)
|
||||
statGroup.7.detail.1.option=stat_netDb.successPeers.60m
|
||||
statGroup.7.detail.1.field=0
|
||||
statGroup.7.detail.2.name=db store sent (5 minutes)
|
||||
statGroup.7.detail.2.option=stat_netDb.storeSent.5m
|
||||
statGroup.7.detail.2.field=3
|
||||
statGroup.7.detail.3.name=db store sent (hour)
|
||||
statGroup.7.detail.3.option=stat_netDb.storeSent.60m
|
||||
statGroup.7.detail.3.field=3
|
||||
statGroup.7.detail.4.name=failed db lookups (hour)
|
||||
statGroup.7.detail.3.option=stat_netDb.failedPeers.60m
|
||||
statGroup.7.detail.3.field=3
|
||||
statGroup.7.detail.1.name=medium messages sent (hour)
|
||||
statGroup.7.detail.1.option=stat_transport.sendMessageMedium.60m
|
||||
statGroup.7.detail.1.field=7
|
||||
statGroup.7.detail.2.name=medium messages received (5 minutes)
|
||||
statGroup.7.detail.2.option=stat_transport.receiveMessageMedium.5m
|
||||
statGroup.7.detail.2.field=7
|
||||
statGroup.7.detail.3.name=medium messages received (hour)
|
||||
statGroup.7.detail.3.option=stat_transport.receiveMessageMedium.60m
|
||||
statGroup.7.detail.3.field=7
|
||||
#
|
||||
statGroup.8.name=transferLarge
|
||||
statGroup.8.detail.0.name=large messages sent (5 minutes)
|
||||
statGroup.8.detail.0.option=stat_transport.sendMessageLarge.5m
|
||||
statGroup.8.detail.0.field=7
|
||||
statGroup.8.detail.1.name=large messages sent (hour)
|
||||
statGroup.8.detail.1.option=stat_transport.sendMessageLarge.60m
|
||||
statGroup.8.detail.1.field=7
|
||||
statGroup.8.detail.2.name=large messages received (5 minutes)
|
||||
statGroup.8.detail.2.option=stat_transport.receiveMessageLarge.5m
|
||||
statGroup.8.detail.2.field=7
|
||||
statGroup.8.detail.3.name=large messages received (hour)
|
||||
statGroup.8.detail.3.option=stat_transport.receiveMessageLarge.60m
|
||||
statGroup.8.detail.3.field=7
|
||||
#
|
||||
statGroup.9.name=networkDbHandling
|
||||
statGroup.9.detail.0.name=lookups received (5 minutes)
|
||||
statGroup.9.detail.0.option=stat_netDb.lookupsReceived.5m
|
||||
statGroup.9.detail.0.field=3
|
||||
statGroup.9.detail.1.name=lookups handled (5 minutes)
|
||||
statGroup.9.detail.1.option=stat_netDb.lookupsHandled.5m
|
||||
statGroup.9.detail.1.field=3
|
||||
statGroup.9.detail.2.name=lookups matched (5 minutes)
|
||||
statGroup.9.detail.2.option=stat_netDb.lookupsMatched.5m
|
||||
statGroup.9.detail.2.field=3
|
||||
statGroup.9.detail.3.name=lookups received (hour)
|
||||
statGroup.9.detail.3.option=stat_netDb.lookupsReceived.60m
|
||||
statGroup.9.detail.3.field=3
|
||||
statGroup.9.detail.4.name=lookups handled (hour)
|
||||
statGroup.9.detail.4.option=stat_netDb.lookupsHandled.60m
|
||||
statGroup.9.detail.4.field=3
|
||||
statGroup.9.detail.5.name=lookups matched (hour)
|
||||
statGroup.9.detail.5.option=stat_netDb.lookupsMatched.60m
|
||||
statGroup.9.detail.5.field=3
|
||||
#
|
||||
statGroup.10.name=networkDbActivity
|
||||
statGroup.10.detail.0.name=lookups sent (hour)
|
||||
statGroup.10.detail.0.option=stat_netDb.successPeers.60m
|
||||
statGroup.10.detail.0.field=7
|
||||
statGroup.10.detail.1.name=lookup peers (hour)
|
||||
statGroup.10.detail.1.option=stat_netDb.successPeers.60m
|
||||
statGroup.10.detail.1.field=0
|
||||
statGroup.10.detail.2.name=db store sent (5 minutes)
|
||||
statGroup.10.detail.2.option=stat_netDb.storeSent.5m
|
||||
statGroup.10.detail.2.field=3
|
||||
statGroup.10.detail.3.name=db store sent (hour)
|
||||
statGroup.10.detail.3.option=stat_netDb.storeSent.60m
|
||||
statGroup.10.detail.3.field=3
|
||||
statGroup.10.detail.4.name=failed db lookups (hour)
|
||||
statGroup.10.detail.3.option=stat_netDb.failedPeers.60m
|
||||
statGroup.10.detail.3.field=3
|
||||
#
|
||||
statGroup.11.name=bandwidth
|
||||
statGroup.11.detail.0.name=send rate (5 minutes)
|
||||
statGroup.11.detail.0.option=stat_bandwidthSendBps.5m
|
||||
statGroup.11.detail.0.field=0
|
||||
statGroup.11.detail.1.name=send rate (60 minutes)
|
||||
statGroup.11.detail.1.option=stat_bandwidthSendBps.60m
|
||||
statGroup.11.detail.1.field=0
|
||||
statGroup.11.detail.2.name=receive rate (5 minutes)
|
||||
statGroup.11.detail.2.option=stat_bandwidthReceiveBps.5m
|
||||
statGroup.11.detail.2.field=0
|
||||
statGroup.11.detail.3.name=receive rate (60 minutes)
|
||||
statGroup.11.detail.3.option=stat_bandwidthReceiveBps.60m
|
||||
statGroup.11.detail.3.field=0
|
||||
#
|
||||
statGroup.12.name=queueing
|
||||
statGroup.12.detail.0.name=time to process inbound (5 minutes)
|
||||
statGroup.12.detail.0.option=stat_inNetMessage.timeToDiscard.5m
|
||||
statGroup.12.detail.0.field=0
|
||||
statGroup.12.detail.1.name=time to process inbound (60 minutes)
|
||||
statGroup.12.detail.1.option=stat_inNetMessage.timeToDiscard.60m
|
||||
statGroup.12.detail.1.field=0
|
||||
statGroup.12.detail.2.name=time to process outbound (5 minutes)
|
||||
statGroup.12.detail.2.option=stat_outNetMessage.timeToDiscard.5m
|
||||
statGroup.12.detail.2.field=0
|
||||
statGroup.12.detail.3.name=time to process outbound (60 minutes)
|
||||
statGroup.12.detail.3.option=stat_outNetMessage.timeToDiscard.60m
|
||||
statGroup.12.detail.3.field=0
|
||||
|
@@ -16,12 +16,15 @@ i2cp.port=##_router_i2cp_port##
|
||||
|
||||
# I2P router administrative web port (currently only responds to /routerConsole.html)
|
||||
router.adminPort=7655
|
||||
|
||||
# Bandwidth limits
|
||||
# These limits are for all i2np connections - tcp or whatever
|
||||
# They are hard enforced with no smoothing.
|
||||
# XXX Until the 0.3.2 release, these should NOT BE USED. Their values will be ignored!!!
|
||||
i2np.bandwidth.inboundBytesPerMinute=##_router_inbps##
|
||||
i2np.bandwidth.outboundBytesPerMinute=##_router_outbps##
|
||||
# These limits are for all i2np connections - tcp or whatever to all peers.
|
||||
# They are hard enforced with no smoothing. If they are <= 0, no limits are enforced.
|
||||
i2np.bandwidth.inboundKBytesPerSecond=-1
|
||||
i2np.bandwidth.outboundKBytesPerSecond=-1
|
||||
# How many bytes will we let accumulate due to inactivity (allowing bursts)?
|
||||
i2np.bandwidth.inboundBurstKBytes=-1
|
||||
i2np.bandwidth.outboundBurstKBytes=-1
|
||||
|
||||
# Publish peer rankings
|
||||
# If true, include the current liveliness and reliability rankings in one's published RouterInfo data
|
||||
@@ -152,6 +155,7 @@ router.maxWaitingJobs=40
|
||||
|
||||
# Keep the router's clock in sync by querying one of the specified NTP servers once
|
||||
# a minute (uses UDP port 123)
|
||||
# This defaults to the DNS round-robin ntp pool - see http://www.pool.ntp.org/
|
||||
# Please change the NTP server specified to include ones closer to you - see
|
||||
# http://www.eecis.udel.edu/~mills/ntp/clock2a.html for a list (you can specify as
|
||||
# many as you want on the args= line - they'll be tried in order until one answers).
|
||||
@@ -164,7 +168,13 @@ router.maxWaitingJobs=40
|
||||
clientApp.0.main=net.i2p.time.Timestamper
|
||||
clientApp.0.name=Timestamper
|
||||
clientApp.0.onBoot=true
|
||||
clientApp.0.args=http://localhost:7655/setTime?k=v clock.fmt.he.net ntp2.belbone.be
|
||||
clientApp.0.args=http://localhost:7655/setTime?putTheValueFromBelowHere pool.ntp.org pool.ntp.org pool.ntp.org
|
||||
|
||||
# The admin time passphrase, used to prevent unauthorized people from updating your
|
||||
# routers time. The value should be included in the timestamper's args above,
|
||||
# otherwise it wont honor timestamp updates. You shouldnt include any spaces or funky
|
||||
# characters - just pick some random numbers.
|
||||
adminTimePassphrase=pleaseSetSomeValueHere
|
||||
|
||||
# SAM bridge (a simplified socket based protocol for using I2P - listens on port 7656. see
|
||||
# the specs at http://www.i2p.net/node/view/144 for more info)
|
||||
|
23
readme.txt
23
readme.txt
@@ -1,4 +1,4 @@
|
||||
$Id: readme.txt,v 1.5 2004/03/21 20:03:54 jrandom Exp $
|
||||
$Id: readme.txt,v 1.1.1.1 2004/04/07 23:41:54 jrandom Exp $
|
||||
I2P Router 0.3
|
||||
|
||||
You have installed a development release of I2P - a variable latency secure
|
||||
@@ -25,8 +25,9 @@ windows), and its management console can be seen via http://localhost:7655/
|
||||
|
||||
Once your router has started up, it may take a few minutes to get integrated
|
||||
with the network (you'll see a few TCP connections listed on the management
|
||||
console). At that point, you can start up any of the various proxies:
|
||||
* startEepProxy: starts an HTTP proxy to access eepsites. Set your browser's
|
||||
console). At that point, you can use any of the various proxies:
|
||||
* eepProxy: this proxy is launched automatically 2 minutes after you start
|
||||
your router, it starts an HTTP proxy to access eepsites. Set your browser's
|
||||
HTTP proxy to localhost:4444 and you can browse various anonymously hosted
|
||||
sites, ala http://duck.i2p/. In addition, the default proxy is set up to
|
||||
tunnel any HTTP requests that don't point at an eepsite (e.g. http://i2p.net/)
|
||||
@@ -53,13 +54,11 @@ If you still have problems, get in touch with the I2P team (contact info below)
|
||||
|
||||
=== Resources / contact info
|
||||
|
||||
I2P is currently revamping our website, so the two main resources are
|
||||
http://i2p.net/ and http://wiki.invisiblenet.net/iip-wiki?I2P (our website's
|
||||
work-in-progress location is http://drupal.i2p.net/ for those who want to see
|
||||
whats coming down the pipe). The development and user community hangs out on
|
||||
a few different linked irc chats - IIP's #i2p, freenode.net's #i2p, and the
|
||||
in-I2P irc network's #i2p (both irc.baffled.i2p and irc.duck.i2p). All of those
|
||||
channels are hooked together, so join whichever one meets your needs.
|
||||
Our website can be found at http://www.i2p.net/
|
||||
The development and user community hangs out on a few different linked irc
|
||||
chats - IIP's #i2p, freenode.net's #i2p, and the in-I2P irc network's #i2p
|
||||
(both irc.baffled.i2p and irc.duck.i2p). All of those channels are hooked
|
||||
together, so join whichever one meets your needs.
|
||||
|
||||
There is also a relatively low traffic mailing list:
|
||||
http://i2p.net/mailman/listinfo/i2p with archives at
|
||||
@@ -78,11 +77,11 @@ The password is "anoncvs".
|
||||
We are a small group of volunteers spread around several continents, working to
|
||||
advance different aspects of the project and discussing the design of the
|
||||
network. For a current list of team members, please see
|
||||
http://drupal.i2p.net/team
|
||||
http://www.i2p.net/team
|
||||
|
||||
=== Licenses
|
||||
|
||||
All code included here is released under an open source license. To review
|
||||
the I2P license policy, please see http://drupal.i2p.net/node/view/66.
|
||||
the I2P license policy, please see http://www.i2p.net/node/view/66.
|
||||
If there is any confusion, please see the source code or contact the
|
||||
developers on the i2p list.
|
||||
|
@@ -27,6 +27,8 @@ public class DataMessage extends I2NPMessageImpl {
|
||||
public final static int MESSAGE_TYPE = 20;
|
||||
private byte _data[];
|
||||
|
||||
private static final int MAX_SIZE = 64*1024;
|
||||
|
||||
public DataMessage(I2PAppContext context) {
|
||||
super(context);
|
||||
_data = null;
|
||||
@@ -41,6 +43,8 @@ public class DataMessage extends I2NPMessageImpl {
|
||||
if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
try {
|
||||
int size = (int)DataHelper.readLong(in, 4);
|
||||
if ( (size <= 0) || (size > MAX_SIZE) )
|
||||
throw new I2NPMessageException("wtf, size out of range? " + size);
|
||||
_data = new byte[size];
|
||||
int read = read(in, _data);
|
||||
if (read != size)
|
||||
|
@@ -84,7 +84,10 @@ public class DatabaseLookupMessage extends I2NPMessageImpl {
|
||||
_key.readBytes(in);
|
||||
_from = new RouterInfo();
|
||||
_from.readBytes(in);
|
||||
boolean tunnelSpecified = DataHelper.readBoolean(in).booleanValue();
|
||||
Boolean val = DataHelper.readBoolean(in);
|
||||
if (val == null)
|
||||
throw new I2NPMessageException("Tunnel must be explicitly specified (or not)");
|
||||
boolean tunnelSpecified = val.booleanValue();
|
||||
if (tunnelSpecified) {
|
||||
_replyTunnel = new TunnelId();
|
||||
_replyTunnel.readBytes(in);
|
||||
|
@@ -70,6 +70,8 @@ public class DatabaseSearchReplyMessage extends I2NPMessageImpl {
|
||||
if (read != compressedLength)
|
||||
throw new IOException("Not enough data to decompress");
|
||||
byte decompressedData[] = DataHelper.decompress(compressedData);
|
||||
if (decompressedData == null)
|
||||
throw new I2NPMessageException("Could not decompress the " + compressedLength + "bytes of data");
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(decompressedData);
|
||||
int num = (int)DataHelper.readLong(bais, 1);
|
||||
_routerInfoStructures.clear();
|
||||
|
@@ -86,7 +86,8 @@ public class DeliveryStatusMessage extends I2NPMessageImpl {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("[DeliveryStatusMessage: ");
|
||||
buf.append("\n\tMessage ID: ").append(getMessageId());
|
||||
buf.append("\n\tArrival: ").append(getArrival());
|
||||
buf.append("\n\tArrival: ").append(_context.clock().now() - _arrival.getTime());
|
||||
buf.append("ms in the past");
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
@@ -122,12 +122,14 @@ public class I2NPMessageReader {
|
||||
_listener.messageReceived(I2NPMessageReader.this, msg, msToRead);
|
||||
}
|
||||
} catch (I2NPMessageException ime) {
|
||||
//_log.warn("Error handling message", ime);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error handling message", ime);
|
||||
_listener.readError(I2NPMessageReader.this, ime);
|
||||
_listener.disconnected(I2NPMessageReader.this);
|
||||
cancelRunner();
|
||||
} catch (IOException ioe) {
|
||||
_log.warn("IO Error handling message", ioe);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("IO Error handling message", ioe);
|
||||
_listener.disconnected(I2NPMessageReader.this);
|
||||
cancelRunner();
|
||||
}
|
||||
|
@@ -35,12 +35,26 @@ public class ClientMessagePool {
|
||||
*
|
||||
*/
|
||||
public void add(ClientMessage msg) {
|
||||
if ( (_context.clientManager().isLocal(msg.getDestination())) ||
|
||||
add(msg, false);
|
||||
}
|
||||
/**
|
||||
* If we're coming from the client subsystem itself, we already know whether
|
||||
* the target is definitely remote and as such don't need to recheck
|
||||
* ourselves, but if we aren't certain, we want it to check for us.
|
||||
*
|
||||
* @param isDefinitelyRemote true if we know for sure that the target is not local
|
||||
*
|
||||
*/
|
||||
public void add(ClientMessage msg, boolean isDefinitelyRemote) {
|
||||
if ( !isDefinitelyRemote ||
|
||||
(_context.clientManager().isLocal(msg.getDestination())) ||
|
||||
(_context.clientManager().isLocal(msg.getDestinationHash())) ) {
|
||||
_log.debug("Adding message for local delivery");
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Adding message for local delivery");
|
||||
_context.clientManager().messageReceived(msg);
|
||||
} else {
|
||||
_log.debug("Adding message for remote delivery");
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Adding message for remote delivery");
|
||||
_context.jobQueue().addJob(new OutboundClientMessageJob(_context, msg));
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package net.i2p.router;
|
||||
/*
|
||||
* free (adj.): unencumbered; not under the control of others
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* Written by jrandom in 2003 and released into the public domain
|
||||
* with no warranty of any kind, either expressed or implied.
|
||||
* It probably won't make your computer catch on fire, or eat
|
||||
* your children, but it might. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
@@ -18,16 +18,24 @@ import net.i2p.data.i2np.SourceRouteBlock;
|
||||
*
|
||||
*/
|
||||
public class InNetMessage {
|
||||
private RouterContext _context;
|
||||
private I2NPMessage _message;
|
||||
private RouterIdentity _fromRouter;
|
||||
private Hash _fromRouterHash;
|
||||
private SourceRouteBlock _replyBlock;
|
||||
private long _created;
|
||||
|
||||
public InNetMessage() {
|
||||
setMessage(null);
|
||||
setFromRouter(null);
|
||||
setFromRouterHash(null);
|
||||
setReplyBlock(null);
|
||||
public InNetMessage(RouterContext context) {
|
||||
_context = context;
|
||||
setMessage(null);
|
||||
setFromRouter(null);
|
||||
setFromRouterHash(null);
|
||||
setReplyBlock(null);
|
||||
context.messageStateMonitor().inboundMessageAdded();
|
||||
_created = context.clock().now();
|
||||
_context.statManager().createRateStat("inNetMessage.timeToDiscard",
|
||||
"How long until we discard an inbound msg?",
|
||||
"InNetMessage", new long[] { 5*60*1000, 30*60*1000, 60*60*1000 });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,9 +68,28 @@ public class InNetMessage {
|
||||
public SourceRouteBlock getReplyBlock() { return _replyBlock; }
|
||||
public void setReplyBlock(SourceRouteBlock block) { _replyBlock = block; }
|
||||
|
||||
/**
|
||||
* Call this after we're done dealing with this message (when we no
|
||||
* longer need its data)
|
||||
*
|
||||
*/
|
||||
public void processingComplete() {
|
||||
_message = null;
|
||||
_context.messageStateMonitor().inboundMessageRead();
|
||||
long timeToDiscard = _context.clock().now() - _created;
|
||||
_context.statManager().addRateData("inNetMessage.timeToDiscard",
|
||||
timeToDiscard, timeToDiscard);
|
||||
}
|
||||
|
||||
public void finalize() {
|
||||
_context.messageStateMonitor().inboundMessageFinalized();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(512);
|
||||
buf.append("InNetMessage: from [").append(getFromRouter()).append("] aka [").append(getFromRouterHash()).append("] message: ").append(getMessage());
|
||||
return buf.toString();
|
||||
StringBuffer buf = new StringBuffer(512);
|
||||
buf.append("InNetMessage: from [").append(getFromRouter());
|
||||
buf.append("] aka [").append(getFromRouterHash());
|
||||
buf.append("] message: ").append(getMessage());
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.data.i2np.DeliveryStatusMessage;
|
||||
import net.i2p.data.i2np.I2NPMessage;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@@ -56,35 +57,37 @@ public class InNetMessagePool {
|
||||
*
|
||||
*/
|
||||
public int add(InNetMessage msg) {
|
||||
Date exp = msg.getMessage().getMessageExpiration();
|
||||
boolean valid = _context.messageValidator().validateMessage(msg.getMessage().getUniqueId(), exp.getTime());
|
||||
I2NPMessage messageBody = msg.getMessage();
|
||||
msg.processingComplete();
|
||||
Date exp = messageBody.getMessageExpiration();
|
||||
boolean valid = _context.messageValidator().validateMessage(messageBody.getUniqueId(), exp.getTime());
|
||||
if (!valid) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Duplicate message received [" + msg.getMessage().getUniqueId()
|
||||
+ " expiring on " + exp + "]: " + msg.getMessage().getClass().getName());
|
||||
_log.warn("Duplicate message received [" + messageBody.getUniqueId()
|
||||
+ " expiring on " + exp + "]: " + messageBody.getClass().getName());
|
||||
_context.statManager().addRateData("inNetPool.dropped", 1, 0);
|
||||
_context.statManager().addRateData("inNetPool.duplicate", 1, 0);
|
||||
_context.messageHistory().droppedOtherMessage(msg.getMessage());
|
||||
_context.messageHistory().messageProcessingError(msg.getMessage().getUniqueId(),
|
||||
msg.getMessage().getClass().getName(),
|
||||
_context.messageHistory().droppedOtherMessage(messageBody);
|
||||
_context.messageHistory().messageProcessingError(messageBody.getUniqueId(),
|
||||
messageBody.getClass().getName(),
|
||||
"Duplicate/expired");
|
||||
return -1;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Message received [" + msg.getMessage().getUniqueId()
|
||||
_log.debug("Message received [" + messageBody.getUniqueId()
|
||||
+ " expiring on " + exp + "] is NOT a duplicate or exipired");
|
||||
}
|
||||
|
||||
int size = -1;
|
||||
int type = msg.getMessage().getType();
|
||||
int type = messageBody.getType();
|
||||
HandlerJobBuilder builder = (HandlerJobBuilder)_handlerJobBuilders.get(new Integer(type));
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Add message to the inNetMessage pool - builder: " + builder
|
||||
+ " message class: " + msg.getMessage().getClass().getName());
|
||||
+ " message class: " + messageBody.getClass().getName());
|
||||
|
||||
if (builder != null) {
|
||||
Job job = builder.createJob(msg.getMessage(), msg.getFromRouter(),
|
||||
Job job = builder.createJob(messageBody, msg.getFromRouter(),
|
||||
msg.getFromRouterHash(), msg.getReplyBlock());
|
||||
if (job != null) {
|
||||
_context.jobQueue().addJob(job);
|
||||
@@ -94,7 +97,7 @@ public class InNetMessagePool {
|
||||
}
|
||||
}
|
||||
|
||||
List origMessages = _context.messageRegistry().getOriginalMessages(msg.getMessage());
|
||||
List origMessages = _context.messageRegistry().getOriginalMessages(messageBody);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Original messages for inbound message: " + origMessages.size());
|
||||
if (origMessages.size() > 1) {
|
||||
@@ -111,7 +114,7 @@ public class InNetMessagePool {
|
||||
+ " : " + omsg + ": reply job: " + job);
|
||||
|
||||
if (job != null) {
|
||||
job.setMessage(msg.getMessage());
|
||||
job.setMessage(messageBody);
|
||||
_context.jobQueue().addJob(job);
|
||||
}
|
||||
}
|
||||
@@ -120,31 +123,31 @@ public class InNetMessagePool {
|
||||
// not handled as a reply
|
||||
if (size == -1) {
|
||||
// was not handled via HandlerJobBuilder
|
||||
_context.messageHistory().droppedOtherMessage(msg.getMessage());
|
||||
if (msg.getMessage().getType() == DeliveryStatusMessage.MESSAGE_TYPE) {
|
||||
_context.messageHistory().droppedOtherMessage(messageBody);
|
||||
if (type == DeliveryStatusMessage.MESSAGE_TYPE) {
|
||||
long timeSinceSent = _context.clock().now() -
|
||||
((DeliveryStatusMessage)msg.getMessage()).getArrival().getTime();
|
||||
((DeliveryStatusMessage)messageBody).getArrival().getTime();
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Dropping unhandled delivery status message created " + timeSinceSent + "ms ago: " + msg);
|
||||
_context.statManager().addRateData("inNetPool.droppedDeliveryStatusDelay", timeSinceSent, timeSinceSent);
|
||||
} else {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Message " + msg.getMessage() + " was not handled by a HandlerJobBuilder - DROPPING: "
|
||||
_log.error("Message " + messageBody + " was not handled by a HandlerJobBuilder - DROPPING: "
|
||||
+ msg, new Exception("DROPPED MESSAGE"));
|
||||
_context.statManager().addRateData("inNetPool.dropped", 1, 0);
|
||||
}
|
||||
} else {
|
||||
String mtype = msg.getMessage().getClass().getName();
|
||||
_context.messageHistory().receiveMessage(mtype, msg.getMessage().getUniqueId(),
|
||||
msg.getMessage().getMessageExpiration(),
|
||||
String mtype = messageBody.getClass().getName();
|
||||
_context.messageHistory().receiveMessage(mtype, messageBody.getUniqueId(),
|
||||
messageBody.getMessageExpiration(),
|
||||
msg.getFromRouterHash(), true);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
String mtype = msg.getMessage().getClass().getName();
|
||||
_context.messageHistory().receiveMessage(mtype, msg.getMessage().getUniqueId(),
|
||||
msg.getMessage().getMessageExpiration(),
|
||||
String mtype = messageBody.getClass().getName();
|
||||
_context.messageHistory().receiveMessage(mtype, messageBody.getUniqueId(),
|
||||
messageBody.getMessageExpiration(),
|
||||
msg.getFromRouterHash(), true);
|
||||
return size;
|
||||
}
|
||||
|
@@ -228,7 +228,32 @@ public class JobQueue {
|
||||
void shutdown() {
|
||||
_alive = false;
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("jobs: \nready jobs: ").append(_readyJobs.size()).append("\n\t");
|
||||
buf.append("current jobs: \n");
|
||||
for (Iterator iter = _queueRunners.values().iterator(); iter.hasNext(); ) {
|
||||
JobQueueRunner runner = (JobQueueRunner)iter.next();
|
||||
Job j = runner.getCurrentJob();
|
||||
|
||||
buf.append("Runner ").append(runner.getRunnerId()).append(": ");
|
||||
if (j == null) {
|
||||
buf.append("no current job ");
|
||||
} else {
|
||||
buf.append(j.toString());
|
||||
buf.append(" started ").append(_context.clock().now() - j.getTiming().getActualStart());
|
||||
buf.append("ms ago");
|
||||
}
|
||||
|
||||
j = runner.getLastJob();
|
||||
if (j == null) {
|
||||
buf.append("no last job");
|
||||
} else {
|
||||
buf.append(j.toString());
|
||||
buf.append(" started ").append(_context.clock().now() - j.getTiming().getActualStart());
|
||||
buf.append("ms ago and finished ");
|
||||
buf.append(_context.clock().now() - j.getTiming().getActualEnd());
|
||||
buf.append("ms ago");
|
||||
}
|
||||
}
|
||||
buf.append("\nready jobs: ").append(_readyJobs.size()).append("\n\t");
|
||||
for (int i = 0; i < _readyJobs.size(); i++)
|
||||
buf.append(_readyJobs.get(i).toString()).append("\n\t");
|
||||
buf.append("\n\ntimed jobs: ").append(_timedJobs.size()).append("\n\t");
|
||||
@@ -254,9 +279,10 @@ public class JobQueue {
|
||||
if (rv != null) {
|
||||
// we found one, but there may be more, so wake up enough
|
||||
// other runners
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Waking up " + (ready-1) + " job runners (and running one)");
|
||||
awaken(ready-1);
|
||||
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Waking up " + (ready-1) + " job runners (and running one)");
|
||||
//awaken(ready-1);
|
||||
return rv;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
@@ -452,6 +478,7 @@ public class JobQueue {
|
||||
* a warning (and if its really excessive, kill the router)
|
||||
*/
|
||||
void updateStats(Job job, long doStart, long origStartAfter, long duration) {
|
||||
if (_context.router() == null) return;
|
||||
String key = job.getName();
|
||||
long lag = doStart - origStartAfter; // how long were we ready and waiting?
|
||||
MessageHistory hist = _context.messageHistory();
|
||||
@@ -511,6 +538,10 @@ public class JobQueue {
|
||||
*
|
||||
*/
|
||||
private void updateMaxLimit() {
|
||||
if (_context.router() == null) {
|
||||
_maxRunners = DEFAULT_MAX_RUNNERS;
|
||||
return;
|
||||
}
|
||||
String str = _context.router().getConfigSetting(PROP_MAX_RUNNERS);
|
||||
if (str != null) {
|
||||
try {
|
||||
@@ -531,6 +562,15 @@ public class JobQueue {
|
||||
*
|
||||
*/
|
||||
private void updateTimingLimits() {
|
||||
if (_context.router() == null) {
|
||||
_lagWarning = DEFAULT_LAG_WARNING;
|
||||
_lagFatal = DEFAULT_LAG_FATAL;
|
||||
_runWarning = DEFAULT_RUN_WARNING;
|
||||
_runFatal = DEFAULT_RUN_FATAL;
|
||||
_warmupTime = DEFAULT_WARMUP_TIME;
|
||||
_maxWaitingJobs = DEFAULT_MAX_WAITING_JOBS;
|
||||
return;
|
||||
}
|
||||
String str = _context.router().getConfigSetting(PROP_LAG_WARNING);
|
||||
if (str != null) {
|
||||
try {
|
||||
|
@@ -133,7 +133,7 @@ public class KeyManager {
|
||||
super(KeyManager.this._context);
|
||||
}
|
||||
public void runJob() {
|
||||
String keyDir = KeyManager.this._context.router().getConfigSetting(PROP_KEYDIR);
|
||||
String keyDir = KeyManager.this._context.getProperty(PROP_KEYDIR);
|
||||
if (keyDir == null)
|
||||
keyDir = DEFAULT_KEYDIR;
|
||||
File dir = new File(keyDir);
|
||||
|
@@ -42,9 +42,13 @@ public class MessageHistory {
|
||||
/** config property determining where we want to log the message history, if we're keeping one */
|
||||
public final static String PROP_MESSAGE_HISTORY_FILENAME = "router.historyFilename";
|
||||
public final static String DEFAULT_MESSAGE_HISTORY_FILENAME = "messageHistory.txt";
|
||||
|
||||
|
||||
private final SimpleDateFormat _fmt;
|
||||
|
||||
public MessageHistory(RouterContext context) {
|
||||
_context = context;
|
||||
_fmt = new SimpleDateFormat("yy/MM/dd.HH:mm:ss.SSS");
|
||||
_fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
_reinitializeJob = new ReinitializeJob();
|
||||
_writeJob = new WriteJob();
|
||||
_submitMessageHistoryJob = new SubmitMessageHistoryJob(_context);
|
||||
@@ -81,6 +85,8 @@ public class MessageHistory {
|
||||
public void initialize(boolean forceReinitialize) {
|
||||
if (!forceReinitialize) return;
|
||||
|
||||
if (_context.router() == null) return;
|
||||
|
||||
if (_context.router().getRouterInfo() == null) {
|
||||
_reinitializeJob.getTiming().setStartAfter(_context.clock().now()+5000);
|
||||
_context.jobQueue().addJob(_reinitializeJob);
|
||||
@@ -302,8 +308,8 @@ public class MessageHistory {
|
||||
if (sentMessage == null) return;
|
||||
StringBuffer buf = new StringBuffer(512);
|
||||
buf.append(getPrefix());
|
||||
buf.append("timed out waiting for a reply to [").append(sentMessage.getMessage().getClass().getName());
|
||||
buf.append("] [").append(sentMessage.getMessage().getUniqueId()).append("] expiring on [");
|
||||
buf.append("timed out waiting for a reply to [").append(sentMessage.getMessageType());
|
||||
buf.append("] [").append(sentMessage.getMessageId()).append("] expiring on [");
|
||||
if (sentMessage != null)
|
||||
buf.append(getTime(new Date(sentMessage.getReplySelector().getExpiration())));
|
||||
buf.append("] ").append(sentMessage.getReplySelector().toString());
|
||||
@@ -439,11 +445,7 @@ public class MessageHistory {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private final static SimpleDateFormat _fmt = new SimpleDateFormat("yy/MM/dd.HH:mm:ss.SSS");
|
||||
static {
|
||||
_fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
private final static String getTime(Date when) {
|
||||
private final String getTime(Date when) {
|
||||
synchronized (_fmt) {
|
||||
return _fmt.format(when);
|
||||
}
|
||||
|
72
router/java/src/net/i2p/router/MessageStateMonitor.java
Normal file
72
router/java/src/net/i2p/router/MessageStateMonitor.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package net.i2p.router;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Keep track of the inbound and outbound messages in memory.
|
||||
*
|
||||
*/
|
||||
public class MessageStateMonitor {
|
||||
private Log _log;
|
||||
private RouterContext _context;
|
||||
private volatile int _inboundLiveCount;
|
||||
private volatile int _inboundReadCount;
|
||||
private volatile int _inboundFinalizedCount;
|
||||
private volatile int _outboundLiveCount;
|
||||
private volatile int _outboundDiscardedCount;
|
||||
|
||||
public MessageStateMonitor(RouterContext context) {
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(MessageStateMonitor.class);
|
||||
_inboundLiveCount = 0;
|
||||
_inboundReadCount = 0;
|
||||
_inboundFinalizedCount = 0;
|
||||
_outboundLiveCount = 0;
|
||||
_outboundDiscardedCount = 0;
|
||||
}
|
||||
|
||||
public void inboundMessageAdded() {
|
||||
_inboundLiveCount++;
|
||||
logStatus("inboundAdded ");
|
||||
}
|
||||
public void inboundMessageRead() {
|
||||
_inboundReadCount++;
|
||||
_inboundLiveCount--;
|
||||
logStatus("inboundRead ");
|
||||
}
|
||||
public void inboundMessageFinalized() {
|
||||
_inboundReadCount--;
|
||||
_inboundFinalizedCount++;
|
||||
logStatus("inboundFinalized ");
|
||||
}
|
||||
|
||||
public void outboundMessageAdded() {
|
||||
_outboundLiveCount++;
|
||||
logStatus("outboundAdded ");
|
||||
}
|
||||
public void outboundMessageDiscarded() {
|
||||
_outboundDiscardedCount++;
|
||||
_outboundLiveCount--;
|
||||
logStatus("outboundDiscarded");
|
||||
}
|
||||
public void outboundMessageFinalized() {
|
||||
_outboundDiscardedCount--;
|
||||
logStatus("outboundFinalized");
|
||||
}
|
||||
|
||||
private void logStatus(String event) {
|
||||
if (false || (_log.shouldLog(Log.DEBUG)))
|
||||
_log.debug(event + ": outbound (live: " + _outboundLiveCount
|
||||
+ " discarded:" + _outboundDiscardedCount + ")"
|
||||
+ " inbound (live: " + (_inboundLiveCount)
|
||||
//+ " inbound (live: " + (_inboundLiveCount-_inboundFinalizedCount)
|
||||
+ " read: " + (_inboundReadCount)
|
||||
//+ " completed: " + _inboundFinalizedCount
|
||||
+ ")");
|
||||
}
|
||||
|
||||
public int getInboundLiveCount() { return _inboundLiveCount; }
|
||||
public int getInboundReadCount() { return _inboundReadCount; }
|
||||
public int getOutboundLiveCount() { return _outboundLiveCount; }
|
||||
public int getOutboundDiscardedCount() { return _outboundDiscardedCount; }
|
||||
}
|
@@ -56,7 +56,8 @@ public class MultiRouter {
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
public void run() {
|
||||
try { Thread.sleep(15*1000); } catch (InterruptedException ie) {}
|
||||
Thread.currentThread().setName("Router* Shutdown");
|
||||
try { Thread.sleep(120*1000); } catch (InterruptedException ie) {}
|
||||
Runtime.getRuntime().halt(-1);
|
||||
}
|
||||
});
|
||||
@@ -66,12 +67,13 @@ public class MultiRouter {
|
||||
router.setKillVMOnEnd(false);
|
||||
_routers.add(router);
|
||||
_log.info("Router " + i + " created from " + args[i]);
|
||||
try { Thread.sleep(1*1000); } catch (InterruptedException ie) {}
|
||||
try { Thread.sleep(2*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _routers.size(); i++) {
|
||||
((Router)_routers.get(i)).runRouter();
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
_log.info("Router " + i + " started");
|
||||
try { Thread.sleep(2*1000 + new java.util.Random().nextInt(2)*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
_log.info("All " + _routers.size() + " routers started up");
|
||||
waitForCompletion();
|
||||
@@ -115,4 +117,4 @@ public class MultiRouter {
|
||||
System.err.println(" to load into the given context. In addition, each routerContextFile");
|
||||
System.err.println(" in turn is used to boot a router");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ import java.io.IOException;
|
||||
*/
|
||||
public class MultiRouterBuilder {
|
||||
public static void main(String args[]) {
|
||||
if (args.length <= 2) {
|
||||
if (args.length < 2) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ public class MultiRouterBuilder {
|
||||
buf.append("i2np.bandwidth.inboundBytesPerMinute=-60\n");
|
||||
buf.append("i2np.bandwidth.outboundBytesPerMinute=-60\n");
|
||||
buf.append("router.publishPeerRankings=true\n");
|
||||
buf.append("router.keepHistory=true\n");
|
||||
buf.append("router.keepHistory=false\n");
|
||||
buf.append("router.submitHistory=false\n");
|
||||
buf.append("router.maxJobRunners=1\n");
|
||||
buf.append("router.jobLagWarning=10000\n");
|
||||
@@ -136,9 +136,9 @@ public class MultiRouterBuilder {
|
||||
buf.append("router.jobRunWarning=10000\n");
|
||||
buf.append("router.jobRunFatal=30000\n");
|
||||
buf.append("router.jobWarmupTime=600000\n");
|
||||
buf.append("router.targetClients=2\n");
|
||||
buf.append("tunnels.numInbound=2\n");
|
||||
buf.append("tunnels.numOutbound=2\n");
|
||||
buf.append("router.targetClients=1\n");
|
||||
buf.append("tunnels.numInbound=6\n");
|
||||
buf.append("tunnels.numOutbound=6\n");
|
||||
buf.append("tunnels.depthInbound=2\n");
|
||||
buf.append("tunnels.depthOutbound=2\n");
|
||||
buf.append("tunnels.tunnelDuration=600000\n");
|
||||
@@ -152,6 +152,7 @@ public class MultiRouterBuilder {
|
||||
buf.append("router.tunnelPoolFile=").append(baseDir.getPath()).append("/tunnelPool.dat\n");
|
||||
buf.append("router.keyBackupDir=").append(baseDir.getPath()).append("/keyBackup\n");
|
||||
buf.append("i2np.tcp.port=").append(basePort).append('\n');
|
||||
buf.append("i2np.tcp.hostname=localhost\n");
|
||||
buf.append("i2cp.port=").append(basePort+1).append('\n');
|
||||
buf.append("router.adminPort=").append(basePort+2).append('\n');
|
||||
buf.append("#clientApp.0.main=net.i2p.sam.SAMBridge\n");
|
||||
@@ -184,7 +185,7 @@ public class MultiRouterBuilder {
|
||||
fos = new FileOutputStream(envFile);
|
||||
fos.write(("loggerFilenameOverride="+baseDir+ "/logs/log-router-#.txt\n").getBytes());
|
||||
fos.write(("router.configLocation="+baseDir+"/router.config\n").getBytes());
|
||||
fos.write(("i2p.vmCommSystem=true\n").getBytes());
|
||||
//fos.write(("i2p.vmCommSystem=true\n").getBytes());
|
||||
fos.write(("i2p.encryption=off\n").getBytes());
|
||||
fos.close();
|
||||
|
||||
@@ -198,4 +199,4 @@ public class MultiRouterBuilder {
|
||||
private static void usage() {
|
||||
System.err.println("Usage: MultiRouterBuilder [routerDir routerPortStart]*");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,6 +35,10 @@ public class OutNetMessage {
|
||||
private RouterContext _context;
|
||||
private RouterInfo _target;
|
||||
private I2NPMessage _message;
|
||||
/** cached message class name, for use after we discard the message */
|
||||
private String _messageType;
|
||||
/** cached message ID, for use after we discard the message */
|
||||
private long _messageId;
|
||||
private long _messageSize;
|
||||
private int _priority;
|
||||
private long _expiration;
|
||||
@@ -75,6 +79,10 @@ public class OutNetMessage {
|
||||
_createdBy = new Exception("Created by");
|
||||
_created = context.clock().now();
|
||||
timestamp("Created");
|
||||
_context.messageStateMonitor().outboundMessageAdded();
|
||||
_context.statManager().createRateStat("outNetMessage.timeToDiscard",
|
||||
"How long until we discard an outbound msg?",
|
||||
"OutNetMessage", new long[] { 5*60*1000, 30*60*1000, 60*60*1000 });
|
||||
}
|
||||
|
||||
public void timestamp(String eventName) {
|
||||
@@ -109,8 +117,15 @@ public class OutNetMessage {
|
||||
public I2NPMessage getMessage() { return _message; }
|
||||
public void setMessage(I2NPMessage msg) {
|
||||
_message = msg;
|
||||
if (msg != null) {
|
||||
_messageType = msg.getClass().getName();
|
||||
_messageId = msg.getUniqueId();
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessageType() { return _messageType; }
|
||||
public long getMessageId() { return _messageId; }
|
||||
|
||||
public long getMessageSize() {
|
||||
if (_messageSize <= 0) {
|
||||
try {
|
||||
@@ -132,7 +147,7 @@ public class OutNetMessage {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); // large enough to hold most messages
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); // large enough to hold most messages
|
||||
_message.writeBytes(baos);
|
||||
byte data[] = baos.toByteArray();
|
||||
_messageSize = data.length;
|
||||
@@ -206,6 +221,36 @@ public class OutNetMessage {
|
||||
public long getCreated() { return _created; }
|
||||
public long getLifetime() { return _context.clock().now() - _created; }
|
||||
|
||||
/**
|
||||
* We've done what we need to do with the data from this message, though
|
||||
* we may keep the object around for a while to use its ID, jobs, etc.
|
||||
*/
|
||||
public void discardData() {
|
||||
long timeToDiscard = _context.clock().now() - _created;
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Discard " + _messageSize + "byte " + _messageType + " message after "
|
||||
+ timeToDiscard);
|
||||
_message = null;
|
||||
_context.statManager().addRateData("outNetMessage.timeToDiscard", timeToDiscard, timeToDiscard);
|
||||
_context.messageStateMonitor().outboundMessageDiscarded();
|
||||
}
|
||||
|
||||
public void finalize() throws Throwable {
|
||||
if (_message != null) {
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("Undiscarded ").append(_messageSize).append("byte ");
|
||||
buf.append(_messageType).append(" message created ");
|
||||
buf.append((_context.clock().now() - _created)).append("ms ago: ");
|
||||
buf.append(_messageId).append(" to ").append(_target.calculateHash().toBase64());
|
||||
buf.append(", timing - \n");
|
||||
renderTimestamps(buf);
|
||||
_log.error(buf.toString(), _createdBy);
|
||||
_context.messageStateMonitor().outboundMessageDiscarded();
|
||||
}
|
||||
_context.messageStateMonitor().outboundMessageFinalized();
|
||||
super.finalize();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append("[OutNetMessage contains ");
|
||||
@@ -230,6 +275,13 @@ public class OutNetMessage {
|
||||
if (_onFailedSend != null)
|
||||
buf.append(" with onFailedSend job: ").append(_onFailedSend);
|
||||
buf.append(" {timestamps: \n");
|
||||
renderTimestamps(buf);
|
||||
buf.append("}");
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void renderTimestamps(StringBuffer buf) {
|
||||
synchronized (_timestamps) {
|
||||
long lastWhen = -1;
|
||||
for (int i = 0; i < _timestampOrder.size(); i++) {
|
||||
@@ -243,13 +295,12 @@ public class OutNetMessage {
|
||||
buf.append(diff);
|
||||
else
|
||||
buf.append(0);
|
||||
buf.append("ms: \t").append(name).append('=').append(formatDate(when.longValue())).append("]\n");
|
||||
buf.append("ms: \t").append(name);
|
||||
buf.append('=').append(formatDate(when.longValue()));
|
||||
buf.append("]\n");
|
||||
lastWhen = when.longValue();
|
||||
}
|
||||
}
|
||||
buf.append("}");
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private final static SimpleDateFormat _fmt = new SimpleDateFormat("HH:mm:ss.SSS");
|
||||
|
@@ -93,6 +93,15 @@ public class Router {
|
||||
_oomListener = new I2PThread.OOMEventListener() {
|
||||
public void outOfMemory(OutOfMemoryError oom) {
|
||||
_log.log(Log.CRIT, "Thread ran out of memory", oom);
|
||||
for (int i = 0; i < 5; i++) { // try this 5 times, in case it OOMs
|
||||
try {
|
||||
_log.log(Log.CRIT, "free mem: " + Runtime.getRuntime().freeMemory() +
|
||||
" total mem: " + Runtime.getRuntime().totalMemory());
|
||||
break; // w00t
|
||||
} catch (OutOfMemoryError oome) {
|
||||
// gobble
|
||||
}
|
||||
}
|
||||
shutdown();
|
||||
}
|
||||
};
|
||||
@@ -276,7 +285,7 @@ public class Router {
|
||||
RateStat sendRate = _context.statManager().getRate("transport.sendMessageSize");
|
||||
for (int i = 0; i < sendRate.getPeriods().length; i++) {
|
||||
Rate rate = sendRate.getRate(sendRate.getPeriods()[i]);
|
||||
double bytes = rate.getLastTotalValue() + rate.getCurrentTotalValue();
|
||||
double bytes = rate.getLastTotalValue();
|
||||
long ms = rate.getLastTotalEventTime() + rate.getLastTotalEventTime();
|
||||
if (ms <= 0) {
|
||||
bytes = 0;
|
||||
@@ -294,9 +303,7 @@ public class Router {
|
||||
buf.append(" over ").append((long)bytes).append(" bytes");
|
||||
buf.append("</li><li>");
|
||||
buf.append(DataHelper.formatDuration(rate.getPeriod())).append(" period send avg: ");
|
||||
// we include lastPeriod + current *partial* period, and jrandom is too lazy to calculate how
|
||||
// much of that partial is contained here, so 2*period it is.
|
||||
bps = bytes*1000.0d/(2*rate.getPeriod());
|
||||
bps = bytes*1000.0d/(rate.getPeriod());
|
||||
if (bps > 2048) {
|
||||
bps /= 1024.0d;
|
||||
buf.append(fmt.format(bps)).append(" KBps");
|
||||
@@ -310,8 +317,8 @@ public class Router {
|
||||
RateStat receiveRate = _context.statManager().getRate("transport.receiveMessageSize");
|
||||
for (int i = 0; i < receiveRate.getPeriods().length; i++) {
|
||||
Rate rate = receiveRate.getRate(receiveRate.getPeriods()[i]);
|
||||
double bytes = rate.getLastTotalValue() + rate.getCurrentTotalValue();
|
||||
long ms = rate.getLastTotalEventTime() + rate.getLastTotalEventTime();
|
||||
double bytes = rate.getLastTotalValue();
|
||||
long ms = rate.getLastTotalEventTime();
|
||||
if (ms <= 0) {
|
||||
bytes = 0;
|
||||
ms = 1;
|
||||
@@ -328,9 +335,7 @@ public class Router {
|
||||
buf.append(" over ").append((long)bytes).append(" bytes");
|
||||
buf.append("</li><li>");
|
||||
buf.append(DataHelper.formatDuration(rate.getPeriod())).append(" period receive avg: ");
|
||||
// we include lastPeriod + current *partial* period, and jrandom is too lazy to calculate how
|
||||
// much of that partial is contained here, so 2*period it is.
|
||||
bps = bytes*1000.0d/(2*rate.getPeriod());
|
||||
bps = bytes*1000.0d/(rate.getPeriod());
|
||||
if (bps > 2048) {
|
||||
bps /= 1024.0d;
|
||||
buf.append(fmt.format(bps)).append(" KBps");
|
||||
@@ -407,8 +412,15 @@ public class Router {
|
||||
r.runRouter();
|
||||
}
|
||||
|
||||
|
||||
private static int __id = 0;
|
||||
private class ShutdownHook extends Thread {
|
||||
private int _id;
|
||||
public ShutdownHook() {
|
||||
_id = ++__id;
|
||||
}
|
||||
public void run() {
|
||||
setName("Router " + _id + " shutdown");
|
||||
_log.log(Log.CRIT, "Shutting down the router...");
|
||||
shutdown();
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ public class RouterContext extends I2PAppContext {
|
||||
private StatisticsManager _statPublisher;
|
||||
private Shitlist _shitlist;
|
||||
private MessageValidator _messageValidator;
|
||||
private MessageStateMonitor _messageStateMonitor;
|
||||
private Calculator _isFailingCalc;
|
||||
private Calculator _integrationCalc;
|
||||
private Calculator _speedCalc;
|
||||
@@ -68,6 +69,7 @@ public class RouterContext extends I2PAppContext {
|
||||
_outNetMessagePool = new OutNetMessagePool(this);
|
||||
_messageHistory = new MessageHistory(this);
|
||||
_messageRegistry = new OutboundMessageRegistry(this);
|
||||
_messageStateMonitor = new MessageStateMonitor(this);
|
||||
_netDb = new KademliaNetworkDatabaseFacade(this);
|
||||
_keyManager = new KeyManager(this);
|
||||
if ("false".equals(getProperty("i2p.vmCommSystem", "false")))
|
||||
@@ -123,6 +125,13 @@ public class RouterContext extends I2PAppContext {
|
||||
* The registry is used by outbound messages to wait for replies.
|
||||
*/
|
||||
public OutboundMessageRegistry messageRegistry() { return _messageRegistry; }
|
||||
/**
|
||||
* The monitor keeps track of inbound and outbound messages currently held in
|
||||
* memory / queued for processing. We'll use this to throttle the router so
|
||||
* we don't overflow.
|
||||
*
|
||||
*/
|
||||
public MessageStateMonitor messageStateMonitor() { return _messageStateMonitor; }
|
||||
/**
|
||||
* Our db cache
|
||||
*/
|
||||
@@ -218,4 +227,29 @@ public class RouterContext extends I2PAppContext {
|
||||
buf.append(_reliabilityCalc).append('\n');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tie in the router's config as properties, as well as whatever the
|
||||
* I2PAppContext says.
|
||||
*
|
||||
*/
|
||||
public String getProperty(String propName) {
|
||||
if (_router != null) {
|
||||
String val = _router.getConfigSetting(propName);
|
||||
if (val != null) return val;
|
||||
}
|
||||
return super.getProperty(propName);
|
||||
}
|
||||
/**
|
||||
* Tie in the router's config as properties, as well as whatever the
|
||||
* I2PAppContext says.
|
||||
*
|
||||
*/
|
||||
public String getProperty(String propName, String defaultVal) {
|
||||
if (_router != null) {
|
||||
String val = _router.getConfigSetting(propName);
|
||||
if (val != null) return val;
|
||||
}
|
||||
return super.getProperty(propName, defaultVal);
|
||||
}
|
||||
}
|
@@ -15,8 +15,8 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.5 $ $Date: 2004/05/13 18:49:09 $";
|
||||
public final static String VERSION = "0.3.1.3";
|
||||
public final static String ID = "$Revision: 1.7 $ $Date: 2004/05/23 11:54:30 $";
|
||||
public final static String VERSION = "0.3.1.5";
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@@ -33,9 +33,14 @@ public class StatisticsManager implements Service {
|
||||
public final static String DEFAULT_PROP_PUBLISH_RANKINGS = "false";
|
||||
public final static String PROP_MAX_PUBLISHED_PEERS = "router.publishPeerMax";
|
||||
public final static int DEFAULT_MAX_PUBLISHED_PEERS = 20;
|
||||
|
||||
|
||||
private final DecimalFormat _fmt;
|
||||
private final DecimalFormat _pct;
|
||||
|
||||
public StatisticsManager(RouterContext context) {
|
||||
_context = context;
|
||||
_fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));
|
||||
_pct = new DecimalFormat("#0.00%", new DecimalFormatSymbols(Locale.UK));
|
||||
_log = context.logManager().getLog(StatisticsManager.class);
|
||||
_includePeerRankings = false;
|
||||
}
|
||||
@@ -92,6 +97,7 @@ public class StatisticsManager implements Service {
|
||||
if (_includePeerRankings) {
|
||||
stats.putAll(_context.profileManager().summarizePeers(_publishedStats));
|
||||
|
||||
includeThroughput(stats);
|
||||
includeRate("transport.sendProcessingTime", stats, new long[] { 60*1000, 60*60*1000 });
|
||||
//includeRate("tcp.queueSize", stats);
|
||||
includeRate("jobQueue.jobLag", stats, new long[] { 60*1000, 60*60*1000 });
|
||||
@@ -104,6 +110,9 @@ public class StatisticsManager implements Service {
|
||||
includeRate("inNetPool.dropped", stats, new long[] { 60*60*1000, 24*60*60*1000 });
|
||||
includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("tunnel.testSuccessTime", stats, new long[] { 60*60*1000l, 24*60*60*1000l });
|
||||
includeRate("tunnel.outboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
|
||||
includeRate("tunnel.inboundMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
|
||||
includeRate("tunnel.participatingMessagesProcessed", stats, new long[] { 10*60*1000, 60*60*1000 });
|
||||
includeRate("netDb.lookupsReceived", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("netDb.lookupsHandled", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("netDb.lookupsMatched", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
@@ -111,8 +120,16 @@ public class StatisticsManager implements Service {
|
||||
includeRate("netDb.successPeers", stats, new long[] { 60*60*1000 });
|
||||
includeRate("netDb.failedPeers", stats, new long[] { 60*60*1000 });
|
||||
includeRate("netDb.searchCount", stats, new long[] { 3*60*60*1000});
|
||||
includeRate("inNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
|
||||
includeRate("outNetMessage.timeToDiscard", stats, new long[] { 5*60*1000, 10*60*1000, 60*60*1000 });
|
||||
includeRate("transport.receiveMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.sendMessageSize", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.sendMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.sendMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.sendMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.receiveMessageSmall", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.receiveMessageMedium", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("transport.receiveMessageLarge", stats, new long[] { 5*60*1000, 60*60*1000 });
|
||||
includeRate("client.sendAckTime", stats, new long[] { 60*60*1000, 24*60*60*1000l }, true);
|
||||
stats.setProperty("stat_uptime", DataHelper.formatDuration(_context.router().getUptime()));
|
||||
stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]");
|
||||
@@ -160,7 +177,7 @@ public class StatisticsManager implements Service {
|
||||
}
|
||||
}
|
||||
|
||||
private static String renderRate(Rate rate, boolean fudgeQuantity) {
|
||||
private String renderRate(Rate rate, boolean fudgeQuantity) {
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
buf.append(num(rate.getAverageValue())).append(';');
|
||||
buf.append(num(rate.getExtremeAverageValue())).append(';');
|
||||
@@ -189,15 +206,55 @@ public class StatisticsManager implements Service {
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static String getPeriod(Rate rate) { return DataHelper.formatDuration(rate.getPeriod()); }
|
||||
|
||||
// TODO: get this to use some random locale, not the user's default (since its published)
|
||||
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));
|
||||
private final static String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
|
||||
private String renderThroughput(double bytes, long ms) {
|
||||
if (bytes <= 0)
|
||||
return "0;0;0;0;";
|
||||
else
|
||||
return num(bytes/(ms/1000)) + ";0;0;0;";
|
||||
}
|
||||
|
||||
private final static DecimalFormat _pct = new DecimalFormat("#0.00%", new DecimalFormatSymbols(Locale.UK));
|
||||
private final static String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
|
||||
private void includeThroughput(Properties stats) {
|
||||
double sendBytes5m = 0;
|
||||
double sendBytes60m = 0;
|
||||
double recvBytes5m = 0;
|
||||
double recvBytes60m = 0;
|
||||
|
||||
RateStat sendRate = _context.statManager().getRate("transport.sendMessageSize");
|
||||
if (sendRate != null) {
|
||||
Rate r = sendRate.getRate(5*60*1000);
|
||||
if (r != null)
|
||||
sendBytes5m = r.getLastTotalValue();
|
||||
r = sendRate.getRate(60*60*1000);
|
||||
if (r != null)
|
||||
sendBytes60m = r.getLastTotalValue();
|
||||
}
|
||||
|
||||
RateStat recvRate = _context.statManager().getRate("transport.receiveMessageSize");
|
||||
if (recvRate != null) {
|
||||
Rate r = recvRate.getRate(5*60*1000);
|
||||
if (r != null)
|
||||
recvBytes5m = r.getLastTotalValue();
|
||||
r = recvRate.getRate(60*60*1000);
|
||||
if (r != null)
|
||||
recvBytes60m = r.getLastTotalValue();
|
||||
}
|
||||
|
||||
String throughputRate = renderThroughput(sendBytes5m, 5*60*1000);
|
||||
stats.setProperty("stat_bandwidthSendBps.5m", throughputRate);
|
||||
throughputRate = renderThroughput(sendBytes60m, 60*60*1000);
|
||||
stats.setProperty("stat_bandwidthSendBps.60m", throughputRate);
|
||||
throughputRate = renderThroughput(recvBytes5m, 5*60*1000);
|
||||
stats.setProperty("stat_bandwidthReceiveBps.5m", throughputRate);
|
||||
throughputRate = renderThroughput(recvBytes60m, 60*60*1000);
|
||||
stats.setProperty("stat_bandwidthReceiveBps.60m", throughputRate);
|
||||
}
|
||||
|
||||
|
||||
private String getPeriod(Rate rate) { return DataHelper.formatDuration(rate.getPeriod()); }
|
||||
|
||||
private final String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
|
||||
private final String pct(double num) { synchronized (_pct) { return _pct.format(num); } }
|
||||
|
||||
public String renderStatusHTML() { return ""; }
|
||||
}
|
||||
|
@@ -8,6 +8,8 @@ import net.i2p.util.HTTPSendData;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.router.transport.BandwidthLimitedInputStream;
|
||||
|
||||
/**
|
||||
* Job that, if its allowed to, will submit the data gathered by the MessageHistory
|
||||
* component to some URL so that the network can be debugged more easily. By default
|
||||
@@ -87,8 +89,8 @@ public class SubmitMessageHistoryJob extends JobImpl {
|
||||
if (size > 0)
|
||||
expectedSend += (int)size/10; // compression
|
||||
FileInputStream fin = new FileInputStream(dataFile);
|
||||
_context.bandwidthLimiter().delayOutbound(null, expectedSend);
|
||||
boolean sent = HTTPSendData.postData(url, size, fin);
|
||||
BandwidthLimitedInputStream in = new BandwidthLimitedInputStream(_context, fin, null, true);
|
||||
boolean sent = HTTPSendData.postData(url, size, in);
|
||||
fin.close();
|
||||
boolean deleted = dataFile.delete();
|
||||
_log.debug("Submitted " + size + " bytes? " + sent + " and deleted? " + deleted);
|
||||
|
@@ -31,11 +31,14 @@ import net.i2p.data.i2np.TunnelSessionKey;
|
||||
import net.i2p.data.i2np.TunnelSigningPrivateKey;
|
||||
import net.i2p.data.i2np.TunnelSigningPublicKey;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Defines the information associated with a tunnel
|
||||
*/
|
||||
public class TunnelInfo extends DataStructureImpl {
|
||||
private I2PAppContext _context;
|
||||
private static Log _log;
|
||||
private TunnelId _id;
|
||||
private Hash _nextHop;
|
||||
private Hash _thisHop;
|
||||
@@ -51,9 +54,12 @@ public class TunnelInfo extends DataStructureImpl {
|
||||
private long _lastTested;
|
||||
private boolean _ready;
|
||||
private boolean _wasEverReady;
|
||||
private int _messagesProcessed;
|
||||
|
||||
public TunnelInfo(I2PAppContext context) {
|
||||
_context = context;
|
||||
if (_log == null)
|
||||
_log = context.logManager().getLog(TunnelInfo.class);
|
||||
setTunnelId(null);
|
||||
setThisHop(null);
|
||||
setNextHop(null);
|
||||
@@ -69,6 +75,7 @@ public class TunnelInfo extends DataStructureImpl {
|
||||
_wasEverReady = false;
|
||||
_created = _context.clock().now();
|
||||
_lastTested = -1;
|
||||
_messagesProcessed = 0;
|
||||
}
|
||||
|
||||
public TunnelId getTunnelId() { return _id; }
|
||||
@@ -162,6 +169,15 @@ public class TunnelInfo extends DataStructureImpl {
|
||||
return len;
|
||||
}
|
||||
|
||||
/** how many messages have passed through this tunnel in its lifetime? */
|
||||
public int getMessagesProcessed() {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Tunnel " + _id.getTunnelId() + " processed " + _messagesProcessed + " messages");
|
||||
return _messagesProcessed;
|
||||
}
|
||||
/** we have just processed a message for this tunnel */
|
||||
public void messageProcessed() { _messagesProcessed++; }
|
||||
|
||||
public void readBytes(InputStream in) throws DataFormatException, IOException {
|
||||
_options = DataHelper.readProperties(in);
|
||||
Boolean includeDest = DataHelper.readBoolean(in);
|
||||
|
@@ -46,7 +46,7 @@ public class AdminManager implements Service {
|
||||
private void startup(int port) {
|
||||
_listener = new AdminListener(_context, port);
|
||||
I2PThread t = new I2PThread(_listener);
|
||||
t.setName("Admin Listener");
|
||||
t.setName("Admin Listener:" + port);
|
||||
t.setDaemon(true);
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.start();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user