mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 16:10:33 +03:00
commit
ccc24337be
@ -17,7 +17,6 @@ addons:
|
||||
- libboost-date-time-dev
|
||||
- libboost-filesystem-dev
|
||||
- libboost-program-options-dev
|
||||
- libboost-regex-dev
|
||||
- libboost-system-dev
|
||||
- libboost-thread-dev
|
||||
- libminiupnpc-dev
|
||||
|
@ -159,7 +159,7 @@ namespace client
|
||||
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
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
|
@ -114,6 +114,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 ();
|
||||
}
|
||||
|
||||
@ -165,6 +183,14 @@ namespace client
|
||||
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");
|
||||
m_AddressBook.Stop ();
|
||||
for (auto it: m_Destinations)
|
||||
|
@ -178,6 +178,13 @@ namespace config {
|
||||
("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");
|
||||
i2pcontrol.add_options()
|
||||
("i2pcontrol.enabled", value<bool>()->default_value(false), "Enable or disable I2P Control Protocol")
|
||||
@ -207,6 +214,7 @@ namespace config {
|
||||
.add(socksproxy)
|
||||
.add(sam)
|
||||
.add(bob)
|
||||
.add(i2cp)
|
||||
.add(i2pcontrol)
|
||||
.add(precomputation)
|
||||
;
|
||||
|
4
Config.h
4
Config.h
@ -68,7 +68,7 @@ namespace config {
|
||||
* @param value Variable where to store option
|
||||
* @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>
|
||||
bool GetOption(const char *name, T& value) {
|
||||
@ -84,7 +84,7 @@ namespace config {
|
||||
* @param value New parameter value
|
||||
* @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>
|
||||
bool SetOption(const char *name, const T& value) {
|
||||
|
@ -45,10 +45,10 @@ namespace i2p
|
||||
#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() {
|
||||
delete &d;
|
||||
};
|
||||
}
|
||||
|
||||
bool Daemon_Singleton::IsService () const
|
||||
{
|
||||
|
2
Daemon.h
2
Daemon.h
@ -22,9 +22,7 @@ namespace i2p
|
||||
virtual bool stop();
|
||||
virtual void run () {};
|
||||
|
||||
bool isLogging;
|
||||
bool isDaemon;
|
||||
|
||||
bool running;
|
||||
|
||||
protected:
|
||||
|
@ -45,7 +45,7 @@ namespace i2p
|
||||
{
|
||||
bool DaemonLinux::start()
|
||||
{
|
||||
if (isDaemon == 1)
|
||||
if (isDaemon)
|
||||
{
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
@ -73,10 +73,10 @@ namespace i2p
|
||||
return false;
|
||||
}
|
||||
|
||||
// close stdin/stdout/stderr descriptors
|
||||
freopen("/dev/null", "r", stdin);
|
||||
freopen("/dev/null", "w", stdout);
|
||||
freopen("/dev/null", "w", stderr);
|
||||
// point std{in,out,err} descriptors to /dev/null
|
||||
stdin = freopen("/dev/null", "r", stdin);
|
||||
stdout = freopen("/dev/null", "w", stdout);
|
||||
stderr = freopen("/dev/null", "w", stderr);
|
||||
}
|
||||
|
||||
// Pidfile
|
||||
|
@ -45,7 +45,7 @@ namespace i2p
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isDaemon == 1)
|
||||
if (isDaemon)
|
||||
{
|
||||
LogPrint(eLogDebug, "Daemon: running as service");
|
||||
I2PService service(SERVICE_NAME);
|
||||
|
@ -130,10 +130,6 @@ namespace client
|
||||
if (!m_IsRunning)
|
||||
{
|
||||
m_IsRunning = true;
|
||||
if (m_IsPublic)
|
||||
PersistTemporaryKeys ();
|
||||
else
|
||||
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||
m_Pool->SetLocalDestination (shared_from_this ());
|
||||
m_Pool->SetActive (true);
|
||||
m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ()));
|
||||
@ -204,14 +200,21 @@ namespace client
|
||||
return m_LeaseSet;
|
||||
}
|
||||
|
||||
void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet)
|
||||
{
|
||||
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
|
||||
auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), GetEncryptionPublicKey (),
|
||||
m_Pool->GetInboundTunnels (numTunnels));
|
||||
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO
|
||||
m_LeaseSet.reset (leaseSet);
|
||||
CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels));
|
||||
}
|
||||
|
||||
bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
|
||||
@ -391,11 +394,6 @@ namespace client
|
||||
{
|
||||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||
UpdateLeaseSet ();
|
||||
if (m_IsPublic)
|
||||
{
|
||||
m_PublishVerificationTimer.cancel ();
|
||||
Publish ();
|
||||
}
|
||||
}
|
||||
|
||||
void LeaseSetDestination::Publish ()
|
||||
@ -642,36 +640,16 @@ namespace client
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void LeaseSetDestination::PersistTemporaryKeys ()
|
||||
{
|
||||
std::string ident = GetIdentHash().ToBase32();
|
||||
std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat"));
|
||||
std::ifstream f(path, std::ifstream::binary);
|
||||
|
||||
if (f) {
|
||||
f.read ((char *)m_EncryptionPublicKey, 256);
|
||||
f.read ((char *)m_EncryptionPrivateKey, 256);
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p");
|
||||
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||
|
||||
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
|
||||
if (f1) {
|
||||
f1.write ((char *)m_EncryptionPublicKey, 256);
|
||||
f1.write ((char *)m_EncryptionPrivateKey, 256);
|
||||
return;
|
||||
}
|
||||
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
@ -840,5 +818,37 @@ namespace client
|
||||
ret.push_back (it1.second);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ClientDestination::PersistTemporaryKeys ()
|
||||
{
|
||||
std::string ident = GetIdentHash().ToBase32();
|
||||
std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat"));
|
||||
std::ifstream f(path, std::ifstream::binary);
|
||||
|
||||
if (f) {
|
||||
f.read ((char *)m_EncryptionPublicKey, 256);
|
||||
f.read ((char *)m_EncryptionPrivateKey, 256);
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p");
|
||||
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
|
||||
|
||||
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
|
||||
if (f1) {
|
||||
f1.write ((char *)m_EncryptionPublicKey, 256);
|
||||
f1.write ((char *)m_EncryptionPrivateKey, 256);
|
||||
return;
|
||||
}
|
||||
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
|
||||
}
|
||||
|
||||
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
||||
{
|
||||
auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels);
|
||||
// sign
|
||||
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO
|
||||
SetLeaseSet (leaseSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,10 +81,6 @@ namespace client
|
||||
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
|
||||
void CancelDestinationRequest (const i2p::data::IdentHash& dest);
|
||||
|
||||
// implements LocalDestination
|
||||
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
|
||||
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; };
|
||||
|
||||
// implements GarlicDestination
|
||||
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();
|
||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const { return m_Pool; }
|
||||
@ -98,8 +94,10 @@ namespace client
|
||||
|
||||
protected:
|
||||
|
||||
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:
|
||||
|
||||
@ -117,13 +115,9 @@ namespace client
|
||||
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
||||
void HandleCleanupTimer (const boost::system::error_code& ecode);
|
||||
void CleanupRemoteLeaseSets ();
|
||||
|
||||
void PersistTemporaryKeys ();
|
||||
|
||||
private:
|
||||
|
||||
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
|
||||
|
||||
volatile bool m_IsRunning;
|
||||
std::thread * m_Thread;
|
||||
boost::asio::io_service m_Service;
|
||||
@ -156,7 +150,8 @@ namespace client
|
||||
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;
|
||||
@ -166,28 +161,31 @@ namespace client
|
||||
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
|
||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
|
||||
// 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 ()); }
|
||||
{ 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;
|
||||
|
12
HTTP.cpp
12
HTTP.cpp
@ -253,21 +253,12 @@ namespace http {
|
||||
if (pos >= eoh)
|
||||
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);
|
||||
}
|
||||
|
||||
std::string HTTPReq::to_string() {
|
||||
std::stringstream ss;
|
||||
ss << method << " " << uri << " " << version << CRLF;
|
||||
ss << "Host: " << host << CRLF;
|
||||
for (auto & h : headers) {
|
||||
ss << h.first << ": " << h.second << CRLF;
|
||||
}
|
||||
@ -406,11 +397,10 @@ namespace http {
|
||||
|
||||
bool MergeChunkedResponse (std::istream& in, std::ostream& out) {
|
||||
std::string hexLen;
|
||||
long int len;
|
||||
while (!in.eof ()) {
|
||||
std::getline (in, hexLen);
|
||||
errno = 0;
|
||||
len = strtoul(hexLen.c_str(), (char **) NULL, 16);
|
||||
long int len = strtoul(hexLen.c_str(), (char **) NULL, 16);
|
||||
if (errno != 0)
|
||||
return false; /* conversion error */
|
||||
if (len == 0)
|
||||
|
17
HTTP.h
17
HTTP.h
@ -38,7 +38,7 @@ namespace http {
|
||||
* @brief Tries to parse url from string
|
||||
* @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);
|
||||
|
||||
/**
|
||||
@ -69,7 +69,6 @@ namespace http {
|
||||
std::string version;
|
||||
std::string method;
|
||||
std::string uri;
|
||||
std::string host;
|
||||
|
||||
HTTPReq (): version("HTTP/1.0"), method("GET"), uri("/") {};
|
||||
|
||||
@ -89,10 +88,12 @@ namespace http {
|
||||
std::string version;
|
||||
std::string status;
|
||||
unsigned short int code;
|
||||
/** simplifies response generation
|
||||
* If this variable is set:
|
||||
* a) Content-Length header will be added if missing
|
||||
* b) contents of body will be included in response
|
||||
/**
|
||||
* @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;
|
||||
|
||||
@ -108,9 +109,9 @@ namespace http {
|
||||
|
||||
/**
|
||||
* @brief Serialize HTTP response to string
|
||||
* @note If version is set to HTTP/1.1, and Date header is missing,
|
||||
* @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 body member is set and Content-Length header is missing,
|
||||
* @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();
|
||||
|
@ -1,16 +1,8 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <boost/asio.hpp>
|
||||
#include <mutex>
|
||||
|
||||
#include "I2PService.h"
|
||||
#include "Destination.h"
|
||||
#include "HTTPProxy.h"
|
||||
#include "util.h"
|
||||
#include "Identity.h"
|
||||
@ -20,6 +12,7 @@
|
||||
#include "I2PEndian.h"
|
||||
#include "I2PTunnel.h"
|
||||
#include "Config.h"
|
||||
#include "HTTP.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -43,7 +36,7 @@ namespace proxy
|
||||
void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
|
||||
void Terminate();
|
||||
void AsyncSockRead();
|
||||
void HTTPRequestFailed(const char *message);
|
||||
void HTTPRequestFailed(/*std::string message*/);
|
||||
void RedirectToJumpService();
|
||||
void ExtractRequest();
|
||||
bool IsI2PAddress();
|
||||
@ -56,7 +49,6 @@ namespace proxy
|
||||
uint8_t m_http_buff[http_buffer_size];
|
||||
std::shared_ptr<boost::asio::ip::tcp::socket> m_sock;
|
||||
std::string m_request; //Data left to be sent
|
||||
std::string m_Response;
|
||||
std::string m_url; //URL
|
||||
std::string m_method; //Method
|
||||
std::string m_version; //HTTP version
|
||||
@ -99,17 +91,10 @@ namespace proxy
|
||||
|
||||
/* All hope is lost beyond this point */
|
||||
//TODO: handle this apropriately
|
||||
void HTTPProxyHandler::HTTPRequestFailed(const char *message)
|
||||
void HTTPProxyHandler::HTTPRequestFailed(/*HTTPProxyHandler::errTypes error*/)
|
||||
{
|
||||
std::size_t size = std::strlen(message);
|
||||
std::stringstream ss;
|
||||
ss << "HTTP/1.0 500 Internal Server Error\r\n"
|
||||
<< "Content-Type: text/plain\r\n";
|
||||
ss << "Content-Length: " << std::to_string(size + 2) << "\r\n"
|
||||
<< "\r\n"; /* end of headers */
|
||||
ss << message << "\r\n";
|
||||
m_Response = ss.str();
|
||||
boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response),
|
||||
static std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n";
|
||||
boost::asio::async_write(*m_sock, boost::asio::buffer(response,response.size()),
|
||||
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
@ -120,8 +105,7 @@ namespace proxy
|
||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||
|
||||
response << "HTTP/1.1 302 Found\r\nLocation: http://" << httpAddr << ":" << httpPort << "/?page=jumpservices&address=" << m_address << "\r\n\r\n";
|
||||
m_Response = response.str ();
|
||||
boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response),
|
||||
boost::asio::async_write(*m_sock, boost::asio::buffer(response.str (),response.str ().length ()),
|
||||
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
@ -133,21 +117,13 @@ namespace proxy
|
||||
void HTTPProxyHandler::ExtractRequest()
|
||||
{
|
||||
LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url);
|
||||
std::string server="";
|
||||
std::string port="80";
|
||||
boost::regex rHTTP("http://(.*?)(:(\\d+))?(/.*)");
|
||||
boost::smatch m;
|
||||
std::string path;
|
||||
if(boost::regex_search(m_url, m, rHTTP, boost::match_extra))
|
||||
{
|
||||
server=m[1].str();
|
||||
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;
|
||||
i2p::http::URL url;
|
||||
url.parse (m_url);
|
||||
m_address = url.host;
|
||||
m_port = url.port;
|
||||
m_path = url.path;
|
||||
if (!m_port) m_port = 80;
|
||||
LogPrint(eLogDebug, "HTTPProxy: server: ", m_address, ", port: ", m_port, ", path: ", m_path);
|
||||
}
|
||||
|
||||
bool HTTPProxyHandler::ValidateHTTPRequest()
|
||||
@ -155,7 +131,7 @@ namespace proxy
|
||||
if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" )
|
||||
{
|
||||
LogPrint(eLogError, "HTTPProxy: unsupported version: ", m_version);
|
||||
HTTPRequestFailed("unsupported HTTP version");
|
||||
HTTPRequestFailed(); //TODO: send right stuff
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -292,13 +268,13 @@ namespace proxy
|
||||
case '\n': EnterState(DONE); break;
|
||||
default:
|
||||
LogPrint(eLogError, "HTTPProxy: rejected invalid request ending with: ", ((int)*http_buff));
|
||||
HTTPRequestFailed("rejected invalid request");
|
||||
HTTPRequestFailed(); //TODO: add correct code
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LogPrint(eLogError, "HTTPProxy: invalid state: ", m_state);
|
||||
HTTPRequestFailed("invalid parser state");
|
||||
HTTPRequestFailed(); //TODO: add correct code 500
|
||||
return false;
|
||||
}
|
||||
http_buff++;
|
||||
@ -354,7 +330,7 @@ namespace proxy
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info");
|
||||
HTTPRequestFailed("error when creating the stream, check logs");
|
||||
HTTPRequestFailed(); // TODO: Send correct error message host unreachable
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,5 +343,6 @@ namespace proxy
|
||||
{
|
||||
return std::make_shared<HTTPProxyHandler> (this, socket);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
#ifndef HTTP_PROXY_H__
|
||||
#define HTTP_PROXY_H__
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <boost/asio.hpp>
|
||||
#include <mutex>
|
||||
#include "I2PService.h"
|
||||
#include "Destination.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace proxy
|
||||
|
164
HTTPServer.cpp
164
HTTPServer.cpp
@ -27,156 +27,6 @@
|
||||
|
||||
namespace i2p {
|
||||
namespace http {
|
||||
const char *itoopieImage =
|
||||
"<img alt=\"ICToopie Icon\" src=\"data:image/png;base64,"
|
||||
"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\" />";
|
||||
|
||||
const char *itoopieFavicon =
|
||||
"data:image/png;base64,"
|
||||
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv"
|
||||
@ -667,7 +517,7 @@ namespace http {
|
||||
i2p::config::GetOption("http.auth", needAuth);
|
||||
i2p::config::GetOption("http.user", user);
|
||||
i2p::config::GetOption("http.pass", pass);
|
||||
};
|
||||
}
|
||||
|
||||
void HTTPConnection::Receive ()
|
||||
{
|
||||
@ -755,12 +605,14 @@ namespace http {
|
||||
|
||||
// Html5 head start
|
||||
ShowPageHead (s);
|
||||
if (req.uri.find("page=") != std::string::npos)
|
||||
if (req.uri.find("page=") != std::string::npos) {
|
||||
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);
|
||||
else
|
||||
} else {
|
||||
ShowStatus (s);
|
||||
res.add_header("Refresh", "5");
|
||||
}
|
||||
ShowPageTail (s);
|
||||
|
||||
res.code = 200;
|
||||
@ -841,7 +693,9 @@ namespace http {
|
||||
return;
|
||||
}
|
||||
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)
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
namespace i2p {
|
||||
namespace http {
|
||||
extern const char *itoopieImage;
|
||||
extern const char *itoopieFavicon;
|
||||
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
|
||||
|
||||
|
587
I2CP.cpp
587
I2CP.cpp
@ -1,29 +1,139 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "I2PEndian.h"
|
||||
#include "Log.h"
|
||||
#include "Timestamp.h"
|
||||
#include "LeaseSet.h"
|
||||
#include "ClientContext.h"
|
||||
#include "Transports.h"
|
||||
#include "Signature.h"
|
||||
#include "I2CP.h"
|
||||
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
|
||||
I2CPDestination::I2CPDestination (I2CPSession& owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic):
|
||||
LeaseSetDestination (isPublic), m_Owner (owner), m_Identity (identity)
|
||||
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):
|
||||
m_Owner (owner), m_Socket (socket),
|
||||
m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0)
|
||||
m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0),
|
||||
m_SessionID (0), m_MessageID (0), m_IsSendAccepted (true)
|
||||
{
|
||||
}
|
||||
|
||||
I2CPSession::~I2CPSession ()
|
||||
{
|
||||
delete[] m_NextMessage;
|
||||
}
|
||||
|
||||
void I2CPSession::Start ()
|
||||
{
|
||||
ReadProtocolByte ();
|
||||
}
|
||||
|
||||
I2CPSession::~I2CPSession ()
|
||||
void I2CPSession::Stop ()
|
||||
{
|
||||
delete[] m_NextMessage;
|
||||
Terminate ();
|
||||
}
|
||||
|
||||
void I2CPSession::ReadProtocolByte ()
|
||||
@ -34,7 +144,7 @@ namespace client
|
||||
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, 1),
|
||||
[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_Buffer[0] == I2CP_PROTOCOL_BYTE)
|
||||
s->Receive ();
|
||||
else
|
||||
s->Terminate ();
|
||||
@ -54,25 +164,34 @@ namespace client
|
||||
Terminate ();
|
||||
else
|
||||
{
|
||||
size_t offset = 0;
|
||||
size_t offset = 0; // from m_Buffer
|
||||
if (m_NextMessage)
|
||||
{
|
||||
if (m_NextMessageOffset + bytes_transferred <= m_NextMessageLen)
|
||||
if (m_NextMessageOffset + bytes_transferred < m_NextMessageLen)
|
||||
{
|
||||
memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred);
|
||||
m_NextMessageOffset += bytes_transferred;
|
||||
offset = bytes_transferred;
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_NextMessage complete
|
||||
offset = m_NextMessageLen - m_NextMessageOffset;
|
||||
memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, offset);
|
||||
HandleNextMessage (m_NextMessage);
|
||||
delete[] m_NextMessage;
|
||||
m_NextMessage = nullptr;
|
||||
}
|
||||
}
|
||||
while (offset < bytes_transferred)
|
||||
{
|
||||
auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE;
|
||||
if (msgLen > 0xFFFF) // 64K
|
||||
{
|
||||
LogPrint (eLogError, "I2CP: message length ", msgLen, " exceeds 64K. Terminated");
|
||||
Terminate ();
|
||||
return;
|
||||
}
|
||||
if (msgLen <= bytes_transferred - offset)
|
||||
{
|
||||
HandleNextMessage (m_Buffer + offset);
|
||||
@ -102,17 +221,463 @@ namespace client
|
||||
|
||||
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 ());
|
||||
}
|
||||
|
||||
void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len)
|
||||
{
|
||||
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 (*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));
|
||||
}
|
||||
|
||||
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 ();
|
||||
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 ();
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (m_Destination)
|
||||
{
|
||||
auto ls = m_Destination->FindLeaseSet (ident);
|
||||
if (ls)
|
||||
SendHostReplyMessage (requestID, ls->GetIdentity ());
|
||||
else
|
||||
{
|
||||
auto s = shared_from_this ();
|
||||
m_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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
119
I2CP.h
119
I2CP.h
@ -1,9 +1,19 @@
|
||||
/*
|
||||
* 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__
|
||||
#define I2CP_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <map>
|
||||
#include <boost/asio.hpp>
|
||||
#include "Destination.h"
|
||||
|
||||
@ -11,7 +21,7 @@ namespace i2p
|
||||
{
|
||||
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_HEADER_LENGTH_OFFSET = 0;
|
||||
@ -19,27 +29,69 @@ namespace client
|
||||
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
|
||||
|
||||
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 (I2CPSession& owner, std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic);
|
||||
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:
|
||||
|
||||
// implements LocalDestination
|
||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Identity; };
|
||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { /* TODO */};
|
||||
|
||||
// I2CP
|
||||
void HandleDataMessage (const uint8_t * buf, size_t len) {};
|
||||
void HandleDataMessage (const uint8_t * buf, size_t len);
|
||||
void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
|
||||
|
||||
private:
|
||||
|
||||
I2CPSession& m_Owner;
|
||||
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;
|
||||
@ -50,8 +102,26 @@ namespace client
|
||||
I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||
~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
|
||||
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:
|
||||
|
||||
@ -60,6 +130,14 @@ namespace client
|
||||
void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||
void HandleNextMessage (const uint8_t * buf);
|
||||
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:
|
||||
|
||||
@ -69,6 +147,9 @@ namespace client
|
||||
size_t m_NextMessageLen, m_NextMessageOffset;
|
||||
|
||||
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);
|
||||
|
||||
@ -77,10 +158,30 @@ namespace client
|
||||
public:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "ClientContext.h"
|
||||
#include "I2PService.h"
|
||||
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace client
|
||||
@ -28,7 +27,7 @@ namespace client
|
||||
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "I2PService: Remote destination ", dest, " not found");
|
||||
LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
|
||||
streamRequestComplete (nullptr);
|
||||
}
|
||||
}
|
||||
@ -71,7 +70,7 @@ namespace client
|
||||
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
|
||||
std::placeholders::_1, std::placeholders::_2));
|
||||
} 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::placeholders::_1, std::placeholders::_2));
|
||||
} 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)
|
||||
{
|
||||
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::transfer_all(),
|
||||
std::bind(&TCPIPPipe::HandleUpstreamWrite,
|
||||
@ -97,14 +96,14 @@ namespace client
|
||||
std::placeholders::_1)
|
||||
);
|
||||
} 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)
|
||||
{
|
||||
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::transfer_all(),
|
||||
std::bind(&TCPIPPipe::HandleDownstreamWrite,
|
||||
@ -112,16 +111,16 @@ namespace client
|
||||
std::placeholders::_1)
|
||||
);
|
||||
} 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)
|
||||
{
|
||||
LogPrint(eLogDebug, "TCPIPPipe downstream got ", (int) bytes_transfered);
|
||||
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received");
|
||||
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)
|
||||
Terminate();
|
||||
} else {
|
||||
@ -135,7 +134,7 @@ namespace client
|
||||
|
||||
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & 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)
|
||||
Terminate();
|
||||
}
|
||||
@ -143,7 +142,7 @@ namespace client
|
||||
|
||||
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & 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)
|
||||
Terminate();
|
||||
}
|
||||
@ -151,9 +150,9 @@ namespace client
|
||||
|
||||
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) {
|
||||
LogPrint(eLogError, "TCPIPPipe Upstream read error:" , ecode.message());
|
||||
LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message());
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
Terminate();
|
||||
} else {
|
||||
@ -206,6 +205,5 @@ namespace client
|
||||
LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -179,9 +179,7 @@ namespace data
|
||||
|
||||
virtual ~LocalDestination() {};
|
||||
virtual const uint8_t * GetEncryptionPrivateKey () const = 0;
|
||||
virtual const uint8_t * GetEncryptionPublicKey () const = 0;
|
||||
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
|
||||
virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0;
|
||||
|
||||
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
|
||||
};
|
||||
|
@ -213,6 +213,7 @@ namespace data
|
||||
m_Buffer[offset] = num;
|
||||
offset++;
|
||||
// leases
|
||||
m_Leases = m_Buffer + offset;
|
||||
auto currentTime = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
@ -231,6 +232,14 @@ namespace data
|
||||
// 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 ();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include "Identity.h"
|
||||
|
||||
@ -88,14 +89,19 @@ namespace data
|
||||
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); };
|
||||
|
||||
@ -104,7 +110,7 @@ namespace data
|
||||
|
||||
uint64_t m_ExpirationTime; // in milliseconds
|
||||
std::shared_ptr<const IdentityEx> m_Identity;
|
||||
uint8_t * m_Buffer;
|
||||
uint8_t * m_Buffer, * m_Leases;
|
||||
size_t m_BufferLen;
|
||||
};
|
||||
}
|
||||
|
20
Log.cpp
20
Log.cpp
@ -12,7 +12,7 @@ namespace i2p {
|
||||
namespace log {
|
||||
Log logger;
|
||||
/**
|
||||
* @enum Maps our loglevel to their symbolic name
|
||||
* @brief Maps our loglevel to their symbolic name
|
||||
*/
|
||||
static const char * g_LogLevelStr[eNumLogLevels] =
|
||||
{
|
||||
@ -56,7 +56,7 @@ namespace log {
|
||||
#endif
|
||||
case eLogFile:
|
||||
case eLogStream:
|
||||
m_LogStream->flush();
|
||||
if (m_LogStream) m_LogStream->flush();
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
@ -107,10 +107,11 @@ namespace log {
|
||||
#endif
|
||||
case eLogFile:
|
||||
case eLogStream:
|
||||
*m_LogStream << TimeAsString(msg->timestamp)
|
||||
<< "@" << short_tid
|
||||
<< "/" << g_LogLevelStr[msg->level]
|
||||
<< " - " << msg->text << std::endl;
|
||||
if (m_LogStream)
|
||||
*m_LogStream << TimeAsString(msg->timestamp)
|
||||
<< "@" << short_tid
|
||||
<< "/" << g_LogLevelStr[msg->level]
|
||||
<< " - " << msg->text << std::endl;
|
||||
break;
|
||||
case eLogStdout:
|
||||
default:
|
||||
@ -130,10 +131,13 @@ namespace log {
|
||||
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 os = std::make_shared<std::ofstream> (path, flags);
|
||||
if (os->is_open ()) {
|
||||
if (os->is_open ())
|
||||
{
|
||||
m_Logfile = path;
|
||||
m_Destination = eLogFile;
|
||||
m_LogStream = os;
|
||||
|
7
Log.h
7
Log.h
@ -86,7 +86,7 @@ namespace log {
|
||||
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
|
||||
*/
|
||||
void SetLogLevel (const std::string& level);
|
||||
@ -101,7 +101,7 @@ namespace log {
|
||||
* @brief Sets log destination to given output stream
|
||||
* @param os Output stream
|
||||
*/
|
||||
void SendTo (std::shared_ptr<std::ostream> s);
|
||||
void SendTo (std::shared_ptr<std::ostream> os);
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
@ -129,7 +129,8 @@ namespace log {
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct Log message container
|
||||
* @struct LogMsg
|
||||
* @brief Log message container
|
||||
*
|
||||
* We creating it somewhere with LogPrint(),
|
||||
* 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:
|
||||
rm -rf obj
|
||||
rm -rf docs/generated
|
||||
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
|
||||
|
||||
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
|
||||
@ -86,9 +87,13 @@ dist:
|
||||
git archive --format=tar.gz -9 --worktree-attributes \
|
||||
--prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz
|
||||
|
||||
doxygen:
|
||||
doxygen -s docs/Doxyfile
|
||||
|
||||
.PHONY: all
|
||||
.PHONY: clean
|
||||
.PHONY: deps
|
||||
.PHONY: doxygen
|
||||
.PHONY: dist
|
||||
.PHONY: api
|
||||
.PHONY: api_client
|
||||
|
@ -9,4 +9,4 @@ CXXFLAGS = -O2
|
||||
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||
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
|
||||
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
||||
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)
|
||||
LDFLAGS += -ldl
|
||||
|
@ -1,5 +1,5 @@
|
||||
# set defaults instead redefine
|
||||
CXXFLAGS ?= -g -Wall
|
||||
CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic
|
||||
INCFLAGS ?=
|
||||
|
||||
## 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_date_time.a
|
||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||
LDLIBS += $(LIBDIR)/libboost_regex.a
|
||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||
LDLIBS += $(LIBDIR)/libcrypto.a
|
||||
LDLIBS += $(LIBDIR)/libssl.a
|
||||
@ -40,7 +39,7 @@ ifeq ($(USE_STATIC),yes)
|
||||
LDLIBS += -lpthread -static-libstdc++ -static-libgcc
|
||||
USE_AESNI := no
|
||||
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
|
||||
|
||||
# UPNP Support (miniupnpc 1.5 or 1.6)
|
||||
|
@ -13,7 +13,6 @@ LDLIBS = \
|
||||
-Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \
|
||||
-Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \
|
||||
-Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \
|
||||
-Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) \
|
||||
-Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \
|
||||
-Wl,-Bstatic -lssl \
|
||||
-Wl,-Bstatic -lcrypto \
|
||||
|
@ -3,7 +3,7 @@ CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX
|
||||
#CXXFLAGS = -g -O2 -Wall -std=c++11
|
||||
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
|
||||
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)
|
||||
LDFLAGS += -ldl
|
||||
|
@ -849,7 +849,8 @@ namespace data
|
||||
template<typename Filter>
|
||||
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 ();
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <openssl/ssl.h>
|
||||
|
@ -353,7 +353,7 @@ namespace data
|
||||
if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable
|
||||
if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable
|
||||
|
||||
SetProperty ("caps", caps.c_str ());
|
||||
SetProperty ("caps", caps);
|
||||
}
|
||||
|
||||
void RouterInfo::WriteToStream (std::ostream& s)
|
||||
|
@ -232,6 +232,11 @@ namespace stream
|
||||
bool acknowledged = false;
|
||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||
uint32_t ackThrough = packet->GetAckThrough ();
|
||||
if (ackThrough > m_SequenceNumber)
|
||||
{
|
||||
LogPrint (eLogError, "Streaming: Unexpected ackThrough=", ackThrough, " > seqn=", m_SequenceNumber);
|
||||
return;
|
||||
}
|
||||
int nackCount = packet->GetNACKCount ();
|
||||
for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();)
|
||||
{
|
||||
@ -336,9 +341,9 @@ namespace stream
|
||||
htobe32buf (packet + size, m_SequenceNumber++);
|
||||
size += 4; // sequenceNum
|
||||
if (isNoAck)
|
||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
||||
else
|
||||
htobuf32 (packet + size, 0);
|
||||
else
|
||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
||||
size += 4; // ack Through
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
@ -521,7 +526,7 @@ namespace stream
|
||||
size += 4; // receiveStreamID
|
||||
htobe32buf (packet + size, m_SequenceNumber++);
|
||||
size += 4; // sequenceNum
|
||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
|
||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0);
|
||||
size += 4; // ack Through
|
||||
packet[size] = 0;
|
||||
size++; // NACK count
|
||||
|
@ -606,7 +606,7 @@ namespace transport
|
||||
|
||||
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);
|
||||
auto it = m_Peers.begin ();
|
||||
std::advance (it, rand () % m_Peers.size ());
|
||||
|
@ -358,7 +358,7 @@ namespace tunnel
|
||||
|
||||
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;
|
||||
std::shared_ptr<OutboundTunnel> tunnel;
|
||||
for (auto it: m_OutboundTunnels)
|
||||
|
2
Tunnel.h
2
Tunnel.h
@ -73,7 +73,7 @@ namespace tunnel
|
||||
|
||||
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
||||
|
||||
virtual void Print (std::stringstream& s) const {};
|
||||
virtual void Print (std::stringstream&) const {};
|
||||
|
||||
// implements TunnelBase
|
||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||
|
@ -125,7 +125,7 @@ install:
|
||||
- cd %BOOST_ROOT%
|
||||
- if defined msvc if not exist "stage%bitness%\lib\%boostlib%boost_system-vc%msvc%0-mt%boostdbg%*" (
|
||||
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
|
||||
)
|
||||
- if defined msvc if not exist C:\stage\OpenSSL-Win%bitness%-vc%msvc%-%type%\ (
|
||||
|
@ -242,7 +242,7 @@ endif()
|
||||
|
||||
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)
|
||||
message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!")
|
||||
endif()
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM ubuntu
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
* 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>
|
||||
Build-Depends: debhelper (>= 9.0.0), dpkg-dev (>= 1.16.1~),
|
||||
gcc (>= 4.7) | clang (>= 3.3),
|
||||
libboost-regex-dev,
|
||||
libboost-system-dev (>= 1.46),
|
||||
libboost-date-time-dev,
|
||||
libboost-filesystem-dev,
|
||||
|
1
debian/i2pd.default
vendored
1
debian/i2pd.default
vendored
@ -4,6 +4,7 @@
|
||||
I2PD_ENABLED="yes"
|
||||
|
||||
# port to listen for incoming connections
|
||||
# comment this line if you want to use value from config
|
||||
I2PD_PORT="4567"
|
||||
|
||||
# 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
|
||||
fi
|
||||
|
||||
if [ -n "$I2PD_PORT" ]; then
|
||||
DAEMON_OPTS="--port $I2PD_PORT $DAEMON_OPTS"
|
||||
fi
|
||||
|
||||
touch "$PIDFILE"
|
||||
chown -f $USER:adm "$PIDFILE"
|
||||
|
||||
@ -51,7 +55,7 @@ do_start()
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \
|
||||
--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 $?
|
||||
}
|
||||
|
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
|
||||
./bootstrap.sh
|
||||
./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
|
||||
cd ..
|
||||
```
|
||||
|
@ -46,7 +46,6 @@ sudo apt-get install \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
libssl-dev
|
||||
|
@ -110,11 +110,11 @@ prompt to build Boost) and run the following:
|
||||
|
||||
cd C:\dev\boost
|
||||
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
|
||||
|
||||
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
|
||||
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.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.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified
|
||||
|
BIN
docs/itoopieImage.png
Normal file
BIN
docs/itoopieImage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
1
stdafx.h
1
stdafx.h
@ -33,7 +33,6 @@
|
||||
#include <mutex>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
@ -1,6 +1,7 @@
|
||||
CXXFLAGS += -Wall -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
||||
|
||||
TESTS = test-http-url test-http-req test-http-res test-http-url_decode
|
||||
TESTS = test-http-url test-http-req test-http-res test-http-url_decode \
|
||||
test-http-merge_chunked
|
||||
|
||||
all: $(TESTS) run
|
||||
|
||||
|
25
tests/test-http-merge_chunked.cpp
Normal file
25
tests/test-http-merge_chunked.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include <cassert>
|
||||
#include "../HTTP.h"
|
||||
|
||||
using namespace i2p::http;
|
||||
|
||||
int main() {
|
||||
const char *buf =
|
||||
"4\r\n"
|
||||
"HTTP\r\n"
|
||||
"A\r\n"
|
||||
" response \r\n"
|
||||
"E\r\n"
|
||||
"with \r\n"
|
||||
"chunks.\r\n"
|
||||
"0\r\n"
|
||||
"\r\n"
|
||||
;
|
||||
std::stringstream in(buf);
|
||||
std::stringstream out;
|
||||
|
||||
assert(MergeChunkedResponse(in, out) == true);
|
||||
assert(out.str() == "HTTP response with \r\nchunks.");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user