mirror of https://github.com/PurpleI2P/i2pd.git
EinMByte
9 years ago
36 changed files with 1805 additions and 1222 deletions
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
set(BENCHMARK_SRC |
||||
"main.cpp" |
||||
) |
||||
|
||||
if(WITH_BENCHMARK) |
||||
add_executable(${BENCHMARK_NAME} ${BENCHMARK_SRC}) |
||||
target_link_libraries( |
||||
${BENCHMARK_NAME} ${CORE_NAME} ${DL_LIB} ${Boost_LIBRARIES} ${CRYPTO++_LIBRARIES} |
||||
${CMAKE_THREAD_LIBS_INIT} |
||||
) |
||||
install(TARGETS |
||||
${BENCHMARK_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} |
||||
) |
||||
endif() |
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
#include "crypto/Signature.h" |
||||
#include <cryptopp/osrng.h> |
||||
#include <iostream> |
||||
#include <chrono> |
||||
#include <functional> |
||||
|
||||
typedef std::function<void(CryptoPP::RandomNumberGenerator&, uint8_t*, uint8_t*)> KeyGenerator; |
||||
|
||||
template<class Verifier, class Signer> |
||||
void benchmark(std::size_t count, std::size_t public_key_size, std::size_t private_key_size, |
||||
std::size_t signature_size, KeyGenerator generator) |
||||
{ |
||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> TimePoint; |
||||
CryptoPP::AutoSeededRandomPool rng; |
||||
|
||||
uint8_t private_key[private_key_size] = {}; |
||||
uint8_t public_key[public_key_size] = {}; |
||||
|
||||
generator(rng, private_key, public_key); |
||||
|
||||
Verifier verifier(public_key); |
||||
Signer signer(private_key); |
||||
|
||||
uint8_t message[512] = {}; |
||||
uint8_t output[signature_size] = {}; |
||||
|
||||
std::chrono::nanoseconds sign_duration(0); |
||||
std::chrono::nanoseconds verify_duration(0); |
||||
|
||||
for(std::size_t i = 0; i < count; ++i) { |
||||
rng.GenerateBlock(message, 512); |
||||
TimePoint begin1 = std::chrono::high_resolution_clock::now(); |
||||
signer.Sign(rng, message, 512, output); |
||||
TimePoint end1 = std::chrono::high_resolution_clock::now(); |
||||
|
||||
sign_duration += std::chrono::duration_cast<std::chrono::nanoseconds>(end1 - begin1); |
||||
|
||||
TimePoint begin2 = std::chrono::high_resolution_clock::now(); |
||||
verifier.Verify(message, 512, output); |
||||
TimePoint end2 = std::chrono::high_resolution_clock::now(); |
||||
|
||||
verify_duration += std::chrono::duration_cast<std::chrono::nanoseconds>(end2 - begin2); |
||||
} |
||||
std::cout << "Conducted " << count << " experiments." << std::endl; |
||||
std::cout << "Total sign time: " << std::chrono::duration_cast<std::chrono::milliseconds>(sign_duration).count() << std::endl; |
||||
std::cout << "Total verify time: " << std::chrono::duration_cast<std::chrono::milliseconds>(verify_duration).count() << std::endl; |
||||
} |
||||
|
||||
|
||||
int main() |
||||
{ |
||||
using namespace i2p::crypto; |
||||
std::cout << "--------DSA---------" << std::endl; |
||||
benchmark<DSAVerifier, DSASigner>( |
||||
1000, DSA_PUBLIC_KEY_LENGTH, |
||||
DSA_PRIVATE_KEY_LENGTH, DSA_SIGNATURE_LENGTH, |
||||
&CreateDSARandomKeys |
||||
); |
||||
std::cout << "-----ECDSAP256------" << std::endl; |
||||
benchmark<ECDSAP256Verifier, ECDSAP256Signer>( |
||||
1000, ECDSAP256_KEY_LENGTH, |
||||
ECDSAP256_KEY_LENGTH, 64, |
||||
&CreateECDSAP256RandomKeys |
||||
); |
||||
std::cout << "-----ECDSAP384------" << std::endl; |
||||
benchmark<ECDSAP384Verifier, ECDSAP384Signer>( |
||||
1000, ECDSAP384_KEY_LENGTH, |
||||
ECDSAP384_KEY_LENGTH, 64, |
||||
&CreateECDSAP384RandomKeys |
||||
); |
||||
std::cout << "-----ECDSAP521------" << std::endl; |
||||
benchmark<ECDSAP521Verifier, ECDSAP521Signer>( |
||||
1000, ECDSAP521_KEY_LENGTH, |
||||
ECDSAP521_KEY_LENGTH, 64, |
||||
&CreateECDSAP521RandomKeys |
||||
); |
||||
std::cout << "-----EDDSA25519-----" << std::endl; |
||||
benchmark<EDDSA25519Verifier, EDDSA25519Signer>( |
||||
1000, EDDSA25519_PUBLIC_KEY_LENGTH, |
||||
EDDSA25519_PRIVATE_KEY_LENGTH, 64, |
||||
&CreateEDDSARandomKeys |
||||
); |
||||
} |
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIFVDCCAzwCCQC2r1XWYtqtAzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJY |
||||
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMwEQYDVQQKDApQdXJwbGUgSTJQ |
||||
MQ0wCwYDVQQLDARJMlBEMR8wHQYJKoZIhvcNAQkBFhBvcmlnbmFsQG1haWwuaTJw |
||||
MB4XDTE1MDIyMjEzNTgxOFoXDTI1MDIxOTEzNTgxOFowbDELMAkGA1UEBhMCWFgx |
||||
CzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKUHVycGxlIEkyUDEN |
||||
MAsGA1UECwwESTJQRDEfMB0GCSqGSIb3DQEJARYQb3JpZ25hbEBtYWlsLmkycDCC |
||||
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALp3D/gdvFjrMm+IE8tHZCWE |
||||
hQ6Pp0CCgCGDBC3WQFLqR98bqVPl4UwRG/MKY/LY7Woai06JNmGcpfw0LMoNnHxT |
||||
bvKtDRe/8kQdhdLHhgIkWKSbMvTAl7uUdV6FzsPgDR0x7scoFVWEhkF0wfmzGF2V |
||||
yr/WCBQejFPu69z03m5tRQ8Xjp2txWV45RawUmFu50bgbZvLCSLfTkIvxmfJzgPN |
||||
pJ3sPa/g7TBZl2uEiAu4uaEKvTuuzStOWCGgFaHYFVlTfFXTvmhFMqHfaidtzrlu |
||||
H35WGrmIWTDl6uGPC5QkSppvkj73rDj5aEyPzWMz5DN3YeECoVSchN+OJJCM6m7+ |
||||
rLFYXghVEp2h+T9O1GBRfcHlQ2E3CrWWvxhmK8dfteJmd501dyNX2paeuIg/aPFO |
||||
54/8m2r11uyF29hgY8VWLdXtqvwhKuK36PCzofEwDp9QQX8GRsEV4pZTrn4bDhGo |
||||
kb9BF7TZTqtL3uyiRmIyBXrNNiYlA1Xm4fyKRtxl0mrPaUXdgdnCt3KxOAJ8WM2B |
||||
7L/kk9U8C/nexHbMxIZfTap49XcUg5dxSO9kOBosIOcCUms8sAzBPDV2tWAByhYF |
||||
jI/Tutbd3F0+fvcmTcIFOlGbOxKgO2SfwXjv/44g/3LMK6IAMFB9UOc8KhnnJP0f |
||||
uAHvMXn1ahRs4pM1VizLAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAIOxdaXT+wfu |
||||
nv/+1hy5T4TlRMNNsuj79ROcy6Mp+JwMG50HjTc0qTlXh8C7nHybDJn4v7DA+Nyn |
||||
RxT0J5I+Gqn+Na9TaC9mLeX/lwe8/KomyhBWxjrsyWj1V6v/cLO924S2rtcfzMDm |
||||
l3SFh9YHM1KF/R9N1XYBwtMzr3bupWDnE1yycYp1F4sMLr5SMzMQ0svQpQEM2/y5 |
||||
kly8+eUzryhm+ag9x1686uEG5gxhQ1eHQoZEaClHUOsV+28+d5If7cqcYx9Hf5Tt |
||||
CiVjJQzdxBF+6GeiJtKxnLtevqlkbyIJt6Cm9/7YIy/ovRGF2AKSYN6oCwmZQ6i1 |
||||
8nRnFq5zE7O94m+GXconWZxy0wVqA6472HThMi7S+Tk/eLYen2ilGY+KCb9a0FH5 |
||||
5MOuWSoJZ8/HfW2VeQmL8EjhWm5F2ybg28wgXK4BOGR3jQi03Fsc+AFidnWxSKo0 |
||||
aiJoPgOsfyu8/fnCcAi07kSmjzUKIWskApgcpGQLNXHFK9mtg7+VA8esRnfLlKtP |
||||
tJf+nNAPY1sqHfGBzh7WWGWal5RGHF5nEm3ta3oiFF5sMKCJ6C87zVwFkEcRytGC |
||||
xOGmiG1O1RPrO5NG7rZUaQ4y1OKl2Y1H+nGONzZ3mvoAOvxEq6JtUnU2kZscpPlk |
||||
fpeOSDoGBYJGbIpzDreBDhxaZrwGq36k |
||||
-----END CERTIFICATE----- |
@ -0,0 +1,246 @@
@@ -0,0 +1,246 @@
|
||||
#include "HTTP.h" |
||||
#include <boost/algorithm/string.hpp> |
||||
#include <iostream> |
||||
#include <regex> |
||||
#include <fstream> |
||||
#include <boost/filesystem.hpp> |
||||
#include "Log.h" |
||||
|
||||
namespace i2p { |
||||
namespace util { |
||||
namespace http { |
||||
|
||||
void Request::parseRequestLine(const std::string& line) |
||||
{ |
||||
std::stringstream ss(line); |
||||
ss >> method; |
||||
ss >> uri; |
||||
} |
||||
|
||||
void Request::parseHeaderLine(const std::string& line) |
||||
{ |
||||
const std::size_t pos = line.find_first_of(':'); |
||||
headers[boost::trim_copy(line.substr(0, pos))] = boost::trim_copy(line.substr(pos + 1)); |
||||
} |
||||
|
||||
void Request::parseHeader(std::stringstream& ss) |
||||
{ |
||||
std::string line; |
||||
while(std::getline(ss, line) && !boost::trim_copy(line).empty()) |
||||
parseHeaderLine(line); |
||||
|
||||
has_header = boost::trim_copy(line).empty(); |
||||
if(!has_header) |
||||
header_part = line; |
||||
else |
||||
header_part = ""; |
||||
} |
||||
|
||||
void Request::setIsComplete() |
||||
{ |
||||
auto it = headers.find("Content-Length"); |
||||
if(it == headers.end()) { |
||||
// If Content-Length is not set, assume there is no more content
|
||||
// TODO: Support chunked transfer, or explictly reject it
|
||||
is_complete = true; |
||||
return; |
||||
} |
||||
const std::size_t length = std::stoi(it->second); |
||||
is_complete = content.size() >= length; |
||||
} |
||||
|
||||
Request::Request(const std::string& data) |
||||
{ |
||||
if(!data.empty()) |
||||
has_data = true; |
||||
|
||||
std::stringstream ss(data); |
||||
|
||||
std::string line; |
||||
std::getline(ss, line); |
||||
|
||||
// Assume the request line is always passed in one go
|
||||
parseRequestLine(line); |
||||
|
||||
parseHeader(ss); |
||||
|
||||
if(has_header && ss) { |
||||
const std::string current = ss.str(); |
||||
content = current.substr(ss.tellg()); |
||||
} |
||||
|
||||
if(has_header) |
||||
setIsComplete(); |
||||
} |
||||
|
||||
std::string Request::getMethod() const |
||||
{ |
||||
return method; |
||||
} |
||||
|
||||
std::string Request::getUri() const |
||||
{ |
||||
return uri; |
||||
} |
||||
|
||||
std::string Request::getHost() const |
||||
{ |
||||
return host; |
||||
} |
||||
|
||||
int Request::getPort() const |
||||
{ |
||||
return port; |
||||
} |
||||
|
||||
std::string Request::getHeader(const std::string& name) const |
||||
{ |
||||
return headers.at(name); |
||||
} |
||||
|
||||
std::string Request::getContent() const |
||||
{ |
||||
return content; |
||||
} |
||||
|
||||
bool Request::hasData() const |
||||
{ |
||||
return has_data; |
||||
} |
||||
|
||||
bool Request::isComplete() const |
||||
{ |
||||
return is_complete; |
||||
} |
||||
|
||||
void Request::clear() |
||||
{ |
||||
has_data = false; |
||||
has_header = false; |
||||
is_complete = false; |
||||
} |
||||
|
||||
void Request::update(const std::string& data) |
||||
{ |
||||
std::stringstream ss(header_part + data); |
||||
if(!has_header) |
||||
parseHeader(ss); |
||||
|
||||
if(has_header && ss) { |
||||
const std::string current = ss.str(); |
||||
content += current.substr(ss.tellg()); |
||||
} |
||||
|
||||
if(has_header) |
||||
setIsComplete(); |
||||
} |
||||
|
||||
Response::Response(int status, const std::string& content) |
||||
: status(status), content(content), headers() |
||||
{ |
||||
|
||||
} |
||||
|
||||
void Response::setHeader(const std::string& name, const std::string& value) |
||||
{ |
||||
headers[name] = value; |
||||
} |
||||
|
||||
std::string Response::toString() const |
||||
{ |
||||
std::stringstream ss; |
||||
ss << "HTTP/1.1 " << status << ' ' << getStatusMessage() << "\r\n"; |
||||
for(auto& pair : headers) |
||||
ss << pair.first << ": " << pair.second << "\r\n"; |
||||
ss << "\r\n" << content; |
||||
return ss.str(); |
||||
} |
||||
|
||||
std::string Response::getStatusMessage() const |
||||
{ |
||||
switch(status) { |
||||
case 105: |
||||
return "Name Not Resolved"; |
||||
case 200: |
||||
return "OK"; |
||||
case 400: |
||||
return "Bad Request"; |
||||
case 404: |
||||
return "Not Found"; |
||||
case 408: |
||||
return "Request Timeout"; |
||||
case 500: |
||||
return "Internal Server Error"; |
||||
case 502: |
||||
return "Not Implemented"; |
||||
case 504: |
||||
return "Gateway Timeout"; |
||||
default: |
||||
return std::string(); |
||||
} |
||||
} |
||||
|
||||
void Response::setContentLength() |
||||
{ |
||||
setHeader("Content-Length", std::to_string(content.size())); |
||||
} |
||||
|
||||
std::string preprocessContent(const std::string& content, const std::string& path) |
||||
{ |
||||
const boost::filesystem::path directory(path); // Given path is assumed to be clean
|
||||
|
||||
static const std::regex re( |
||||
"<\\!\\-\\-\\s*#include\\s+virtual\\s*\\=\\s*\"([^\"]*)\"\\s*\\-\\->" |
||||
); |
||||
|
||||
boost::system::error_code e; |
||||
|
||||
std::string result; |
||||
|
||||
std::smatch match; |
||||
auto it = content.begin(); |
||||
while(std::regex_search(it, content.end(), match, re)) { |
||||
const auto last = it; |
||||
std::advance(it, match.position()); |
||||
result.append(last, it); |
||||
std::advance(it, match.length()); |
||||
|
||||
// Read the contents of the included file
|
||||
std::ifstream ifs( |
||||
boost::filesystem::canonical(directory / std::string(match[1]), e).string(), |
||||
std::ios_base::in | std::ios_base::binary |
||||
); |
||||
if(e || !ifs) |
||||
continue; |
||||
|
||||
std::string data; |
||||
ifs.seekg(0, ifs.end); |
||||
data.resize(ifs.tellg()); |
||||
ifs.seekg(0, ifs.beg); |
||||
ifs.read(&data[0], data.size()); |
||||
|
||||
result += data; |
||||
} |
||||
|
||||
// Append all of the remaining content
|
||||
result.append(it, content.end()); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
std::string getMimeType(const std::string& filename) |
||||
{ |
||||
const std::string ext = filename.substr(filename.find_last_of(".")); |
||||
if(ext == ".css") |
||||
return "text/css"; |
||||
else if(ext == ".js") |
||||
return "text/javascript"; |
||||
else if(ext == ".html" || ext == ".htm") |
||||
return "text/html"; |
||||
else |
||||
return "application/octet-stream"; |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
#ifndef _HTTP_H__ |
||||
#define _HTTP_H__ |
||||
|
||||
#include <string> |
||||
#include <map> |
||||
#include <sstream> |
||||
|
||||
namespace i2p { |
||||
namespace util { |
||||
namespace http { |
||||
|
||||
class Request { |
||||
|
||||
void parseRequestLine(const std::string& line); |
||||
|
||||
void parseHeaderLine(const std::string& line); |
||||
|
||||
void parseHeader(std::stringstream& ss); |
||||
|
||||
void setIsComplete(); |
||||
public: |
||||
Request() = default; |
||||
|
||||
Request(const std::string& data); |
||||
|
||||
std::string getMethod() const; |
||||
|
||||
std::string getUri() const; |
||||
|
||||
std::string getHost() const; |
||||
|
||||
int getPort() const; |
||||
|
||||
/**
|
||||
* @throw std::out_of_range if no such header exists |
||||
*/ |
||||
std::string getHeader(const std::string& name) const; |
||||
|
||||
std::string getContent() const; |
||||
|
||||
bool hasData() const; |
||||
|
||||
bool isComplete() const; |
||||
|
||||
void clear(); |
||||
|
||||
void update(const std::string& data); |
||||
|
||||
private: |
||||
std::string header_part; |
||||
|
||||
std::string method; |
||||
std::string uri; |
||||
std::string host; |
||||
std::string content; |
||||
int port; |
||||
std::map<std::string, std::string> headers; |
||||
bool has_data; |
||||
bool has_header; |
||||
bool is_complete; |
||||
}; |
||||
|
||||
class Response { |
||||
public: |
||||
Response() = default; |
||||
|
||||
Response(int status, const std::string& content = ""); |
||||
|
||||
/**
|
||||
* @note overrides existing header values with the same name |
||||
*/ |
||||
void setHeader(const std::string& name, const std::string& value); |
||||
|
||||
std::string toString() const; |
||||
|
||||
/**
|
||||
* @return the message associated with the satus of this response, or the |
||||
* empty string if the status number is invalid |
||||
*/ |
||||
std::string getStatusMessage() const; |
||||
|
||||
void setContentLength(); |
||||
|
||||
private: |
||||
int status; |
||||
std::string content; |
||||
std::map<std::string, std::string> headers; |
||||
}; |
||||
|
||||
/**
|
||||
* Handle server side includes. |
||||
*/ |
||||
std::string preprocessContent(const std::string& content, const std::string& path); |
||||
|
||||
/**
|
||||
* @return the MIME type based on the extension of the given filename |
||||
*/ |
||||
std::string getMimeType(const std::string& filename); |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
#endif // _HTTP_H__
|
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<title>404 - Page not found</title> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<link rel="stylesheet" href="css/main.css"> |
||||
</head> |
||||
|
||||
|
||||
<body> |
||||
<div class="header"> |
||||
<h1>404 - Page not found</h1> |
||||
</div> |
||||
|
||||
<div class="content"> |
||||
<h2 class="content-subhead">The page you were looking for could not be found.</h2> |
||||
</div> |
||||
|
||||
<!--#include virtual="menu.html" --> |
||||
<!--#include virtual="footer.html" --> |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
body { |
||||
font-family: sans-serif; |
||||
margin: 0px; |
||||
padding: 0px; |
||||
} |
||||
|
||||
.header { |
||||
margin: 0px 150px; |
||||
text-align: center; |
||||
padding: 2.5em 2em 0px; |
||||
border-bottom: 1px solid #EEE; |
||||
} |
||||
|
||||
h1 { |
||||
color: #333; |
||||
font-weight: 300; |
||||
} |
||||
|
||||
h2 { |
||||
color: #ccc; |
||||
font-weight: 300; |
||||
} |
||||
|
||||
.content { |
||||
margin: 0px 150px auto; |
||||
padding: 0px 2em; |
||||
line-height: 1.6em; |
||||
} |
||||
|
||||
.content-subhead { |
||||
margin: 50px 0px 20px; |
||||
font-weight: 300; |
||||
color: #888; |
||||
} |
||||
|
||||
#menu { |
||||
width: 150px; |
||||
position: fixed; |
||||
top: 0px; |
||||
bottom: 0px; |
||||
z-index: 1000; |
||||
background: #191818 none repeat scroll 0% 0%; |
||||
overflow-y: auto; |
||||
display: block; |
||||
margin: 0px; |
||||
padding: 0px; |
||||
} |
||||
|
||||
.menu-heading { |
||||
background: #1f8dd6; |
||||
display: block; |
||||
padding: 10px; |
||||
color: white; |
||||
font-variant: small-caps; |
||||
font-size: 23px; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.menu-list { |
||||
list-style: none; |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
.menu-item { |
||||
padding: 0; |
||||
margin: 0; |
||||
padding: 10px; |
||||
} |
||||
|
||||
.menu-link { |
||||
text-decoration: none; |
||||
color: #ccc; |
||||
font-weight: bold; |
||||
font-size: 15px; |
||||
} |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
<div id="main"> |
||||
<noscript> |
||||
<div class="header"><h1>Please enable JavaScript!</h1></div> |
||||
</noscript> |
||||
</div> |
||||
|
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<title>Purple I2P 0.10.0 Webconsole</title> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<link rel="stylesheet" href="css/main.css"> |
||||
</head> |
||||
|
||||
<body> |
||||
<div class="header"> |
||||
<h1>I2P help</h1> |
||||
</div> |
||||
|
||||
<div class="content"> |
||||
<h2 class="content-subhead">Need help? Join us at IRC: #i2pd-dev at irc.freenode.net</h2> |
||||
<h2 class="content-subhead"> |
||||
<a href="https://github.com/PurpleI2P/i2pd">i2pd at GitHub</a> |
||||
</h2> |
||||
<h2 class="content-subhead"><a href="https://geti2p.net/en/">I2P Project</a> </h2> |
||||
</div> |
||||
|
||||
<!--#include virtual="menu.html" --> |
||||
<!--#include virtual="footer.html" --> |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,101 @@
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<title>Purple I2P 0.10.0 Webconsole</title> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<link rel="stylesheet" href="css/main.css"> |
||||
<script type="text/javascript" src="javascript/I2PControl.js"></script> |
||||
<script type="text/javascript"> |
||||
function updateRouterInfo(result, session) { |
||||
if(session.error) { |
||||
alert("Error: " + session.error["message"]); |
||||
return; |
||||
} |
||||
I2PControl.updateDocument({ |
||||
"version" : result["i2p.router.version"], |
||||
"status" : I2PControl.statusToString(result["i2p.router.net.status"]), |
||||
"uptime" : I2PControl.msToString(result["i2p.router.uptime"]), |
||||
"knownpeers" : result["i2p.router.netdb.knownpeers"], |
||||
"activepeers" : result["i2p.router.netdb.activepeers"], |
||||
"tunnels-participating" : result["i2p.router.net.tunnels.participating"], |
||||
"tunnels-successrate" : result["i2p.router.net.tunnels.creationsuccessrate"] + "%", |
||||
"bw-in" : result["i2p.router.net.bw.inbound.1s"], |
||||
"bw-out" : result["i2p.router.net.bw.outbound.1s"] |
||||
}); |
||||
|
||||
window.setTimeout(function() { requestRouterInfo(session); }, 5000); |
||||
} |
||||
|
||||
function requestRouterInfo(session) { |
||||
session.request("RouterInfo", { |
||||
"i2p.router.version" : "", |
||||
"i2p.router.net.status" : "", |
||||
"i2p.router.uptime" : "", |
||||
"i2p.router.netdb.knownpeers" : "", |
||||
"i2p.router.netdb.activepeers" : "", |
||||
"i2p.router.net.tunnels.participating" : "", |
||||
"i2p.router.net.tunnels.creationsuccessrate" : "", |
||||
"i2p.router.net.bw.inbound.1s" : "", |
||||
"i2p.router.net.bw.outbound.1s" : "" |
||||
}, updateRouterInfo); |
||||
} |
||||
|
||||
window.onload = function() { |
||||
var session = new I2PControl.Session("itoopie"); |
||||
session.start(function() { requestRouterInfo(session); }); |
||||
document.getElementById("shutdown").onclick = function() { |
||||
session.request("RouterManager", {"Shutdown" : ""}, function() {}); |
||||
this.disabled = true; |
||||
}; |
||||
document.getElementById("shutdown-graceful").onclick = function() { |
||||
session.request("RouterManager", {"ShutdownGraceful" : ""}, function() {}); |
||||
this.disabled = true; |
||||
}; |
||||
document.getElementById("reseed").onclick = function() { |
||||
session.request("RouterManager", {"Reseed" : ""}, function() {}); |
||||
this.disabled = true; |
||||
}; |
||||
}; |
||||
|
||||
</script> |
||||
</head> |
||||
|
||||
<body> |
||||
<div class="header"> |
||||
<h1>i2pd router console</h1> |
||||
<h2>Version: <span id="version"></span>, uptime: <span id="uptime"></span></h2> |
||||
<h2>Network status: <span id="status"></span></h2> |
||||
<p> |
||||
<button id="shutdown-graceful">graceful shutdown</button> |
||||
<button id="shutdown">force shutdown</button> |
||||
<button id="restart" disabled>restart</button> |
||||
<button id="reseed">reseed</button> |
||||
</p> |
||||
</div> |
||||
|
||||
<div class="content"> |
||||
<h2 class="content-subhead"> |
||||
Tunnels participating: <span id="tunnels-participating"></span> |
||||
</h2> |
||||
<h2 class="content-subhead"> |
||||
Tunnel create success rate: <span id="tunnels-successrate"></span> |
||||
</h2> |
||||
<h2 class="content-subhead"> |
||||
Active peers: <span id="activepeers"></span> |
||||
</h2> |
||||
<h2 class="content-subhead"> |
||||
Known peers: <span id="knownpeers"></span> |
||||
</h2> |
||||
<h2 class="content-subhead"> |
||||
Bandwidth: |
||||
in <span id="bw-in"></span> Bps / |
||||
out <span id="bw-out"></span> Bps |
||||
</h2> |
||||
</div> |
||||
|
||||
<!--#include virtual="menu.html" --> |
||||
<!--#include virtual="footer.html" --> |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
var I2PControl = I2PControl || {} |
||||
|
||||
I2PControl.Session = function(password) { |
||||
this.token = ""; |
||||
this.ready = false; |
||||
this.error = false; |
||||
this.password = password; |
||||
}; |
||||
|
||||
I2PControl.Session.prototype = { |
||||
|
||||
request : function(method, params, handler) { |
||||
var request = new XMLHttpRequest(); |
||||
request.open("POST", "", true); |
||||
request.setRequestHeader('Content-Type', 'application/json'); |
||||
var self = this; |
||||
request.onreadystatechange = function() { |
||||
if(this.readyState == 4 && this.status == "200" && this.responseText != "") { |
||||
var data = JSON.parse(this.responseText); |
||||
if(data.hasOwnProperty("error")) { |
||||
if(data["error"]["code"] == -32003 || data["error"]["code"] == -32004) { |
||||
// Get a new token and resend the request
|
||||
self.start(function() { |
||||
self.request(method, params, handler); |
||||
}); |
||||
return; |
||||
} |
||||
// Cannot fix the error, report it
|
||||
self.error = data["error"]; |
||||
} |
||||
handler(data.result, self); |
||||
} |
||||
}; |
||||
if(this.token != "") |
||||
params["Token"] = this.token; |
||||
|
||||
var rpc = { |
||||
"id" : 0, |
||||
"method" : method , |
||||
"params" : params, |
||||
"jsonrpc": "2.0" |
||||
} |
||||
request.send(JSON.stringify(rpc)); |
||||
}, |
||||
|
||||
start : function(onReady) { |
||||
var self = this; |
||||
|
||||
var handleAuthenticate = function(result) { |
||||
self.token = result["Token"]; |
||||
self.ready = true; |
||||
onReady(); |
||||
}; |
||||
|
||||
this.request( |
||||
"Authenticate", |
||||
{"API" : 1, "Password" : this.password}, |
||||
handleAuthenticate |
||||
); |
||||
}, |
||||
|
||||
}; |
||||
|
||||
I2PControl.statusToString = function(status) { |
||||
switch(status) { |
||||
case 0: return "OK"; |
||||
case 1: return "TESTING"; |
||||
case 2: return "FIREWALLED"; |
||||
case 3: return "HIDDEN"; |
||||
case 4: return "WARN_FIREWALLED_AND_FAST"; |
||||
case 5: return "WARN_FIREWALLED_AND_FLOODFILL"; |
||||
case 6: return "WARN_FIREWALLED_WITH_INBOUND_TCP"; |
||||
case 7: return "WARN_FIREWALLED_WITH_UDP_DISABLED"; |
||||
case 8: return "ERROR_I2CP"; |
||||
case 9: return "ERROR_CLOCK_SKEW"; |
||||
case 10: return "ERROR_PRIVATE_TCP_ADDRESS"; |
||||
case 11: return "ERROR_SYMMETRIC_NAT"; |
||||
case 12: return "ERROR_UDP_PORT_IN_USE"; |
||||
case 13: return "ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL"; |
||||
case 14: return "ERROR_UDP_DISABLED_AND_TCP_UNSET"; |
||||
default: return "UNKNOWN"; |
||||
} |
||||
}; |
||||
|
||||
I2PControl.msToString = function(mseconds) { |
||||
var seconds = mseconds / 1000; |
||||
var numdays = Math.floor(seconds / 86400); |
||||
var numhours = Math.floor((seconds % 86400) / 3600); |
||||
var numminutes = Math.floor(((seconds % 86400) % 3600) / 60); |
||||
var numseconds = ((seconds % 86400) % 3600) % 60; |
||||
|
||||
return numdays + "d " + numhours + "h " + numminutes + "m " + numseconds + "s"; |
||||
} |
||||
|
||||
I2PControl.updateDocument = function(values) { |
||||
|
||||
for(id in values) { |
||||
if(!values.hasOwnProperty(id)) |
||||
continue; |
||||
document.getElementById(id).innerHTML = values[id]; |
||||
} |
||||
}; |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
<div id="menu"> |
||||
<span class="menu-heading">i2pd</span> |
||||
<ul class="menu-list"> |
||||
<li class="menu-item"> |
||||
<a href="index.html" class="menu-link">Home</a> |
||||
</li> |
||||
<li class="menu-item"> |
||||
<a href="netdb.html" class="menu-link">Network Database</a> |
||||
</li> |
||||
<li class="menu-item"> |
||||
<a href="tunnels.html" class="menu-link">Tunnels</a> |
||||
</li> |
||||
<li class="menu-item"> |
||||
<a href="config.html" class="menu-link">Configure</a> |
||||
</li> |
||||
<li class="menu-item"> |
||||
<a href="help.html" class="menu-link">Help</a> |
||||
</li> |
||||
</ul> |
||||
</div> |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<title>Purple I2P 0.10.0 Webconsole</title> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<link rel="stylesheet" href="css/main.css"> |
||||
<script type="text/javascript" src="javascript/I2PControl.js"></script> |
||||
<script type="text/javascript"> |
||||
function updateNetDbInfo(result, session) { |
||||
if(session.error) { |
||||
alert("Error: " + session.error["message"]); |
||||
return; |
||||
} |
||||
I2PControl.updateDocument({ |
||||
"knownpeers" : result["i2p.router.netdb.knownpeers"], |
||||
"activepeers" : result["i2p.router.netdb.activepeers"], |
||||
"floodfills" : result["i2p.router.netdb.floodfills"], |
||||
"leasesets" : result["i2p.router.netdb.leasesets"], |
||||
}); |
||||
|
||||
window.setTimeout(function() { requestNetDbInfo(session); }, 10000); |
||||
} |
||||
|
||||
function requestNetDbInfo(session) { |
||||
session.request("RouterInfo", { |
||||
"i2p.router.netdb.knownpeers" : "", |
||||
"i2p.router.netdb.activepeers" : "", |
||||
"i2p.router.netdb.floodfills" : "", |
||||
"i2p.router.netdb.leasesets" : "", |
||||
}, updateNetDbInfo); |
||||
} |
||||
|
||||
window.onload = function() { |
||||
var session = new I2PControl.Session("itoopie"); |
||||
session.start(function() { requestNetDbInfo(session); }); |
||||
}; |
||||
</script> |
||||
</head> |
||||
|
||||
<body> |
||||
<div class="header"> |
||||
<h1>i2pd router console</h1> |
||||
<h2>Network Database Information</h2> |
||||
</div> |
||||
|
||||
<div class="content"> |
||||
<h2 class="content-subhead">Active peers: <span id="activepeers"></span></h2> |
||||
<h2 class="content-subhead">Known peers: <span id="knownpeers"></span></h2> |
||||
<h2 class="content-subhead">Floodfills: <span id="floodfills"></span></h2> |
||||
</br> |
||||
<h2 class="content-subhead">LeaseSets: <span id="leasesets"></span></h2> |
||||
</div> |
||||
|
||||
<!--#include virtual="menu.html" --> |
||||
<!--#include virtual="footer.html" --> |
||||
|
||||
</body> |
||||
</html> |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<title>Purple I2P 0.10.0 Webconsole</title> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<link rel="stylesheet" href="css/main.css"> |
||||
<script type="text/javascript" src="javascript/I2PControl.js"></script> |
||||
<script type="text/javascript"> |
||||
|
||||
function buildTable(direction, result) { |
||||
var table = document.getElementById(direction + "-tunnels").getElementsByTagName("tbody")[0]; |
||||
|
||||
var cmd = "i2p.router.net.tunnels." + direction + ".list"; |
||||
for(id in result[cmd]) { |
||||
if(!result[cmd].hasOwnProperty(id)) |
||||
continue; |
||||
var tunnel = result[cmd][id]; |
||||
|
||||
var row = table.insertRow(table.rows.length); |
||||
row.insertCell(0).appendChild(document.createTextNode(id)); |
||||
row.insertCell(1).appendChild(document.createTextNode(tunnel["state"] ? tunnel["state"] : "running")); |
||||
row.insertCell(2).appendChild(document.createTextNode(tunnel["layout"])); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
function updateTunnelInfo(result, session) { |
||||
if(session.error) { |
||||
alert("Error: " + session.error["message"]); |
||||
return; |
||||
} |
||||
|
||||
buildTable("inbound", result); |
||||
buildTable("outbound", result); |
||||
} |
||||
|
||||
function requestTunnelInfo(session) { |
||||
session.request("RouterInfo", { |
||||
"i2p.router.net.tunnels.inbound.list" : "", |
||||
"i2p.router.net.tunnels.outbound.list" : "", |
||||
}, updateTunnelInfo); |
||||
} |
||||
|
||||
window.onload = function() { |
||||
var session = new I2PControl.Session("itoopie"); |
||||
session.start(function() { requestTunnelInfo(session); }); |
||||
}; |
||||
</script> |
||||
</head> |
||||
|
||||
<body> |
||||
<div class="header"> |
||||
<h1>i2pd router console</h1> |
||||
<h2>Tunnel Information</h2> |
||||
</div> |
||||
|
||||
<div class="content"> |
||||
|
||||
<h2 class="content-subhead">Inbound Tunnels</h2> |
||||
<table id="inbound-tunnels"> |
||||
<thead> |
||||
<th>Tunnel ID</th> |
||||
<th>Status</th> |
||||
<th>Overview</th> |
||||
</thead> |
||||
<tbody> |
||||
</tbody> |
||||
</table> |
||||
<h2 class="content-subhead">Outbound Tunnels</h2> |
||||
<table id="outbound-tunnels"> |
||||
<thead> |
||||
<th>Tunnel ID</th> |
||||
<th>Status</th> |
||||
<th>Overview</th> |
||||
</thead> |
||||
<tbody> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
|
||||
<!--#include virtual="menu.html" --> |
||||
<!--#include virtual="footer.html" --> |
||||
|
||||
</body> |
||||
</html> |
Loading…
Reference in new issue