mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
upstream pull
This commit is contained in:
commit
44cfe6af1c
@ -705,6 +705,7 @@ namespace client
|
||||
i2p::http::HTTPReq req;
|
||||
req.AddHeader("Host", dest_host);
|
||||
req.AddHeader("User-Agent", "Wget/1.11.4");
|
||||
req.AddHeader("X-Accept-Encoding", "x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n");
|
||||
req.AddHeader("Connection", "close");
|
||||
if (!m_Etag.empty())
|
||||
req.AddHeader("If-None-Match", m_Etag);
|
||||
@ -721,7 +722,9 @@ namespace client
|
||||
std::string response;
|
||||
uint8_t recv_buf[4096];
|
||||
bool end = false;
|
||||
while (!end) {
|
||||
int numAttempts = 5;
|
||||
while (!end)
|
||||
{
|
||||
stream->AsyncReceive (boost::asio::buffer (recv_buf, 4096),
|
||||
[&](const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||
{
|
||||
@ -734,60 +737,69 @@ namespace client
|
||||
30); // wait for 30 seconds
|
||||
std::unique_lock<std::mutex> l(newDataReceivedMutex);
|
||||
if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout)
|
||||
{
|
||||
LogPrint (eLogError, "Addressbook: subscriptions request timeout expired");
|
||||
numAttempts++;
|
||||
if (numAttempts > 5) end = true;
|
||||
}
|
||||
}
|
||||
// process remaining buffer
|
||||
while (size_t len = stream->ReadSome (recv_buf, sizeof(recv_buf))) {
|
||||
while (size_t len = stream->ReadSome (recv_buf, sizeof(recv_buf)))
|
||||
response.append ((char *)recv_buf, len);
|
||||
}
|
||||
/* parse response */
|
||||
i2p::http::HTTPRes res;
|
||||
int res_head_len = res.parse(response);
|
||||
if (res_head_len < 0) {
|
||||
if (res_head_len < 0)
|
||||
{
|
||||
LogPrint(eLogError, "Addressbook: can't parse http response from ", dest_host);
|
||||
return false;
|
||||
}
|
||||
if (res_head_len == 0) {
|
||||
if (res_head_len == 0)
|
||||
{
|
||||
LogPrint(eLogError, "Addressbook: incomplete http response from ", dest_host, ", interrupted by timeout");
|
||||
return false;
|
||||
}
|
||||
/* assert: res_head_len > 0 */
|
||||
response.erase(0, res_head_len);
|
||||
if (res.code == 304) {
|
||||
if (res.code == 304)
|
||||
{
|
||||
LogPrint (eLogInfo, "Addressbook: no updates from ", dest_host, ", code 304");
|
||||
return false;
|
||||
}
|
||||
if (res.code != 200) {
|
||||
if (res.code != 200)
|
||||
{
|
||||
LogPrint (eLogWarning, "Adressbook: can't get updates from ", dest_host, ", response code ", res.code);
|
||||
return false;
|
||||
}
|
||||
int len = res.content_length();
|
||||
if (response.empty()) {
|
||||
if (response.empty())
|
||||
{
|
||||
LogPrint(eLogError, "Addressbook: empty response from ", dest_host, ", expected ", len, " bytes");
|
||||
return false;
|
||||
}
|
||||
if (len > 0 && len != (int) response.length()) {
|
||||
LogPrint(eLogError, "Addressbook: response size mismatch, expected: ", response.length(), ", got: ", len, "bytes");
|
||||
if (!res.is_gzipped () && len > 0 && len != (int) response.length())
|
||||
{
|
||||
LogPrint(eLogError, "Addressbook: response size mismatch, expected: ", len, ", got: ", response.length(), "bytes");
|
||||
return false;
|
||||
}
|
||||
/* assert: res.code == 200 */
|
||||
auto it = res.headers.find("ETag");
|
||||
if (it != res.headers.end()) {
|
||||
m_Etag = it->second;
|
||||
}
|
||||
if (it != res.headers.end()) m_Etag = it->second;
|
||||
it = res.headers.find("If-Modified-Since");
|
||||
if (it != res.headers.end()) {
|
||||
m_LastModified = it->second;
|
||||
}
|
||||
if (res.is_chunked()) {
|
||||
if (it != res.headers.end()) m_LastModified = it->second;
|
||||
if (res.is_chunked())
|
||||
{
|
||||
std::stringstream in(response), out;
|
||||
i2p::http::MergeChunkedResponse (in, out);
|
||||
response = out.str();
|
||||
} else if (res.is_gzipped()) {
|
||||
}
|
||||
else if (res.is_gzipped())
|
||||
{
|
||||
std::stringstream out;
|
||||
i2p::data::GzipInflator inflator;
|
||||
inflator.Inflate ((const uint8_t *) response.data(), response.length(), out);
|
||||
if (out.fail()) {
|
||||
if (out.fail())
|
||||
{
|
||||
LogPrint(eLogError, "Addressbook: can't gunzip http response");
|
||||
return false;
|
||||
}
|
||||
|
@ -50,11 +50,12 @@ namespace client
|
||||
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
|
||||
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
|
||||
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
|
||||
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
|
||||
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
|
||||
if (httpProxyKeys.length () > 0)
|
||||
{
|
||||
i2p::data::PrivateKeys keys;
|
||||
if(LoadPrivateKeys (keys, httpProxyKeys, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1))
|
||||
if(LoadPrivateKeys (keys, httpProxyKeys, sigType))
|
||||
{
|
||||
std::map<std::string, std::string> params;
|
||||
ReadI2CPOptionsFromConfig ("httpproxy.", params);
|
||||
@ -80,11 +81,12 @@ namespace client
|
||||
uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort);
|
||||
std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr);
|
||||
uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort);
|
||||
i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType);
|
||||
LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort);
|
||||
if (socksProxyKeys.length () > 0)
|
||||
{
|
||||
i2p::data::PrivateKeys keys;
|
||||
if (LoadPrivateKeys (keys, socksProxyKeys, i2p::data::SIGNING_KEY_TYPE_DSA_SHA1))
|
||||
if (LoadPrivateKeys (keys, socksProxyKeys, sigType))
|
||||
{
|
||||
std::map<std::string, std::string> params;
|
||||
ReadI2CPOptionsFromConfig ("socksproxy.", params);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
||||
#include "Identity.h"
|
||||
#include "Config.h"
|
||||
#include "version.h"
|
||||
|
||||
@ -85,6 +86,7 @@ namespace config {
|
||||
("httpproxy.address", value<std::string>()->default_value("127.0.0.1"), "HTTP Proxy listen address")
|
||||
("httpproxy.port", value<uint16_t>()->default_value(4444), "HTTP Proxy listen port")
|
||||
("httpproxy.keys", value<std::string>()->default_value(""), "File to persist HTTP Proxy keys")
|
||||
("httpproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||
("httpproxy.inbound.length", value<std::string>()->default_value("3"), "HTTP proxy inbound tunnel length")
|
||||
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
||||
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
||||
@ -100,6 +102,7 @@ namespace config {
|
||||
("socksproxy.address", value<std::string>()->default_value("127.0.0.1"), "SOCKS Proxy listen address")
|
||||
("socksproxy.port", value<uint16_t>()->default_value(4447), "SOCKS Proxy listen port")
|
||||
("socksproxy.keys", value<std::string>()->default_value(""), "File to persist SOCKS Proxy keys")
|
||||
("socksproxy.signaturetype", value<i2p::data::SigningKeyType>()->default_value(i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519), "Signature type for new keys. 7 (EdDSA) by default")
|
||||
("socksproxy.inbound.length", value<std::string>()->default_value("3"), "SOCKS proxy inbound tunnel length")
|
||||
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
||||
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
||||
|
@ -14,8 +14,8 @@ namespace client
|
||||
{
|
||||
LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params):
|
||||
m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic),
|
||||
m_PublishReplyToken (0), m_PublishConfirmationTimer (m_Service),
|
||||
m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service)
|
||||
m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
|
||||
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service)
|
||||
{
|
||||
int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
|
||||
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
||||
@ -426,6 +426,16 @@ namespace client
|
||||
LogPrint (eLogDebug, "Destination: Publishing LeaseSet is pending");
|
||||
return;
|
||||
}
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (ts < m_LastSubmissionTime + PUBLISH_MIN_INTERVAL)
|
||||
{
|
||||
LogPrint (eLogDebug, "Destination: Publishing LeaseSet is too fast. Wait for ", PUBLISH_MIN_INTERVAL, " seconds");
|
||||
m_PublishDelayTimer.cancel ();
|
||||
m_PublishDelayTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_MIN_INTERVAL));
|
||||
m_PublishDelayTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishDelayTimer,
|
||||
shared_from_this (), std::placeholders::_1));
|
||||
return;
|
||||
}
|
||||
auto outbound = m_Pool->GetNextOutboundTunnel ();
|
||||
if (!outbound)
|
||||
{
|
||||
@ -453,6 +463,7 @@ namespace client
|
||||
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
|
||||
shared_from_this (), std::placeholders::_1));
|
||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
|
||||
m_LastSubmissionTime = ts;
|
||||
}
|
||||
|
||||
void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
|
||||
@ -477,13 +488,18 @@ namespace client
|
||||
// "this" added due to bug in gcc 4.7-4.8
|
||||
[s,this](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
|
||||
{
|
||||
if (leaseSet && s->m_LeaseSet)
|
||||
if (leaseSet)
|
||||
{
|
||||
// we got latest LeasetSet
|
||||
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32());
|
||||
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
||||
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||
return;
|
||||
if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet)
|
||||
{
|
||||
// we got latest LeasetSet
|
||||
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32());
|
||||
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
||||
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||
return;
|
||||
}
|
||||
else
|
||||
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", GetIdentHash().ToBase32());
|
||||
}
|
||||
else
|
||||
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32());
|
||||
@ -493,6 +509,12 @@ namespace client
|
||||
}
|
||||
}
|
||||
|
||||
void LeaseSetDestination::HandlePublishDelayTimer (const boost::system::error_code& ecode)
|
||||
{
|
||||
if (ecode != boost::asio::error::operation_aborted)
|
||||
Publish ();
|
||||
}
|
||||
|
||||
bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
|
||||
{
|
||||
if (!m_Pool || !IsReady ())
|
||||
|
@ -30,6 +30,7 @@ namespace client
|
||||
const uint8_t PROTOCOL_TYPE_RAW = 18;
|
||||
const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
||||
const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successfull publish
|
||||
const int PUBLISH_MIN_INTERVAL = 20; // in seconds
|
||||
const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically
|
||||
const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds
|
||||
const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds
|
||||
@ -122,6 +123,7 @@ namespace client
|
||||
void Publish ();
|
||||
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
||||
void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
|
||||
void HandlePublishDelayTimer (const boost::system::error_code& ecode);
|
||||
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len);
|
||||
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
||||
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||
@ -146,9 +148,11 @@ namespace client
|
||||
std::shared_ptr<i2p::data::LocalLeaseSet> m_LeaseSet;
|
||||
bool m_IsPublic;
|
||||
uint32_t m_PublishReplyToken;
|
||||
uint64_t m_LastSubmissionTime; // in seconds
|
||||
std::set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
|
||||
|
||||
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_CleanupTimer;
|
||||
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
|
||||
m_PublishDelayTimer, m_CleanupTimer;
|
||||
|
||||
public:
|
||||
|
||||
|
13
HTTP.cpp
13
HTTP.cpp
@ -312,7 +312,8 @@ namespace http {
|
||||
return "";
|
||||
}
|
||||
|
||||
bool HTTPRes::is_chunked() {
|
||||
bool HTTPRes::is_chunked() const
|
||||
{
|
||||
auto it = headers.find("Transfer-Encoding");
|
||||
if (it == headers.end())
|
||||
return false;
|
||||
@ -321,16 +322,20 @@ namespace http {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HTTPRes::is_gzipped() {
|
||||
bool HTTPRes::is_gzipped(bool includingI2PGzip) const
|
||||
{
|
||||
auto it = headers.find("Content-Encoding");
|
||||
if (it == headers.end())
|
||||
return false; /* no header */
|
||||
if (it->second.find("gzip") != std::string::npos)
|
||||
return true; /* gotcha! */
|
||||
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
long int HTTPMsg::content_length() {
|
||||
|
||||
long int HTTPMsg::content_length() const
|
||||
{
|
||||
unsigned long int length = 0;
|
||||
auto it = headers.find("Content-Length");
|
||||
if (it == headers.end())
|
||||
|
6
HTTP.h
6
HTTP.h
@ -64,7 +64,7 @@ namespace http {
|
||||
void del_header(const char *name);
|
||||
|
||||
/** @brief Returns declared message length or -1 if unknown */
|
||||
long int content_length();
|
||||
long int content_length() const;
|
||||
};
|
||||
|
||||
struct HTTPReq
|
||||
@ -129,10 +129,10 @@ namespace http {
|
||||
void write(std::ostream & o);
|
||||
|
||||
/** @brief Checks that response declared as chunked data */
|
||||
bool is_chunked();
|
||||
bool is_chunked() const ;
|
||||
|
||||
/** @brief Checks that response contains compressed data */
|
||||
bool is_gzipped();
|
||||
bool is_gzipped(bool includingI2PGzip = true) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
2
SSU.h
2
SSU.h
@ -30,7 +30,7 @@ namespace transport
|
||||
|
||||
struct SSUPacket
|
||||
{
|
||||
i2p::crypto::AESAlignedBuffer<SSU_MTU_V4 + 18> buf; // max MTU + iv + size
|
||||
i2p::crypto::AESAlignedBuffer<SSU_MTU_V6 + 18> buf; // max MTU + iv + size
|
||||
boost::asio::ip::udp::endpoint from;
|
||||
size_t len;
|
||||
};
|
||||
|
@ -462,6 +462,7 @@ namespace transport
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (m_SentMessages.empty ()) return; // nothing to resend
|
||||
if (numResent < MAX_OUTGOING_WINDOW_SIZE)
|
||||
ScheduleResend ();
|
||||
else
|
||||
|
@ -21,13 +21,13 @@ namespace transport
|
||||
#ifdef MESHNET
|
||||
const size_t SSU_MTU_V6 = 1286;
|
||||
#else
|
||||
const size_t SSU_MTU_V6 = 1472;
|
||||
const size_t SSU_MTU_V6 = 1488;
|
||||
#endif
|
||||
const size_t IPV4_HEADER_SIZE = 20;
|
||||
const size_t IPV6_HEADER_SIZE = 40;
|
||||
const size_t UDP_HEADER_SIZE = 8;
|
||||
const size_t SSU_V4_MAX_PACKET_SIZE = SSU_MTU_V4 - IPV4_HEADER_SIZE - UDP_HEADER_SIZE; // 1456
|
||||
const size_t SSU_V6_MAX_PACKET_SIZE = SSU_MTU_V6 - IPV6_HEADER_SIZE - UDP_HEADER_SIZE; // 1424
|
||||
const size_t SSU_V6_MAX_PACKET_SIZE = SSU_MTU_V6 - IPV6_HEADER_SIZE - UDP_HEADER_SIZE; // 1440
|
||||
const int RESEND_INTERVAL = 3; // in seconds
|
||||
const int MAX_NUM_RESENDS = 5;
|
||||
const int DECAY_INTERVAL = 20; // in seconds
|
||||
|
30
contrib/apparmor/usr.sbin.i2pd
Normal file
30
contrib/apparmor/usr.sbin.i2pd
Normal file
@ -0,0 +1,30 @@
|
||||
# Basic profile for i2pd
|
||||
# Should work without modifications with Ubuntu/Debian packages
|
||||
# Author: Darknet Villain <supervillain@riseup.net>
|
||||
#
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/sbin/i2pd {
|
||||
#include <abstractions/base>
|
||||
|
||||
network inet dgram,
|
||||
network inet stream,
|
||||
network inet6 dgram,
|
||||
network inet6 stream,
|
||||
network netlink raw,
|
||||
|
||||
/etc/gai.conf r,
|
||||
/etc/host.conf r,
|
||||
/etc/hosts r,
|
||||
/etc/nsswitch.conf r,
|
||||
/run/resolvconf/resolv.conf r,
|
||||
|
||||
# path specific (feel free to modify if you have another paths)
|
||||
/etc/i2pd/** r,
|
||||
/var/lib/i2pd/** rw,
|
||||
/var/log/i2pd.log w,
|
||||
/var/run/i2pd/i2pd.pid rw,
|
||||
/usr/sbin/i2pd mr,
|
||||
|
||||
|
||||
}
|
@ -46,6 +46,7 @@ All options below still possible in cmdline, but better write it in config file:
|
||||
* --httpproxy.address= - The address to listen on (HTTP Proxy)
|
||||
* --httpproxy.port= - The port to listen on (HTTP Proxy) 4444 by default
|
||||
* --httpproxy.keys= - optional keys file for HTTP proxy local destination
|
||||
* --httpproxy.signaturetype= - signature type for new keys if keys file is set. 7 by default
|
||||
* --httpproxy.inbound.length= - Inbound tunnels length if keys is set. 3 by default
|
||||
* --httpproxy.inbound.quantity= - Inbound tunnels quantity if keys is set. 5 by default
|
||||
* --httpproxy.outbound.length= - Outbound tunnels length if keys is set. 3 by default
|
||||
@ -55,6 +56,7 @@ All options below still possible in cmdline, but better write it in config file:
|
||||
* --socksproxy.address= - The address to listen on (SOCKS Proxy)
|
||||
* --socksproxy.port= - The port to listen on (SOCKS Proxy). 4447 by default
|
||||
* --socksproxy.keys= - optional keys file for SOCKS proxy local destination
|
||||
* --socksproxy.signaturetype= - signature type for new keys if keys file is set. 7 by default
|
||||
* --socksproxy.inbound.length= - Inbound tunnels length if keys is set. 3 by default
|
||||
* --socksproxy.inbound.quantity= - Inbound tunnels quantity if keys is set. 5 by default
|
||||
* --socksproxy.outbound.length= - Outbound tunnels length if keys is set. 3 by default
|
||||
|
Loading…
Reference in New Issue
Block a user