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 @@ |
|||||||
|
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 @@ |
|||||||
|
#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 @@ |
|||||||
-----BEGIN CERTIFICATE----- |
|
||||||
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 |
|
||||||
fpeOSDoGBYJGbIpzDreBDhxaZrwGq36k |
|
||||||
-----END CERTIFICATE----- |
|
@ -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 @@ |
|||||||
|
#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 @@ |
|||||||
|
<!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 @@ |
|||||||
|
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 @@ |
|||||||
|
<div id="main"> |
||||||
|
<noscript> |
||||||
|
<div class="header"><h1>Please enable JavaScript!</h1></div> |
||||||
|
</noscript> |
||||||
|
</div> |
||||||
|
|
@ -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 @@ |
|||||||
|
<!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 @@ |
|||||||
|
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 @@ |
|||||||
|
<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 @@ |
|||||||
|
<!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 @@ |
|||||||
|
<!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