forked from I2P_Developers/i2p.i2p
Compare commits
125 Commits
Author | SHA1 | Date | |
---|---|---|---|
5d4bdc5697 | |||
0fdb286005 | |||
59a8493aa7 | |||
25378e894b | |||
3b9fea20b6 | |||
c6bb8f09ca | |||
4a9bd84bf0 | |||
c02522b0fe | |||
c2a71ef756 | |||
e669110cf4 | |||
f4cf31c13d | |||
7b23a5dcce | |||
b2fda0c79d | |||
5af96f5ccb | |||
ca445ac178 | |||
16fb31b6eb | |||
a1ff325b7b | |||
5eaec4c841 | |||
ffcc34c4f9 | |||
2dbe33e769 | |||
60c7db0733 | |||
0ed95bbdf1 | |||
c901bcf9b7 | |||
0ccf915a18 | |||
52b1c0a926 | |||
399865e6c8 | |||
54aeab1524 | |||
91f83277e2 | |||
c937cb2f07 | |||
ebd150e473 | |||
9218f7b82c | |||
edaf7aee5d | |||
43c18d0f4d | |||
65d85f7479 | |||
476e23db5b | |||
abaa5d87f6 | |||
ce3e7e623c | |||
3fd35a9c18 | |||
f170ae741e | |||
03562b037d | |||
472312709a | |||
b68463249e | |||
740a2da702 | |||
85c8e56417 | |||
481ef56e74 | |||
008795770f | |||
834fb7e317 | |||
da4827f287 | |||
9f4439583d | |||
69981e4d78 | |||
a857c6a88f | |||
e8d19439f8 | |||
56216250a7 | |||
bea331db26 | |||
bc4e833a47 | |||
83f399fffc | |||
5214436d18 | |||
8603250d73 | |||
9a8a099701 | |||
a5a0c8c837 | |||
604bcd5874 | |||
d29f9409bf | |||
b5a0f5910d | |||
ccb2600e67 | |||
f06e21ff5a | |||
bb0817a2ec | |||
6911f865ca | |||
fe28b2732c | |||
e8e8c37496 | |||
ef0f1ca1e7 | |||
31ca34b954 | |||
c4e6a2f0a8 | |||
b56845e200 | |||
d7a1fee781 | |||
b1f802c42d | |||
5f022e6e1f | |||
392cbb817e | |||
130399a1e7 | |||
37d5531737 | |||
f0b6cbaf89 | |||
707b173e77 | |||
4381bb5026 | |||
5850ad1217 | |||
806d598a04 | |||
e737e5c950 | |||
bbcde2f52b | |||
f6ef77429c | |||
44491c1514 | |||
71a6cf4ee6 | |||
744ce6966f | |||
d25cec02c2 | |||
f02bf37fd3 | |||
304b9d41d7 | |||
2d6af89f60 | |||
d6425973e2 | |||
d5ad56c4de | |||
4f1f2cc99e | |||
da439dd127 | |||
1375d01bdf | |||
7b9db07f13 | |||
f2f26136c1 | |||
0f60ac5acf | |||
c28f19fe8a | |||
09a6dbc755 | |||
3bc0e0fc8a | |||
eb0e187a54 | |||
a788d30f34 | |||
591dfc961e | |||
809e12b034 | |||
1669d174e1 | |||
3cfd28de43 | |||
4888207eca | |||
294cb96107 | |||
b648fa2b70 | |||
ab99122211 | |||
dd014fee88 | |||
c81f864de3 | |||
90fe7dceec | |||
3a568096f2 | |||
94e694fc61 | |||
bdfa6e4af5 | |||
8e64ffb4f6 | |||
6c162643cb | |||
ff7742bca3 | |||
9685884279 |
@ -26,13 +26,11 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
#include "platform.hpp"
|
||||
#include "mutex.hpp"
|
||||
#include "time.hpp"
|
||||
#include "logger.hpp"
|
||||
@ -41,10 +39,10 @@ using namespace Libsockthread;
|
||||
/*
|
||||
* Closes the log file
|
||||
*/
|
||||
void Logger::close(void)
|
||||
void Logger::close()
|
||||
{
|
||||
logf_m.lock();
|
||||
if (logf == 0) {
|
||||
if (logf == NULL) {
|
||||
logf_m.unlock();
|
||||
return;
|
||||
}
|
||||
@ -53,7 +51,7 @@ void Logger::close(void)
|
||||
cerr << "fclose() failed: " << strerror(errno) << '\n';
|
||||
cerr_m.unlock();
|
||||
}
|
||||
logf = 0;
|
||||
logf = NULL;
|
||||
logf_m.unlock();
|
||||
}
|
||||
|
||||
@ -88,15 +86,14 @@ void Logger::log(priority_t priority, const char* format, ...)
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
string s;
|
||||
Time t;
|
||||
logf_m.lock();
|
||||
|
||||
if (logf != 0) {
|
||||
if (logf != NULL) {
|
||||
/*
|
||||
* Remember! If you change the format here, change it in the else too
|
||||
*/
|
||||
fprintf(logf, "%c %s ", ll, t.utc(s).c_str());
|
||||
fprintf(logf, "%c %s ", ll, t.utc().c_str());
|
||||
vfprintf(logf, format, ap);
|
||||
fputc('\n', logf);
|
||||
if (fflush(logf) == EOF) {
|
||||
@ -106,7 +103,7 @@ void Logger::log(priority_t priority, const char* format, ...)
|
||||
}
|
||||
} else {
|
||||
// if they don't have an open log file, just use stderr
|
||||
fprintf(stderr, "%c %s ", ll, t.utc(s).c_str());
|
||||
fprintf(stderr, "%c %s ", ll, t.utc().c_str());
|
||||
vfprintf(stderr, format, ap);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
@ -118,8 +115,8 @@ void Logger::log(priority_t priority, const char* format, ...)
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a log file for appending. If there already is an open log file, then
|
||||
* it is closed and the new one is opened.
|
||||
* Opens a log file for appending. If a log file is already open, then it is
|
||||
* closed and the new one is opened.
|
||||
*
|
||||
* file - file location to open
|
||||
*/
|
||||
@ -145,8 +142,8 @@ bool Logger::open(const string& file)
|
||||
// g++ -Wall -c mutex.cpp -o mutex.o
|
||||
// g++ -Wall -c time.cpp -o time.o
|
||||
// g++ -Wall -DUNIT_TEST -c logger.cpp -o logger.o
|
||||
// g++ -Wall -DUNIT_TEST logger.o mutex.o thread.o time.o -o logger -lpthread
|
||||
int main(void)
|
||||
// g++ -Wall -DUNIT_TEST logger.o mutex.o thread.o time.o -o logger -pthread
|
||||
int main()
|
||||
{
|
||||
Logger logger;
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_LOGGER_HPP
|
||||
@ -40,8 +42,7 @@
|
||||
* LWARN - errors we automatically recover from
|
||||
* LERROR - major, important errors
|
||||
*
|
||||
* Obviously, these only work if your Logger object is called "logger" and is
|
||||
* global
|
||||
* These only work if your Logger object is called "logger"
|
||||
*/
|
||||
// Prints out the file name, function name, and line number before the message
|
||||
#define LDEBUG(format, ...) logger.log(Logger::DEBUG, "%s:%s:%d:" \
|
||||
@ -69,16 +70,17 @@
|
||||
namespace Libsockthread {
|
||||
class Logger {
|
||||
public:
|
||||
typedef enum {DEBUG = 0, MINOR = 1, INFO = 2, WARN = 3, ERROR = 4}
|
||||
priority_t;
|
||||
enum priority_t {DEBUG = 0, MINOR = 1, INFO = 2, WARN = 3,
|
||||
ERROR = 4};
|
||||
|
||||
Logger(void)
|
||||
: logf(0), loglevel(Logger::DEBUG) { }
|
||||
~Logger(void) { close(); }
|
||||
Logger()
|
||||
: logf(NULL), loglevel(Logger::DEBUG) { }
|
||||
~Logger()
|
||||
{ close(); }
|
||||
|
||||
void close(void);
|
||||
void close();
|
||||
void log(priority_t priority, const char* format, ...);
|
||||
priority_t get_loglevel(void)
|
||||
priority_t get_loglevel()
|
||||
{ loglevel_m.lock(); priority_t ll = loglevel;
|
||||
loglevel_m.unlock(); return ll; }
|
||||
bool open(const string& file);
|
||||
|
@ -26,31 +26,28 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
// Modelled after JThread by Jori Liesenborgs
|
||||
/*
|
||||
* Modelled after JThread by Jori Liesenborgs
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include "platform.hpp"
|
||||
#ifdef WINTHREAD
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
using namespace std;
|
||||
#include "mutex.hpp"
|
||||
using namespace Libsockthread;
|
||||
|
||||
/*
|
||||
* Creates a mutex
|
||||
*/
|
||||
Mutex::Mutex(void)
|
||||
Mutex::Mutex()
|
||||
{
|
||||
#ifdef WINTHREAD
|
||||
mutex = CreateMutex(0, false, 0);
|
||||
assert(mutex != 0);
|
||||
mutex = CreateMutex(NULL, false, NULL);
|
||||
assert(mutex != NULL);
|
||||
#else
|
||||
int rc = pthread_mutex_init(&mutex, 0);
|
||||
int rc = pthread_mutex_init(&mutex, NULL);
|
||||
assert(rc == 0);
|
||||
#endif
|
||||
}
|
||||
@ -58,7 +55,7 @@ Mutex::Mutex(void)
|
||||
/*
|
||||
* Destroys a mutex
|
||||
*/
|
||||
Mutex::~Mutex(void)
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
#ifdef WINTHREAD
|
||||
BOOL rc = CloseHandle(mutex);
|
||||
@ -72,7 +69,7 @@ Mutex::~Mutex(void)
|
||||
/*
|
||||
* Locks the mutex
|
||||
*/
|
||||
void Mutex::lock(void)
|
||||
void Mutex::lock()
|
||||
{
|
||||
#ifdef WINTHREAD
|
||||
DWORD rc = WaitForSingleObject(mutex, INFINITE);
|
||||
@ -86,7 +83,7 @@ void Mutex::lock(void)
|
||||
/*
|
||||
* Unlocks the mutex
|
||||
*/
|
||||
void Mutex::unlock(void)
|
||||
void Mutex::unlock()
|
||||
{
|
||||
#ifdef WINTHREAD
|
||||
BOOL rc = ReleaseMutex(mutex);
|
||||
@ -100,13 +97,12 @@ void Mutex::unlock(void)
|
||||
#ifdef UNIT_TEST
|
||||
// g++ -Wall -c thread.cpp -o thread.o
|
||||
// g++ -Wall -DUNIT_TEST -c mutex.cpp -o mutex.o
|
||||
// g++ -Wall -DUNIT_TEST mutex.o thread.o -o mutex -lpthread
|
||||
#include <iostream>
|
||||
// g++ -Wall -DUNIT_TEST mutex.o thread.o -o mutex -pthread
|
||||
#include "thread.hpp"
|
||||
|
||||
Mutex widget;
|
||||
|
||||
int main(void)
|
||||
int main()
|
||||
{
|
||||
class Mutex_test : public Thread
|
||||
{
|
||||
@ -114,7 +110,7 @@ int main(void)
|
||||
Mutex_test(int n)
|
||||
: testval(n) {}
|
||||
|
||||
void* thread(void)
|
||||
void* thread()
|
||||
{
|
||||
widget.lock();
|
||||
cout << "I got it! thread #" << testval << '\n';
|
||||
@ -122,9 +118,11 @@ int main(void)
|
||||
// widget, since it is never unlocked
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int testval;
|
||||
};
|
||||
|
||||
Mutex_test t1(1);
|
||||
Mutex_test t2(2);
|
||||
Mutex_test t3(3);
|
||||
|
@ -26,9 +26,13 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
// Modelled after JThread by Jori Liesenborgs
|
||||
/*
|
||||
* Modelled after JThread by Jori Liesenborgs
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_MUTEX_HPP
|
||||
#define LIBSOCKTHREAD_MUTEX_HPP
|
||||
@ -36,11 +40,11 @@
|
||||
namespace Libsockthread {
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex(void);
|
||||
~Mutex(void);
|
||||
Mutex();
|
||||
~Mutex();
|
||||
|
||||
void lock(void);
|
||||
void unlock(void);
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
#ifdef WINTHREAD
|
||||
HANDLE mutex;
|
||||
|
@ -26,6 +26,14 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id: platform.hpp,v 1.5 2004/07/22 03:54:01 mpc Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Global includes and platform configuration. This is used to compile the
|
||||
* library, but is not intended for use by users of the library in their
|
||||
* own programs.
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_PLATFORM_HPP
|
||||
@ -34,30 +42,36 @@
|
||||
/*
|
||||
* Operating system
|
||||
*/
|
||||
#define FREEBSD 0 // FreeBSD (untested)
|
||||
#define MINGW 1 // Windows native (Mingw)
|
||||
#define FREEBSD 0 // FreeBSD
|
||||
#define WIN32 1 // Windows
|
||||
#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
|
||||
#if OS == WIN32
|
||||
#define WINSOCK
|
||||
#define WINTHREAD
|
||||
#endif
|
||||
|
||||
#if OS == LINUX
|
||||
#define NO_GETHOSTBYNAME2
|
||||
#ifndef WINSOCK
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#if OS == CYGWIN
|
||||
#define FAST32_IS_LONG
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#define NO_GETHOSTBYNAME2
|
||||
#define NO_INET_NTOP
|
||||
#define NO_INET_PTON
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#ifndef WINSOCK
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifndef WINTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <stdint.h> // TODO replace with Boost's version
|
||||
#include <string>
|
||||
#if defined WINSOCK || defined WINTHREAD
|
||||
#include <windows.h>
|
||||
#endif
|
||||
using namespace std;
|
||||
#include "types.hpp"
|
||||
|
||||
#endif // LIBSOCKTHREAD_PLATFORM_HPP
|
||||
|
@ -26,252 +26,47 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id: socket.cpp,v 1.8 2004/07/22 22:08:20 mpc Exp $
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
using namespace std;
|
||||
#include "platform.hpp"
|
||||
#include "socket_error.hpp"
|
||||
#include "socket.hpp"
|
||||
using namespace Libsockthread;
|
||||
|
||||
size_t Socket::total = 0; // the total number of sockets in use
|
||||
|
||||
/*
|
||||
* Constructs an IPv4 TCP socket
|
||||
*/
|
||||
Socket::Socket(void)
|
||||
{
|
||||
++total;
|
||||
try {
|
||||
#ifdef WINSOCK
|
||||
if (total == 1)
|
||||
winsock_startup();
|
||||
#endif
|
||||
create_socket(PF_INET, SOCK_STREAM);
|
||||
} catch (const Socket_error& x) {
|
||||
--total;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructs the socket
|
||||
*
|
||||
* domain - either PF_INET or PF_INET6
|
||||
* type - either SOCK_STREAM or SOCK_DGRAM
|
||||
*/
|
||||
Socket::Socket(int domain, int type)
|
||||
{
|
||||
++total;
|
||||
try {
|
||||
#ifdef WINSOCK
|
||||
if (total == 1)
|
||||
winsock_startup();
|
||||
#endif
|
||||
create_socket(domain, type);
|
||||
} catch {const Socket_error& x) {
|
||||
--total;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the socket
|
||||
*/
|
||||
Socket::~Socket(void)
|
||||
{
|
||||
close();
|
||||
--total;
|
||||
assert(total >= 0);
|
||||
#ifdef WINSOCK
|
||||
if (total == 0)
|
||||
winsock_cleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Closes the socket
|
||||
*/
|
||||
void Socket::close(void)
|
||||
void Socket::close()
|
||||
{
|
||||
#ifdef WINSOCK
|
||||
if (closesocket(sock) == SOCKET_ERROR) {
|
||||
LERROR("closesocket() failed: %s", winsock_strerror(WSAGetLastError()));
|
||||
if (sock != SERR) {
|
||||
if (close(sock) == -1)
|
||||
; // FIXME log the error
|
||||
}
|
||||
#else
|
||||
if (close(sock) == -1) {
|
||||
LERROR("close() failed: %s", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
sock = SERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates the socket
|
||||
*
|
||||
* domain - either PF_INET or PF_INET6
|
||||
* type - either SOCK_STREAM or SOCK_DGRAM
|
||||
* Changes the address associated with the socket
|
||||
*/
|
||||
void Socket::create_socket(int domain, int type)
|
||||
void Socket::set_addr(Socket_addr& addr)
|
||||
{
|
||||
assert((domain == PF_INET || domain == PF_INET6) &&
|
||||
(type == SOCK_STREAM || type == SOCK_DGRAM));
|
||||
sock = socket(domain, type, 0);
|
||||
#ifdef WINSOCK
|
||||
if (sock == INVALID_SOCKET)
|
||||
throw Socket_error(sam_winsock_strerror(WSAGetLastError()));
|
||||
#else
|
||||
if (sock == -1)
|
||||
close();
|
||||
this->addr = addr;
|
||||
setup_socket();
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepares the socket for use
|
||||
*/
|
||||
void Socket::setup_socket()
|
||||
{
|
||||
assert(sock == SERR); // the descriptor shouldn't be active
|
||||
if (!addr.is_ready())
|
||||
throw Socket_error("Couldn't create socket: address isn't ready");
|
||||
|
||||
sock = socket(addr.get_family(), addr.get_type(), 0);
|
||||
if (sock == SERR)
|
||||
throw Socket_error(strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WINSOCK
|
||||
/*
|
||||
* Unloads the Winsock network subsystem
|
||||
*/
|
||||
void Socket::winsock_cleanup(void)
|
||||
{
|
||||
int rc = WSACleanup();
|
||||
assert(rc != SOCKET_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads the Winsock network sucksystem
|
||||
*/
|
||||
void Socket::winsock_startup(void)
|
||||
{
|
||||
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||
WSADATA wsaData;
|
||||
int rc = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (rc != 0)
|
||||
throw Socket_error(winsock_strerror(rc));
|
||||
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
|
||||
winsock_cleanup();
|
||||
throw Socket_error("Bad Winsock version");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Apparently Winsock does not have a strerror() equivalent for its functions
|
||||
*
|
||||
* code - code from WSAGetLastError()
|
||||
*
|
||||
* Returns: error string (from http://msdn.microsoft.com/library/default.asp?
|
||||
* url=/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp)
|
||||
*/
|
||||
const char* Socket::winsock_strerror(int code)
|
||||
{
|
||||
switch (code) {
|
||||
case WSAEINTR:
|
||||
return "Interrupted function call";
|
||||
case WSAEACCES: // yes, that is the correct spelling
|
||||
return "Permission denied";
|
||||
case WSAEFAULT:
|
||||
return "Bad address";
|
||||
case WSAEINVAL:
|
||||
return "Invalid argument";
|
||||
case WSAEMFILE:
|
||||
return "Too many open files";
|
||||
case WSAEWOULDBLOCK:
|
||||
return "Resource temporarily unavailable";
|
||||
case WSAEINPROGRESS:
|
||||
return "Operation now in progress";
|
||||
case WSAEALREADY:
|
||||
return "Operation already in progress";
|
||||
case WSAENOTSOCK:
|
||||
return "Socket operations on nonsocket";
|
||||
case WSAEDESTADDRREQ:
|
||||
return "Destination address required";
|
||||
case WSAEMSGSIZE:
|
||||
return "Message too long";
|
||||
case WSAEPROTOTYPE:
|
||||
return "Protocol wrong type for socket";
|
||||
case WSAENOPROTOOPT:
|
||||
return "Bad protocol option";
|
||||
case WSAEPROTONOSUPPORT:
|
||||
return "Protocol not supported";
|
||||
case WSAESOCKTNOSUPPORT:
|
||||
return "Socket type not supported";
|
||||
case WSAEOPNOTSUPP:
|
||||
return "Operation not supported";
|
||||
case WSAEPFNOSUPPORT:
|
||||
return "Protocol family not supported";
|
||||
case WSAEAFNOSUPPORT:
|
||||
return "Address family not supported by protocol family";
|
||||
case WSAEADDRINUSE:
|
||||
return "Address already in use";
|
||||
case WSAEADDRNOTAVAIL:
|
||||
return "Cannot assign requested address";
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
case WSAENETUNREACH:
|
||||
return "Network is unreachable";
|
||||
case WSAENETRESET:
|
||||
return "Network dropped connection on reset";
|
||||
case WSAECONNABORTED:
|
||||
return "Software caused connection abort";
|
||||
case WSAECONNRESET:
|
||||
return "Connection reset by peer";
|
||||
case WSAENOBUFS:
|
||||
return "No buffer space available";
|
||||
case WSAEISCONN:
|
||||
return "Socket is already connected";
|
||||
case WSAENOTCONN:
|
||||
return "Socket is not connected";
|
||||
case WSAESHUTDOWN:
|
||||
return "Cannot send after socket shutdown";
|
||||
case WSAETIMEDOUT:
|
||||
return "Connection timed out";
|
||||
case WSAECONNREFUSED:
|
||||
return "Connection refused";
|
||||
case WSAEHOSTDOWN:
|
||||
return "Host is down";
|
||||
case WSAEHOSTUNREACH:
|
||||
return "No route to host";
|
||||
case WSAEPROCLIM:
|
||||
return "Too many processes";
|
||||
case WSASYSNOTREADY:
|
||||
return "Network subsystem is unavailable";
|
||||
case WSAVERNOTSUPPORTED:
|
||||
return "Winsock.dll version out of range";
|
||||
case WSANOTINITIALISED:
|
||||
return "Successful WSAStartup not yet performed";
|
||||
case WSAEDISCON:
|
||||
return "Graceful shutdown in progress";
|
||||
case WSATYPE_NOT_FOUND:
|
||||
return "Class type not found";
|
||||
case WSAHOST_NOT_FOUND:
|
||||
return "Host not found";
|
||||
case WSATRY_AGAIN:
|
||||
return "Nonauthoritative host not found";
|
||||
case WSANO_RECOVERY:
|
||||
return "This is a nonrecoverable error";
|
||||
case WSANO_DATA:
|
||||
return "Valid name, no data record of requested type";
|
||||
/* None of this shit compiles under Mingw - who knows why...
|
||||
case WSA_INVALID_HANDLE:
|
||||
return "Specified event object handle is invalid";
|
||||
case WSA_INVALID_PARAMETER:
|
||||
return "One or more parameters are invalid";
|
||||
case WSA_IO_INCOMPLETE:
|
||||
return "Overlapped I/O event object not in signaled state";
|
||||
case WSA_IO_PENDING:
|
||||
return "Overlapped operations will complete later";
|
||||
case WSA_NOT_ENOUGH_MEMORY:
|
||||
return "Insufficient memory available";
|
||||
case WSA_OPERATION_ABORTED:
|
||||
return "Overlapped operation aborted";
|
||||
case WSAINVALIDPROCTABLE:
|
||||
return "Invalid procedure table from service provider";
|
||||
case WSAINVALIDPROVIDER:
|
||||
return "Invalid service provider version number";
|
||||
case WSAPROVIDERFAILEDINIT:
|
||||
return "Unable to initialize a service provider";
|
||||
*/
|
||||
case WSASYSCALLFAILURE:
|
||||
return "System call failure";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
#endif // WINSOCK
|
||||
|
@ -26,38 +26,42 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id: socket.hpp,v 1.8 2004/07/22 22:08:20 mpc Exp $
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_SOCKET_HPP
|
||||
#define LIBSOCKTHREAD_SOCKET_HPP
|
||||
|
||||
namespace Libsockthread {
|
||||
class Socket_error : public runtime_error {
|
||||
public:
|
||||
Socket_error(const string& s)
|
||||
: runtime_error(s) { }
|
||||
};
|
||||
class Socket {
|
||||
public:
|
||||
Socket(void); // throws Socket_error
|
||||
Socket(int domain, int type); // throws Socket_error
|
||||
~Socket(void);
|
||||
#ifdef WINSOCK
|
||||
typedef SOCKET socket_t;
|
||||
enum { SERR = SOCKET_ERROR };
|
||||
#else
|
||||
typedef int socket_t;
|
||||
enum { SERR = -1 };
|
||||
#endif
|
||||
|
||||
void close(void);
|
||||
Socket()
|
||||
: addr(), sock(SERR) {}
|
||||
Socket(Socket_addr& addr) // throws Socket_error
|
||||
: addr(addr), sock(SERR) { setup_socket(); }
|
||||
|
||||
void close();
|
||||
size_t read(vector<uchar_t>& buf, size_t max = 0);
|
||||
size_t read_until(vector<uchar_t>& buf, uchar_t delim = '\n');
|
||||
void set_addr(Socket_addr& addr); // throws Socket_error
|
||||
void set_blocking(bool blocking);
|
||||
size_t write(vector<uchar_t>& buf);
|
||||
void write_all(vector<uchar_t>& buf);
|
||||
size_t write_until(vector<uchar_t& buf, uchar_t delim = '\n');
|
||||
private:
|
||||
#ifdef WINSOCK
|
||||
typedef SOCKET socket_t;
|
||||
|
||||
void winsock_cleanup(void);
|
||||
void winsock_startup(void); // throws Socket_error
|
||||
const char* winsock_strerror(int code);
|
||||
#else
|
||||
typedef int socket_t;
|
||||
#endif
|
||||
void create_socket(int domain, int type); // throws Socket_error
|
||||
void setup_socket(); // throws Socket_error
|
||||
|
||||
Socket_addr addr;
|
||||
socket_t sock;
|
||||
static size_t total; // the total number of sockets in memory
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -26,58 +26,83 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id: socket_addr.cpp,v 1.4 2004/07/22 19:10:59 mpc Exp $
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <cassert>
|
||||
using namespace std;
|
||||
#include "platform.hpp"
|
||||
#include "socket.hpp"
|
||||
#include "socket_error.hpp"
|
||||
#include "socket_addr.hpp"
|
||||
using namespace Libsockthread;
|
||||
|
||||
Socket_addr::Socket_addr(int domain, const string& host, uint16_t port)
|
||||
: domain(domain), host(host), port(port)
|
||||
Socket_addr::Socket_addr(Socket_addr& rhs)
|
||||
{
|
||||
memset(&hostaddr, 0, sizeof hostaddr);
|
||||
hostaddr.sin_family = domain;
|
||||
hostaddr.sin_port = htons(port);
|
||||
resolve(host.c_str(), ipaddr);
|
||||
int rc;
|
||||
#ifdef NO_INET_ATON
|
||||
rc = hostaddr.sin_addr.s_addr = inet_addr(ipaddr);
|
||||
#elif defined NO_INET_PTON
|
||||
rc = inet_aton(ipaddr, &hostaddr.sin_addr);
|
||||
#else
|
||||
rc = inet_pton(AF_INET, ipaddr, &hostaddr.sin_addr);
|
||||
#endif
|
||||
assert(rc != 0 && rc != -1);
|
||||
delete[] ip;
|
||||
if (rhs.resolved) {
|
||||
if (rhs.family == AF_INET) {
|
||||
ip = new char[INET_ADDRSTRLEN];
|
||||
else
|
||||
ip = new char[INET6_ADDRSTRLEN];
|
||||
strcpy(ip, rhs.ip);
|
||||
}
|
||||
family = rhs.family;
|
||||
host = rhs.host;
|
||||
port = rhs.port;
|
||||
resolved = rhs.resolved;
|
||||
type = rhs.type;
|
||||
}
|
||||
|
||||
Socket_addr& Socket_addr::operator=(const Socket_addr& rhs)
|
||||
{
|
||||
if (this == &rhs) // check for self-assignment: a = a
|
||||
return *this;
|
||||
|
||||
delete[] ip;
|
||||
if (rhs.resolved) {
|
||||
if (rhs.family == AF_INET)
|
||||
ip = new char[INET_ADDRSTRLEN];
|
||||
else
|
||||
ip = new char[INET6_ADDRSTRLEN];
|
||||
strcpy(ip, rhs.ip);
|
||||
}
|
||||
family = rhs.family;
|
||||
host = rhs.host;
|
||||
port = rhs.port;
|
||||
type = rhs.type;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a DNS lookup on `hostname' and puts the result in `ipaddr'
|
||||
* Performs a DNS lookup
|
||||
*/
|
||||
bool Socket::resolve(const char* hostname, char* ipaddr)
|
||||
void Socket_addr::resolve()
|
||||
{
|
||||
struct hostent *h;
|
||||
#ifdef NO_GETHOSTBYNAME2
|
||||
h = gethostbyname(hostname);
|
||||
#else
|
||||
h = gethostbyname2(hostname, domain);
|
||||
#endif
|
||||
if (h == 0) {
|
||||
LWARN("DNS resolution failed for %s", hostname);
|
||||
throw Socket_error("DNS resolution failed");
|
||||
}
|
||||
struct in_addr a;
|
||||
a.s_addr = ((struct in_addr *)h->h_addr)->s_addr;
|
||||
#ifdef NO_INET_NTOP
|
||||
char *tmp;
|
||||
tmp = inet_ntoa(a);
|
||||
assert(tmp != 0);
|
||||
strlcpy(ipaddr, tmp, INET_ADDRSTRLEN); // inet_ntoa() was very poorly designed
|
||||
#else
|
||||
int rc = inet_ntop(domain, &a, ipaddr, INET_ADDRSTRLEN);
|
||||
assert(rc != 0);
|
||||
#endif
|
||||
resolved = false; // in case they already had a host name but just set a
|
||||
// new one with set_host()
|
||||
hostent* hent = gethostbyname(host.c_str());
|
||||
if (hent == NULL)
|
||||
throw Dns_error(hstrerror(h_errno));
|
||||
assert(hent->h_addrtype == AF_INET || hent->h_addrtype == AF_INET6);
|
||||
family = hent->h_addrtype;
|
||||
delete[] ip;
|
||||
if (family == AF_INET) {
|
||||
ip = new char[INET_ADDRSTRLEN];
|
||||
else
|
||||
ip = new char[INET6_ADDRSTRLEN];
|
||||
strcpy(ip, hent->h_addr_list[0]);
|
||||
resolved = true;
|
||||
}
|
||||
|
||||
bool Socket_addr::operator==(const Socket_addr& rhs)
|
||||
{
|
||||
if (rhs.family == family
|
||||
&& rhs.host == host
|
||||
&& strcmp(rhs.ip, ip) == 0
|
||||
&& rhs.port == port
|
||||
&& rhs.resolved == resolved
|
||||
&& rhs.type == type)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id: socket_addr.hpp,v 1.4 2004/07/22 19:10:59 mpc Exp $
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_SOCKET_ADDR_HPP
|
||||
@ -34,15 +36,42 @@
|
||||
namespace Libsockthread {
|
||||
class Socket_addr {
|
||||
public:
|
||||
Socket_addr(int domain, const string& host, uint16_t port);
|
||||
private:
|
||||
bool resolve(const char* hostname, char* ipaddr);
|
||||
Socket_addr()
|
||||
: family(AF_INET), resolved(false) { }
|
||||
Socket_addr(Socket_addr& rhs);
|
||||
Socket_addr(int type, string& host, uint16_t port)
|
||||
: family(AF_INET), host(host), type(type), port(port)
|
||||
{ resolve(); } // throws Dns_error
|
||||
~Socket_addr()
|
||||
{ delete[] ip; }
|
||||
|
||||
int domain; // PF_INET or PF_INET6
|
||||
int get_family() const
|
||||
{ return family; }
|
||||
const char* get_ip() const // Warning! This can be NULL!
|
||||
{ return ip; }
|
||||
uint16_t get_port() const
|
||||
{ return port; }
|
||||
int get_type() const
|
||||
{ return type;
|
||||
bool is_ready() const
|
||||
{ return resolved; }
|
||||
Socket_addr& operator=(const Socket_addr& rhs);
|
||||
bool operator==(const Socket_addr& rhs);
|
||||
void set_host(string& host) // throws Dns_error
|
||||
{ this->host = host; resolve(); }
|
||||
void set_port(uint16_t port)
|
||||
{ this->port = port; }
|
||||
void set_type(int type)
|
||||
{ this->type = type; }
|
||||
private:
|
||||
void resolve(); // throws Dns_error
|
||||
|
||||
int family; // AF_INET or AF_INET6
|
||||
string host;
|
||||
char ipaddr[INET_ADDRSTRLEN];
|
||||
struct sockaddr_in hostaddr;
|
||||
char* ip;
|
||||
uint16_t port;
|
||||
bool resolved;
|
||||
int type; // SOCK_STREAM or SOCK_DGRAM
|
||||
};
|
||||
}
|
||||
|
||||
|
35
apps/enclave/libsockthread/src/socket_connector.cpp
Normal file
35
apps/enclave/libsockthread/src/socket_connector.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "socket_connector.hpp"
|
||||
using namespace Libsockthread;
|
46
apps/enclave/libsockthread/src/socket_connector.hpp
Normal file
46
apps/enclave/libsockthread/src/socket_connector.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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_SOCKET_CONNECTOR_HPP
|
||||
#define LIBSOCKTHREAD_SOCKET_CONNECTOR_HPP
|
||||
|
||||
namespace Libsockthread {
|
||||
class Socket_connector : public Socket {
|
||||
public:
|
||||
Socket_connector(Socket_addr& addr)
|
||||
: Socket(addr);
|
||||
|
||||
void connect();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LIBSOCKTHREAD_SOCKET_CONNECTOR_HPP
|
47
apps/enclave/libsockthread/src/socket_error.hpp
Normal file
47
apps/enclave/libsockthread/src/socket_error.hpp
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.
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_SOCKET_ERROR_HPP
|
||||
#define LIBSOCKTHREAD_SOCKET_ERROR_HPP
|
||||
|
||||
namespace Libsockthread {
|
||||
class Socket_error : public runtime_error {
|
||||
public:
|
||||
Socket_error(const string& s)
|
||||
: runtime_error(s) { }
|
||||
};
|
||||
class Dns_error : public Socket_error {
|
||||
public:
|
||||
Dns_error(const string& s)
|
||||
: Socket_error(s) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LIBSOCKTHREAD_SOCKET_ERROR_HPP
|
35
apps/enclave/libsockthread/src/socket_listener.cpp
Normal file
35
apps/enclave/libsockthread/src/socket_listener.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "socket_listener.hpp"
|
||||
using namespace Libsockthread;
|
47
apps/enclave/libsockthread/src/socket_listener.hpp
Normal file
47
apps/enclave/libsockthread/src/socket_listener.hpp
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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_SOCKET_LISTENER_HPP
|
||||
#define LIBSOCKTHREAD_SOCKET_LISTENER_HPP
|
||||
|
||||
namespace Libsockthread {
|
||||
class Socket_listener {
|
||||
public:
|
||||
Socket_listener(Socket_addr& addr)
|
||||
: Socket(addr);
|
||||
|
||||
void accept();
|
||||
void listen();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LIBSOCKTHREAD_SOCKET_LISTENER_HPP
|
@ -12,6 +12,8 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -26,6 +26,8 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -26,18 +26,15 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
// Modelled after JThread by Jori Liesenborgs
|
||||
/*
|
||||
* Modelled after JThread by Jori Liesenborgs
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include "platform.hpp"
|
||||
#ifdef WINTHREAD
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
using namespace std;
|
||||
#include "mutex.hpp"
|
||||
#include "thread.hpp"
|
||||
using namespace Libsockthread;
|
||||
@ -45,12 +42,12 @@ using namespace Libsockthread;
|
||||
/*
|
||||
* Gets the return value of a finished thread
|
||||
*/
|
||||
void* Thread::get_retval(void)
|
||||
void* Thread::get_retval()
|
||||
{
|
||||
void* val;
|
||||
running_m.lock();
|
||||
if (running)
|
||||
val = 0;
|
||||
val = NULL;
|
||||
else
|
||||
val = retval;
|
||||
running_m.unlock();
|
||||
@ -60,7 +57,7 @@ void* Thread::get_retval(void)
|
||||
/*
|
||||
* Checks whether the thread is running
|
||||
*/
|
||||
bool Thread::is_running(void)
|
||||
bool Thread::is_running()
|
||||
{
|
||||
running_m.lock();
|
||||
bool r = running;
|
||||
@ -72,7 +69,7 @@ bool Thread::is_running(void)
|
||||
* Stops the thread
|
||||
* Generally NOT a good idea
|
||||
*/
|
||||
void Thread::kill(void)
|
||||
void Thread::kill()
|
||||
{
|
||||
running_m.lock();
|
||||
#ifndef NDEBUG
|
||||
@ -83,7 +80,7 @@ void Thread::kill(void)
|
||||
}
|
||||
#endif
|
||||
#ifdef WINTHREAD
|
||||
BOOL rc = TerminateThread(handle, 0);
|
||||
BOOL rc = TerminateThread(handle, NULL);
|
||||
assert(rc);
|
||||
#else
|
||||
int rc = pthread_cancel(id);
|
||||
@ -96,7 +93,7 @@ void Thread::kill(void)
|
||||
/*
|
||||
* Starts the thread
|
||||
*/
|
||||
void Thread::start(void)
|
||||
void Thread::start()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
// check whether the thread is already running
|
||||
@ -106,8 +103,8 @@ void Thread::start(void)
|
||||
#endif
|
||||
continue_m.lock();
|
||||
#ifdef WINTHREAD
|
||||
handle = CreateThread(0, 0, &the_thread, this, 0, &id);
|
||||
assert(handle != 0);
|
||||
handle = CreateThread(NULL, 0, &the_thread, this, 0, &id);
|
||||
assert(handle != NULL);
|
||||
#else
|
||||
int rc = pthread_create(&id, 0, &the_thread, this);
|
||||
assert(rc == 0);
|
||||
@ -145,10 +142,8 @@ void* Thread::the_thread(void *param)
|
||||
#ifdef UNIT_TEST
|
||||
// g++ -Wall -c mutex.cpp -o mutex.o
|
||||
// g++ -Wall -DUNIT_TEST -c thread.cpp -o thread.o
|
||||
// g++ -Wall -DUNIT_TEST mutex.o thread.o -o thread -lpthread
|
||||
#include <iostream>
|
||||
|
||||
int main(void)
|
||||
// g++ -Wall -DUNIT_TEST mutex.o thread.o -o thread -pthread
|
||||
int main()
|
||||
{
|
||||
class Thread_test : public Thread
|
||||
{
|
||||
@ -156,15 +151,14 @@ int main(void)
|
||||
Thread_test(int testval)
|
||||
: testval(testval) { }
|
||||
|
||||
int get_testval(void)
|
||||
int get_testval()
|
||||
{
|
||||
testval_m.lock();
|
||||
int rc = testval;
|
||||
testval_m.unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void *thread(void)
|
||||
void *thread()
|
||||
{
|
||||
// just do something
|
||||
while (true) {
|
||||
@ -174,6 +168,7 @@ int main(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int testval;
|
||||
Mutex testval_m;
|
||||
|
@ -26,9 +26,13 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
// Modelled after JThread by Jori Liesenborgs
|
||||
/*
|
||||
* Modelled after JThread by Jori Liesenborgs
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_THREAD_HPP
|
||||
#define LIBSOCKTHREAD_THREAD_HPP
|
||||
@ -36,16 +40,16 @@
|
||||
namespace Libsockthread {
|
||||
class Thread {
|
||||
public:
|
||||
Thread(void)
|
||||
: retval(0), running(false) { }
|
||||
virtual ~Thread(void)
|
||||
Thread()
|
||||
: retval(NULL), running(false) { }
|
||||
virtual ~Thread()
|
||||
{ kill(); }
|
||||
|
||||
void* get_retval(void);
|
||||
bool is_running(void);
|
||||
void kill(void);
|
||||
void start(void);
|
||||
virtual void *thread(void) = 0;
|
||||
void* get_retval();
|
||||
bool is_running();
|
||||
void kill();
|
||||
void start();
|
||||
virtual void* thread() = 0;
|
||||
private:
|
||||
#ifdef WINTHREAD
|
||||
static DWORD WINAPI the_thread(void* param);
|
||||
@ -56,7 +60,7 @@ namespace Libsockthread {
|
||||
pthread_t id;
|
||||
#endif
|
||||
Mutex continue_m;
|
||||
void *retval;
|
||||
void* retval;
|
||||
bool running;
|
||||
Mutex running_m;
|
||||
};
|
||||
|
@ -26,68 +26,59 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
#include "platform.hpp"
|
||||
#include "time.hpp"
|
||||
using namespace Libsockthread;
|
||||
|
||||
/*
|
||||
* Converts the time to an ISO 8601 standard time and date and puts it in a
|
||||
* string
|
||||
* Converts the time to an ISO 8601 standard date and time
|
||||
* Example: 2004-07-01T19:03:47Z
|
||||
*/
|
||||
string& Time::utc(string &s) const
|
||||
string& Time::utc()
|
||||
{
|
||||
struct tm* tm;
|
||||
|
||||
tm = gmtime(&unixtime);
|
||||
struct tm* tm = gmtime(&unixtime);
|
||||
char t[21];
|
||||
strftime(t, sizeof t, "%Y-%m-%dT%H:%M:%SZ", tm);
|
||||
return s = t;
|
||||
return formatted = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts the time to an ISO 8601 standard date and puts it in a string
|
||||
* Converts the time to an ISO 8601 standard date
|
||||
* Example: 2004-07-01Z
|
||||
*/
|
||||
string& Time::utc_date(string &s) const
|
||||
string& Time::utc_date()
|
||||
{
|
||||
struct tm* tm;
|
||||
|
||||
tm = gmtime(&unixtime);
|
||||
struct tm* tm = gmtime(&unixtime);
|
||||
char t[12];
|
||||
strftime(t, sizeof t, "%Y-%m-%dZ", tm);
|
||||
return s = t;
|
||||
return formatted = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts the time to an ISO 8601 standard time and puts it in a string
|
||||
* Converts the time to an ISO 8601 standard time
|
||||
* Example: 19:03:47Z
|
||||
*/
|
||||
string& Time::utc_time(string &s) const
|
||||
string& Time::utc_time()
|
||||
{
|
||||
struct tm* tm;
|
||||
|
||||
tm = gmtime(&unixtime);
|
||||
struct tm* tm = gmtime(&unixtime);
|
||||
char t[10];
|
||||
strftime(t, sizeof t, "%H:%M:%SZ", tm);
|
||||
return s = t;
|
||||
return formatted = t;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
// g++ -Wall -DUNIT_TEST time.cpp -o time
|
||||
#include <iostream>
|
||||
|
||||
int main(void)
|
||||
int main()
|
||||
{
|
||||
Time t;
|
||||
string s;
|
||||
cout << "Current date and time is " << t.utc(s) << '\n';
|
||||
cout << "Current date is " << t.utc_date(s) << '\n';
|
||||
cout << "Current time is " << t.utc_time(s) << '\n';
|
||||
cout << "Current date and time is " << t.utc() << '\n';
|
||||
cout << "Current date is " << t.utc_date() << '\n';
|
||||
cout << "Current time is " << t.utc_time() << '\n';
|
||||
cout << "Formatted time is " << t.get_formatted() << " (should be the same)\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_TIME_HPP
|
||||
@ -34,13 +36,18 @@
|
||||
namespace Libsockthread {
|
||||
class Time {
|
||||
public:
|
||||
Time(void) { now(); }
|
||||
Time()
|
||||
{ now(); }
|
||||
|
||||
void now(void) { unixtime = time(0); }
|
||||
string& utc(string &s) const;
|
||||
string& utc_date(string &s) const;
|
||||
string& utc_time(string &s) const;
|
||||
string& get_formatted()
|
||||
{ return formatted; }
|
||||
void now()
|
||||
{ unixtime = time(0); }
|
||||
string& utc();
|
||||
string& utc_date();
|
||||
string& utc_time();
|
||||
private:
|
||||
string formatted;
|
||||
time_t unixtime;
|
||||
};
|
||||
}
|
||||
|
45
apps/enclave/libsockthread/src/types.hpp
Normal file
45
apps/enclave/libsockthread/src/types.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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef LIBSOCKTHREAD_TYPES_HPP
|
||||
#define LIBSOCKTHREAD_TYPES_HPP
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
#endif // LIBSOCKTHREAD_TYPES_HPP
|
@ -9,12 +9,12 @@
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
|
||||
<javac srcdir="./src" debug="true" deprecation="on" source="1.3" target="1.3" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
|
||||
</target>
|
||||
<target name="compileGUI">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac debug="true" destdir="./build/obj">
|
||||
<javac debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj">
|
||||
<src path="src/" />
|
||||
<classpath path="../../../core/java/build/i2p.jar" />
|
||||
<classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />
|
||||
|
@ -27,7 +27,7 @@ public class PeerData {
|
||||
/** date sent (Long) to EventDataPoint containing the datapoints sent in the current period */
|
||||
private Map _dataPoints;
|
||||
/** date sent (Long) to EventDataPoint containing pings that haven't yet timed out or been ponged */
|
||||
private Map _pendingPings;
|
||||
private TreeMap _pendingPings;
|
||||
private long _sessionStart;
|
||||
private long _lifetimeSent;
|
||||
private long _lifetimeReceived;
|
||||
@ -208,14 +208,32 @@ public class PeerData {
|
||||
public void pongReceived(long dateSent, long pongSent) {
|
||||
long now = Clock.getInstance().now();
|
||||
synchronized (_updateLock) {
|
||||
EventDataPoint data = (EventDataPoint) _pendingPings.remove(new Long(dateSent));
|
||||
if (_pendingPings.size() <= 0) {
|
||||
_log.warn("Pong received (sent at " + dateSent + ", " + (now-dateSent)
|
||||
+ "ms ago, pong delay " + (pongSent-dateSent) + "ms, pong receive delay "
|
||||
+ (now-pongSent) + "ms)");
|
||||
return;
|
||||
}
|
||||
Long first = (Long)_pendingPings.firstKey();
|
||||
EventDataPoint data = (EventDataPoint)_pendingPings.remove(new Long(dateSent));
|
||||
|
||||
if (data != null) {
|
||||
data.setPongReceived(now);
|
||||
data.setPongSent(pongSent);
|
||||
data.setWasPonged(true);
|
||||
locked_addDataPoint(data);
|
||||
|
||||
if (dateSent != first.longValue()) {
|
||||
_log.error("Out of order delivery: received " + dateSent
|
||||
+ " but the first pending is " + first.longValue()
|
||||
+ " (delta " + (dateSent - first.longValue()) + ")");
|
||||
} else {
|
||||
_log.info("In order delivery for " + dateSent + " in ping "
|
||||
+ _peer.getComment());
|
||||
}
|
||||
} else {
|
||||
_log.warn("Pong received, but no matching ping? ping sent at = " + dateSent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_sendRate.addData(pongSent - dateSent, 0);
|
||||
|
@ -11,7 +11,7 @@
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true"
|
||||
debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
destdir="./build/obj"
|
||||
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
|
||||
</target>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true"
|
||||
debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
destdir="./build/obj"
|
||||
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
|
||||
</target>
|
||||
|
@ -46,6 +46,7 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
@ -69,6 +70,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
private I2PAppContext _context;
|
||||
private static long __tunnelId = 0;
|
||||
private long _tunnelId;
|
||||
private Properties _clientOptions;
|
||||
|
||||
public static final int PACKET_DELAY = 100;
|
||||
|
||||
@ -104,6 +106,9 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
_tunnelId = ++__tunnelId;
|
||||
_log = _context.logManager().getLog(I2PTunnel.class);
|
||||
_event = new EventDispatcherImpl();
|
||||
_clientOptions = new Properties();
|
||||
_clientOptions.putAll(System.getProperties());
|
||||
|
||||
addConnectionEventListener(lsnr);
|
||||
boolean gui = true;
|
||||
boolean checkRunByE = true;
|
||||
@ -167,6 +172,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
public Properties getClientOptions() { return _clientOptions; }
|
||||
|
||||
private void addtask(I2PTunnelTask tsk) {
|
||||
tsk.setTunnel(this);
|
||||
if (tsk.isOpen()) {
|
||||
@ -197,6 +204,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
|
||||
if ("help".equals(cmdname)) {
|
||||
runHelp(l);
|
||||
} else if ("clientoptions".equals(cmdname)) {
|
||||
runClientOptions(args, l);
|
||||
} else if ("server".equals(cmdname)) {
|
||||
runServer(args, l);
|
||||
} else if ("textserver".equals(cmdname)) {
|
||||
@ -262,6 +271,29 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
l.log("list");
|
||||
l.log("run <commandfile>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the extra I2CP options to use in any subsequent I2CP sessions.
|
||||
* Usage: "clientoptions[ key=value]*" .
|
||||
*
|
||||
* Sets the event "clientoptions_onResult" = "ok" after completion.
|
||||
*
|
||||
* @param args each args[i] is a key=value pair to add to the options
|
||||
* @param l logger to receive events and output
|
||||
*/
|
||||
public void runClientOptions(String args[], Logging l) {
|
||||
_clientOptions.clear();
|
||||
if (args != null) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
int index = args[i].indexOf('=');
|
||||
if (index <= 0) continue;
|
||||
String key = args[i].substring(0, index);
|
||||
String val = args[i].substring(index+1);
|
||||
_clientOptions.setProperty(key, val);
|
||||
}
|
||||
}
|
||||
notifyEvent("clientoptions_onResult", "ok");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the server pointing at the host and port specified using the private i2p
|
||||
@ -304,7 +336,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
notifyEvent("serverTaskId", new Integer(-1));
|
||||
return;
|
||||
}
|
||||
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this);
|
||||
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, privKeyFile, args[2], l, (EventDispatcher) this, this);
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
@ -350,7 +382,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
return;
|
||||
}
|
||||
|
||||
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this);
|
||||
I2PTunnelServer serv = new I2PTunnelServer(serverHost, portNum, args[2], l, (EventDispatcher) this, this);
|
||||
serv.setReadTimeout(readTimeout);
|
||||
serv.startRunning();
|
||||
addtask(serv);
|
||||
@ -386,7 +418,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
return;
|
||||
}
|
||||
I2PTunnelTask task;
|
||||
task = new I2PTunnelClient(port, args[1], l, ownDest, (EventDispatcher) this);
|
||||
task = new I2PTunnelClient(port, args[1], l, ownDest, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("clientTaskId", new Integer(task.getId()));
|
||||
} else {
|
||||
@ -423,7 +455,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
proxy = args[1];
|
||||
}
|
||||
I2PTunnelTask task;
|
||||
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this);
|
||||
task = new I2PTunnelHTTPClient(port, l, ownDest, proxy, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("httpclientTaskId", new Integer(task.getId()));
|
||||
} else {
|
||||
@ -460,7 +492,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
}
|
||||
|
||||
I2PTunnelTask task;
|
||||
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this);
|
||||
task = new I2PSOCKSTunnel(port, l, ownDest, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("sockstunnelTaskId", new Integer(task.getId()));
|
||||
} else {
|
||||
@ -779,7 +811,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
if (allargs.length() != 0) {
|
||||
I2PTunnelTask task;
|
||||
// pings always use the main destination
|
||||
task = new I2Ping(allargs, l, false, (EventDispatcher) this);
|
||||
task = new I2Ping(allargs, l, false, (EventDispatcher) this, this);
|
||||
addtask(task);
|
||||
notifyEvent("pingTaskId", new Integer(task.getId()));
|
||||
} else {
|
||||
|
@ -19,8 +19,8 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
|
||||
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1
|
||||
protected long readTimeout = DEFAULT_READ_TIMEOUT;
|
||||
|
||||
public I2PTunnelClient(int localPort, String destination, Logging l, boolean ownDest, EventDispatcher notifyThis) {
|
||||
super(localPort, ownDest, l, notifyThis, "SynSender");
|
||||
public I2PTunnelClient(int localPort, String destination, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(localPort, ownDest, l, notifyThis, "SynSender", tunnel);
|
||||
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
notifyEvent("openClientResult", "error");
|
||||
|
@ -60,8 +60,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
// I2PTunnelClientBase(localPort, ownDest, l, (EventDispatcher)null);
|
||||
//}
|
||||
|
||||
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName) {
|
||||
super(localPort + " (uninitialized)", notifyThis);
|
||||
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l, EventDispatcher notifyThis, String handlerName, I2PTunnel tunnel) {
|
||||
super(localPort + " (uninitialized)", notifyThis, tunnel);
|
||||
_clientId = ++__clientId;
|
||||
this.localPort = localPort;
|
||||
this.l = l;
|
||||
@ -103,16 +103,25 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
||||
|
||||
private static I2PSocketManager socketManager;
|
||||
|
||||
protected static synchronized I2PSocketManager getSocketManager() {
|
||||
protected synchronized I2PSocketManager getSocketManager() {
|
||||
return getSocketManager(getTunnel());
|
||||
}
|
||||
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
|
||||
if (socketManager == null) {
|
||||
socketManager = buildSocketManager();
|
||||
socketManager = buildSocketManager(tunnel);
|
||||
}
|
||||
return socketManager;
|
||||
}
|
||||
|
||||
protected static I2PSocketManager buildSocketManager() {
|
||||
protected I2PSocketManager buildSocketManager() {
|
||||
return buildSocketManager(getTunnel());
|
||||
}
|
||||
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel) {
|
||||
Properties props = new Properties();
|
||||
props.putAll(System.getProperties());
|
||||
if (tunnel == null)
|
||||
props.putAll(System.getProperties());
|
||||
else
|
||||
props.putAll(tunnel.getClientOptions());
|
||||
I2PSocketManager sockManager = I2PSocketManagerFactory.createManager(I2PTunnel.host, Integer.parseInt(I2PTunnel.port), props);
|
||||
sockManager.setName("Client");
|
||||
return sockManager;
|
||||
|
@ -59,7 +59,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
"Cache-control: no-cache\r\n"+
|
||||
"\r\n"+
|
||||
"<html><body><H1>I2P ERROR: DESTINATION NOT FOUND</H1>"+
|
||||
"That I2P Desitination was not found. Perhaps you pasted in the "+
|
||||
"That I2P Destination 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>. "+
|
||||
@ -71,7 +71,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
"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>"+
|
||||
"That Desitination was reachable, but timed out getting a "+
|
||||
"That Destination was reachable, but timed out getting a "+
|
||||
"response. This is likely a temporary error, so you should simply "+
|
||||
"try to refresh, though if the problem persists, the remote "+
|
||||
"destination may have issues. Could not get a response from "+
|
||||
@ -81,8 +81,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
/** used to assign unique IDs to the threads / clients. no logic or functionality */
|
||||
private static volatile long __clientId = 0;
|
||||
|
||||
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest, String wwwProxy, EventDispatcher notifyThis) {
|
||||
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId));
|
||||
public I2PTunnelHTTPClient(int localPort, Logging l, boolean ownDest, String wwwProxy, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(localPort, ownDest, l, notifyThis, "HTTPHandler " + (++__clientId), tunnel);
|
||||
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
notifyEvent("openHTTPClientResult", "error");
|
||||
@ -127,7 +127,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
if (pos == -1) break;
|
||||
method = line.substring(0, pos);
|
||||
String request = line.substring(pos + 1);
|
||||
if (request.startsWith("/") && System.getProperty("i2ptunnel.noproxy") != null) {
|
||||
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
|
||||
request = "http://i2p" + request;
|
||||
}
|
||||
pos = request.indexOf("//");
|
||||
|
@ -45,15 +45,15 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
/** default timeout to 3 minutes - override if desired */
|
||||
private long readTimeout = DEFAULT_READ_TIMEOUT;
|
||||
|
||||
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis) {
|
||||
super(host + ":" + port + " <- " + privData, notifyThis);
|
||||
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host + ":" + port + " <- " + privData, notifyThis, tunnel);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
|
||||
init(host, port, bais, privData, l);
|
||||
}
|
||||
|
||||
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
|
||||
EventDispatcher notifyThis) {
|
||||
super(host + ":" + port + " <- " + privkeyname, notifyThis);
|
||||
EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
|
||||
try {
|
||||
init(host, port, new FileInputStream(privkey), privkeyname, l);
|
||||
} catch (IOException ioe) {
|
||||
@ -62,8 +62,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis) {
|
||||
super(host + ":" + port + " <- " + privkeyname, notifyThis);
|
||||
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(host + ":" + port + " <- " + privkeyname, notifyThis, tunnel);
|
||||
init(host, port, privData, privkeyname, l);
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
this.remotePort = port;
|
||||
I2PClient client = I2PClientFactory.createClient();
|
||||
Properties props = new Properties();
|
||||
props.putAll(System.getProperties());
|
||||
props.putAll(getTunnel().getClientOptions());
|
||||
synchronized (slock) {
|
||||
sockMgr = I2PSocketManagerFactory.createManager(privData, I2PTunnel.host, Integer.parseInt(I2PTunnel.port),
|
||||
props);
|
||||
|
@ -26,16 +26,19 @@ public abstract class I2PTunnelTask implements EventDispatcher {
|
||||
// I2PTunnelTask(name, (EventDispatcher)null);
|
||||
//}
|
||||
|
||||
protected I2PTunnelTask(String name, EventDispatcher notifyThis) {
|
||||
protected I2PTunnelTask(String name, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
attachEventDispatcher(notifyThis);
|
||||
this.name = name;
|
||||
this.id = -1;
|
||||
this.tunnel = tunnel;
|
||||
}
|
||||
|
||||
/** for apps that use multiple I2PTunnel instances */
|
||||
public void setTunnel(I2PTunnel pTunnel) {
|
||||
tunnel = pTunnel;
|
||||
}
|
||||
|
||||
public I2PTunnel getTunnel() { return tunnel; }
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
|
@ -47,15 +47,15 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
|
||||
// I2Ping(cmd, l, (EventDispatcher)null);
|
||||
//}
|
||||
|
||||
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis) {
|
||||
super("I2Ping [" + cmd + "]", notifyThis);
|
||||
public I2Ping(String cmd, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super("I2Ping [" + cmd + "]", notifyThis, tunnel);
|
||||
this.l = l;
|
||||
command = cmd;
|
||||
synchronized (slock) {
|
||||
if (ownDest) {
|
||||
sockMgr = I2PTunnelClient.buildSocketManager();
|
||||
sockMgr = I2PTunnelClient.buildSocketManager(tunnel);
|
||||
} else {
|
||||
sockMgr = I2PTunnelClient.getSocketManager();
|
||||
sockMgr = I2PTunnelClient.getSocketManager(tunnel);
|
||||
}
|
||||
}
|
||||
Thread t = new I2PThread(this);
|
||||
|
@ -10,6 +10,7 @@ import java.net.Socket;
|
||||
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.i2ptunnel.I2PTunnel;
|
||||
import net.i2p.i2ptunnel.I2PTunnelClientBase;
|
||||
import net.i2p.i2ptunnel.I2PTunnelRunner;
|
||||
import net.i2p.i2ptunnel.Logging;
|
||||
@ -26,8 +27,8 @@ public class I2PSOCKSTunnel extends I2PTunnelClientBase {
|
||||
// I2PSOCKSTunnel(localPort, l, ownDest, (EventDispatcher)null);
|
||||
//}
|
||||
|
||||
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis) {
|
||||
super(localPort, ownDest, l, notifyThis, "SOCKSHandler");
|
||||
public I2PSOCKSTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
|
||||
super(localPort, ownDest, l, notifyThis, "SOCKSHandler", tunnel);
|
||||
|
||||
if (waitEventValue("openBaseClientResult").equals("error")) {
|
||||
notifyEvent("openSOCKSTunnelResult", "error");
|
||||
|
@ -8,7 +8,7 @@
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac srcdir="./src" debug="true" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" />
|
||||
<javac srcdir="./src" debug="true" deprecation="on" source="1.3" target="1.3" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" />
|
||||
</target>
|
||||
<target name="jar" depends="compile">
|
||||
<jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" />
|
||||
|
@ -454,7 +454,8 @@ class I2PSocketImpl implements I2PSocket {
|
||||
_log.debug(getPrefix() + "Message size is: " + data.length);
|
||||
boolean sent = sendBlock(data);
|
||||
if (!sent) {
|
||||
_log.error(getPrefix() + "Error sending message to peer. Killing socket runner");
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getPrefix() + "Error sending message to peer. Killing socket runner");
|
||||
errorOccurred();
|
||||
return false;
|
||||
}
|
||||
@ -475,9 +476,10 @@ class I2PSocketImpl implements I2PSocket {
|
||||
packetsHandled++;
|
||||
}
|
||||
if ((bc.getCurrentSize() > 0) && (packetsHandled > 1)) {
|
||||
_log.error(getPrefix() + "A SCARY MONSTER HAS EATEN SOME DATA! " + "(input stream: "
|
||||
+ in.hashCode() + "; "
|
||||
+ "queue size: " + bc.getCurrentSize() + ")");
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getPrefix() + "We lost some data queued up due to a network send error (input stream: "
|
||||
+ in.hashCode() + "; "
|
||||
+ "queue size: " + bc.getCurrentSize() + ")");
|
||||
}
|
||||
synchronized (flagLock) {
|
||||
closed2 = true;
|
||||
@ -492,7 +494,8 @@ class I2PSocketImpl implements I2PSocket {
|
||||
byte[] packet = I2PSocketManager.makePacket(getMask(0x02), remoteID, new byte[0]);
|
||||
boolean sent = manager.getSession().sendMessage(remote, packet);
|
||||
if (!sent) {
|
||||
_log.error(getPrefix() + "Error sending close packet to peer");
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getPrefix() + "Error sending close packet to peer");
|
||||
errorOccurred();
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +264,8 @@ public class I2PSocketManager implements I2PSessionListener {
|
||||
s.queueData(payload);
|
||||
return;
|
||||
} else {
|
||||
_log.error(getName() + ": Null socket with data available");
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getName() + ": Null socket with data available");
|
||||
throw new IllegalStateException("Null socket with data available");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
<html><body>
|
||||
<p>Implements a TCP-like (reliable, authenticated, in order) set of sockets for
|
||||
communicating over the IP-like (unreliable, unauthenticated, unordered) I2P
|
||||
messages.</p>
|
||||
|
||||
<p>When an application wants to use streams, it must fetch an {@link
|
||||
net.i2p.client.streaming.I2PSocketManager} from the {@link
|
||||
net.i2p.client.streaming.I2PSocketManagerFactory}, which in turn builds its own
|
||||
{@link net.i2p.client.I2PSession} internally. All communication over that
|
||||
{@link net.i2p.client.I2PSession} is handled by the {@link
|
||||
net.i2p.client.streaming.I2PSocketManager}, as it imposes its own formatting on
|
||||
the raw messages sent and received. If an application wants to receive streams
|
||||
from other clients on the network, it should access the blocking {@link
|
||||
net.i2p.client.streaming.I2PServerSocket#accept} method, which will provide an
|
||||
{@link net.i2p.client.streaming.I2PSocket} when a new one is available. If an
|
||||
application wants to create a new stream to a peer, it should do so with the
|
||||
appropriate {@link net.i2p.client.streaming.I2PSocketManager#connect} call.</p>
|
||||
</body></html>
|
@ -9,13 +9,13 @@
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac srcdir="./src" debug="true" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
|
||||
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
|
||||
</target>
|
||||
|
||||
<target name="compileGUI" depends="builddep">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac debug="true" destdir="./build/obj">
|
||||
<javac debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj">
|
||||
<src path="src/" />
|
||||
<classpath path="../../../core/java/build/i2p.jar" />
|
||||
<classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />
|
||||
|
@ -8,7 +8,7 @@
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac srcdir="./src" debug="true" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
|
||||
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
|
||||
</target>
|
||||
<target name="jar" depends="compile">
|
||||
<war destfile="./build/phttprelay.war" webxml="web.xml">
|
||||
|
57
apps/routerconsole/java/build.xml
Normal file
57
apps/routerconsole/java/build.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project basedir="." default="all" name="routerconsole">
|
||||
<target name="all" depends="clean, build" />
|
||||
<target name="build" depends="builddep, jar" />
|
||||
<target name="builddep" depends="jetty" >
|
||||
<ant dir="../../../router/java/" target="build" />
|
||||
<!-- router will build core -->
|
||||
</target>
|
||||
<target name="jetty">
|
||||
<untar src="jetty-4.2.21-min.tar.bz2" compression="bzip2" dest="." />
|
||||
<ant dir="jetty-4.2.21-min/extra/jdk1.2/" target="all" />
|
||||
</target>
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
destdir="./build/obj"
|
||||
classpath="../../../core/java/build/i2p.jar:../../../router/java/build/router.jar:jetty-4.2.21-min/extra/lib/org.mortbay.jetty-jdk1.2.jar" />
|
||||
</target>
|
||||
<target name="jar" depends="compile">
|
||||
<jar destfile="./build/routerconsole.jar" basedir="./build/obj" includes="**/*.class">
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="i2p.jar router.jar" />
|
||||
</manifest>
|
||||
</jar>
|
||||
<ant target="war" />
|
||||
</target>
|
||||
<target name="war">
|
||||
<war destfile="build/routerconsole.war" webxml="../jsp/web.xml"
|
||||
basedir="../jsp/" excludes="web.xml">
|
||||
</war>
|
||||
</target>
|
||||
<target name="javadoc">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/javadoc" />
|
||||
<javadoc
|
||||
sourcepath="./src:../../../core/java/src:../../router/java/src" destdir="./build/javadoc"
|
||||
packagenames="*"
|
||||
use="true"
|
||||
splitindex="true"
|
||||
windowtitle="Router Console" />
|
||||
</target>
|
||||
<target name="clean">
|
||||
<delete dir="./build" />
|
||||
</target>
|
||||
<target name="cleandep" depends="clean">
|
||||
<!-- router will clean core -->
|
||||
<ant dir="../../../router/java/" target="distclean" />
|
||||
</target>
|
||||
<target name="distclean" depends="clean">
|
||||
<!-- router will clean core -->
|
||||
<ant dir="../../../router/java/" target="distclean" />
|
||||
<delete dir="./jetty-4.2.21-min" />
|
||||
</target>
|
||||
</project>
|
@ -0,0 +1,38 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class ConfigAdvancedHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigAdvancedHelper() {}
|
||||
|
||||
public String getSettings() {
|
||||
StringBuffer buf = new StringBuffer(4*1024);
|
||||
Set names = _context.router().getConfigSettings();
|
||||
TreeSet sortedNames = new TreeSet(names);
|
||||
for (Iterator iter = sortedNames.iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String val = _context.router().getConfigSetting(name);
|
||||
buf.append(name).append('=').append(val).append('\n');
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.ClientTunnelSettings;
|
||||
|
||||
public class ConfigClientsHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** copied from the package private {@link net.i2p.router.tunnelmanager.TunnelPool} */
|
||||
public final static String TARGET_CLIENTS_PARAM = "router.targetClients";
|
||||
/** copied from the package private {@link net.i2p.router.tunnelmanager.TunnelPool} */
|
||||
public final static int TARGET_CLIENTS_DEFAULT = 3;
|
||||
|
||||
public ConfigClientsHelper() {}
|
||||
|
||||
public String getClientCountSelectBox() {
|
||||
int count = TARGET_CLIENTS_DEFAULT;
|
||||
String val = _context.router().getConfigSetting(TARGET_CLIENTS_PARAM);
|
||||
if (val != null) {
|
||||
try {
|
||||
count = Integer.parseInt(val);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore, use default from above
|
||||
}
|
||||
}
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("<select name=\"clientcount\">\n");
|
||||
for (int i = 0; i < 5; i++) {
|
||||
buf.append("<option value=\"").append(i).append("\" ");
|
||||
if (count == i)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">").append(i).append("</option>\n");
|
||||
}
|
||||
if (count >= 5) {
|
||||
buf.append("<option value=\"").append(count);
|
||||
buf.append("\" selected>").append(count);
|
||||
buf.append("</option>\n");
|
||||
}
|
||||
buf.append("</select>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getTunnelCountSelectBox() {
|
||||
int count = ClientTunnelSettings.DEFAULT_NUM_INBOUND;
|
||||
String val = _context.router().getConfigSetting(ClientTunnelSettings.PROP_NUM_INBOUND);
|
||||
if (val != null) {
|
||||
try {
|
||||
count = Integer.parseInt(val);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore, use default from above
|
||||
}
|
||||
}
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("<select name=\"tunnelcount\">\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
buf.append("<option value=\"").append(i).append("\" ");
|
||||
if (count == i)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">").append(i).append("</option>\n");
|
||||
}
|
||||
if (count >= 4) {
|
||||
buf.append("<option value=\"").append(count);
|
||||
buf.append("\" selected>").append(count);
|
||||
buf.append("</option>\n");
|
||||
}
|
||||
buf.append("</select>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String getTunnelDepthSelectBox() {
|
||||
int count = ClientTunnelSettings.DEFAULT_DEPTH_INBOUND;
|
||||
String val = _context.router().getConfigSetting(ClientTunnelSettings.PROP_DEPTH_INBOUND);
|
||||
if (val != null) {
|
||||
try {
|
||||
count = Integer.parseInt(val);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore, use default from above
|
||||
}
|
||||
}
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("<select name=\"tunneldepth\">\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
buf.append("<option value=\"").append(i).append("\" ");
|
||||
if (count == i)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">").append(i).append("</option>\n");
|
||||
}
|
||||
if (count >= 4) {
|
||||
buf.append("<option value=\"").append(count);
|
||||
buf.append("\" selected>").append(count);
|
||||
buf.append("</option>\n");
|
||||
}
|
||||
buf.append("</select>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class ConfigLoggingHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigLoggingHelper() {}
|
||||
|
||||
public String getLogFilePattern() {
|
||||
return _context.logManager().getBaseLogfilename();
|
||||
}
|
||||
public String getRecordPattern() {
|
||||
return new String(_context.logManager().getFormat());
|
||||
}
|
||||
public String getDatePattern() {
|
||||
return _context.logManager().getDateFormatPattern();
|
||||
}
|
||||
public String getMaxFileSize() {
|
||||
int bytes = _context.logManager().getFileSize();
|
||||
if (bytes == 0) return "1m";
|
||||
if (bytes > 1024*1024*1024)
|
||||
return (bytes/(1024*1024*1024)) + "g";
|
||||
else if (bytes > 1024*1024)
|
||||
return (bytes/(1024*1024)) + "m";
|
||||
else
|
||||
return (bytes/(1024)) + "k";
|
||||
}
|
||||
public String getLogLevelTable() {
|
||||
StringBuffer buf = new StringBuffer(32*1024);
|
||||
buf.append("<textarea rows=\"20\" cols=\"80\">");
|
||||
List logs = _context.logManager().getLogs();
|
||||
TreeMap sortedLogs = new TreeMap();
|
||||
for (int i = 0; i < logs.size(); i++) {
|
||||
Log l = (Log)logs.get(i);
|
||||
sortedLogs.put(l.getName(), l);
|
||||
}
|
||||
int i = 0;
|
||||
for (Iterator iter = sortedLogs.values().iterator(); iter.hasNext(); i++) {
|
||||
Log l = (Log)iter.next();
|
||||
buf.append(l.getName()).append('=');
|
||||
buf.append(Log.toLevelString(l.getMinimumPriority()));
|
||||
buf.append("\n");
|
||||
}
|
||||
buf.append("</textarea><br />\n");
|
||||
buf.append("<i>Valid levels are DEBUG, INFO, WARN, ERROR, CRIT</i>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
public String getLogLevelTableDetail() {
|
||||
StringBuffer buf = new StringBuffer(8*1024);
|
||||
buf.append("<table border=\"1\">\n");
|
||||
buf.append("<tr><td>Package/class</td><td>Level</td></tr>\n");
|
||||
List logs = _context.logManager().getLogs();
|
||||
TreeMap sortedLogs = new TreeMap();
|
||||
for (int i = 0; i < logs.size(); i++) {
|
||||
Log l = (Log)logs.get(i);
|
||||
sortedLogs.put(l.getName(), l);
|
||||
}
|
||||
int i = 0;
|
||||
for (Iterator iter = sortedLogs.values().iterator(); iter.hasNext(); i++) {
|
||||
Log l = (Log)iter.next();
|
||||
buf.append("<tr>\n <td><input size=\"50\" type=\"text\" name=\"logrecord.");
|
||||
buf.append(i).append(".package\" value=\"").append(l.getName());
|
||||
buf.append("\" /></td>\n");
|
||||
buf.append("<td><select name=\"logrecord.").append(i);
|
||||
buf.append(".level\">\n\t");
|
||||
buf.append("<option value=\"DEBUG\" ");
|
||||
if (l.getMinimumPriority() == Log.DEBUG)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">Debug</option>\n\t");
|
||||
buf.append("<option value=\"INFO\" ");
|
||||
if (l.getMinimumPriority() == Log.INFO)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">Info</option>\n\t");
|
||||
buf.append("<option value=\"WARN\" ");
|
||||
if (l.getMinimumPriority() == Log.WARN)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">Warn</option>\n\t");
|
||||
buf.append("<option value=\"ERROR\" ");
|
||||
if (l.getMinimumPriority() == Log.ERROR)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">Error</option>\n\t");
|
||||
buf.append("<option value=\"CRIT\" ");
|
||||
if (l.getMinimumPriority() == Log.CRIT)
|
||||
buf.append("selected=\"true\" ");
|
||||
buf.append(">Critical</option>\n\t");
|
||||
buf.append("</select></td>\n</tr>\n");
|
||||
}
|
||||
buf.append("</table>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.ClientTunnelSettings;
|
||||
|
||||
public class ConfigNetHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigNetHelper() {}
|
||||
|
||||
/** copied from various private TCP components */
|
||||
private final static String PROP_I2NP_TCP_HOSTNAME = "i2np.tcp.hostname";
|
||||
private final static String PROP_I2NP_TCP_PORT = "i2np.tcp.port";
|
||||
|
||||
public String getHostname() {
|
||||
return _context.getProperty(PROP_I2NP_TCP_HOSTNAME);
|
||||
}
|
||||
public String getPort() {
|
||||
int port = 8887;
|
||||
String val = _context.getProperty(PROP_I2NP_TCP_PORT);
|
||||
if (val != null) {
|
||||
try {
|
||||
port = Integer.parseInt(val);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore, use default from above
|
||||
}
|
||||
}
|
||||
return "" + port;
|
||||
}
|
||||
|
||||
public String getEnableTimeSyncChecked() {
|
||||
String enabled = System.getProperty("timestamper.enabled");
|
||||
if ( (enabled == null) || (!"true".equals(enabled)) )
|
||||
return "";
|
||||
else
|
||||
return " checked ";
|
||||
}
|
||||
|
||||
public static final String PROP_INBOUND_KBPS = "i2np.bandwidth.inboundKBytesPerSecond";
|
||||
public static final String PROP_OUTBOUND_KBPS = "i2np.bandwidth.outboundKBytesPerSecond";
|
||||
public static final String PROP_INBOUND_BURST = "i2np.bandwidth.inboundBurstKBytes";
|
||||
public static final String PROP_OUTBOUND_BURST = "i2np.bandwidth.outboundBurstKBytes";
|
||||
|
||||
public String getInboundRate() {
|
||||
String rate = _context.getProperty(PROP_INBOUND_KBPS);
|
||||
if (rate != null)
|
||||
return rate;
|
||||
else
|
||||
return "-1";
|
||||
}
|
||||
public String getOutboundRate() {
|
||||
String rate = _context.getProperty(PROP_OUTBOUND_KBPS);
|
||||
if (rate != null)
|
||||
return rate;
|
||||
else
|
||||
return "Unlimited";
|
||||
}
|
||||
public String getInboundBurstFactorBox() {
|
||||
String rate = _context.getProperty(PROP_INBOUND_KBPS);
|
||||
String burst = _context.getProperty(PROP_INBOUND_BURST);
|
||||
int numSeconds = 1;
|
||||
if ( (burst != null) && (rate != null) ) {
|
||||
int rateKBps = 0;
|
||||
int burstKB = 0;
|
||||
try {
|
||||
rateKBps = Integer.parseInt(rate);
|
||||
burstKB = Integer.parseInt(burst);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore
|
||||
}
|
||||
if ( (rateKBps > 0) && (burstKB > 0) ) {
|
||||
numSeconds = burstKB / rateKBps;
|
||||
}
|
||||
}
|
||||
return getBurstFactor(numSeconds, "inboundburstfactor");
|
||||
}
|
||||
|
||||
public String getOutboundBurstFactorBox() {
|
||||
String rate = _context.getProperty(PROP_OUTBOUND_KBPS);
|
||||
String burst = _context.getProperty(PROP_OUTBOUND_BURST);
|
||||
int numSeconds = 1;
|
||||
if ( (burst != null) && (rate != null) ) {
|
||||
int rateKBps = 0;
|
||||
int burstKB = 0;
|
||||
try {
|
||||
rateKBps = Integer.parseInt(rate);
|
||||
burstKB = Integer.parseInt(burst);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// ignore
|
||||
}
|
||||
if ( (rateKBps > 0) && (burstKB > 0) ) {
|
||||
numSeconds = burstKB / rateKBps;
|
||||
}
|
||||
}
|
||||
return getBurstFactor(numSeconds, "outboundburstfactor");
|
||||
}
|
||||
|
||||
private static String getBurstFactor(int numSeconds, String name) {
|
||||
StringBuffer buf = new StringBuffer(256);
|
||||
buf.append("<select name=\"").append(name).append("\">\n");
|
||||
for (int i = 1; i < 10; i++) {
|
||||
buf.append("<option value=\"").append(i).append("\" ");
|
||||
if ( (i == numSeconds) || (i == 10) )
|
||||
buf.append("selected ");
|
||||
buf.append(">");
|
||||
if (i == 1)
|
||||
buf.append("1 second (no burst)</option>\n");
|
||||
else
|
||||
buf.append(i).append(" seconds</option>\n");
|
||||
}
|
||||
buf.append("</select>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.util.List;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
class ContextHelper {
|
||||
public static RouterContext getContext(String contextId) {
|
||||
List contexts = RouterContext.listContexts();
|
||||
if ( (contexts == null) || (contexts.size() <= 0) )
|
||||
throw new IllegalStateException("No contexts? wtf");
|
||||
if ( (contextId == null) || (contextId.trim().length() <= 0) )
|
||||
return (RouterContext)contexts.get(0);
|
||||
for (int i = 0; i < contexts.size(); i++) {
|
||||
RouterContext context = (RouterContext)contexts.get(i);
|
||||
Hash hash = context.routerHash();
|
||||
if (hash == null) continue;
|
||||
if (hash.toBase64().startsWith(contextId))
|
||||
return context;
|
||||
}
|
||||
// not found, so just give them the first we can find
|
||||
return (RouterContext)contexts.get(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class LogsHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public LogsHelper() {}
|
||||
|
||||
public String getLogs() {
|
||||
List msgs = _context.logManager().getBuffer().getMostRecentMessages();
|
||||
StringBuffer buf = new StringBuffer(16*1024);
|
||||
buf.append("<h2>Most recent console messages:</h2><ul>");
|
||||
buf.append("<code>\n");
|
||||
for (int i = 0; i < msgs.size(); i++) {
|
||||
String msg = (String)msgs.get(i);
|
||||
buf.append("<li>");
|
||||
buf.append(msg);
|
||||
buf.append("</li>\n");
|
||||
}
|
||||
buf.append("</code></ul>\n");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class NavHelper {
|
||||
private static Map _apps = new HashMap();
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public NavHelper() {}
|
||||
|
||||
/**
|
||||
* To register a new client application so that it shows up on the router
|
||||
* console's nav bar, it should be registered with this singleton.
|
||||
*
|
||||
* @param name pretty name the app will be called in the link
|
||||
* @param path full path pointing to the application's root
|
||||
* (e.g. /i2ptunnel/index.jsp)
|
||||
*/
|
||||
public static void registerApp(String name, String path) {
|
||||
_apps.put(name, path);
|
||||
}
|
||||
public static void unregisterApp(String name) {
|
||||
_apps.remove(name);
|
||||
}
|
||||
|
||||
public String getClientAppLinks() {
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
for (Iterator iter = _apps.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String path = (String)_apps.get(name);
|
||||
buf.append("<a href=\"").append(path).append("\">");
|
||||
buf.append(name).append("</a> |");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class NetDbHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public NetDbHelper() {}
|
||||
|
||||
public String getNetDbSummary() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
||||
try {
|
||||
_context.netDb().renderStatusHTML(baos);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return new String(baos.toByteArray());
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
|
||||
public class ProfilesHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ProfilesHelper() {}
|
||||
|
||||
public String getProfileSummary() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(16*1024);
|
||||
try {
|
||||
_context.profileOrganizer().renderStatusHTML(baos);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return new String(baos.toByteArray());
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.util.MultiException;
|
||||
|
||||
public class RouterConsoleRunner {
|
||||
private Server _server;
|
||||
private String _listenPort = "7657";
|
||||
private String _listenHost = "0.0.0.0";
|
||||
private String _webAppsDir = "./webapps/";
|
||||
|
||||
public RouterConsoleRunner(String args[]) {
|
||||
if (args.length == 3) {
|
||||
_listenPort = args[0].trim();
|
||||
_listenHost = args[1].trim();
|
||||
_webAppsDir = args[2].trim();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
RouterConsoleRunner runner = new RouterConsoleRunner(args);
|
||||
runner.startConsole();
|
||||
}
|
||||
|
||||
public void startConsole() {
|
||||
_server = new Server();
|
||||
try {
|
||||
_server.addListener(_listenHost + ':' + _listenPort);
|
||||
_server.setRootWebApp("routerconsole");
|
||||
_server.addWebApplications(_webAppsDir);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
try {
|
||||
_server.start();
|
||||
} catch (MultiException me) {
|
||||
me.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopConsole() {
|
||||
try {
|
||||
_server.stop();
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,377 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.router.Router;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.RouterVersion;
|
||||
|
||||
/**
|
||||
* Simple helper to query the appropriate router for data necessary to render
|
||||
* the summary sections on the router console.
|
||||
*/
|
||||
public class SummaryHelper {
|
||||
private RouterContext _context;
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the shortened 4 character ident for the router located within
|
||||
* the current JVM at the given context.
|
||||
*
|
||||
*/
|
||||
public String getIdent() {
|
||||
if (_context == null) return "[no router]";
|
||||
|
||||
if (_context.routerHash() != null)
|
||||
return _context.routerHash().toBase64().substring(0, 4);
|
||||
else
|
||||
return "[unknown]";
|
||||
}
|
||||
/**
|
||||
* Retrieve the version number of the router.
|
||||
*
|
||||
*/
|
||||
public String getVersion() {
|
||||
return RouterVersion.VERSION;
|
||||
}
|
||||
/**
|
||||
* Retrieve a pretty printed uptime count (ala 4d or 7h or 39m)
|
||||
*
|
||||
*/
|
||||
public String getUptime() {
|
||||
if (_context == null) return "[no router]";
|
||||
|
||||
Router router = _context.router();
|
||||
if (router == null)
|
||||
return "[not up]";
|
||||
else
|
||||
return DataHelper.formatDuration(router.getUptime());
|
||||
}
|
||||
|
||||
/**
|
||||
* How many active peers the router has.
|
||||
*
|
||||
*/
|
||||
public int getActivePeers() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.profileOrganizer().countActivePeers();
|
||||
}
|
||||
/**
|
||||
* How many active peers the router ranks as fast.
|
||||
*
|
||||
*/
|
||||
public int getFastPeers() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.profileOrganizer().countFastPeers();
|
||||
}
|
||||
/**
|
||||
* How many active peers the router ranks as having a high capacity.
|
||||
*
|
||||
*/
|
||||
public int getHighCapacityPeers() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.profileOrganizer().countHighCapacityPeers();
|
||||
}
|
||||
/**
|
||||
* How many active peers the router ranks as well integrated.
|
||||
*
|
||||
*/
|
||||
public int getWellIntegratedPeers() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.profileOrganizer().countWellIntegratedPeers();
|
||||
}
|
||||
/**
|
||||
* How many peers the router ranks as failing.
|
||||
*
|
||||
*/
|
||||
public int getFailingPeers() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.profileOrganizer().countFailingPeers();
|
||||
}
|
||||
/**
|
||||
* How many peers totally suck.
|
||||
*
|
||||
*/
|
||||
public int getShitlistedPeers() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.shitlist().getRouterCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* How fast we have been receiving data over the last minute (pretty printed
|
||||
* string with 2 decimal places representing the KBps)
|
||||
*
|
||||
*/
|
||||
public String getInboundMinuteKBps() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
RateStat receiveRate = _context.statManager().getRate("transport.receiveMessageSize");
|
||||
Rate rate = receiveRate.getRate(60*1000);
|
||||
double bytes = rate.getLastTotalValue();
|
||||
double bps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
return fmt.format(bps);
|
||||
}
|
||||
/**
|
||||
* How fast we have been sending data over the last minute (pretty printed
|
||||
* string with 2 decimal places representing the KBps)
|
||||
*
|
||||
*/
|
||||
public String getOutboundMinuteKBps() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
RateStat receiveRate = _context.statManager().getRate("transport.sendMessageSize");
|
||||
Rate rate = receiveRate.getRate(60*1000);
|
||||
double bytes = rate.getLastTotalValue();
|
||||
double bps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
return fmt.format(bps);
|
||||
}
|
||||
|
||||
/**
|
||||
* How fast we have been receiving data over the last 5 minutes (pretty printed
|
||||
* string with 2 decimal places representing the KBps)
|
||||
*
|
||||
*/
|
||||
public String getInboundFiveMinuteKBps() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
RateStat receiveRate = _context.statManager().getRate("transport.receiveMessageSize");
|
||||
Rate rate = receiveRate.getRate(5*60*1000);
|
||||
double bytes = rate.getLastTotalValue();
|
||||
double bps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
return fmt.format(bps);
|
||||
}
|
||||
|
||||
/**
|
||||
* How fast we have been sending data over the last 5 minutes (pretty printed
|
||||
* string with 2 decimal places representing the KBps)
|
||||
*
|
||||
*/
|
||||
public String getOutboundFiveMinuteKBps() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
RateStat receiveRate = _context.statManager().getRate("transport.sendMessageSize");
|
||||
Rate rate = receiveRate.getRate(5*60*1000);
|
||||
double bytes = rate.getLastTotalValue();
|
||||
double bps = (bytes*1000.0d)/(rate.getPeriod()*1024.0d);
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
return fmt.format(bps);
|
||||
}
|
||||
|
||||
/**
|
||||
* How fast we have been receiving data since the router started (pretty printed
|
||||
* string with 2 decimal places representing the KBps)
|
||||
*
|
||||
*/
|
||||
public String getInboundLifetimeKBps() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
long received = _context.bandwidthLimiter().getTotalAllocatedInboundBytes();
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
|
||||
// we use the unadjusted time, since thats what getWhenStarted is based off
|
||||
long lifetime = _context.clock().now()-_context.clock().getOffset()
|
||||
- _context.router().getWhenStarted();
|
||||
lifetime /= 1000;
|
||||
if (received > 0) {
|
||||
double receivedKBps = received / (lifetime*1024.0);
|
||||
return fmt.format(receivedKBps);
|
||||
} else {
|
||||
return "0.0";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How fast we have been sending data since the router started (pretty printed
|
||||
* string with 2 decimal places representing the KBps)
|
||||
*
|
||||
*/
|
||||
public String getOutboundLifetimeKBps() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
long sent = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
|
||||
// we use the unadjusted time, since thats what getWhenStarted is based off
|
||||
long lifetime = _context.clock().now()-_context.clock().getOffset()
|
||||
- _context.router().getWhenStarted();
|
||||
lifetime /= 1000;
|
||||
if (sent > 0) {
|
||||
double sendKBps = sent / (lifetime*1024.0);
|
||||
return fmt.format(sendKBps);
|
||||
} else {
|
||||
return "0.0";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How much data have we received since the router started (pretty printed
|
||||
* string with 2 decimal places and the appropriate units - GB/MB/KB/bytes)
|
||||
*
|
||||
*/
|
||||
public String getInboundTransferred() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
long received = _context.bandwidthLimiter().getTotalAllocatedInboundBytes();
|
||||
|
||||
return getTransferred(received);
|
||||
}
|
||||
|
||||
/**
|
||||
* How much data have we sent since the router started (pretty printed
|
||||
* string with 2 decimal places and the appropriate units - GB/MB/KB/bytes)
|
||||
*
|
||||
*/
|
||||
public String getOutboundTransferred() {
|
||||
if (_context == null)
|
||||
return "0.0";
|
||||
|
||||
long sent = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
|
||||
return getTransferred(sent);
|
||||
}
|
||||
|
||||
private static String getTransferred(long bytes) {
|
||||
int scale = 0;
|
||||
if (bytes > 1024*1024*1024) {
|
||||
// gigs transferred
|
||||
scale = 3;
|
||||
bytes /= (1024*1024*1024);
|
||||
} else if (bytes > 1024*1024) {
|
||||
// megs transferred
|
||||
scale = 2;
|
||||
bytes /= (1024*1024);
|
||||
} else if (bytes > 1024) {
|
||||
// kbytes transferred
|
||||
scale = 1;
|
||||
bytes /= 1024;
|
||||
} else {
|
||||
scale = 0;
|
||||
}
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("##0.00");
|
||||
|
||||
String str = fmt.format(bytes);
|
||||
switch (scale) {
|
||||
case 1: return str + "KB";
|
||||
case 2: return str + "MB";
|
||||
case 3: return str + "GB";
|
||||
default: return bytes + "bytes";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* How many free inbound tunnels we have.
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public int getInboundTunnels() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.tunnelManager().getFreeTunnelCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* How many active outbound tunnels we have.
|
||||
*
|
||||
*/
|
||||
public int getOutboundTunnels() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.tunnelManager().getOutboundTunnelCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* How many tunnels we are participating in.
|
||||
*
|
||||
*/
|
||||
public int getParticipatingTunnels() {
|
||||
if (_context == null)
|
||||
return 0;
|
||||
else
|
||||
return _context.tunnelManager().getParticipatingCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* How lagged our job queue is over the last minute (pretty printed with
|
||||
* the units attached)
|
||||
*
|
||||
*/
|
||||
public String getJobLag() {
|
||||
if (_context == null)
|
||||
return "0ms";
|
||||
|
||||
Rate lagRate = _context.statManager().getRate("jobQueue.jobLag").getRate(60*1000);
|
||||
return ((int)lagRate.getAverageValue()) + "ms";
|
||||
}
|
||||
|
||||
/**
|
||||
* How long it takes us to pump out a message, averaged over the last minute
|
||||
* (pretty printed with the units attached)
|
||||
*
|
||||
*/
|
||||
public String getMessageDelay() {
|
||||
if (_context == null)
|
||||
return "0ms";
|
||||
|
||||
Rate delayRate = _context.statManager().getRate("transport.sendProcessingTime").getRate(60*1000);
|
||||
return ((int)delayRate.getAverageValue()) + "ms";
|
||||
}
|
||||
|
||||
/**
|
||||
* How long it takes us to test our tunnels, averaged over the last 10 minutes
|
||||
* (pretty printed with the units attached)
|
||||
*
|
||||
*/
|
||||
public String getTunnelLag() {
|
||||
if (_context == null)
|
||||
return "0ms";
|
||||
|
||||
Rate lagRate = _context.statManager().getRate("tunnel.testSuccessTime").getRate(10*60*1000);
|
||||
return ((int)lagRate.getAverageValue()) + "ms";
|
||||
}
|
||||
}
|
53
apps/routerconsole/jsp/config.jsp
Normal file
53
apps/routerconsole/jsp/config.jsp
Normal file
@ -0,0 +1,53 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - logs</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<jsp:useBean class="net.i2p.router.web.ConfigNetHelper" id="nethelper" scope="request" />
|
||||
<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
|
||||
<div class="main" id="main">
|
||||
<%@include file="confignav.jsp" %>
|
||||
<form action="config.jsp" method="POST">
|
||||
<b>External hostname/IP address:</b>
|
||||
<input name="hostname" type="text" size="32" value="<jsp:getProperty name="nethelper" property="hostname" />" />
|
||||
<input type="submit" name="guesshost" value="Guess" /><br />
|
||||
<b>Externally reachable TCP port:</b>
|
||||
<input name="port" type="text" size="4" value="<jsp:getProperty name="nethelper" property="port" />" /> <br />
|
||||
<i>The hostname/IP address and TCP port must be reachable from the outside world. If
|
||||
you are behind a firewall or NAT, this means you must poke a hole for this port. If
|
||||
you are using DHCP and do not have a static IP address, you must use a service like
|
||||
<a href="http://dyndns.org/">dyndns</a>. The "guess" functionality makes an HTTP request
|
||||
to <a href="http://www.whatismyip.com/">www.whatismyip.com</a>.</i>
|
||||
<hr />
|
||||
<b>Enable internal time synchronization?</b> <input type="checkbox" <jsp:getProperty name="nethelper" property="enableTimeSyncChecked" /> name="enabletimesync" /><br />
|
||||
<i>If disabled, your machine <b>must</b> be NTP synchronized</i>
|
||||
<hr />
|
||||
<b>Bandwidth limiter</b><br />
|
||||
<b>Inbound rate</b>:
|
||||
<input name="inboundrate" type="text" size="2" value="<jsp:getProperty name="nethelper" property="inboundRate" />" /> KBytes per second<br />
|
||||
<b>Inbound burst duration:</b>
|
||||
<jsp:getProperty name="nethelper" property="inboundBurstFactorBox" /><br />
|
||||
<b>Outbound rate:</b>
|
||||
<input name="outboundrate" type="text" size="2" value="<jsp:getProperty name="nethelper" property="outboundRate" />" /> KBytes per second<br />
|
||||
<b>Outbound burst duration:</b>
|
||||
<jsp:getProperty name="nethelper" property="outboundBurstFactorBox" /><br />
|
||||
<i>A negative rate means there is no limit</i><br />
|
||||
<hr />
|
||||
<b>Reseed</b> (from <input name="reseedfrom" type="text" size="40" value="http://dev.i2p.net/i2pdb/" />):
|
||||
<input type="submit" name="reseed" value="now" /><br />
|
||||
<hr />
|
||||
<input type="submit" value="Save changes" /> <input type="reset" value="Cancel" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
26
apps/routerconsole/jsp/configadvanced.jsp
Normal file
26
apps/routerconsole/jsp/configadvanced.jsp
Normal file
@ -0,0 +1,26 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - config advanced</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<jsp:useBean class="net.i2p.router.web.ConfigAdvancedHelper" id="advancedhelper" scope="request" />
|
||||
<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
|
||||
<div class="main" id="main">
|
||||
<%@include file="confignav.jsp" %>
|
||||
<form action="configadvanced.jsp" method="POST">
|
||||
<textarea rows="20" cols="80" name="config"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br />
|
||||
<input type="submit" value="Apply" /> <input type="reset" value="Cancel" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
32
apps/routerconsole/jsp/configclients.jsp
Normal file
32
apps/routerconsole/jsp/configclients.jsp
Normal file
@ -0,0 +1,32 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - config clients</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<jsp:useBean class="net.i2p.router.web.ConfigClientsHelper" id="clientshelper" scope="request" />
|
||||
<jsp:setProperty name="clientshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
|
||||
<div class="main" id="main">
|
||||
<%@include file="confignav.jsp" %>
|
||||
<form action="configclients.jsp" method="POST">
|
||||
<b>Estimated number of clients/destinations:</b>
|
||||
<jsp:getProperty name="clientshelper" property="clientCountSelectBox" /><br />
|
||||
<b>Default number of inbound tunnels per client:</b>
|
||||
<jsp:getProperty name="clientshelper" property="tunnelCountSelectBox" /><br />
|
||||
<b>Default number of hops per tunnel:</b>
|
||||
<jsp:getProperty name="clientshelper" property="tunnelDepthSelectBox" /><br />
|
||||
<hr />
|
||||
<input type="submit" value="Save changes" /> <input type="reset" value="Cancel" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
39
apps/routerconsole/jsp/configlogging.jsp
Normal file
39
apps/routerconsole/jsp/configlogging.jsp
Normal file
@ -0,0 +1,39 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - config clients</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
<jsp:useBean class="net.i2p.router.web.ConfigLoggingHelper" id="logginghelper" scope="request" />
|
||||
<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<div class="main" id="main">
|
||||
<%@include file="confignav.jsp" %>
|
||||
<form action="configlogging.jsp" method="POST">
|
||||
<b>Logging filename:</b>
|
||||
<input type="text" name="logfilename" size="40" value="<jsp:getProperty name="logginghelper" property="logFilePattern" />" /><br />
|
||||
<i>(the symbol '#' will be replaced during log rotation)</i><br />
|
||||
<b>Log record format:</b>
|
||||
<input type="text" name="logformat" size="20" value="<jsp:getProperty name="logginghelper" property="recordPattern" />" /><br />
|
||||
<i>(use 'd' = date, 'c' = class, 't' = thread, 'p' = priority, 'm' = message)</i><br />
|
||||
<b>Log date format:</b>
|
||||
<input type="text" name="logdateformat" size="20" value="<jsp:getProperty name="logginghelper" property="datePattern" />" /><br />
|
||||
<i>('MM' = month, 'dd' = day, 'HH' = hour, 'mm' = minute, 'ss' = second, 'SSS' = millisecond)</i><br />
|
||||
<b>Max log file size:</b>
|
||||
<input type="text" name="logfilesize" size="4" value="<jsp:getProperty name="logginghelper" property="maxFileSize" />" /><br />
|
||||
<hr />
|
||||
<b>Log levels:</b> <br />
|
||||
<jsp:getProperty name="logginghelper" property="logLevelTable" />
|
||||
<hr />
|
||||
<input type="submit" value="Apply changes" /> <input type="submit" value="Apply and Save" /> <input type="reset" value="Cancel" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
8
apps/routerconsole/jsp/confignav.jsp
Normal file
8
apps/routerconsole/jsp/confignav.jsp
Normal file
@ -0,0 +1,8 @@
|
||||
<h4><% if (request.getRequestURI().indexOf("config.jsp") != -1) {
|
||||
%>Network | <% } else { %><a href="config.jsp">Network</a> | <% }
|
||||
if (request.getRequestURI().indexOf("configclients.jsp") != -1) {
|
||||
%>Clients | <% } else { %><a href="configclients.jsp">Clients</a> | <% }
|
||||
if (request.getRequestURI().indexOf("configlogging.jsp") != -1) {
|
||||
%>Logging | <% } else { %><a href="configlogging.jsp">Logging</a> | <% }
|
||||
if (request.getRequestURI().indexOf("configadvanced.jsp") != -1) {
|
||||
%>Advanced | <% } else { %><a href="configadvanced.jsp">Advanced</a> | <% } %></h4>
|
60
apps/routerconsole/jsp/default.css
Normal file
60
apps/routerconsole/jsp/default.css
Normal file
@ -0,0 +1,60 @@
|
||||
body {
|
||||
font-family: Verdana, Tahoma, Helvetica, sans-serif;
|
||||
margin: 1em 0em;
|
||||
padding: 0em;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.logo {
|
||||
float: left;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.routersummary {
|
||||
/* width: 8em; */
|
||||
/* height: 5em; */
|
||||
/* position: fixed; */
|
||||
float: left;
|
||||
/* left: 1em; */
|
||||
/* top: 1em; */
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
background-color: #fafaff;
|
||||
color: inherit;
|
||||
font-size: small;
|
||||
clear: left; /* fixes a bug in Opera */
|
||||
}
|
||||
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 12em;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.main {
|
||||
margin: 0em 1em 1em 12em;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffffef;
|
||||
border: medium solid #ffffd0;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
26
apps/routerconsole/jsp/help.jsp
Normal file
26
apps/routerconsole/jsp/help.jsp
Normal file
@ -0,0 +1,26 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - logs</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<div class="main" id="main">
|
||||
hmm. we should probably have some help text here.<br />
|
||||
This "routerconsole" application runs on top of a trimmed down <a href="jetty.mortbay.com/jetty/index.html">Jetty</a>
|
||||
instance (trimmed down, as in, we do not include the demo apps or other add-ons), allowing you to deploy standard
|
||||
JSP/Servlet web applications into your router. Jetty in turn makes use of Apache's javax.servlet (javax.servlet.jar)
|
||||
implementation, as well as their xerces-j XML parser (xerces.jar). Their XML parser requires the Sun XML
|
||||
APIs (JAXP) which is included in binary form (xml-apis.jar) as required by their binary code license.
|
||||
This product includes software developed by the Apache Software Foundation (http://www.apache.org/). See the
|
||||
<a href="http://www.i2p.net/">I2P</a> site or the source for more license details.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
apps/routerconsole/jsp/i2plogo.png
Normal file
BIN
apps/routerconsole/jsp/i2plogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 925 B |
19
apps/routerconsole/jsp/index.jsp
Normal file
19
apps/routerconsole/jsp/index.jsp
Normal file
@ -0,0 +1,19 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - home</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<div class="main" id="main">
|
||||
<h2>Welcome to your router console</h2>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
21
apps/routerconsole/jsp/logs.jsp
Normal file
21
apps/routerconsole/jsp/logs.jsp
Normal file
@ -0,0 +1,21 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - logs</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<div class="main" id="main">
|
||||
<jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
|
||||
<jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="logsHelper" property="logs" />
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
18
apps/routerconsole/jsp/nav.jsp
Normal file
18
apps/routerconsole/jsp/nav.jsp
Normal file
@ -0,0 +1,18 @@
|
||||
<%
|
||||
if (request.getParameter("i2p.contextId") != null) {
|
||||
session.setAttribute("i2p.contextId", request.getParameter("i2p.contextId"));
|
||||
}%>
|
||||
|
||||
<div class="logo">
|
||||
<a href="index.jsp"><img src="i2plogo.png" alt="Router Console" width="187" height="35" /></a><br />
|
||||
[<a href="config.jsp">configuration</a> | <a href="help.jsp">help</a>]
|
||||
</div>
|
||||
|
||||
<h3>
|
||||
<a href="profiles.jsp">Profiles</a> |
|
||||
<a href="netdb.jsp">Network Database</a> |
|
||||
<a href="logs.jsp">Logs</a>
|
||||
<jsp:useBean class="net.i2p.router.web.NavHelper" id="navhelper" scope="request" />
|
||||
<jsp:setProperty name="navhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="navhelper" property="clientAppLinks" />
|
||||
</h3>
|
21
apps/routerconsole/jsp/netdb.jsp
Normal file
21
apps/routerconsole/jsp/netdb.jsp
Normal file
@ -0,0 +1,21 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - network database summary</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<div class="main" id="main">
|
||||
<jsp:useBean class="net.i2p.router.web.NetDbHelper" id="netdbHelper" scope="request" />
|
||||
<jsp:setProperty name="netdbHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="netdbHelper" property="netDbSummary" />
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
1
apps/routerconsole/jsp/notice.jsp
Normal file
1
apps/routerconsole/jsp/notice.jsp
Normal file
@ -0,0 +1 @@
|
||||
<%=(null != request.getParameter("i2p.console.notice") ? request.getParameter("i2p.console.notice") : "")%>
|
21
apps/routerconsole/jsp/profiles.jsp
Normal file
21
apps/routerconsole/jsp/profiles.jsp
Normal file
@ -0,0 +1,21 @@
|
||||
<%@page contentType="text/html"%>
|
||||
<%@page pageEncoding="UTF-8"%>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html><head>
|
||||
<title>I2P Router Console - peer profiles</title>
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head><body>
|
||||
|
||||
<%@include file="nav.jsp" %>
|
||||
<%@include file="summary.jsp" %>
|
||||
<%@include file="notice.jsp" %>
|
||||
|
||||
<div class="main" id="main">
|
||||
<jsp:useBean class="net.i2p.router.web.ProfilesHelper" id="profilesHelper" scope="request" />
|
||||
<jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
<jsp:getProperty name="profilesHelper" property="profileSummary" />
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
40
apps/routerconsole/jsp/summary.jsp
Normal file
40
apps/routerconsole/jsp/summary.jsp
Normal file
@ -0,0 +1,40 @@
|
||||
<%@page import="net.i2p.router.web.SummaryHelper" %>
|
||||
<jsp:useBean class="net.i2p.router.web.SummaryHelper" id="helper" scope="request" />
|
||||
<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||
|
||||
<div class="routersummary">
|
||||
<u><b>General</b></u><br />
|
||||
<b>Ident:</b> <jsp:getProperty name="helper" property="ident" /><br />
|
||||
<b>Version:</b> <jsp:getProperty name="helper" property="version" /><br />
|
||||
<b>Uptime:</b> <jsp:getProperty name="helper" property="uptime" /><br />
|
||||
<hr />
|
||||
|
||||
<u><b>Peers</b></u><br />
|
||||
<b>Active:</b> <jsp:getProperty name="helper" property="activePeers" /><br />
|
||||
<b>Fast:</b> <jsp:getProperty name="helper" property="fastPeers" /><br />
|
||||
<b>High capacity:</b> <jsp:getProperty name="helper" property="highCapacityPeers" /><br />
|
||||
<b>Well integrated:</b> <jsp:getProperty name="helper" property="wellIntegratedPeers" /><br />
|
||||
<b>Failing:</b> <jsp:getProperty name="helper" property="failingPeers" /><br />
|
||||
<b>Shitlisted:</b> <jsp:getProperty name="helper" property="shitlistedPeers" /><br />
|
||||
<hr />
|
||||
|
||||
<u><b>Bandwidth in/out</b></u><br />
|
||||
<b>1m:</b> <jsp:getProperty name="helper" property="inboundMinuteKBps" />/<jsp:getProperty name="helper" property="outboundMinuteKBps" />KBps<br />
|
||||
<b>5m:</b> <jsp:getProperty name="helper" property="inboundFiveMinuteKBps" />/<jsp:getProperty name="helper" property="outboundFiveMinuteKBps" />KBps<br />
|
||||
<b>Total:</b> <jsp:getProperty name="helper" property="inboundLifetimeKBps" />/<jsp:getProperty name="helper" property="outboundLifetimeKBps" />KBps<br />
|
||||
<b>Used:</b> <jsp:getProperty name="helper" property="inboundTransferred" />/<jsp:getProperty name="helper" property="outboundTransferred" /><br />
|
||||
<hr />
|
||||
|
||||
<u><b>Tunnels</b></u><br />
|
||||
<b>Inbound:</b> <jsp:getProperty name="helper" property="inboundTunnels" /><br />
|
||||
<b>Outbound:</b> <jsp:getProperty name="helper" property="outboundTunnels" /><br />
|
||||
<b>Participating:</b> <jsp:getProperty name="helper" property="participatingTunnels" /><br />
|
||||
<hr />
|
||||
|
||||
<u><b>Congestion</b></u><br />
|
||||
<b>Job lag:</b> <jsp:getProperty name="helper" property="jobLag" /><br />
|
||||
<b>Message delay:</b> <jsp:getProperty name="helper" property="messageDelay" /><br />
|
||||
<b>Tunnel lag:</b> <jsp:getProperty name="helper" property="tunnelLag" /><br />
|
||||
<hr />
|
||||
|
||||
</div>
|
17
apps/routerconsole/jsp/web.xml
Normal file
17
apps/routerconsole/jsp/web.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE web-app
|
||||
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
|
||||
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
|
||||
|
||||
<web-app>
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
<welcome-file-list>
|
||||
<welcome-file>
|
||||
index.jsp
|
||||
</welcome-file>
|
||||
</welcome-file-list>
|
||||
</web-app>
|
25
apps/routerconsole/readme.txt
Normal file
25
apps/routerconsole/readme.txt
Normal file
@ -0,0 +1,25 @@
|
||||
The routerconsole application is an embedable web server / servlet container.
|
||||
In it there is a bundled routerconsole.war containing JSPs (per jsp/*) that
|
||||
implement a web based control panel for the router. This console gives the user
|
||||
a quick view into how their router is operating and exposes some pages to
|
||||
configure it.
|
||||
|
||||
The web server itself is Jetty [1] and is contained within the various jar files
|
||||
under lib/. To embed this web server and the included router console, the
|
||||
startRouter script needs to be updated to include those jar files in the
|
||||
class path, plus the router.config needs appropriate entries to start up the
|
||||
server:
|
||||
|
||||
clientApp.3.main=net.i2p.router.web.RouterConsoleRunner
|
||||
clientApp.3.name=webConsole
|
||||
clientApp.3.args=7657 0.0.0.0 ./webapps/
|
||||
|
||||
That instructs the router to fire up the webserver listening on port 7657 on
|
||||
all of its interfaces (0.0.0.0), loading up any .war files under the ./webapps/
|
||||
directory. The RouterConsoleRunner itself configures the Jetty server to give
|
||||
the ./webapps/routerconsole.war control over the root context, directing a
|
||||
request to http://localhost:7657/index.jsp to the routerconsole.war's index.jsp.
|
||||
Any other .war file will be mounted under their filename's context (e.g.
|
||||
myi2p.war would be reachable at http://localhost:7657/myi2p/index.jsp).
|
||||
|
||||
[1] http://jetty.mortbay.com/jetty/index.html
|
63
apps/sam/c/Makefile.freebsd
Normal file
63
apps/sam/c/Makefile.freebsd
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# This Makefile is compatible with GNU Make (gmake) and should work on FreeBSD
|
||||
#
|
||||
|
||||
#
|
||||
# Your operating system
|
||||
#
|
||||
|
||||
OS = FREEBSD
|
||||
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
|
||||
INCDIR = inc
|
||||
LIBDIR = lib
|
||||
OBJDIR = obj
|
||||
SRCDIR = src
|
||||
|
||||
#
|
||||
# Programs
|
||||
#
|
||||
|
||||
AR = ar
|
||||
CC = gcc
|
||||
|
||||
#
|
||||
# Flags
|
||||
#
|
||||
|
||||
CFLAGS = -g -O2 -pipe -std=c99 -Wall
|
||||
CFLAGS += -DOS=$(OS)
|
||||
CFLAGS += -I$(INCDIR)
|
||||
|
||||
#
|
||||
# Object files
|
||||
#
|
||||
|
||||
OBJS = $(OBJDIR)/sam.o
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: depend libsam
|
||||
|
||||
depend:
|
||||
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
libsam: $(OBJS)
|
||||
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||
|
||||
#
|
||||
# Cleanup rules
|
||||
#
|
||||
|
||||
clean:
|
||||
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||
|
||||
tidy: clean
|
@ -1,4 +1,9 @@
|
||||
v1.20
|
||||
v1.25
|
||||
* Rewrote sendq functions to automatically send big packets, for better
|
||||
network performance
|
||||
|
||||
v1.20 2004-07-11
|
||||
* Ported to FreeBSD (Makefile.freebsd)
|
||||
* Full winsock compatibility - all Windows functions now return appropriate
|
||||
error strings
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
/*
|
||||
* Operating system
|
||||
*/
|
||||
#define FREEBSD 0 // FreeBSD (untested)
|
||||
#define FREEBSD 0 // FreeBSD
|
||||
#define MINGW 1 // Windows native (Mingw)
|
||||
#define LINUX 2 // Linux
|
||||
#define CYGWIN 3 // Cygwin
|
||||
@ -83,9 +83,10 @@
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
@ -34,18 +34,28 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
/* The maximum length a SAM command can be */
|
||||
#define SAM_CMD_LEN 128
|
||||
/*The maximum size of a single datagram packet (-30 temporary bug fix for SAM)*/
|
||||
#define SAM_DGRAM_PAYLOAD_MAX ((31 * 1024) - 30)
|
||||
/* The longest log message */
|
||||
#define SAM_LOGMSG_LEN 256
|
||||
/* The longest `name' arg for the naming lookup callback */
|
||||
#define SAM_NAME_LEN 256
|
||||
/* The max size of a single stream packet */
|
||||
#define SAM_STREAM_PAYLOAD_MAX (32 * 1024)
|
||||
/* The length of a base 64 public key - it's actually 516, but +1 for '\0' */
|
||||
#define SAM_PUBKEY_LEN 517
|
||||
/* A public key SAM command's length */
|
||||
#define SAM_PKCMD_LEN (SAM_PUBKEY_LEN + SAM_CMD_LEN)
|
||||
/* The maximum length a SAM non-data reply can be */
|
||||
#define SAM_REPLY_LEN 1024
|
||||
|
||||
/*
|
||||
* Shorten some standard variable types
|
||||
@ -81,14 +91,14 @@ typedef enum { /* see sam_strerror() for detailed descriptions of these */
|
||||
*/
|
||||
|
||||
/* SAM controls */
|
||||
extern bool sam_close(void);
|
||||
extern bool sam_close();
|
||||
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 bool sam_read_buffer();
|
||||
extern const char *sam_strerror(samerr_t code);
|
||||
/* SAM controls - callbacks */
|
||||
extern void (*sam_diedback)(void);
|
||||
extern void (*sam_diedback)();
|
||||
extern void (*sam_logback)(char *str);
|
||||
extern void (*sam_namingback)(char *name, sam_pubkey_t pubkey,
|
||||
samerr_t result);
|
||||
@ -105,10 +115,9 @@ 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);
|
||||
extern void sam_sendq_add(sam_sid_t stream_id, sam_sendq_t **sendq,
|
||||
const void *data, size_t dsize);
|
||||
extern void sam_sendq_flush(sam_sid_t stream_id, sam_sendq_t **sendq);
|
||||
|
||||
/* Datagram commands */
|
||||
extern samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data,
|
||||
|
@ -31,19 +31,20 @@
|
||||
#include "platform.h"
|
||||
#include "sam.h"
|
||||
|
||||
static bool sam_hello(void);
|
||||
static bool sam_hello();
|
||||
static void sam_log(const char *format, ...);
|
||||
static void sam_parse(char *s);
|
||||
static ssize_t sam_read1(char *buf, size_t n);
|
||||
static ssize_t sam_read2(void *buf, size_t n);
|
||||
static bool sam_readable(void);
|
||||
static bool sam_readable();
|
||||
static sam_sendq_t *sam_sendq_create();
|
||||
static samerr_t sam_session_create(const char *destname, sam_conn_t style,
|
||||
uint_t tunneldepth);
|
||||
static bool sam_socket_connect(const char *host, uint16_t port);
|
||||
static bool sam_socket_resolve(const char *hostname, char *ipaddr);
|
||||
#ifdef WINSOCK
|
||||
static samerr_t sam_winsock_cleanup(void);
|
||||
static samerr_t sam_winsock_startup(void);
|
||||
static samerr_t sam_winsock_cleanup();
|
||||
static samerr_t sam_winsock_startup();
|
||||
static const char *sam_winsock_strerror(int code);
|
||||
#endif
|
||||
static ssize_t sam_write(const void *buf, size_t n);
|
||||
@ -61,7 +62,7 @@ void (*sam_databack)(sam_sid_t stream_id, void *data, size_t size) = NULL;
|
||||
/* a peer sent some datagram data (`data' MUST be freed) */
|
||||
void (*sam_dgramback)(sam_pubkey_t dest, void *data, size_t size) = NULL;
|
||||
/* we lost the connection to the SAM host */
|
||||
void (*sam_diedback)(void) = NULL;
|
||||
void (*sam_diedback)() = NULL;
|
||||
/* logging callback */
|
||||
void (*sam_logback)(char *str) = NULL;
|
||||
/* naming lookup reply - `pubkey' will be NULL if `result' isn't SAM_OK */
|
||||
@ -79,7 +80,7 @@ static bool samd_connected = false; /* Whether we're connected with SAM */
|
||||
*
|
||||
* Returns: true on success, false on failure
|
||||
*/
|
||||
bool sam_close(void)
|
||||
bool sam_close()
|
||||
{
|
||||
if (!samd_connected)
|
||||
return true;
|
||||
@ -119,7 +120,7 @@ bool sam_close(void)
|
||||
* Returns: true on success, false on failure
|
||||
*/
|
||||
samerr_t sam_connect(const char *samhost, uint16_t samport,
|
||||
const char *destname, sam_conn_t style, uint_t tunneldepth)
|
||||
const char *destname, sam_conn_t style, uint_t tunneldepth)
|
||||
{
|
||||
samerr_t rc;
|
||||
|
||||
@ -189,7 +190,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
|
||||
#ifdef NO_Z_FORMAT
|
||||
SAMLOG("Invalid data send size (%u bytes)", size);
|
||||
#else
|
||||
SAMLOG("Invalid data send size (%z bytes)", size);
|
||||
SAMLOG("Invalid data send size (%dz bytes)", size);
|
||||
#endif
|
||||
return SAM_TOO_BIG;
|
||||
}
|
||||
@ -197,7 +198,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
|
||||
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%u\n",
|
||||
dest, size);
|
||||
#else
|
||||
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%z\n",
|
||||
snprintf(cmd, sizeof cmd, "DATAGRAM SEND DESTINATION=%s SIZE=%dz\n",
|
||||
dest, size);
|
||||
#endif
|
||||
sam_write(cmd, strlen(cmd));
|
||||
@ -212,7 +213,7 @@ samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data, size_t size)
|
||||
*
|
||||
* Returns: true on success, false on reply failure
|
||||
*/
|
||||
static bool sam_hello(void)
|
||||
static bool sam_hello()
|
||||
{
|
||||
#define SAM_HELLO_CMD "HELLO VERSION MIN=1.0 MAX=1.0\n"
|
||||
#define SAM_HELLO_REPLY "HELLO REPLY RESULT=OK VERSION=1.0"
|
||||
@ -491,7 +492,7 @@ static void sam_parse(char *s)
|
||||
*
|
||||
* Returns: true if we read anything, or false if nothing was there
|
||||
*/
|
||||
bool sam_read_buffer(void)
|
||||
bool sam_read_buffer()
|
||||
{
|
||||
bool read_something = false;
|
||||
char reply[SAM_REPLY_LEN];
|
||||
@ -639,7 +640,7 @@ static ssize_t sam_read2(void *buf, size_t n)
|
||||
*
|
||||
* Returns: true if data is waiting, false otherwise
|
||||
*/
|
||||
static bool sam_readable(void)
|
||||
static bool sam_readable()
|
||||
{
|
||||
fd_set rset; /* set of readable descriptors */
|
||||
struct timeval tv;
|
||||
@ -679,36 +680,58 @@ static bool sam_readable(void)
|
||||
*
|
||||
* Returns: true on success, false on error
|
||||
*/
|
||||
samerr_t sam_sendq_add(sam_sendq_t *sendq, const void *data, size_t dsize)
|
||||
void sam_sendq_add(sam_sid_t stream_id, sam_sendq_t **sendq, const void *data,
|
||||
size_t dsize)
|
||||
{
|
||||
assert(dsize >= 0);
|
||||
if (dsize == 0) {
|
||||
SAMLOGS("dsize is 0 - adding nothing");
|
||||
return SAM_OK;
|
||||
} else if (sendq->size + dsize > SAM_STREAM_PAYLOAD_MAX) {
|
||||
SAMLOGS("The queue size would exceed the maximum SAM payload size -" \
|
||||
" will not add to the queue");
|
||||
return SAM_TOO_BIG;
|
||||
SAMLOGS("dsize is 0 - doing nothing");
|
||||
return;
|
||||
}
|
||||
|
||||
sendq->data = realloc(sendq->data, sendq->size + dsize);
|
||||
memcpy(sendq->data + sendq->size, data, dsize);
|
||||
sendq->size += dsize;
|
||||
/* if the sendq pointer is set to NULL, create a sendq */
|
||||
if (*sendq == NULL)
|
||||
*sendq = sam_sendq_create();
|
||||
|
||||
return SAM_OK;
|
||||
/* the added data doesn't fill the queue - add but don't send */
|
||||
if ((*sendq)->size + dsize < SAM_STREAM_PAYLOAD_MAX) {
|
||||
memcpy((*sendq)->data + (*sendq)->size, data, dsize);
|
||||
(*sendq)->size += dsize;
|
||||
return;
|
||||
}
|
||||
|
||||
/* what luck! - an exact fit - send the packet */
|
||||
if ((*sendq)->size + dsize == SAM_STREAM_PAYLOAD_MAX) {
|
||||
memcpy((*sendq)->data + (*sendq)->size, data, dsize);
|
||||
(*sendq)->size = SAM_STREAM_PAYLOAD_MAX;
|
||||
sam_sendq_flush(stream_id, sendq);
|
||||
return;
|
||||
}
|
||||
|
||||
/* they have more data than the queue can hold, so we'll have to send some*/
|
||||
size_t s = SAM_STREAM_PAYLOAD_MAX - (*sendq)->size; // space free in packet
|
||||
memcpy((*sendq)->data + (*sendq)->size, data, s); //append as much as we can
|
||||
dsize -= s; /* update dsize to the size of whatever data hasn't been sent*/
|
||||
(*sendq)->size = SAM_STREAM_PAYLOAD_MAX; /* it's a full packet */
|
||||
sam_sendq_flush(stream_id, sendq); /* send the queued data */
|
||||
sam_sendq_add(stream_id, sendq, data + s, dsize); /* recurse the rest */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a data queue for use with sam_stream_send
|
||||
* Creates a data queue for use with sam_sendq_add()
|
||||
*
|
||||
* Returns: pointer to the newly created send queue
|
||||
*/
|
||||
sam_sendq_t *sam_sendq_create(void)
|
||||
static sam_sendq_t *sam_sendq_create()
|
||||
{
|
||||
sam_sendq_t *sendq;
|
||||
|
||||
sendq = malloc(sizeof(sam_sendq_t));
|
||||
sendq->data = NULL;
|
||||
sendq->data = malloc(SAM_STREAM_PAYLOAD_MAX);
|
||||
/* ^^ a waste of memory perhaps, but more efficient than realloc'ing every
|
||||
* time data is added the to queue */
|
||||
sendq->size = 0;
|
||||
|
||||
return sendq;
|
||||
@ -720,10 +743,13 @@ sam_sendq_t *sam_sendq_create(void)
|
||||
* sendq - the send queue
|
||||
* stream_id - stream number to send to
|
||||
*/
|
||||
void sam_sendq_send(sam_sendq_t *sendq, sam_sid_t stream_id)
|
||||
void sam_sendq_flush(sam_sid_t stream_id, sam_sendq_t **sendq)
|
||||
{
|
||||
sam_stream_send(stream_id, sendq->data, sendq->size);
|
||||
free(sendq);
|
||||
sam_stream_send(stream_id, (*sendq)->data, (*sendq)->size);
|
||||
/* we now free it in case they aren't going to use it anymore */
|
||||
free((*sendq)->data);
|
||||
free(*sendq);
|
||||
*sendq = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -738,7 +764,7 @@ void sam_sendq_send(sam_sendq_t *sendq, sam_sid_t stream_id)
|
||||
* Returns: SAM error code
|
||||
*/
|
||||
static samerr_t sam_session_create(const char *destname, sam_conn_t style,
|
||||
uint_t tunneldepth)
|
||||
uint_t tunneldepth)
|
||||
{
|
||||
#define SAM_SESSTATUS_REPLY_OK "SESSION STATUS RESULT=OK"
|
||||
#define SAM_SESSTATUS_REPLY_DD "SESSION STATUS RESULT=DUPLICATED_DEST"
|
||||
@ -957,7 +983,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
|
||||
SAMLOG("Invalid data send size (%u bytes) for stream %d",
|
||||
size, stream_id);
|
||||
#else
|
||||
SAMLOG("Invalid data send size (%z bytes) for stream %d",
|
||||
SAMLOG("Invalid data send size (%dz bytes) for stream %d",
|
||||
size, stream_id);
|
||||
#endif
|
||||
return SAM_TOO_BIG;
|
||||
@ -971,7 +997,7 @@ samerr_t sam_stream_send(sam_sid_t stream_id, const void *data, size_t size)
|
||||
stream_id, size);
|
||||
#endif
|
||||
#else
|
||||
snprintf(cmd, sizeof cmd, "STREAM SEND ID=%d SIZE=%z\n",
|
||||
snprintf(cmd, sizeof cmd, "STREAM SEND ID=%d SIZE=%dz\n",
|
||||
stream_id, size);
|
||||
#endif
|
||||
sam_write(cmd, strlen(cmd));
|
||||
@ -1034,7 +1060,7 @@ const char *sam_strerror(samerr_t code)
|
||||
*
|
||||
* Returns: SAM error code
|
||||
*/
|
||||
samerr_t sam_winsock_cleanup(void)
|
||||
samerr_t sam_winsock_cleanup()
|
||||
{
|
||||
if (WSACleanup() == SOCKET_ERROR) {
|
||||
SAMLOG("WSACleanup() failed: %s",
|
||||
@ -1050,7 +1076,7 @@ samerr_t sam_winsock_cleanup(void)
|
||||
*
|
||||
* Returns: SAM error code
|
||||
*/
|
||||
samerr_t sam_winsock_startup(void)
|
||||
samerr_t sam_winsock_startup()
|
||||
{
|
||||
/*
|
||||
* Is Windows retarded or what?
|
||||
|
3957
apps/sam/code.leo
3957
apps/sam/code.leo
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,8 @@
|
||||
SAM - Simple Anonymous Messaging - is a protocol which allows
|
||||
I2P applications to access the I2P network via an unencrypted
|
||||
TCP socket connection.
|
||||
|
||||
Interim SAM protocol specification can be found at:
|
||||
http://drupal.i2p.net/node/view/144
|
||||
|
||||
At time of first writing this README, an implementation of the SAM
|
||||
server has been implemented in Jython (www.jython.org).
|
||||
|
||||
You can find the server code, and build files, in the ../jython
|
||||
directory.
|
||||
|
||||
A python client implementation, containing demo functions,
|
||||
can be found in the ../python directory.
|
||||
|
||||
I2P developers are strongly encouraged to create SAM
|
||||
client implementations in other languages, most importantly,
|
||||
popular portable languages like C/C++, Perl and Ruby.
|
||||
|
||||
The 'code.leo' file in this directory is used by the Leo
|
||||
code editor (http://leo.sf.net), to manage the source in a
|
||||
flexible tree format. While I can't insist on it, I'd
|
||||
massively appreciate it if you could use this editor when
|
||||
making additions and changes to the files herein, because
|
||||
it will save me a lot of maintenance effort.
|
||||
The Simple Anonymous Messaging protocol provides a way for
|
||||
client applications to communicate anonymously over I2P without
|
||||
having to deal with the complexities of I2CP. More information can
|
||||
be found at http://www.i2p.net/sam and a comparison of the various
|
||||
client access techniques is up at http://www.i2p.net/applications
|
||||
|
||||
There are a few SAM libraries available in this package, as well as
|
||||
a Java implementation of the SAM bridge.
|
@ -11,7 +11,7 @@
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac
|
||||
srcdir="./src"
|
||||
debug="true"
|
||||
debug="true" deprecation="on" source="1.3" target="1.3"
|
||||
destdir="./build/obj"
|
||||
classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
|
||||
</target>
|
||||
|
@ -660,7 +660,10 @@ public class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatag
|
||||
}
|
||||
}
|
||||
|
||||
return streamSession.closeConnection(id);
|
||||
boolean closed = streamSession.closeConnection(id);
|
||||
if ( (!closed) && (_log.shouldLog(Log.WARN)) )
|
||||
_log.warn("Stream unable to be closed, but this is non fatal");
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check whether a size is inside the limits allowed by this protocol */
|
||||
|
@ -7,6 +7,7 @@ import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.Clock;
|
||||
|
||||
public class TestCreateSessionRaw {
|
||||
private static Log _log = new Log(TestCreateSessionRaw.class);
|
||||
@ -15,6 +16,7 @@ public class TestCreateSessionRaw {
|
||||
testTransient(samHost, samPort, conOptions);
|
||||
testNewDest(samHost, samPort, conOptions);
|
||||
testOldDest(samHost, samPort, conOptions);
|
||||
testFast(samHost, samPort, conOptions);
|
||||
}
|
||||
|
||||
private static void testTransient(String host, int port, String conOptions) {
|
||||
@ -36,21 +38,34 @@ public class TestCreateSessionRaw {
|
||||
_log.debug("\n\nTest of subsequent contact complete\n\n");
|
||||
}
|
||||
|
||||
private static void testFast(String host, int port, String conOptions) {
|
||||
String destName = "Alice" + Math.random();
|
||||
long totalTime = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
long before = Clock.getInstance().now();
|
||||
testDest(host, port, conOptions, destName);
|
||||
long after = Clock.getInstance().now();
|
||||
long difference = after-before;
|
||||
_log.debug("Time to test destination: " + difference + " \n\n");
|
||||
totalTime += difference;
|
||||
}
|
||||
_log.debug("\n\nTime to test fast reconnection: " + totalTime + " over 10 runs");
|
||||
}
|
||||
|
||||
private static void testDest(String host, int port, String conOptions, String destName) {
|
||||
_log.info("\n\nTesting creating a new destination (should come back with 'SESSION STATUS RESULT=OK DESTINATION=someName)\n\n\n");
|
||||
//_log.info("\n\nTesting creating a new destination (should come back with 'SESSION STATUS RESULT=OK DESTINATION=someName)\n\n\n");
|
||||
try {
|
||||
Socket s = new Socket(host, port);
|
||||
OutputStream out = s.getOutputStream();
|
||||
out.write("HELLO VERSION MIN=1.0 MAX=1.0\n".getBytes());
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
String line = reader.readLine();
|
||||
_log.debug("line read for valid version: " + line);
|
||||
//_log.debug("line read for valid version: " + line);
|
||||
String req = "SESSION CREATE STYLE=RAW DESTINATION=" + destName + " " + conOptions + "\n";
|
||||
out.write(req.getBytes());
|
||||
line = reader.readLine();
|
||||
_log.info("Response to creating the session with destination " + destName + ": " + line);
|
||||
_log.debug("The above should contain SESSION STATUS RESULT=OK\n\n\n");
|
||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||
_log.debug("The above should contain SESSION STATUS RESULT=OK");
|
||||
s.close();
|
||||
} catch (Exception e) {
|
||||
_log.error("Error testing for valid version", e);
|
||||
@ -60,7 +75,7 @@ public class TestCreateSessionRaw {
|
||||
public static void main(String args[]) {
|
||||
// "i2cp.tcp.host=www.i2p.net i2cp.tcp.port=7765";
|
||||
// "i2cp.tcp.host=localhost i2cp.tcp.port=7654 tunnels.inboundDepth=0";
|
||||
String conOptions = "i2cp.tcp.host=dev.i2p.net i2cp.tcp.port=7002 tunnels.inboundDepth=0";
|
||||
String conOptions = "i2cp.tcp.host=dev.i2p.net i2cp.tcp.port=7002 tunnels.depthInbound=0 tunnels.depthOutbound=0";
|
||||
if (args.length > 0) {
|
||||
conOptions = "";
|
||||
for (int i = 0; i < args.length; i++)
|
||||
|
@ -1,54 +0,0 @@
|
||||
-----------------------------------
|
||||
Instructions for building i2psam.jar
|
||||
------------------------------------
|
||||
|
||||
1) Requirements
|
||||
|
||||
You will need:
|
||||
|
||||
- jython - www.jython.org
|
||||
|
||||
Note that you don't need python to build the SAM server
|
||||
|
||||
IMPORTANT - when you're installing jython, and running
|
||||
'java on jython_n.n.class',
|
||||
make sure you run the java.exe that's in your SDK, not the one in your
|
||||
JRE.
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
2) Preparation
|
||||
|
||||
- add the main jython directory to your PATH. Test this by typing
|
||||
'jythonc' from a shell prompt.
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
3) Building
|
||||
|
||||
- type 'ant build'
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
4) Installing
|
||||
|
||||
Copy i2psam.jar to wherever the jar files live on your i2p installation,
|
||||
usually <i2pbasedir>/lib
|
||||
|
||||
Find jython.jar, and copy it there too
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
5) Running
|
||||
|
||||
(assuming that you're putting the start script into your main i2p
|
||||
runtime directory, where the I2P jars live in a 'lib' subdirectory)
|
||||
|
||||
You will need to launch i2psam.jar with a command like:
|
||||
|
||||
java -cp lib/jython.jar:lib/i2p.jar:lib/mstreaming.jar:lib/i2psam.jar i2psam
|
||||
|
||||
or on windows,
|
||||
|
||||
java -cp lib\jython.jar;lib\i2p.jar;lib\mstreaming.jar;lib\i2psam.jar i2psam
|
||||
|
@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project basedir="." default="all" name="sam">
|
||||
|
||||
<target name="all" depends="build" />
|
||||
|
||||
<target name="build" depends="builddep, jar" />
|
||||
|
||||
<target name="builddep">
|
||||
<ant dir="../../../core/java/" target="build" />
|
||||
<ant dir="../../ministreaming/java/" target="build" />
|
||||
</target>
|
||||
|
||||
<target name="jar">
|
||||
|
||||
<condition property="jythonext" value=".bat">
|
||||
<os family="windows" />
|
||||
</condition>
|
||||
<condition property="jythonext" value="">
|
||||
<not>
|
||||
<os family="windows" />
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<exec executable="jythonc${jythonext}" dir=".">
|
||||
<env key="CLASSPATH" path="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar"/>
|
||||
<arg value="--jar"/><arg path="./i2psam.jar"/>
|
||||
<arg path="./src/i2psam.py"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="clean">
|
||||
<delete file="i2psam.jar" />
|
||||
<delete dir="./jpywork" />
|
||||
</target>
|
||||
|
||||
</project>
|
File diff suppressed because it is too large
Load Diff
18
apps/sam/python/bugs.txt
Normal file
18
apps/sam/python/bugs.txt
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
Known Bugs:
|
||||
* TunnelServer may crash the I2P router in the following
|
||||
ways when a large file is downloaded:
|
||||
|
||||
* Out of memory exception (for large files)
|
||||
* Mysterious router death with no errors in the router logs
|
||||
(more recently)
|
||||
* BUG! in SAM proxy
|
||||
See http://oregonstate.edu/~barnesc/temp/sam_crash.txt
|
||||
* A small number of datagram packets sent are lost (even in a local
|
||||
loopback). This is apparently a bug in I2P.
|
||||
* Errors raised for sockets are non entirely consistent.
|
||||
See todo.txt for how to fix this.
|
||||
* A session does not close until a program exits.
|
||||
This should be fine once I2P is patched to allow multiple
|
||||
programs to use a single session at once.
|
||||
* i2p.router.start() does not work.
|
33
apps/sam/python/doc/guide/eeproxy.html
Normal file
33
apps/sam/python/doc/guide/eeproxy.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>Eeproxy - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>Eeproxy</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'>
|
||||
The <strong>Eeproxy</strong> is run by the I2P router. The proxy is normally used for web browsers, as a means of accessing eepsites.
|
||||
|
||||
|
||||
<p>
|
||||
The eeproxy is usually available at <a href="http://127.0.0.1:4444/" class='printable' title="http://127.0.0.1:4444/">http://127.0.0.1:4444/</a>.
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
</em><!-- Time since request: 0.77 secs. -->
|
||||
</body></html>
|
55
apps/sam/python/doc/guide/i2p.eep.html
Normal file
55
apps/sam/python/doc/guide/i2p.eep.html
Normal file
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>User's Guide:i2p.eep - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>User's Guide:i2p.eep</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'>
|
||||
Module <code >i2p.eep</code > allows Python programs to access the <a href="./eeproxy.html" class='printable' title ="Eeproxy">Eeproxy</a>.
|
||||
|
||||
|
||||
<p>
|
||||
With this module, a program can easily download eepsites.
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="Functions"> Functions </a></h2>
|
||||
|
||||
<p>
|
||||
<strong>urlopen</strong>(url, eepaddr='127.0.0.1:4444')
|
||||
<ul >
|
||||
|
||||
<pre> Like urllib2.urlopen(url), but only works for eep-sites.
|
||||
Example: f = urlopen('<a href="http://duck.i2p/index.html" class='printable' title="http://duck.i2p/index.html">http://duck.i2p/index.html</a>')
|
||||
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>urlget</strong>(url, eepaddr='127.0.0.1:4444')
|
||||
<ul >
|
||||
|
||||
<pre> Get contents of an eepsite.
|
||||
Example: urlget('<a href="http://duck.i2p/" class='printable' title="http://duck.i2p/">http://duck.i2p/</a>').
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
|
||||
</em><!-- Time since request: 0.78 secs. -->
|
||||
</body></html>
|
61
apps/sam/python/doc/guide/i2p.html
Normal file
61
apps/sam/python/doc/guide/i2p.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>User's Guide:i2p - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>User's Guide:i2p</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'>
|
||||
Package <code >i2p</code > is a container package for more specific modules.
|
||||
|
||||
|
||||
<p>
|
||||
It exports the following names:
|
||||
<ul >
|
||||
|
||||
<pre> <a href="./i2p.sam.html" class='printable' title ="User's Guide:i2p.sam">sam</a>
|
||||
<a href="./i2p.eep.html" class='printable' title ="User's Guide:i2p.eep">eep</a>
|
||||
<a href="./i2p.router.html" class='printable' title ="User's Guide:i2p.router">router</a>
|
||||
<a href="#Error" class='printable' title ="User's Guide:i2p">Error</a>
|
||||
<a href="#RouterError" class='printable' title ="User's Guide:i2p">RouterError</a>
|
||||
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
class <strong>Error</strong>(Exception):
|
||||
<ul >
|
||||
|
||||
<pre> Base class for all I2P errors.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
class <strong>RouterError</strong>(Error):
|
||||
|
||||
<ul >
|
||||
|
||||
<pre> Could not connect to router.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
</em><!-- Time since request: 0.85 secs. -->
|
||||
|
||||
</body></html>
|
87
apps/sam/python/doc/guide/i2p.router.html
Normal file
87
apps/sam/python/doc/guide/i2p.router.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>User's Guide:i2p.router - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>User's Guide:i2p.router</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'>
|
||||
Module <code >i2p.router</code > allows Python programs to control the I2P router.
|
||||
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="Functions"> Functions </a></h2>
|
||||
|
||||
<p>
|
||||
<strong>check</strong>(dir=None)
|
||||
<ul ><pre>
|
||||
Checks whether a locally installed router is running. Does
|
||||
nothing if successful, otherwise raises i2p.RouterError.
|
||||
|
||||
An I2P installation is located by using find(dir).
|
||||
The router.config file is parsed for 'router.adminPort'.
|
||||
This port is queried to determine whether the router is
|
||||
running.
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>find</strong>(dir=None)
|
||||
<ul ><pre>
|
||||
|
||||
Find the absolute path to a locally installed I2P router.
|
||||
|
||||
An I2P installation is located by looking in the
|
||||
environment I2P, then in PATH, then in the dir argument
|
||||
given to the function. It looks for startRouter.sh or
|
||||
startRouter.bat. Raises ValueError if an I2P installation
|
||||
could not be located.
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>start</strong>(dir=None, hidden=False)
|
||||
<ul ><pre>
|
||||
Start a locally installed I2P router. Does nothing if
|
||||
the router has already been started.
|
||||
|
||||
An I2P installation is located by using find(dir).
|
||||
|
||||
If hidden is True, do not show a terminal for the router.
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>stop</strong>(dir=None, force=False)
|
||||
<ul ><pre>
|
||||
Stop a locally installed I2P router, if it was started by
|
||||
the current Python program. If force is True, stop the
|
||||
router even if it was started by another process. Do nothing
|
||||
if force is False and the router was started by another program.
|
||||
|
||||
The file 'router.config' is located using the same search
|
||||
process used for find(dir). It is parsed for
|
||||
'router.shutdownPassword' and 'router.adminPort'. The
|
||||
router is shut down through the admin port.
|
||||
|
||||
Raises i2p.RouterError if the I2P router is running but cannot
|
||||
be stopped. You must uncomment the
|
||||
'router.shutdownPassword' line for this command to work.
|
||||
</pre>
|
||||
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
</em><!-- Time since request: 0.77 secs. -->
|
||||
</body></html>
|
308
apps/sam/python/doc/guide/i2p.sam.html
Normal file
308
apps/sam/python/doc/guide/i2p.sam.html
Normal file
@ -0,0 +1,308 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>User's Guide:i2p.sam - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>User's Guide:i2p.sam</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'><a name="top"></a>
|
||||
Module <code >i2p.sam</code > allows Python programs to access the <a href="./samproxy.html" class='printable' title ="SAM proxy">SAM proxy</a>.
|
||||
|
||||
|
||||
<p>
|
||||
With this module, a program can send stream data, datagrams, and raw packets across the I2P network.
|
||||
|
||||
<p>
|
||||
|
||||
<p><table border="0" id="toc"><tr><td align="center">
|
||||
<b>Table of contents</b></td></tr><tr id='tocinside'><td>
|
||||
<div style="margin-bottom:0px;">
|
||||
<A CLASS="internal" HREF="#Sockets">1 Sockets</A><BR>
|
||||
</div>
|
||||
<div style="margin-bottom:0px;">
|
||||
<A CLASS="internal" HREF="#Tunnels">2 Tunnels</A><BR>
|
||||
</div>
|
||||
<div style="margin-left:2em;">
|
||||
<A CLASS="internal" HREF="#Tunnel_Server">2.1 Tunnel Server</A><BR>
|
||||
|
||||
<A CLASS="internal" HREF="#Tunnel_Client">2.2 Tunnel Client</A><BR>
|
||||
</div>
|
||||
<div style="margin-bottom:0px;">
|
||||
<A CLASS="internal" HREF="#Errors">3 Errors</A><BR>
|
||||
</div>
|
||||
<div style="margin-bottom:0px;">
|
||||
<A CLASS="internal" HREF="#Constants">4 Constants</A><BR>
|
||||
</div>
|
||||
</td></tr></table><P>
|
||||
<h2><a name="Sockets"> Sockets </a></h2>
|
||||
|
||||
<p>
|
||||
|
||||
<strong>socket</strong>(session, type, samaddr='127.0.0.1:7656', **kwargs)
|
||||
<ul ><pre>
|
||||
Create a new socket. Argument session should be a session
|
||||
name -- if the name has not yet been used, an I2P
|
||||
Destination will be created for it, otherwise, the
|
||||
existing Destination will be re-used. An empty session
|
||||
string causes a transient session to be created. Argument
|
||||
type is one of SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW.
|
||||
|
||||
I2P configuration keyword arguments:
|
||||
|
||||
* in_depth - depth of incoming tunnel (default 2)
|
||||
* out_depth - depth of outgoing tunnel (default 2)
|
||||
|
||||
A single session may be shared by more than one socket, if
|
||||
the sockets are the same type, and if the sockets are
|
||||
created within the same Python process. The socket
|
||||
objects are multithread-safe.
|
||||
|
||||
Examples:
|
||||
a = i2p.socket('Alice', i2p.SOCK_STREAM)
|
||||
b = i2p.socket('Bob', i2p.SOCK_DGRAM,
|
||||
in_depth=2, out_depth=5)
|
||||
|
||||
The created object behaves identically to a socket from
|
||||
module socket, with the following exceptions:
|
||||
|
||||
* I2P Destinations are used as address arguments [1].
|
||||
* bind is a no-op: sockets are always bound.
|
||||
* send* methods send all data and are non-blocking.
|
||||
|
||||
A given session name can only be open in a single Python
|
||||
program at a time. If you need to overcome this
|
||||
limitation, consider patching I2P.
|
||||
|
||||
[1]. Alternatively, a host name can be used as an address.
|
||||
It will be resolved using hosts.txt.
|
||||
|
||||
For details on how to use socket objects, see
|
||||
http://www.python.org/doc/current/lib/socket-objects.html
|
||||
|
||||
See the examples directory for code examples.
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>socket()</strong> object properties:
|
||||
<ul >
|
||||
|
||||
<pre> dest - Local I2P Destination of socket
|
||||
session - Session name
|
||||
type - Socket type: SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW.
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>poll</strong>()
|
||||
|
||||
<ul >
|
||||
|
||||
<pre> Returns a polling object. Works on SAM sockets and Python sockets.
|
||||
See <a href='http://www.python.org/doc/current/lib/module-select.html' class='printable' title="http://www.python.org/doc/current/lib/module-select.html">select.poll()</a> in the Python library for more information.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
<strong>resolve</strong>(host, samaddr='127.0.0.1:7656')
|
||||
<ul >
|
||||
|
||||
<pre> Resolve I2P host name --> I2P Destination.
|
||||
Returns the same string if host is already a Destination.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
<strong>select</strong>(readlist, writelist, errlist, timeout=None)
|
||||
<ul >
|
||||
|
||||
<pre> Performs a select call. Works on SAM sockets and Python sockets.
|
||||
See <a href='http://www.python.org/doc/current/lib/module-select.html' class='printable' title="http://www.python.org/doc/current/lib/module-select.html">select.select()</a> in the Python library for more information.
|
||||
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="Tunnels"> Tunnels </a></h2>
|
||||
|
||||
<p>
|
||||
Tunnels allow stream sockets to be joined, so that connections to a listening socket are relayed to one or more sending sockets. This allows an ordinary web server to be exposed as an I2P Destination, or an I2P Destination to be bound as a local port, and so on.
|
||||
|
||||
<p>
|
||||
class <strong>Tunnel</strong>(self, receive, make_send, nconnect=-1, timeout=60.0)
|
||||
<ul ><pre>
|
||||
A Tunnel relays connections from a 'receive' socket to one
|
||||
or more 'send' sockets. The receive socket must be bound
|
||||
and listening. For each incoming connection, a new send
|
||||
socket is created by calling make_send(). Data is then
|
||||
exchanged between the created streams until one socket is
|
||||
closed. nconnect is the maximum number of simultaneous
|
||||
connections (-1 for infinite), and timeout is the time that
|
||||
a single connection can last for (None allows a connection
|
||||
to last forever).
|
||||
|
||||
Sockets must accept stream traffic and support the Python
|
||||
socket interface. A separate daemonic thread is created to
|
||||
manage the tunnel. For high performance, make_send() should
|
||||
make a socket and connect in non-blocking mode (you should
|
||||
catch and discard the sam.BlockError or socket.error due to
|
||||
executing connect on a non-blocking socket).
|
||||
|
||||
Security Note:
|
||||
A firewall is needed to maintain the end user's anonymity.
|
||||
An attacker could keep a tunnel socket open by pinging it
|
||||
regularly. The accepted sockets from 'receive' must prevent
|
||||
this by closing down eventually.
|
||||
|
||||
Socket errors do not cause the Tunnel to shut down.
|
||||
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
<strong>close</strong>()
|
||||
<ul >
|
||||
|
||||
<pre> Close all connections made for this tunnel.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
|
||||
<h3><a name="Tunnel_Server"> Tunnel Server </a></h3>
|
||||
|
||||
<p>
|
||||
class <strong>TunnelServer</strong>(session, port, samaddr='127.0.0.1:7656', nconnect=-1, timeout=None, **kwargs)
|
||||
<ul ><pre>
|
||||
Tunnels incoming SAM streams --> localhost:port.
|
||||
|
||||
nconnect and timeout are the maximum number of connections
|
||||
and maximum time per connection. All other arguments are
|
||||
passed to sam.socket(). This call blocks until the tunnel
|
||||
is ready.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
<strong>TunnelServer</strong> properties:
|
||||
|
||||
<ul ><pre>
|
||||
dest - I2P Destination of server.
|
||||
session - Session name for server.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
|
||||
<h3><a name="Tunnel_Client"> Tunnel Client </a></h3>
|
||||
|
||||
<p>
|
||||
class <strong>TunnelClient</strong>(session, port, dest, samaddr='127.0.0.1:7656', nconnect=-1, timeout=None, **kwargs)
|
||||
<ul ><pre>
|
||||
|
||||
Derived from Tunnel.
|
||||
Tunnels localhost:port --> I2P Destination dest.
|
||||
|
||||
A session named 'session' is created locally, for purposes
|
||||
of routing to 'dest'. nconnect and timeout are the maximum
|
||||
number of connections and maximum time per connection. All
|
||||
other arguments are passed to sam.socket(). This call blocks
|
||||
until the tunnel is ready.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
<strong>TunnelClient</strong> properties:
|
||||
<ul ><pre>
|
||||
dest - Local Destination used for routing.
|
||||
remotedest - Remote Destination.
|
||||
session - Session name for local Destination.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="Errors"> Errors </a></h2>
|
||||
|
||||
<p>
|
||||
class <strong>Error</strong>(i2p.Error)
|
||||
<ul ><pre>
|
||||
Base class for all SAM errors.
|
||||
</pre>
|
||||
</ul >
|
||||
class <strong>BlockError</strong>(Error)
|
||||
|
||||
<ul ><pre>
|
||||
Socket call would have blocked.
|
||||
</pre>
|
||||
</ul >
|
||||
class <strong>ClosedError</strong>(Error)
|
||||
<ul ><pre>
|
||||
A command was used on a socket that closed gracefully.
|
||||
</pre>
|
||||
</ul >
|
||||
class <strong>NetworkError</strong>(Error)
|
||||
<ul ><pre>
|
||||
|
||||
Network error occurred within I2P.
|
||||
|
||||
The error object is a 2-tuple: (errtag, errdesc).
|
||||
errtag is a SAM error string,
|
||||
errdesc is a human readable error description.
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="Constants"> Constants </a></h2>
|
||||
|
||||
<p>
|
||||
<strong>Socket types</strong>
|
||||
<ul ><pre>
|
||||
SOCK_STREAM = 1
|
||||
SOCK_DGRAM = 2
|
||||
SOCK_RAW = 3
|
||||
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>Packet sizes</strong>
|
||||
<ul ><pre>
|
||||
MAX_DGRAM = 31744 # Maximum size for datagram packet
|
||||
MAX_RAW = 32768 # Maximum size for raw packet
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>Flags for recv()</strong>
|
||||
<ul ><pre>
|
||||
MSG_DONTWAIT = 128 # Don't block
|
||||
MSG_PEEK = 2 # Peek at incoming data
|
||||
MSG_WAITALL = 64 # Wait for all data or error
|
||||
</pre>
|
||||
</ul >
|
||||
<strong>Polling flags</strong>
|
||||
|
||||
<ul ><pre>
|
||||
POLLIN = 1
|
||||
POLLOUT = 4
|
||||
POLLERR = 8
|
||||
POLLHUP = 16
|
||||
POLLNVAL = 32
|
||||
POLLPRI = 1
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
</em><!-- Time since request: 0.86 secs. -->
|
||||
</body></html>
|
76
apps/sam/python/doc/guide/index.html
Normal file
76
apps/sam/python/doc/guide/index.html
Normal file
@ -0,0 +1,76 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>Main Page - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>Main Page</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'>
|
||||
<strong>Python-I2P</strong> is a Python interface to <a href='http://www.i2p.net' class='printable' title="http://www.i2p.net">I2P</a>.
|
||||
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="Quick_Start"> Quick Start </a></h2>
|
||||
|
||||
<p>
|
||||
Install:
|
||||
|
||||
<p>
|
||||
<ul ><pre>
|
||||
python setup.py install
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
Use:
|
||||
|
||||
<p>
|
||||
|
||||
<ul ><pre>
|
||||
>>> from i2p import sam
|
||||
>>> s = sam.socket('Alice', sam.SOCK_STREAM)
|
||||
>>> s.connect('duck.i2p')
|
||||
>>> s.send('GET / HTTP/1.0\r\n\r\n')
|
||||
>>> s.recv(1000)
|
||||
(HTTP response from duck.i2p)
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="User's_Guide"> User's Guide </a></h2>
|
||||
|
||||
<p>
|
||||
The following modules are available:
|
||||
|
||||
<p>
|
||||
<ul >
|
||||
|
||||
<pre> <a href="./i2p.html" class='printable' title ="User's Guide:i2p">i2p</a> (Container package)
|
||||
<a href="./i2p.sam.html" class='printable' title ="User's Guide:i2p.sam">i2p.sam</a> (Send and receive across the I2P network)
|
||||
<a href="./i2p.eep.html" class='printable' title ="User's Guide:i2p.eep">i2p.eep</a> (Retrieve eepsites)
|
||||
<a href="./i2p.router.html" class='printable' title ="User's Guide:i2p.router">i2p.router</a> (Manage the I2P router)
|
||||
|
||||
</pre>
|
||||
</ul >
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
</em><!-- Time since request: 0.78 secs. -->
|
||||
</body></html>
|
37
apps/sam/python/doc/guide/samproxy.html
Normal file
37
apps/sam/python/doc/guide/samproxy.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="en"><head><title>SAM proxy - Wikipedia</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel="shortcut icon" href="/favicon.ico">
|
||||
<script type="text/javascript" src="/~barnesc/wiki/stylesheets/wikibits.js"></script>
|
||||
<style type='text/css'><!--
|
||||
@import url("/~barnesc/wiki/stylesheets/wikiprintable.css");
|
||||
/*/*/
|
||||
a.new, #quickbar a.new { color: #CC2200; }
|
||||
#quickbar { position: absolute; top: 4px; left: 4px; border-right: 1px solid gray; }
|
||||
#article { margin-left: 152px; margin-right: 4px; }
|
||||
/* */
|
||||
//--></style>
|
||||
</head>
|
||||
|
||||
<body bgcolor='#FFFFFF' onload=''>
|
||||
<h1 class='pagetitle'>SAM proxy</h1><p class='subtitle'>From Python-I2P.
|
||||
|
||||
|
||||
<div class='bodytext'>
|
||||
A <strong>SAM proxy</strong> is run by the I2P router. The proxy allows streams, datagrams, and raw packets to be sent through the I2P network. A client application uses a telnet-like session to communicate with the proxy. In this way, the core features of the I2P library can be used by any language.
|
||||
|
||||
|
||||
<p>
|
||||
The protocol used for SAM is described in <a href='http://dev.i2p.net/pipermail/i2p/2004-July/000353.html' class='printable' title="http://dev.i2p.net/pipermail/i2p/2004-July/000353.html">SAM 1.0</a>.
|
||||
|
||||
<p>
|
||||
In practice, a <em>SAM library</em> is usually written, so that client applications do not need to use the low-level SAM commands.
|
||||
|
||||
<p>
|
||||
</div>
|
||||
<p><em>
|
||||
|
||||
</em><!-- Time since request: 0.77 secs. -->
|
||||
</body></html>
|
5
apps/sam/python/doc/guide/wiki/eeproxy.txt
Normal file
5
apps/sam/python/doc/guide/wiki/eeproxy.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Title: Eeproxy
|
||||
|
||||
The '''Eeproxy''' is run by the I2P router. The proxy is normally used for web browsers, as a means of accessing eepsites.
|
||||
|
||||
The eeproxy is usually available at http://127.0.0.1:4444/.
|
18
apps/sam/python/doc/guide/wiki/i2p.eep.txt
Normal file
18
apps/sam/python/doc/guide/wiki/i2p.eep.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Title: User's Guide:i2p.eep
|
||||
|
||||
Module <code>i2p.eep</code> allows Python programs to access the [[Eeproxy]].
|
||||
|
||||
With this module, a program can easily download eepsites.
|
||||
|
||||
== Functions ==
|
||||
|
||||
'''urlopen'''(url, eepaddr='127.0.0.1:4444')
|
||||
<ul>
|
||||
Like urllib2.urlopen(url), but only works for eep-sites.
|
||||
Example: f = urlopen('http://duck.i2p/index.html')
|
||||
</ul>
|
||||
'''urlget'''(url, eepaddr='127.0.0.1:4444')
|
||||
<ul>
|
||||
Get contents of an eepsite.
|
||||
Example: urlget('http://duck.i2p/').
|
||||
</ul>
|
51
apps/sam/python/doc/guide/wiki/i2p.router.txt
Normal file
51
apps/sam/python/doc/guide/wiki/i2p.router.txt
Normal file
@ -0,0 +1,51 @@
|
||||
Title: User's Guide:i2p.router
|
||||
|
||||
Module <code>i2p.router</code> allows Python programs to control the I2P router.
|
||||
|
||||
== Functions ==
|
||||
|
||||
'''check'''(dir=None)
|
||||
<ul><pre>
|
||||
Checks whether a locally installed router is running. Does
|
||||
nothing if successful, otherwise raises i2p.RouterError.
|
||||
|
||||
An I2P installation is located by using find(dir).
|
||||
The router.config file is parsed for 'router.adminPort'.
|
||||
This port is queried to determine whether the router is
|
||||
running.
|
||||
</pre></ul>
|
||||
'''find'''(dir=None)
|
||||
<ul><pre>
|
||||
Find the absolute path to a locally installed I2P router.
|
||||
|
||||
An I2P installation is located by looking in the
|
||||
environment I2P, then in PATH, then in the dir argument
|
||||
given to the function. It looks for startRouter.sh or
|
||||
startRouter.bat. Raises ValueError if an I2P installation
|
||||
could not be located.
|
||||
</pre></ul>
|
||||
'''start'''(dir=None, hidden=False)
|
||||
<ul><pre>
|
||||
Start a locally installed I2P router. Does nothing if
|
||||
the router has already been started.
|
||||
|
||||
An I2P installation is located by using find(dir).
|
||||
|
||||
If hidden is True, do not show a terminal for the router.
|
||||
</pre></ul>
|
||||
'''stop'''(dir=None, force=False)
|
||||
<ul><pre>
|
||||
Stop a locally installed I2P router, if it was started by
|
||||
the current Python program. If force is True, stop the
|
||||
router even if it was started by another process. Do nothing
|
||||
if force is False and the router was started by another program.
|
||||
|
||||
The file 'router.config' is located using the same search
|
||||
process used for find(dir). It is parsed for
|
||||
'router.shutdownPassword' and 'router.adminPort'. The
|
||||
router is shut down through the admin port.
|
||||
|
||||
Raises i2p.RouterError if the I2P router is running but cannot
|
||||
be stopped. You must uncomment the
|
||||
'router.shutdownPassword' line for this command to work.
|
||||
</pre></ul>
|
202
apps/sam/python/doc/guide/wiki/i2p.sam.txt
Normal file
202
apps/sam/python/doc/guide/wiki/i2p.sam.txt
Normal file
@ -0,0 +1,202 @@
|
||||
Title: User's Guide:i2p.sam
|
||||
|
||||
Module <code>i2p.sam</code> allows Python programs to access the [[SAM proxy]].
|
||||
|
||||
With this module, a program can send stream data, datagrams, and raw packets across the I2P network.
|
||||
|
||||
== Sockets ==
|
||||
|
||||
'''socket'''(session, type, samaddr='127.0.0.1:7656', **kwargs)
|
||||
<ul><pre>
|
||||
Create a new socket. Argument session should be a session
|
||||
name -- if the name has not yet been used, an I2P
|
||||
Destination will be created for it, otherwise, the
|
||||
existing Destination will be re-used. An empty session
|
||||
string causes a transient session to be created. Argument
|
||||
type is one of SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW.
|
||||
|
||||
I2P configuration keyword arguments:
|
||||
|
||||
* in_depth - depth of incoming tunnel (default 2)
|
||||
* out_depth - depth of outgoing tunnel (default 2)
|
||||
|
||||
A single session may be shared by more than one socket, if
|
||||
the sockets are the same type, and if the sockets are
|
||||
created within the same Python process. The socket
|
||||
objects are multithread-safe.
|
||||
|
||||
Examples:
|
||||
a = i2p.socket('Alice', i2p.SOCK_STREAM)
|
||||
b = i2p.socket('Bob', i2p.SOCK_DGRAM,
|
||||
in_depth=2, out_depth=5)
|
||||
|
||||
The created object behaves identically to a socket from
|
||||
module socket, with the following exceptions:
|
||||
|
||||
* I2P Destinations are used as address arguments [1].
|
||||
* bind is a no-op: sockets are always bound.
|
||||
* send* methods send all data and are non-blocking.
|
||||
|
||||
A given session name can only be open in a single Python
|
||||
program at a time. If you need to overcome this
|
||||
limitation, consider patching I2P.
|
||||
|
||||
[1]. Alternatively, a host name can be used as an address.
|
||||
It will be resolved using hosts.txt.
|
||||
|
||||
For details on how to use socket objects, see
|
||||
http://www.python.org/doc/current/lib/socket-objects.html
|
||||
|
||||
See the examples directory for code examples.
|
||||
</pre></ul>
|
||||
'''socket()''' object properties:
|
||||
<ul>
|
||||
dest - Local I2P Destination of socket
|
||||
session - Session name
|
||||
type - Socket type: SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW.
|
||||
</ul>
|
||||
'''poll'''()
|
||||
<ul>
|
||||
Returns a polling object. Works on SAM sockets and Python sockets.
|
||||
See [http://www.python.org/doc/current/lib/module-select.html select.poll()] in the Python library for more information.
|
||||
</ul>
|
||||
|
||||
'''resolve'''(host, samaddr='127.0.0.1:7656')
|
||||
<ul>
|
||||
Resolve I2P host name --> I2P Destination.
|
||||
Returns the same string if host is already a Destination.
|
||||
</ul>
|
||||
|
||||
'''select'''(readlist, writelist, errlist, timeout=None)
|
||||
<ul>
|
||||
Performs a select call. Works on SAM sockets and Python sockets.
|
||||
See [http://www.python.org/doc/current/lib/module-select.html select.select()] in the Python library for more information.
|
||||
</ul>
|
||||
|
||||
== Tunnels ==
|
||||
|
||||
Tunnels allow stream sockets to be joined, so that connections to a listening socket are relayed to one or more sending sockets. This allows an ordinary web server to be exposed as an I2P Destination, or an I2P Destination to be bound as a local port, and so on.
|
||||
|
||||
class '''Tunnel'''(self, receive, make_send, nconnect=-1, timeout=60.0)
|
||||
<ul><pre>
|
||||
A Tunnel relays connections from a 'receive' socket to one
|
||||
or more 'send' sockets. The receive socket must be bound
|
||||
and listening. For each incoming connection, a new send
|
||||
socket is created by calling make_send(). Data is then
|
||||
exchanged between the created streams until one socket is
|
||||
closed. nconnect is the maximum number of simultaneous
|
||||
connections (-1 for infinite), and timeout is the time that
|
||||
a single connection can last for (None allows a connection
|
||||
to last forever).
|
||||
|
||||
Sockets must accept stream traffic and support the Python
|
||||
socket interface. A separate daemonic thread is created to
|
||||
manage the tunnel. For high performance, make_send() should
|
||||
make a socket and connect in non-blocking mode (you should
|
||||
catch and discard the sam.BlockError or socket.error due to
|
||||
executing connect on a non-blocking socket).
|
||||
|
||||
Security Note:
|
||||
A firewall is needed to maintain the end user's anonymity.
|
||||
An attacker could keep a tunnel socket open by pinging it
|
||||
regularly. The accepted sockets from 'receive' must prevent
|
||||
this by closing down eventually.
|
||||
|
||||
Socket errors do not cause the Tunnel to shut down.
|
||||
</pre></ul>
|
||||
|
||||
'''close'''()
|
||||
<ul>
|
||||
Close all connections made for this tunnel.
|
||||
</ul>
|
||||
|
||||
=== Tunnel Server ===
|
||||
|
||||
class '''TunnelServer'''(session, port, samaddr='127.0.0.1:7656', nconnect=-1, timeout=None, **kwargs)
|
||||
<ul><pre>
|
||||
Tunnels incoming SAM streams --> localhost:port.
|
||||
|
||||
nconnect and timeout are the maximum number of connections
|
||||
and maximum time per connection. All other arguments are
|
||||
passed to sam.socket(). This call blocks until the tunnel
|
||||
is ready.
|
||||
</pre></ul>
|
||||
|
||||
'''TunnelServer''' properties:
|
||||
<ul><pre>
|
||||
dest - I2P Destination of server.
|
||||
session - Session name for server.
|
||||
</pre></ul>
|
||||
|
||||
=== Tunnel Client ===
|
||||
|
||||
class '''TunnelClient'''(session, port, dest, samaddr='127.0.0.1:7656', nconnect=-1, timeout=None, **kwargs)
|
||||
<ul><pre>
|
||||
Derived from Tunnel.
|
||||
Tunnels localhost:port --> I2P Destination dest.
|
||||
|
||||
A session named 'session' is created locally, for purposes
|
||||
of routing to 'dest'. nconnect and timeout are the maximum
|
||||
number of connections and maximum time per connection. All
|
||||
other arguments are passed to sam.socket(). This call blocks
|
||||
until the tunnel is ready.
|
||||
</pre></ul>
|
||||
|
||||
'''TunnelClient''' properties:
|
||||
<ul><pre>
|
||||
dest - Local Destination used for routing.
|
||||
remotedest - Remote Destination.
|
||||
session - Session name for local Destination.
|
||||
</pre></ul>
|
||||
|
||||
== Errors ==
|
||||
|
||||
class '''Error'''(i2p.Error)
|
||||
<ul><pre>
|
||||
Base class for all SAM errors.
|
||||
</pre></ul>
|
||||
class '''BlockError'''(Error)
|
||||
<ul><pre>
|
||||
Socket call would have blocked.
|
||||
</pre></ul>
|
||||
class '''ClosedError'''(Error)
|
||||
<ul><pre>
|
||||
A command was used on a socket that closed gracefully.
|
||||
</pre></ul>
|
||||
class '''NetworkError'''(Error)
|
||||
<ul><pre>
|
||||
Network error occurred within I2P.
|
||||
|
||||
The error object is a 2-tuple: (errtag, errdesc).
|
||||
errtag is a SAM error string,
|
||||
errdesc is a human readable error description.
|
||||
</pre></ul>
|
||||
|
||||
== Constants ==
|
||||
|
||||
'''Socket types'''
|
||||
<ul><pre>
|
||||
SOCK_STREAM = 1
|
||||
SOCK_DGRAM = 2
|
||||
SOCK_RAW = 3
|
||||
</pre></ul>
|
||||
'''Packet sizes'''
|
||||
<ul><pre>
|
||||
MAX_DGRAM = 31744 # Maximum size for datagram packet
|
||||
MAX_RAW = 32768 # Maximum size for raw packet
|
||||
</pre></ul>
|
||||
'''Flags for recv()'''
|
||||
<ul><pre>
|
||||
MSG_DONTWAIT = 128 # Don't block
|
||||
MSG_PEEK = 2 # Peek at incoming data
|
||||
MSG_WAITALL = 64 # Wait for all data or error
|
||||
</pre></ul>
|
||||
'''Polling flags'''
|
||||
<ul><pre>
|
||||
POLLIN = 1
|
||||
POLLOUT = 4
|
||||
POLLERR = 8
|
||||
POLLHUP = 16
|
||||
POLLNVAL = 32
|
||||
POLLPRI = 1
|
||||
</pre></ul>
|
22
apps/sam/python/doc/guide/wiki/i2p.txt
Normal file
22
apps/sam/python/doc/guide/wiki/i2p.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Title: User's Guide:i2p
|
||||
|
||||
Package <code>i2p</code> is a container package for more specific modules.
|
||||
|
||||
It exports the following names:
|
||||
<ul>
|
||||
[[:User's Guide:i2p.sam|sam]]
|
||||
[[:User's Guide:i2p.eep|eep]]
|
||||
[[:User's Guide:i2p.router|router]]
|
||||
[[:User's Guide:i2p#Error|Error]]
|
||||
[[:User's Guide:i2p#RouterError|RouterError]]
|
||||
</ul>
|
||||
|
||||
class '''Error'''(Exception):
|
||||
<ul>
|
||||
Base class for all I2P errors.
|
||||
</ul>
|
||||
|
||||
class '''RouterError'''(Error):
|
||||
<ul>
|
||||
Could not connect to router.
|
||||
</ul>
|
33
apps/sam/python/doc/guide/wiki/index.txt
Normal file
33
apps/sam/python/doc/guide/wiki/index.txt
Normal file
@ -0,0 +1,33 @@
|
||||
Title: Main Page
|
||||
|
||||
'''Python-I2P''' is a Python interface to [http://www.i2p.net I2P].
|
||||
|
||||
== Quick Start ==
|
||||
|
||||
Install:
|
||||
|
||||
<ul><pre>
|
||||
python setup.py install
|
||||
</pre></ul>
|
||||
|
||||
Use:
|
||||
|
||||
<ul><pre>
|
||||
>>> from i2p import sam
|
||||
>>> s = sam.socket('Alice', sam.SOCK_STREAM)
|
||||
>>> s.connect('duck.i2p')
|
||||
>>> s.send('GET / HTTP/1.0\r\n\r\n')
|
||||
>>> s.recv(1000)
|
||||
(HTTP response from duck.i2p)
|
||||
</pre></ul>
|
||||
|
||||
== User's Guide ==
|
||||
|
||||
The following modules are available:
|
||||
|
||||
<ul>
|
||||
[[:User's Guide:i2p|i2p]] (Container package)
|
||||
[[:User's Guide:i2p.sam|i2p.sam]] (Send and receive across the I2P network)
|
||||
[[:User's Guide:i2p.eep|i2p.eep]] (Retrieve eepsites)
|
||||
[[:User's Guide:i2p.router|i2p.router]] (Manage the I2P router)
|
||||
</ul>
|
18
apps/sam/python/doc/guide/wiki/readme.txt
Normal file
18
apps/sam/python/doc/guide/wiki/readme.txt
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
The documentation was created by using MediaWiki software.
|
||||
|
||||
This directory houses the wiki text sources.
|
||||
|
||||
Feel free to move to any other documentation system, if
|
||||
it is efficient and easy to maintain.
|
||||
|
||||
Ideally, one could patch pydoc to export only certain
|
||||
names, in a certain order, like so:
|
||||
|
||||
__pydoc__ = ['f', 'g'] # f() and g() documented in order
|
||||
|
||||
This could proceed recursively for all namespaces.
|
||||
|
||||
Combine this with a second patch to make pydoc create
|
||||
nice CSS, and this whole guide could be generated
|
||||
directly from the sources.
|
7
apps/sam/python/doc/guide/wiki/samproxy.txt
Normal file
7
apps/sam/python/doc/guide/wiki/samproxy.txt
Normal file
@ -0,0 +1,7 @@
|
||||
Title: SAM proxy
|
||||
|
||||
A '''SAM proxy''' is run by the I2P router. The proxy allows streams, datagrams, and raw packets to be sent through the I2P network. A client application uses a telnet-like session to communicate with the proxy. In this way, the core features of the I2P library can be used by any language.
|
||||
|
||||
The protocol used for SAM is described in [http://dev.i2p.net/pipermail/i2p/2004-July/000353.html SAM 1.0].
|
||||
|
||||
In practice, a ''SAM library'' is usually written, so that client applications do not need to use the low-level SAM commands.
|
14
apps/sam/python/doc/index.html
Normal file
14
apps/sam/python/doc/index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body bgcolor=#ffffff text=#000000 link=#0000ff alink=#0000ff vlink=#0000ff>
|
||||
|
||||
<h1>Python-I2P</h1>
|
||||
|
||||
Documentation:
|
||||
|
||||
<ul>
|
||||
<li><a href="./guide/index.html">User's Guide</a><br>
|
||||
<li><a href="./pydoc/i2p.html">Pydoc Documentation</a><br>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
40
apps/sam/python/doc/pydoc/i2p.eep.html
Normal file
40
apps/sam/python/doc/pydoc/i2p.eep.html
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Python: module i2p.eep</title>
|
||||
</head><body bgcolor="#f0f0f8">
|
||||
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
|
||||
<tr bgcolor="#7799ee">
|
||||
<td valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="i2p.html"><font color="#ffffff">i2p</font></a>.eep</strong></big></big></font></td
|
||||
><td align=right valign=bottom
|
||||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///D|/code/i2p/i2p/eep.py">d:\code\i2p\i2p\eep.py</a></font></td></tr></table>
|
||||
<p><tt>Eeproxy Python API</tt></p>
|
||||
<p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#aa55cc">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#fffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="urllib2.html">urllib2</a><br>
|
||||
</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#eeaa77">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#eeaa77"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><dl><dt><a name="-urlget"><strong>urlget</strong></a>(url, eepaddr<font color="#909090">='127.0.0.1:4444'</font>)</dt><dd><tt>Get contents of an eepsite.<br>
|
||||
Example: <a href="#-urlget">urlget</a>('<a href="http://duck.i2p/">http://duck.i2p/</a>').</tt></dd></dl>
|
||||
<dl><dt><a name="-urlopen"><strong>urlopen</strong></a>(url, eepaddr<font color="#909090">='127.0.0.1:4444'</font>)</dt><dd><tt>Like urllib2.<a href="#-urlopen">urlopen</a>(url), but only works for eep-sites.<br>
|
||||
Example: f = <a href="#-urlopen">urlopen</a>('<a href="http://duck.i2p/index.html">http://duck.i2p/index.html</a>')</tt></dd></dl>
|
||||
</td></tr></table><p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#55aa55">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#55aa55"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><strong>eepaddr</strong> = '127.0.0.1:4444'</td></tr></table>
|
||||
</body></html>
|
90
apps/sam/python/doc/pydoc/i2p.html
Normal file
90
apps/sam/python/doc/pydoc/i2p.html
Normal file
@ -0,0 +1,90 @@
|
||||
|
||||
<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Python: package i2p</title>
|
||||
</head><body bgcolor="#f0f0f8">
|
||||
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
|
||||
<tr bgcolor="#7799ee">
|
||||
<td valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>i2p</strong></big></big></font></td
|
||||
><td align=right valign=bottom
|
||||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:///D|/code/i2p/i2p/__init__.py">d:\code\i2p\i2p\__init__.py</a></font></td></tr></table>
|
||||
<p><tt>i2p -- I2P Python interface</tt></p>
|
||||
<p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#aa55cc">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="i2p.eep.html">eep</a><br>
|
||||
</td><td width="25%" valign=top><a href="i2p.router.html">router</a><br>
|
||||
</td><td width="25%" valign=top><a href="i2p.sam.html">sam</a><br>
|
||||
</td><td width="25%" valign=top><a href="i2p.samclasses.html">samclasses</a><br>
|
||||
</td></tr></table></td></tr></table><p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ee77aa">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><dl>
|
||||
<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>
|
||||
</font></dt><dd>
|
||||
<dl>
|
||||
<dt><font face="helvetica, arial"><a href="i2p.html#Error">Error</a>
|
||||
</font></dt><dd>
|
||||
<dl>
|
||||
<dt><font face="helvetica, arial"><a href="i2p.html#RouterError">RouterError</a>
|
||||
</font></dt></dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ffc8d8">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#000000" face="helvetica, arial"><a name="Error">class <strong>Error</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
|
||||
|
||||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
|
||||
<td colspan=2><tt>Base class for all I2P errors.<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
|
||||
<dl><dt><a name="Error-__getitem__"><strong>__getitem__</strong></a>(...)</dt></dl>
|
||||
|
||||
<dl><dt><a name="Error-__init__"><strong>__init__</strong></a>(...)</dt></dl>
|
||||
|
||||
<dl><dt><a name="Error-__str__"><strong>__str__</strong></a>(...)</dt></dl>
|
||||
|
||||
</td></tr></table> <p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ffc8d8">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#000000" face="helvetica, arial"><a name="RouterError">class <strong>RouterError</strong></a>(<a href="i2p.html#Error">Error</a>)</font></td></tr>
|
||||
|
||||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
|
||||
<td colspan=2><tt>Could not connect to router.<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%"><dl><dt>Method resolution order:</dt>
|
||||
<dd><a href="i2p.html#RouterError">RouterError</a></dd>
|
||||
<dd><a href="i2p.html#Error">Error</a></dd>
|
||||
<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
|
||||
</dl>
|
||||
<hr>
|
||||
Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
|
||||
<dl><dt><a name="RouterError-__getitem__"><strong>__getitem__</strong></a>(...)</dt></dl>
|
||||
|
||||
<dl><dt><a name="RouterError-__init__"><strong>__init__</strong></a>(...)</dt></dl>
|
||||
|
||||
<dl><dt><a name="RouterError-__str__"><strong>__str__</strong></a>(...)</dt></dl>
|
||||
|
||||
</td></tr></table></td></tr></table><p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#55aa55">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#55aa55"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><strong>__all__</strong> = ['Error', 'RouterError', 'sam', 'eep', 'router']</td></tr></table>
|
||||
</body></html>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user