mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
169 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13f33a9d19 | ||
|
|
be3fa6091d | ||
|
|
8ffddf06e4 | ||
|
|
9b7f583b2b | ||
|
|
9fe4f3adea | ||
|
|
74d9f89c09 | ||
|
|
184c6ee252 | ||
|
|
1c024afc1b | ||
|
|
51519361e2 | ||
|
|
bd092295a4 | ||
|
|
153c275d74 | ||
|
|
db0dfa1bf1 | ||
|
|
debd13d8c3 | ||
|
|
4b8466e5e5 | ||
|
|
9d9793e1af | ||
|
|
46fafebade | ||
|
|
1dae3d951a | ||
|
|
da5be9f01d | ||
|
|
344d0ae3ec | ||
|
|
3639c86adf | ||
|
|
4fc80fd366 | ||
|
|
f76c04b7a6 | ||
|
|
8130487b18 | ||
|
|
83790a5a73 | ||
|
|
1b35f68de9 | ||
|
|
3e912c6198 | ||
|
|
6264569ca0 | ||
|
|
b9cbdb2dc4 | ||
|
|
7ae563867c | ||
|
|
f2f760bda4 | ||
|
|
ed561ad86b | ||
|
|
675861c323 | ||
|
|
ba330a42d6 | ||
|
|
2a9727c6b7 | ||
|
|
5be147e8cc | ||
|
|
eb96edbd31 | ||
|
|
14c85fa975 | ||
|
|
b0e3339370 | ||
|
|
70e502e55d | ||
|
|
ff38a3bbfe | ||
|
|
b5723a6c18 | ||
|
|
89012cd73b | ||
|
|
756e86662b | ||
|
|
27ca3b4b01 | ||
|
|
a5be4c9d0e | ||
|
|
07cc547bab | ||
|
|
f672af9706 | ||
|
|
58b058ab3a | ||
|
|
28c2ca8bf8 | ||
|
|
8970e6a48a | ||
|
|
b8eef181b9 | ||
|
|
fb94d6ae2b | ||
|
|
68482d712b | ||
|
|
e795de5562 | ||
|
|
ae6877ce2f | ||
|
|
a0f3e81b11 | ||
|
|
88f52c4902 | ||
|
|
bf8db7725f | ||
|
|
f4d8c3304a | ||
|
|
44556b7f5e | ||
|
|
2e1e95d483 | ||
|
|
b15b38868d | ||
|
|
8feca6874a | ||
|
|
ecd3a49d48 | ||
|
|
6de7cd5063 | ||
|
|
f6d7f7d984 | ||
|
|
d5d501875e | ||
|
|
88561c22d3 | ||
|
|
b786576bcb | ||
|
|
21b5f2c96a | ||
|
|
d8f24b442b | ||
|
|
4d2b535b04 | ||
|
|
37fc21f3cf | ||
|
|
5e068c3af5 | ||
|
|
e2c192d254 | ||
|
|
e481ed37ce | ||
|
|
4d7c089b09 | ||
|
|
a4dc67cba0 | ||
|
|
03973cc6d4 | ||
|
|
66c301c031 | ||
|
|
e4edc59689 | ||
|
|
667ea43b3c | ||
|
|
d6bfe7810a | ||
|
|
444539b826 | ||
|
|
c8d6425123 | ||
|
|
e50c35d38c | ||
|
|
aa764fbd1c | ||
|
|
2628426084 | ||
|
|
aa6bc8042a | ||
|
|
26a6c9e932 | ||
|
|
ace3e86546 | ||
|
|
d79c6b8f06 | ||
|
|
6538a2e673 | ||
|
|
153d883aeb | ||
|
|
689432f627 | ||
|
|
cd237219e4 | ||
|
|
8589493581 | ||
|
|
ca2e148ad7 | ||
|
|
f7ca44cad8 | ||
|
|
1b2ac38a50 | ||
|
|
f62d25fa5f | ||
|
|
025eec1782 | ||
|
|
846ff46b2e | ||
|
|
f9718bccb9 | ||
|
|
f66f4ffee6 | ||
|
|
a47417ff49 | ||
|
|
c9836cf0f7 | ||
|
|
289b679e3c | ||
|
|
23e019ec83 | ||
|
|
eeffcea69e | ||
|
|
ae10793d0f | ||
|
|
a062bca431 | ||
|
|
6a453bcc8a | ||
|
|
5a2c4919c6 | ||
|
|
09a80ed654 | ||
|
|
6c9b4a8c5d | ||
|
|
d9babda1b8 | ||
|
|
ea8e1be294 | ||
|
|
44eccd85fd | ||
|
|
a62720b9d8 | ||
|
|
1a9422c3f9 | ||
|
|
8622385e88 | ||
|
|
d0ffaab339 | ||
|
|
347157b999 | ||
|
|
a9f3235fd3 | ||
|
|
4098a5c08e | ||
|
|
dba7a2ee4f | ||
|
|
a5f49550b3 | ||
|
|
5c9a69e0e8 | ||
|
|
2bf32fb3fa | ||
|
|
0de1e2c6fc | ||
|
|
61868d97c4 | ||
|
|
c994c11d8c | ||
|
|
5ad10955be | ||
|
|
95f100f378 | ||
|
|
3d6c93cd6b | ||
|
|
fc25da37c5 | ||
|
|
896bb2187e | ||
|
|
99398bf0da | ||
|
|
827a54435d | ||
|
|
3c9459e489 | ||
|
|
9291f5c9c6 | ||
|
|
0ab5f993c7 | ||
|
|
4f8db487e7 | ||
|
|
0e1765e045 | ||
|
|
ebc411bbbd | ||
|
|
a76d8f0f9f | ||
|
|
f245feb0b0 | ||
|
|
43a90d7b98 | ||
|
|
2e1a9a8df9 | ||
|
|
57bb0da1d6 | ||
|
|
0d2df22074 | ||
|
|
c7173d5e1c | ||
|
|
789eb48698 | ||
|
|
e686fad546 | ||
|
|
4e4f9b6f8b | ||
|
|
f2292fd618 | ||
|
|
7035ead9e7 | ||
|
|
f01f6e94d1 | ||
|
|
f10064ce39 | ||
|
|
b68f06ca83 | ||
|
|
2ce61402bb | ||
|
|
70e9d85a75 | ||
|
|
a461f462d2 | ||
|
|
50ff0d251a | ||
|
|
f6103d3841 | ||
|
|
cb68d19bed | ||
|
|
89d2505a7c | ||
|
|
9ddfc750e5 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -5,6 +5,10 @@ router.keys
|
|||||||
i2p
|
i2p
|
||||||
libi2pd.so
|
libi2pd.so
|
||||||
netDb
|
netDb
|
||||||
|
/i2pd
|
||||||
|
/libi2pd.a
|
||||||
|
/libi2pdclient.a
|
||||||
|
|
||||||
|
|
||||||
# Autotools
|
# Autotools
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ addons:
|
|||||||
- libboost-date-time-dev
|
- libboost-date-time-dev
|
||||||
- libboost-filesystem-dev
|
- libboost-filesystem-dev
|
||||||
- libboost-program-options-dev
|
- libboost-program-options-dev
|
||||||
- libboost-regex-dev
|
|
||||||
- libboost-system-dev
|
- libboost-system-dev
|
||||||
- libboost-thread-dev
|
- libboost-thread-dev
|
||||||
- libminiupnpc-dev
|
- libminiupnpc-dev
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -160,7 +159,7 @@ namespace client
|
|||||||
|
|
||||||
int AddressBookFilesystemStorage::Save (const std::map<std::string, i2p::data::IdentHash>& addresses)
|
int AddressBookFilesystemStorage::Save (const std::map<std::string, i2p::data::IdentHash>& addresses)
|
||||||
{
|
{
|
||||||
if (addresses.size() == 0) {
|
if (addresses.empty()) {
|
||||||
LogPrint(eLogWarning, "Addressbook: not saving empty addressbook");
|
LogPrint(eLogWarning, "Addressbook: not saving empty addressbook");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -716,12 +715,14 @@ namespace client
|
|||||||
if (status == 200) // OK
|
if (status == 200) // OK
|
||||||
{
|
{
|
||||||
bool isChunked = false, isGzip = false;
|
bool isChunked = false, isGzip = false;
|
||||||
|
m_Etag = ""; m_LastModified = "";
|
||||||
std::string header, statusMessage;
|
std::string header, statusMessage;
|
||||||
std::getline (response, statusMessage);
|
std::getline (response, statusMessage);
|
||||||
// read until new line meaning end of header
|
// read until new line meaning end of header
|
||||||
while (!response.eof () && header != "\r")
|
while (!response.eof () && header != "\r")
|
||||||
{
|
{
|
||||||
std::getline (response, header);
|
std::getline (response, header);
|
||||||
|
if (response.fail ()) break;
|
||||||
auto colon = header.find (':');
|
auto colon = header.find (':');
|
||||||
if (colon != std::string::npos)
|
if (colon != std::string::npos)
|
||||||
{
|
{
|
||||||
@@ -741,9 +742,8 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogPrint (eLogInfo, "Addressbook: received ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified);
|
LogPrint (eLogInfo, "Addressbook: received ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified);
|
||||||
if (!response.eof ())
|
if (!response.eof () && !response.fail ())
|
||||||
{
|
{
|
||||||
success = true;
|
|
||||||
if (!isChunked)
|
if (!isChunked)
|
||||||
success = ProcessResponse (response, isGzip);
|
success = ProcessResponse (response, isGzip);
|
||||||
else
|
else
|
||||||
|
|||||||
86
ChangeLog
Normal file
86
ChangeLog
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# for this file format description,
|
||||||
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
|
## [2.8.0] - UNRELEASED
|
||||||
|
### Changed
|
||||||
|
- Proxy refactoring & speedup
|
||||||
|
- I2PControl refactoring & fixes (proper jsonrpc responses on errors)
|
||||||
|
- boost::regex no more needed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- initscripts: added openrc one, in sysv-ish make I2PD_PORT optional
|
||||||
|
|
||||||
|
## [2.7.0] - 2016-05-18
|
||||||
|
### Added
|
||||||
|
- Precomputed El-Gamal/DH tables
|
||||||
|
- Configurable limit of transit tunnels
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Speed-up of assymetric crypto for non-x64 platforms
|
||||||
|
- Refactoring of web-console
|
||||||
|
|
||||||
|
## [2.6.0] - 2016-03-31
|
||||||
|
### Added
|
||||||
|
- Gracefull shutdown on SIGINT
|
||||||
|
- Numeric bandwidth limits (was: by router class)
|
||||||
|
- Jumpservices in web-console
|
||||||
|
- Logging to syslog
|
||||||
|
- Tray icon for windows application
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Logs refactoring
|
||||||
|
- Improved statistics in web-console
|
||||||
|
|
||||||
|
### Deprecated:
|
||||||
|
- Renamed main/tunnels config files (will use old, if found, but emits warning)
|
||||||
|
|
||||||
|
## [2.5.1] - 2016-03-10
|
||||||
|
### Fixed
|
||||||
|
- Doesn't create ~/.i2pd dir if missing
|
||||||
|
|
||||||
|
## [2.5.0] - 2016-03-04
|
||||||
|
### Added
|
||||||
|
- IRC server tunnels
|
||||||
|
- SOCKS outproxy support
|
||||||
|
- Support for gzipped addressbook updates
|
||||||
|
- Support for router families
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Shared RTT/RTO between streams
|
||||||
|
- Filesystem work refactoring
|
||||||
|
|
||||||
|
## [2.4.0] - 2016-02-03
|
||||||
|
### Added
|
||||||
|
- X-I2P-* headers for server http-tunnels
|
||||||
|
- I2CP options for I2P tunnels
|
||||||
|
- Show I2P tunnels in webconsole
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Refactoring of cmdline/config parsing
|
||||||
|
|
||||||
|
## [2.3.0] - 2016-01-12
|
||||||
|
### Added
|
||||||
|
- Support for new router bandwidth class codes (P and X)
|
||||||
|
- I2PControl supports external webui
|
||||||
|
- Added --pidfile and --notransit parameters
|
||||||
|
- Ability to specify signature type for i2p tunnel
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Fixed multiple floodfill-related bugs
|
||||||
|
- New webconsole layout
|
||||||
|
|
||||||
|
## [2.2.0] - 2015-12-22
|
||||||
|
### Added
|
||||||
|
- Ability to connect to router without ip via introducer
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Persist temporary encryption keys for local destinations
|
||||||
|
- Performance improvements for EdDSA
|
||||||
|
- New addressbook structure
|
||||||
|
|
||||||
|
## [2.1.0] - 2015-11-12
|
||||||
|
### Added
|
||||||
|
- Implementation of EdDSA
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- EdDSA is default signature type for new RouterInfos
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
#include "util.h"
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@@ -114,6 +115,24 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I2CP
|
||||||
|
bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp);
|
||||||
|
if (i2cp)
|
||||||
|
{
|
||||||
|
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
||||||
|
uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
|
||||||
|
LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
|
||||||
|
m_I2CPServer->Start ();
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_AddressBook.StartResolvers ();
|
m_AddressBook.StartResolvers ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +184,14 @@ namespace client
|
|||||||
m_BOBCommandChannel = nullptr;
|
m_BOBCommandChannel = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_I2CPServer)
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "Clients: stopping I2CP");
|
||||||
|
m_I2CPServer->Stop ();
|
||||||
|
delete m_I2CPServer;
|
||||||
|
m_I2CPServer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Clients: stopping AddressBook");
|
LogPrint(eLogInfo, "Clients: stopping AddressBook");
|
||||||
m_AddressBook.Stop ();
|
m_AddressBook.Stop ();
|
||||||
for (auto it: m_Destinations)
|
for (auto it: m_Destinations)
|
||||||
@@ -266,7 +293,7 @@ namespace client
|
|||||||
template<typename Section, typename Type>
|
template<typename Section, typename Type>
|
||||||
std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
|
std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
|
||||||
{
|
{
|
||||||
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
|
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Destination.h"
|
#include "Destination.h"
|
||||||
|
#include "I2PService.h"
|
||||||
#include "HTTPProxy.h"
|
#include "HTTPProxy.h"
|
||||||
#include "SOCKS.h"
|
#include "SOCKS.h"
|
||||||
#include "I2PTunnel.h"
|
#include "I2PTunnel.h"
|
||||||
|
|||||||
@@ -178,6 +178,13 @@ namespace config {
|
|||||||
("bob.port", value<uint16_t>()->default_value(2827), "BOB listen port")
|
("bob.port", value<uint16_t>()->default_value(2827), "BOB listen port")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
options_description i2cp("I2CP options");
|
||||||
|
i2cp.add_options()
|
||||||
|
("i2cp.enabled", value<bool>()->default_value(false), "Enable or disable I2CP")
|
||||||
|
("i2cp.address", value<std::string>()->default_value("127.0.0.1"), "I2CP listen address")
|
||||||
|
("i2cp.port", value<uint16_t>()->default_value(7654), "I2CP listen port")
|
||||||
|
;
|
||||||
|
|
||||||
options_description i2pcontrol("I2PControl options");
|
options_description i2pcontrol("I2PControl options");
|
||||||
i2pcontrol.add_options()
|
i2pcontrol.add_options()
|
||||||
("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol")
|
("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol")
|
||||||
@@ -207,6 +214,7 @@ namespace config {
|
|||||||
.add(socksproxy)
|
.add(socksproxy)
|
||||||
.add(sam)
|
.add(sam)
|
||||||
.add(bob)
|
.add(bob)
|
||||||
|
.add(i2cp)
|
||||||
.add(i2pcontrol)
|
.add(i2pcontrol)
|
||||||
.add(precomputation)
|
.add(precomputation)
|
||||||
;
|
;
|
||||||
|
|||||||
4
Config.h
4
Config.h
@@ -68,7 +68,7 @@ namespace config {
|
|||||||
* @param value Variable where to store option
|
* @param value Variable where to store option
|
||||||
* @return this function returns false if parameter not found
|
* @return this function returns false if parameter not found
|
||||||
*
|
*
|
||||||
* @example uint16_t port; GetOption("sam.port", port);
|
* Example: uint16_t port; GetOption("sam.port", port);
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool GetOption(const char *name, T& value) {
|
bool GetOption(const char *name, T& value) {
|
||||||
@@ -84,7 +84,7 @@ namespace config {
|
|||||||
* @param value New parameter value
|
* @param value New parameter value
|
||||||
* @return true if value set up successful, false otherwise
|
* @return true if value set up successful, false otherwise
|
||||||
*
|
*
|
||||||
* @example uint16_t port = 2827; SetOption("bob.port", port);
|
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool SetOption(const char *name, const T& value) {
|
bool SetOption(const char *name, const T& value) {
|
||||||
|
|||||||
@@ -298,11 +298,13 @@ namespace crypto
|
|||||||
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
|
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
|
||||||
#endif
|
#endif
|
||||||
// calculate a
|
// calculate a
|
||||||
a = BN_new ();
|
|
||||||
if (g_ElggTable)
|
if (g_ElggTable)
|
||||||
a = ElggPow (k, g_ElggTable, ctx);
|
a = ElggPow (k, g_ElggTable, ctx);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
a = BN_new ();
|
||||||
BN_mod_exp (a, elgg, k, elgp, ctx);
|
BN_mod_exp (a, elgg, k, elgp, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
BIGNUM * y = BN_new ();
|
BIGNUM * y = BN_new ();
|
||||||
BN_bin2bn (key, 256, y);
|
BN_bin2bn (key, 256, y);
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ namespace i2p
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
Daemon_Singleton::Daemon_Singleton() : running(1), d(*new Daemon_Singleton_Private()) {};
|
Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {}
|
||||||
Daemon_Singleton::~Daemon_Singleton() {
|
Daemon_Singleton::~Daemon_Singleton() {
|
||||||
delete &d;
|
delete &d;
|
||||||
};
|
}
|
||||||
|
|
||||||
bool Daemon_Singleton::IsService () const
|
bool Daemon_Singleton::IsService () const
|
||||||
{
|
{
|
||||||
@@ -265,5 +265,5 @@ namespace i2p
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
Daemon.h
29
Daemon.h
@@ -1,14 +1,9 @@
|
|||||||
#ifndef DAEMON_H__
|
#ifndef DAEMON_H__
|
||||||
#define DAEMON_H__
|
#define DAEMON_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define Daemon i2p::util::DaemonWin32::Instance()
|
|
||||||
#else
|
|
||||||
#define Daemon i2p::util::DaemonLinux::Instance()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
@@ -22,9 +17,7 @@ namespace i2p
|
|||||||
virtual bool stop();
|
virtual bool stop();
|
||||||
virtual void run () {};
|
virtual void run () {};
|
||||||
|
|
||||||
bool isLogging;
|
|
||||||
bool isDaemon;
|
bool isDaemon;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -38,7 +31,22 @@ namespace i2p
|
|||||||
Daemon_Singleton_Private &d;
|
Daemon_Singleton_Private &d;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(QT_GUI_LIB) // check if QT
|
||||||
|
#define Daemon i2p::util::DaemonQT::Instance()
|
||||||
|
// dummy, invoked from RunQT
|
||||||
|
class DaemonQT: public i2p::util::Daemon_Singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static DaemonQT& Instance()
|
||||||
|
{
|
||||||
|
static DaemonQT instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#define Daemon i2p::util::DaemonWin32::Instance()
|
||||||
class DaemonWin32 : public Daemon_Singleton
|
class DaemonWin32 : public Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -54,7 +62,8 @@ namespace i2p
|
|||||||
void run ();
|
void run ();
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
class DaemonLinux : public Daemon_Singleton
|
#define Daemon i2p::util::DaemonLinux::Instance()
|
||||||
|
class DaemonLinux : public Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static DaemonLinux& Instance()
|
static DaemonLinux& Instance()
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
bool DaemonLinux::start()
|
bool DaemonLinux::start()
|
||||||
{
|
{
|
||||||
if (isDaemon == 1)
|
if (isDaemon)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@@ -73,10 +73,10 @@ namespace i2p
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// close stdin/stdout/stderr descriptors
|
// point std{in,out,err} descriptors to /dev/null
|
||||||
freopen("/dev/null", "r", stdin);
|
stdin = freopen("/dev/null", "r", stdin);
|
||||||
freopen("/dev/null", "w", stdout);
|
stdout = freopen("/dev/null", "w", stdout);
|
||||||
freopen("/dev/null", "w", stderr);
|
stderr = freopen("/dev/null", "w", stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pidfile
|
// Pidfile
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace i2p
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDaemon == 1)
|
if (isDaemon)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "Daemon: running as service");
|
LogPrint(eLogDebug, "Daemon: running as service");
|
||||||
I2PService service(SERVICE_NAME);
|
I2PService service(SERVICE_NAME);
|
||||||
|
|||||||
525
Destination.cpp
525
Destination.cpp
@@ -13,17 +13,11 @@ namespace i2p
|
|||||||
{
|
{
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic,
|
LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params):
|
||||||
const std::map<std::string, std::string> * params):
|
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), m_IsPublic (isPublic),
|
||||||
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
|
m_PublishReplyToken (0), m_PublishConfirmationTimer (m_Service),
|
||||||
m_Keys (keys), m_IsPublic (isPublic), m_PublishReplyToken (0),
|
|
||||||
m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service),
|
|
||||||
m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service)
|
m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service)
|
||||||
{
|
{
|
||||||
if (m_IsPublic)
|
|
||||||
PersistTemporaryKeys ();
|
|
||||||
else
|
|
||||||
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
|
||||||
int inboundTunnelLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
|
int inboundTunnelLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
|
||||||
int outboundTunnelLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
|
int outboundTunnelLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
|
||||||
int inboundTunnelsQuantity = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
int inboundTunnelsQuantity = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
||||||
@@ -103,11 +97,9 @@ namespace client
|
|||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inboundTunnelLen, outboundTunnelLen, inboundTunnelsQuantity, outboundTunnelsQuantity);
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inboundTunnelLen, outboundTunnelLen, inboundTunnelsQuantity, outboundTunnelsQuantity);
|
||||||
if (explicitPeers)
|
if (explicitPeers)
|
||||||
m_Pool->SetExplicitPeers (explicitPeers);
|
m_Pool->SetExplicitPeers (explicitPeers);
|
||||||
if (m_IsPublic)
|
|
||||||
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDestination::~ClientDestination ()
|
LeaseSetDestination::~LeaseSetDestination ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
Stop ();
|
Stop ();
|
||||||
@@ -116,11 +108,9 @@ namespace client
|
|||||||
m_LeaseSetRequests.clear ();
|
m_LeaseSetRequests.clear ();
|
||||||
if (m_Pool)
|
if (m_Pool)
|
||||||
i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
|
i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
|
||||||
if (m_DatagramDestination)
|
|
||||||
delete m_DatagramDestination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Run ()
|
void LeaseSetDestination::Run ()
|
||||||
{
|
{
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
@@ -135,26 +125,25 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Start ()
|
bool LeaseSetDestination::Start ()
|
||||||
{
|
{
|
||||||
if (!m_IsRunning)
|
if (!m_IsRunning)
|
||||||
{
|
{
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Pool->SetLocalDestination (shared_from_this ());
|
m_Pool->SetLocalDestination (shared_from_this ());
|
||||||
m_Pool->SetActive (true);
|
m_Pool->SetActive (true);
|
||||||
m_Thread = new std::thread (std::bind (&ClientDestination::Run, shared_from_this ()));
|
m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ()));
|
||||||
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (shared_from_this ()); // TODO:
|
|
||||||
m_StreamingDestination->Start ();
|
|
||||||
for (auto it: m_StreamingDestinationsByPorts)
|
|
||||||
it.second->Start ();
|
|
||||||
|
|
||||||
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
|
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
|
||||||
m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer,
|
m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Stop ()
|
bool LeaseSetDestination::Stop ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
{
|
{
|
||||||
@@ -162,16 +151,6 @@ namespace client
|
|||||||
m_PublishConfirmationTimer.cancel ();
|
m_PublishConfirmationTimer.cancel ();
|
||||||
m_PublishVerificationTimer.cancel ();
|
m_PublishVerificationTimer.cancel ();
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
m_StreamingDestination->Stop ();
|
|
||||||
m_StreamingDestination = nullptr;
|
|
||||||
for (auto it: m_StreamingDestinationsByPorts)
|
|
||||||
it.second->Stop ();
|
|
||||||
if (m_DatagramDestination)
|
|
||||||
{
|
|
||||||
auto d = m_DatagramDestination;
|
|
||||||
m_DatagramDestination = nullptr;
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
if (m_Pool)
|
if (m_Pool)
|
||||||
{
|
{
|
||||||
m_Pool->SetLocalDestination (nullptr);
|
m_Pool->SetLocalDestination (nullptr);
|
||||||
@@ -184,10 +163,13 @@ namespace client
|
|||||||
delete m_Thread;
|
delete m_Thread;
|
||||||
m_Thread = 0;
|
m_Thread = 0;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> ClientDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
auto it = m_RemoteLeaseSets.find (ident);
|
auto it = m_RemoteLeaseSets.find (ident);
|
||||||
if (it != m_RemoteLeaseSets.end ())
|
if (it != m_RemoteLeaseSets.end ())
|
||||||
@@ -210,7 +192,7 @@ namespace client
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> ClientDestination::GetLeaseSet ()
|
std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSet ()
|
||||||
{
|
{
|
||||||
if (!m_Pool) return nullptr;
|
if (!m_Pool) return nullptr;
|
||||||
if (!m_LeaseSet)
|
if (!m_LeaseSet)
|
||||||
@@ -218,12 +200,24 @@ namespace client
|
|||||||
return m_LeaseSet;
|
return m_LeaseSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::UpdateLeaseSet ()
|
void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet)
|
||||||
{
|
{
|
||||||
m_LeaseSet.reset (new i2p::data::LeaseSet (m_Pool));
|
m_LeaseSet.reset (newLeaseSet);
|
||||||
|
if (m_IsPublic)
|
||||||
|
{
|
||||||
|
m_PublishVerificationTimer.cancel ();
|
||||||
|
Publish ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::UpdateLeaseSet ()
|
||||||
|
{
|
||||||
|
int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
|
||||||
|
if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum
|
||||||
|
CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
|
bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -239,17 +233,17 @@ namespace client
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
m_Service.post (std::bind (&ClientDestination::HandleGarlicMessage, shared_from_this (), msg));
|
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
m_Service.post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
|
m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||||
{
|
{
|
||||||
uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET];
|
uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET];
|
||||||
switch (typeID)
|
switch (typeID)
|
||||||
@@ -272,7 +266,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
|
void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
|
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
|
||||||
size_t offset = DATABASE_STORE_HEADER_SIZE;
|
size_t offset = DATABASE_STORE_HEADER_SIZE;
|
||||||
@@ -336,7 +330,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len)
|
void LeaseSetDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
i2p::data::IdentHash key (buf);
|
i2p::data::IdentHash key (buf);
|
||||||
int num = buf[32]; // num
|
int num = buf[32]; // num
|
||||||
@@ -379,7 +373,7 @@ namespace client
|
|||||||
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
|
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
|
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
|
||||||
if (msgID == m_PublishReplyToken)
|
if (msgID == m_PublishReplyToken)
|
||||||
@@ -389,25 +383,20 @@ namespace client
|
|||||||
m_PublishReplyToken = 0;
|
m_PublishReplyToken = 0;
|
||||||
// schedule verification
|
// schedule verification
|
||||||
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
|
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
|
||||||
m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer,
|
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
|
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::SetLeaseSetUpdated ()
|
void LeaseSetDestination::SetLeaseSetUpdated ()
|
||||||
{
|
{
|
||||||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||||
UpdateLeaseSet ();
|
UpdateLeaseSet ();
|
||||||
if (m_IsPublic)
|
|
||||||
{
|
|
||||||
m_PublishVerificationTimer.cancel ();
|
|
||||||
Publish ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::Publish ()
|
void LeaseSetDestination::Publish ()
|
||||||
{
|
{
|
||||||
if (!m_LeaseSet || !m_Pool)
|
if (!m_LeaseSet || !m_Pool)
|
||||||
{
|
{
|
||||||
@@ -425,6 +414,12 @@ namespace client
|
|||||||
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
|
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto inbound = m_Pool->GetNextInboundTunnel ();
|
||||||
|
if (!inbound)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
||||||
if (!floodfill)
|
if (!floodfill)
|
||||||
{
|
{
|
||||||
@@ -435,14 +430,14 @@ namespace client
|
|||||||
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
||||||
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
||||||
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
||||||
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken));
|
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound));
|
||||||
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
||||||
m_PublishConfirmationTimer.async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer,
|
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
|
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
|
void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
@@ -455,7 +450,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode)
|
void LeaseSetDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
@@ -471,7 +466,7 @@ namespace client
|
|||||||
// we got latest LeasetSet
|
// we got latest LeasetSet
|
||||||
LogPrint (eLogDebug, "Destination: published LeaseSet verified");
|
LogPrint (eLogDebug, "Destination: published LeaseSet verified");
|
||||||
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
||||||
s->m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -483,6 +478,222 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
|
||||||
|
{
|
||||||
|
if (!m_Pool || !IsReady ())
|
||||||
|
{
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::CancelDestinationRequest (const i2p::data::IdentHash& dest)
|
||||||
|
{
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
m_Service.post ([dest, s](void)
|
||||||
|
{
|
||||||
|
auto it = s->m_LeaseSetRequests.find (dest);
|
||||||
|
if (it != s->m_LeaseSetRequests.end ())
|
||||||
|
{
|
||||||
|
auto requestComplete = it->second->requestComplete;
|
||||||
|
s->m_LeaseSetRequests.erase (it);
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
|
||||||
|
{
|
||||||
|
std::set<i2p::data::IdentHash> excluded;
|
||||||
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
|
||||||
|
if (floodfill)
|
||||||
|
{
|
||||||
|
auto request = std::make_shared<LeaseSetRequest> (m_Service);
|
||||||
|
request->requestComplete = requestComplete;
|
||||||
|
auto ret = m_LeaseSetRequests.insert (std::pair<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> >(dest,request));
|
||||||
|
if (ret.second) // inserted
|
||||||
|
{
|
||||||
|
if (!SendLeaseSetRequest (dest, floodfill, request))
|
||||||
|
{
|
||||||
|
// request failed
|
||||||
|
m_LeaseSetRequests.erase (dest);
|
||||||
|
if (request->requestComplete) request->requestComplete (nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // duplicate
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already");
|
||||||
|
// TODO: queue up requests
|
||||||
|
if (request->requestComplete) request->requestComplete (nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found");
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
||||||
|
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
|
||||||
|
{
|
||||||
|
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
|
||||||
|
request->replyTunnel = m_Pool->GetNextInboundTunnel ();
|
||||||
|
if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
|
||||||
|
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
|
||||||
|
request->outboundTunnel = m_Pool->GetNextOutboundTunnel ();
|
||||||
|
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
|
||||||
|
|
||||||
|
if (request->replyTunnel && request->outboundTunnel)
|
||||||
|
{
|
||||||
|
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
||||||
|
request->requestTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
request->requestTimeoutTimer.cancel ();
|
||||||
|
|
||||||
|
uint8_t replyKey[32], replyTag[32];
|
||||||
|
RAND_bytes (replyKey, 32); // random session key
|
||||||
|
RAND_bytes (replyTag, 32); // random session tag
|
||||||
|
AddSessionKey (replyKey, replyTag);
|
||||||
|
|
||||||
|
auto msg = WrapMessage (nextFloodfill,
|
||||||
|
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
||||||
|
request->replyTunnel, replyKey, replyTag));
|
||||||
|
request->outboundTunnel->SendTunnelDataMsg (
|
||||||
|
{
|
||||||
|
i2p::tunnel::TunnelMessageBlock
|
||||||
|
{
|
||||||
|
i2p::tunnel::eDeliveryTypeRouter,
|
||||||
|
nextFloodfill->GetIdentHash (), 0, msg
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
|
||||||
|
request->requestTimeoutTimer.async_wait (std::bind (&LeaseSetDestination::HandleRequestTimoutTimer,
|
||||||
|
shared_from_this (), std::placeholders::_1, dest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
auto it = m_LeaseSetRequests.find (dest);
|
||||||
|
if (it != m_LeaseSetRequests.end ())
|
||||||
|
{
|
||||||
|
bool done = false;
|
||||||
|
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
if (ts < it->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
|
||||||
|
{
|
||||||
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, it->second->excluded);
|
||||||
|
if (floodfill)
|
||||||
|
{
|
||||||
|
// reset tunnels, because one them might fail
|
||||||
|
it->second->outboundTunnel = nullptr;
|
||||||
|
it->second->replyTunnel = nullptr;
|
||||||
|
done = !SendLeaseSetRequest (dest, floodfill, it->second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
auto requestComplete = it->second->requestComplete;
|
||||||
|
m_LeaseSetRequests.erase (it);
|
||||||
|
if (requestComplete) requestComplete (nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::HandleCleanupTimer (const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
CleanupExpiredTags ();
|
||||||
|
CleanupRemoteLeaseSets ();
|
||||||
|
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
|
||||||
|
m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer,
|
||||||
|
shared_from_this (), std::placeholders::_1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::CleanupRemoteLeaseSets ()
|
||||||
|
{
|
||||||
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();)
|
||||||
|
{
|
||||||
|
if (it->second->IsEmpty () || ts > it->second->GetExpirationTime ()) // leaseset expired
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
|
||||||
|
it = m_RemoteLeaseSets.erase (it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
|
||||||
|
LeaseSetDestination (isPublic, params),
|
||||||
|
m_Keys (keys), m_DatagramDestination (nullptr)
|
||||||
|
{
|
||||||
|
if (isPublic)
|
||||||
|
PersistTemporaryKeys ();
|
||||||
|
else
|
||||||
|
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||||
|
if (isPublic)
|
||||||
|
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientDestination::~ClientDestination ()
|
||||||
|
{
|
||||||
|
if (m_DatagramDestination)
|
||||||
|
delete m_DatagramDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientDestination::Start ()
|
||||||
|
{
|
||||||
|
if (LeaseSetDestination::Start ())
|
||||||
|
{
|
||||||
|
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO:
|
||||||
|
m_StreamingDestination->Start ();
|
||||||
|
for (auto it: m_StreamingDestinationsByPorts)
|
||||||
|
it.second->Start ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientDestination::Stop ()
|
||||||
|
{
|
||||||
|
if (LeaseSetDestination::Stop ())
|
||||||
|
{
|
||||||
|
m_StreamingDestination->Stop ();
|
||||||
|
m_StreamingDestination = nullptr;
|
||||||
|
for (auto it: m_StreamingDestinationsByPorts)
|
||||||
|
it.second->Stop ();
|
||||||
|
if (m_DatagramDestination)
|
||||||
|
{
|
||||||
|
auto d = m_DatagramDestination;
|
||||||
|
m_DatagramDestination = nullptr;
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
uint32_t length = bufbe32toh (buf);
|
uint32_t length = bufbe32toh (buf);
|
||||||
@@ -512,8 +723,8 @@ namespace client
|
|||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
|
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
|
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
|
||||||
{
|
{
|
||||||
if (!streamRequestComplete)
|
if (!streamRequestComplete)
|
||||||
@@ -526,7 +737,7 @@ namespace client
|
|||||||
streamRequestComplete(CreateStream (leaseSet, port));
|
streamRequestComplete(CreateStream (leaseSet, port));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto s = shared_from_this ();
|
auto s = GetSharedFromThis ();
|
||||||
RequestDestination (dest,
|
RequestDestination (dest,
|
||||||
[s, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
|
[s, streamRequestComplete, port](std::shared_ptr<i2p::data::LeaseSet> ls)
|
||||||
{
|
{
|
||||||
@@ -579,7 +790,7 @@ namespace client
|
|||||||
|
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
|
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
|
||||||
{
|
{
|
||||||
auto dest = std::make_shared<i2p::stream::StreamingDestination> (shared_from_this (), port, gzip);
|
auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
|
||||||
if (port)
|
if (port)
|
||||||
m_StreamingDestinationsByPorts[port] = dest;
|
m_StreamingDestinationsByPorts[port] = dest;
|
||||||
else // update default
|
else // update default
|
||||||
@@ -590,173 +801,23 @@ namespace client
|
|||||||
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
|
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
|
||||||
{
|
{
|
||||||
if (!m_DatagramDestination)
|
if (!m_DatagramDestination)
|
||||||
m_DatagramDestination = new i2p::datagram::DatagramDestination (shared_from_this ());
|
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ());
|
||||||
return m_DatagramDestination;
|
return m_DatagramDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
|
std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const
|
||||||
{
|
{
|
||||||
if (!m_Pool || !IsReady ())
|
std::vector<std::shared_ptr<const i2p::stream::Stream> > ret;
|
||||||
{
|
if (m_StreamingDestination)
|
||||||
if (requestComplete) requestComplete (nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_Service.post (std::bind (&ClientDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::CancelDestinationRequest (const i2p::data::IdentHash& dest)
|
|
||||||
{
|
|
||||||
auto s = shared_from_this ();
|
|
||||||
m_Service.post ([dest, s](void)
|
|
||||||
{
|
|
||||||
auto it = s->m_LeaseSetRequests.find (dest);
|
|
||||||
if (it != s->m_LeaseSetRequests.end ())
|
|
||||||
{
|
|
||||||
auto requestComplete = it->second->requestComplete;
|
|
||||||
s->m_LeaseSetRequests.erase (it);
|
|
||||||
if (requestComplete) requestComplete (nullptr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
|
|
||||||
{
|
|
||||||
std::set<i2p::data::IdentHash> excluded;
|
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
|
|
||||||
if (floodfill)
|
|
||||||
{
|
{
|
||||||
auto request = std::make_shared<LeaseSetRequest> (m_Service);
|
for (auto& it: m_StreamingDestination->GetStreams ())
|
||||||
request->requestComplete = requestComplete;
|
ret.push_back (it.second);
|
||||||
auto ret = m_LeaseSetRequests.insert (std::pair<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> >(dest,request));
|
|
||||||
if (ret.second) // inserted
|
|
||||||
{
|
|
||||||
if (!SendLeaseSetRequest (dest, floodfill, request))
|
|
||||||
{
|
|
||||||
// request failed
|
|
||||||
m_LeaseSetRequests.erase (dest);
|
|
||||||
if (request->requestComplete) request->requestComplete (nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // duplicate
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already");
|
|
||||||
// TODO: queue up requests
|
|
||||||
if (request->requestComplete) request->requestComplete (nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found");
|
|
||||||
if (requestComplete) requestComplete (nullptr);
|
|
||||||
}
|
}
|
||||||
|
for (auto& it: m_StreamingDestinationsByPorts)
|
||||||
|
for (auto& it1: it.second->GetStreams ())
|
||||||
|
ret.push_back (it1.second);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
|
|
||||||
{
|
|
||||||
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
|
|
||||||
request->replyTunnel = m_Pool->GetNextInboundTunnel ();
|
|
||||||
if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
|
|
||||||
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
|
|
||||||
request->outboundTunnel = m_Pool->GetNextOutboundTunnel ();
|
|
||||||
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
|
|
||||||
|
|
||||||
if (request->replyTunnel && request->outboundTunnel)
|
|
||||||
{
|
|
||||||
request->excluded.insert (nextFloodfill->GetIdentHash ());
|
|
||||||
request->requestTime = i2p::util::GetSecondsSinceEpoch ();
|
|
||||||
request->requestTimeoutTimer.cancel ();
|
|
||||||
|
|
||||||
uint8_t replyKey[32], replyTag[32];
|
|
||||||
RAND_bytes (replyKey, 32); // random session key
|
|
||||||
RAND_bytes (replyTag, 32); // random session tag
|
|
||||||
AddSessionKey (replyKey, replyTag);
|
|
||||||
|
|
||||||
auto msg = WrapMessage (nextFloodfill,
|
|
||||||
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
|
|
||||||
request->replyTunnel, replyKey, replyTag));
|
|
||||||
request->outboundTunnel->SendTunnelDataMsg (
|
|
||||||
{
|
|
||||||
i2p::tunnel::TunnelMessageBlock
|
|
||||||
{
|
|
||||||
i2p::tunnel::eDeliveryTypeRouter,
|
|
||||||
nextFloodfill->GetIdentHash (), 0, msg
|
|
||||||
}
|
|
||||||
});
|
|
||||||
request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
|
|
||||||
request->requestTimeoutTimer.async_wait (std::bind (&ClientDestination::HandleRequestTimoutTimer,
|
|
||||||
shared_from_this (), std::placeholders::_1, dest));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest)
|
|
||||||
{
|
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
|
||||||
{
|
|
||||||
auto it = m_LeaseSetRequests.find (dest);
|
|
||||||
if (it != m_LeaseSetRequests.end ())
|
|
||||||
{
|
|
||||||
bool done = false;
|
|
||||||
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
|
||||||
if (ts < it->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
|
|
||||||
{
|
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, it->second->excluded);
|
|
||||||
if (floodfill)
|
|
||||||
{
|
|
||||||
// reset tunnels, because one them might fail
|
|
||||||
it->second->outboundTunnel = nullptr;
|
|
||||||
it->second->replyTunnel = nullptr;
|
|
||||||
done = !SendLeaseSetRequest (dest, floodfill, it->second);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (done)
|
|
||||||
{
|
|
||||||
auto requestComplete = it->second->requestComplete;
|
|
||||||
m_LeaseSetRequests.erase (it);
|
|
||||||
if (requestComplete) requestComplete (nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::HandleCleanupTimer (const boost::system::error_code& ecode)
|
|
||||||
{
|
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
|
||||||
{
|
|
||||||
CleanupExpiredTags ();
|
|
||||||
CleanupRemoteLeaseSets ();
|
|
||||||
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
|
|
||||||
m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer,
|
|
||||||
shared_from_this (), std::placeholders::_1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::CleanupRemoteLeaseSets ()
|
|
||||||
{
|
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
|
||||||
for (auto it = m_RemoteLeaseSets.begin (); it != m_RemoteLeaseSets.end ();)
|
|
||||||
{
|
|
||||||
if (it->second->IsEmpty () || ts > it->second->GetExpirationTime ()) // leaseset expired
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
|
|
||||||
it = m_RemoteLeaseSets.erase (it);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDestination::PersistTemporaryKeys ()
|
void ClientDestination::PersistTemporaryKeys ()
|
||||||
{
|
{
|
||||||
@@ -780,20 +841,14 @@ namespace client
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
|
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const
|
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<const i2p::stream::Stream> > ret;
|
auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels);
|
||||||
if (m_StreamingDestination)
|
// sign
|
||||||
{
|
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO
|
||||||
for (auto& it: m_StreamingDestination->GetStreams ())
|
SetLeaseSet (leaseSet);
|
||||||
ret.push_back (it.second);
|
|
||||||
}
|
|
||||||
for (auto& it: m_StreamingDestinationsByPorts)
|
|
||||||
for (auto& it1: it.second->GetStreams ())
|
|
||||||
ret.push_back (it1.second);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
111
Destination.h
111
Destination.h
@@ -49,8 +49,8 @@ namespace client
|
|||||||
|
|
||||||
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
|
||||||
|
|
||||||
class ClientDestination: public i2p::garlic::GarlicDestination,
|
class LeaseSetDestination: public i2p::garlic::GarlicDestination,
|
||||||
public std::enable_shared_from_this<ClientDestination>
|
public std::enable_shared_from_this<LeaseSetDestination>
|
||||||
{
|
{
|
||||||
typedef std::function<void (std::shared_ptr<i2p::data::LeaseSet> leaseSet)> RequestComplete;
|
typedef std::function<void (std::shared_ptr<i2p::data::LeaseSet> leaseSet)> RequestComplete;
|
||||||
// leaseSet = nullptr means not found
|
// leaseSet = nullptr means not found
|
||||||
@@ -68,11 +68,11 @@ namespace client
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
~ClientDestination ();
|
~LeaseSetDestination ();
|
||||||
|
|
||||||
virtual void Start ();
|
virtual bool Start ();
|
||||||
virtual void Stop ();
|
virtual bool Stop ();
|
||||||
bool IsRunning () const { return m_IsRunning; };
|
bool IsRunning () const { return m_IsRunning; };
|
||||||
boost::asio::io_service& GetService () { return m_Service; };
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
||||||
@@ -80,28 +80,9 @@ namespace client
|
|||||||
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
|
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
|
||||||
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
|
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
|
||||||
void CancelDestinationRequest (const i2p::data::IdentHash& dest);
|
void CancelDestinationRequest (const i2p::data::IdentHash& dest);
|
||||||
|
|
||||||
// streaming
|
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
|
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
|
|
||||||
// following methods operate with default streaming destination
|
|
||||||
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
|
|
||||||
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
|
|
||||||
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
|
||||||
void StopAcceptingStreams ();
|
|
||||||
bool IsAcceptingStreams () const;
|
|
||||||
|
|
||||||
// datagram
|
|
||||||
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
|
||||||
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
|
|
||||||
|
|
||||||
// implements LocalDestination
|
|
||||||
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
|
||||||
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
|
||||||
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; };
|
|
||||||
|
|
||||||
// implements GarlicDestination
|
// implements GarlicDestination
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> GetLeaseSet ();
|
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const { return m_Pool; }
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const { return m_Pool; }
|
||||||
void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
|
|
||||||
@@ -111,9 +92,13 @@ namespace client
|
|||||||
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
void SetLeaseSetUpdated ();
|
void SetLeaseSetUpdated ();
|
||||||
|
|
||||||
// I2CP
|
protected:
|
||||||
void HandleDataMessage (const uint8_t * buf, size_t len);
|
|
||||||
|
|
||||||
|
void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet);
|
||||||
|
// I2CP
|
||||||
|
virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
|
||||||
|
virtual void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
@@ -129,29 +114,22 @@ namespace client
|
|||||||
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
|
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
|
||||||
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
||||||
void HandleCleanupTimer (const boost::system::error_code& ecode);
|
void HandleCleanupTimer (const boost::system::error_code& ecode);
|
||||||
void CleanupRemoteLeaseSets ();
|
void CleanupRemoteLeaseSets ();
|
||||||
void PersistTemporaryKeys ();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
volatile bool m_IsRunning;
|
volatile bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::io_service::work m_Work;
|
boost::asio::io_service::work m_Work;
|
||||||
i2p::data::PrivateKeys m_Keys;
|
|
||||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
|
||||||
std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
|
std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
|
||||||
std::map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
|
std::map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
|
||||||
|
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
|
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
|
||||||
std::shared_ptr<i2p::data::LeaseSet> m_LeaseSet;
|
std::shared_ptr<i2p::data::LocalLeaseSet> m_LeaseSet;
|
||||||
bool m_IsPublic;
|
bool m_IsPublic;
|
||||||
uint32_t m_PublishReplyToken;
|
uint32_t m_PublishReplyToken;
|
||||||
std::set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
|
std::set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
|
||||||
|
|
||||||
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
|
||||||
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
|
||||||
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
|
||||||
|
|
||||||
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_CleanupTimer;
|
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_CleanupTimer;
|
||||||
|
|
||||||
@@ -159,6 +137,63 @@ namespace client
|
|||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
|
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClientDestination: public LeaseSetDestination
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
|
~ClientDestination ();
|
||||||
|
|
||||||
|
bool Start ();
|
||||||
|
bool Stop ();
|
||||||
|
|
||||||
|
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
||||||
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
|
||||||
|
|
||||||
|
// streaming
|
||||||
|
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
|
||||||
|
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
|
||||||
|
// following methods operate with default streaming destination
|
||||||
|
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
|
||||||
|
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
|
||||||
|
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
|
||||||
|
void StopAcceptingStreams ();
|
||||||
|
bool IsAcceptingStreams () const;
|
||||||
|
|
||||||
|
// datagram
|
||||||
|
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||||
|
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
|
||||||
|
|
||||||
|
// implements LocalDestination
|
||||||
|
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
||||||
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// I2CP
|
||||||
|
void HandleDataMessage (const uint8_t * buf, size_t len);
|
||||||
|
void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::shared_ptr<ClientDestination> GetSharedFromThis ()
|
||||||
|
{ return std::static_pointer_cast<ClientDestination>(shared_from_this ()); }
|
||||||
|
void PersistTemporaryKeys ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
i2p::data::PrivateKeys m_Keys;
|
||||||
|
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
||||||
|
|
||||||
|
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
|
||||||
|
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
|
||||||
|
i2p::datagram::DatagramDestination * m_DatagramDestination;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// for HTTP only
|
||||||
std::vector<std::shared_ptr<const i2p::stream::Stream> > GetAllStreams () const;
|
std::vector<std::shared_ptr<const i2p::stream::Stream> > GetAllStreams () const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
8
FS.cpp
8
FS.cpp
@@ -55,6 +55,14 @@ namespace fs {
|
|||||||
dataDir += "/Library/Application Support/" + appName;
|
dataDir += "/Library/Application Support/" + appName;
|
||||||
return;
|
return;
|
||||||
#else /* other unix */
|
#else /* other unix */
|
||||||
|
#if defined(ANDROID)
|
||||||
|
if (boost::filesystem::exists("/sdcard"))
|
||||||
|
{
|
||||||
|
dataDir = "/sdcard/" + appName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// otherwise use /data/files
|
||||||
|
#endif
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (isService) {
|
if (isService) {
|
||||||
dataDir = "/var/lib/" + appName;
|
dataDir = "/var/lib/" + appName;
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ namespace data
|
|||||||
int numCertificates = 0;
|
int numCertificates = 0;
|
||||||
|
|
||||||
if (!i2p::fs::ReadDir(certDir, files)) {
|
if (!i2p::fs::ReadDir(certDir, files)) {
|
||||||
LogPrint(eLogWarning, "Reseed: Can't load reseed certificates from ", certDir);
|
LogPrint(eLogWarning, "Family: Can't load family certificates from ", certDir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
Garlic.h
2
Garlic.h
@@ -163,7 +163,7 @@ namespace garlic
|
|||||||
virtual void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
virtual void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
virtual void SetLeaseSetUpdated ();
|
virtual void SetLeaseSetUpdated ();
|
||||||
|
|
||||||
virtual std::shared_ptr<const i2p::data::LeaseSet> GetLeaseSet () = 0; // TODO
|
virtual std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () = 0; // TODO
|
||||||
virtual std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const = 0;
|
virtual std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const = 0;
|
||||||
virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from) = 0;
|
virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from) = 0;
|
||||||
|
|
||||||
|
|||||||
57
HTTP.cpp
57
HTTP.cpp
@@ -6,8 +6,10 @@
|
|||||||
* See full license text in LICENSE file at top of project tree
|
* See full license text in LICENSE file at top of project tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "HTTP.h"
|
#include "HTTP.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace http {
|
namespace http {
|
||||||
@@ -44,9 +46,10 @@ namespace http {
|
|||||||
bool parse_header_line(const std::string & line, std::map<std::string, std::string> & headers) {
|
bool parse_header_line(const std::string & line, std::map<std::string, std::string> & headers) {
|
||||||
std::size_t pos = 0;
|
std::size_t pos = 0;
|
||||||
std::size_t len = 2; /* strlen(": ") */
|
std::size_t len = 2; /* strlen(": ") */
|
||||||
|
std::size_t max = line.length();
|
||||||
if ((pos = line.find(": ", pos)) == std::string::npos)
|
if ((pos = line.find(": ", pos)) == std::string::npos)
|
||||||
return false;
|
return false;
|
||||||
while (isspace(line.at(pos + len)))
|
while ((pos + len) < max && isspace(line.at(pos + len)))
|
||||||
len++;
|
len++;
|
||||||
std::string name = line.substr(0, pos);
|
std::string name = line.substr(0, pos);
|
||||||
std::string value = line.substr(pos + len);
|
std::string value = line.substr(pos + len);
|
||||||
@@ -54,6 +57,13 @@ namespace http {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gen_rfc1123_date(std::string & out) {
|
||||||
|
std::time_t now = std::time(nullptr);
|
||||||
|
char buf[128];
|
||||||
|
std::strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", std::gmtime(&now));
|
||||||
|
out = buf;
|
||||||
|
}
|
||||||
|
|
||||||
bool URL::parse(const char *str, std::size_t len) {
|
bool URL::parse(const char *str, std::size_t len) {
|
||||||
std::string url(str, len ? len : strlen(str));
|
std::string url(str, len ? len : strlen(str));
|
||||||
return parse(url);
|
return parse(url);
|
||||||
@@ -184,6 +194,25 @@ namespace http {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTTPMsg::add_header(const char *name, std::string & value, bool replace) {
|
||||||
|
add_header(name, value.c_str(), replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPMsg::add_header(const char *name, const char *value, bool replace) {
|
||||||
|
std::size_t count = headers.count(name);
|
||||||
|
if (count && !replace)
|
||||||
|
return;
|
||||||
|
if (count) {
|
||||||
|
headers[name] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
headers.insert(std::pair<std::string, std::string>(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTTPMsg::del_header(const char *name) {
|
||||||
|
headers.erase(name);
|
||||||
|
}
|
||||||
|
|
||||||
int HTTPReq::parse(const char *buf, size_t len) {
|
int HTTPReq::parse(const char *buf, size_t len) {
|
||||||
std::string str(buf, len);
|
std::string str(buf, len);
|
||||||
return parse(str);
|
return parse(str);
|
||||||
@@ -225,21 +254,12 @@ namespace http {
|
|||||||
if (pos >= eoh)
|
if (pos >= eoh)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto it = headers.find("Host");
|
|
||||||
if (it != headers.end ()) {
|
|
||||||
host = it->second;
|
|
||||||
} else if (version == "HTTP/1.1") {
|
|
||||||
return -1; /* 'Host' header required for HTTP/1.1 */
|
|
||||||
} else if (url.host != "") {
|
|
||||||
host = url.host;
|
|
||||||
}
|
|
||||||
return eoh + strlen(HTTP_EOH);
|
return eoh + strlen(HTTP_EOH);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HTTPReq::to_string() {
|
std::string HTTPReq::to_string() {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << method << " " << uri << " " << version << CRLF;
|
ss << method << " " << uri << " " << version << CRLF;
|
||||||
ss << "Host: " << host << CRLF;
|
|
||||||
for (auto & h : headers) {
|
for (auto & h : headers) {
|
||||||
ss << h.first << ": " << h.second << CRLF;
|
ss << h.first << ": " << h.second << CRLF;
|
||||||
}
|
}
|
||||||
@@ -256,7 +276,7 @@ namespace http {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int HTTPRes::length() {
|
long int HTTPMsg::length() {
|
||||||
unsigned long int length = 0;
|
unsigned long int length = 0;
|
||||||
auto it = headers.find("Content-Length");
|
auto it = headers.find("Content-Length");
|
||||||
if (it == headers.end())
|
if (it == headers.end())
|
||||||
@@ -311,12 +331,24 @@ namespace http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string HTTPRes::to_string() {
|
std::string HTTPRes::to_string() {
|
||||||
|
if (version == "HTTP/1.1" && headers.count("Date") == 0) {
|
||||||
|
std::string date;
|
||||||
|
gen_rfc1123_date(date);
|
||||||
|
add_header("Date", date.c_str());
|
||||||
|
}
|
||||||
|
if (status == "OK" && code != 200)
|
||||||
|
status = HTTPCodeToStatus(code); // update
|
||||||
|
if (body.length() > 0 && headers.count("Content-Length") == 0)
|
||||||
|
add_header("Content-Length", std::to_string(body.length()).c_str());
|
||||||
|
/* build response */
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << version << " " << code << " " << status << CRLF;
|
ss << version << " " << code << " " << status << CRLF;
|
||||||
for (auto & h : headers) {
|
for (auto & h : headers) {
|
||||||
ss << h.first << ": " << h.second << CRLF;
|
ss << h.first << ": " << h.second << CRLF;
|
||||||
}
|
}
|
||||||
ss << CRLF;
|
ss << CRLF;
|
||||||
|
if (body.length() > 0)
|
||||||
|
ss << body;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,11 +398,10 @@ namespace http {
|
|||||||
|
|
||||||
bool MergeChunkedResponse (std::istream& in, std::ostream& out) {
|
bool MergeChunkedResponse (std::istream& in, std::ostream& out) {
|
||||||
std::string hexLen;
|
std::string hexLen;
|
||||||
long int len;
|
|
||||||
while (!in.eof ()) {
|
while (!in.eof ()) {
|
||||||
std::getline (in, hexLen);
|
std::getline (in, hexLen);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
len = strtoul(hexLen.c_str(), (char **) NULL, 16);
|
long int len = strtoul(hexLen.c_str(), (char **) NULL, 16);
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
return false; /* conversion error */
|
return false; /* conversion error */
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
|
|||||||
45
HTTP.h
45
HTTP.h
@@ -38,7 +38,7 @@ namespace http {
|
|||||||
* @brief Tries to parse url from string
|
* @brief Tries to parse url from string
|
||||||
* @return true on success, false on invalid url
|
* @return true on success, false on invalid url
|
||||||
*/
|
*/
|
||||||
bool parse (const char *str, size_t len = 0);
|
bool parse (const char *str, std::size_t len = 0);
|
||||||
bool parse (const std::string& url);
|
bool parse (const std::string& url);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,12 +54,21 @@ namespace http {
|
|||||||
std::string to_string ();
|
std::string to_string ();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HTTPReq {
|
struct HTTPMsg {
|
||||||
std::map<std::string, std::string> headers;
|
std::map<std::string, std::string> headers;
|
||||||
|
|
||||||
|
void add_header(const char *name, std::string & value, bool replace = false);
|
||||||
|
void add_header(const char *name, const char *value, bool replace = false);
|
||||||
|
void del_header(const char *name);
|
||||||
|
|
||||||
|
/** @brief Returns declared message length or -1 if unknown */
|
||||||
|
long int length();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HTTPReq : HTTPMsg {
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string method;
|
std::string method;
|
||||||
std::string uri;
|
std::string uri;
|
||||||
std::string host;
|
|
||||||
|
|
||||||
HTTPReq (): version("HTTP/1.0"), method("GET"), uri("/") {};
|
HTTPReq (): version("HTTP/1.0"), method("GET"), uri("/") {};
|
||||||
|
|
||||||
@@ -75,11 +84,18 @@ namespace http {
|
|||||||
std::string to_string();
|
std::string to_string();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HTTPRes {
|
struct HTTPRes : HTTPMsg {
|
||||||
std::map<std::string, std::string> headers;
|
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string status;
|
std::string status;
|
||||||
unsigned short int code;
|
unsigned short int code;
|
||||||
|
/**
|
||||||
|
* @brief Simplifies response generation
|
||||||
|
*
|
||||||
|
* If this variable is set, on @a to_string() call:
|
||||||
|
* * Content-Length header will be added if missing,
|
||||||
|
* * contents of @a body will be included in generated response
|
||||||
|
*/
|
||||||
|
std::string body;
|
||||||
|
|
||||||
HTTPRes (): version("HTTP/1.1"), status("OK"), code(200) {}
|
HTTPRes (): version("HTTP/1.1"), status("OK"), code(200) {}
|
||||||
|
|
||||||
@@ -91,14 +107,17 @@ namespace http {
|
|||||||
int parse(const char *buf, size_t len);
|
int parse(const char *buf, size_t len);
|
||||||
int parse(const std::string& buf);
|
int parse(const std::string& buf);
|
||||||
|
|
||||||
/** @brief Serialize HTTP response to string */
|
/**
|
||||||
|
* @brief Serialize HTTP response to string
|
||||||
|
* @note If @a version is set to HTTP/1.1, and Date header is missing,
|
||||||
|
* it will be generated based on current time and added to headers
|
||||||
|
* @note If @a body is set and Content-Length header is missing,
|
||||||
|
* this header will be added, based on body's length
|
||||||
|
*/
|
||||||
std::string to_string();
|
std::string to_string();
|
||||||
|
|
||||||
/** @brief Checks that response declared as chunked data */
|
/** @brief Checks that response declared as chunked data */
|
||||||
bool is_chunked();
|
bool is_chunked();
|
||||||
|
|
||||||
/** @brief Returns declared response length or -1 if unknown */
|
|
||||||
long int length();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,6 +134,14 @@ namespace http {
|
|||||||
* @return Decoded string
|
* @return Decoded string
|
||||||
*/
|
*/
|
||||||
std::string UrlDecode(const std::string& data, bool null = false);
|
std::string UrlDecode(const std::string& data, bool null = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Merge HTTP response content with Transfer-Encoding: chunked
|
||||||
|
* @param in Input stream
|
||||||
|
* @param out Output stream
|
||||||
|
* @return true on success, false otherwise
|
||||||
|
*/
|
||||||
|
bool MergeChunkedResponse (std::istream& in, std::ostream& out);
|
||||||
} // http
|
} // http
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/regex.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include "HTTPProxy.h"
|
#include "HTTPProxy.h"
|
||||||
@@ -13,6 +12,7 @@
|
|||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "I2PTunnel.h"
|
#include "I2PTunnel.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "HTTP.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@@ -93,7 +93,7 @@ namespace proxy
|
|||||||
//TODO: handle this apropriately
|
//TODO: handle this apropriately
|
||||||
void HTTPProxyHandler::HTTPRequestFailed(/*HTTPProxyHandler::errTypes error*/)
|
void HTTPProxyHandler::HTTPRequestFailed(/*HTTPProxyHandler::errTypes error*/)
|
||||||
{
|
{
|
||||||
static std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n";
|
static std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n\r\n";
|
||||||
boost::asio::async_write(*m_sock, boost::asio::buffer(response,response.size()),
|
boost::asio::async_write(*m_sock, boost::asio::buffer(response,response.size()),
|
||||||
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
@@ -117,21 +117,14 @@ namespace proxy
|
|||||||
void HTTPProxyHandler::ExtractRequest()
|
void HTTPProxyHandler::ExtractRequest()
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url);
|
LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url);
|
||||||
std::string server="";
|
i2p::http::URL url;
|
||||||
std::string port="80";
|
url.parse (m_url);
|
||||||
boost::regex rHTTP("http://(.*?)(:(\\d+))?(/.*)");
|
m_address = url.host;
|
||||||
boost::smatch m;
|
m_port = url.port;
|
||||||
std::string path;
|
m_path = url.path;
|
||||||
if(boost::regex_search(m_url, m, rHTTP, boost::match_extra))
|
if (url.query.length () > 0) m_path += "?" + url.query;
|
||||||
{
|
if (!m_port) m_port = 80;
|
||||||
server=m[1].str();
|
LogPrint(eLogDebug, "HTTPProxy: server: ", m_address, ", port: ", m_port, ", path: ", m_path);
|
||||||
if (m[2].str() != "") port=m[3].str();
|
|
||||||
path=m[4].str();
|
|
||||||
}
|
|
||||||
LogPrint(eLogDebug, "HTTPProxy: server: ", server, ", port: ", port, ", path: ", path);
|
|
||||||
m_address = server;
|
|
||||||
m_port = boost::lexical_cast<int>(port);
|
|
||||||
m_path = path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTPProxyHandler::ValidateHTTPRequest()
|
bool HTTPProxyHandler::ValidateHTTPRequest()
|
||||||
|
|||||||
250
HTTPServer.cpp
250
HTTPServer.cpp
@@ -1,4 +1,3 @@
|
|||||||
#include <ctime>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@@ -22,162 +21,13 @@
|
|||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "HTTPServer.h"
|
#include "HTTPServer.h"
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
// For image and info
|
// For image and info
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace http {
|
namespace http {
|
||||||
const char *itoopieImage =
|
|
||||||
"<img alt=\"ICToopie Icon\" src=\"data:image/png;base64,"
|
|
||||||
"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\" />";
|
|
||||||
|
|
||||||
const char *itoopieFavicon =
|
const char *itoopieFavicon =
|
||||||
"data:image/png;base64,"
|
"data:image/png;base64,"
|
||||||
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv"
|
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv"
|
||||||
@@ -241,15 +91,15 @@ namespace http {
|
|||||||
|
|
||||||
if ((num = seconds / 86400) > 0) {
|
if ((num = seconds / 86400) > 0) {
|
||||||
s << num << " days, ";
|
s << num << " days, ";
|
||||||
seconds -= num;
|
seconds -= num * 86400;
|
||||||
}
|
}
|
||||||
if ((num = seconds / 3600) > 0) {
|
if ((num = seconds / 3600) > 0) {
|
||||||
s << num << " hours, ";
|
s << num << " hours, ";
|
||||||
seconds -= num;
|
seconds -= num * 3600;
|
||||||
}
|
}
|
||||||
if ((num = seconds / 60) > 0) {
|
if ((num = seconds / 60) > 0) {
|
||||||
s << num << " min, ";
|
s << num << " min, ";
|
||||||
seconds -= num;
|
seconds -= num * 60;
|
||||||
}
|
}
|
||||||
s << seconds << " seconds";
|
s << seconds << " seconds";
|
||||||
}
|
}
|
||||||
@@ -278,7 +128,7 @@ namespace http {
|
|||||||
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
|
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
|
||||||
" <head>\r\n"
|
" <head>\r\n"
|
||||||
" <meta charset=\"UTF-8\">\r\n" /* TODO: Find something to parse html/template system. This is horrible. */
|
" <meta charset=\"UTF-8\">\r\n" /* TODO: Find something to parse html/template system. This is horrible. */
|
||||||
" <link rel='shortcut icon' href='" << itoopieFavicon << "'>\r\n"
|
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
||||||
" <title>Purple I2P " VERSION " Webconsole</title>\r\n"
|
" <title>Purple I2P " VERSION " Webconsole</title>\r\n"
|
||||||
<< cssStyles <<
|
<< cssStyles <<
|
||||||
"</head>\r\n";
|
"</head>\r\n";
|
||||||
@@ -287,15 +137,15 @@ namespace http {
|
|||||||
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
|
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
|
||||||
"<div class=wrapper>\r\n"
|
"<div class=wrapper>\r\n"
|
||||||
"<div class=left>\r\n"
|
"<div class=left>\r\n"
|
||||||
" <a href=/>Main page</a><br>\r\n<br>\r\n"
|
" <a href=\"/\">Main page</a><br>\r\n<br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_COMMANDS << ">Router commands</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << ">Local destinations</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_TUNNELS << ">Tunnels</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << ">Transit tunnels</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_TRANSPORTS << ">Transports</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_I2P_TUNNELS << ">I2P tunnels</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_JUMPSERVICES << ">Jump services</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_JUMPSERVICES << "\">Jump services</a><br>\r\n"
|
||||||
" <a href=/?page=" << HTTP_PAGE_SAM_SESSIONS << ">SAM sessions</a><br>\r\n"
|
" <a href=\"/?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n"
|
||||||
"</div>\r\n"
|
"</div>\r\n"
|
||||||
"<div class=right>";
|
"<div class=right>";
|
||||||
}
|
}
|
||||||
@@ -381,15 +231,15 @@ namespace http {
|
|||||||
clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels();
|
clientTunnelCount += i2p::tunnel::tunnels.CountInboundTunnels();
|
||||||
size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels();
|
size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels();
|
||||||
|
|
||||||
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
|
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
|
||||||
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
|
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowJumpServices (std::stringstream& s, const std::string& address)
|
void ShowJumpServices (std::stringstream& s, const std::string& address)
|
||||||
{
|
{
|
||||||
s << "<form type=\"GET\" action=\"/\">";
|
s << "<form method=\"get\" action=\"/\">";
|
||||||
s << "<input type=\"hidden\" name=\"page\" value=\"jumpservices\">";
|
s << "<input type=\"hidden\" name=\"page\" value=\"jumpservices\">";
|
||||||
s << "<input type=\"text\" name=\"address\" value=\"" << address << "\">";
|
s << "<input type=\"text\" name=\"address\" value=\"" << address << "\">";
|
||||||
s << "<input type=\"submit\" value=\"Update\">";
|
s << "<input type=\"submit\" value=\"Update\">";
|
||||||
s << "</form><br>\r\n";
|
s << "</form><br>\r\n";
|
||||||
s << "<b>Jump services for " << address << "</b>\r\n<ul>\r\n";
|
s << "<b>Jump services for " << address << "</b>\r\n<ul>\r\n";
|
||||||
@@ -405,7 +255,7 @@ namespace http {
|
|||||||
for (auto& it: i2p::client::context.GetDestinations ())
|
for (auto& it: i2p::client::context.GetDestinations ())
|
||||||
{
|
{
|
||||||
auto ident = it.second->GetIdentHash ();;
|
auto ident = it.second->GetIdentHash ();;
|
||||||
s << "<a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << ">";
|
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,21 +359,21 @@ namespace http {
|
|||||||
{
|
{
|
||||||
/* commands */
|
/* commands */
|
||||||
s << "<b>Router Commands</b><br>\r\n";
|
s << "<b>Router Commands</b><br>\r\n";
|
||||||
s << " <a href=/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << ">Run peer test</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "\">Run peer test</a><br>\r\n";
|
||||||
//s << " <a href=/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << ">Reload config</a><br>\r\n";
|
//s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
|
||||||
if (i2p::context.AcceptsTunnels ())
|
if (i2p::context.AcceptsTunnels ())
|
||||||
s << " <a href=/?cmd=" << HTTP_COMMAND_STOP_ACCEPTING_TUNNELS << ">Stop accepting tunnels</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_STOP_ACCEPTING_TUNNELS << "\">Stop accepting tunnels</a><br>\r\n";
|
||||||
else
|
else
|
||||||
s << " <a href=/?cmd=" << HTTP_COMMAND_START_ACCEPTING_TUNNELS << ">Start accepting tunnels</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_START_ACCEPTING_TUNNELS << "\">Start accepting tunnels</a><br>\r\n";
|
||||||
#ifndef WIN32
|
#if (!defined(WIN32) && !defined(QT_GUI_LIB))
|
||||||
if (Daemon.gracefullShutdownInterval) {
|
if (Daemon.gracefullShutdownInterval) {
|
||||||
s << " <a href=/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << ">Cancel gracefull shutdown (";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "\">Cancel gracefull shutdown (";
|
||||||
s << Daemon.gracefullShutdownInterval;
|
s << Daemon.gracefullShutdownInterval;
|
||||||
s << " seconds remains)</a><br>\r\n";
|
s << " seconds remains)</a><br>\r\n";
|
||||||
} else {
|
} else {
|
||||||
s << " <a href=/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << ">Start gracefull shutdown</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "\">Start gracefull shutdown</a><br>\r\n";
|
||||||
}
|
}
|
||||||
s << " <a href=/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << ">Force shutdown</a><br>\r\n";
|
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "\">Force shutdown</a><br>\r\n";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,7 +451,7 @@ namespace http {
|
|||||||
s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n";
|
s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n";
|
||||||
for (auto& it: sam->GetSessions ())
|
for (auto& it: sam->GetSessions ())
|
||||||
{
|
{
|
||||||
s << "<a href=/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << ">";
|
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
|
||||||
s << it.first << "</a><br>\r\n" << std::endl;
|
s << it.first << "</a><br>\r\n" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -620,7 +470,7 @@ namespace http {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ident = session->localDestination->GetIdentHash();
|
auto& ident = session->localDestination->GetIdentHash();
|
||||||
s << "<a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << ">";
|
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
s << "<b>Streams:</b><br>\r\n";
|
s << "<b>Streams:</b><br>\r\n";
|
||||||
@@ -644,7 +494,7 @@ namespace http {
|
|||||||
for (auto& it: i2p::client::context.GetClientTunnels ())
|
for (auto& it: i2p::client::context.GetClientTunnels ())
|
||||||
{
|
{
|
||||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << ">";
|
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << it.second->GetName () << "</a> ⇐ ";
|
s << it.second->GetName () << "</a> ⇐ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << "<br>\r\n"<< std::endl;
|
s << "<br>\r\n"<< std::endl;
|
||||||
@@ -653,7 +503,7 @@ namespace http {
|
|||||||
for (auto& it: i2p::client::context.GetServerTunnels ())
|
for (auto& it: i2p::client::context.GetServerTunnels ())
|
||||||
{
|
{
|
||||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << ">";
|
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << it.second->GetName () << "</a> ⇒ ";
|
s << it.second->GetName () << "</a> ⇒ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << ":" << it.second->GetLocalPort ();
|
s << ":" << it.second->GetLocalPort ();
|
||||||
@@ -668,7 +518,7 @@ namespace http {
|
|||||||
i2p::config::GetOption("http.auth", needAuth);
|
i2p::config::GetOption("http.auth", needAuth);
|
||||||
i2p::config::GetOption("http.user", user);
|
i2p::config::GetOption("http.user", user);
|
||||||
i2p::config::GetOption("http.pass", pass);
|
i2p::config::GetOption("http.pass", pass);
|
||||||
};
|
}
|
||||||
|
|
||||||
void HTTPConnection::Receive ()
|
void HTTPConnection::Receive ()
|
||||||
{
|
{
|
||||||
@@ -749,20 +599,24 @@ namespace http {
|
|||||||
|
|
||||||
if (needAuth && !CheckAuth(req)) {
|
if (needAuth && !CheckAuth(req)) {
|
||||||
res.code = 401;
|
res.code = 401;
|
||||||
res.headers.insert(std::pair<std::string, std::string>("WWW-Authenticate", "Basic realm=\"WebAdmin\""));
|
res.add_header("WWW-Authenticate", "Basic realm=\"WebAdmin\"");
|
||||||
SendReply(res, content);
|
SendReply(res, content);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Html5 head start
|
// Html5 head start
|
||||||
ShowPageHead (s);
|
ShowPageHead (s);
|
||||||
if (req.uri.find("page=") != std::string::npos)
|
if (req.uri.find("page=") != std::string::npos) {
|
||||||
HandlePage (req, res, s);
|
HandlePage (req, res, s);
|
||||||
else if (req.uri.find("cmd=") != std::string::npos)
|
} else if (req.uri.find("cmd=") != std::string::npos) {
|
||||||
HandleCommand (req, res, s);
|
HandleCommand (req, res, s);
|
||||||
else
|
} else {
|
||||||
ShowStatus (s);
|
ShowStatus (s);
|
||||||
|
//res.add_header("Refresh", "5");
|
||||||
|
}
|
||||||
ShowPageTail (s);
|
ShowPageTail (s);
|
||||||
|
|
||||||
|
res.code = 200;
|
||||||
content = s.str ();
|
content = s.str ();
|
||||||
SendReply (res, content);
|
SendReply (res, content);
|
||||||
}
|
}
|
||||||
@@ -824,12 +678,12 @@ namespace http {
|
|||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_START) {
|
else if (cmd == HTTP_COMMAND_SHUTDOWN_START) {
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
#ifndef WIN32
|
#if (!defined(WIN32) && !defined(QT_GUI_LIB))
|
||||||
Daemon.gracefullShutdownInterval = 10*60;
|
Daemon.gracefullShutdownInterval = 10*60;
|
||||||
#endif
|
#endif
|
||||||
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
|
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
#ifndef WIN32
|
#if (!defined(WIN32) && !defined(QT_GUI_LIB))
|
||||||
Daemon.gracefullShutdownInterval = 0;
|
Daemon.gracefullShutdownInterval = 0;
|
||||||
#endif
|
#endif
|
||||||
} else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) {
|
} else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) {
|
||||||
@@ -840,26 +694,18 @@ namespace http {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s << "<b>SUCCESS</b>: Command accepted<br><br>\r\n";
|
s << "<b>SUCCESS</b>: Command accepted<br><br>\r\n";
|
||||||
s << "<a href=\"/?page=commands\">Back to commands list</a>";
|
s << "<a href=\"/?page=commands\">Back to commands list</a><br>\r\n";
|
||||||
|
s << "<p>You will be redirected in 5 seconds</b>";
|
||||||
|
res.add_header("Refresh", "5; url=/?page=commands");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
|
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
|
||||||
{
|
{
|
||||||
std::time_t time_now = std::time(nullptr);
|
reply.add_header("Content-Type", "text/html");
|
||||||
char time_buff[128];
|
reply.body = content;
|
||||||
std::strftime(time_buff, sizeof(time_buff), "%a, %d %b %Y %H:%M:%S GMT", std::gmtime(&time_now));
|
|
||||||
reply.status = HTTPCodeToStatus(reply.code);
|
|
||||||
reply.headers.insert(std::pair<std::string, std::string>("Date", time_buff));
|
|
||||||
reply.headers.insert(std::pair<std::string, std::string>("Content-Type", "text/html"));
|
|
||||||
reply.headers.insert(std::pair<std::string, std::string>("Content-Length", std::to_string(content.size())));
|
|
||||||
|
|
||||||
std::string res = reply.to_string();
|
std::string res = reply.to_string();
|
||||||
std::vector<boost::asio::const_buffer> buffers;
|
boost::asio::async_write (*m_Socket, boost::asio::buffer(res),
|
||||||
|
|
||||||
buffers.push_back(boost::asio::buffer(res));
|
|
||||||
buffers.push_back(boost::asio::buffer(content));
|
|
||||||
|
|
||||||
boost::asio::async_write (*m_Socket, buffers,
|
|
||||||
std::bind (&HTTPConnection::Terminate, shared_from_this (), std::placeholders::_1));
|
std::bind (&HTTPConnection::Terminate, shared_from_this (), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace http {
|
namespace http {
|
||||||
extern const char *itoopieImage;
|
|
||||||
extern const char *itoopieFavicon;
|
extern const char *itoopieFavicon;
|
||||||
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
|
|||||||
671
I2CP.cpp
671
I2CP.cpp
@@ -1,23 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2016, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
|
#include "LeaseSet.h"
|
||||||
|
#include "ClientContext.h"
|
||||||
|
#include "Transports.h"
|
||||||
|
#include "Signature.h"
|
||||||
#include "I2CP.h"
|
#include "I2CP.h"
|
||||||
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
|
|
||||||
|
I2CPDestination::I2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||||
|
LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
||||||
|
{
|
||||||
|
memcpy (m_EncryptionPrivateKey, key, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
uint32_t length = bufbe32toh (buf);
|
||||||
|
if (length > len - 4) length = len - 4;
|
||||||
|
m_Owner->SendMessagePayloadMessage (buf + 4, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
||||||
|
{
|
||||||
|
i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPrivateKey, tunnels); // we don't care about encryption key
|
||||||
|
m_LeaseSetExpirationTime = ls.GetExpirationTime ();
|
||||||
|
uint8_t * leases = ls.GetLeases ();
|
||||||
|
leases[-1] = tunnels.size ();
|
||||||
|
htobe16buf (leases - 3, m_Owner->GetSessionID ());
|
||||||
|
size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size ();
|
||||||
|
m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
auto ls = new i2p::data::LocalLeaseSet (m_Identity, buf, len);
|
||||||
|
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
||||||
|
SetLeaseSet (ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPDestination::SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce)
|
||||||
|
{
|
||||||
|
auto msg = NewI2NPMessage ();
|
||||||
|
uint8_t * buf = msg->GetPayload ();
|
||||||
|
htobe32buf (buf, len);
|
||||||
|
memcpy (buf + 4, payload, len);
|
||||||
|
msg->len += len + 4;
|
||||||
|
msg->FillI2NPMessageHeader (eI2NPData);
|
||||||
|
auto remote = FindLeaseSet (ident);
|
||||||
|
if (remote)
|
||||||
|
GetService ().post (std::bind (&I2CPDestination::SendMsg, GetSharedFromThis (), msg, remote));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto s = GetSharedFromThis ();
|
||||||
|
RequestDestination (ident,
|
||||||
|
[s, msg, nonce](std::shared_ptr<i2p::data::LeaseSet> ls)
|
||||||
|
{
|
||||||
|
if (ls)
|
||||||
|
{
|
||||||
|
bool sent = s->SendMsg (msg, ls);
|
||||||
|
s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s->m_Owner->SendMessageStatusMessage (nonce, eI2CPMessageStatusNoLeaseSet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I2CPDestination::SendMsg (std::shared_ptr<I2NPMessage> msg, std::shared_ptr<const i2p::data::LeaseSet> remote)
|
||||||
|
{
|
||||||
|
auto outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
|
||||||
|
auto leases = remote->GetNonExpiredLeases ();
|
||||||
|
if (!leases.empty () && outboundTunnel)
|
||||||
|
{
|
||||||
|
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||||
|
uint32_t i = rand () % leases.size ();
|
||||||
|
auto garlic = WrapMessage (remote, msg, true);
|
||||||
|
msgs.push_back (i2p::tunnel::TunnelMessageBlock
|
||||||
|
{
|
||||||
|
i2p::tunnel::eDeliveryTypeTunnel,
|
||||||
|
leases[i]->tunnelGateway, leases[i]->tunnelID,
|
||||||
|
garlic
|
||||||
|
});
|
||||||
|
outboundTunnel->SendTunnelDataMsg (msgs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (outboundTunnel)
|
||||||
|
LogPrint (eLogWarning, "I2CP: Failed to send message. All leases expired");
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "I2CP: Failed to send message. No outbound tunnels");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
||||||
m_Owner (owner), m_Socket (socket),
|
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
||||||
m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0)
|
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
I2CPSession::~I2CPSession ()
|
||||||
|
{
|
||||||
|
delete[] m_Payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::Start ()
|
||||||
{
|
{
|
||||||
ReadProtocolByte ();
|
ReadProtocolByte ();
|
||||||
}
|
}
|
||||||
|
|
||||||
I2CPSession::~I2CPSession ()
|
void I2CPSession::Stop ()
|
||||||
{
|
{
|
||||||
delete[] m_NextMessage;
|
Terminate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPSession::ReadProtocolByte ()
|
void I2CPSession::ReadProtocolByte ()
|
||||||
@@ -25,88 +140,542 @@ namespace client
|
|||||||
if (m_Socket)
|
if (m_Socket)
|
||||||
{
|
{
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, 1),
|
m_Socket->async_read_some (boost::asio::buffer (m_Header, 1),
|
||||||
[s](const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
[s](const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
if (!ecode && bytes_transferred > 0 && s->m_Buffer[0] == I2CP_PRTOCOL_BYTE)
|
if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE)
|
||||||
s->Receive ();
|
s->ReceiveHeader ();
|
||||||
else
|
else
|
||||||
s->Terminate ();
|
s->Terminate ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPSession::Receive ()
|
void I2CPSession::ReceiveHeader ()
|
||||||
{
|
{
|
||||||
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, I2CP_SESSION_BUFFER_SIZE),
|
boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Header, I2CP_HEADER_SIZE),
|
||||||
std::bind (&I2CPSession::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
boost::asio::transfer_all (),
|
||||||
|
std::bind (&I2CPSession::HandleReceivedHeader, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPSession::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void I2CPSession::HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
if (ecode)
|
if (ecode)
|
||||||
Terminate ();
|
Terminate ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
m_PayloadLen = bufbe32toh (m_Header + I2CP_HEADER_LENGTH_OFFSET);
|
||||||
if (m_NextMessage)
|
if (m_PayloadLen > 0)
|
||||||
{
|
{
|
||||||
if (m_NextMessageOffset + bytes_transferred <= m_NextMessageLen)
|
m_Payload = new uint8_t[m_PayloadLen];
|
||||||
{
|
ReceivePayload ();
|
||||||
memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred);
|
}
|
||||||
m_NextMessageOffset += bytes_transferred;
|
else // no following payload
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offset = m_NextMessageLen - m_NextMessageOffset;
|
|
||||||
memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, offset);
|
|
||||||
HandleNextMessage (m_NextMessage);
|
|
||||||
delete[] m_NextMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (offset < bytes_transferred)
|
|
||||||
{
|
{
|
||||||
auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE;
|
HandleMessage ();
|
||||||
if (msgLen <= bytes_transferred - offset)
|
ReceiveHeader (); // next message
|
||||||
{
|
}
|
||||||
HandleNextMessage (m_Buffer + offset);
|
|
||||||
offset += msgLen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_NextMessageLen = msgLen;
|
|
||||||
m_NextMessageOffset = bytes_transferred - offset;
|
|
||||||
m_NextMessage = new uint8_t[m_NextMessageLen];
|
|
||||||
memcpy (m_NextMessage, m_Buffer + offset, m_NextMessageOffset);
|
|
||||||
offset = bytes_transferred;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Receive ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPSession::HandleNextMessage (const uint8_t * buf)
|
void I2CPSession::ReceivePayload ()
|
||||||
{
|
{
|
||||||
auto handler = m_Owner.GetMessagesHandlers ()[buf[I2CP_HEADER_TYPE_OFFSET]];
|
boost::asio::async_read (*m_Socket, boost::asio::buffer (m_Payload, m_PayloadLen),
|
||||||
if (handler)
|
boost::asio::transfer_all (),
|
||||||
(this->*handler)(buf + I2CP_HEADER_SIZE, bufbe32toh (buf + I2CP_HEADER_LENGTH_OFFSET));
|
std::bind (&I2CPSession::HandleReceivedPayload, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
if (ecode)
|
||||||
|
Terminate ();
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "I2CP: Unknown I2CP messsage ", (int)buf[I2CP_HEADER_TYPE_OFFSET]);
|
{
|
||||||
|
HandleMessage ();
|
||||||
|
delete[] m_Payload;
|
||||||
|
m_Payload = nullptr;
|
||||||
|
m_PayloadLen = 0;
|
||||||
|
ReceiveHeader (); // next message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::HandleMessage ()
|
||||||
|
{
|
||||||
|
auto handler = m_Owner.GetMessagesHandlers ()[m_Header[I2CP_HEADER_TYPE_OFFSET]];
|
||||||
|
if (handler)
|
||||||
|
(this->*handler)(m_Payload, m_PayloadLen);
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: Unknown I2CP messsage ", (int)m_Header[I2CP_HEADER_TYPE_OFFSET]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPSession::Terminate ()
|
void I2CPSession::Terminate ()
|
||||||
{
|
{
|
||||||
|
if (m_Destination)
|
||||||
|
{
|
||||||
|
m_Destination->Stop ();
|
||||||
|
m_Destination = nullptr;
|
||||||
|
}
|
||||||
|
if (m_Socket)
|
||||||
|
{
|
||||||
|
m_Socket->close ();
|
||||||
|
m_Socket = nullptr;
|
||||||
|
}
|
||||||
|
m_Owner.RemoveSession (GetSessionID ());
|
||||||
|
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " terminated");
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len)
|
||||||
|
{
|
||||||
|
auto socket = m_Socket;
|
||||||
|
if (socket)
|
||||||
|
{
|
||||||
|
auto l = len + I2CP_HEADER_SIZE;
|
||||||
|
uint8_t * buf = new uint8_t[l];
|
||||||
|
htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len);
|
||||||
|
buf[I2CP_HEADER_TYPE_OFFSET] = type;
|
||||||
|
memcpy (buf + I2CP_HEADER_SIZE, payload, len);
|
||||||
|
boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (),
|
||||||
|
std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (),
|
||||||
|
std::placeholders::_1, std::placeholders::_2, buf));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: Can't write to the socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf)
|
||||||
|
{
|
||||||
|
delete[] buf;
|
||||||
|
if (ecode && ecode != boost::asio::error::operation_aborted)
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string I2CPSession::ExtractString (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t l = buf[0];
|
||||||
|
if (l > len) l = len;
|
||||||
|
return std::string ((const char *)(buf + 1), l);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t I2CPSession::PutString (uint8_t * buf, size_t len, const std::string& str)
|
||||||
|
{
|
||||||
|
auto l = str.length ();
|
||||||
|
if (l + 1 >= len) l = len - 1;
|
||||||
|
if (l > 255) l = 255; // 1 byte max
|
||||||
|
buf[0] = l;
|
||||||
|
memcpy (buf + 1, str.c_str (), l);
|
||||||
|
return l + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::ExtractMapping (const uint8_t * buf, size_t len, std::map<std::string, std::string>& mapping)
|
||||||
|
// TODO: move to Base.cpp
|
||||||
|
{
|
||||||
|
size_t offset = 0;
|
||||||
|
while (offset < len)
|
||||||
|
{
|
||||||
|
std::string param = ExtractString (buf + offset, len - offset);
|
||||||
|
offset += param.length () + 1;
|
||||||
|
if (buf[offset] != '=')
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead '=' after ", param);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
std::string value = ExtractString (buf + offset, len - offset);
|
||||||
|
offset += value.length () + 1;
|
||||||
|
if (buf[offset] != ';')
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead ';' after ", value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset++;
|
||||||
|
mapping.insert (std::make_pair (param, value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len)
|
void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
|
// get version
|
||||||
|
auto version = ExtractString (buf, len);
|
||||||
|
auto l = version.length () + 1 + 8;
|
||||||
|
uint8_t * payload = new uint8_t[l];
|
||||||
|
// set date
|
||||||
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
htobe64buf (payload, ts);
|
||||||
|
// echo vesrion back
|
||||||
|
PutString (payload + 8, l - 8, version);
|
||||||
|
SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l);
|
||||||
|
delete[] payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
I2CPServer::I2CPServer (const std::string& interface, int port)
|
void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
RAND_bytes ((uint8_t *)&m_SessionID, 2);
|
||||||
|
auto identity = std::make_shared<i2p::data::IdentityEx>();
|
||||||
|
size_t offset = identity->FromBuffer (buf, len);
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "I2CP: create session maformed identity");
|
||||||
|
SendSessionStatusMessage (3); // invalid
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint16_t optionsSize = bufbe16toh (buf + offset);
|
||||||
|
offset += 2;
|
||||||
|
if (optionsSize > len - offset)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "I2CP: options size ", optionsSize, "exceeds message size");
|
||||||
|
SendSessionStatusMessage (3); // invalid
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::map<std::string, std::string> params;
|
||||||
|
ExtractMapping (buf + offset, optionsSize, params);
|
||||||
|
offset += optionsSize; // options
|
||||||
|
if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false;
|
||||||
|
|
||||||
|
offset += 8; // date
|
||||||
|
if (identity->Verify (buf, offset, buf + offset)) // signature
|
||||||
|
{
|
||||||
|
bool isPublic = true;
|
||||||
|
if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false;
|
||||||
|
if (!m_Destination)
|
||||||
|
{
|
||||||
|
m_Destination = std::make_shared<I2CPDestination>(shared_from_this (), identity, isPublic, params);
|
||||||
|
SendSessionStatusMessage (1); // created
|
||||||
|
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created");
|
||||||
|
m_Destination->Start ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "I2CP: session already exists");
|
||||||
|
SendSessionStatusMessage (4); // refused
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "I2CP: create session signature verification falied");
|
||||||
|
SendSessionStatusMessage (3); // invalid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::DestroySessionMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
SendSessionStatusMessage (0); // destroy
|
||||||
|
LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " destroyed");
|
||||||
|
if (m_Destination)
|
||||||
|
{
|
||||||
|
m_Destination->Stop ();
|
||||||
|
m_Destination = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
// TODO: implement actual reconfiguration
|
||||||
|
SendSessionStatusMessage (2); // updated
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendSessionStatusMessage (uint8_t status)
|
||||||
|
{
|
||||||
|
uint8_t buf[3];
|
||||||
|
htobe16buf (buf, m_SessionID);
|
||||||
|
buf[2] = status;
|
||||||
|
SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status)
|
||||||
|
{
|
||||||
|
if (!nonce) return; // don't send status with zero nonce
|
||||||
|
uint8_t buf[15];
|
||||||
|
htobe16buf (buf, m_SessionID);
|
||||||
|
htobe32buf (buf + 2, m_MessageID++);
|
||||||
|
buf[6] = (uint8_t)status;
|
||||||
|
memset (buf + 7, 0, 4); // size
|
||||||
|
htobe32buf (buf + 11, nonce);
|
||||||
|
SendI2CPMessage (I2CP_MESSAGE_STATUS_MESSAGE, buf, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
uint16_t sessionID = bufbe16toh (buf);
|
||||||
|
if (sessionID == m_SessionID)
|
||||||
|
{
|
||||||
|
size_t offset = 2;
|
||||||
|
if (m_Destination)
|
||||||
|
{
|
||||||
|
offset += i2p::crypto::DSA_PRIVATE_KEY_LENGTH; // skip signing private key
|
||||||
|
// we always assume this field as 20 bytes (DSA) regardless actual size
|
||||||
|
// instead of
|
||||||
|
//offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen ();
|
||||||
|
m_Destination->SetEncryptionPrivateKey (buf + offset);
|
||||||
|
offset += 256;
|
||||||
|
m_Destination->LeaseSetCreated (buf + offset, len - offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendMessageMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
uint16_t sessionID = bufbe16toh (buf);
|
||||||
|
if (sessionID == m_SessionID)
|
||||||
|
{
|
||||||
|
size_t offset = 2;
|
||||||
|
if (m_Destination)
|
||||||
|
{
|
||||||
|
i2p::data::IdentityEx identity;
|
||||||
|
offset += identity.FromBuffer (buf + offset, len - offset);
|
||||||
|
uint32_t payloadLen = bufbe32toh (buf + offset);
|
||||||
|
offset += 4;
|
||||||
|
uint32_t nonce = bufbe32toh (buf + offset + payloadLen);
|
||||||
|
if (m_IsSendAccepted)
|
||||||
|
SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted
|
||||||
|
m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
SendMessageMessageHandler (buf, len - 8); // ignore flags(2) and expiration(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
uint16_t sessionID = bufbe16toh (buf);
|
||||||
|
if (sessionID == m_SessionID || sessionID == 0xFFFF) // -1 means without session
|
||||||
|
{
|
||||||
|
uint32_t requestID = bufbe32toh (buf + 2);
|
||||||
|
//uint32_t timeout = bufbe32toh (buf + 6);
|
||||||
|
i2p::data::IdentHash ident;
|
||||||
|
switch (buf[10])
|
||||||
|
{
|
||||||
|
case 0: // hash
|
||||||
|
ident = i2p::data::IdentHash (buf + 11);
|
||||||
|
break;
|
||||||
|
case 1: // address
|
||||||
|
{
|
||||||
|
auto name = ExtractString (buf + 11, len - 11);
|
||||||
|
if (!i2p::client::context.GetAddressBook ().GetIdentHash (name, ident))
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "I2CP: address ", name, " not found");
|
||||||
|
SendHostReplyMessage (requestID, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LogPrint (eLogError, "I2CP: request type ", (int)buf[10], " is not supported");
|
||||||
|
SendHostReplyMessage (requestID, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<LeaseSetDestination> destination = m_Destination;
|
||||||
|
if(!destination) destination = i2p::client::context.GetSharedLocalDestination ();
|
||||||
|
if (destination)
|
||||||
|
{
|
||||||
|
auto ls = destination->FindLeaseSet (ident);
|
||||||
|
if (ls)
|
||||||
|
SendHostReplyMessage (requestID, ls->GetIdentity ());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
destination->RequestDestination (ident,
|
||||||
|
[s, requestID](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||||
|
{
|
||||||
|
s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SendHostReplyMessage (requestID, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendHostReplyMessage (uint32_t requestID, std::shared_ptr<const i2p::data::IdentityEx> identity)
|
||||||
|
{
|
||||||
|
if (identity)
|
||||||
|
{
|
||||||
|
size_t l = identity->GetFullLen () + 7;
|
||||||
|
uint8_t * buf = new uint8_t[l];
|
||||||
|
htobe16buf (buf, m_SessionID);
|
||||||
|
htobe32buf (buf + 2, requestID);
|
||||||
|
buf[6] = 0; // result code
|
||||||
|
identity->ToBuffer (buf + 7, l - 7);
|
||||||
|
SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, l);
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t buf[7];
|
||||||
|
htobe16buf (buf, m_SessionID);
|
||||||
|
htobe32buf (buf + 2, requestID);
|
||||||
|
buf[6] = 1; // result code
|
||||||
|
SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::DestLookupMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
if (m_Destination)
|
||||||
|
{
|
||||||
|
auto ls = m_Destination->FindLeaseSet (buf);
|
||||||
|
if (ls)
|
||||||
|
{
|
||||||
|
auto l = ls->GetIdentity ()->GetFullLen ();
|
||||||
|
uint8_t * identBuf = new uint8_t[l];
|
||||||
|
ls->GetIdentity ()->ToBuffer (identBuf, l);
|
||||||
|
SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, identBuf, l);
|
||||||
|
delete[] identBuf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
i2p::data::IdentHash ident (buf);
|
||||||
|
m_Destination->RequestDestination (ident,
|
||||||
|
[s, ident](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||||
|
{
|
||||||
|
if (leaseSet) // found
|
||||||
|
{
|
||||||
|
auto l = leaseSet->GetIdentity ()->GetFullLen ();
|
||||||
|
uint8_t * identBuf = new uint8_t[l];
|
||||||
|
leaseSet->GetIdentity ()->ToBuffer (identBuf, l);
|
||||||
|
s->SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, identBuf, l);
|
||||||
|
delete[] identBuf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s->SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, ident, 32); // not found
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t limits[64];
|
||||||
|
memset (limits, 0, 64);
|
||||||
|
htobe32buf (limits, i2p::transport::transports.GetInBandwidth ()); // inbound
|
||||||
|
htobe32buf (limits + 4, i2p::transport::transports.GetOutBandwidth ()); // outbound
|
||||||
|
SendI2CPMessage (I2CP_BANDWIDTH_LIMITS_MESSAGE, limits, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPSession::SendMessagePayloadMessage (const uint8_t * payload, size_t len)
|
||||||
|
{
|
||||||
|
// we don't use SendI2CPMessage to eliminate additional copy
|
||||||
|
auto l = len + 10 + I2CP_HEADER_SIZE;
|
||||||
|
uint8_t * buf = new uint8_t[l];
|
||||||
|
htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len + 10);
|
||||||
|
buf[I2CP_HEADER_TYPE_OFFSET] = I2CP_MESSAGE_PAYLOAD_MESSAGE;
|
||||||
|
htobe16buf (buf + I2CP_HEADER_SIZE, m_SessionID);
|
||||||
|
htobe32buf (buf + I2CP_HEADER_SIZE + 2, m_MessageID++);
|
||||||
|
htobe32buf (buf + I2CP_HEADER_SIZE + 6, len);
|
||||||
|
memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len);
|
||||||
|
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (),
|
||||||
|
std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (),
|
||||||
|
std::placeholders::_1, std::placeholders::_2, buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
I2CPServer::I2CPServer (const std::string& interface, int port):
|
||||||
|
m_IsRunning (false), m_Thread (nullptr),
|
||||||
|
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port))
|
||||||
{
|
{
|
||||||
memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers));
|
memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers));
|
||||||
m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler;
|
m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE] = &I2CPSession::CreateSessionMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_DESTROY_SESSION_MESSAGE] = &I2CPSession::DestroySessionMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_RECONFIGURE_SESSION_MESSAGE] = &I2CPSession::ReconfigureSessionMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler;
|
||||||
|
m_MessagesHandlers[I2CP_GET_BANDWIDTH_LIMITS_MESSAGE] = &I2CPSession::GetBandwidthLimitsMessageHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
I2CPServer::~I2CPServer ()
|
||||||
|
{
|
||||||
|
if (m_IsRunning)
|
||||||
|
Stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPServer::Start ()
|
||||||
|
{
|
||||||
|
Accept ();
|
||||||
|
m_IsRunning = true;
|
||||||
|
m_Thread = new std::thread (std::bind (&I2CPServer::Run, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPServer::Stop ()
|
||||||
|
{
|
||||||
|
m_IsRunning = false;
|
||||||
|
m_Acceptor.cancel ();
|
||||||
|
for (auto it: m_Sessions)
|
||||||
|
it.second->Stop ();
|
||||||
|
m_Sessions.clear ();
|
||||||
|
m_Service.stop ();
|
||||||
|
if (m_Thread)
|
||||||
|
{
|
||||||
|
m_Thread->join ();
|
||||||
|
delete m_Thread;
|
||||||
|
m_Thread = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPServer::Run ()
|
||||||
|
{
|
||||||
|
while (m_IsRunning)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Service.run ();
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "I2CP: runtime exception: ", ex.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPServer::Accept ()
|
||||||
|
{
|
||||||
|
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service);
|
||||||
|
m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this,
|
||||||
|
std::placeholders::_1, newSocket));
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPServer::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket)
|
||||||
|
{
|
||||||
|
if (!ecode && socket)
|
||||||
|
{
|
||||||
|
boost::system::error_code ec;
|
||||||
|
auto ep = socket->remote_endpoint (ec);
|
||||||
|
if (!ec)
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "I2CP: new connection from ", ep);
|
||||||
|
auto session = std::make_shared<I2CPSession>(*this, socket);
|
||||||
|
m_Sessions[session->GetSessionID ()] = session;
|
||||||
|
session->Start ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: incoming connection error ", ec.message ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "I2CP: accept error: ", ecode.message ());
|
||||||
|
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
Accept ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2CPServer::RemoveSession (uint16_t sessionID)
|
||||||
|
{
|
||||||
|
m_Sessions.erase (sessionID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
142
I2CP.h
142
I2CP.h
@@ -1,16 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2016, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef I2CP_H__
|
#ifndef I2CP_H__
|
||||||
#define I2CP_H__
|
#define I2CP_H__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <map>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
#include "Destination.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
const uint8_t I2CP_PRTOCOL_BYTE = 0x2A;
|
const uint8_t I2CP_PROTOCOL_BYTE = 0x2A;
|
||||||
const size_t I2CP_SESSION_BUFFER_SIZE = 4096;
|
const size_t I2CP_SESSION_BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
|
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
|
||||||
@@ -18,6 +29,70 @@ namespace client
|
|||||||
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
|
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
|
||||||
|
|
||||||
const uint8_t I2CP_GET_DATE_MESSAGE = 32;
|
const uint8_t I2CP_GET_DATE_MESSAGE = 32;
|
||||||
|
const uint8_t I2CP_SET_DATE_MESSAGE = 33;
|
||||||
|
const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1;
|
||||||
|
const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2;
|
||||||
|
const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20;
|
||||||
|
const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3;
|
||||||
|
const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37;
|
||||||
|
const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4;
|
||||||
|
const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5;
|
||||||
|
const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36;
|
||||||
|
const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31;
|
||||||
|
const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22;
|
||||||
|
const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38;
|
||||||
|
const uint8_t I2CP_HOST_REPLY_MESSAGE = 39;
|
||||||
|
const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34;
|
||||||
|
const uint8_t I2CP_DEST_REPLY_MESSAGE = 35;
|
||||||
|
const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8;
|
||||||
|
const uint8_t I2CP_BANDWIDTH_LIMITS_MESSAGE = 23;
|
||||||
|
|
||||||
|
enum I2CPMessageStatus
|
||||||
|
{
|
||||||
|
eI2CPMessageStatusAccepted = 1,
|
||||||
|
eI2CPMessageStatusGuaranteedSuccess = 4,
|
||||||
|
eI2CPMessageStatusGuaranteedFailure = 5,
|
||||||
|
eI2CPMessageStatusNoLeaseSet = 21
|
||||||
|
};
|
||||||
|
|
||||||
|
// params
|
||||||
|
const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet";
|
||||||
|
const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability";
|
||||||
|
|
||||||
|
class I2CPSession;
|
||||||
|
class I2CPDestination: public LeaseSetDestination
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
I2CPDestination (std::shared_ptr<I2CPSession> owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params);
|
||||||
|
|
||||||
|
void SetEncryptionPrivateKey (const uint8_t * key);
|
||||||
|
void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession
|
||||||
|
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
|
||||||
|
|
||||||
|
// implements LocalDestination
|
||||||
|
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
||||||
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Identity; };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// I2CP
|
||||||
|
void HandleDataMessage (const uint8_t * buf, size_t len);
|
||||||
|
void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::shared_ptr<I2CPDestination> GetSharedFromThis ()
|
||||||
|
{ return std::static_pointer_cast<I2CPDestination>(shared_from_this ()); }
|
||||||
|
bool SendMsg (std::shared_ptr<I2NPMessage> msg, std::shared_ptr<const i2p::data::LeaseSet> remote);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::shared_ptr<I2CPSession> m_Owner;
|
||||||
|
std::shared_ptr<const i2p::data::IdentityEx> m_Identity;
|
||||||
|
uint8_t m_EncryptionPrivateKey[256];
|
||||||
|
uint64_t m_LeaseSetExpirationTime;
|
||||||
|
};
|
||||||
|
|
||||||
class I2CPServer;
|
class I2CPServer;
|
||||||
class I2CPSession: public std::enable_shared_from_this<I2CPSession>
|
class I2CPSession: public std::enable_shared_from_this<I2CPSession>
|
||||||
@@ -27,23 +102,56 @@ namespace client
|
|||||||
I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||||
~I2CPSession ();
|
~I2CPSession ();
|
||||||
|
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
uint16_t GetSessionID () const { return m_SessionID; };
|
||||||
|
|
||||||
|
// called from I2CPDestination
|
||||||
|
void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len);
|
||||||
|
void SendMessagePayloadMessage (const uint8_t * payload, size_t len);
|
||||||
|
void SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status);
|
||||||
|
|
||||||
// message handlers
|
// message handlers
|
||||||
void GetDateMessageHandler (const uint8_t * buf, size_t len);
|
void GetDateMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void CreateSessionMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void DestroySessionMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void SendMessageMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void HostLookupMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void DestLookupMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
void GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ReadProtocolByte ();
|
void ReadProtocolByte ();
|
||||||
void Receive ();
|
void ReceiveHeader ();
|
||||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleNextMessage (const uint8_t * buf);
|
void ReceivePayload ();
|
||||||
|
void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
|
void HandleMessage ();
|
||||||
void Terminate ();
|
void Terminate ();
|
||||||
|
|
||||||
|
void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf);
|
||||||
|
std::string ExtractString (const uint8_t * buf, size_t len);
|
||||||
|
size_t PutString (uint8_t * buf, size_t len, const std::string& str);
|
||||||
|
void ExtractMapping (const uint8_t * buf, size_t len, std::map<std::string, std::string>& mapping);
|
||||||
|
|
||||||
|
void SendSessionStatusMessage (uint8_t status);
|
||||||
|
void SendHostReplyMessage (uint32_t requestID, std::shared_ptr<const i2p::data::IdentityEx> identity);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
I2CPServer& m_Owner;
|
I2CPServer& m_Owner;
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
||||||
uint8_t m_Buffer[I2CP_SESSION_BUFFER_SIZE], * m_NextMessage;
|
uint8_t m_Header[I2CP_HEADER_SIZE], * m_Payload;
|
||||||
size_t m_NextMessageLen, m_NextMessageOffset;
|
size_t m_PayloadLen;
|
||||||
|
|
||||||
|
std::shared_ptr<I2CPDestination> m_Destination;
|
||||||
|
uint16_t m_SessionID;
|
||||||
|
uint32_t m_MessageID;
|
||||||
|
bool m_IsSendAccepted;
|
||||||
};
|
};
|
||||||
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len);
|
typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
@@ -52,10 +160,30 @@ namespace client
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
I2CPServer (const std::string& interface, int port);
|
I2CPServer (const std::string& interface, int port);
|
||||||
|
~I2CPServer ();
|
||||||
|
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
boost::asio::io_service& GetService () { return m_Service; };
|
||||||
|
|
||||||
|
void RemoveSession (uint16_t sessionID);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Run ();
|
||||||
|
|
||||||
|
void Accept ();
|
||||||
|
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
I2CPMessageHandler m_MessagesHandlers[256];
|
I2CPMessageHandler m_MessagesHandlers[256];
|
||||||
|
std::map<uint16_t, std::shared_ptr<I2CPSession> > m_Sessions;
|
||||||
|
|
||||||
|
bool m_IsRunning;
|
||||||
|
std::thread * m_Thread;
|
||||||
|
boost::asio::io_service m_Service;
|
||||||
|
boost::asio::ip::tcp::acceptor m_Acceptor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,23 @@ namespace i2p
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LeaseSet> leaseSet, uint32_t replyToken)
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
|
||||||
|
{
|
||||||
|
if (!leaseSet) return nullptr;
|
||||||
|
auto m = NewI2NPShortMessage ();
|
||||||
|
uint8_t * payload = m->GetPayload ();
|
||||||
|
memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32);
|
||||||
|
payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet
|
||||||
|
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
|
||||||
|
size_t size = DATABASE_STORE_HEADER_SIZE;
|
||||||
|
memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
|
||||||
|
size += leaseSet->GetBufferLen ();
|
||||||
|
m->len += size;
|
||||||
|
m->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
|
||||||
{
|
{
|
||||||
if (!leaseSet) return nullptr;
|
if (!leaseSet) return nullptr;
|
||||||
auto m = NewI2NPShortMessage ();
|
auto m = NewI2NPShortMessage ();
|
||||||
@@ -258,14 +274,13 @@ namespace i2p
|
|||||||
payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet
|
payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet
|
||||||
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken);
|
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken);
|
||||||
size_t size = DATABASE_STORE_HEADER_SIZE;
|
size_t size = DATABASE_STORE_HEADER_SIZE;
|
||||||
if (replyToken)
|
if (replyToken && replyTunnel)
|
||||||
{
|
{
|
||||||
auto leases = leaseSet->GetNonExpiredLeases ();
|
if (replyTunnel)
|
||||||
if (leases.size () > 0)
|
|
||||||
{
|
{
|
||||||
htobe32buf (payload + size, leases[0]->tunnelID);
|
htobe32buf (payload + size, replyTunnel->GetNextTunnelID ());
|
||||||
size += 4; // reply tunnelID
|
size += 4; // reply tunnelID
|
||||||
memcpy (payload + size, leases[0]->tunnelGateway, 32);
|
memcpy (payload + size, replyTunnel->GetNextIdentHash (), 32);
|
||||||
size += 32; // reply tunnel gateway
|
size += 32; // reply tunnel gateway
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -224,7 +224,8 @@ namespace tunnel
|
|||||||
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
|
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0);
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0);
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LeaseSet> leaseSet, uint32_t replyToken = 0);
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LeaseSet> leaseSet); // for floodfill only
|
||||||
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken = 0, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel = nullptr);
|
||||||
bool IsRouterInfoMsg (std::shared_ptr<I2NPMessage> msg);
|
bool IsRouterInfoMsg (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
|
||||||
bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText);
|
bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText);
|
||||||
|
|||||||
164
I2PControl.cpp
164
I2PControl.cpp
@@ -2,8 +2,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/date_time/local_time/local_time.hpp>
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
#include <boost/property_tree/ini_parser.hpp>
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
|
|
||||||
@@ -16,6 +14,7 @@
|
|||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "HTTP.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
@@ -24,6 +23,7 @@
|
|||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "util.h"
|
||||||
#include "I2PControl.h"
|
#include "I2PControl.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@@ -189,71 +189,64 @@ namespace client
|
|||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
|
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
bool isHtml = !memcmp (buf->data (), "POST", 4);
|
|
||||||
std::stringstream ss;
|
|
||||||
ss.write (buf->data (), bytes_transferred);
|
|
||||||
if (isHtml)
|
|
||||||
{
|
|
||||||
std::string header;
|
|
||||||
size_t contentLength = 0;
|
|
||||||
while (!ss.eof () && header != "\r")
|
|
||||||
{
|
|
||||||
std::getline(ss, header);
|
|
||||||
auto colon = header.find (':');
|
|
||||||
if (colon != std::string::npos && header.substr (0, colon) == "Content-Length")
|
|
||||||
contentLength = std::stoi (header.substr (colon + 1));
|
|
||||||
}
|
|
||||||
if (ss.eof ())
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "I2PControl: malformed request, HTTP header expected");
|
|
||||||
return; // TODO:
|
|
||||||
}
|
|
||||||
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
|
|
||||||
if (rem > 0)
|
|
||||||
{
|
|
||||||
bytes_transferred = boost::asio::read (*socket, boost::asio::buffer (buf->data (), rem));
|
|
||||||
ss.write (buf->data (), bytes_transferred);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::ostringstream response;
|
|
||||||
#if GCC47_BOOST149
|
|
||||||
LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7");
|
|
||||||
response << "{\"id\":null,\"error\":";
|
|
||||||
response << "{\"code\":-32603,\"message\":\"JSON requests is not supported with this version of boost\"},";
|
|
||||||
response << "\"jsonrpc\":\"2.0\"}";
|
|
||||||
#else
|
|
||||||
boost::property_tree::ptree pt;
|
|
||||||
boost::property_tree::read_json (ss, pt);
|
|
||||||
|
|
||||||
std::string id = pt.get<std::string>("id");
|
|
||||||
std::string method = pt.get<std::string>("method");
|
|
||||||
auto it = m_MethodHandlers.find (method);
|
|
||||||
if (it != m_MethodHandlers.end ())
|
|
||||||
{
|
|
||||||
response << "{\"id\":" << id << ",\"result\":{";
|
|
||||||
(this->*(it->second))(pt.get_child ("params"), response);
|
|
||||||
response << "},\"jsonrpc\":\"2.0\"}";
|
|
||||||
} else {
|
|
||||||
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
|
|
||||||
response << "{\"id\":null,\"error\":";
|
|
||||||
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
|
||||||
response << "\"jsonrpc\":\"2.0\"}";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
SendResponse (socket, buf, response, isHtml);
|
|
||||||
}
|
|
||||||
catch (std::exception& ex)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "I2PControl: handle request unknown exception");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* try to parse received data */
|
||||||
|
std::stringstream json;
|
||||||
|
std::string response;
|
||||||
|
bool isHTTP = false;
|
||||||
|
if (memcmp (buf->data (), "POST", 4) == 0) {
|
||||||
|
long int remains = 0;
|
||||||
|
isHTTP = true;
|
||||||
|
i2p::http::HTTPReq req;
|
||||||
|
std::size_t len = req.parse(buf->data(), bytes_transferred);
|
||||||
|
if (len <= 0) {
|
||||||
|
LogPrint(eLogError, "I2PControl: incomplete/malformed POST request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* append to json chunk of data from 1st request */
|
||||||
|
json.write(buf->begin() + len, bytes_transferred - len);
|
||||||
|
remains = req.length() - len;
|
||||||
|
/* if request has Content-Length header, fetch rest of data and store to json buffer */
|
||||||
|
while (remains > 0) {
|
||||||
|
len = ((long int) buf->size() < remains) ? buf->size() : remains;
|
||||||
|
bytes_transferred = boost::asio::read (*socket, boost::asio::buffer (buf->data (), len));
|
||||||
|
json.write(buf->begin(), bytes_transferred);
|
||||||
|
remains -= bytes_transferred;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
json.write(buf->begin(), bytes_transferred);
|
||||||
|
}
|
||||||
|
LogPrint(eLogDebug, "I2PControl: json from request: ", json.str());
|
||||||
|
#if GCC47_BOOST149
|
||||||
|
LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7");
|
||||||
|
BuildErrorResponse(response, 32603, "JSON requests is not supported with this version of boost");
|
||||||
|
#else
|
||||||
|
/* now try to parse json itself */
|
||||||
|
try {
|
||||||
|
boost::property_tree::ptree pt;
|
||||||
|
boost::property_tree::read_json (json, pt);
|
||||||
|
|
||||||
|
std::string id = pt.get<std::string>("id");
|
||||||
|
std::string method = pt.get<std::string>("method");
|
||||||
|
auto it = m_MethodHandlers.find (method);
|
||||||
|
if (it != m_MethodHandlers.end ()) {
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "{\"id\":" << id << ",\"result\":{";
|
||||||
|
(this->*(it->second))(pt.get_child ("params"), ss);
|
||||||
|
ss << "},\"jsonrpc\":\"2.0\"}";
|
||||||
|
response = ss.str();
|
||||||
|
} else {
|
||||||
|
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
|
||||||
|
BuildErrorResponse(response, 32601, "Method not found");
|
||||||
|
}
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
|
||||||
|
BuildErrorResponse(response, 32603, ex.what());
|
||||||
|
} catch (...) {
|
||||||
|
LogPrint (eLogError, "I2PControl: handle request unknown exception");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
SendResponse (socket, buf, response, isHTTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
|
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
|
||||||
@@ -275,27 +268,28 @@ namespace client
|
|||||||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I2PControlService::BuildErrorResponse (std::string & content, int code, const char *message) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "{\"id\":null,\"error\":";
|
||||||
|
ss << "{\"code\":" << -code << ",\"message\":\"" << message << "\"},";
|
||||||
|
ss << "\"jsonrpc\":\"2.0\"}";
|
||||||
|
content = ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
std::shared_ptr<I2PControlBuffer> buf, std::string& content, bool isHTTP)
|
||||||
{
|
{
|
||||||
size_t len = response.str ().length (), offset = 0;
|
if (isHTTP) {
|
||||||
if (isHtml)
|
i2p::http::HTTPRes res;
|
||||||
{
|
res.code = 200;
|
||||||
std::ostringstream header;
|
res.add_header("Content-Type", "application/json");
|
||||||
header << "HTTP/1.1 200 OK\r\n";
|
res.add_header("Connection", "close");
|
||||||
header << "Connection: close\r\n";
|
res.body = content;
|
||||||
header << "Content-Length: " << boost::lexical_cast<std::string>(len) << "\r\n";
|
std::string tmp = res.to_string();
|
||||||
header << "Content-Type: application/json\r\n";
|
content = tmp;
|
||||||
header << "Date: ";
|
|
||||||
auto facet = new boost::local_time::local_time_facet ("%a, %d %b %Y %H:%M:%S GMT");
|
|
||||||
header.imbue(std::locale (header.getloc(), facet));
|
|
||||||
header << boost::posix_time::second_clock::local_time() << "\r\n";
|
|
||||||
header << "\r\n";
|
|
||||||
offset = header.str ().size ();
|
|
||||||
memcpy (buf->data (), header.str ().c_str (), offset);
|
|
||||||
}
|
}
|
||||||
memcpy (buf->data () + offset, response.str ().c_str (), len);
|
std::copy(content.begin(), content.end(), buf->begin());
|
||||||
boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), offset + len),
|
boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), content.length()),
|
||||||
boost::asio::transfer_all (),
|
boost::asio::transfer_all (),
|
||||||
std::bind(&I2PControlService::HandleResponseSent, this,
|
std::bind(&I2PControlService::HandleResponseSent, this,
|
||||||
std::placeholders::_1, std::placeholders::_2, socket, buf));
|
std::placeholders::_1, std::placeholders::_2, socket, buf));
|
||||||
@@ -322,7 +316,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
InsertParam (results, "API", api);
|
InsertParam (results, "API", api);
|
||||||
results << ",";
|
results << ",";
|
||||||
std::string token = boost::lexical_cast<std::string>(i2p::util::GetSecondsSinceEpoch ());
|
std::string token = std::to_string(i2p::util::GetSecondsSinceEpoch ());
|
||||||
m_Tokens.insert (token);
|
m_Tokens.insert (token);
|
||||||
InsertParam (results, "Token", token);
|
InsertParam (results, "Token", token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,9 @@ namespace client
|
|||||||
void ReadRequest (std::shared_ptr<ssl_socket> socket);
|
void ReadRequest (std::shared_ptr<ssl_socket> socket);
|
||||||
void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred,
|
void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred,
|
||||||
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
|
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
|
||||||
|
void BuildErrorResponse (std::string & content, int code, const char *message);
|
||||||
void SendResponse (std::shared_ptr<ssl_socket> socket,
|
void SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml);
|
std::shared_ptr<I2PControlBuffer> buf, std::string& response, bool isHtml);
|
||||||
void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
||||||
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
|
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "I2PService.h"
|
#include "I2PService.h"
|
||||||
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace client
|
namespace client
|
||||||
@@ -28,7 +27,7 @@ namespace client
|
|||||||
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
|
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "I2PService: Remote destination ", dest, " not found");
|
LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
|
||||||
streamRequestComplete (nullptr);
|
streamRequestComplete (nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +70,7 @@ namespace client
|
|||||||
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
|
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "TCPIPPipe: no upstream socket for read");
|
LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,14 +81,14 @@ namespace client
|
|||||||
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
|
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "TCPIPPipe: no downstream socket for read");
|
LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPIPPipe::UpstreamWrite(const uint8_t * buf, size_t len)
|
void TCPIPPipe::UpstreamWrite(const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
if (m_up) {
|
if (m_up) {
|
||||||
LogPrint(eLogDebug, "TCPIPPipe: write upstream ", (int)len);
|
LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written");
|
||||||
boost::asio::async_write(*m_up, boost::asio::buffer(buf, len),
|
boost::asio::async_write(*m_up, boost::asio::buffer(buf, len),
|
||||||
boost::asio::transfer_all(),
|
boost::asio::transfer_all(),
|
||||||
std::bind(&TCPIPPipe::HandleUpstreamWrite,
|
std::bind(&TCPIPPipe::HandleUpstreamWrite,
|
||||||
@@ -97,14 +96,14 @@ namespace client
|
|||||||
std::placeholders::_1)
|
std::placeholders::_1)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "tcpip pipe upstream socket null");
|
LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TCPIPPipe::DownstreamWrite(const uint8_t * buf, size_t len)
|
void TCPIPPipe::DownstreamWrite(const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
if (m_down) {
|
if (m_down) {
|
||||||
LogPrint(eLogDebug, "TCPIPPipe: write downstream ", (int)len);
|
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written");
|
||||||
boost::asio::async_write(*m_down, boost::asio::buffer(buf, len),
|
boost::asio::async_write(*m_down, boost::asio::buffer(buf, len),
|
||||||
boost::asio::transfer_all(),
|
boost::asio::transfer_all(),
|
||||||
std::bind(&TCPIPPipe::HandleDownstreamWrite,
|
std::bind(&TCPIPPipe::HandleDownstreamWrite,
|
||||||
@@ -112,16 +111,16 @@ namespace client
|
|||||||
std::placeholders::_1)
|
std::placeholders::_1)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "tcpip pipe downstream socket null");
|
LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
|
void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "TCPIPPipe downstream got ", (int) bytes_transfered);
|
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received");
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint(eLogError, "TCPIPPipe Downstream read error:" , ecode.message());
|
LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
Terminate();
|
Terminate();
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +134,7 @@ namespace client
|
|||||||
|
|
||||||
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
|
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint(eLogError, "TCPIPPipe Downstream write error:" , ecode.message());
|
LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
Terminate();
|
Terminate();
|
||||||
}
|
}
|
||||||
@@ -143,7 +142,7 @@ namespace client
|
|||||||
|
|
||||||
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
|
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint(eLogError, "TCPIPPipe Upstream write error:" , ecode.message());
|
LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
Terminate();
|
Terminate();
|
||||||
}
|
}
|
||||||
@@ -151,9 +150,9 @@ namespace client
|
|||||||
|
|
||||||
void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
|
void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "TCPIPPipe upstream got ", (int) bytes_transfered);
|
LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received");
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint(eLogError, "TCPIPPipe Upstream read error:" , ecode.message());
|
LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
Terminate();
|
Terminate();
|
||||||
} else {
|
} else {
|
||||||
@@ -206,6 +205,5 @@ namespace client
|
|||||||
LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
|
LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,16 +178,10 @@ namespace data
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~LocalDestination() {};
|
virtual ~LocalDestination() {};
|
||||||
virtual const PrivateKeys& GetPrivateKeys () const = 0;
|
|
||||||
virtual const uint8_t * GetEncryptionPrivateKey () const = 0;
|
virtual const uint8_t * GetEncryptionPrivateKey () const = 0;
|
||||||
virtual const uint8_t * GetEncryptionPublicKey () const = 0;
|
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
|
||||||
|
|
||||||
std::shared_ptr<const IdentityEx> GetIdentity () const { return GetPrivateKeys ().GetPublic (); };
|
|
||||||
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
|
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
|
||||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
|
||||||
{
|
|
||||||
GetPrivateKeys ().Sign (buf, len, signature);
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
105
LeaseSet.cpp
105
LeaseSet.cpp
@@ -4,7 +4,7 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
#include "TunnelPool.h"
|
#include "Tunnel.h"
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@@ -21,56 +21,6 @@ namespace data
|
|||||||
ReadFromBuffer ();
|
ReadFromBuffer ();
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaseSet::LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool):
|
|
||||||
m_IsValid (true), m_StoreLeases (true), m_ExpirationTime (0)
|
|
||||||
{
|
|
||||||
if (!pool) return;
|
|
||||||
// header
|
|
||||||
auto localDestination = pool->GetLocalDestination ();
|
|
||||||
if (!localDestination)
|
|
||||||
{
|
|
||||||
m_Buffer = nullptr;
|
|
||||||
m_BufferLen = 0;
|
|
||||||
m_IsValid = false;
|
|
||||||
LogPrint (eLogError, "LeaseSet: Destination for local LeaseSet doesn't exist");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_Buffer = new uint8_t[MAX_LS_BUFFER_SIZE];
|
|
||||||
m_BufferLen = localDestination->GetIdentity ()->ToBuffer (m_Buffer, MAX_LS_BUFFER_SIZE);
|
|
||||||
memcpy (m_Buffer + m_BufferLen, localDestination->GetEncryptionPublicKey (), 256);
|
|
||||||
m_BufferLen += 256;
|
|
||||||
auto signingKeyLen = localDestination->GetIdentity ()->GetSigningPublicKeyLen ();
|
|
||||||
memset (m_Buffer + m_BufferLen, 0, signingKeyLen);
|
|
||||||
m_BufferLen += signingKeyLen;
|
|
||||||
int numTunnels = pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
|
|
||||||
if (numTunnels > 16) numTunnels = 16; // 16 tunnels maximum
|
|
||||||
auto tunnels = pool->GetInboundTunnels (numTunnels);
|
|
||||||
m_Buffer[m_BufferLen] = tunnels.size (); // num leases
|
|
||||||
m_BufferLen++;
|
|
||||||
// leases
|
|
||||||
auto currentTime = i2p::util::GetMillisecondsSinceEpoch ();
|
|
||||||
for (auto it: tunnels)
|
|
||||||
{
|
|
||||||
memcpy (m_Buffer + m_BufferLen, it->GetNextIdentHash (), 32);
|
|
||||||
m_BufferLen += 32; // gateway id
|
|
||||||
htobe32buf (m_Buffer + m_BufferLen, it->GetNextTunnelID ());
|
|
||||||
m_BufferLen += 4; // tunnel id
|
|
||||||
uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration
|
|
||||||
ts *= 1000; // in milliseconds
|
|
||||||
if (ts > m_ExpirationTime) m_ExpirationTime = ts;
|
|
||||||
// make sure leaseset is newer than previous, but adding some time to expiration date
|
|
||||||
ts += (currentTime - it->GetCreationTime ()*1000LL)*2/i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT; // up to 2 secs
|
|
||||||
htobe64buf (m_Buffer + m_BufferLen, ts);
|
|
||||||
m_BufferLen += 8; // end date
|
|
||||||
}
|
|
||||||
// signature
|
|
||||||
localDestination->Sign (m_Buffer, m_BufferLen, m_Buffer + m_BufferLen);
|
|
||||||
m_BufferLen += localDestination->GetIdentity ()->GetSignatureLen ();
|
|
||||||
LogPrint (eLogDebug, "LeaseSet: Local LeaseSet of ", tunnels.size (), " leases created");
|
|
||||||
|
|
||||||
ReadFromBuffer ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LeaseSet::Update (const uint8_t * buf, size_t len)
|
void LeaseSet::Update (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
if (len > m_BufferLen)
|
if (len > m_BufferLen)
|
||||||
@@ -195,7 +145,7 @@ namespace data
|
|||||||
if (size > len) return 0;
|
if (size > len) return 0;
|
||||||
uint8_t num = buf[size];
|
uint8_t num = buf[size];
|
||||||
size++; // num
|
size++; // num
|
||||||
if (size + num*44 > len) return 0;
|
if (size + num*LEASE_SIZE > len) return 0;
|
||||||
uint64_t timestamp= 0 ;
|
uint64_t timestamp= 0 ;
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
@@ -243,6 +193,57 @@ namespace data
|
|||||||
if (IsEmpty ()) return true;
|
if (IsEmpty ()) return true;
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
return ts > m_ExpirationTime;
|
return ts > m_ExpirationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
||||||
|
m_ExpirationTime (0), m_Identity (identity)
|
||||||
|
{
|
||||||
|
int num = tunnels.size ();
|
||||||
|
if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES;
|
||||||
|
// identity
|
||||||
|
auto signingKeyLen = m_Identity->GetSigningPublicKeyLen ();
|
||||||
|
m_BufferLen = m_Identity->GetFullLen () + 256 + signingKeyLen + 1 + num*LEASE_SIZE + m_Identity->GetSignatureLen ();
|
||||||
|
m_Buffer = new uint8_t[m_BufferLen];
|
||||||
|
auto offset = m_Identity->ToBuffer (m_Buffer, m_BufferLen);
|
||||||
|
memcpy (m_Buffer + offset, encryptionPublicKey, 256);
|
||||||
|
offset += 256;
|
||||||
|
memset (m_Buffer + offset, 0, signingKeyLen);
|
||||||
|
offset += signingKeyLen;
|
||||||
|
// num leases
|
||||||
|
m_Buffer[offset] = num;
|
||||||
|
offset++;
|
||||||
|
// leases
|
||||||
|
m_Leases = m_Buffer + offset;
|
||||||
|
auto currentTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
memcpy (m_Buffer + offset, tunnels[i]->GetNextIdentHash (), 32);
|
||||||
|
offset += 32; // gateway id
|
||||||
|
htobe32buf (m_Buffer + offset, tunnels[i]->GetNextTunnelID ());
|
||||||
|
offset += 4; // tunnel id
|
||||||
|
uint64_t ts = tunnels[i]->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration
|
||||||
|
ts *= 1000; // in milliseconds
|
||||||
|
if (ts > m_ExpirationTime) m_ExpirationTime = ts;
|
||||||
|
// make sure leaseset is newer than previous, but adding some time to expiration date
|
||||||
|
ts += (currentTime - tunnels[i]->GetCreationTime ()*1000LL)*2/i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT; // up to 2 secs
|
||||||
|
htobe64buf (m_Buffer + offset, ts);
|
||||||
|
offset += 8; // end date
|
||||||
|
}
|
||||||
|
// we don't sign it yet. must be signed later on
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
|
||||||
|
m_ExpirationTime (0), m_Identity (identity)
|
||||||
|
{
|
||||||
|
m_BufferLen = len;
|
||||||
|
m_Buffer = new uint8_t[m_BufferLen];
|
||||||
|
memcpy (m_Buffer, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocalLeaseSet::IsExpired () const
|
||||||
|
{
|
||||||
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
|
return ts > m_ExpirationTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
LeaseSet.h
37
LeaseSet.h
@@ -4,6 +4,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ namespace i2p
|
|||||||
|
|
||||||
namespace tunnel
|
namespace tunnel
|
||||||
{
|
{
|
||||||
class TunnelPool;
|
class InboundTunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace data
|
namespace data
|
||||||
@@ -37,14 +38,14 @@ namespace data
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const int MAX_LS_BUFFER_SIZE = 3072;
|
const size_t MAX_LS_BUFFER_SIZE = 3072;
|
||||||
|
const size_t LEASE_SIZE = 44; // 32 + 4 + 8
|
||||||
const uint8_t MAX_NUM_LEASES = 16;
|
const uint8_t MAX_NUM_LEASES = 16;
|
||||||
class LeaseSet: public RoutingDestination
|
class LeaseSet: public RoutingDestination
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true);
|
LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true);
|
||||||
LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool);
|
|
||||||
~LeaseSet () { delete[] m_Buffer; };
|
~LeaseSet () { delete[] m_Buffer; };
|
||||||
void Update (const uint8_t * buf, size_t len);
|
void Update (const uint8_t * buf, size_t len);
|
||||||
bool IsNewer (const uint8_t * buf, size_t len) const;
|
bool IsNewer (const uint8_t * buf, size_t len) const;
|
||||||
@@ -82,6 +83,36 @@ namespace data
|
|||||||
uint8_t * m_Buffer;
|
uint8_t * m_Buffer;
|
||||||
size_t m_BufferLen;
|
size_t m_BufferLen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LocalLeaseSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
|
||||||
|
LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len);
|
||||||
|
~LocalLeaseSet () { delete[] m_Buffer; };
|
||||||
|
|
||||||
|
const uint8_t * GetBuffer () const { return m_Buffer; };
|
||||||
|
uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); };
|
||||||
|
size_t GetBufferLen () const { return m_BufferLen; };
|
||||||
|
size_t GetSignatureLen () const { return m_Identity->GetSignatureLen (); };
|
||||||
|
uint8_t * GetLeases () { return m_Leases; };
|
||||||
|
|
||||||
|
const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); };
|
||||||
|
bool IsExpired () const;
|
||||||
|
uint64_t GetExpirationTime () const { return m_ExpirationTime; };
|
||||||
|
void SetExpirationTime (uint64_t expirationTime) { m_ExpirationTime = expirationTime; };
|
||||||
|
bool operator== (const LeaseSet& other) const
|
||||||
|
{ return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); };
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint64_t m_ExpirationTime; // in milliseconds
|
||||||
|
std::shared_ptr<const IdentityEx> m_Identity;
|
||||||
|
uint8_t * m_Buffer, * m_Leases;
|
||||||
|
size_t m_BufferLen;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
Log.cpp
20
Log.cpp
@@ -12,7 +12,7 @@ namespace i2p {
|
|||||||
namespace log {
|
namespace log {
|
||||||
Log logger;
|
Log logger;
|
||||||
/**
|
/**
|
||||||
* @enum Maps our loglevel to their symbolic name
|
* @brief Maps our loglevel to their symbolic name
|
||||||
*/
|
*/
|
||||||
static const char * g_LogLevelStr[eNumLogLevels] =
|
static const char * g_LogLevelStr[eNumLogLevels] =
|
||||||
{
|
{
|
||||||
@@ -56,7 +56,7 @@ namespace log {
|
|||||||
#endif
|
#endif
|
||||||
case eLogFile:
|
case eLogFile:
|
||||||
case eLogStream:
|
case eLogStream:
|
||||||
m_LogStream->flush();
|
if (m_LogStream) m_LogStream->flush();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
@@ -107,10 +107,11 @@ namespace log {
|
|||||||
#endif
|
#endif
|
||||||
case eLogFile:
|
case eLogFile:
|
||||||
case eLogStream:
|
case eLogStream:
|
||||||
*m_LogStream << TimeAsString(msg->timestamp)
|
if (m_LogStream)
|
||||||
<< "@" << short_tid
|
*m_LogStream << TimeAsString(msg->timestamp)
|
||||||
<< "/" << g_LogLevelStr[msg->level]
|
<< "@" << short_tid
|
||||||
<< " - " << msg->text << std::endl;
|
<< "/" << g_LogLevelStr[msg->level]
|
||||||
|
<< " - " << msg->text << std::endl;
|
||||||
break;
|
break;
|
||||||
case eLogStdout:
|
case eLogStdout:
|
||||||
default:
|
default:
|
||||||
@@ -130,10 +131,13 @@ namespace log {
|
|||||||
Process();
|
Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SendTo (const std::string& path) {
|
void Log::SendTo (const std::string& path)
|
||||||
|
{
|
||||||
|
if (m_LogStream) m_LogStream = nullptr; // close previous
|
||||||
auto flags = std::ofstream::out | std::ofstream::app;
|
auto flags = std::ofstream::out | std::ofstream::app;
|
||||||
auto os = std::make_shared<std::ofstream> (path, flags);
|
auto os = std::make_shared<std::ofstream> (path, flags);
|
||||||
if (os->is_open ()) {
|
if (os->is_open ())
|
||||||
|
{
|
||||||
m_Logfile = path;
|
m_Logfile = path;
|
||||||
m_Destination = eLogFile;
|
m_Destination = eLogFile;
|
||||||
m_LogStream = os;
|
m_LogStream = os;
|
||||||
|
|||||||
7
Log.h
7
Log.h
@@ -86,7 +86,7 @@ namespace log {
|
|||||||
LogLevel GetLogLevel () { return m_MinLevel; };
|
LogLevel GetLogLevel () { return m_MinLevel; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets minimal alloed level for log messages
|
* @brief Sets minimal allowed level for log messages
|
||||||
* @param level String with wanted minimal msg level
|
* @param level String with wanted minimal msg level
|
||||||
*/
|
*/
|
||||||
void SetLogLevel (const std::string& level);
|
void SetLogLevel (const std::string& level);
|
||||||
@@ -101,7 +101,7 @@ namespace log {
|
|||||||
* @brief Sets log destination to given output stream
|
* @brief Sets log destination to given output stream
|
||||||
* @param os Output stream
|
* @param os Output stream
|
||||||
*/
|
*/
|
||||||
void SendTo (std::shared_ptr<std::ostream> s);
|
void SendTo (std::shared_ptr<std::ostream> os);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/**
|
/**
|
||||||
@@ -129,7 +129,8 @@ namespace log {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct Log message container
|
* @struct LogMsg
|
||||||
|
* @brief Log message container
|
||||||
*
|
*
|
||||||
* We creating it somewhere with LogPrint(),
|
* We creating it somewhere with LogPrint(),
|
||||||
* then put in MsgQueue for later processing.
|
* then put in MsgQueue for later processing.
|
||||||
|
|||||||
5
Makefile
5
Makefile
@@ -76,6 +76,7 @@ $(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf obj
|
rm -rf obj
|
||||||
|
rm -rf docs/generated
|
||||||
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
|
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
|
||||||
|
|
||||||
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
|
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
|
||||||
@@ -86,9 +87,13 @@ dist:
|
|||||||
git archive --format=tar.gz -9 --worktree-attributes \
|
git archive --format=tar.gz -9 --worktree-attributes \
|
||||||
--prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz
|
--prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz
|
||||||
|
|
||||||
|
doxygen:
|
||||||
|
doxygen -s docs/Doxyfile
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
.PHONY: deps
|
.PHONY: deps
|
||||||
|
.PHONY: doxygen
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
.PHONY: api
|
.PHONY: api
|
||||||
.PHONY: api_client
|
.PHONY: api_client
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ CXXFLAGS = -O2
|
|||||||
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
|
||||||
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ CXX = clang++
|
|||||||
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX
|
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX
|
||||||
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
||||||
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
|
|
||||||
ifeq ($(USE_UPNP),1)
|
ifeq ($(USE_UPNP),1)
|
||||||
LDFLAGS += -ldl
|
LDFLAGS += -ldl
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# set defaults instead redefine
|
# set defaults instead redefine
|
||||||
CXXFLAGS ?= -g -Wall
|
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic
|
||||||
INCFLAGS ?=
|
INCFLAGS ?=
|
||||||
|
|
||||||
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time
|
||||||
@@ -32,7 +32,6 @@ ifeq ($(USE_STATIC),yes)
|
|||||||
LDLIBS = $(LIBDIR)/libboost_system.a
|
LDLIBS = $(LIBDIR)/libboost_system.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_regex.a
|
|
||||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||||
LDLIBS += $(LIBDIR)/libcrypto.a
|
LDLIBS += $(LIBDIR)/libcrypto.a
|
||||||
LDLIBS += $(LIBDIR)/libssl.a
|
LDLIBS += $(LIBDIR)/libssl.a
|
||||||
@@ -40,7 +39,7 @@ ifeq ($(USE_STATIC),yes)
|
|||||||
LDLIBS += -lpthread -static-libstdc++ -static-libgcc
|
LDLIBS += -lpthread -static-libstdc++ -static-libgcc
|
||||||
USE_AESNI := no
|
USE_AESNI := no
|
||||||
else
|
else
|
||||||
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# UPNP Support (miniupnpc 1.5 or 1.6)
|
# UPNP Support (miniupnpc 1.5 or 1.6)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ LDLIBS = \
|
|||||||
-Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \
|
-Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \
|
-Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \
|
-Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) \
|
|
||||||
-Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \
|
-Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lssl \
|
-Wl,-Bstatic -lssl \
|
||||||
-Wl,-Bstatic -lcrypto \
|
-Wl,-Bstatic -lcrypto \
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX
|
|||||||
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
||||||
INCFLAGS = -I/usr/local/include -I/usr/local/ssl/include
|
INCFLAGS = -I/usr/local/include -I/usr/local/ssl/include
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib
|
||||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread
|
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
|
|
||||||
ifeq ($(USE_UPNP),1)
|
ifeq ($(USE_UPNP),1)
|
||||||
LDFLAGS += -ldl
|
LDFLAGS += -ldl
|
||||||
|
|||||||
@@ -849,7 +849,8 @@ namespace data
|
|||||||
template<typename Filter>
|
template<typename Filter>
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (Filter filter) const
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (Filter filter) const
|
||||||
{
|
{
|
||||||
if (!m_RouterInfos.size ()) return 0;
|
if (m_RouterInfos.empty())
|
||||||
|
return 0;
|
||||||
uint32_t ind = rand () % m_RouterInfos.size ();
|
uint32_t ind = rand () % m_RouterInfos.size ();
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -1,13 +1,43 @@
|
|||||||
i2pd
|
i2pd
|
||||||
====
|
====
|
||||||
|
|
||||||
Independent C++ implementation of I2P router
|
i2pd is a full-featured C++ implementation of
|
||||||
|
[I2P](https://geti2p.net/en/about/intro) client.
|
||||||
|
|
||||||
License
|
I2P (Invisible Internet Project) is anonymous network which works on top of
|
||||||
-------
|
public Internet. Privacy and anonymity are achieved by strong encryption and
|
||||||
|
bouncing your traffic through thousands of I2P nodes all around the world.
|
||||||
|
|
||||||
This project is licensed under the BSD 3-clause license, which can be found in the file
|
We are building network which helps people to communicate and share information
|
||||||
LICENSE in the root of the project source code.
|
without restrictions.
|
||||||
|
|
||||||
|
* [Website](http://i2pd.website)
|
||||||
|
* [Documentation](https://i2pd.readthedocs.io/en/latest/)
|
||||||
|
* [Wiki](https://github.com/PurpleI2P/i2pd/wiki)
|
||||||
|
* [Tickets/Issues](https://github.com/PurpleI2P/i2pd/issues)
|
||||||
|
* [Twitter](https://twitter.com/i2porignal)
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------
|
||||||
|
|
||||||
|
The easiest way to install i2pd is by using
|
||||||
|
[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest).
|
||||||
|
See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build
|
||||||
|
i2pd from source on your OS.
|
||||||
|
|
||||||
|
**Supported systems:**
|
||||||
|
|
||||||
|
* Linux x86/x64 - [](https://travis-ci.org/PurpleI2P/i2pd)
|
||||||
|
* Windows - [](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
||||||
|
* Mac OS X
|
||||||
|
* FreeBSD
|
||||||
|
* Android *(coming soon)*
|
||||||
|
|
||||||
|
Using i2pd
|
||||||
|
----------
|
||||||
|
|
||||||
|
See [documentation](https://i2pd.readthedocs.io/en/latest/) and
|
||||||
|
[example config file](https://github.com/PurpleI2P/i2pd/blob/openssl/docs/i2pd.conf).
|
||||||
|
|
||||||
Donations
|
Donations
|
||||||
---------
|
---------
|
||||||
@@ -17,22 +47,8 @@ LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59
|
|||||||
ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z
|
ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z
|
||||||
DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y
|
DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y
|
||||||
|
|
||||||
Documentation:
|
License
|
||||||
--------------
|
-------
|
||||||
http://i2pd.readthedocs.org
|
|
||||||
|
|
||||||
Supported OS
|
This project is licensed under the BSD 3-clause license, which can be found in the file
|
||||||
------------
|
LICENSE in the root of the project source code.
|
||||||
|
|
||||||
* Linux x86/x64 - [](https://travis-ci.org/PurpleI2P/i2pd)
|
|
||||||
* Windows - [](https://ci.appveyor.com/project/PurpleI2P/i2pd)
|
|
||||||
* Mac OS X
|
|
||||||
* FreeBSD
|
|
||||||
|
|
||||||
More documentation
|
|
||||||
------------------
|
|
||||||
|
|
||||||
* [Building from source / unix](docs/build_notes_unix.md)
|
|
||||||
* [Building from source / windows](docs/build_notes_windows.md)
|
|
||||||
* [Configuring your i2pd](docs/configuration.md)
|
|
||||||
* [Github wiki](https://github.com/PurpleI2P/i2pd/wiki/)
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <boost/regex.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/asio/ssl.hpp>
|
#include <boost/asio/ssl.hpp>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
@@ -17,7 +16,6 @@
|
|||||||
#include "NetDb.h"
|
#include "NetDb.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
@@ -374,7 +372,7 @@ namespace data
|
|||||||
boost::asio::io_service service;
|
boost::asio::io_service service;
|
||||||
boost::system::error_code ecode;
|
boost::system::error_code ecode;
|
||||||
auto it = boost::asio::ip::tcp::resolver(service).resolve (
|
auto it = boost::asio::ip::tcp::resolver(service).resolve (
|
||||||
boost::asio::ip::tcp::resolver::query (u.host_, std::to_string (u.port_)), ecode);
|
boost::asio::ip::tcp::resolver::query (u.host_, std::to_string (u.port_)), ecode);
|
||||||
if (!ecode)
|
if (!ecode)
|
||||||
{
|
{
|
||||||
boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23);
|
boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ namespace i2p
|
|||||||
routerInfo.AddNTCPAddress (host.c_str(), port);
|
routerInfo.AddNTCPAddress (host.c_str(), port);
|
||||||
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
|
||||||
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
|
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
|
||||||
routerInfo.SetProperty ("netId", std::to_string (I2PD_NET_ID));
|
routerInfo.SetProperty ("netId", std::to_string (I2PD_NET_ID));
|
||||||
routerInfo.SetProperty ("router.version", I2P_VERSION);
|
routerInfo.SetProperty ("router.version", I2P_VERSION);
|
||||||
routerInfo.CreateBuffer (m_Keys);
|
routerInfo.CreateBuffer (m_Keys);
|
||||||
m_RouterInfo.SetRouterIdentity (GetIdentity ());
|
m_RouterInfo.SetRouterIdentity (GetIdentity ());
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace i2p
|
|||||||
RouterContext ();
|
RouterContext ();
|
||||||
void Init ();
|
void Init ();
|
||||||
|
|
||||||
|
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
||||||
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
|
i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; };
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> GetSharedRouterInfo () const
|
std::shared_ptr<const i2p::data::RouterInfo> GetSharedRouterInfo () const
|
||||||
{
|
{
|
||||||
@@ -73,13 +74,14 @@ namespace i2p
|
|||||||
void UpdateStats ();
|
void UpdateStats ();
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||||
const uint8_t * GetEncryptionPrivateKey () const { return m_Keys.GetPrivateKey (); };
|
const uint8_t * GetEncryptionPrivateKey () const { return m_Keys.GetPrivateKey (); };
|
||||||
const uint8_t * GetEncryptionPublicKey () const { return GetIdentity ()->GetStandardIdentity ().publicKey; };
|
const uint8_t * GetEncryptionPublicKey () const { return GetIdentity ()->GetStandardIdentity ().publicKey; };
|
||||||
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
|
||||||
void SetLeaseSetUpdated () {};
|
void SetLeaseSetUpdated () {};
|
||||||
|
|
||||||
// implements GarlicDestination
|
// implements GarlicDestination
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> GetLeaseSet () { return nullptr; };
|
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () { return nullptr; };
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const;
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const;
|
||||||
void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
|
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ namespace data
|
|||||||
if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable
|
if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable
|
||||||
if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable
|
if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable
|
||||||
|
|
||||||
SetProperty ("caps", caps.c_str ());
|
SetProperty ("caps", caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::WriteToStream (std::ostream& s)
|
void RouterInfo::WriteToStream (std::ostream& s)
|
||||||
|
|||||||
@@ -232,6 +232,11 @@ namespace stream
|
|||||||
bool acknowledged = false;
|
bool acknowledged = false;
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
uint32_t ackThrough = packet->GetAckThrough ();
|
uint32_t ackThrough = packet->GetAckThrough ();
|
||||||
|
if (ackThrough > m_SequenceNumber)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Streaming: Unexpected ackThrough=", ackThrough, " > seqn=", m_SequenceNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int nackCount = packet->GetNACKCount ();
|
int nackCount = packet->GetNACKCount ();
|
||||||
for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();)
|
for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();)
|
||||||
{
|
{
|
||||||
@@ -336,9 +341,9 @@ namespace stream
|
|||||||
htobe32buf (packet + size, m_SequenceNumber++);
|
htobe32buf (packet + size, m_SequenceNumber++);
|
||||||
size += 4; // sequenceNum
|
size += 4; // sequenceNum
|
||||||
if (isNoAck)
|
if (isNoAck)
|
||||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
|
||||||
else
|
|
||||||
htobuf32 (packet + size, 0);
|
htobuf32 (packet + size, 0);
|
||||||
|
else
|
||||||
|
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
||||||
size += 4; // ack Through
|
size += 4; // ack Through
|
||||||
packet[size] = 0;
|
packet[size] = 0;
|
||||||
size++; // NACK count
|
size++; // NACK count
|
||||||
@@ -521,7 +526,7 @@ namespace stream
|
|||||||
size += 4; // receiveStreamID
|
size += 4; // receiveStreamID
|
||||||
htobe32buf (packet + size, m_SequenceNumber++);
|
htobe32buf (packet + size, m_SequenceNumber++);
|
||||||
size += 4; // sequenceNum
|
size += 4; // sequenceNum
|
||||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0);
|
||||||
size += 4; // ack Through
|
size += 4; // ack Through
|
||||||
packet[size] = 0;
|
packet[size] = 0;
|
||||||
size++; // NACK count
|
size++; // NACK count
|
||||||
|
|||||||
@@ -456,8 +456,13 @@ namespace transport
|
|||||||
{
|
{
|
||||||
m_SSUServer->DeleteSession (ssuSession);
|
m_SSUServer->DeleteSession (ssuSession);
|
||||||
LogPrint (eLogDebug, "Transports: SSU session closed");
|
LogPrint (eLogDebug, "Transports: SSU session closed");
|
||||||
}
|
}
|
||||||
// TODO: delete NTCP
|
auto ntcpSession = m_NTCPServer ? m_NTCPServer->FindNTCPSession(router->GetIdentHash()) : nullptr;
|
||||||
|
if (ntcpSession) // try deleting ntcp session too
|
||||||
|
{
|
||||||
|
ntcpSession->Terminate ();
|
||||||
|
LogPrint(eLogDebug, "Transports: NTCP session closed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transports::DetectExternalIP ()
|
void Transports::DetectExternalIP ()
|
||||||
@@ -606,7 +611,7 @@ namespace transport
|
|||||||
|
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer () const
|
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRandomPeer () const
|
||||||
{
|
{
|
||||||
if (!m_Peers.size ()) return nullptr;
|
if (m_Peers.empty ()) return nullptr;
|
||||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||||
auto it = m_Peers.begin ();
|
auto it = m_Peers.begin ();
|
||||||
std::advance (it, rand () % m_Peers.size ());
|
std::advance (it, rand () % m_Peers.size ());
|
||||||
|
|||||||
12
Tunnel.cpp
12
Tunnel.cpp
@@ -358,7 +358,7 @@ namespace tunnel
|
|||||||
|
|
||||||
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
|
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
|
||||||
{
|
{
|
||||||
if (!m_OutboundTunnels.size ()) return nullptr;
|
if (m_OutboundTunnels.empty ()) return nullptr;
|
||||||
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
|
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0;
|
||||||
std::shared_ptr<OutboundTunnel> tunnel;
|
std::shared_ptr<OutboundTunnel> tunnel;
|
||||||
for (auto it: m_OutboundTunnels)
|
for (auto it: m_OutboundTunnels)
|
||||||
@@ -562,7 +562,7 @@ namespace tunnel
|
|||||||
case eTunnelStatePending:
|
case eTunnelStatePending:
|
||||||
if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT)
|
if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Tunnel: pending build request ", it->first, " timeout, deleted");
|
LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " timeout, deleted");
|
||||||
// update stats
|
// update stats
|
||||||
auto config = tunnel->GetTunnelConfig ();
|
auto config = tunnel->GetTunnelConfig ();
|
||||||
if (config)
|
if (config)
|
||||||
@@ -587,7 +587,7 @@ namespace tunnel
|
|||||||
it++;
|
it++;
|
||||||
break;
|
break;
|
||||||
case eTunnelStateBuildFailed:
|
case eTunnelStateBuildFailed:
|
||||||
LogPrint (eLogWarning, "Tunnel: pending build request ", it->first, " failed, deleted");
|
LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted");
|
||||||
it = pendingTunnels.erase (it);
|
it = pendingTunnels.erase (it);
|
||||||
m_NumFailedTunnelCreations++;
|
m_NumFailedTunnelCreations++;
|
||||||
break;
|
break;
|
||||||
@@ -861,6 +861,12 @@ namespace tunnel
|
|||||||
// TODO: locking
|
// TODO: locking
|
||||||
return m_OutboundTunnels.size();
|
return m_OutboundTunnels.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ANDROID_ARM7A
|
||||||
|
template std::shared_ptr<InboundTunnel> Tunnels::CreateTunnel<InboundTunnel>(std::shared_ptr<TunnelConfig>, std::shared_ptr<OutboundTunnel>);
|
||||||
|
template std::shared_ptr<OutboundTunnel> Tunnels::CreateTunnel<OutboundTunnel>(std::shared_ptr<TunnelConfig>, std::shared_ptr<OutboundTunnel>);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
Tunnel.h
2
Tunnel.h
@@ -73,7 +73,7 @@ namespace tunnel
|
|||||||
|
|
||||||
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
||||||
|
|
||||||
virtual void Print (std::stringstream& s) const {};
|
virtual void Print (std::stringstream&) const {};
|
||||||
|
|
||||||
// implements TunnelBase
|
// implements TunnelBase
|
||||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ install:
|
|||||||
- cd %BOOST_ROOT%
|
- cd %BOOST_ROOT%
|
||||||
- if defined msvc if not exist "stage%bitness%\lib\%boostlib%boost_system-vc%msvc%0-mt%boostdbg%*" (
|
- if defined msvc if not exist "stage%bitness%\lib\%boostlib%boost_system-vc%msvc%0-mt%boostdbg%*" (
|
||||||
bootstrap > c:\projects\instdir\build_boost.log
|
bootstrap > c:\projects\instdir\build_boost.log
|
||||||
&& b2 toolset=msvc-%msvc%.0 %boost_variant% link=%type% runtime-link=%type% address-model=%bitness% --build-type=minimal --with-filesystem --with-program_options --with-regex --with-date_time --stagedir=stage%bitness% >> c:\projects\instdir\build_boost.log
|
&& b2 toolset=msvc-%msvc%.0 %boost_variant% link=%type% runtime-link=%type% address-model=%bitness% --build-type=minimal --with-filesystem --with-program_options --with-date_time --stagedir=stage%bitness% >> c:\projects\instdir\build_boost.log
|
||||||
|| type c:\projects\instdir\build_boost.log
|
|| type c:\projects\instdir\build_boost.log
|
||||||
)
|
)
|
||||||
- if defined msvc if not exist C:\stage\OpenSSL-Win%bitness%-vc%msvc%-%type%\ (
|
- if defined msvc if not exist C:\stage\OpenSSL-Win%bitness%-vc%msvc%-%type%\ (
|
||||||
|
|||||||
10
build/.gitignore
vendored
Normal file
10
build/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Various generated files
|
||||||
|
/CMakeFiles/
|
||||||
|
/i2pd
|
||||||
|
/libi2pd.a
|
||||||
|
/libi2pdclient.a
|
||||||
|
/cmake_install.cmake
|
||||||
|
/CMakeCache.txt
|
||||||
|
/CPackConfig.cmake
|
||||||
|
/CPackSourceConfig.cmake
|
||||||
|
/install_manifest.txt
|
||||||
@@ -242,7 +242,7 @@ endif()
|
|||||||
|
|
||||||
target_link_libraries(i2pdclient libi2pd)
|
target_link_libraries(i2pdclient libi2pd)
|
||||||
|
|
||||||
find_package ( Boost COMPONENTS system filesystem regex program_options date_time REQUIRED )
|
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
||||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||||
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu
|
FROM ubuntu
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \
|
RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \
|
||||||
libboost-program-options-dev libboost-regex-dev libboost-date-time-dev \
|
libboost-program-options-dev libboost-date-time-dev \
|
||||||
libssl-dev git build-essential
|
libssl-dev git build-essential
|
||||||
|
|
||||||
RUN git clone https://github.com/PurpleI2P/i2pd.git
|
RUN git clone https://github.com/PurpleI2P/i2pd.git
|
||||||
|
|||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
|||||||
|
i2pd (2.7.0-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* updated to version 2.7.0/0.9.25
|
||||||
|
|
||||||
|
-- hagen <hagen@i2pmail.org> Wed, 18 May 2016 01:11:04 +0000
|
||||||
|
|
||||||
i2pd (2.2.0-2) unstable; urgency=low
|
i2pd (2.2.0-2) unstable; urgency=low
|
||||||
|
|
||||||
* updated to version 2.2.0
|
* updated to version 2.2.0
|
||||||
|
|||||||
1
debian/control
vendored
1
debian/control
vendored
@@ -4,7 +4,6 @@ Priority: extra
|
|||||||
Maintainer: hagen <hagen@i2pmail.org>
|
Maintainer: hagen <hagen@i2pmail.org>
|
||||||
Build-Depends: debhelper (>= 9.0.0), dpkg-dev (>= 1.16.1~),
|
Build-Depends: debhelper (>= 9.0.0), dpkg-dev (>= 1.16.1~),
|
||||||
gcc (>= 4.7) | clang (>= 3.3),
|
gcc (>= 4.7) | clang (>= 3.3),
|
||||||
libboost-regex-dev,
|
|
||||||
libboost-system-dev (>= 1.46),
|
libboost-system-dev (>= 1.46),
|
||||||
libboost-date-time-dev,
|
libboost-date-time-dev,
|
||||||
libboost-filesystem-dev,
|
libboost-filesystem-dev,
|
||||||
|
|||||||
3
debian/i2pd.1
vendored
3
debian/i2pd.1
vendored
@@ -36,6 +36,9 @@ Where to write pidfile (don\'t write by default)
|
|||||||
\fB\-\-log=\fR
|
\fB\-\-log=\fR
|
||||||
Logs destination: \fIstdout\fR, \fIfile\fR, \fIsyslog\fR (\fIstdout\fR if not set, \fIfile\fR - otherwise, for compatibility)
|
Logs destination: \fIstdout\fR, \fIfile\fR, \fIsyslog\fR (\fIstdout\fR if not set, \fIfile\fR - otherwise, for compatibility)
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-logfile\fR
|
||||||
|
Path to logfile (default - autodetect)
|
||||||
|
.TP
|
||||||
\fB\-\-loglevel=\fR
|
\fB\-\-loglevel=\fR
|
||||||
Log messages above this level (\fIdebug\fR, \fBinfo\fR, \fIwarn\fR, \fIerror\fR)
|
Log messages above this level (\fIdebug\fR, \fBinfo\fR, \fIwarn\fR, \fIerror\fR)
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
1
debian/i2pd.default
vendored
1
debian/i2pd.default
vendored
@@ -4,6 +4,7 @@
|
|||||||
I2PD_ENABLED="yes"
|
I2PD_ENABLED="yes"
|
||||||
|
|
||||||
# port to listen for incoming connections
|
# port to listen for incoming connections
|
||||||
|
# comment this line if you want to use value from config
|
||||||
I2PD_PORT="4567"
|
I2PD_PORT="4567"
|
||||||
|
|
||||||
# Additional options that are passed to the Daemon.
|
# Additional options that are passed to the Daemon.
|
||||||
|
|||||||
6
debian/i2pd.init
vendored
6
debian/i2pd.init
vendored
@@ -41,6 +41,10 @@ do_start()
|
|||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$I2PD_PORT" ]; then
|
||||||
|
DAEMON_OPTS="--port $I2PD_PORT $DAEMON_OPTS"
|
||||||
|
fi
|
||||||
|
|
||||||
touch "$PIDFILE"
|
touch "$PIDFILE"
|
||||||
chown -f $USER:adm "$PIDFILE"
|
chown -f $USER:adm "$PIDFILE"
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ do_start()
|
|||||||
|| return 1
|
|| return 1
|
||||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
|
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
|
||||||
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
|
--service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \
|
||||||
--port=$I2PD_PORT $DAEMON_OPTS > /dev/null 2>&1 \
|
$DAEMON_OPTS > /dev/null 2>&1 \
|
||||||
|| return 2
|
|| return 2
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|||||||
41
debian/i2pd.openrc
vendored
Normal file
41
debian/i2pd.openrc
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
pidfile="/var/run/i2pd.pid"
|
||||||
|
logfile="/var/log/i2pd.log"
|
||||||
|
mainconf="/etc/i2pd/i2pd.conf"
|
||||||
|
tunconf="/etc/i2pd/tunnels.conf"
|
||||||
|
|
||||||
|
name="i2pd"
|
||||||
|
command="/usr/sbin/i2pd"
|
||||||
|
command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --pidfile=$pidfile"
|
||||||
|
description="i2p router written in C++"
|
||||||
|
required_dirs="/var/lib/i2pd"
|
||||||
|
required_files="$mainconf"
|
||||||
|
start_stop_daemon_args="--chuid i2pd"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need mountall
|
||||||
|
use net
|
||||||
|
after bootmisc
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
if [ -r /etc/default/i2pd ]; then
|
||||||
|
. /etc/default/i2pd
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x$I2PD_ENABLED" != "xyes" ]; then
|
||||||
|
ewarn "i2pd disabled in /etc/default/i2pd"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
checkpath -f -o i2pd:adm $logfile
|
||||||
|
checkpath -f -o i2pd:adm $pidfile
|
||||||
|
|
||||||
|
if [ -n "$I2PD_PORT" -a "$I2PD_PORT" -gt 0 ]; then
|
||||||
|
command_args="$command_args --port=$I2PD_PORT"
|
||||||
|
fi
|
||||||
|
if [ -n "$DAEMON_OPTS" ]; then
|
||||||
|
command_args="$command_args $DAEMON_OPTS"
|
||||||
|
fi
|
||||||
|
}
|
||||||
259
docs/Doxyfile
Normal file
259
docs/Doxyfile
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = "i2pd"
|
||||||
|
PROJECT_NUMBER =
|
||||||
|
PROJECT_BRIEF = "load-balanced unspoofable packet switching network"
|
||||||
|
PROJECT_LOGO =
|
||||||
|
OUTPUT_DIRECTORY = docs/generated
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
ALLOW_UNICODE_NAMES = NO
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ABBREVIATE_BRIEF =
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = YES
|
||||||
|
STRIP_FROM_PATH =
|
||||||
|
STRIP_FROM_INC_PATH =
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 4
|
||||||
|
ALIASES =
|
||||||
|
TCL_SUBST =
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
EXTENSION_MAPPING =
|
||||||
|
MARKDOWN_SUPPORT = YES
|
||||||
|
AUTOLINK_SUPPORT = YES
|
||||||
|
BUILTIN_STL_SUPPORT = NO
|
||||||
|
CPP_CLI_SUPPORT = NO
|
||||||
|
SIP_SUPPORT = NO
|
||||||
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
SUBGROUPING = YES
|
||||||
|
INLINE_GROUPED_CLASSES = NO
|
||||||
|
INLINE_SIMPLE_STRUCTS = NO
|
||||||
|
TYPEDEF_HIDES_STRUCT = NO
|
||||||
|
LOOKUP_CACHE_SIZE = 0
|
||||||
|
EXTRACT_ALL = NO
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_PACKAGE = NO
|
||||||
|
EXTRACT_STATIC = NO
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
EXTRACT_LOCAL_METHODS = NO
|
||||||
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
CASE_SENSE_NAMES = YES
|
||||||
|
HIDE_SCOPE_NAMES = NO
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
SHOW_GROUPED_MEMB_INC = NO
|
||||||
|
FORCE_LOCAL_INCLUDES = NO
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = YES
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_MEMBERS_CTORS_1ST = NO
|
||||||
|
SORT_GROUP_NAMES = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
STRICT_PROTO_MATCHING = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
FILE_VERSION_FILTER =
|
||||||
|
LAYOUT_FILE =
|
||||||
|
CITE_BIB_FILES =
|
||||||
|
QUIET = YES
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
WARN_NO_PARAMDOC = NO
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
INPUT =
|
||||||
|
INPUT_ENCODING = UTF-8
|
||||||
|
FILE_PATTERNS = *.cpp *.h
|
||||||
|
RECURSIVE = NO
|
||||||
|
EXCLUDE =
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
EXAMPLE_PATTERNS =
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_PATTERNS =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
FILTER_SOURCE_PATTERNS =
|
||||||
|
USE_MDFILE_AS_MAINPAGE =
|
||||||
|
SOURCE_BROWSER = NO
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
REFERENCED_BY_RELATION = NO
|
||||||
|
REFERENCES_RELATION = NO
|
||||||
|
REFERENCES_LINK_SOURCE = YES
|
||||||
|
SOURCE_TOOLTIPS = YES
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = NO
|
||||||
|
CLANG_ASSISTED_PARSING = NO
|
||||||
|
CLANG_OPTIONS =
|
||||||
|
ALPHABETICAL_INDEX = YES
|
||||||
|
COLS_IN_ALPHA_INDEX = 5
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_EXTRA_STYLESHEET =
|
||||||
|
HTML_EXTRA_FILES =
|
||||||
|
HTML_COLORSTYLE_HUE = 220
|
||||||
|
HTML_COLORSTYLE_SAT = 100
|
||||||
|
HTML_COLORSTYLE_GAMMA = 80
|
||||||
|
HTML_TIMESTAMP = YES
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
HTML_INDEX_NUM_ENTRIES = 100
|
||||||
|
GENERATE_DOCSET = NO
|
||||||
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||||
|
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||||
|
DOCSET_PUBLISHER_NAME = Publisher
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
CHM_FILE =
|
||||||
|
HHC_LOCATION =
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
CHM_INDEX_ENCODING =
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
GENERATE_QHP = NO
|
||||||
|
QCH_FILE =
|
||||||
|
QHP_NAMESPACE = org.doxygen.Project
|
||||||
|
QHP_VIRTUAL_FOLDER = doc
|
||||||
|
QHP_CUST_FILTER_NAME =
|
||||||
|
QHP_CUST_FILTER_ATTRS =
|
||||||
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
QHG_LOCATION =
|
||||||
|
GENERATE_ECLIPSEHELP = NO
|
||||||
|
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
GENERATE_TREEVIEW = NO
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
FORMULA_TRANSPARENT = YES
|
||||||
|
USE_MATHJAX = NO
|
||||||
|
MATHJAX_FORMAT = HTML-CSS
|
||||||
|
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||||
|
MATHJAX_EXTENSIONS =
|
||||||
|
MATHJAX_CODEFILE =
|
||||||
|
SEARCHENGINE = YES
|
||||||
|
SERVER_BASED_SEARCH = NO
|
||||||
|
EXTERNAL_SEARCH = NO
|
||||||
|
SEARCHENGINE_URL =
|
||||||
|
SEARCHDATA_FILE = searchdata.xml
|
||||||
|
EXTERNAL_SEARCH_ID =
|
||||||
|
EXTRA_SEARCH_MAPPINGS =
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME = latex
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
COMPACT_LATEX = NO
|
||||||
|
PAPER_TYPE = a4
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
LATEX_FOOTER =
|
||||||
|
LATEX_EXTRA_FILES =
|
||||||
|
PDF_HYPERLINKS = YES
|
||||||
|
USE_PDFLATEX = YES
|
||||||
|
LATEX_BATCHMODE = NO
|
||||||
|
LATEX_HIDE_INDICES = NO
|
||||||
|
LATEX_SOURCE_CODE = NO
|
||||||
|
LATEX_BIB_STYLE = plain
|
||||||
|
GENERATE_RTF = NO
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = NO
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_SUBDIR =
|
||||||
|
MAN_LINKS = NO
|
||||||
|
GENERATE_XML = NO
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
GENERATE_DOCBOOK = NO
|
||||||
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
DOCBOOK_PROGRAMLISTING = NO
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
GENERATE_PERLMOD = NO
|
||||||
|
PERLMOD_LATEX = NO
|
||||||
|
PERLMOD_PRETTY = YES
|
||||||
|
PERLMOD_MAKEVAR_PREFIX =
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH =
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED =
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE =
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
EXTERNAL_PAGES = YES
|
||||||
|
PERL_PATH = /usr/bin/perl
|
||||||
|
CLASS_DIAGRAMS = YES
|
||||||
|
MSCGEN_PATH =
|
||||||
|
DIA_PATH =
|
||||||
|
HIDE_UNDOC_RELATIONS = YES
|
||||||
|
HAVE_DOT = NO
|
||||||
|
DOT_NUM_THREADS = 0
|
||||||
|
DOT_FONTNAME = Helvetica
|
||||||
|
DOT_FONTSIZE = 10
|
||||||
|
DOT_FONTPATH =
|
||||||
|
CLASS_GRAPH = YES
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
GROUP_GRAPHS = YES
|
||||||
|
UML_LOOK = NO
|
||||||
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
TEMPLATE_RELATIONS = NO
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
CALL_GRAPH = NO
|
||||||
|
CALLER_GRAPH = NO
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DIRECTORY_GRAPH = YES
|
||||||
|
DOT_IMAGE_FORMAT = png
|
||||||
|
INTERACTIVE_SVG = NO
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
MSCFILE_DIRS =
|
||||||
|
DIAFILE_DIRS =
|
||||||
|
PLANTUML_JAR_PATH =
|
||||||
|
DOT_GRAPH_MAX_NODES = 50
|
||||||
|
MAX_DOT_GRAPH_DEPTH = 0
|
||||||
|
DOT_TRANSPARENT = NO
|
||||||
|
DOT_MULTI_TARGETS = NO
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
@@ -22,7 +22,7 @@ Proceed with building Boost normal way, but let's define dedicated staging direc
|
|||||||
```sh
|
```sh
|
||||||
./bootstrap.sh
|
./bootstrap.sh
|
||||||
./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \
|
./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \
|
||||||
--build-type=minimal --with-filesystem --with-program_options --with-regex --with-date_time \
|
--build-type=minimal --with-filesystem --with-program_options --with-date_time \
|
||||||
--stagedir=stage-mingw-64
|
--stagedir=stage-mingw-64
|
||||||
cd ..
|
cd ..
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ sudo apt-get install \
|
|||||||
libboost-date-time-dev \
|
libboost-date-time-dev \
|
||||||
libboost-filesystem-dev \
|
libboost-filesystem-dev \
|
||||||
libboost-program-options-dev \
|
libboost-program-options-dev \
|
||||||
libboost-regex-dev \
|
|
||||||
libboost-system-dev \
|
libboost-system-dev \
|
||||||
libboost-thread-dev \
|
libboost-thread-dev \
|
||||||
libssl-dev
|
libssl-dev
|
||||||
|
|||||||
@@ -110,11 +110,11 @@ prompt to build Boost) and run the following:
|
|||||||
|
|
||||||
cd C:\dev\boost
|
cd C:\dev\boost
|
||||||
bootstrap
|
bootstrap
|
||||||
b2 toolset=msvc-12.0 --build-type=complete --with-filesystem --with-program_options --with-regex --with-date_time
|
b2 toolset=msvc-12.0 --build-type=complete --with-filesystem --with-program_options --with-date_time
|
||||||
|
|
||||||
If you are on 64-bit Windows and you want to build 64-bit version as well
|
If you are on 64-bit Windows and you want to build 64-bit version as well
|
||||||
|
|
||||||
b2 toolset=msvc-12.0 --build-type=complete --stagedir=stage64 address-model=64 --with-filesystem --with-program_options --with-regex --with-date_time
|
b2 toolset=msvc-12.0 --build-type=complete --stagedir=stage64 address-model=64 --with-filesystem --with-program_options --with-date_time
|
||||||
|
|
||||||
After Boost is compiled, set the environment variable `BOOST_ROOT` to
|
After Boost is compiled, set the environment variable `BOOST_ROOT` to
|
||||||
the directory Boost was unpacked to, e.g., C:\dev\boost.
|
the directory Boost was unpacked to, e.g., C:\dev\boost.
|
||||||
|
|||||||
@@ -58,7 +58,11 @@ All options below still possible in cmdline, but better write it in config file:
|
|||||||
|
|
||||||
* --bob.address= - The address to listen on (BOB command channel)
|
* --bob.address= - The address to listen on (BOB command channel)
|
||||||
* --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified
|
* --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified
|
||||||
* --sam.enabled= - If BOB is enabled. false by default
|
* --bob.enabled= - If BOB is enabled. false by default
|
||||||
|
|
||||||
|
* --i2cp.address= - The address to listen on
|
||||||
|
* --i2cp.port= - Port of I2CP server. Usually 7654. IPCP is off if not specified
|
||||||
|
* --i2cp.enabled= - If I2CP is enabled. false by default. Other services don't requeire I2CP
|
||||||
|
|
||||||
* --i2pcontrol.address= - The address to listen on (I2P control service)
|
* --i2pcontrol.address= - The address to listen on (I2P control service)
|
||||||
* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified
|
* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified
|
||||||
|
|||||||
@@ -1,20 +1,27 @@
|
|||||||
i2pd
|
i2pd
|
||||||
====
|
====
|
||||||
|
|
||||||
`Website <http://i2pd.website>`_ |
|
i2pd is a full-featured C++ implementation of
|
||||||
`Github <https://github.com/PurpleI2P/i2pd>`_ |
|
`I2P <https://geti2p.net/en/about/intro>`_ client.
|
||||||
`Issues <https://github.com/PurpleI2P/i2pd/issues>`_
|
|
||||||
|
|
||||||
i2pd is C++ implementation of `I2P <https://geti2p.net/en/about/intro>`_.
|
* `Website <http://i2pd.website>`_
|
||||||
|
* `GitHub <https://github.com/PurpleI2P/i2pd>`_
|
||||||
|
* `Wiki <https://github.com/PurpleI2P/i2pd/wiki>`_
|
||||||
|
* `Tickets/Issues <https://github.com/PurpleI2P/i2pd/issues>`_
|
||||||
|
* `Twitter <https://twitter.com/i2porignal>`_
|
||||||
|
|
||||||
Supports:
|
Installing
|
||||||
---------
|
----------
|
||||||
|
|
||||||
* Complete I2P router functionality
|
The easiest way to install i2pd is by using
|
||||||
* Floodfill
|
`precompiled binaries <https://github.com/PurpleI2P/i2pd/releases/latest>`_.
|
||||||
* HTTP and SOCKS proxy
|
See documentation for how to build i2pd from source on your OS.
|
||||||
* I2P client and server tunnels
|
|
||||||
* SAM and BOB interfaces
|
Using i2pd
|
||||||
|
----------
|
||||||
|
|
||||||
|
See documentation and
|
||||||
|
`example config file <https://github.com/PurpleI2P/i2pd/blob/openssl/docs/i2pd.conf>`_.
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
---------
|
---------
|
||||||
@@ -28,3 +35,4 @@ Contents:
|
|||||||
configuration
|
configuration
|
||||||
family
|
family
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
docs/itoopieImage.png
Normal file
BIN
docs/itoopieImage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
18
i2pd.cpp
18
i2pd.cpp
@@ -1,9 +1,24 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
|
||||||
|
#if defined(QT_GUI_LIB)
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
int RunQT (int argc, char* argv[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
if (Daemon.init(argc, argv))
|
return i2p::qt::RunQT (argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
int main( int argc, char* argv[] )
|
||||||
|
{
|
||||||
|
if (Daemon.init(argc, argv))
|
||||||
{
|
{
|
||||||
if (Daemon.start())
|
if (Daemon.start())
|
||||||
Daemon.run ();
|
Daemon.run ();
|
||||||
@@ -11,6 +26,7 @@ int main( int argc, char* argv[] )
|
|||||||
}
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|||||||
1
qt/.gitignore
vendored
Normal file
1
qt/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build*/
|
||||||
161
qt/i2pd_qt/DaemonQT.cpp
Normal file
161
qt/i2pd_qt/DaemonQT.cpp
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#include "DaemonQT.h"
|
||||||
|
#include "../../Daemon.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
Worker::Worker (DaemonQTImpl& daemon):
|
||||||
|
m_Daemon (daemon)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Worker::startDaemon()
|
||||||
|
{
|
||||||
|
qDebug("Performing daemon start...");
|
||||||
|
m_Daemon.start();
|
||||||
|
qDebug("Daemon started.");
|
||||||
|
emit resultReady();
|
||||||
|
}
|
||||||
|
void Worker::restartDaemon()
|
||||||
|
{
|
||||||
|
qDebug("Performing daemon restart...");
|
||||||
|
m_Daemon.restart();
|
||||||
|
qDebug("Daemon restarted.");
|
||||||
|
emit resultReady();
|
||||||
|
}
|
||||||
|
void Worker::stopDaemon() {
|
||||||
|
qDebug("Performing daemon stop...");
|
||||||
|
m_Daemon.stop();
|
||||||
|
qDebug("Daemon stopped.");
|
||||||
|
emit resultReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller::Controller(DaemonQTImpl& daemon):
|
||||||
|
m_Daemon (daemon)
|
||||||
|
{
|
||||||
|
Worker *worker = new Worker (m_Daemon);
|
||||||
|
worker->moveToThread(&workerThread);
|
||||||
|
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(this, &Controller::startDaemon, worker, &Worker::startDaemon);
|
||||||
|
connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon);
|
||||||
|
connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon);
|
||||||
|
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
|
||||||
|
workerThread.start();
|
||||||
|
}
|
||||||
|
Controller::~Controller()
|
||||||
|
{
|
||||||
|
qDebug("Closing and waiting for daemon worker thread...");
|
||||||
|
workerThread.quit();
|
||||||
|
workerThread.wait();
|
||||||
|
qDebug("Waiting for daemon worker thread finished.");
|
||||||
|
if(m_Daemon.isRunning())
|
||||||
|
{
|
||||||
|
qDebug("Stopping the daemon...");
|
||||||
|
m_Daemon.stop();
|
||||||
|
qDebug("Stopped the daemon.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DaemonQTImpl::DaemonQTImpl ():
|
||||||
|
mutex(nullptr), m_IsRunning(nullptr), m_RunningChangedCallback(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DaemonQTImpl::~DaemonQTImpl ()
|
||||||
|
{
|
||||||
|
delete mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonQTImpl::init(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
mutex=new QMutex(QMutex::Recursive);
|
||||||
|
setRunningCallback(0);
|
||||||
|
m_IsRunning=false;
|
||||||
|
return Daemon.init(argc,argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonQTImpl::start()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
setRunning(true);
|
||||||
|
Daemon.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonQTImpl::stop()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
Daemon.stop();
|
||||||
|
setRunning(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonQTImpl::restart()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(mutex);
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonQTImpl::setRunningCallback(runningChangedCallback cb)
|
||||||
|
{
|
||||||
|
m_RunningChangedCallback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DaemonQTImpl::isRunning()
|
||||||
|
{
|
||||||
|
return m_IsRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DaemonQTImpl::setRunning(bool newValue)
|
||||||
|
{
|
||||||
|
bool oldValue = m_IsRunning;
|
||||||
|
if(oldValue!=newValue)
|
||||||
|
{
|
||||||
|
m_IsRunning = newValue;
|
||||||
|
if(m_RunningChangedCallback)
|
||||||
|
m_RunningChangedCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RunQT (int argc, char* argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
int result;
|
||||||
|
|
||||||
|
{
|
||||||
|
DaemonQTImpl daemon;
|
||||||
|
qDebug("Initialising the daemon...");
|
||||||
|
bool daemonInitSuccess = daemon.init(argc, argv);
|
||||||
|
if(!daemonInitSuccess)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(0, "Error", "Daemon init failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
qDebug("Initialised, creating the main window...");
|
||||||
|
MainWindow w;
|
||||||
|
qDebug("Before main window.show()...");
|
||||||
|
w.show ();
|
||||||
|
|
||||||
|
{
|
||||||
|
i2p::qt::Controller daemonQtController(daemon);
|
||||||
|
qDebug("Starting the daemon...");
|
||||||
|
emit daemonQtController.startDaemon();
|
||||||
|
//daemon.start ();
|
||||||
|
qDebug("Starting GUI event loop...");
|
||||||
|
result = app.exec();
|
||||||
|
//daemon.stop ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//QMessageBox::information(&w, "Debug", "demon stopped");
|
||||||
|
qDebug("Exiting the application");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
81
qt/i2pd_qt/DaemonQT.h
Normal file
81
qt/i2pd_qt/DaemonQT.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef DAEMONQT_H
|
||||||
|
#define DAEMONQT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
class DaemonQTImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DaemonQTImpl ();
|
||||||
|
~DaemonQTImpl ();
|
||||||
|
|
||||||
|
typedef void (*runningChangedCallback)();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief init
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
* @return success
|
||||||
|
*/
|
||||||
|
bool init(int argc, char* argv[]);
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
void restart();
|
||||||
|
void setRunningCallback(runningChangedCallback cb);
|
||||||
|
bool isRunning();
|
||||||
|
private:
|
||||||
|
void setRunning(bool running);
|
||||||
|
private:
|
||||||
|
QMutex* mutex;
|
||||||
|
bool m_IsRunning;
|
||||||
|
runningChangedCallback m_RunningChangedCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Worker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
Worker (DaemonQTImpl& daemon);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
DaemonQTImpl& m_Daemon;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void startDaemon();
|
||||||
|
void restartDaemon();
|
||||||
|
void stopDaemon();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultReady();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Controller : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QThread workerThread;
|
||||||
|
public:
|
||||||
|
Controller(DaemonQTImpl& daemon);
|
||||||
|
~Controller();
|
||||||
|
private:
|
||||||
|
DaemonQTImpl& m_Daemon;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void handleResults(){}
|
||||||
|
signals:
|
||||||
|
void startDaemon();
|
||||||
|
void stopDaemon();
|
||||||
|
void restartDaemon();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DAEMONQT_H
|
||||||
1
qt/i2pd_qt/android/.gitignore
vendored
Normal file
1
qt/i2pd_qt/android/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/gen/
|
||||||
64
qt/i2pd_qt/android/AndroidManifest.xml
Normal file
64
qt/i2pd_qt/android/AndroidManifest.xml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.8.0" android:versionCode="1" android:installLocation="auto">
|
||||||
|
<uses-sdk android:minSdkVersion="11"/>
|
||||||
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
|
<!-- <application android:hardwareAccelerated="true" -->
|
||||||
|
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="i2pd" android:icon="@drawable/icon">
|
||||||
|
<!-- android:configChanges="screenSize|smallestScreenSize" are since api 13, "layoutDirection" since api 17 -->
|
||||||
|
<activity android:configChanges="orientation|uiMode|screenLayout|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.purplei2p.i2pd.I2PDMainActivity" android:label="i2pd" android:screenOrientation="unspecified" android:launchMode="singleTop">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
|
||||||
|
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
||||||
|
<meta-data android:name="android.app.repository" android:value="default"/>
|
||||||
|
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||||
|
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||||
|
<!-- Deploy Qt libs as part of package -->
|
||||||
|
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||||
|
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||||
|
<!-- Run with local libs -->
|
||||||
|
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
||||||
|
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||||
|
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||||
|
<!-- Messages maps -->
|
||||||
|
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
||||||
|
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
||||||
|
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
||||||
|
<!-- Messages maps -->
|
||||||
|
|
||||||
|
<!-- Splash screen -->
|
||||||
|
<!--
|
||||||
|
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
|
||||||
|
-->
|
||||||
|
<!-- Splash screen -->
|
||||||
|
|
||||||
|
<!-- Background running -->
|
||||||
|
<!-- Warning: changing this value to true may cause unexpected crashes if the
|
||||||
|
application still try to draw after
|
||||||
|
"applicationStateChanged(Qt::ApplicationSuspended)"
|
||||||
|
signal is sent! -->
|
||||||
|
<meta-data android:name="android.app.background_running" android:value="false"/>
|
||||||
|
<!-- Background running -->
|
||||||
|
|
||||||
|
<!-- auto screen scale factor -->
|
||||||
|
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
|
||||||
|
<!-- auto screen scale factor -->
|
||||||
|
</activity>
|
||||||
|
<service android:enabled="true" android:name=".LocalService"/>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
|
||||||
|
Remove the comment if you do not require these default permissions. -->
|
||||||
|
<!-- %%INSERT_PERMISSIONS -->
|
||||||
|
|
||||||
|
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
|
||||||
|
Remove the comment if you do not require these default features. -->
|
||||||
|
<!-- %%INSERT_FEATURES -->
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
</manifest>
|
||||||
57
qt/i2pd_qt/android/build.gradle
Normal file
57
qt/i2pd_qt/android/build.gradle
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:1.1.0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
/*******************************************************
|
||||||
|
* The following variables:
|
||||||
|
* - androidBuildToolsVersion,
|
||||||
|
* - androidCompileSdkVersion
|
||||||
|
* - qt5AndroidDir - holds the path to qt android files
|
||||||
|
* needed to build any Qt application
|
||||||
|
* on Android.
|
||||||
|
*
|
||||||
|
* are defined in gradle.properties file. This file is
|
||||||
|
* updated by QtCreator and androiddeployqt tools.
|
||||||
|
* Changing them manually might break the compilation!
|
||||||
|
*******************************************************/
|
||||||
|
|
||||||
|
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||||
|
|
||||||
|
buildToolsVersion androidBuildToolsVersion
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
manifest.srcFile 'AndroidManifest.xml'
|
||||||
|
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
|
||||||
|
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
|
||||||
|
res.srcDirs = [qt5AndroidDir + '/res', 'res']
|
||||||
|
resources.srcDirs = ['src']
|
||||||
|
renderscript.srcDirs = ['src']
|
||||||
|
assets.srcDirs = ['assets']
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
qt/i2pd_qt/android/libs/android-support-v4.jar
Normal file
BIN
qt/i2pd_qt/android/libs/android-support-v4.jar
Normal file
Binary file not shown.
14
qt/i2pd_qt/android/project.properties
Normal file
14
qt/i2pd_qt/android/project.properties
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-11
|
||||||
BIN
qt/i2pd_qt/android/res/drawable-hdpi/icon.png
Normal file
BIN
qt/i2pd_qt/android/res/drawable-hdpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
BIN
qt/i2pd_qt/android/res/drawable/itoopie_notification_icon.png
Normal file
BIN
qt/i2pd_qt/android/res/drawable/itoopie_notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
4
qt/i2pd_qt/android/res/layout/splash.xml
Normal file
4
qt/i2pd_qt/android/res/layout/splash.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent" />
|
||||||
6
qt/i2pd_qt/android/res/values-de/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-de/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Ministro-Dienst wurde nicht gefunden.\nAnwendung kann nicht gestartet werden</string>
|
||||||
|
<string name="ministro_needed_msg">Diese Anwendung benötigt den Ministro-Dienst. Möchten Sie ihn installieren?</string>
|
||||||
|
<string name="fatal_error_msg">In Ihrer Anwendung ist ein schwerwiegender Fehler aufgetreten, sie kann nicht fortgesetzt werden</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-el/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-el/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Δεν ήταν δυνατή η εύρεση της υπηρεσίας Ministro. Δεν είναι δυνατή η εκκίνηση της εφαρμογής.</string>
|
||||||
|
<string name="ministro_needed_msg">Η εφαρμογή απαιτεί την υπηρεσία Ministro. Να εγκατασταθεί η υπηρεσία?</string>
|
||||||
|
<string name="fatal_error_msg">Παρουσιάστηκε ένα κρίσιμο σφάλμα και η εφαρμογή δεν μπορεί να συνεχίσει.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-es/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-es/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Servicio Ministro inesistente. Imposible ejecutar la aplicación.</string>
|
||||||
|
<string name="ministro_needed_msg">Esta aplicación requiere el servicio Ministro. Instalarlo?</string>
|
||||||
|
<string name="fatal_error_msg">La aplicación ha causado un error grave y no es posible continuar.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-et/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-et/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Ei suuda leida Ministro teenust.\nProgrammi ei saa käivitada.</string>
|
||||||
|
<string name="ministro_needed_msg">See programm vajab Ministro teenust.\nKas soovite paigaldada?</string>
|
||||||
|
<string name="fatal_error_msg">Programmiga juhtus fataalne viga.\nKahjuks ei saa jätkata.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-fa/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-fa/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">سرویس Ministro را پیدا نمیکند. برنامه نمیتواند آغاز شود.</string>
|
||||||
|
<string name="ministro_needed_msg">این نرمافزار به سرویس Ministro احتیاج دارد. آیا دوست دارید آن را نصب کنید؟</string>
|
||||||
|
<string name="fatal_error_msg">خطایی اساسی در برنامهتان رخ داد و اجرای برنامه نمیتواند ادامه یابد.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-fr/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-fr/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Le service Ministro est introuvable.\nL\'application ne peut pas démarrer.</string>
|
||||||
|
<string name="ministro_needed_msg">Cette application requiert le service Ministro. Voulez-vous l\'installer?</string>
|
||||||
|
<string name="fatal_error_msg">Votre application a rencontré une erreur fatale et ne peut pas continuer.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-id/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-id/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Layanan Ministro tidak bisa ditemukan.\nAplikasi tidak bisa dimulai.</string>
|
||||||
|
<string name="ministro_needed_msg">Aplikasi ini membutuhkan layanan Ministro. Apakah Anda ingin menginstalnya?</string>
|
||||||
|
<string name="fatal_error_msg">Aplikasi Anda mengalami kesalahan fatal dan tidak dapat melanjutkan.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-it/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-it/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Servizio Ministro inesistente. Impossibile eseguire \nl\'applicazione.</string>
|
||||||
|
<string name="ministro_needed_msg">Questa applicazione richiede il servizio Ministro.Installarlo?</string>
|
||||||
|
<string name="fatal_error_msg">L\'applicazione ha provocato un errore grave e non puo\' continuare.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-ja/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-ja/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Ministroサービスが見つかりません。\nアプリケーションが起動できません。</string>
|
||||||
|
<string name="ministro_needed_msg">このアプリケーションにはMinistroサービスが必要です。 インストールしてもよろしいですか?</string>
|
||||||
|
<string name="fatal_error_msg">アプリケーションで致命的なエラーが発生したため続行できません。</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-ms/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-ms/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Tidak jumpa servis Ministro.\nAplikasi tidak boleh dimulakan.</string>
|
||||||
|
<string name="ministro_needed_msg">Aplikasi ini memerlukan servis Ministro. Adakah anda ingin pasang servis itu?</string>
|
||||||
|
<string name="fatal_error_msg">Aplikasi anda menemui ralat muat dan tidak boleh diteruskan.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-nb/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-nb/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Kan ikke finne tjenesten Ministro. Applikasjonen kan ikke starte.</string>
|
||||||
|
<string name="ministro_needed_msg">Denne applikasjonen krever tjenesten Ministro. Vil du installere denne?</string>
|
||||||
|
<string name="fatal_error_msg">Applikasjonen fikk en kritisk feil og kan ikke fortsette</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-nl/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-nl/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">De Ministro service is niet gevonden.\nDe applicatie kan niet starten.</string>
|
||||||
|
<string name="ministro_needed_msg">Deze applicatie maakt gebruik van de Ministro service. Wilt u deze installeren?</string>
|
||||||
|
<string name="fatal_error_msg">Er is een fatale fout in de applicatie opgetreden. De applicatie kan niet verder gaan.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-pl/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-pl/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Usługa Ministro nie została znaleziona.\nAplikacja nie może zostać uruchomiona.</string>
|
||||||
|
<string name="ministro_needed_msg">Aplikacja wymaga usługi Ministro. Czy chcesz ją zainstalować?</string>
|
||||||
|
<string name="fatal_error_msg">Wystąpił błąd krytyczny. Aplikacja zostanie zamknięta.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-pt-rBR/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-pt-rBR/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Não foi possível encontrar o serviço Ministro.\nA aplicação não pode iniciar.</string>
|
||||||
|
<string name="ministro_needed_msg">Essa aplicação requer o serviço Ministro. Gostaria de instalá-lo?</string>
|
||||||
|
<string name="fatal_error_msg">Sua aplicação encontrou um erro fatal e não pode continuar.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-ro/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-ro/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Serviciul Ministro nu poate fi găsit.\nAplicaţia nu poate porni.</string>
|
||||||
|
<string name="ministro_needed_msg">Această aplicaţie necesită serviciul Ministro.\nDoriţi să-l instalaţi?</string>
|
||||||
|
<string name="fatal_error_msg">Aplicaţia dumneavoastră a întâmpinat o eroare fatală şi nu poate continua.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-rs/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-rs/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Ministro servise nije pronađen. Aplikacija ne može biti pokrenuta.</string>
|
||||||
|
<string name="ministro_needed_msg">Ova aplikacija zahteva Ministro servis. Želite li da ga instalirate?</string>
|
||||||
|
<string name="fatal_error_msg">Vaša aplikacija je naišla na fatalnu grešku i ne može nastaviti sa radom.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-ru/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-ru/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">Сервис Ministro не найден.\nПриложение нельзя запустить.</string>
|
||||||
|
<string name="ministro_needed_msg">Этому приложению необходим сервис Ministro. Вы хотите его установить?</string>
|
||||||
|
<string name="fatal_error_msg">Ваше приложение столкнулось с фатальной ошибкой и не может более работать.</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-zh-rCN/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-zh-rCN/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">无法找到Ministro服务。\n应用程序无法启动。</string>
|
||||||
|
<string name="ministro_needed_msg">此应用程序需要Ministro服务。您想安装它吗?</string>
|
||||||
|
<string name="fatal_error_msg">您的应用程序遇到一个致命错误导致它无法继续。</string>
|
||||||
|
</resources>
|
||||||
6
qt/i2pd_qt/android/res/values-zh-rTW/strings.xml
Normal file
6
qt/i2pd_qt/android/res/values-zh-rTW/strings.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<string name="ministro_not_found_msg">無法找到Ministro服務。\n應用程序無法啟動。</string>
|
||||||
|
<string name="ministro_needed_msg">此應用程序需要Ministro服務。您想安裝它嗎?</string>
|
||||||
|
<string name="fatal_error_msg">您的應用程序遇到一個致命錯誤導致它無法繼續。</string>
|
||||||
|
</resources>
|
||||||
25
qt/i2pd_qt/android/res/values/libs.xml
Normal file
25
qt/i2pd_qt/android/res/values/libs.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<array name="qt_sources">
|
||||||
|
<item>https://download.qt-project.org/ministro/android/qt5/qt-5.4</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- The following is handled automatically by the deployment tool. It should
|
||||||
|
not be edited manually. -->
|
||||||
|
|
||||||
|
<array name="bundled_libs">
|
||||||
|
<!-- %%INSERT_EXTRA_LIBS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="qt_libs">
|
||||||
|
<!-- %%INSERT_QT_LIBS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="bundled_in_lib">
|
||||||
|
<!-- %%INSERT_BUNDLED_IN_LIB%% -->
|
||||||
|
</array>
|
||||||
|
<array name="bundled_in_assets">
|
||||||
|
<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user