mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 16:10:33 +03:00
commit
03d7330af5
@ -203,7 +203,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
AddressBook::AddressBook (): m_Storage(new AddressBookFilesystemStorage), m_IsLoaded (false), m_IsDownloading (false),
|
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
|
||||||
m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
|
m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -215,6 +215,8 @@ namespace client
|
|||||||
|
|
||||||
void AddressBook::Start ()
|
void AddressBook::Start ()
|
||||||
{
|
{
|
||||||
|
if (!m_Storage)
|
||||||
|
m_Storage = new AddressBookFilesystemStorage;
|
||||||
m_Storage->Init();
|
m_Storage->Init();
|
||||||
LoadHosts (); /* try storage, then hosts.txt, then download */
|
LoadHosts (); /* try storage, then hosts.txt, then download */
|
||||||
StartSubscriptions ();
|
StartSubscriptions ();
|
||||||
|
104
Base.cpp
104
Base.cpp
@ -1,5 +1,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "Log.h"
|
#include <string.h>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@ -284,107 +285,6 @@ namespace data
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
GzipInflator::GzipInflator (): m_IsDirty (false)
|
|
||||||
{
|
|
||||||
memset (&m_Inflator, 0, sizeof (m_Inflator));
|
|
||||||
inflateInit2 (&m_Inflator, MAX_WBITS + 16); // gzip
|
|
||||||
}
|
|
||||||
|
|
||||||
GzipInflator::~GzipInflator ()
|
|
||||||
{
|
|
||||||
inflateEnd (&m_Inflator);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GzipInflator::Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
|
|
||||||
{
|
|
||||||
if (m_IsDirty) inflateReset (&m_Inflator);
|
|
||||||
m_IsDirty = true;
|
|
||||||
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
|
||||||
m_Inflator.avail_in = inLen;
|
|
||||||
m_Inflator.next_out = out;
|
|
||||||
m_Inflator.avail_out = outLen;
|
|
||||||
int err;
|
|
||||||
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END)
|
|
||||||
return outLen - m_Inflator.avail_out;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "Decompression error ", err);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& s)
|
|
||||||
{
|
|
||||||
m_IsDirty = true;
|
|
||||||
uint8_t * out = new uint8_t[GZIP_CHUNK_SIZE];
|
|
||||||
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
|
||||||
m_Inflator.avail_in = inLen;
|
|
||||||
int ret;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
m_Inflator.next_out = out;
|
|
||||||
m_Inflator.avail_out = GZIP_CHUNK_SIZE;
|
|
||||||
ret = inflate (&m_Inflator, Z_NO_FLUSH);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "Decompression error ", ret);
|
|
||||||
inflateEnd (&m_Inflator);
|
|
||||||
s.setstate(std::ios_base::failbit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out);
|
|
||||||
}
|
|
||||||
while (!m_Inflator.avail_out); // more data to read
|
|
||||||
delete[] out;
|
|
||||||
return ret == Z_STREAM_END || ret < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GzipInflator::Inflate (std::istream& in, std::ostream& out)
|
|
||||||
{
|
|
||||||
uint8_t * buf = new uint8_t[GZIP_CHUNK_SIZE];
|
|
||||||
while (!in.eof ())
|
|
||||||
{
|
|
||||||
in.read ((char *)buf, GZIP_CHUNK_SIZE);
|
|
||||||
Inflate (buf, in.gcount (), out);
|
|
||||||
}
|
|
||||||
delete[] buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
GzipDeflator::GzipDeflator (): m_IsDirty (false)
|
|
||||||
{
|
|
||||||
memset (&m_Deflator, 0, sizeof (m_Deflator));
|
|
||||||
deflateInit2 (&m_Deflator, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); // 15 + 16 sets gzip
|
|
||||||
}
|
|
||||||
|
|
||||||
GzipDeflator::~GzipDeflator ()
|
|
||||||
{
|
|
||||||
deflateEnd (&m_Deflator);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GzipDeflator::SetCompressionLevel (int level)
|
|
||||||
{
|
|
||||||
deflateParams (&m_Deflator, level, Z_DEFAULT_STRATEGY);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t GzipDeflator::Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
|
|
||||||
{
|
|
||||||
if (m_IsDirty) deflateReset (&m_Deflator);
|
|
||||||
m_IsDirty = true;
|
|
||||||
m_Deflator.next_in = const_cast<uint8_t *>(in);
|
|
||||||
m_Deflator.avail_in = inLen;
|
|
||||||
m_Deflator.next_out = out;
|
|
||||||
m_Deflator.avail_out = outLen;
|
|
||||||
int err;
|
|
||||||
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END)
|
|
||||||
return outLen - m_Deflator.avail_out;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "Compression error ", err);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
117
Base.h
117
Base.h
@ -2,15 +2,11 @@
|
|||||||
#define BASE_H__
|
#define BASE_H__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <zlib.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p {
|
||||||
{
|
namespace data {
|
||||||
namespace data
|
|
||||||
{
|
|
||||||
size_t ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount, char * OutBuffer, size_t len);
|
size_t ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount, char * OutBuffer, size_t len);
|
||||||
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
|
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
|
||||||
const char * GetBase32SubstitutionTable ();
|
const char * GetBase32SubstitutionTable ();
|
||||||
@ -23,112 +19,7 @@ namespace data
|
|||||||
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
||||||
*/
|
*/
|
||||||
size_t Base64EncodingBufferSize(const size_t input_size);
|
size_t Base64EncodingBufferSize(const size_t input_size);
|
||||||
|
} // data
|
||||||
template<int sz>
|
} // i2p
|
||||||
class Tag
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); };
|
|
||||||
Tag (const Tag<sz>& ) = default;
|
|
||||||
#ifndef _WIN32 // FIXME!!! msvs 2013 can't compile it
|
|
||||||
Tag (Tag<sz>&& ) = default;
|
|
||||||
#endif
|
|
||||||
Tag () = default;
|
|
||||||
|
|
||||||
Tag<sz>& operator= (const Tag<sz>& ) = default;
|
|
||||||
#ifndef _WIN32
|
|
||||||
Tag<sz>& operator= (Tag<sz>&& ) = default;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t * operator()() { return m_Buf; };
|
|
||||||
const uint8_t * operator()() const { return m_Buf; };
|
|
||||||
|
|
||||||
operator uint8_t * () { return m_Buf; };
|
|
||||||
operator const uint8_t * () const { return m_Buf; };
|
|
||||||
|
|
||||||
const uint64_t * GetLL () const { return ll; };
|
|
||||||
|
|
||||||
bool operator== (const Tag<sz>& other) const { return !memcmp (m_Buf, other.m_Buf, sz); };
|
|
||||||
bool operator< (const Tag<sz>& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; };
|
|
||||||
|
|
||||||
bool IsZero () const
|
|
||||||
{
|
|
||||||
for (int i = 0; i < sz/8; i++)
|
|
||||||
if (ll[i]) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToBase64 () const
|
|
||||||
{
|
|
||||||
char str[sz*2];
|
|
||||||
int l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
|
|
||||||
str[l] = 0;
|
|
||||||
return std::string (str);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToBase32 () const
|
|
||||||
{
|
|
||||||
char str[sz*2];
|
|
||||||
int l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
|
|
||||||
str[l] = 0;
|
|
||||||
return std::string (str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FromBase32 (const std::string& s)
|
|
||||||
{
|
|
||||||
i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FromBase64 (const std::string& s)
|
|
||||||
{
|
|
||||||
i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
union // 8 bytes alignment
|
|
||||||
{
|
|
||||||
uint8_t m_Buf[sz];
|
|
||||||
uint64_t ll[sz/8];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const size_t GZIP_CHUNK_SIZE = 16384;
|
|
||||||
class GzipInflator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
GzipInflator ();
|
|
||||||
~GzipInflator ();
|
|
||||||
|
|
||||||
size_t Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
|
||||||
bool Inflate (const uint8_t * in, size_t inLen, std::ostream& s);
|
|
||||||
// return true when finshed or error, s failbit will be set in case of error
|
|
||||||
void Inflate (std::istream& in, std::ostream& out);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
z_stream m_Inflator;
|
|
||||||
bool m_IsDirty;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GzipDeflator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
GzipDeflator ();
|
|
||||||
~GzipDeflator ();
|
|
||||||
|
|
||||||
void SetCompressionLevel (int level);
|
|
||||||
size_t Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
z_stream m_Deflator;
|
|
||||||
bool m_IsDirty;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
11
ChangeLog
11
ChangeLog
@ -1,14 +1,23 @@
|
|||||||
# for this file format description,
|
# for this file format description,
|
||||||
# see https://github.com/olivierlacan/keep-a-changelog
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
## [2.8.0] - UNRELEASED
|
## [2.9.0] - UNRELEASED
|
||||||
### Changed
|
### Changed
|
||||||
- Proxy refactoring & speedup
|
- Proxy refactoring & speedup
|
||||||
|
|
||||||
|
## [2.8.0] - 2016-06-20
|
||||||
|
### Added
|
||||||
|
- Basic Android support
|
||||||
|
- I2CP implementation
|
||||||
|
- 'doxygen' target
|
||||||
|
|
||||||
|
### Changed
|
||||||
- I2PControl refactoring & fixes (proper jsonrpc responses on errors)
|
- I2PControl refactoring & fixes (proper jsonrpc responses on errors)
|
||||||
- boost::regex no more needed
|
- boost::regex no more needed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- initscripts: added openrc one, in sysv-ish make I2PD_PORT optional
|
- initscripts: added openrc one, in sysv-ish make I2PD_PORT optional
|
||||||
|
- properly close NTCP sessions (memleak)
|
||||||
|
|
||||||
## [2.7.0] - 2016-05-18
|
## [2.7.0] - 2016-05-18
|
||||||
### Added
|
### Added
|
||||||
|
79
Config.cpp
79
Config.cpp
@ -26,83 +26,6 @@ namespace config {
|
|||||||
options_description m_OptionsDesc;
|
options_description m_OptionsDesc;
|
||||||
variables_map m_Options;
|
variables_map m_Options;
|
||||||
|
|
||||||
/* list of renamed options */
|
|
||||||
std::map<std::string, std::string> remapped_options = {
|
|
||||||
{ "tunnelscfg", "tunconf" },
|
|
||||||
{ "v6", "ipv6" },
|
|
||||||
{ "httpaddress", "http.address" },
|
|
||||||
{ "httpport", "http.port" },
|
|
||||||
{ "httpproxyaddress", "httpproxy.address" },
|
|
||||||
{ "httpproxyport", "httpproxy.port" },
|
|
||||||
{ "socksproxyaddress", "socksproxy.address" },
|
|
||||||
{ "socksproxyport", "socksproxy.port" },
|
|
||||||
{ "samaddress", "sam.address" },
|
|
||||||
{ "samport", "sam.port" },
|
|
||||||
{ "bobaddress", "bob.address" },
|
|
||||||
{ "bobport", "bob.port" },
|
|
||||||
{ "i2pcontroladdress", "i2pcontrol.address" },
|
|
||||||
{ "i2pcontroladdress", "i2pcontrol.port" },
|
|
||||||
{ "proxykeys", "httpproxy.keys" },
|
|
||||||
};
|
|
||||||
/* list of options, that loose their argument and become simple switch */
|
|
||||||
std::set<std::string> boolean_options = {
|
|
||||||
"daemon", "floodfill", "notransit", "service", "ipv6"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* this function is a solid piece of shit, remove it after 2.6.0 */
|
|
||||||
std::pair<std::string, std::string> old_syntax_parser(const std::string& s) {
|
|
||||||
std::string name = "";
|
|
||||||
std::string value = "";
|
|
||||||
std::size_t pos = 0;
|
|
||||||
/* shortcuts -- -h */
|
|
||||||
if (s.length() == 2 && s.at(0) == '-' && s.at(1) != '-')
|
|
||||||
return make_pair(s.substr(1), "");
|
|
||||||
/* old-style -- -log, /log, etc */
|
|
||||||
if (s.at(0) == '/' || (s.at(0) == '-' && s.at(1) != '-')) {
|
|
||||||
if ((pos = s.find_first_of("= ")) != std::string::npos) {
|
|
||||||
name = s.substr(1, pos - 1);
|
|
||||||
value = s.substr(pos + 1);
|
|
||||||
} else {
|
|
||||||
name = s.substr(1, pos);
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
if (boolean_options.count(name) > 0 && value != "")
|
|
||||||
std::cerr << "args: don't give an argument to switch option: " << s << std::endl;
|
|
||||||
if (m_OptionsDesc.find_nothrow(name, false)) {
|
|
||||||
std::cerr << "args: option " << s << " style is DEPRECATED, use --" << name << " instead" << std::endl;
|
|
||||||
return std::make_pair(name, value);
|
|
||||||
}
|
|
||||||
if (remapped_options.count(name) > 0) {
|
|
||||||
name = remapped_options[name];
|
|
||||||
std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl;
|
|
||||||
return std::make_pair(name, value);
|
|
||||||
} /* else */
|
|
||||||
}
|
|
||||||
/* long options -- --help */
|
|
||||||
if (s.substr(0, 2) == "--") {
|
|
||||||
if ((pos = s.find_first_of("= ")) != std::string::npos) {
|
|
||||||
name = s.substr(2, pos - 2);
|
|
||||||
value = s.substr(pos + 1);
|
|
||||||
} else {
|
|
||||||
name = s.substr(2, pos);
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
if (boolean_options.count(name) > 0 && value != "") {
|
|
||||||
std::cerr << "args: don't give an argument to switch option: " << s << std::endl;
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
if (m_OptionsDesc.find_nothrow(name, false))
|
|
||||||
return std::make_pair(name, value);
|
|
||||||
if (remapped_options.count(name) > 0) {
|
|
||||||
name = remapped_options[name];
|
|
||||||
std::cerr << "args: option " << s << " is DEPRECATED, use --" << name << " instead" << std::endl;
|
|
||||||
return std::make_pair(name, value);
|
|
||||||
} /* else */
|
|
||||||
}
|
|
||||||
std::cerr << "args: unknown option -- " << s << std::endl;
|
|
||||||
return std::make_pair("", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
options_description general("General options");
|
options_description general("General options");
|
||||||
general.add_options()
|
general.add_options()
|
||||||
@ -225,7 +148,7 @@ namespace config {
|
|||||||
auto style = boost::program_options::command_line_style::unix_style
|
auto style = boost::program_options::command_line_style::unix_style
|
||||||
| boost::program_options::command_line_style::allow_long_disguise;
|
| boost::program_options::command_line_style::allow_long_disguise;
|
||||||
style &= ~ boost::program_options::command_line_style::allow_guessing;
|
style &= ~ boost::program_options::command_line_style::allow_guessing;
|
||||||
store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options);
|
store(parse_command_line(argc, argv, m_OptionsDesc, style), m_Options);
|
||||||
} catch (boost::program_options::error& e) {
|
} catch (boost::program_options::error& e) {
|
||||||
std::cerr << "args: " << e.what() << std::endl;
|
std::cerr << "args: " << e.what() << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
2
Crypto.h
2
Crypto.h
@ -9,7 +9,9 @@
|
|||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
#include "Tag.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
226
DaemonWin32.cpp
226
DaemonWin32.cpp
@ -1,113 +1,115 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include "Config.h"
|
#include <clocale>
|
||||||
#include "Daemon.h"
|
#include "Config.h"
|
||||||
#include "util.h"
|
#include "Daemon.h"
|
||||||
#include "Log.h"
|
#include "util.h"
|
||||||
|
#include "Log.h"
|
||||||
#ifdef _WIN32
|
|
||||||
|
#ifdef _WIN32
|
||||||
#include "Win32/Win32Service.h"
|
|
||||||
#ifdef WIN32_APP
|
#include "Win32/Win32Service.h"
|
||||||
#include "Win32/Win32App.h"
|
#ifdef WIN32_APP
|
||||||
#endif
|
#include "Win32/Win32App.h"
|
||||||
|
#endif
|
||||||
namespace i2p
|
|
||||||
{
|
namespace i2p
|
||||||
namespace util
|
{
|
||||||
{
|
namespace util
|
||||||
bool DaemonWin32::init(int argc, char* argv[])
|
{
|
||||||
{
|
bool DaemonWin32::init(int argc, char* argv[])
|
||||||
setlocale(LC_CTYPE, "");
|
{
|
||||||
SetConsoleCP(1251);
|
setlocale(LC_CTYPE, "");
|
||||||
SetConsoleOutputCP(1251);
|
SetConsoleCP(1251);
|
||||||
|
SetConsoleOutputCP(1251);
|
||||||
if (!Daemon_Singleton::init(argc, argv))
|
setlocale(LC_ALL, "Russian");
|
||||||
return false;
|
|
||||||
|
if (!Daemon_Singleton::init(argc, argv))
|
||||||
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
|
return false;
|
||||||
if (serviceControl == "install")
|
|
||||||
{
|
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
|
||||||
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
|
if (serviceControl == "install")
|
||||||
InstallService(
|
{
|
||||||
SERVICE_NAME, // Name of service
|
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
|
||||||
SERVICE_DISPLAY_NAME, // Name to display
|
InstallService(
|
||||||
SERVICE_START_TYPE, // Service start type
|
SERVICE_NAME, // Name of service
|
||||||
SERVICE_DEPENDENCIES, // Dependencies
|
SERVICE_DISPLAY_NAME, // Name to display
|
||||||
SERVICE_ACCOUNT, // Service running account
|
SERVICE_START_TYPE, // Service start type
|
||||||
SERVICE_PASSWORD // Password of the account
|
SERVICE_DEPENDENCIES, // Dependencies
|
||||||
);
|
SERVICE_ACCOUNT, // Service running account
|
||||||
return false;
|
SERVICE_PASSWORD // Password of the account
|
||||||
}
|
);
|
||||||
else if (serviceControl == "remove")
|
return false;
|
||||||
{
|
}
|
||||||
LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
|
else if (serviceControl == "remove")
|
||||||
UninstallService(SERVICE_NAME);
|
{
|
||||||
return false;
|
LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
|
||||||
}
|
UninstallService(SERVICE_NAME);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (isDaemon)
|
if (isDaemon)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "Daemon: running as service");
|
LogPrint(eLogDebug, "Daemon: running as service");
|
||||||
I2PService service(SERVICE_NAME);
|
I2PService service(SERVICE_NAME);
|
||||||
if (!I2PService::Run(service))
|
if (!I2PService::Run(service))
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
|
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogDebug, "Daemon: running as user");
|
LogPrint(eLogDebug, "Daemon: running as user");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DaemonWin32::start()
|
bool DaemonWin32::start()
|
||||||
{
|
{
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
SetConsoleCP(1251);
|
SetConsoleCP(1251);
|
||||||
SetConsoleOutputCP(1251);
|
SetConsoleOutputCP(1251);
|
||||||
setlocale(LC_ALL, "Russian");
|
setlocale(LC_ALL, "Russian");
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
if (!i2p::win32::StartWin32App ()) return false;
|
if (!i2p::win32::StartWin32App ()) return false;
|
||||||
|
|
||||||
// override log
|
// override log
|
||||||
i2p::config::SetOption("log", std::string ("file"));
|
i2p::config::SetOption("log", std::string ("file"));
|
||||||
#endif
|
#endif
|
||||||
bool ret = Daemon_Singleton::start();
|
bool ret = Daemon_Singleton::start();
|
||||||
if (ret && i2p::log::Logger().GetLogType() == eLogFile)
|
if (ret && i2p::log::Logger().GetLogType() == eLogFile)
|
||||||
{
|
{
|
||||||
// TODO: find out where this garbage to console comes from
|
// TODO: find out where this garbage to console comes from
|
||||||
SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
|
SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
|
||||||
SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
|
SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
|
||||||
}
|
}
|
||||||
bool insomnia; i2p::config::GetOption("insomnia", insomnia);
|
bool insomnia; i2p::config::GetOption("insomnia", insomnia);
|
||||||
if (insomnia)
|
if (insomnia)
|
||||||
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
|
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DaemonWin32::stop()
|
bool DaemonWin32::stop()
|
||||||
{
|
{
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
i2p::win32::StopWin32App ();
|
i2p::win32::StopWin32App ();
|
||||||
#endif
|
#endif
|
||||||
return Daemon_Singleton::stop();
|
return Daemon_Singleton::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonWin32::run ()
|
void DaemonWin32::run ()
|
||||||
{
|
{
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
i2p::win32::RunWin32App ();
|
i2p::win32::RunWin32App ();
|
||||||
#else
|
#else
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
std::this_thread::sleep_for (std::chrono::seconds(1));
|
std::this_thread::sleep_for (std::chrono::seconds(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,7 +31,7 @@ namespace client
|
|||||||
{
|
{
|
||||||
|
|
||||||
int len = i2p::util::lexical_cast<int>(it->second, inboundTunnelLen);
|
int len = i2p::util::lexical_cast<int>(it->second, inboundTunnelLen);
|
||||||
if (len > 0)
|
if (len >= 0)
|
||||||
{
|
{
|
||||||
inboundTunnelLen = len;
|
inboundTunnelLen = len;
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ namespace client
|
|||||||
{
|
{
|
||||||
|
|
||||||
int len = i2p::util::lexical_cast<int>(it->second, outboundTunnelLen);
|
int len = i2p::util::lexical_cast<int>(it->second, outboundTunnelLen);
|
||||||
if (len > 0)
|
if (len >= 0)
|
||||||
{
|
{
|
||||||
outboundTunnelLen = len;
|
outboundTunnelLen = len;
|
||||||
}
|
}
|
||||||
|
37
Garlic.cpp
37
Garlic.cpp
@ -7,6 +7,7 @@
|
|||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
|
#include "Transports.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
@ -514,22 +515,34 @@ namespace garlic
|
|||||||
buf += 32;
|
buf += 32;
|
||||||
uint32_t gwTunnel = bufbe32toh (buf);
|
uint32_t gwTunnel = bufbe32toh (buf);
|
||||||
buf += 4;
|
buf += 4;
|
||||||
std::shared_ptr<i2p::tunnel::OutboundTunnel> tunnel;
|
auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from);
|
||||||
if (from && from->GetTunnelPool ())
|
if (from) // received through an inbound tunnel
|
||||||
tunnel = from->GetTunnelPool ()->GetNextOutboundTunnel ();
|
{
|
||||||
if (tunnel) // we have send it through an outbound tunnel
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> tunnel;
|
||||||
{
|
if (from->GetTunnelPool ())
|
||||||
auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from);
|
tunnel = from->GetTunnelPool ()->GetNextOutboundTunnel ();
|
||||||
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
|
else
|
||||||
}
|
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
|
||||||
else
|
if (tunnel) // we have send it through an outbound tunnel
|
||||||
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
|
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
|
||||||
|
}
|
||||||
|
else // received directly
|
||||||
|
i2p::transport::transports.SendMessage (gwHash, i2p::CreateTunnelGatewayMsg (gwTunnel, msg)); // send directly
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eGarlicDeliveryTypeRouter:
|
case eGarlicDeliveryTypeRouter:
|
||||||
LogPrint (eLogWarning, "Garlic: type router not supported");
|
{
|
||||||
|
uint8_t * ident = buf;
|
||||||
buf += 32;
|
buf += 32;
|
||||||
break;
|
if (!from) // received directly
|
||||||
|
i2p::transport::transports.SendMessage (ident,
|
||||||
|
CreateI2NPMessage (buf, GetI2NPMessageLength (buf)));
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported");
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
|
LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
|
||||||
}
|
}
|
||||||
|
108
Gzip.cpp
Normal file
108
Gzip.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* 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 <inttypes.h>
|
||||||
|
#include <string.h> /* memset */
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Gzip.h"
|
||||||
|
|
||||||
|
namespace i2p {
|
||||||
|
namespace data {
|
||||||
|
const size_t GZIP_CHUNK_SIZE = 16384;
|
||||||
|
|
||||||
|
GzipInflator::GzipInflator (): m_IsDirty (false)
|
||||||
|
{
|
||||||
|
memset (&m_Inflator, 0, sizeof (m_Inflator));
|
||||||
|
inflateInit2 (&m_Inflator, MAX_WBITS + 16); // gzip
|
||||||
|
}
|
||||||
|
|
||||||
|
GzipInflator::~GzipInflator ()
|
||||||
|
{
|
||||||
|
inflateEnd (&m_Inflator);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GzipInflator::Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
if (m_IsDirty) inflateReset (&m_Inflator);
|
||||||
|
m_IsDirty = true;
|
||||||
|
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
||||||
|
m_Inflator.avail_in = inLen;
|
||||||
|
m_Inflator.next_out = out;
|
||||||
|
m_Inflator.avail_out = outLen;
|
||||||
|
int err;
|
||||||
|
if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) {
|
||||||
|
return outLen - m_Inflator.avail_out;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os)
|
||||||
|
{
|
||||||
|
m_IsDirty = true;
|
||||||
|
uint8_t * out = new uint8_t[GZIP_CHUNK_SIZE];
|
||||||
|
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
||||||
|
m_Inflator.avail_in = inLen;
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
m_Inflator.next_out = out;
|
||||||
|
m_Inflator.avail_out = GZIP_CHUNK_SIZE;
|
||||||
|
ret = inflate (&m_Inflator, Z_NO_FLUSH);
|
||||||
|
if (ret < 0) {
|
||||||
|
inflateEnd (&m_Inflator);
|
||||||
|
os.setstate(std::ios_base::failbit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
os.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out);
|
||||||
|
} while (!m_Inflator.avail_out); // more data to read
|
||||||
|
delete[] out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GzipInflator::Inflate (std::istream& in, std::ostream& out)
|
||||||
|
{
|
||||||
|
uint8_t * buf = new uint8_t[GZIP_CHUNK_SIZE];
|
||||||
|
while (!in.eof ())
|
||||||
|
{
|
||||||
|
in.read ((char *) buf, GZIP_CHUNK_SIZE);
|
||||||
|
Inflate (buf, in.gcount (), out);
|
||||||
|
}
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
GzipDeflator::GzipDeflator (): m_IsDirty (false)
|
||||||
|
{
|
||||||
|
memset (&m_Deflator, 0, sizeof (m_Deflator));
|
||||||
|
deflateInit2 (&m_Deflator, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); // 15 + 16 sets gzip
|
||||||
|
}
|
||||||
|
|
||||||
|
GzipDeflator::~GzipDeflator ()
|
||||||
|
{
|
||||||
|
deflateEnd (&m_Deflator);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GzipDeflator::SetCompressionLevel (int level)
|
||||||
|
{
|
||||||
|
deflateParams (&m_Deflator, level, Z_DEFAULT_STRATEGY);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GzipDeflator::Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
if (m_IsDirty) deflateReset (&m_Deflator);
|
||||||
|
m_IsDirty = true;
|
||||||
|
m_Deflator.next_in = const_cast<uint8_t *>(in);
|
||||||
|
m_Deflator.avail_in = inLen;
|
||||||
|
m_Deflator.next_out = out;
|
||||||
|
m_Deflator.avail_out = outLen;
|
||||||
|
int err;
|
||||||
|
if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) {
|
||||||
|
return outLen - m_Deflator.avail_out;
|
||||||
|
} /* else */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // data
|
||||||
|
} // i2p
|
44
Gzip.h
Normal file
44
Gzip.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef GZIP_H__
|
||||||
|
#define GZIP_H__
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
namespace i2p {
|
||||||
|
namespace data {
|
||||||
|
class GzipInflator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
GzipInflator ();
|
||||||
|
~GzipInflator ();
|
||||||
|
|
||||||
|
size_t Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
||||||
|
/** @note @a os failbit will be set in case of error */
|
||||||
|
void Inflate (const uint8_t * in, size_t inLen, std::ostream& os);
|
||||||
|
void Inflate (std::istream& in, std::ostream& out);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
z_stream m_Inflator;
|
||||||
|
bool m_IsDirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GzipDeflator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
GzipDeflator ();
|
||||||
|
~GzipDeflator ();
|
||||||
|
|
||||||
|
void SetCompressionLevel (int level);
|
||||||
|
size_t Deflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
z_stream m_Deflator;
|
||||||
|
bool m_IsDirty;
|
||||||
|
};
|
||||||
|
} // data
|
||||||
|
} // i2p
|
||||||
|
|
||||||
|
#endif /* GZIP_H__ */
|
7
HTTP.cpp
7
HTTP.cpp
@ -81,7 +81,8 @@ namespace http {
|
|||||||
}
|
}
|
||||||
/* user[:pass] */
|
/* user[:pass] */
|
||||||
pos_c = url.find('@', pos_p);
|
pos_c = url.find('@', pos_p);
|
||||||
if (pos_c != std::string::npos) {
|
std::size_t pos_slash = url.find('/', pos_p);
|
||||||
|
if (pos_c != std::string::npos && (pos_slash == std::string::npos || pos_slash > pos_c)) {
|
||||||
std::size_t delim = url.find(':', pos_p);
|
std::size_t delim = url.find(':', pos_p);
|
||||||
if (delim != std::string::npos && delim < pos_c) {
|
if (delim != std::string::npos && delim < pos_c) {
|
||||||
user = url.substr(pos_p, delim - pos_p);
|
user = url.substr(pos_p, delim - pos_p);
|
||||||
@ -90,7 +91,7 @@ namespace http {
|
|||||||
} else {
|
} else {
|
||||||
user = url.substr(pos_p, pos_c - pos_p);
|
user = url.substr(pos_p, pos_c - pos_p);
|
||||||
}
|
}
|
||||||
pos_p = pos_c + 1;
|
pos_p = pos_c + 1;
|
||||||
}
|
}
|
||||||
/* hostname[:port][/path] */
|
/* hostname[:port][/path] */
|
||||||
pos_c = url.find_first_of(":/", pos_p);
|
pos_c = url.find_first_of(":/", pos_p);
|
||||||
@ -276,7 +277,7 @@ namespace http {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int HTTPMsg::length() {
|
long int HTTPMsg::content_length() {
|
||||||
unsigned long int length = 0;
|
unsigned long int length = 0;
|
||||||
auto it = headers.find("Content-Length");
|
auto it = headers.find("Content-Length");
|
||||||
if (it == headers.end())
|
if (it == headers.end())
|
||||||
|
2
HTTP.h
2
HTTP.h
@ -62,7 +62,7 @@ namespace http {
|
|||||||
void del_header(const char *name);
|
void del_header(const char *name);
|
||||||
|
|
||||||
/** @brief Returns declared message length or -1 if unknown */
|
/** @brief Returns declared message length or -1 if unknown */
|
||||||
long int length();
|
long int content_length();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HTTPReq : HTTPMsg {
|
struct HTTPReq : HTTPMsg {
|
||||||
|
159
HTTPProxy.cpp
159
HTTPProxy.cpp
@ -3,6 +3,13 @@
|
|||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "I2PService.h"
|
||||||
|
#include "Destination.h"
|
||||||
#include "HTTPProxy.h"
|
#include "HTTPProxy.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
@ -14,12 +21,19 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "HTTP.h"
|
#include "HTTP.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p {
|
||||||
{
|
namespace proxy {
|
||||||
namespace proxy
|
bool str_rmatch(std::string & str, const char *suffix) {
|
||||||
{
|
auto pos = str.rfind (suffix);
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
return false; /* not found */
|
||||||
|
if (str.length() == (pos + std::strlen(suffix)))
|
||||||
|
return true; /* match */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static const size_t http_buffer_size = 8192;
|
static const size_t http_buffer_size = 8192;
|
||||||
class HTTPProxyHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this<HTTPProxyHandler>
|
class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this<HTTPReqHandler>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
enum state
|
enum state
|
||||||
@ -36,10 +50,9 @@ namespace proxy
|
|||||||
void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
|
void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
|
||||||
void Terminate();
|
void Terminate();
|
||||||
void AsyncSockRead();
|
void AsyncSockRead();
|
||||||
void HTTPRequestFailed(/*std::string message*/);
|
void HTTPRequestFailed(const char *message);
|
||||||
void RedirectToJumpService();
|
void RedirectToJumpService(std::string & host);
|
||||||
void ExtractRequest();
|
void ExtractRequest();
|
||||||
bool IsI2PAddress();
|
|
||||||
bool ValidateHTTPRequest();
|
bool ValidateHTTPRequest();
|
||||||
void HandleJumpServices();
|
void HandleJumpServices();
|
||||||
bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len);
|
bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len);
|
||||||
@ -59,26 +72,26 @@ namespace proxy
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HTTPProxyHandler(HTTPProxyServer * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) :
|
HTTPReqHandler(HTTPProxy * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) :
|
||||||
I2PServiceHandler(parent), m_sock(sock)
|
I2PServiceHandler(parent), m_sock(sock)
|
||||||
{ EnterState(GET_METHOD); }
|
{ EnterState(GET_METHOD); }
|
||||||
~HTTPProxyHandler() { Terminate(); }
|
~HTTPReqHandler() { Terminate(); }
|
||||||
void Handle () { AsyncSockRead(); }
|
void Handle () { AsyncSockRead(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void HTTPProxyHandler::AsyncSockRead()
|
void HTTPReqHandler::AsyncSockRead()
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "HTTPProxy: async sock read");
|
LogPrint(eLogDebug, "HTTPProxy: async sock read");
|
||||||
if(m_sock) {
|
if (!m_sock) {
|
||||||
m_sock->async_receive(boost::asio::buffer(m_http_buff, http_buffer_size),
|
|
||||||
std::bind(&HTTPProxyHandler::HandleSockRecv, shared_from_this(),
|
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
|
||||||
} else {
|
|
||||||
LogPrint(eLogError, "HTTPProxy: no socket for read");
|
LogPrint(eLogError, "HTTPProxy: no socket for read");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
m_sock->async_receive(boost::asio::buffer(m_http_buff, http_buffer_size),
|
||||||
|
std::bind(&HTTPReqHandler::HandleSockRecv, shared_from_this(),
|
||||||
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::Terminate() {
|
void HTTPReqHandler::Terminate() {
|
||||||
if (Kill()) return;
|
if (Kill()) return;
|
||||||
if (m_sock)
|
if (m_sock)
|
||||||
{
|
{
|
||||||
@ -91,30 +104,45 @@ namespace proxy
|
|||||||
|
|
||||||
/* All hope is lost beyond this point */
|
/* All hope is lost beyond this point */
|
||||||
//TODO: handle this apropriately
|
//TODO: handle this apropriately
|
||||||
void HTTPProxyHandler::HTTPRequestFailed(/*HTTPProxyHandler::errTypes error*/)
|
void HTTPReqHandler::HTTPRequestFailed(const char *message)
|
||||||
{
|
{
|
||||||
static std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n\r\n";
|
i2p::http::HTTPRes res;
|
||||||
boost::asio::async_write(*m_sock, boost::asio::buffer(response,response.size()),
|
res.code = 500;
|
||||||
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
res.add_header("Content-Type", "text/plain");
|
||||||
|
res.add_header("Connection", "close");
|
||||||
|
res.body = message;
|
||||||
|
res.body += "\r\n";
|
||||||
|
std::string response = res.to_string();
|
||||||
|
boost::asio::async_write(*m_sock, boost::asio::buffer(response),
|
||||||
|
std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::RedirectToJumpService(/*HTTPProxyHandler::errTypes error*/)
|
void HTTPReqHandler::RedirectToJumpService(std::string & host)
|
||||||
{
|
{
|
||||||
std::stringstream response;
|
i2p::http::HTTPRes res;
|
||||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
i2p::http::URL url;
|
||||||
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";
|
/* TODO: don't redirect to webconsole, it's not always work, handle jumpservices here */
|
||||||
boost::asio::async_write(*m_sock, boost::asio::buffer(response.str (),response.str ().length ()),
|
i2p::config::GetOption("http.address", url.host);
|
||||||
std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
i2p::config::GetOption("http.port", url.port);
|
||||||
|
url.path = "/";
|
||||||
|
url.query = "page=jumpservices&address=";
|
||||||
|
url.query += host;
|
||||||
|
|
||||||
|
res.code = 302; /* redirect */
|
||||||
|
res.add_header("Location", url.to_string().c_str());
|
||||||
|
|
||||||
|
std::string response = res.to_string();
|
||||||
|
boost::asio::async_write(*m_sock, boost::asio::buffer(response),
|
||||||
|
std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::EnterState(HTTPProxyHandler::state nstate)
|
void HTTPReqHandler::EnterState(HTTPReqHandler::state nstate)
|
||||||
{
|
{
|
||||||
m_state = nstate;
|
m_state = nstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::ExtractRequest()
|
void HTTPReqHandler::ExtractRequest()
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url);
|
LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url);
|
||||||
i2p::http::URL url;
|
i2p::http::URL url;
|
||||||
@ -127,18 +155,18 @@ namespace proxy
|
|||||||
LogPrint(eLogDebug, "HTTPProxy: server: ", m_address, ", port: ", m_port, ", path: ", m_path);
|
LogPrint(eLogDebug, "HTTPProxy: server: ", m_address, ", port: ", m_port, ", path: ", m_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTPProxyHandler::ValidateHTTPRequest()
|
bool HTTPReqHandler::ValidateHTTPRequest()
|
||||||
{
|
{
|
||||||
if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" )
|
if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" )
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "HTTPProxy: unsupported version: ", m_version);
|
LogPrint(eLogError, "HTTPProxy: unsupported version: ", m_version);
|
||||||
HTTPRequestFailed(); //TODO: send right stuff
|
HTTPRequestFailed("unsupported HTTP version");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::HandleJumpServices()
|
void HTTPReqHandler::HandleJumpServices()
|
||||||
{
|
{
|
||||||
static const char * helpermark1 = "?i2paddresshelper=";
|
static const char * helpermark1 = "?i2paddresshelper=";
|
||||||
static const char * helpermark2 = "&i2paddresshelper=";
|
static const char * helpermark2 = "&i2paddresshelper=";
|
||||||
@ -170,31 +198,20 @@ namespace proxy
|
|||||||
m_path.erase(addressHelperPos);
|
m_path.erase(addressHelperPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTPProxyHandler::IsI2PAddress()
|
bool HTTPReqHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len)
|
||||||
{
|
|
||||||
auto pos = m_address.rfind (".i2p");
|
|
||||||
if (pos != std::string::npos && (pos+4) == m_address.length ())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPProxyHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len)
|
|
||||||
{
|
{
|
||||||
ExtractRequest(); //TODO: parse earlier
|
ExtractRequest(); //TODO: parse earlier
|
||||||
if (!ValidateHTTPRequest()) return false;
|
if (!ValidateHTTPRequest()) return false;
|
||||||
HandleJumpServices();
|
HandleJumpServices();
|
||||||
|
|
||||||
i2p::data::IdentHash identHash;
|
i2p::data::IdentHash identHash;
|
||||||
if (IsI2PAddress ())
|
if (str_rmatch(m_address, ".i2p"))
|
||||||
{
|
{
|
||||||
if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){
|
if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){
|
||||||
RedirectToJumpService();
|
RedirectToJumpService(m_address);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_request = m_method;
|
m_request = m_method;
|
||||||
m_request.push_back(' ');
|
m_request.push_back(' ');
|
||||||
@ -235,7 +252,7 @@ namespace proxy
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTPProxyHandler::HandleData(uint8_t *http_buff, std::size_t len)
|
bool HTTPReqHandler::HandleData(uint8_t *http_buff, std::size_t len)
|
||||||
{
|
{
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
{
|
{
|
||||||
@ -269,13 +286,13 @@ namespace proxy
|
|||||||
case '\n': EnterState(DONE); break;
|
case '\n': EnterState(DONE); break;
|
||||||
default:
|
default:
|
||||||
LogPrint(eLogError, "HTTPProxy: rejected invalid request ending with: ", ((int)*http_buff));
|
LogPrint(eLogError, "HTTPProxy: rejected invalid request ending with: ", ((int)*http_buff));
|
||||||
HTTPRequestFailed(); //TODO: add correct code
|
HTTPRequestFailed("rejected invalid request");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint(eLogError, "HTTPProxy: invalid state: ", m_state);
|
LogPrint(eLogError, "HTTPProxy: invalid state: ", m_state);
|
||||||
HTTPRequestFailed(); //TODO: add correct code 500
|
HTTPRequestFailed("invalid parser state");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
http_buff++;
|
http_buff++;
|
||||||
@ -286,7 +303,7 @@ namespace proxy
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len)
|
void HTTPReqHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "HTTPProxy: sock recv: ", len, " bytes");
|
LogPrint(eLogDebug, "HTTPProxy: sock recv: ", len, " bytes");
|
||||||
if(ecode)
|
if(ecode)
|
||||||
@ -301,49 +318,45 @@ namespace proxy
|
|||||||
if (m_state == DONE)
|
if (m_state == DONE)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "HTTPProxy: requested: ", m_url);
|
LogPrint(eLogDebug, "HTTPProxy: requested: ", m_url);
|
||||||
GetOwner()->CreateStream (std::bind (&HTTPProxyHandler::HandleStreamRequestComplete,
|
GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete,
|
||||||
shared_from_this(), std::placeholders::_1), m_address, m_port);
|
shared_from_this(), std::placeholders::_1), m_address, m_port);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AsyncSockRead();
|
AsyncSockRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::SentHTTPFailed(const boost::system::error_code & ecode)
|
void HTTPReqHandler::SentHTTPFailed(const boost::system::error_code & ecode)
|
||||||
{
|
{
|
||||||
if (ecode)
|
if (ecode)
|
||||||
LogPrint (eLogError, "HTTPProxy: Closing socket after sending failure because: ", ecode.message ());
|
LogPrint (eLogError, "HTTPProxy: Closing socket after sending failure because: ", ecode.message ());
|
||||||
Terminate();
|
Terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPProxyHandler::HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream)
|
void HTTPReqHandler::HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream)
|
||||||
{
|
{
|
||||||
if (stream)
|
if (!stream) {
|
||||||
{
|
|
||||||
if (Kill()) return;
|
|
||||||
LogPrint (eLogInfo, "HTTPProxy: New I2PTunnel connection");
|
|
||||||
auto connection = std::make_shared<i2p::client::I2PTunnelConnection>(GetOwner(), m_sock, stream);
|
|
||||||
GetOwner()->AddHandler (connection);
|
|
||||||
connection->I2PConnect (reinterpret_cast<const uint8_t*>(m_request.data()), m_request.size());
|
|
||||||
Done(shared_from_this());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info");
|
LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info");
|
||||||
HTTPRequestFailed(); // TODO: Send correct error message host unreachable
|
HTTPRequestFailed("error when creating the stream, check logs");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (Kill())
|
||||||
|
return;
|
||||||
|
LogPrint (eLogDebug, "HTTPProxy: New I2PTunnel connection");
|
||||||
|
auto connection = std::make_shared<i2p::client::I2PTunnelConnection>(GetOwner(), m_sock, stream);
|
||||||
|
GetOwner()->AddHandler (connection);
|
||||||
|
connection->I2PConnect (reinterpret_cast<const uint8_t*>(m_request.data()), m_request.size());
|
||||||
|
Done (shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPProxyServer::HTTPProxyServer(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination):
|
HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination):
|
||||||
TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ())
|
TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<i2p::client::I2PServiceHandler> HTTPProxyServer::CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
|
std::shared_ptr<i2p::client::I2PServiceHandler> HTTPProxy::CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
|
||||||
{
|
{
|
||||||
return std::make_shared<HTTPProxyHandler> (this, socket);
|
return std::make_shared<HTTPReqHandler> (this, socket);
|
||||||
}
|
}
|
||||||
|
} // http
|
||||||
}
|
} // i2p
|
||||||
}
|
|
||||||
|
25
HTTPProxy.h
25
HTTPProxy.h
@ -1,32 +1,21 @@
|
|||||||
#ifndef HTTP_PROXY_H__
|
#ifndef HTTP_PROXY_H__
|
||||||
#define HTTP_PROXY_H__
|
#define HTTP_PROXY_H__
|
||||||
|
|
||||||
#include <memory>
|
namespace i2p {
|
||||||
#include <set>
|
namespace proxy {
|
||||||
#include <boost/asio.hpp>
|
class HTTPProxy: public i2p::client::TCPIPAcceptor
|
||||||
#include <mutex>
|
|
||||||
#include "I2PService.h"
|
|
||||||
#include "Destination.h"
|
|
||||||
|
|
||||||
namespace i2p
|
|
||||||
{
|
|
||||||
namespace proxy
|
|
||||||
{
|
|
||||||
class HTTPProxyServer: public i2p::client::TCPIPAcceptor
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HTTPProxyServer(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr);
|
HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr);
|
||||||
~HTTPProxyServer() {};
|
~HTTPProxy() {};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Implements TCPIPAcceptor
|
// Implements TCPIPAcceptor
|
||||||
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||||
const char* GetName() { return "HTTP Proxy"; }
|
const char* GetName() { return "HTTP Proxy"; }
|
||||||
};
|
};
|
||||||
|
} // http
|
||||||
typedef HTTPProxyServer HTTPProxy;
|
} // i2p
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,6 +58,9 @@ namespace http {
|
|||||||
" .tunnel.another { color: #434343; }\r\n"
|
" .tunnel.another { color: #434343; }\r\n"
|
||||||
" caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n"
|
" caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n"
|
||||||
" table { width: 100%; border-collapse: collapse; text-align: center; }\r\n"
|
" table { width: 100%; border-collapse: collapse; text-align: center; }\r\n"
|
||||||
|
" .private { background: black; color: black; } .private:hover { background: black; color: white } \r\n"
|
||||||
|
" .slide p, .slide [type='checkbox']{ display:none; } \r\n"
|
||||||
|
" .slide [type='checkbox']:checked ~ p { display:block; } \r\n"
|
||||||
"</style>\r\n";
|
"</style>\r\n";
|
||||||
|
|
||||||
const char HTTP_PAGE_TUNNELS[] = "tunnels";
|
const char HTTP_PAGE_TUNNELS[] = "tunnels";
|
||||||
@ -126,8 +129,12 @@ namespace http {
|
|||||||
s <<
|
s <<
|
||||||
"<!DOCTYPE html>\r\n"
|
"<!DOCTYPE html>\r\n"
|
||||||
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
|
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
|
||||||
" <head>\r\n"
|
" <head>\r\n" /* TODO: Find something to parse html/template system. This is horrible. */
|
||||||
" <meta charset=\"UTF-8\">\r\n" /* TODO: Find something to parse html/template system. This is horrible. */
|
#if (!defined(WIN32))
|
||||||
|
" <meta charset=\"UTF-8\">\r\n"
|
||||||
|
#else
|
||||||
|
" <meta charset=\"windows-1251\">\r\n"
|
||||||
|
#endif
|
||||||
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
||||||
" <title>Purple I2P " VERSION " Webconsole</title>\r\n"
|
" <title>Purple I2P " VERSION " Webconsole</title>\r\n"
|
||||||
<< cssStyles <<
|
<< cssStyles <<
|
||||||
@ -201,6 +208,10 @@ namespace http {
|
|||||||
s << numKBytesSent / 1024 / 1024 << " GiB";
|
s << numKBytesSent / 1024 / 1024 << " GiB";
|
||||||
s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " KiB/s)<br>\r\n";
|
s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " KiB/s)<br>\r\n";
|
||||||
s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n<br>\r\n";
|
s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n<br>\r\n";
|
||||||
|
s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n";
|
||||||
|
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
||||||
|
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
||||||
|
s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
|
||||||
s << "<b>Our external address:</b>" << "<br>\r\n" ;
|
s << "<b>Our external address:</b>" << "<br>\r\n" ;
|
||||||
for (auto address : i2p::context.GetRouterInfo().GetAddresses())
|
for (auto address : i2p::context.GetRouterInfo().GetAddresses())
|
||||||
{
|
{
|
||||||
@ -223,6 +234,7 @@ namespace http {
|
|||||||
}
|
}
|
||||||
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
|
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
|
||||||
}
|
}
|
||||||
|
s << "</p>\r\n</div>\r\n";
|
||||||
s << "<br>\r\n<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
s << "<br>\r\n<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
||||||
s << "<b>Floodfills:</b> " << i2p::data::netdb.GetNumFloodfills () << " ";
|
s << "<b>Floodfills:</b> " << i2p::data::netdb.GetNumFloodfills () << " ";
|
||||||
s << "<b>LeaseSets:</b> " << i2p::data::netdb.GetNumLeaseSets () << "<br>\r\n";
|
s << "<b>LeaseSets:</b> " << i2p::data::netdb.GetNumLeaseSets () << "<br>\r\n";
|
||||||
@ -612,7 +624,7 @@ namespace http {
|
|||||||
HandleCommand (req, res, s);
|
HandleCommand (req, res, s);
|
||||||
} else {
|
} else {
|
||||||
ShowStatus (s);
|
ShowStatus (s);
|
||||||
//res.add_header("Refresh", "5");
|
res.add_header("Refresh", "10");
|
||||||
}
|
}
|
||||||
ShowPageTail (s);
|
ShowPageTail (s);
|
||||||
|
|
||||||
|
14
I2CP.cpp
14
I2CP.cpp
@ -114,7 +114,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr<proto::socket> socket):
|
||||||
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
m_Owner (owner), m_Socket (socket), m_Payload (nullptr),
|
||||||
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
|
m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true)
|
||||||
{
|
{
|
||||||
@ -583,7 +583,12 @@ namespace client
|
|||||||
|
|
||||||
I2CPServer::I2CPServer (const std::string& interface, int port):
|
I2CPServer::I2CPServer (const std::string& interface, int port):
|
||||||
m_IsRunning (false), m_Thread (nullptr),
|
m_IsRunning (false), m_Thread (nullptr),
|
||||||
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port))
|
m_Acceptor (m_Service,
|
||||||
|
#ifdef ANDROID
|
||||||
|
I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address
|
||||||
|
#else
|
||||||
|
I2CPSession::proto::endpoint(boost::asio::ip::address::from_string(interface), port))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers));
|
memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers));
|
||||||
m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler;
|
m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler;
|
||||||
@ -644,12 +649,13 @@ namespace client
|
|||||||
|
|
||||||
void I2CPServer::Accept ()
|
void I2CPServer::Accept ()
|
||||||
{
|
{
|
||||||
auto newSocket = std::make_shared<boost::asio::ip::tcp::socket> (m_Service);
|
auto newSocket = std::make_shared<I2CPSession::proto::socket> (m_Service);
|
||||||
m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this,
|
m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this,
|
||||||
std::placeholders::_1, newSocket));
|
std::placeholders::_1, newSocket));
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPServer::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket)
|
void I2CPServer::HandleAccept(const boost::system::error_code& ecode,
|
||||||
|
std::shared_ptr<I2CPSession::proto::socket> socket)
|
||||||
{
|
{
|
||||||
if (!ecode && socket)
|
if (!ecode && socket)
|
||||||
{
|
{
|
||||||
|
16
I2CP.h
16
I2CP.h
@ -99,7 +99,14 @@ namespace client
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2CPSession (I2CPServer& owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
#ifdef ANDROID
|
||||||
|
typedef boost::asio::local::stream_protocol proto;
|
||||||
|
#else
|
||||||
|
typedef boost::asio::ip::tcp proto;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
I2CPSession (I2CPServer& owner, std::shared_ptr<proto::socket> socket);
|
||||||
|
|
||||||
~I2CPSession ();
|
~I2CPSession ();
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
@ -144,7 +151,7 @@ namespace client
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
I2CPServer& m_Owner;
|
I2CPServer& m_Owner;
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
std::shared_ptr<proto::socket> m_Socket;
|
||||||
uint8_t m_Header[I2CP_HEADER_SIZE], * m_Payload;
|
uint8_t m_Header[I2CP_HEADER_SIZE], * m_Payload;
|
||||||
size_t m_PayloadLen;
|
size_t m_PayloadLen;
|
||||||
|
|
||||||
@ -173,7 +180,8 @@ namespace client
|
|||||||
void Run ();
|
void Run ();
|
||||||
|
|
||||||
void Accept ();
|
void Accept ();
|
||||||
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
|
||||||
|
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<I2CPSession::proto::socket> socket);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -183,7 +191,7 @@ namespace client
|
|||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::ip::tcp::acceptor m_Acceptor;
|
I2CPSession::proto::acceptor m_Acceptor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
/* append to json chunk of data from 1st request */
|
/* append to json chunk of data from 1st request */
|
||||||
json.write(buf->begin() + len, bytes_transferred - len);
|
json.write(buf->begin() + len, bytes_transferred - len);
|
||||||
remains = req.length() - len;
|
remains = req.content_length() - len;
|
||||||
/* if request has Content-Length header, fetch rest of data and store to json buffer */
|
/* if request has Content-Length header, fetch rest of data and store to json buffer */
|
||||||
while (remains > 0) {
|
while (remains > 0) {
|
||||||
len = ((long int) buf->size() < remains) ? buf->size() : remains;
|
len = ((long int) buf->size() < remains) ? buf->size() : remains;
|
||||||
|
1
Makefile
1
Makefile
@ -11,6 +11,7 @@ include filelist.mk
|
|||||||
|
|
||||||
USE_AESNI := yes
|
USE_AESNI := yes
|
||||||
USE_STATIC := no
|
USE_STATIC := no
|
||||||
|
USE_UPNP := no
|
||||||
|
|
||||||
ifeq ($(UNAME),Darwin)
|
ifeq ($(UNAME),Darwin)
|
||||||
DAEMON_SRC += DaemonLinux.cpp
|
DAEMON_SRC += DaemonLinux.cpp
|
||||||
|
@ -8,7 +8,7 @@ INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
|
|||||||
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
|
||||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
|
|
||||||
ifeq ($(USE_UPNP),1)
|
ifeq ($(USE_UPNP),yes)
|
||||||
LDFLAGS += -ldl
|
LDFLAGS += -ldl
|
||||||
CXXFLAGS += -DUSE_UPNP
|
CXXFLAGS += -DUSE_UPNP
|
||||||
endif
|
endif
|
||||||
|
@ -33,18 +33,18 @@ ifeq ($(USE_STATIC),yes)
|
|||||||
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
LDLIBS += $(LIBDIR)/libboost_date_time.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
LDLIBS += $(LIBDIR)/libboost_filesystem.a
|
||||||
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
LDLIBS += $(LIBDIR)/libboost_program_options.a
|
||||||
LDLIBS += $(LIBDIR)/libcrypto.a
|
|
||||||
LDLIBS += $(LIBDIR)/libssl.a
|
LDLIBS += $(LIBDIR)/libssl.a
|
||||||
|
LDLIBS += $(LIBDIR)/libcrypto.a
|
||||||
LDLIBS += $(LIBDIR)/libz.a
|
LDLIBS += $(LIBDIR)/libz.a
|
||||||
LDLIBS += -lpthread -static-libstdc++ -static-libgcc
|
LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt
|
||||||
USE_AESNI := no
|
USE_AESNI := no
|
||||||
else
|
else
|
||||||
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# UPNP Support (miniupnpc 1.5 or 1.6)
|
# UPNP Support (miniupnpc 1.5 or 1.6)
|
||||||
ifeq ($(USE_UPNP),1)
|
ifeq ($(USE_UPNP),yes)
|
||||||
LDFLAGS += -ldl
|
LDFLAGS += -lminiupnpc
|
||||||
CXXFLAGS += -DUSE_UPNP
|
CXXFLAGS += -DUSE_UPNP
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -1,47 +1,47 @@
|
|||||||
USE_WIN32_APP=yes
|
USE_WIN32_APP=yes
|
||||||
CXX = g++
|
CXX = g++
|
||||||
WINDRES = windres
|
WINDRES = windres
|
||||||
CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
|
||||||
NEEDED_CXXFLAGS = -std=c++11
|
NEEDED_CXXFLAGS = -std=c++11
|
||||||
BOOST_SUFFIX = -mt
|
BOOST_SUFFIX = -mt
|
||||||
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
INCFLAGS = -I/usr/include/ -I/usr/local/include/
|
||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib \
|
LDFLAGS = -Wl,-rpath,/usr/local/lib \
|
||||||
-L/usr/local/lib \
|
-L/usr/local/lib
|
||||||
-L/c/dev/openssl \
|
|
||||||
-L/c/dev/boost/lib
|
# UPNP Support
|
||||||
LDLIBS = \
|
ifeq ($(USE_UPNP),yes)
|
||||||
-Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \
|
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
|
||||||
-Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \
|
LDLIBS = -Wl,-Bstatic -lminiupnpc
|
||||||
-Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \
|
endif
|
||||||
-Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \
|
|
||||||
-Wl,-Bstatic -lssl \
|
LDLIBS += \
|
||||||
-Wl,-Bstatic -lcrypto \
|
-Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lz \
|
-Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lwsock32 \
|
-Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lws2_32 \
|
-Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \
|
||||||
-Wl,-Bstatic -lgdi32 \
|
-Wl,-Bstatic -lssl \
|
||||||
-Wl,-Bstatic -liphlpapi \
|
-Wl,-Bstatic -lcrypto \
|
||||||
-static-libgcc -static-libstdc++ \
|
-Wl,-Bstatic -lz \
|
||||||
-Wl,-Bstatic -lstdc++ \
|
-Wl,-Bstatic -lwsock32 \
|
||||||
-Wl,-Bstatic -lpthread
|
-Wl,-Bstatic -lws2_32 \
|
||||||
|
-Wl,-Bstatic -lgdi32 \
|
||||||
ifeq ($(USE_WIN32_APP), yes)
|
-Wl,-Bstatic -liphlpapi \
|
||||||
CXXFLAGS += -DWIN32_APP
|
-static-libgcc -static-libstdc++ \
|
||||||
LDFLAGS += -mwindows -s
|
-Wl,-Bstatic -lstdc++ \
|
||||||
DAEMON_RC += Win32/Resource.rc
|
-Wl,-Bstatic -lpthread
|
||||||
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
|
|
||||||
endif
|
ifeq ($(USE_WIN32_APP), yes)
|
||||||
|
CXXFLAGS += -DWIN32_APP
|
||||||
# UPNP Support
|
LDFLAGS += -mwindows -s
|
||||||
ifeq ($(USE_UPNP),1)
|
DAEMON_RC += Win32/Resource.rc
|
||||||
CXXFLAGS += -DUSE_UPNP
|
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_AESNI),1)
|
ifeq ($(USE_AESNI),yes)
|
||||||
CPU_FLAGS = -maes -DAESNI
|
CPU_FLAGS = -maes -DAESNI
|
||||||
else
|
else
|
||||||
CPU_FLAGS = -msse
|
CPU_FLAGS = -msse
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj/%.o : %.rc
|
obj/%.o : %.rc
|
||||||
$(WINDRES) -i $< -o $@
|
$(WINDRES) -i $< -o $@
|
||||||
|
@ -5,7 +5,7 @@ INCFLAGS = -I/usr/local/include -I/usr/local/ssl/include
|
|||||||
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib
|
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib
|
||||||
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
||||||
|
|
||||||
ifeq ($(USE_UPNP),1)
|
ifeq ($(USE_UPNP),yes)
|
||||||
LDFLAGS += -ldl
|
LDFLAGS += -ldl
|
||||||
CXXFLAGS += -DUSE_UPNP
|
CXXFLAGS += -DUSE_UPNP
|
||||||
endif
|
endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <zlib.h>
|
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
@ -430,7 +430,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "NTCP: Server session from ", m_Socket.remote_endpoint (), " connected");
|
LogPrint (eLogDebug, "NTCP: Server session from ", m_Socket.remote_endpoint (), " connected");
|
||||||
m_Server.AddNTCPSession (shared_from_this ());
|
m_Server.AddNTCPSession (shared_from_this ());
|
||||||
|
|
||||||
Connected ();
|
Connected ();
|
||||||
@ -942,7 +942,7 @@ namespace transport
|
|||||||
{
|
{
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTCP: Connect error: ", ecode.message ());
|
LogPrint (eLogError, "NTCP: Can't connect to ", conn->GetSocket ().remote_endpoint (), ": ", ecode.message ());
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
i2p::data::netdb.SetUnreachable (conn->GetRemoteIdentity ()->GetIdentHash (), true);
|
||||||
conn->Terminate ();
|
conn->Terminate ();
|
||||||
|
21
NetDb.cpp
21
NetDb.cpp
@ -2,7 +2,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <zlib.h>
|
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
@ -450,6 +450,12 @@ namespace data
|
|||||||
}
|
}
|
||||||
offset += 32;
|
offset += 32;
|
||||||
}
|
}
|
||||||
|
// we must send reply back before this check
|
||||||
|
if (ident == i2p::context.GetIdentHash ())
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NetDb: database store with own RouterInfo received, dropped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
size_t payloadOffset = offset;
|
size_t payloadOffset = offset;
|
||||||
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
@ -488,11 +494,16 @@ namespace data
|
|||||||
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
|
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
|
||||||
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||||
std::set<IdentHash> excluded;
|
std::set<IdentHash> excluded;
|
||||||
for (int i = 0; i < 3; i++)
|
excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself
|
||||||
|
excluded.insert (ident); // don't flood back
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
auto floodfill = GetClosestFloodfill (ident, excluded);
|
auto floodfill = GetClosestFloodfill (ident, excluded);
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), floodMsg);
|
{
|
||||||
|
transports.SendMessage (floodfill->GetIdentHash (), CopyI2NPMessage(floodMsg));
|
||||||
|
excluded.insert (floodfill->GetIdentHash ());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -610,7 +621,7 @@ namespace data
|
|||||||
uint32_t replyTunnelID = 0;
|
uint32_t replyTunnelID = 0;
|
||||||
if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel
|
if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel
|
||||||
{
|
{
|
||||||
replyTunnelID = bufbe32toh (buf + 64);
|
replyTunnelID = bufbe32toh (buf + 65);
|
||||||
excluded += 4;
|
excluded += 4;
|
||||||
}
|
}
|
||||||
uint16_t numExcluded = bufbe16toh (excluded);
|
uint16_t numExcluded = bufbe16toh (excluded);
|
||||||
@ -671,7 +682,7 @@ namespace data
|
|||||||
|
|
||||||
if (!replyMsg)
|
if (!replyMsg)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NetDb: Requested ", key, " not found. ", numExcluded, " excluded");
|
LogPrint (eLogWarning, "NetDb: Requested ", key, " not found, ", numExcluded, " peers excluded");
|
||||||
// find or cleate response
|
// find or cleate response
|
||||||
std::vector<IdentHash> closestFloodfills;
|
std::vector<IdentHash> closestFloodfills;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
2
NetDb.h
2
NetDb.h
@ -8,7 +8,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
|
#include "Gzip.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "Queue.h"
|
#include "Queue.h"
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
|
8
SSU.cpp
8
SSU.cpp
@ -231,7 +231,7 @@ namespace transport
|
|||||||
session = std::make_shared<SSUSession> (*this, packet->from);
|
session = std::make_shared<SSUSession> (*this, packet->from);
|
||||||
session->WaitForConnect ();
|
session->WaitForConnect ();
|
||||||
(*sessions)[packet->from] = session;
|
(*sessions)[packet->from] = session;
|
||||||
LogPrint (eLogInfo, "SSU: new session from ", packet->from.address ().to_string (), ":", packet->from.port (), " created");
|
LogPrint (eLogDebug, "SSU: new session from ", packet->from.address ().to_string (), ":", packet->from.port (), " created");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
session->ProcessNextMessage (packet->buf, packet->len, packet->from);
|
session->ProcessNextMessage (packet->buf, packet->len, packet->from);
|
||||||
@ -312,7 +312,7 @@ namespace transport
|
|||||||
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
|
auto session = std::make_shared<SSUSession> (*this, remoteEndpoint, router, peerTest);
|
||||||
sessions[remoteEndpoint] = session;
|
sessions[remoteEndpoint] = session;
|
||||||
// connect
|
// connect
|
||||||
LogPrint (eLogInfo, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ",
|
LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ",
|
||||||
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ());
|
remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ());
|
||||||
session->Connect ();
|
session->Connect ();
|
||||||
}
|
}
|
||||||
@ -364,10 +364,10 @@ namespace transport
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (introducerSession) // session found
|
if (introducerSession) // session found
|
||||||
LogPrint (eLogInfo, "SSU: Session to introducer already exists");
|
LogPrint (eLogWarning, "SSU: Session to introducer already exists");
|
||||||
else // create new
|
else // create new
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "SSU: Creating new session to introducer");
|
LogPrint (eLogDebug, "SSU: Creating new session to introducer ", introducer->iHost);
|
||||||
boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort);
|
boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort);
|
||||||
introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router);
|
introducerSession = std::make_shared<SSUSession> (*this, introducerEndpoint, router);
|
||||||
m_Sessions[introducerEndpoint] = introducerSession;
|
m_Sessions[introducerEndpoint] = introducerSession;
|
||||||
|
12
SSUData.cpp
12
SSUData.cpp
@ -241,7 +241,7 @@ namespace transport
|
|||||||
if (!msg->IsExpired ())
|
if (!msg->IsExpired ())
|
||||||
m_Handler.PutNextMessage (msg);
|
m_Handler.PutNextMessage (msg);
|
||||||
else
|
else
|
||||||
LogPrint (eLogInfo, "SSU: message expired");
|
LogPrint (eLogDebug, "SSU: message expired");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "SSU: Message ", msgID, " already received");
|
LogPrint (eLogWarning, "SSU: Message ", msgID, " already received");
|
||||||
@ -425,6 +425,7 @@ namespace transport
|
|||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
int numResent = 0;
|
||||||
for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();)
|
for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();)
|
||||||
{
|
{
|
||||||
if (ts >= it->second->nextResendTime)
|
if (ts >= it->second->nextResendTime)
|
||||||
@ -437,6 +438,7 @@ namespace transport
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_Session.Send (f->buf, f->len); // resend
|
m_Session.Send (f->buf, f->len); // resend
|
||||||
|
numResent++;
|
||||||
}
|
}
|
||||||
catch (boost::system::system_error& ec)
|
catch (boost::system::system_error& ec)
|
||||||
{
|
{
|
||||||
@ -457,7 +459,13 @@ namespace transport
|
|||||||
else
|
else
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
ScheduleResend ();
|
if (numResent < MAX_OUTGOING_WINDOW_SIZE)
|
||||||
|
ScheduleResend ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "SSU: resend window exceeds max size. Session terminated");
|
||||||
|
m_Session.Close ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ namespace transport
|
|||||||
const int DECAY_INTERVAL = 20; // in seconds
|
const int DECAY_INTERVAL = 20; // in seconds
|
||||||
const int INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds
|
const int INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds
|
||||||
const unsigned int MAX_NUM_RECEIVED_MESSAGES = 1000; // how many msgID we store for duplicates check
|
const unsigned int MAX_NUM_RECEIVED_MESSAGES = 1000; // how many msgID we store for duplicates check
|
||||||
|
const int MAX_OUTGOING_WINDOW_SIZE = 200; // how many unacked message we can store
|
||||||
// data flags
|
// data flags
|
||||||
const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02;
|
const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02;
|
||||||
const uint8_t DATA_FLAG_WANT_REPLY = 0x04;
|
const uint8_t DATA_FLAG_WANT_REPLY = 0x04;
|
||||||
|
@ -814,7 +814,7 @@ namespace transport
|
|||||||
if (!ecode)
|
if (!ecode)
|
||||||
{
|
{
|
||||||
// timeout expired
|
// timeout expired
|
||||||
LogPrint (eLogWarning, "SSU: session was not established after ", SSU_CONNECT_TIMEOUT, " seconds");
|
LogPrint (eLogWarning, "SSU: session with ", m_RemoteEndpoint, " was not established after ", SSU_CONNECT_TIMEOUT, " seconds");
|
||||||
Failed ();
|
Failed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -891,7 +891,7 @@ namespace transport
|
|||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "SSU: no activity for ", SSU_TERMINATION_TIMEOUT, " seconds");
|
LogPrint (eLogWarning, "SSU: no activity with ", m_RemoteEndpoint, " for ", SSU_TERMINATION_TIMEOUT, " seconds");
|
||||||
Failed ();
|
Failed ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ namespace stream
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint (eLogDebug, "Streaming: Received seqn=", receivedSeqn);
|
LogPrint (eLogDebug, "Streaming: Received seqn=", receivedSeqn, " on sSID=", m_SendStreamID);
|
||||||
if (receivedSeqn == m_LastReceivedSequenceNumber + 1)
|
if (receivedSeqn == m_LastReceivedSequenceNumber + 1)
|
||||||
{
|
{
|
||||||
// we have received next in sequence message
|
// we have received next in sequence message
|
||||||
@ -129,13 +129,13 @@ namespace stream
|
|||||||
if (receivedSeqn <= m_LastReceivedSequenceNumber)
|
if (receivedSeqn <= m_LastReceivedSequenceNumber)
|
||||||
{
|
{
|
||||||
// we have received duplicate
|
// we have received duplicate
|
||||||
LogPrint (eLogWarning, "Streaming: Duplicate message ", receivedSeqn, " received");
|
LogPrint (eLogWarning, "Streaming: Duplicate message ", receivedSeqn, " on sSID=", m_SendStreamID);
|
||||||
SendQuickAck (); // resend ack for previous message again
|
SendQuickAck (); // resend ack for previous message again
|
||||||
delete packet; // packet dropped
|
delete packet; // packet dropped
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Streaming: Missing messages from ", m_LastReceivedSequenceNumber + 1, " to ", receivedSeqn - 1);
|
LogPrint (eLogWarning, "Streaming: Missing messages on sSID=", m_SendStreamID, ": from ", m_LastReceivedSequenceNumber + 1, " to ", receivedSeqn - 1);
|
||||||
// save message and wait for missing message again
|
// save message and wait for missing message again
|
||||||
SavePacket (packet);
|
SavePacket (packet);
|
||||||
if (m_LastReceivedSequenceNumber >= 0)
|
if (m_LastReceivedSequenceNumber >= 0)
|
||||||
@ -183,7 +183,7 @@ namespace stream
|
|||||||
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, packet->GetOptionSize ());
|
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, packet->GetOptionSize ());
|
||||||
optionData += m_RemoteIdentity->GetFullLen ();
|
optionData += m_RemoteIdentity->GetFullLen ();
|
||||||
if (!m_RemoteLeaseSet)
|
if (!m_RemoteLeaseSet)
|
||||||
LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase64 ());
|
LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), ", sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED)
|
if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED)
|
||||||
@ -263,7 +263,7 @@ namespace stream
|
|||||||
uint64_t rtt = ts - sentPacket->sendTime;
|
uint64_t rtt = ts - sentPacket->sendTime;
|
||||||
m_RTT = (m_RTT*seqn + rtt)/(seqn + 1);
|
m_RTT = (m_RTT*seqn + rtt)/(seqn + 1);
|
||||||
m_RTO = m_RTT*1.5; // TODO: implement it better
|
m_RTO = m_RTT*1.5; // TODO: implement it better
|
||||||
LogPrint (eLogDebug, "Packet ", seqn, " acknowledged rtt=", rtt);
|
LogPrint (eLogDebug, "Streaming: Packet ", seqn, " acknowledged rtt=", rtt);
|
||||||
m_SentPackets.erase (it++);
|
m_SentPackets.erase (it++);
|
||||||
delete sentPacket;
|
delete sentPacket;
|
||||||
acknowledged = true;
|
acknowledged = true;
|
||||||
@ -395,8 +395,11 @@ namespace stream
|
|||||||
}
|
}
|
||||||
if (packets.size () > 0)
|
if (packets.size () > 0)
|
||||||
{
|
{
|
||||||
m_IsAckSendScheduled = false;
|
if (m_SavedPackets.empty ()) // no NACKS
|
||||||
m_AckSendTimer.cancel ();
|
{
|
||||||
|
m_IsAckSendScheduled = false;
|
||||||
|
m_AckSendTimer.cancel ();
|
||||||
|
}
|
||||||
bool isEmpty = m_SentPackets.empty ();
|
bool isEmpty = m_SentPackets.empty ();
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
for (auto it: packets)
|
for (auto it: packets)
|
||||||
@ -448,7 +451,7 @@ namespace stream
|
|||||||
auto seqn = it->GetSeqn ();
|
auto seqn = it->GetSeqn ();
|
||||||
if (numNacks + (seqn - nextSeqn) >= 256)
|
if (numNacks + (seqn - nextSeqn) >= 256)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Number of NACKs exceeds 256. seqn=", seqn, " nextSeqn=", nextSeqn);
|
LogPrint (eLogError, "Streaming: Number of NACKs exceeds 256. seqn=", seqn, " nextSeqn=", nextSeqn);
|
||||||
htobe32buf (packet + 12, nextSeqn); // change ack Through
|
htobe32buf (packet + 12, nextSeqn); // change ack Through
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -489,7 +492,7 @@ namespace stream
|
|||||||
m_Status = eStreamStatusClosing;
|
m_Status = eStreamStatusClosing;
|
||||||
Close (); // recursion
|
Close (); // recursion
|
||||||
if (m_Status == eStreamStatusClosing) //still closing
|
if (m_Status == eStreamStatusClosing) //still closing
|
||||||
LogPrint (eLogInfo, "Streaming: Trying to send stream data before closing");
|
LogPrint (eLogDebug, "Streaming: Trying to send stream data before closing, sSID=", m_SendStreamID);
|
||||||
break;
|
break;
|
||||||
case eStreamStatusReset:
|
case eStreamStatusReset:
|
||||||
SendClose ();
|
SendClose ();
|
||||||
@ -511,7 +514,7 @@ namespace stream
|
|||||||
m_LocalDestination.DeleteStream (shared_from_this ());
|
m_LocalDestination.DeleteStream (shared_from_this ());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Streaming: Unexpected stream status ", (int)m_Status);
|
LogPrint (eLogWarning, "Streaming: Unexpected stream status ", (int)m_Status, "sSID=", m_SendStreamID);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,7 +546,7 @@ namespace stream
|
|||||||
|
|
||||||
p->len = size;
|
p->len = size;
|
||||||
m_Service.post (std::bind (&Stream::SendPacket, shared_from_this (), p));
|
m_Service.post (std::bind (&Stream::SendPacket, shared_from_this (), p));
|
||||||
LogPrint (eLogDebug, "Streaming: FIN sent");
|
LogPrint (eLogDebug, "Streaming: FIN sent, sSID=", m_SendStreamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Stream::ConcatenatePackets (uint8_t * buf, size_t len)
|
size_t Stream::ConcatenatePackets (uint8_t * buf, size_t len)
|
||||||
@ -597,7 +600,7 @@ namespace stream
|
|||||||
UpdateCurrentRemoteLease ();
|
UpdateCurrentRemoteLease ();
|
||||||
if (!m_RemoteLeaseSet)
|
if (!m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Streaming: Can't send packets, missing remote LeaseSet");
|
LogPrint (eLogError, "Streaming: Can't send packets, missing remote LeaseSet, sSID=", m_SendStreamID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -622,7 +625,7 @@ namespace stream
|
|||||||
m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel);
|
m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel);
|
||||||
if (!m_CurrentOutboundTunnel)
|
if (!m_CurrentOutboundTunnel)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Streaming: No outbound tunnels in the pool");
|
LogPrint (eLogError, "Streaming: No outbound tunnels in the pool, sSID=", m_SendStreamID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,7 +649,7 @@ namespace stream
|
|||||||
m_CurrentOutboundTunnel->SendTunnelDataMsg (msgs);
|
m_CurrentOutboundTunnel->SendTunnelDataMsg (msgs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "Streaming: All leases are expired");
|
LogPrint (eLogWarning, "Streaming: All leases are expired, sSID=", m_SendStreamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -665,7 +668,7 @@ namespace stream
|
|||||||
// check for resend attempts
|
// check for resend attempts
|
||||||
if (m_NumResendAttempts >= MAX_NUM_RESEND_ATTEMPTS)
|
if (m_NumResendAttempts >= MAX_NUM_RESEND_ATTEMPTS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Streaming: packet was not ACKed after ", MAX_NUM_RESEND_ATTEMPTS, " attempts, terminate");
|
LogPrint (eLogWarning, "Streaming: packet was not ACKed after ", MAX_NUM_RESEND_ATTEMPTS, " attempts, terminate, sSID=", m_SendStreamID);
|
||||||
m_Status = eStreamStatusReset;
|
m_Status = eStreamStatusReset;
|
||||||
Close ();
|
Close ();
|
||||||
return;
|
return;
|
||||||
@ -700,13 +703,13 @@ namespace stream
|
|||||||
case 4:
|
case 4:
|
||||||
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
|
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
|
||||||
UpdateCurrentRemoteLease (); // pick another lease
|
UpdateCurrentRemoteLease (); // pick another lease
|
||||||
LogPrint (eLogWarning, "Streaming: Another remote lease has been selected for stream");
|
LogPrint (eLogWarning, "Streaming: Another remote lease has been selected for stream with sSID=", m_SendStreamID);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// pick another outbound tunnel
|
// pick another outbound tunnel
|
||||||
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
|
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
|
||||||
m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (m_CurrentOutboundTunnel);
|
m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (m_CurrentOutboundTunnel);
|
||||||
LogPrint (eLogWarning, "Streaming: Another outbound tunnel has been selected for stream");
|
LogPrint (eLogWarning, "Streaming: Another outbound tunnel has been selected for stream with sSID=", m_SendStreamID);
|
||||||
break;
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
@ -722,7 +725,7 @@ namespace stream
|
|||||||
{
|
{
|
||||||
if (m_LastReceivedSequenceNumber < 0)
|
if (m_LastReceivedSequenceNumber < 0)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Streaming: SYN has not been recived after ", ACK_SEND_TIMEOUT, " milliseconds after follow on, terminate");
|
LogPrint (eLogWarning, "Streaming: SYN has not been recived after ", ACK_SEND_TIMEOUT, " milliseconds after follow on, terminate sSID=", m_SendStreamID);
|
||||||
m_Status = eStreamStatusReset;
|
m_Status = eStreamStatusReset;
|
||||||
Close ();
|
Close ();
|
||||||
return;
|
return;
|
||||||
@ -825,7 +828,7 @@ namespace stream
|
|||||||
it->second->HandleNextPacket (packet);
|
it->second->HandleNextPacket (packet);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Streaming: Unknown stream sendStreamID=", sendStreamID);
|
LogPrint (eLogError, "Streaming: Unknown stream sSID=", sendStreamID);
|
||||||
delete packet;
|
delete packet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -841,7 +844,7 @@ namespace stream
|
|||||||
auto it = m_SavedPackets.find (receiveStreamID);
|
auto it = m_SavedPackets.find (receiveStreamID);
|
||||||
if (it != m_SavedPackets.end ())
|
if (it != m_SavedPackets.end ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Streaming: Processing ", it->second.size (), " saved packets for receiveStreamID=", receiveStreamID);
|
LogPrint (eLogDebug, "Streaming: Processing ", it->second.size (), " saved packets for rSID=", receiveStreamID);
|
||||||
for (auto it1: it->second)
|
for (auto it1: it->second)
|
||||||
incomingStream->HandleNextPacket (it1);
|
incomingStream->HandleNextPacket (it1);
|
||||||
m_SavedPackets.erase (it);
|
m_SavedPackets.erase (it);
|
||||||
@ -860,7 +863,7 @@ namespace stream
|
|||||||
m_PendingIncomingTimer.expires_from_now (boost::posix_time::seconds(PENDING_INCOMING_TIMEOUT));
|
m_PendingIncomingTimer.expires_from_now (boost::posix_time::seconds(PENDING_INCOMING_TIMEOUT));
|
||||||
m_PendingIncomingTimer.async_wait (std::bind (&StreamingDestination::HandlePendingIncomingTimer,
|
m_PendingIncomingTimer.async_wait (std::bind (&StreamingDestination::HandlePendingIncomingTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
LogPrint (eLogDebug, "Streaming: Pending incoming stream added");
|
LogPrint (eLogDebug, "Streaming: Pending incoming stream added, rSID=", receiveStreamID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
90
Tag.h
Normal file
90
Tag.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 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 TAG_H__
|
||||||
|
#define TAG_H__
|
||||||
|
|
||||||
|
#include <string.h> /* memcpy */
|
||||||
|
|
||||||
|
#include "Base.h"
|
||||||
|
|
||||||
|
namespace i2p {
|
||||||
|
namespace data {
|
||||||
|
template<int sz>
|
||||||
|
class Tag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); };
|
||||||
|
Tag (const Tag<sz>& ) = default;
|
||||||
|
#ifndef _WIN32 // FIXME!!! msvs 2013 can't compile it
|
||||||
|
Tag (Tag<sz>&& ) = default;
|
||||||
|
#endif
|
||||||
|
Tag () = default;
|
||||||
|
|
||||||
|
Tag<sz>& operator= (const Tag<sz>& ) = default;
|
||||||
|
#ifndef _WIN32
|
||||||
|
Tag<sz>& operator= (Tag<sz>&& ) = default;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t * operator()() { return m_Buf; };
|
||||||
|
const uint8_t * operator()() const { return m_Buf; };
|
||||||
|
|
||||||
|
operator uint8_t * () { return m_Buf; };
|
||||||
|
operator const uint8_t * () const { return m_Buf; };
|
||||||
|
|
||||||
|
const uint64_t * GetLL () const { return ll; };
|
||||||
|
|
||||||
|
bool operator== (const Tag<sz>& other) const { return !memcmp (m_Buf, other.m_Buf, sz); };
|
||||||
|
bool operator< (const Tag<sz>& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; };
|
||||||
|
|
||||||
|
bool IsZero () const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sz/8; i++)
|
||||||
|
if (ll[i]) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToBase64 () const
|
||||||
|
{
|
||||||
|
char str[sz*2];
|
||||||
|
int l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
|
||||||
|
str[l] = 0;
|
||||||
|
return std::string (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToBase32 () const
|
||||||
|
{
|
||||||
|
char str[sz*2];
|
||||||
|
int l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
|
||||||
|
str[l] = 0;
|
||||||
|
return std::string (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FromBase32 (const std::string& s)
|
||||||
|
{
|
||||||
|
i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FromBase64 (const std::string& s)
|
||||||
|
{
|
||||||
|
i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
union // 8 bytes alignment
|
||||||
|
{
|
||||||
|
uint8_t m_Buf[sz];
|
||||||
|
uint64_t ll[sz/8];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // data
|
||||||
|
} // i2p
|
||||||
|
|
||||||
|
#endif /* TAG_H__ */
|
@ -92,7 +92,7 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
if (isEndpoint)
|
if (isEndpoint)
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "TransitTunnel: endpoint ", receiveTunnelID, " created");
|
LogPrint (eLogDebug, "TransitTunnel: endpoint ", receiveTunnelID, " created");
|
||||||
return std::make_shared<TransitTunnelEndpoint> (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
|
return std::make_shared<TransitTunnelEndpoint> (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
|
||||||
}
|
}
|
||||||
else if (isGateway)
|
else if (isGateway)
|
||||||
@ -102,7 +102,7 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created");
|
LogPrint (eLogDebug, "TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created");
|
||||||
return std::make_shared<TransitTunnelParticipant> (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
|
return std::make_shared<TransitTunnelParticipant> (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
Tunnel.cpp
29
Tunnel.cpp
@ -217,6 +217,7 @@ namespace tunnel
|
|||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
m_NumReceivedBytes += msg->GetLength ();
|
m_NumReceivedBytes += msg->GetLength ();
|
||||||
|
msg->from = shared_from_this ();
|
||||||
HandleI2NPMessage (msg);
|
HandleI2NPMessage (msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,6 +769,22 @@ namespace tunnel
|
|||||||
return newTunnel;
|
return newTunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<InboundTunnel> Tunnels::CreateInboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||||
|
{
|
||||||
|
if (config)
|
||||||
|
return CreateTunnel<InboundTunnel>(config, outboundTunnel);
|
||||||
|
else
|
||||||
|
return CreateZeroHopsInboundTunnel ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<OutboundTunnel> Tunnels::CreateOutboundTunnel (std::shared_ptr<TunnelConfig> config)
|
||||||
|
{
|
||||||
|
if (config)
|
||||||
|
return CreateTunnel<OutboundTunnel>(config);
|
||||||
|
else
|
||||||
|
return CreateZeroHopsOutboundTunnel ();
|
||||||
|
}
|
||||||
|
|
||||||
void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel)
|
void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel)
|
||||||
{
|
{
|
||||||
m_PendingInboundTunnels[replyMsgID] = tunnel;
|
m_PendingInboundTunnels[replyMsgID] = tunnel;
|
||||||
@ -815,20 +832,22 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Tunnels::CreateZeroHopsInboundTunnel ()
|
std::shared_ptr<ZeroHopsInboundTunnel> Tunnels::CreateZeroHopsInboundTunnel ()
|
||||||
{
|
{
|
||||||
auto inboundTunnel = std::make_shared<ZeroHopsInboundTunnel> ();
|
auto inboundTunnel = std::make_shared<ZeroHopsInboundTunnel> ();
|
||||||
inboundTunnel->SetState (eTunnelStateEstablished);
|
inboundTunnel->SetState (eTunnelStateEstablished);
|
||||||
m_InboundTunnels.push_back (inboundTunnel);
|
m_InboundTunnels.push_back (inboundTunnel);
|
||||||
m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel;
|
m_Tunnels[inboundTunnel->GetTunnelID ()] = inboundTunnel;
|
||||||
|
return inboundTunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::CreateZeroHopsOutboundTunnel ()
|
std::shared_ptr<ZeroHopsOutboundTunnel> Tunnels::CreateZeroHopsOutboundTunnel ()
|
||||||
{
|
{
|
||||||
auto outboundTunnel = std::make_shared<ZeroHopsOutboundTunnel> ();
|
auto outboundTunnel = std::make_shared<ZeroHopsOutboundTunnel> ();
|
||||||
outboundTunnel->SetState (eTunnelStateEstablished);
|
outboundTunnel->SetState (eTunnelStateEstablished);
|
||||||
m_OutboundTunnels.push_back (outboundTunnel);
|
m_OutboundTunnels.push_back (outboundTunnel);
|
||||||
// we don't insert into m_Tunnels
|
// we don't insert into m_Tunnels
|
||||||
|
return outboundTunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Tunnels::GetTransitTunnelsExpirationTimeout ()
|
int Tunnels::GetTransitTunnelsExpirationTimeout ()
|
||||||
@ -861,12 +880,6 @@ namespace tunnel
|
|||||||
// TODO: locking
|
// TODO: locking
|
||||||
return m_OutboundTunnels.size();
|
return m_OutboundTunnels.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ANDROID_ARM7A
|
|
||||||
template std::shared_ptr<InboundTunnel> Tunnels::CreateTunnel<InboundTunnel>(std::shared_ptr<TunnelConfig>, std::shared_ptr<OutboundTunnel>);
|
|
||||||
template std::shared_ptr<OutboundTunnel> Tunnels::CreateTunnel<OutboundTunnel>(std::shared_ptr<TunnelConfig>, std::shared_ptr<OutboundTunnel>);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
Tunnel.h
11
Tunnel.h
@ -176,10 +176,10 @@ namespace tunnel
|
|||||||
void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
|
void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
|
||||||
void AddOutboundTunnel (std::shared_ptr<OutboundTunnel> newTunnel);
|
void AddOutboundTunnel (std::shared_ptr<OutboundTunnel> newTunnel);
|
||||||
void AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel);
|
void AddInboundTunnel (std::shared_ptr<InboundTunnel> newTunnel);
|
||||||
|
std::shared_ptr<InboundTunnel> CreateInboundTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel);
|
||||||
|
std::shared_ptr<OutboundTunnel> CreateOutboundTunnel (std::shared_ptr<TunnelConfig> config);
|
||||||
void PostTunnelData (std::shared_ptr<I2NPMessage> msg);
|
void PostTunnelData (std::shared_ptr<I2NPMessage> msg);
|
||||||
void PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
void PostTunnelData (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||||
template<class TTunnel>
|
|
||||||
std::shared_ptr<TTunnel> CreateTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
|
||||||
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel);
|
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<InboundTunnel> tunnel);
|
||||||
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel);
|
void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> tunnel);
|
||||||
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops,
|
std::shared_ptr<TunnelPool> CreateTunnelPool (int numInboundHops,
|
||||||
@ -189,6 +189,9 @@ namespace tunnel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
template<class TTunnel>
|
||||||
|
std::shared_ptr<TTunnel> CreateTunnel (std::shared_ptr<TunnelConfig> config, std::shared_ptr<OutboundTunnel> outboundTunnel = nullptr);
|
||||||
|
|
||||||
template<class TTunnel>
|
template<class TTunnel>
|
||||||
std::shared_ptr<TTunnel> GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels);
|
std::shared_ptr<TTunnel> GetPendingTunnel (uint32_t replyMsgID, const std::map<uint32_t, std::shared_ptr<TTunnel> >& pendingTunnels);
|
||||||
|
|
||||||
@ -204,8 +207,8 @@ namespace tunnel
|
|||||||
void ManagePendingTunnels (PendingTunnels& pendingTunnels);
|
void ManagePendingTunnels (PendingTunnels& pendingTunnels);
|
||||||
void ManageTunnelPools ();
|
void ManageTunnelPools ();
|
||||||
|
|
||||||
void CreateZeroHopsInboundTunnel ();
|
std::shared_ptr<ZeroHopsInboundTunnel> CreateZeroHopsInboundTunnel ();
|
||||||
void CreateZeroHopsOutboundTunnel ();
|
std::shared_ptr<ZeroHopsOutboundTunnel> CreateZeroHopsOutboundTunnel ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -159,6 +159,11 @@ namespace tunnel
|
|||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsEmpty () const
|
||||||
|
{
|
||||||
|
return !m_FirstHop;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool IsInbound () const { return m_FirstHop->isGateway; }
|
virtual bool IsInbound () const { return m_FirstHop->isGateway; }
|
||||||
|
|
||||||
virtual uint32_t GetTunnelID () const
|
virtual uint32_t GetTunnelID () const
|
||||||
|
@ -329,8 +329,9 @@ namespace tunnel
|
|||||||
bool TunnelPool::SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
|
bool TunnelPool::SelectPeers (std::vector<std::shared_ptr<const i2p::data::IdentityEx> >& peers, bool isInbound)
|
||||||
{
|
{
|
||||||
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
||||||
auto prevHop = i2p::context.GetSharedRouterInfo ();
|
|
||||||
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
|
||||||
|
if (numHops <= 0) return true; // peers is empty
|
||||||
|
auto prevHop = i2p::context.GetSharedRouterInfo ();
|
||||||
if (i2p::transport::transports.GetNumPeers () > 25)
|
if (i2p::transport::transports.GetNumPeers () > 25)
|
||||||
{
|
{
|
||||||
auto r = i2p::transport::transports.GetRandomPeer ();
|
auto r = i2p::transport::transports.GetRandomPeer ();
|
||||||
@ -389,9 +390,16 @@ namespace tunnel
|
|||||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
|
||||||
if (SelectPeers (peers, true))
|
if (SelectPeers (peers, true))
|
||||||
{
|
{
|
||||||
std::reverse (peers.begin (), peers.end ());
|
std::shared_ptr<TunnelConfig> config;
|
||||||
auto tunnel = tunnels.CreateTunnel<InboundTunnel> (std::make_shared<TunnelConfig> (peers), outboundTunnel);
|
if (m_NumInboundHops > 0)
|
||||||
|
{
|
||||||
|
std::reverse (peers.begin (), peers.end ());
|
||||||
|
config = std::make_shared<TunnelConfig> (peers);
|
||||||
|
}
|
||||||
|
auto tunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
|
||||||
tunnel->SetTunnelPool (shared_from_this ());
|
tunnel->SetTunnelPool (shared_from_this ());
|
||||||
|
if (tunnel->IsEstablished ()) // zero hops
|
||||||
|
TunnelCreated (tunnel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Tunnels: Can't create inbound tunnel, no peers available");
|
LogPrint (eLogError, "Tunnels: Can't create inbound tunnel, no peers available");
|
||||||
@ -403,8 +411,12 @@ namespace tunnel
|
|||||||
if (!outboundTunnel)
|
if (!outboundTunnel)
|
||||||
outboundTunnel = tunnels.GetNextOutboundTunnel ();
|
outboundTunnel = tunnels.GetNextOutboundTunnel ();
|
||||||
LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel...");
|
LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel...");
|
||||||
auto newTunnel = tunnels.CreateTunnel<InboundTunnel> (std::make_shared<TunnelConfig>(tunnel->GetPeers ()), outboundTunnel);
|
std::shared_ptr<TunnelConfig> config;
|
||||||
|
if (m_NumInboundHops > 0) config = std::make_shared<TunnelConfig>(tunnel->GetPeers ());
|
||||||
|
auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
|
||||||
newTunnel->SetTunnelPool (shared_from_this());
|
newTunnel->SetTunnelPool (shared_from_this());
|
||||||
|
if (newTunnel->IsEstablished ()) // zero hops
|
||||||
|
TunnelCreated (newTunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelPool::CreateOutboundTunnel ()
|
void TunnelPool::CreateOutboundTunnel ()
|
||||||
@ -418,9 +430,13 @@ namespace tunnel
|
|||||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
|
||||||
if (SelectPeers (peers, false))
|
if (SelectPeers (peers, false))
|
||||||
{
|
{
|
||||||
auto tunnel = tunnels.CreateTunnel<OutboundTunnel> (
|
std::shared_ptr<TunnelConfig> config;
|
||||||
std::make_shared<TunnelConfig> (peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()));
|
if (m_NumOutboundHops > 0)
|
||||||
|
config = std::make_shared<TunnelConfig>(peers, inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
|
||||||
|
auto tunnel = tunnels.CreateOutboundTunnel (config);
|
||||||
tunnel->SetTunnelPool (shared_from_this ());
|
tunnel->SetTunnelPool (shared_from_this ());
|
||||||
|
if (tunnel->IsEstablished ()) // zero hops
|
||||||
|
TunnelCreated (tunnel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no peers available");
|
LogPrint (eLogError, "Tunnels: Can't create outbound tunnel, no peers available");
|
||||||
@ -437,10 +453,13 @@ namespace tunnel
|
|||||||
if (inboundTunnel)
|
if (inboundTunnel)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel...");
|
LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel...");
|
||||||
auto newTunnel = tunnels.CreateTunnel<OutboundTunnel> (
|
std::shared_ptr<TunnelConfig> config;
|
||||||
std::make_shared<TunnelConfig> (tunnel->GetPeers (),
|
if (m_NumOutboundHops > 0)
|
||||||
inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ()));
|
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
|
||||||
|
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
||||||
newTunnel->SetTunnelPool (shared_from_this ());
|
newTunnel->SetTunnelPool (shared_from_this ());
|
||||||
|
if (newTunnel->IsEstablished ()) // zero hops
|
||||||
|
TunnelCreated (newTunnel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found");
|
LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found");
|
||||||
@ -449,7 +468,7 @@ namespace tunnel
|
|||||||
void TunnelPool::CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel)
|
void TunnelPool::CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel...");
|
LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel...");
|
||||||
auto tunnel = tunnels.CreateTunnel<InboundTunnel> (std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers ()), outboundTunnel);
|
auto tunnel = tunnels.CreateInboundTunnel (std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers ()), outboundTunnel);
|
||||||
tunnel->SetTunnelPool (shared_from_this ());
|
tunnel->SetTunnelPool (shared_from_this ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
78
UPnP.cpp
78
UPnP.cpp
@ -6,13 +6,6 @@
|
|||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#define dlsym GetProcAddress
|
|
||||||
#else
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
@ -24,32 +17,11 @@
|
|||||||
#include <miniupnpc/miniupnpc.h>
|
#include <miniupnpc/miniupnpc.h>
|
||||||
#include <miniupnpc/upnpcommands.h>
|
#include <miniupnpc/upnpcommands.h>
|
||||||
|
|
||||||
// These are per-process and are safe to reuse for all threads
|
|
||||||
decltype(upnpDiscover) *upnpDiscoverFunc;
|
|
||||||
decltype(UPNP_AddPortMapping) *UPNP_AddPortMappingFunc;
|
|
||||||
decltype(UPNP_GetValidIGD) *UPNP_GetValidIGDFunc;
|
|
||||||
decltype(UPNP_GetExternalIPAddress) *UPNP_GetExternalIPAddressFunc;
|
|
||||||
decltype(UPNP_DeletePortMapping) *UPNP_DeletePortMappingFunc;
|
|
||||||
decltype(freeUPNPDevlist) *freeUPNPDevlistFunc;
|
|
||||||
decltype(FreeUPNPUrls) *FreeUPNPUrlsFunc;
|
|
||||||
|
|
||||||
// Nice approach http://stackoverflow.com/a/21517513/673826
|
|
||||||
template<class M, typename F>
|
|
||||||
F GetKnownProcAddressImpl(M hmod, const char *name, F) {
|
|
||||||
auto proc = reinterpret_cast<F>(dlsym(hmod, name));
|
|
||||||
if (!proc) {
|
|
||||||
LogPrint(eLogError, "UPnP: Error resolving ", name, " from library, version mismatch?");
|
|
||||||
}
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
#define GetKnownProcAddress(hmod, func) GetKnownProcAddressImpl(hmod, #func, func##Func);
|
|
||||||
|
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace transport
|
namespace transport
|
||||||
{
|
{
|
||||||
UPnP::UPnP () : m_Thread (nullptr) , m_IsModuleLoaded (false)
|
UPnP::UPnP () : m_Thread (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,33 +37,6 @@ namespace transport
|
|||||||
|
|
||||||
void UPnP::Start()
|
void UPnP::Start()
|
||||||
{
|
{
|
||||||
if (!m_IsModuleLoaded) {
|
|
||||||
#ifdef MAC_OSX
|
|
||||||
m_Module = dlopen ("libminiupnpc.dylib", RTLD_LAZY);
|
|
||||||
#elif _WIN32
|
|
||||||
m_Module = LoadLibrary ("libminiupnpc.dll"); // from MSYS2
|
|
||||||
#else
|
|
||||||
m_Module = dlopen ("libminiupnpc.so", RTLD_LAZY);
|
|
||||||
#endif
|
|
||||||
if (m_Module == NULL)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "UPnP: Error loading UPNP library, version mismatch?");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
upnpDiscoverFunc = GetKnownProcAddress (m_Module, upnpDiscover);
|
|
||||||
UPNP_GetValidIGDFunc = GetKnownProcAddress (m_Module, UPNP_GetValidIGD);
|
|
||||||
UPNP_GetExternalIPAddressFunc = GetKnownProcAddress (m_Module, UPNP_GetExternalIPAddress);
|
|
||||||
UPNP_AddPortMappingFunc = GetKnownProcAddress (m_Module, UPNP_AddPortMapping);
|
|
||||||
UPNP_DeletePortMappingFunc = GetKnownProcAddress (m_Module, UPNP_DeletePortMapping);
|
|
||||||
freeUPNPDevlistFunc = GetKnownProcAddress (m_Module, freeUPNPDevlist);
|
|
||||||
FreeUPNPUrlsFunc = GetKnownProcAddress (m_Module, FreeUPNPUrls);
|
|
||||||
if (upnpDiscoverFunc && UPNP_GetValidIGDFunc && UPNP_GetExternalIPAddressFunc && UPNP_AddPortMappingFunc &&
|
|
||||||
UPNP_DeletePortMappingFunc && freeUPNPDevlistFunc && FreeUPNPUrlsFunc)
|
|
||||||
m_IsModuleLoaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_Thread = new std::thread (std::bind (&UPnP::Run, this));
|
m_Thread = new std::thread (std::bind (&UPnP::Run, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,16 +68,16 @@ namespace transport
|
|||||||
{
|
{
|
||||||
int nerror = 0;
|
int nerror = 0;
|
||||||
#if MINIUPNPC_API_VERSION >= 14
|
#if MINIUPNPC_API_VERSION >= 14
|
||||||
m_Devlist = upnpDiscoverFunc (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror);
|
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror);
|
||||||
#else
|
#else
|
||||||
m_Devlist = upnpDiscoverFunc (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror);
|
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
r = UPNP_GetValidIGDFunc (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||||
if (r == 1)
|
if (r == 1)
|
||||||
{
|
{
|
||||||
r = UPNP_GetExternalIPAddressFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
r = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||||
if(r != UPNPCOMMAND_SUCCESS)
|
if(r != UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress () returned ", r);
|
LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress () returned ", r);
|
||||||
@ -171,7 +116,7 @@ namespace transport
|
|||||||
std::string strDesc = "I2Pd";
|
std::string strDesc = "I2Pd";
|
||||||
try {
|
try {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
r = UPNP_AddPortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0");
|
r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0");
|
||||||
if (r!=UPNPCOMMAND_SUCCESS)
|
if (r!=UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: AddPortMapping (", strPort.c_str () ,", ", strPort.c_str () ,", ", m_NetworkAddr, ") failed with code ", r);
|
LogPrint (eLogError, "UPnP: AddPortMapping (", strPort.c_str () ,", ", strPort.c_str () ,", ", m_NetworkAddr, ") failed with code ", r);
|
||||||
@ -208,20 +153,15 @@ namespace transport
|
|||||||
strType = "UDP";
|
strType = "UDP";
|
||||||
}
|
}
|
||||||
int r = 0;
|
int r = 0;
|
||||||
r = UPNP_DeletePortMappingFunc (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
|
r = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
|
||||||
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", r, "\n");
|
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", r, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UPnP::Close ()
|
void UPnP::Close ()
|
||||||
{
|
{
|
||||||
freeUPNPDevlistFunc (m_Devlist);
|
freeUPNPDevlist (m_Devlist);
|
||||||
m_Devlist = 0;
|
m_Devlist = 0;
|
||||||
FreeUPNPUrlsFunc (&m_upnpUrls);
|
FreeUPNPUrls (&m_upnpUrls);
|
||||||
#ifndef _WIN32
|
|
||||||
dlclose (m_Module);
|
|
||||||
#else
|
|
||||||
FreeLibrary (m_Module);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
6
UPnP.h
6
UPnP.h
@ -48,12 +48,6 @@ namespace transport
|
|||||||
struct UPNPDev * m_Devlist = 0;
|
struct UPNPDev * m_Devlist = 0;
|
||||||
char m_NetworkAddr[64];
|
char m_NetworkAddr[64];
|
||||||
char m_externalIPAddress[40];
|
char m_externalIPAddress[40];
|
||||||
bool m_IsModuleLoaded;
|
|
||||||
#ifndef _WIN32
|
|
||||||
void *m_Module;
|
|
||||||
#else
|
|
||||||
HINSTANCE m_Module;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ set (LIBI2PD_SRC
|
|||||||
"${CMAKE_SOURCE_DIR}/Config.cpp"
|
"${CMAKE_SOURCE_DIR}/Config.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Crypto.cpp"
|
"${CMAKE_SOURCE_DIR}/Crypto.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Garlic.cpp"
|
"${CMAKE_SOURCE_DIR}/Garlic.cpp"
|
||||||
|
"${CMAKE_SOURCE_DIR}/Gzip.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/I2NPProtocol.cpp"
|
"${CMAKE_SOURCE_DIR}/I2NPProtocol.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/Identity.cpp"
|
"${CMAKE_SOURCE_DIR}/Identity.cpp"
|
||||||
"${CMAKE_SOURCE_DIR}/LeaseSet.cpp"
|
"${CMAKE_SOURCE_DIR}/LeaseSet.cpp"
|
||||||
@ -338,6 +339,10 @@ if (WITH_BINARY)
|
|||||||
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now" )
|
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now" )
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (WITH_UPNP)
|
||||||
|
target_link_libraries("${PROJECT_NAME}" "miniupnpc")
|
||||||
|
endif ()
|
||||||
|
|
||||||
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
|
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
|
||||||
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
||||||
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
|
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
|
||||||
|
1
debian/control
vendored
1
debian/control
vendored
@ -8,6 +8,7 @@ Build-Depends: debhelper (>= 9.0.0), dpkg-dev (>= 1.16.1~),
|
|||||||
libboost-date-time-dev,
|
libboost-date-time-dev,
|
||||||
libboost-filesystem-dev,
|
libboost-filesystem-dev,
|
||||||
libboost-program-options-dev,
|
libboost-program-options-dev,
|
||||||
|
libminiupnpc-dev,
|
||||||
libssl-dev
|
libssl-dev
|
||||||
Standards-Version: 3.9.3
|
Standards-Version: 3.9.3
|
||||||
Homepage: https://github.com/PurpleI2P/i2pd
|
Homepage: https://github.com/PurpleI2P/i2pd
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
diff --git a/Makefile b/Makefile
|
diff --git a/Makefile b/Makefile
|
||||||
index 2e86fd8..c1037af 100644
|
index fe8ae7e..fc8abda 100644
|
||||||
--- a/Makefile
|
--- a/Makefile
|
||||||
+++ b/Makefile
|
+++ b/Makefile
|
||||||
@@ -9,7 +9,7 @@ DEPS := obj/make.dep
|
@@ -9,9 +9,9 @@ DEPS := obj/make.dep
|
||||||
|
|
||||||
include filelist.mk
|
include filelist.mk
|
||||||
|
|
||||||
-USE_AESNI := yes
|
-USE_AESNI := yes
|
||||||
+USE_AESNI := no
|
+USE_AESNI := no
|
||||||
USE_STATIC := no
|
USE_STATIC := no
|
||||||
|
-USE_UPNP := no
|
||||||
|
+USE_UPNP := yes
|
||||||
|
|
||||||
ifeq ($(UNAME),Darwin)
|
ifeq ($(UNAME),Darwin)
|
||||||
|
DAEMON_SRC += DaemonLinux.cpp
|
2
debian/patches/series
vendored
2
debian/patches/series
vendored
@ -1 +1 @@
|
|||||||
0001-disable-aesni-by-default.patch
|
01-tune-build-opts.patch
|
||||||
|
@ -172,8 +172,6 @@ pacman -S mingw-w64-i686-miniupnpc
|
|||||||
make USE_UPNP=1
|
make USE_UPNP=1
|
||||||
```
|
```
|
||||||
|
|
||||||
It requires libminiupnpc.dll from /mingw32/bin
|
|
||||||
|
|
||||||
### Creating Visual Studio project
|
### Creating Visual Studio project
|
||||||
|
|
||||||
Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options.
|
Start CMake GUI, navigate to i2pd directory, choose building directory, e.g. ./out, and configure options.
|
||||||
|
@ -41,7 +41,7 @@ All options below still possible in cmdline, but better write it in config file:
|
|||||||
* --http.pass= - Password for basic auth (default: random, see logs)
|
* --http.pass= - Password for basic auth (default: random, see logs)
|
||||||
|
|
||||||
* --httpproxy.address= - The address to listen on (HTTP Proxy)
|
* --httpproxy.address= - The address to listen on (HTTP Proxy)
|
||||||
* --httpproxy.port= - The port to listen on (HTTP Proxy) 4446 by default
|
* --httpproxy.port= - The port to listen on (HTTP Proxy) 4444 by default
|
||||||
* --httpproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS)
|
* --httpproxy.keys= - optional keys file for proxy local destination (both HTTP and SOCKS)
|
||||||
* --httpproxy.enabled= - If HTTP proxy is enabled. true by default
|
* --httpproxy.enabled= - If HTTP proxy is enabled. true by default
|
||||||
|
|
||||||
@ -60,9 +60,9 @@ All options below still possible in cmdline, but better write it in config file:
|
|||||||
* --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified
|
* --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified
|
||||||
* --bob.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.address= - The address to listen on or an abstract address for Android LocalSocket
|
||||||
* --i2cp.port= - Port of I2CP server. Usually 7654. IPCP is off if not specified
|
* --i2cp.port= - Port of I2CP server. Usually 7654. Ignored for Andorid
|
||||||
* --i2cp.enabled= - If I2CP is enabled. false by default. Other services don't requeire I2CP
|
* --i2cp.enabled= - If I2CP is enabled. false by default. Other services don't require I2CP
|
||||||
|
|
||||||
* --i2pcontrol.address= - The address to listen on (I2P control service)
|
* --i2pcontrol.address= - The address to listen on (I2P control service)
|
||||||
* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified
|
* --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
LIB_SRC = \
|
LIB_SRC = \
|
||||||
Crypto.cpp Datagram.cpp Garlic.cpp I2NPProtocol.cpp LeaseSet.cpp \
|
Gzip.cpp Crypto.cpp Datagram.cpp Garlic.cpp I2NPProtocol.cpp LeaseSet.cpp \
|
||||||
Log.cpp NTCPSession.cpp NetDb.cpp NetDbRequests.cpp Profiling.cpp \
|
Log.cpp NTCPSession.cpp NetDb.cpp NetDbRequests.cpp Profiling.cpp \
|
||||||
Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \
|
Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \
|
||||||
SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
|
SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
|
||||||
|
1
qt/i2pd_qt/.gitignore
vendored
Normal file
1
qt/i2pd_qt/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
i2pd_qt.pro.user*
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.8.0" android:versionCode="1" android:installLocation="auto">
|
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.8.0" android:versionCode="2" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
|
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
|
||||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
<!-- <application android:hardwareAccelerated="true" -->
|
<!-- <application android:hardwareAccelerated="true" -->
|
||||||
|
5
qt/i2pd_qt/i2pd.qrc
Normal file
5
qt/i2pd_qt/i2pd.qrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>images/icon.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
@ -1,192 +1,128 @@
|
|||||||
#-------------------------------------------------
|
QT += core gui
|
||||||
#
|
|
||||||
# Project created by QtCreator 2016-06-14T04:53:04
|
|
||||||
#
|
|
||||||
#-------------------------------------------------
|
|
||||||
|
|
||||||
QT += core gui
|
|
||||||
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
TARGET = i2pd_qt
|
TARGET = i2pd_qt
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
QMAKE_CXXFLAGS *= -std=c++11
|
QMAKE_CXXFLAGS *= -std=c++11
|
||||||
|
DEFINES += USE_UPNP
|
||||||
|
|
||||||
|
# change to your own path, where you will store all needed libraries with 'git clone' commands below.
|
||||||
|
MAIN_PATH = /path/to/libraries
|
||||||
|
|
||||||
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
|
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git
|
||||||
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
||||||
|
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
|
||||||
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
|
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
|
||||||
# change to your own
|
|
||||||
BOOST_PATH = /mnt/media/android/Boost-for-Android-Prebuilt
|
BOOST_PATH = $$MAIN_PATH/Boost-for-Android-Prebuilt
|
||||||
OPENSSL_PATH = /mnt/media/android/OpenSSL-for-Android-Prebuilt
|
OPENSSL_PATH = $$MAIN_PATH/OpenSSL-for-Android-Prebuilt
|
||||||
IFADDRS_PATH = /mnt/media/android/android-ifaddrs
|
MINIUPNP_PATH = $$MAIN_PATH/MiniUPnP-for-Android-Prebuilt
|
||||||
|
IFADDRS_PATH = $$MAIN_PATH/android-ifaddrs
|
||||||
|
|
||||||
# Steps in Android SDK manager:
|
# Steps in Android SDK manager:
|
||||||
# 1) Check Extras/Google Support Library https://developer.android.com/topic/libraries/support-library/setup.html
|
# 1) Check Extras/Google Support Library https://developer.android.com/topic/libraries/support-library/setup.html
|
||||||
# 2) Check API 11
|
# 2) Check API 11
|
||||||
# Finally, click Install.
|
# Finally, click Install.
|
||||||
|
|
||||||
SOURCES += DaemonQT.cpp\
|
SOURCES += DaemonQT.cpp mainwindow.cpp \
|
||||||
mainwindow.cpp \
|
../../HTTPServer.cpp ../../I2PControl.cpp ../../Daemon.cpp ../../Config.cpp \
|
||||||
../../HTTPServer.cpp ../../I2PControl.cpp ../../UPnP.cpp ../../Daemon.cpp ../../Config.cpp \
|
../../AddressBook.cpp ../../api.cpp ../../Base.cpp ../../BOB.cpp ../../ClientContext.cpp \
|
||||||
../../AddressBook.cpp \
|
../../Crypto.cpp ../../Datagram.cpp ../../Destination.cpp ../../Family.cpp ../../FS.cpp \
|
||||||
../../api.cpp \
|
../../Garlic.cpp ../../HTTP.cpp ../../HTTPProxy.cpp ../../I2CP.cpp ../../I2NPProtocol.cpp \
|
||||||
../../Base.cpp \
|
../../I2PEndian.cpp ../../I2PService.cpp ../../I2PTunnel.cpp ../../Identity.cpp \
|
||||||
../../BOB.cpp \
|
../../LeaseSet.cpp ../../Log.cpp ../../NetDb.cpp ../../NetDbRequests.cpp \
|
||||||
../../ClientContext.cpp \
|
../../NTCPSession.cpp ../../Profiling.cpp ../../Reseed.cpp ../../RouterContext.cpp \
|
||||||
../../Crypto.cpp \
|
../../RouterInfo.cpp ../../SAM.cpp ../../Signature.cpp ../../SOCKS.cpp ../../SSU.cpp \
|
||||||
../../Datagram.cpp \
|
../../SSUData.cpp ../../SSUSession.cpp ../../Streaming.cpp ../../TransitTunnel.cpp \
|
||||||
../../Destination.cpp \
|
../../Transports.cpp ../../Tunnel.cpp ../../TunnelEndpoint.cpp ../../TunnelGateway.cpp \
|
||||||
../../Family.cpp \
|
../../TunnelPool.cpp ../../UPnP.cpp ../../util.cpp ../../Gzip.cpp ../../i2pd.cpp
|
||||||
../../FS.cpp \
|
|
||||||
../../Garlic.cpp \
|
|
||||||
../../HTTP.cpp \
|
|
||||||
../../HTTPProxy.cpp \
|
|
||||||
../../I2CP.cpp \
|
|
||||||
../../I2NPProtocol.cpp \
|
|
||||||
../../I2PEndian.cpp \
|
|
||||||
../../I2PService.cpp \
|
|
||||||
../../I2PTunnel.cpp \
|
|
||||||
../../Identity.cpp \
|
|
||||||
../../LeaseSet.cpp \
|
|
||||||
../../Log.cpp \
|
|
||||||
../../NetDb.cpp \
|
|
||||||
../../NetDbRequests.cpp \
|
|
||||||
../../NTCPSession.cpp \
|
|
||||||
../../Profiling.cpp \
|
|
||||||
../../Reseed.cpp \
|
|
||||||
../../RouterContext.cpp \
|
|
||||||
../../RouterInfo.cpp \
|
|
||||||
../../SAM.cpp \
|
|
||||||
../../Signature.cpp \
|
|
||||||
../../SOCKS.cpp \
|
|
||||||
../../SSU.cpp \
|
|
||||||
../../SSUData.cpp \
|
|
||||||
../../SSUSession.cpp \
|
|
||||||
../../Streaming.cpp \
|
|
||||||
../../TransitTunnel.cpp \
|
|
||||||
../../Transports.cpp \
|
|
||||||
../../Tunnel.cpp \
|
|
||||||
../../TunnelEndpoint.cpp \
|
|
||||||
../../TunnelGateway.cpp \
|
|
||||||
../../TunnelPool.cpp \
|
|
||||||
../../util.cpp \
|
|
||||||
../../i2pd.cpp \
|
|
||||||
$$IFADDRS_PATH/ifaddrs.c
|
|
||||||
|
|
||||||
HEADERS += DaemonQT.h mainwindow.h \
|
HEADERS += DaemonQT.h mainwindow.h \
|
||||||
../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \
|
../../HTTPServer.h ../../I2PControl.h ../../UPnP.h ../../Daemon.h ../../Config.h \
|
||||||
../../AddressBook.h \
|
../../AddressBook.h ../../api.h ../../Base.h ../../BOB.h ../../ClientContext.h \
|
||||||
../../api.h \
|
../../Crypto.h ../../Datagram.h ../../Destination.h ../../Family.h ../../FS.h \
|
||||||
../../Base.h \
|
../../Garlic.h ../../HTTP.h ../../HTTPProxy.h ../../I2CP.h ../../I2NPProtocol.h \
|
||||||
../../BOB.h \
|
../../I2PEndian.h ../../I2PService.h ../../I2PTunnel.h ../../Identity.h ../../LeaseSet.h \
|
||||||
../../ClientContext.h \
|
../../LittleBigEndian.h ../../Log.h ../../NetDb.h ../../NetDbRequests.h ../../NTCPSession.h \
|
||||||
../../Crypto.h \
|
../../Profiling.h ../../Queue.h ../../Reseed.h ../../RouterContext.h ../../RouterInfo.h \
|
||||||
../../Datagram.h \
|
../../SAM.h ../../Signature.h ../../SOCKS.h ../../SSU.h ../../SSUData.h ../../SSUSession.h \
|
||||||
../../Destination.h \
|
../../Streaming.h ../../Timestamp.h ../../TransitTunnel.h ../../Transports.h \
|
||||||
../../Family.h \
|
../../TransportSession.h ../../Tunnel.h ../../TunnelBase.h ../../TunnelConfig.h \
|
||||||
../../FS.h \
|
../../TunnelEndpoint.h ../../TunnelGateway.h ../../TunnelPool.h ../../UPnP.h \
|
||||||
../../Garlic.h \
|
../../util.h ../../version.h ..//../Gzip.h ../../Tag.h
|
||||||
../../HTTP.h \
|
|
||||||
../../HTTPProxy.h \
|
|
||||||
../../I2CP.h \
|
|
||||||
../../I2NPProtocol.h \
|
|
||||||
../../I2PEndian.h \
|
|
||||||
../../I2PService.h \
|
|
||||||
../../I2PTunnel.h \
|
|
||||||
../../Identity.h \
|
|
||||||
../../LeaseSet.h \
|
|
||||||
../../LittleBigEndian.h \
|
|
||||||
../../Log.h \
|
|
||||||
../../NetDb.h \
|
|
||||||
../../NetDbRequests.h \
|
|
||||||
../../NTCPSession.h \
|
|
||||||
../../Profiling.h \
|
|
||||||
../../Queue.h \
|
|
||||||
../../Reseed.h \
|
|
||||||
../../RouterContext.h \
|
|
||||||
../../RouterInfo.h \
|
|
||||||
../../SAM.h \
|
|
||||||
../../Signature.h \
|
|
||||||
../../SOCKS.h \
|
|
||||||
../../SSU.h \
|
|
||||||
../../SSUData.h \
|
|
||||||
../../SSUSession.h \
|
|
||||||
../../Streaming.h \
|
|
||||||
../../Timestamp.h \
|
|
||||||
../../TransitTunnel.h \
|
|
||||||
../../Transports.h \
|
|
||||||
../../TransportSession.h \
|
|
||||||
../../Tunnel.h \
|
|
||||||
../../TunnelBase.h \
|
|
||||||
../../TunnelConfig.h \
|
|
||||||
../../TunnelEndpoint.h \
|
|
||||||
../../TunnelGateway.h \
|
|
||||||
../../TunnelPool.h \
|
|
||||||
../../util.h \
|
|
||||||
../../version.h \
|
|
||||||
$$IFADDRS_PATH/ifaddrs.h
|
|
||||||
|
|
||||||
FORMS += mainwindow.ui
|
FORMS += mainwindow.ui
|
||||||
|
|
||||||
CONFIG += mobility
|
CONFIG += mobility
|
||||||
|
|
||||||
MOBILITY =
|
MOBILITY =
|
||||||
|
|
||||||
LIBS += -lz
|
LIBS += -lz
|
||||||
|
|
||||||
android {
|
android {
|
||||||
message("Using Android settings")
|
message("Using Android settings")
|
||||||
DEFINES += ANDROID=1
|
DEFINES += ANDROID=1
|
||||||
DEFINES += __ANDROID__
|
DEFINES += __ANDROID__
|
||||||
INCLUDEPATH += $$BOOST_PATH/boost_1_53_0/include \
|
|
||||||
$$OPENSSL_PATH/openssl-1.0.2/include \
|
|
||||||
$$IFADDRS_PATH
|
|
||||||
DISTFILES += \
|
|
||||||
android/AndroidManifest.xml
|
|
||||||
|
|
||||||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
INCLUDEPATH += $$BOOST_PATH/boost_1_53_0/include \
|
||||||
|
$$OPENSSL_PATH/openssl-1.0.2/include \
|
||||||
|
$$MINIUPNP_PATH/miniupnp-2.0/include \
|
||||||
|
$$IFADDRS_PATH
|
||||||
|
DISTFILES += android/AndroidManifest.xml
|
||||||
|
|
||||||
equals(ANDROID_TARGET_ARCH, armeabi-v7a){
|
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
||||||
|
|
||||||
DEFINES += ANDROID_ARM7A
|
SOURCES += $$IFADDRS_PATH/ifaddrs.c
|
||||||
|
HEADERS += $$IFADDRS_PATH/ifaddrs.h
|
||||||
|
|
||||||
# http://stackoverflow.com/a/30235934/529442
|
equals(ANDROID_TARGET_ARCH, armeabi-v7a){
|
||||||
LIBS += -L$$BOOST_PATH/boost_1_53_0/armeabi-v7a/lib \
|
DEFINES += ANDROID_ARM7A
|
||||||
-lboost_system-gcc-mt-1_53 \
|
# http://stackoverflow.com/a/30235934/529442
|
||||||
-lboost_date_time-gcc-mt-1_53 \
|
LIBS += -L$$BOOST_PATH/boost_1_53_0/armeabi-v7a/lib \
|
||||||
-lboost_filesystem-gcc-mt-1_53 \
|
-lboost_system-gcc-mt-1_53 -lboost_date_time-gcc-mt-1_53 \
|
||||||
-lboost_program_options-gcc-mt-1_53 \
|
-lboost_filesystem-gcc-mt-1_53 -lboost_program_options-gcc-mt-1_53 \
|
||||||
-L$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/ -lcrypto -lssl
|
-L$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/ -lcrypto -lssl \
|
||||||
|
-L$$MINIUPNP_PATH/miniupnp-2.0/armeabi-v7a/lib/ -lminiupnpc
|
||||||
|
|
||||||
PRE_TARGETDEPS += $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libcrypto.a \
|
PRE_TARGETDEPS += $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libcrypto.a \
|
||||||
$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libssl.a
|
$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libssl.a
|
||||||
|
DEPENDPATH += $$OPENSSL_PATH/openssl-1.0.2/include
|
||||||
|
|
||||||
DEPENDPATH += $$OPENSSL_PATH/openssl-1.0.2/include
|
ANDROID_EXTRA_LIBS += $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libcrypto_1_0_0.so \
|
||||||
|
$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libssl_1_0_0.so \
|
||||||
|
$$MINIUPNP_PATH/miniupnp-2.0/armeabi-v7a/lib/libminiupnpc.so
|
||||||
|
}
|
||||||
|
|
||||||
ANDROID_EXTRA_LIBS += $$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libcrypto_1_0_0.so \
|
equals(ANDROID_TARGET_ARCH, x86){
|
||||||
$$OPENSSL_PATH/openssl-1.0.2/armeabi-v7a/lib/libssl_1_0_0.so
|
# http://stackoverflow.com/a/30235934/529442
|
||||||
}
|
LIBS += -L$$BOOST_PATH/boost_1_53_0/x86/lib \
|
||||||
equals(ANDROID_TARGET_ARCH, x86){
|
-lboost_system-gcc-mt-1_53 -lboost_date_time-gcc-mt-1_53 \
|
||||||
# http://stackoverflow.com/a/30235934/529442
|
-lboost_filesystem-gcc-mt-1_53 -lboost_program_options-gcc-mt-1_53 \
|
||||||
LIBS += -L$$BOOST_PATH/boost_1_53_0/x86/lib \
|
-L$$OPENSSL_PATH/openssl-1.0.2/x86/lib/ -lcrypto -lssl \
|
||||||
-lboost_system-gcc-mt-1_53 \
|
-L$$MINIUPNP_PATH/miniupnp-2.0/x86/lib/ -lminiupnpc
|
||||||
-lboost_date_time-gcc-mt-1_53 \
|
|
||||||
-lboost_filesystem-gcc-mt-1_53 \
|
|
||||||
-lboost_program_options-gcc-mt-1_53 \
|
|
||||||
-L$$OPENSSL_PATH/openssl-1.0.2/x86/lib/ -lcrypto -lssl
|
|
||||||
|
|
||||||
PRE_TARGETDEPS += $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libcrypto.a \
|
PRE_TARGETDEPS += $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libcrypto.a \
|
||||||
$$OPENSSL_PATH/openssl-1.0.2/x86/lib/libssl.a
|
$$OPENSSL_PATH/openssl-1.0.2/x86/lib/libssl.a
|
||||||
|
|
||||||
DEPENDPATH += $$OPENSSL_PATH/openssl-1.0.2/include
|
DEPENDPATH += $$OPENSSL_PATH/openssl-1.0.2/include
|
||||||
|
|
||||||
ANDROID_EXTRA_LIBS += $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libcrypto_1_0_0.so \
|
ANDROID_EXTRA_LIBS += $$OPENSSL_PATH/openssl-1.0.2/x86/lib/libcrypto_1_0_0.so \
|
||||||
$$OPENSSL_PATH/openssl-1.0.2/x86/lib/libssl_1_0_0.so
|
$$OPENSSL_PATH/openssl-1.0.2/x86/lib/libssl_1_0_0.so \
|
||||||
}
|
$$MINIUPNP_PATH/miniupnp-2.0/x86/lib/libminiupnpc.so
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
linux:!android {
|
linux:!android {
|
||||||
message("Using Linux settings")
|
message("Using Linux settings")
|
||||||
LIBS += -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
|
LIBS += -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread -lminiupnpc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
!android:!symbian:!maemo5:!simulator {
|
||||||
|
message("Build with a system tray icon")
|
||||||
|
# see also http://doc.qt.io/qt-4.8/qt-desktop-systray-systray-pro.html for example on wince*
|
||||||
|
#sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS i2pd_qt.pro resources images
|
||||||
|
RESOURCES = i2pd.qrc
|
||||||
|
QT += xml
|
||||||
|
#INSTALLS += sources
|
||||||
|
}
|
||||||
|
BIN
qt/i2pd_qt/images/icon.png
Normal file
BIN
qt/i2pd_qt/images/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
@ -1,10 +1,19 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
//#include "ui_mainwindow.h"
|
//#include "ui_mainwindow.h"
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QTimer>
|
||||||
|
#include "../../RouterContext.h"
|
||||||
|
#ifndef ANDROID
|
||||||
|
#include <QtDebug>
|
||||||
|
#endif
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) :
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
QMainWindow(parent)/*,
|
QMainWindow(parent)/*,
|
||||||
ui(new Ui::MainWindow)*/
|
ui(new Ui::MainWindow)*/
|
||||||
|
#ifndef ANDROID
|
||||||
|
,
|
||||||
|
quitting(false)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
//ui->setupUi(this);
|
//ui->setupUi(this);
|
||||||
if (objectName().isEmpty())
|
if (objectName().isEmpty())
|
||||||
@ -22,30 +31,132 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
verticalLayout1->setContentsMargins(0, 0, 0, 0);
|
verticalLayout1->setContentsMargins(0, 0, 0, 0);
|
||||||
quitButton = new QPushButton(verticalLayoutWidget);
|
quitButton = new QPushButton(verticalLayoutWidget);
|
||||||
quitButton->setObjectName(QStringLiteral("quitButton"));
|
quitButton->setObjectName(QStringLiteral("quitButton"));
|
||||||
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||||
sizePolicy.setHorizontalStretch(0);
|
sizePolicy.setHorizontalStretch(1);
|
||||||
sizePolicy.setVerticalStretch(0);
|
//sizePolicy.setVerticalStretch(1);
|
||||||
sizePolicy.setHeightForWidth(quitButton->sizePolicy().hasHeightForWidth());
|
sizePolicy.setHeightForWidth(quitButton->sizePolicy().hasHeightForWidth());
|
||||||
quitButton->setSizePolicy(sizePolicy);
|
quitButton->setSizePolicy(sizePolicy);
|
||||||
|
|
||||||
verticalLayout1->addWidget(quitButton);
|
verticalLayout1->addWidget(quitButton);
|
||||||
|
gracefulQuitButton = new QPushButton(verticalLayoutWidget);
|
||||||
|
gracefulQuitButton->setObjectName(QStringLiteral("gracefulQuitButton"));
|
||||||
|
QSizePolicy sizePolicy2(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||||
|
sizePolicy2.setHorizontalStretch(1);
|
||||||
|
//sizePolicy2.setVerticalStretch(1);
|
||||||
|
sizePolicy2.setHeightForWidth(gracefulQuitButton->sizePolicy().hasHeightForWidth());
|
||||||
|
gracefulQuitButton->setSizePolicy(sizePolicy2);
|
||||||
|
verticalLayout1->addWidget(gracefulQuitButton);
|
||||||
|
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0));
|
setWindowTitle(QApplication::translate("MainWindow", "i2pd", 0));
|
||||||
quitButton->setText(QApplication::translate("MainWindow", "Quit", 0));
|
quitButton->setText(QApplication::translate("MainWindow", "Quit", 0));
|
||||||
|
gracefulQuitButton->setText(QApplication::translate("MainWindow", "Graceful Quit", 0));
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
createActions();
|
||||||
|
createTrayIcon();
|
||||||
|
#endif
|
||||||
|
|
||||||
QObject::connect(quitButton, SIGNAL(released()), this, SLOT(handleQuitButton()));
|
QObject::connect(quitButton, SIGNAL(released()), this, SLOT(handleQuitButton()));
|
||||||
|
QObject::connect(gracefulQuitButton, SIGNAL(released()), this, SLOT(handleGracefulQuitButton()));
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
QObject::connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||||
|
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
|
||||||
|
|
||||||
|
setIcon();
|
||||||
|
trayIcon->show();
|
||||||
|
#endif
|
||||||
|
|
||||||
//QMetaObject::connectSlotsByName(this);
|
//QMetaObject::connectSlotsByName(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
void MainWindow::createActions() {
|
||||||
|
toggleWindowVisibleAction = new QAction(tr("&Toggle the window"), this);
|
||||||
|
connect(toggleWindowVisibleAction, SIGNAL(triggered()), this, SLOT(toggleVisibilitySlot()));
|
||||||
|
|
||||||
|
//quitAction = new QAction(tr("&Quit"), this);
|
||||||
|
//connect(quitAction, SIGNAL(triggered()), QApplication::instance(), SLOT(quit()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::toggleVisibilitySlot() {
|
||||||
|
setVisible(!isVisible());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::createTrayIcon() {
|
||||||
|
trayIconMenu = new QMenu(this);
|
||||||
|
trayIconMenu->addAction(toggleWindowVisibleAction);
|
||||||
|
//trayIconMenu->addSeparator();
|
||||||
|
//trayIconMenu->addAction(quitAction);
|
||||||
|
|
||||||
|
trayIcon = new QSystemTrayIcon(this);
|
||||||
|
trayIcon->setContextMenu(trayIconMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setIcon() {
|
||||||
|
QIcon icon(":/images/icon.png");
|
||||||
|
trayIcon->setIcon(icon);
|
||||||
|
setWindowIcon(icon);
|
||||||
|
|
||||||
|
trayIcon->setToolTip(QApplication::translate("MainWindow", "i2pd", 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) {
|
||||||
|
switch (reason) {
|
||||||
|
case QSystemTrayIcon::Trigger:
|
||||||
|
case QSystemTrayIcon::DoubleClick:
|
||||||
|
case QSystemTrayIcon::MiddleClick:
|
||||||
|
setVisible(!isVisible());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qDebug() << "MainWindow::iconActivated(): unknown reason: " << reason << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||||
|
if(quitting){ QMainWindow::closeEvent(event); return; }
|
||||||
|
if (trayIcon->isVisible()) {
|
||||||
|
QMessageBox::information(this, tr("i2pd"),
|
||||||
|
tr("The program will keep running in the "
|
||||||
|
"system tray. To gracefully terminate the program, "
|
||||||
|
"choose <b>Graceful Quit</b> at the main i2pd window."));
|
||||||
|
hide();
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void MainWindow::handleQuitButton() {
|
void MainWindow::handleQuitButton() {
|
||||||
qDebug("Quit pressed. Hiding the main window");
|
qDebug("Quit pressed. Hiding the main window");
|
||||||
|
#ifndef ANDROID
|
||||||
|
quitting=true;
|
||||||
|
#endif
|
||||||
close();
|
close();
|
||||||
QApplication::instance()->quit();
|
QApplication::instance()->quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::handleGracefulQuitButton() {
|
||||||
|
qDebug("Graceful Quit pressed.");
|
||||||
|
gracefulQuitButton->setText(QApplication::translate("MainWindow", "Graceful quit is in progress", 0));
|
||||||
|
gracefulQuitButton->setEnabled(false);
|
||||||
|
gracefulQuitButton->adjustSize();
|
||||||
|
verticalLayoutWidget->adjustSize();
|
||||||
|
i2p::context.SetAcceptsTunnels (false); // stop accpting tunnels
|
||||||
|
QTimer::singleShot(10*60*1000/*millis*/, this, SLOT(handleGracefulQuitTimerEvent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::handleGracefulQuitTimerEvent() {
|
||||||
|
qDebug("Hiding the main window");
|
||||||
|
#ifndef ANDROID
|
||||||
|
quitting=true;
|
||||||
|
#endif
|
||||||
|
close();
|
||||||
|
qDebug("Performing quit");
|
||||||
|
QApplication::instance()->quit();
|
||||||
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
qDebug("Destroying main window");
|
qDebug("Destroying main window");
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
#include <QtWidgets/QPushButton>
|
#include <QtWidgets/QPushButton>
|
||||||
#include <QtWidgets/QVBoxLayout>
|
#include <QtWidgets/QVBoxLayout>
|
||||||
#include <QtWidgets/QWidget>
|
#include <QtWidgets/QWidget>
|
||||||
|
#ifndef ANDROID
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
#include <QMenu>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
@ -25,14 +30,43 @@ public:
|
|||||||
explicit MainWindow(QWidget *parent = 0);
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
//#ifndef ANDROID
|
||||||
|
// void setVisible(bool visible);
|
||||||
|
//#endif
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleQuitButton();
|
void handleQuitButton();
|
||||||
|
void handleGracefulQuitButton();
|
||||||
|
void handleGracefulQuitTimerEvent();
|
||||||
|
#ifndef ANDROID
|
||||||
|
void setIcon();
|
||||||
|
void iconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||||
|
void toggleVisibilitySlot();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifndef ANDROID
|
||||||
|
void createActions();
|
||||||
|
void createTrayIcon();
|
||||||
|
#endif
|
||||||
|
|
||||||
QWidget *centralWidget;
|
QWidget *centralWidget;
|
||||||
QWidget *verticalLayoutWidget;
|
QWidget *verticalLayoutWidget;
|
||||||
QVBoxLayout *verticalLayout1;
|
QVBoxLayout *verticalLayout1;
|
||||||
QPushButton *quitButton;
|
QPushButton *quitButton;
|
||||||
|
QPushButton *gracefulQuitButton;
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
bool quitting;
|
||||||
|
QAction *toggleWindowVisibleAction;
|
||||||
|
QSystemTrayIcon *trayIcon;
|
||||||
|
QMenu *trayIconMenu;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#ifndef ANDROID
|
||||||
|
void closeEvent(QCloseEvent *event);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
@ -37,6 +37,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="gracefulShutdownButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Graceful Quit</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
@ -60,8 +67,25 @@
|
|||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>gracefulShutdownButton</sender>
|
||||||
|
<signal>released()</signal>
|
||||||
|
<receiver>MainWindow</receiver>
|
||||||
|
<slot>handleGracefulQuitButton()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>395</x>
|
||||||
|
<y>319</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>399</x>
|
||||||
|
<y>239</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
</connections>
|
</connections>
|
||||||
<slots>
|
<slots>
|
||||||
<slot>handleQuitButton()</slot>
|
<slot>handleQuitButton()</slot>
|
||||||
|
<slot>handleGracefulQuitButton()</slot>
|
||||||
</slots>
|
</slots>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
CXXFLAGS += -Wall -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
|
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
|
test-http-merge_chunked test-base-64
|
||||||
|
|
||||||
all: $(TESTS) run
|
all: $(TESTS) run
|
||||||
|
|
||||||
test-http-%: test-http-%.cpp ../HTTP.cpp
|
test-http-%: ../HTTP.cpp test-http-%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
test-base-%: ../Base.cpp test-base-%.cpp
|
||||||
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^
|
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -o $@ $^
|
||||||
|
|
||||||
run: $(TESTS)
|
run: $(TESTS)
|
||||||
|
45
tests/test-base-64.cpp
Normal file
45
tests/test-base-64.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <cassert>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../Base.h"
|
||||||
|
|
||||||
|
using namespace i2p::data;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
const char *in = "test";
|
||||||
|
size_t in_len = strlen(in);
|
||||||
|
char out[16];
|
||||||
|
|
||||||
|
/* bytes -> b64 */
|
||||||
|
assert(ByteStreamToBase64(NULL, 0, NULL, 0) == 0);
|
||||||
|
assert(ByteStreamToBase64(NULL, 0, out, sizeof(out)) == 0);
|
||||||
|
|
||||||
|
assert(Base64EncodingBufferSize(2) == 4);
|
||||||
|
assert(Base64EncodingBufferSize(4) == 8);
|
||||||
|
assert(Base64EncodingBufferSize(6) == 8);
|
||||||
|
assert(Base64EncodingBufferSize(7) == 12);
|
||||||
|
assert(Base64EncodingBufferSize(9) == 12);
|
||||||
|
assert(Base64EncodingBufferSize(10) == 16);
|
||||||
|
assert(Base64EncodingBufferSize(12) == 16);
|
||||||
|
assert(Base64EncodingBufferSize(13) == 20);
|
||||||
|
|
||||||
|
assert(ByteStreamToBase64((uint8_t *) in, in_len, out, sizeof(out)) == 8);
|
||||||
|
assert(memcmp(out, "dGVzdA==", 8) == 0);
|
||||||
|
|
||||||
|
/* b64 -> bytes */
|
||||||
|
assert(Base64ToByteStream(NULL, 0, NULL, 0) == 0);
|
||||||
|
assert(Base64ToByteStream(NULL, 0, (uint8_t *) out, sizeof(out)) == 0);
|
||||||
|
|
||||||
|
in = "dGVzdA=="; /* valid b64 */
|
||||||
|
assert(Base64ToByteStream(in, strlen(in), (uint8_t *) out, sizeof(out)) == 4);
|
||||||
|
assert(memcmp(out, "test", 4) == 0);
|
||||||
|
|
||||||
|
in = "dGVzdA="; /* invalid b64 : not padded */
|
||||||
|
assert(Base64ToByteStream(in, strlen(in), (uint8_t *) out, sizeof(out)) == 0);
|
||||||
|
|
||||||
|
in = "dG/z.A=="; /* invalid b64 : char not from alphabet */
|
||||||
|
// assert(Base64ToByteStream(in, strlen(in), (uint8_t *) out, sizeof(out)) == 0);
|
||||||
|
// ^^^ fails, current implementation not checks acceptable symbols
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -22,7 +22,6 @@ int main() {
|
|||||||
assert(req->version == "HTTP/1.0");
|
assert(req->version == "HTTP/1.0");
|
||||||
assert(req->method == "GET");
|
assert(req->method == "GET");
|
||||||
assert(req->uri == "/");
|
assert(req->uri == "/");
|
||||||
assert(req->host == "inr.i2p");
|
|
||||||
assert(req->headers.size() == 3);
|
assert(req->headers.size() == 3);
|
||||||
assert(req->headers.count("Host") == 1);
|
assert(req->headers.count("Host") == 1);
|
||||||
assert(req->headers.count("Accept") == 1);
|
assert(req->headers.count("Accept") == 1);
|
||||||
@ -42,7 +41,6 @@ int main() {
|
|||||||
assert(req->version == "HTTP/1.0");
|
assert(req->version == "HTTP/1.0");
|
||||||
assert(req->method == "GET");
|
assert(req->method == "GET");
|
||||||
assert(req->uri == "/");
|
assert(req->uri == "/");
|
||||||
assert(req->host == "");
|
|
||||||
assert(req->headers.size() == 0);
|
assert(req->headers.size() == 0);
|
||||||
delete req;
|
delete req;
|
||||||
|
|
||||||
@ -52,7 +50,7 @@ int main() {
|
|||||||
"\r\n";
|
"\r\n";
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
req = new HTTPReq;
|
req = new HTTPReq;
|
||||||
assert((ret = req->parse(buf, len)) == -1); /* no host header */
|
assert((ret = req->parse(buf, len)) > 0);
|
||||||
delete req;
|
delete req;
|
||||||
|
|
||||||
/* test: parsing incomplete request */
|
/* test: parsing incomplete request */
|
||||||
@ -76,7 +74,6 @@ int main() {
|
|||||||
assert((ret = req->parse(buf, len)) == len); /* no host header */
|
assert((ret = req->parse(buf, len)) == len); /* no host header */
|
||||||
assert(req->method == "GET");
|
assert(req->method == "GET");
|
||||||
assert(req->uri == "http://inr.i2p");
|
assert(req->uri == "http://inr.i2p");
|
||||||
assert(req->host == "stats.i2p");
|
|
||||||
assert(req->headers.size() == 3);
|
assert(req->headers.size() == 3);
|
||||||
assert(req->headers.count("Host") == 1);
|
assert(req->headers.count("Host") == 1);
|
||||||
assert(req->headers.count("Accept") == 1);
|
assert(req->headers.count("Accept") == 1);
|
||||||
|
@ -29,7 +29,7 @@ int main() {
|
|||||||
assert(res->headers.find("Server")->second == "nginx/1.2.1");
|
assert(res->headers.find("Server")->second == "nginx/1.2.1");
|
||||||
assert(res->headers.find("Content-Length")->second == "536");
|
assert(res->headers.find("Content-Length")->second == "536");
|
||||||
assert(res->is_chunked() == false);
|
assert(res->is_chunked() == false);
|
||||||
assert(res->length() == 536);
|
assert(res->content_length() == 536);
|
||||||
delete res;
|
delete res;
|
||||||
|
|
||||||
/* test: building request */
|
/* test: building request */
|
||||||
|
Loading…
Reference in New Issue
Block a user