mirror of https://github.com/PurpleI2P/i2pd
commit
af66f335c9
@ -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
|
||||
);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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