From c994c11d8c82d3ee8809d28d48167215c0c3e8b6 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 01/69] * HTTPProxy.{cpp,h} : rename classes, drop typedef --- HTTPProxy.cpp | 65 ++++++++++++++++++++++++--------------------------- HTTPProxy.h | 18 ++++++-------- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index f681f365..6915274c 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -21,12 +21,10 @@ #include "I2PTunnel.h" #include "Config.h" -namespace i2p -{ -namespace proxy -{ +namespace i2p { +namespace proxy { static const size_t http_buffer_size = 8192; - class HTTPProxyHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this + class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: enum state @@ -67,26 +65,26 @@ namespace proxy public: - HTTPProxyHandler(HTTPProxyServer * parent, std::shared_ptr sock) : + HTTPReqHandler(HTTPProxy * parent, std::shared_ptr sock) : I2PServiceHandler(parent), m_sock(sock) { EnterState(GET_METHOD); } - ~HTTPProxyHandler() { Terminate(); } + ~HTTPReqHandler() { Terminate(); } void Handle () { AsyncSockRead(); } }; - void HTTPProxyHandler::AsyncSockRead() + void HTTPReqHandler::AsyncSockRead() { LogPrint(eLogDebug, "HTTPProxy: async sock read"); if(m_sock) { m_sock->async_receive(boost::asio::buffer(m_http_buff, http_buffer_size), - std::bind(&HTTPProxyHandler::HandleSockRecv, shared_from_this(), + std::bind(&HTTPReqHandler::HandleSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else { LogPrint(eLogError, "HTTPProxy: no socket for read"); } } - void HTTPProxyHandler::Terminate() { + void HTTPReqHandler::Terminate() { if (Kill()) return; if (m_sock) { @@ -99,7 +97,7 @@ namespace proxy /* All hope is lost beyond this point */ //TODO: handle this apropriately - void HTTPProxyHandler::HTTPRequestFailed(const char *message) + void HTTPReqHandler::HTTPRequestFailed(const char *message) { std::size_t size = std::strlen(message); std::stringstream ss; @@ -108,29 +106,28 @@ namespace proxy ss << "Content-Length: " << std::to_string(size + 2) << "\r\n" << "\r\n"; /* end of headers */ ss << message << "\r\n"; - m_Response = ss.str(); - boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response), - std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); + std::string response = ss.str(); + boost::asio::async_write(*m_sock, boost::asio::buffer(response, response.size()), + std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - void HTTPProxyHandler::RedirectToJumpService(/*HTTPProxyHandler::errTypes error*/) + void HTTPReqHandler::RedirectToJumpService(/*HTTPReqHandler::errTypes error*/) { std::stringstream response; std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); response << "HTTP/1.1 302 Found\r\nLocation: http://" << httpAddr << ":" << httpPort << "/?page=jumpservices&address=" << m_address << "\r\n\r\n"; - m_Response = response.str (); - boost::asio::async_write(*m_sock, boost::asio::buffer(m_Response), - std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); + boost::asio::async_write(*m_sock, boost::asio::buffer(response.str (),response.str ().length ()), + 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; } - void HTTPProxyHandler::ExtractRequest() + void HTTPReqHandler::ExtractRequest() { LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url); std::string server=""; @@ -150,7 +147,7 @@ namespace proxy m_path = path; } - bool HTTPProxyHandler::ValidateHTTPRequest() + bool HTTPReqHandler::ValidateHTTPRequest() { if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" ) { @@ -161,7 +158,7 @@ namespace proxy return true; } - void HTTPProxyHandler::HandleJumpServices() + void HTTPReqHandler::HandleJumpServices() { static const char * helpermark1 = "?i2paddresshelper="; static const char * helpermark2 = "&i2paddresshelper="; @@ -193,7 +190,7 @@ namespace proxy m_path.erase(addressHelperPos); } - bool HTTPProxyHandler::IsI2PAddress() + bool HTTPReqHandler::IsI2PAddress() { auto pos = m_address.rfind (".i2p"); if (pos != std::string::npos && (pos+4) == m_address.length ()) @@ -203,7 +200,7 @@ namespace proxy return false; } - bool HTTPProxyHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) + bool HTTPReqHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) { ExtractRequest(); //TODO: parse earlier if (!ValidateHTTPRequest()) return false; @@ -258,7 +255,7 @@ namespace proxy 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) { @@ -309,7 +306,7 @@ namespace proxy 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"); if(ecode) @@ -324,7 +321,7 @@ namespace proxy if (m_state == DONE) { 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); } else @@ -333,14 +330,14 @@ namespace proxy } - void HTTPProxyHandler::SentHTTPFailed(const boost::system::error_code & ecode) + void HTTPReqHandler::SentHTTPFailed(const boost::system::error_code & ecode) { if (ecode) LogPrint (eLogError, "HTTPProxy: Closing socket after sending failure because: ", ecode.message ()); Terminate(); } - void HTTPProxyHandler::HandleStreamRequestComplete (std::shared_ptr stream) + void HTTPReqHandler::HandleStreamRequestComplete (std::shared_ptr stream) { if (stream) { @@ -358,14 +355,14 @@ namespace proxy } } - HTTPProxyServer::HTTPProxyServer(const std::string& address, int port, std::shared_ptr localDestination): + HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination): TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) { } - std::shared_ptr HTTPProxyServer::CreateHandler(std::shared_ptr socket) + std::shared_ptr HTTPProxy::CreateHandler(std::shared_ptr socket) { - return std::make_shared (this, socket); + return std::make_shared (this, socket); } -} -} +} // http +} // i2p diff --git a/HTTPProxy.h b/HTTPProxy.h index 0356adb5..29b997eb 100644 --- a/HTTPProxy.h +++ b/HTTPProxy.h @@ -1,25 +1,21 @@ #ifndef HTTP_PROXY_H__ #define HTTP_PROXY_H__ -namespace i2p -{ -namespace proxy -{ - class HTTPProxyServer: public i2p::client::TCPIPAcceptor +namespace i2p { +namespace proxy { + class HTTPProxy: public i2p::client::TCPIPAcceptor { public: - HTTPProxyServer(const std::string& address, int port, std::shared_ptr localDestination = nullptr); - ~HTTPProxyServer() {}; + HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination = nullptr); + ~HTTPProxy() {}; protected: // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); const char* GetName() { return "HTTP Proxy"; } }; - - typedef HTTPProxyServer HTTPProxy; -} -} +} // http +} // i2p #endif From 61868d97c4d3f3ab15aa1ff2b8f6a5f413cc6720 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 02/69] * HTTPProxy.cpp : migrate HTTPRequestFailed(), RedirectToJumpService() to new http classes --- HTTPProxy.cpp | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 6915274c..06753b78 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -20,6 +20,7 @@ #include "I2PEndian.h" #include "I2PTunnel.h" #include "Config.h" +#include "HTTP.h" namespace i2p { namespace proxy { @@ -42,7 +43,7 @@ namespace proxy { void Terminate(); void AsyncSockRead(); void HTTPRequestFailed(const char *message); - void RedirectToJumpService(); + void RedirectToJumpService(std::string & host); void ExtractRequest(); bool IsI2PAddress(); bool ValidateHTTPRequest(); @@ -99,26 +100,33 @@ namespace proxy { //TODO: handle this apropriately void HTTPReqHandler::HTTPRequestFailed(const char *message) { - std::size_t size = std::strlen(message); - std::stringstream ss; - ss << "HTTP/1.0 500 Internal Server Error\r\n" - << "Content-Type: text/plain\r\n"; - ss << "Content-Length: " << std::to_string(size + 2) << "\r\n" - << "\r\n"; /* end of headers */ - ss << message << "\r\n"; - std::string response = ss.str(); + i2p::http::HTTPRes res; + res.code = 500; + 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, response.size()), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - void HTTPReqHandler::RedirectToJumpService(/*HTTPReqHandler::errTypes error*/) + void HTTPReqHandler::RedirectToJumpService(std::string & host) { - std::stringstream response; - std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); - uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); + i2p::http::HTTPRes res; + i2p::http::URL url; - response << "HTTP/1.1 302 Found\r\nLocation: http://" << httpAddr << ":" << httpPort << "/?page=jumpservices&address=" << m_address << "\r\n\r\n"; - boost::asio::async_write(*m_sock, boost::asio::buffer(response.str (),response.str ().length ()), + i2p::config::GetOption("http.address", url.host); + 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, response.length()), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } @@ -210,7 +218,7 @@ namespace proxy { if (IsI2PAddress ()) { if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){ - RedirectToJumpService(); + RedirectToJumpService(m_address); return false; } } From 0de1e2c6fc6b8592b9db4a3c27751ec28e5e242b Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 03/69] * HTTPProxy.cpp : extract IsI2PAddress() from class and generalize --- HTTPProxy.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 06753b78..cbbd66c4 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -24,6 +24,15 @@ namespace i2p { 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; class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { @@ -45,7 +54,6 @@ namespace proxy { void HTTPRequestFailed(const char *message); void RedirectToJumpService(std::string & host); void ExtractRequest(); - bool IsI2PAddress(); bool ValidateHTTPRequest(); void HandleJumpServices(); bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); @@ -198,16 +206,6 @@ namespace proxy { m_path.erase(addressHelperPos); } - bool HTTPReqHandler::IsI2PAddress() - { - auto pos = m_address.rfind (".i2p"); - if (pos != std::string::npos && (pos+4) == m_address.length ()) - { - return true; - } - return false; - } - bool HTTPReqHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) { ExtractRequest(); //TODO: parse earlier @@ -215,14 +213,13 @@ namespace proxy { HandleJumpServices(); i2p::data::IdentHash identHash; - if (IsI2PAddress ()) + if (str_rmatch(m_address, ".i2p")) { if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){ RedirectToJumpService(m_address); return false; } } - m_request = m_method; m_request.push_back(' '); @@ -335,7 +332,6 @@ namespace proxy { else AsyncSockRead(); } - } void HTTPReqHandler::SentHTTPFailed(const boost::system::error_code & ecode) From 2bf32fb3fadd82ccefaf4bdb7e664d42f51e797d Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 04/69] * HTTPProxy.cpp : kill ExtractRequest(), drop boost::regex --- HTTPProxy.cpp | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index cbbd66c4..2001f620 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -1,7 +1,5 @@ #include #include -#include -#include #include #include #include @@ -53,7 +51,6 @@ namespace proxy { void AsyncSockRead(); void HTTPRequestFailed(const char *message); void RedirectToJumpService(std::string & host); - void ExtractRequest(); bool ValidateHTTPRequest(); void HandleJumpServices(); bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); @@ -143,26 +140,6 @@ namespace proxy { m_state = nstate; } - void HTTPReqHandler::ExtractRequest() - { - LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url); - std::string server=""; - std::string port="80"; - boost::regex rHTTP("http://(.*?)(:(\\d+))?(/.*)"); - boost::smatch m; - std::string path; - if(boost::regex_search(m_url, m, rHTTP, boost::match_extra)) - { - server=m[1].str(); - if (m[2].str() != "") port=m[3].str(); - path=m[4].str(); - } - LogPrint(eLogDebug, "HTTPProxy: server: ", server, ", port: ", port, ", path: ", path); - m_address = server; - m_port = boost::lexical_cast(port); - m_path = path; - } - bool HTTPReqHandler::ValidateHTTPRequest() { if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" ) @@ -208,7 +185,11 @@ namespace proxy { bool HTTPReqHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) { - ExtractRequest(); //TODO: parse earlier + i2p::http::URL url; + url.parse(m_url); + m_address = url.host; /* < compatibility */ + m_port = url.port; /* < compatibility */ + m_path = url.path; /* < compatibility */ if (!ValidateHTTPRequest()) return false; HandleJumpServices(); From 5c9a69e0e81fdb759d91bb42c0e2ab130f631099 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 05/69] * drop boost_regex from build deps --- .travis.yml | 1 - Makefile.bsd | 2 +- Makefile.homebrew | 2 +- Makefile.linux | 3 +-- Makefile.mingw | 1 - Makefile.osx | 2 +- Reseed.cpp | 1 - appveyor.yml | 2 +- build/CMakeLists.txt | 2 +- build/Dockerfile | 2 +- debian/control | 1 - docs/build_notes_cross.md | 2 +- docs/build_notes_unix.md | 1 - docs/build_notes_windows.md | 4 ++-- stdafx.h | 1 - 15 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index c791187d..d83cdbc0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,6 @@ addons: - libboost-date-time-dev - libboost-filesystem-dev - libboost-program-options-dev - - libboost-regex-dev - libboost-system-dev - libboost-thread-dev - libminiupnpc-dev diff --git a/Makefile.bsd b/Makefile.bsd index 255233f1..d6871f07 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -9,4 +9,4 @@ CXXFLAGS = -O2 NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 INCFLAGS = -I/usr/include/ -I/usr/local/include/ LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread +LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread diff --git a/Makefile.homebrew b/Makefile.homebrew index 163b7950..6ce513fe 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -6,7 +6,7 @@ CXX = clang++ CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib -LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread +LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread ifeq ($(USE_UPNP),1) LDFLAGS += -ldl diff --git a/Makefile.linux b/Makefile.linux index 791382c6..70307267 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -32,7 +32,6 @@ ifeq ($(USE_STATIC),yes) LDLIBS = $(LIBDIR)/libboost_system.a LDLIBS += $(LIBDIR)/libboost_date_time.a LDLIBS += $(LIBDIR)/libboost_filesystem.a - LDLIBS += $(LIBDIR)/libboost_regex.a LDLIBS += $(LIBDIR)/libboost_program_options.a LDLIBS += $(LIBDIR)/libcrypto.a LDLIBS += $(LIBDIR)/libssl.a @@ -40,7 +39,7 @@ ifeq ($(USE_STATIC),yes) LDLIBS += -lpthread -static-libstdc++ -static-libgcc USE_AESNI := no else - LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread + LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread endif # UPNP Support (miniupnpc 1.5 or 1.6) diff --git a/Makefile.mingw b/Makefile.mingw index 5fe3c479..0390d66a 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -13,7 +13,6 @@ LDLIBS = \ -Wl,-Bstatic -lboost_system$(BOOST_SUFFIX) \ -Wl,-Bstatic -lboost_date_time$(BOOST_SUFFIX) \ -Wl,-Bstatic -lboost_filesystem$(BOOST_SUFFIX) \ - -Wl,-Bstatic -lboost_regex$(BOOST_SUFFIX) \ -Wl,-Bstatic -lboost_program_options$(BOOST_SUFFIX) \ -Wl,-Bstatic -lssl \ -Wl,-Bstatic -lcrypto \ diff --git a/Makefile.osx b/Makefile.osx index 71f95a7f..ef236c9a 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -3,7 +3,7 @@ CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX #CXXFLAGS = -g -O2 -Wall -std=c++11 INCFLAGS = -I/usr/local/include -I/usr/local/ssl/include LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib -L/usr/local/ssl/lib -LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_regex -lboost_program_options -lpthread +LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread ifeq ($(USE_UPNP),1) LDFLAGS += -ldl diff --git a/Reseed.cpp b/Reseed.cpp index ddefc460..6f27891d 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include diff --git a/appveyor.yml b/appveyor.yml index 6600714d..6018bea0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -125,7 +125,7 @@ install: - cd %BOOST_ROOT% - if defined msvc if not exist "stage%bitness%\lib\%boostlib%boost_system-vc%msvc%0-mt%boostdbg%*" ( bootstrap > c:\projects\instdir\build_boost.log - && b2 toolset=msvc-%msvc%.0 %boost_variant% link=%type% runtime-link=%type% address-model=%bitness% --build-type=minimal --with-filesystem --with-program_options --with-regex --with-date_time --stagedir=stage%bitness% >> c:\projects\instdir\build_boost.log + && b2 toolset=msvc-%msvc%.0 %boost_variant% link=%type% runtime-link=%type% address-model=%bitness% --build-type=minimal --with-filesystem --with-program_options --with-date_time --stagedir=stage%bitness% >> c:\projects\instdir\build_boost.log || type c:\projects\instdir\build_boost.log ) - if defined msvc if not exist C:\stage\OpenSSL-Win%bitness%-vc%msvc%-%type%\ ( diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 7944e2ec..4a1bfe2b 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -242,7 +242,7 @@ endif() target_link_libraries(i2pdclient libi2pd) -find_package ( Boost COMPONENTS system filesystem regex program_options date_time REQUIRED ) +find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED ) if(NOT DEFINED Boost_INCLUDE_DIRS) message(SEND_ERROR "Boost is not found, or your boost version was bellow 1.46. Please download Boost!") endif() diff --git a/build/Dockerfile b/build/Dockerfile index f570bd79..751fe956 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \ - libboost-program-options-dev libboost-regex-dev libboost-date-time-dev \ + libboost-program-options-dev libboost-date-time-dev \ libssl-dev git build-essential RUN git clone https://github.com/PurpleI2P/i2pd.git diff --git a/debian/control b/debian/control index ceca7a5f..78906ba4 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,6 @@ Priority: extra Maintainer: hagen Build-Depends: debhelper (>= 9.0.0), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), - libboost-regex-dev, libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, diff --git a/docs/build_notes_cross.md b/docs/build_notes_cross.md index d819ba34..78d60e6a 100644 --- a/docs/build_notes_cross.md +++ b/docs/build_notes_cross.md @@ -22,7 +22,7 @@ Proceed with building Boost normal way, but let's define dedicated staging direc ```sh ./bootstrap.sh ./b2 toolset=gcc-mingw target-os=windows variant=release link=static runtime-link=static address-model=64 \ - --build-type=minimal --with-filesystem --with-program_options --with-regex --with-date_time \ + --build-type=minimal --with-filesystem --with-program_options --with-date_time \ --stagedir=stage-mingw-64 cd .. ``` diff --git a/docs/build_notes_unix.md b/docs/build_notes_unix.md index 05605343..cdde1ee7 100644 --- a/docs/build_notes_unix.md +++ b/docs/build_notes_unix.md @@ -46,7 +46,6 @@ sudo apt-get install \ libboost-date-time-dev \ libboost-filesystem-dev \ libboost-program-options-dev \ - libboost-regex-dev \ libboost-system-dev \ libboost-thread-dev \ libssl-dev diff --git a/docs/build_notes_windows.md b/docs/build_notes_windows.md index 81e0dfc2..921a6110 100644 --- a/docs/build_notes_windows.md +++ b/docs/build_notes_windows.md @@ -110,11 +110,11 @@ prompt to build Boost) and run the following: cd C:\dev\boost bootstrap - b2 toolset=msvc-12.0 --build-type=complete --with-filesystem --with-program_options --with-regex --with-date_time + b2 toolset=msvc-12.0 --build-type=complete --with-filesystem --with-program_options --with-date_time If you are on 64-bit Windows and you want to build 64-bit version as well - b2 toolset=msvc-12.0 --build-type=complete --stagedir=stage64 address-model=64 --with-filesystem --with-program_options --with-regex --with-date_time + b2 toolset=msvc-12.0 --build-type=complete --stagedir=stage64 address-model=64 --with-filesystem --with-program_options --with-date_time After Boost is compiled, set the environment variable `BOOST_ROOT` to the directory Boost was unpacked to, e.g., C:\dev\boost. diff --git a/stdafx.h b/stdafx.h index ed13bf8b..42490354 100644 --- a/stdafx.h +++ b/stdafx.h @@ -33,7 +33,6 @@ #include #include -#include #include #include #include From a5f49550b3c6a010b7cc933c5cab628f6fced3f9 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 06/69] * HTTPProxy.cpp : unwrap AsyncSockRead() --- HTTPProxy.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 2001f620..42e4fc72 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -81,13 +81,13 @@ namespace proxy { void HTTPReqHandler::AsyncSockRead() { LogPrint(eLogDebug, "HTTPProxy: async sock read"); - if(m_sock) { - 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)); - } else { + if (!m_sock) { 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 HTTPReqHandler::Terminate() { From dba7a2ee4f32ac6d2b0c4ed01a73150c0f42a132 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 07/69] * HTTPProxy.cpp : HandleJumpServices() -> ExtractAddressHelper() --- HTTPProxy.cpp | 57 +++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 42e4fc72..884d2521 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -52,7 +52,7 @@ namespace proxy { void HTTPRequestFailed(const char *message); void RedirectToJumpService(std::string & host); bool ValidateHTTPRequest(); - void HandleJumpServices(); + bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64); bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); @@ -123,12 +123,14 @@ namespace proxy { i2p::config::GetOption("http.address", url.host); i2p::config::GetOption("http.port", url.port); + url.schema = "http"; url.path = "/"; url.query = "page=jumpservices&address="; url.query += host; res.code = 302; /* redirect */ res.add_header("Location", url.to_string().c_str()); + res.add_header("Connection", "close"); std::string response = res.to_string(); boost::asio::async_write(*m_sock, boost::asio::buffer(response, response.length()), @@ -151,47 +153,40 @@ namespace proxy { return true; } - void HTTPReqHandler::HandleJumpServices() + bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64) { - static const char * helpermark1 = "?i2paddresshelper="; - static const char * helpermark2 = "&i2paddresshelper="; - size_t addressHelperPos1 = m_path.rfind (helpermark1); - size_t addressHelperPos2 = m_path.rfind (helpermark2); - size_t addressHelperPos; - if (addressHelperPos1 == std::string::npos) - { - if (addressHelperPos2 == std::string::npos) - return; //Not a jump service - else - addressHelperPos = addressHelperPos2; - } - else - { - if (addressHelperPos2 == std::string::npos) - addressHelperPos = addressHelperPos1; - else if ( addressHelperPos1 > addressHelperPos2 ) - addressHelperPos = addressHelperPos1; - else - addressHelperPos = addressHelperPos2; - } - auto base64 = m_path.substr (addressHelperPos + strlen(helpermark1)); - base64 = i2p::util::http::urlDecode(base64); //Some of the symbols may be urlencoded - LogPrint (eLogInfo, "HTTPProxy: jump service for ", m_address, ", inserting to address book"); - //TODO: this is very dangerous and broken. We should ask the user before doing anything see http://pastethis.i2p/raw/pn5fL4YNJL7OSWj3Sc6N/ - //TODO: we could redirect the user again to avoid dirtiness in the browser - i2p::client::context.GetAddressBook ().InsertAddress (m_address, base64); - m_path.erase(addressHelperPos); + const char *param = "i2paddresshelper="; + std::size_t pos = url.query.find(param); + std::size_t len = std::strlen(param); + std::map params; + + if (pos == std::string::npos) + return false; /* not found */ + if (!url.parse_query(params)) + return false; + + std::string value = params["i2paddresshelper"]; + len += value.length(); + b64 = i2p::http::UrlDecode(value); + url.query.replace(pos, len, ""); + return true; } bool HTTPReqHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) { + std::string b64; i2p::http::URL url; url.parse(m_url); m_address = url.host; /* < compatibility */ m_port = url.port; /* < compatibility */ m_path = url.path; /* < compatibility */ if (!ValidateHTTPRequest()) return false; - HandleJumpServices(); + + /* TODO: notify user */ + if (ExtractAddressHelper(url, b64)) { + i2p::client::context.GetAddressBook ().InsertAddress (url.host, b64); + LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", url.host, " to address book"); + } i2p::data::IdentHash identHash; if (str_rmatch(m_address, ".i2p")) From 4098a5c08e636d786f68b22e94e8e7996f095380 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 08/69] * HTTPProxy.cpp : rename variable --- HTTPProxy.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 884d2521..bd03a6a6 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -31,7 +31,6 @@ namespace proxy { return false; } - static const size_t http_buffer_size = 8192; class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: @@ -57,7 +56,7 @@ namespace proxy { void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); - uint8_t m_http_buff[http_buffer_size]; + uint8_t m_downstream_recv_buf[8192]; std::shared_ptr m_sock; std::string m_request; //Data left to be sent std::string m_Response; @@ -85,7 +84,7 @@ namespace proxy { LogPrint(eLogError, "HTTPProxy: no socket for read"); return; } - m_sock->async_receive(boost::asio::buffer(m_http_buff, http_buffer_size), + m_sock->async_receive(boost::asio::buffer(m_downstream_recv_buf, sizeof(m_downstream_recv_buf)), std::bind(&HTTPReqHandler::HandleSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } @@ -297,7 +296,7 @@ namespace proxy { return; } - if (HandleData(m_http_buff, len)) + if (HandleData(m_downstream_recv_buf, len)) { if (m_state == DONE) { From a9f3235fd3f1163eeb97329c1749887aa3bd9e22 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 09/69] * HTTPProxy.cpp : unwrap HandleStreamRequestComplete() --- HTTPProxy.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index bd03a6a6..7150e14f 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -318,20 +318,18 @@ namespace proxy { void HTTPReqHandler::HandleStreamRequestComplete (std::shared_ptr stream) { - if (stream) - { - if (Kill()) return; - LogPrint (eLogInfo, "HTTPProxy: New I2PTunnel connection"); - auto connection = std::make_shared(GetOwner(), m_sock, stream); - GetOwner()->AddHandler (connection); - connection->I2PConnect (reinterpret_cast(m_request.data()), m_request.size()); - Done(shared_from_this()); - } - else - { + if (!stream) { LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info"); HTTPRequestFailed("error when creating the stream, check logs"); + return; } + if (Kill()) + return; + LogPrint (eLogDebug, "HTTPProxy: New I2PTunnel connection"); + auto connection = std::make_shared(GetOwner(), m_sock, stream); + GetOwner()->AddHandler (connection); + connection->I2PConnect (reinterpret_cast(m_request.data()), m_request.size()); + Done (shared_from_this()); } HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination): From 347157b9992a07290bb45e815398a27106e43333 Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 10/69] * HTTPProxy.cpp : direct use of parsed url parts in CreateHTTPRequest() --- HTTPProxy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 7150e14f..43ee8631 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -188,10 +188,10 @@ namespace proxy { } i2p::data::IdentHash identHash; - if (str_rmatch(m_address, ".i2p")) + if (str_rmatch(url.host, ".i2p")) { - if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){ - RedirectToJumpService(m_address); + if (!i2p::client::context.GetAddressBook ().GetIdentHash (url.host, identHash)){ + RedirectToJumpService(url.host); return false; } } From d0ffaab339b6aa21d5f4ec4be2b71c7e5e051ecb Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 27 May 2016 00:00:00 +0000 Subject: [PATCH 11/69] * HTTPProxy: * use new http classes instead homemade parser * proper error handling for "address not found", "addresshelper" and "not .i2p domain" cases * use std::vector instead uint8_t[] for buffers * general code cleanup --- HTTPProxy.cpp | 221 +++++++++++++++----------------------------------- 1 file changed, 66 insertions(+), 155 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 43ee8631..cc534470 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -34,45 +34,26 @@ namespace proxy { class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: - enum state - { - GET_METHOD, - GET_HOSTNAME, - GET_HTTPV, - GET_HTTPVNL, //TODO: fallback to finding HOst: header if needed - DONE - }; - - void EnterState(state nstate); - bool HandleData(uint8_t *http_buff, std::size_t len); + + bool HandleRequest(std::size_t len); void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void Terminate(); void AsyncSockRead(); void HTTPRequestFailed(const char *message); void RedirectToJumpService(std::string & host); - bool ValidateHTTPRequest(); bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64); - bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); + void SanitizeHTTPRequest(i2p::http::HTTPReq & req); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); - uint8_t m_downstream_recv_buf[8192]; std::shared_ptr m_sock; - std::string m_request; //Data left to be sent - std::string m_Response; - std::string m_url; //URL - std::string m_method; //Method - std::string m_version; //HTTP version - std::string m_address; //Address - std::string m_path; //Path - int m_port; //Port - state m_state;//Parsing state + std::vector m_recv_buf; /* as "downstream recieve buffer", from client to me */ + std::vector m_send_buf; /* as "upstream send buffer", from me to remote host */ public: HTTPReqHandler(HTTPProxy * parent, std::shared_ptr sock) : - I2PServiceHandler(parent), m_sock(sock) - { EnterState(GET_METHOD); } + I2PServiceHandler(parent), m_sock(sock), m_recv_buf(8192), m_send_buf(0) {}; ~HTTPReqHandler() { Terminate(); } void Handle () { AsyncSockRead(); } }; @@ -84,7 +65,7 @@ namespace proxy { LogPrint(eLogError, "HTTPProxy: no socket for read"); return; } - m_sock->async_receive(boost::asio::buffer(m_downstream_recv_buf, sizeof(m_downstream_recv_buf)), + m_sock->async_receive(boost::asio::buffer(m_recv_buf), std::bind(&HTTPReqHandler::HandleSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } @@ -100,8 +81,6 @@ namespace proxy { Done(shared_from_this()); } - /* All hope is lost beyond this point */ - //TODO: handle this apropriately void HTTPReqHandler::HTTPRequestFailed(const char *message) { i2p::http::HTTPRes res; @@ -136,22 +115,6 @@ namespace proxy { std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - void HTTPReqHandler::EnterState(HTTPReqHandler::state nstate) - { - m_state = nstate; - } - - bool HTTPReqHandler::ValidateHTTPRequest() - { - if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" ) - { - LogPrint(eLogError, "HTTPProxy: unsupported version: ", m_version); - HTTPRequestFailed("unsupported HTTP version"); - return false; - } - return true; - } - bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64) { const char *param = "i2paddresshelper="; @@ -171,118 +134,74 @@ namespace proxy { return true; } - bool HTTPReqHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) + void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) { - std::string b64; + req.del_header("Referer"); + req.add_header("Connection", "close", true); + req.add_header("User-Agent", "MYOB/6.66 (AN/ON)", true); + } + + /** + * @param len length of data in m_recv_buf + * @return true on processed request or false if more data needed + */ + bool HTTPReqHandler::HandleRequest(std::size_t len) + { + i2p::http::HTTPReq req; i2p::http::URL url; - url.parse(m_url); - m_address = url.host; /* < compatibility */ - m_port = url.port; /* < compatibility */ - m_path = url.path; /* < compatibility */ - if (!ValidateHTTPRequest()) return false; + std::string b64; + + int req_len = 0; + + req_len = req.parse((const char *) m_recv_buf.data(), len); + if (req_len == 0) + return false; /* need more data */ + if (req_len < 0) { + LogPrint(eLogError, "HTTPProxy: unable to parse request"); + HTTPRequestFailed("invalid request"); + return true; /* parse error */ + } + + /* parsing success, now let's look inside request */ + LogPrint(eLogDebug, "HTTPProxy: requested: ", req.uri); + url.parse(req.uri); - /* TODO: notify user */ if (ExtractAddressHelper(url, b64)) { i2p::client::context.GetAddressBook ().InsertAddress (url.host, b64); - LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", url.host, " to address book"); + std::string message = "added b64 from addresshelper for " + url.host + " to address book"; + LogPrint (eLogInfo, "HTTPProxy: ", message); + message += ", please reload page"; + HTTPRequestFailed(message.c_str()); + return true; /* request processed */ } i2p::data::IdentHash identHash; - if (str_rmatch(url.host, ".i2p")) - { - if (!i2p::client::context.GetAddressBook ().GetIdentHash (url.host, identHash)){ + if (str_rmatch(url.host, ".i2p")) { + if (!i2p::client::context.GetAddressBook ().GetIdentHash (url.host, identHash)) { RedirectToJumpService(url.host); - return false; + return true; /* request processed */ } + /* TODO: outproxy handler here */ + } else { + std::string message = "Host " + url.host + " not inside i2p network, but outproxy support still missing"; + HTTPRequestFailed(message.c_str()); + LogPrint (eLogWarning, "HTTPProxy: ", message); + return true; } + SanitizeHTTPRequest(req); - m_request = m_method; - m_request.push_back(' '); - m_request += m_path; - m_request.push_back(' '); - m_request += m_version; - m_request.push_back('\r'); - m_request.push_back('\n'); - m_request.append("Connection: close\r\n"); - // TODO: temporary shortcut. Must be implemented properly - uint8_t * eol = nullptr; - bool isEndOfHeader = false; - while (!isEndOfHeader && len && (eol = (uint8_t *)memchr (http_buff, '\r', len))) - { - if (eol) - { - *eol = 0; eol++; - if (strncmp ((const char *)http_buff, "Referer", 7) && strncmp ((const char *)http_buff, "Connection", 10)) // strip out referer and connection - { - if (!strncmp ((const char *)http_buff, "User-Agent", 10)) // replace UserAgent - m_request.append("User-Agent: MYOB/6.66 (AN/ON)"); - else - m_request.append ((const char *)http_buff); - m_request.append ("\r\n"); - } - isEndOfHeader = !http_buff[0]; - auto l = eol - http_buff; - http_buff = eol; - len -= l; - if (len > 0) // \r - { - http_buff++; - len--; - } - } - } - m_request.append(reinterpret_cast(http_buff),len); - return true; - } + /* drop original request from input buffer */ + m_recv_buf.erase(m_recv_buf.begin(), m_recv_buf.begin() + req_len); + + /* build new buffer from modified request and data from original request */ + std::string request = req.to_string(); + m_send_buf.assign(request.begin(), request.end()); + m_send_buf.insert(m_send_buf.end(), m_recv_buf.begin(), m_recv_buf.end()); + + /* connect to destination */ + GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete, + shared_from_this(), std::placeholders::_1), url.host, url.port); - bool HTTPReqHandler::HandleData(uint8_t *http_buff, std::size_t len) - { - while (len > 0) - { - //TODO: fallback to finding HOst: header if needed - switch (m_state) - { - case GET_METHOD: - switch (*http_buff) - { - case ' ': EnterState(GET_HOSTNAME); break; - default: m_method.push_back(*http_buff); break; - } - break; - case GET_HOSTNAME: - switch (*http_buff) - { - case ' ': EnterState(GET_HTTPV); break; - default: m_url.push_back(*http_buff); break; - } - break; - case GET_HTTPV: - switch (*http_buff) - { - case '\r': EnterState(GET_HTTPVNL); break; - default: m_version.push_back(*http_buff); break; - } - break; - case GET_HTTPVNL: - switch (*http_buff) - { - case '\n': EnterState(DONE); break; - default: - LogPrint(eLogError, "HTTPProxy: rejected invalid request ending with: ", ((int)*http_buff)); - HTTPRequestFailed("rejected invalid request"); - return false; - } - break; - default: - LogPrint(eLogError, "HTTPProxy: invalid state: ", m_state); - HTTPRequestFailed("invalid parser state"); - return false; - } - http_buff++; - len--; - if (m_state == DONE) - return CreateHTTPRequest(http_buff,len); - } return true; } @@ -296,17 +215,9 @@ namespace proxy { return; } - if (HandleData(m_downstream_recv_buf, len)) - { - if (m_state == DONE) - { - LogPrint(eLogDebug, "HTTPProxy: requested: ", m_url); - GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete, - shared_from_this(), std::placeholders::_1), m_address, m_port); - } - else - AsyncSockRead(); - } + if (HandleRequest(len)) + return; /* request processed */ + AsyncSockRead(); } void HTTPReqHandler::SentHTTPFailed(const boost::system::error_code & ecode) @@ -328,7 +239,7 @@ namespace proxy { LogPrint (eLogDebug, "HTTPProxy: New I2PTunnel connection"); auto connection = std::make_shared(GetOwner(), m_sock, stream); GetOwner()->AddHandler (connection); - connection->I2PConnect (reinterpret_cast(m_request.data()), m_request.size()); + connection->I2PConnect (m_send_buf.data(), m_send_buf.size()); Done (shared_from_this()); } From 1a9422c3f9e57513c1aea05d557cefc79ff1a454 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 27 May 2016 16:22:42 -0400 Subject: [PATCH 12/69] send SetDateMessage --- I2CP.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- I2CP.h | 9 +++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 5c718a48..fbd3e51b 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -1,9 +1,9 @@ #include #include "I2PEndian.h" #include "Log.h" +#include "Timestamp.h" #include "I2CP.h" - namespace i2p { namespace client @@ -104,14 +104,67 @@ namespace client { } + void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len) + { + auto l = len + I2CP_HEADER_SIZE; + uint8_t * buf = new uint8_t[l]; + htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len); + buf[I2CP_HEADER_TYPE_OFFSET] = type; + memcpy (buf + I2CP_HEADER_SIZE, payload, len); + boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), + std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2, buf)); + } + + void I2CPSession::HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf) + { + delete[] buf; + if (ecode && ecode != boost::asio::error::operation_aborted) + Terminate (); + } + + std::string I2CPSession::ExtractString (const uint8_t * buf, size_t len) + { + uint8_t l = buf[0]; + if (l > len) l = len; + return std::string ((const char *)buf, l); + } + + size_t I2CPSession::PutString (uint8_t * buf, size_t len, const std::string& str) + { + auto l = str.length (); + if (l + 1 >= len) l = len - 1; + if (l > 255) l = 255; // 1 byte max + buf[0] = l; + memcpy (buf + 1, str.c_str (), l); + return l + 1; + } + void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len) { + // get version + auto version = ExtractString (buf, len); + auto l = version.length () + 1 + 8; + uint8_t * payload = new uint8_t[l]; + // set date + auto ts = i2p::util::GetMillisecondsSinceEpoch (); + htobe64buf (payload, ts); + // echo vesrion back + PutString (payload + 8, l - 8, version); + SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); + } + + void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) + { + // TODO + m_Destination = std::make_shared(*this, nullptr, false); } I2CPServer::I2CPServer (const std::string& interface, int port) { memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers)); - m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; + m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; + m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE ] = &I2CPSession::CreateSessionMessageHandler; } } } diff --git a/I2CP.h b/I2CP.h index 020fd22a..c495d34e 100644 --- a/I2CP.h +++ b/I2CP.h @@ -19,6 +19,8 @@ namespace client const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; const uint8_t I2CP_GET_DATE_MESSAGE = 32; + const uint8_t I2CP_SET_DATE_MESSAGE = 33; + const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; class I2CPSession; class I2CPDestination: public LeaseSetDestination @@ -52,6 +54,7 @@ namespace client // message handlers void GetDateMessageHandler (const uint8_t * buf, size_t len); + void CreateSessionMessageHandler (const uint8_t * buf, size_t len); private: @@ -61,6 +64,12 @@ namespace client void HandleNextMessage (const uint8_t * buf); void Terminate (); + void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); + void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); + + std::string ExtractString (const uint8_t * buf, size_t len); + size_t PutString (uint8_t * buf, size_t len, const std::string& str); + private: I2CPServer& m_Owner; From 44eccd85fd86c77a415a329d91115ffa49b31985 Mon Sep 17 00:00:00 2001 From: hagen Date: Sat, 28 May 2016 00:00:00 +0000 Subject: [PATCH 13/69] * HTTPServer.cpp : * autorefresh for status page * autoreturn to commands list --- HTTPServer.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 5d54711d..2af92057 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -755,12 +755,14 @@ namespace http { // Html5 head start ShowPageHead (s); - if (req.uri.find("page=") != std::string::npos) + if (req.uri.find("page=") != std::string::npos) { HandlePage (req, res, s); - else if (req.uri.find("cmd=") != std::string::npos) + } else if (req.uri.find("cmd=") != std::string::npos) { HandleCommand (req, res, s); - else + } else { ShowStatus (s); + res.add_header("Refresh", "5"); + } ShowPageTail (s); res.code = 200; @@ -841,7 +843,9 @@ namespace http { return; } s << "SUCCESS: Command accepted

\r\n"; - s << "Back to commands list"; + s << "Back to commands list
\r\n"; + s << "

You will be redirected in 5 seconds"; + res.add_header("Refresh", "5; url=/?page=commands"); } void HTTPConnection::SendReply (HTTPRes& reply, std::string& content) From ea8e1be294537d21e59b7d5d6d3a0fc61ec48c3e Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 29 May 2016 00:00:00 +0000 Subject: [PATCH 14/69] * update default init-script : make --port optional --- debian/i2pd.default | 1 + debian/i2pd.init | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/debian/i2pd.default b/debian/i2pd.default index bf6eb005..28b0e621 100644 --- a/debian/i2pd.default +++ b/debian/i2pd.default @@ -4,6 +4,7 @@ I2PD_ENABLED="yes" # port to listen for incoming connections +# comment this line if you want to use value from config I2PD_PORT="4567" # Additional options that are passed to the Daemon. diff --git a/debian/i2pd.init b/debian/i2pd.init index 8cfee8d4..02b37546 100644 --- a/debian/i2pd.init +++ b/debian/i2pd.init @@ -41,6 +41,10 @@ do_start() return 2 fi + if [ -n "$I2PD_PORT" ]; then + DAEMON_OPTS="--port $I2PD_PORT $DAEMON_OPTS" + fi + touch "$PIDFILE" chown -f $USER:adm "$PIDFILE" @@ -51,7 +55,7 @@ do_start() || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --chuid "$USER" -- \ --service --daemon --log=file --logfile=$LOGFILE --conf=$I2PCONF --tunconf=$TUNCONF \ - --port=$I2PD_PORT $DAEMON_OPTS > /dev/null 2>&1 \ + $DAEMON_OPTS > /dev/null 2>&1 \ || return 2 return $? } From d9babda1b8470bd76c998640f5f3ec9e4601b4f2 Mon Sep 17 00:00:00 2001 From: hagen Date: Sun, 29 May 2016 00:00:00 +0000 Subject: [PATCH 15/69] + debian/i2pd.openrc (experimental) --- debian/i2pd.openrc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 debian/i2pd.openrc diff --git a/debian/i2pd.openrc b/debian/i2pd.openrc new file mode 100644 index 00000000..ddcb4003 --- /dev/null +++ b/debian/i2pd.openrc @@ -0,0 +1,27 @@ +#!/sbin/openrc-run + +pidfile="/var/run/i2pd.pid" +logfile="/var/log/i2pd.log" +mainconf="/etc/i2pd/i2pd.conf" +tunconf="/etc/i2pd/tunnels.conf" + +. /etc/default/i2pd + +name="i2pd" +command="/usr/sbin/i2pd" +command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf" +description="i2p router written in C++" +required_dirs="/var/lib/i2pd" +required_files="$mainconf" +start_stop_daemon_args="--chuid i2pd" + +depend() { + need mountall + use net + after bootmisc +} + +start_pre() { + checkpath -f -o i2pd:adm -w $pidfile + checkpath -f -o i2pd:adm -w $logfile +} From 6c9b4a8c5df8ff57a73d706601196f7ea256c68f Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 May 2016 09:33:50 -0400 Subject: [PATCH 16/69] moved LeaseSet creating away from LeaseSetDestination --- Destination.cpp | 84 +++++++++++++++++++++++++++---------------------- Destination.h | 27 ++++++++-------- I2CP.cpp | 1 + I2CP.h | 7 +++-- Identity.h | 1 - 5 files changed, 66 insertions(+), 54 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index 40c8768e..bb67b601 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -130,10 +130,6 @@ namespace client if (!m_IsRunning) { m_IsRunning = true; - if (m_IsPublic) - PersistTemporaryKeys (); - else - i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); m_Pool->SetLocalDestination (shared_from_this ()); m_Pool->SetActive (true); m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ())); @@ -204,14 +200,21 @@ namespace client return m_LeaseSet; } + void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) + { + m_LeaseSet.reset (newLeaseSet); + if (m_IsPublic) + { + m_PublishVerificationTimer.cancel (); + Publish (); + } + } + void LeaseSetDestination::UpdateLeaseSet () { int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum - auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), GetEncryptionPublicKey (), - m_Pool->GetInboundTunnels (numTunnels)); - Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO - m_LeaseSet.reset (leaseSet); + CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels)); } bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) @@ -391,11 +394,6 @@ namespace client { i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); UpdateLeaseSet (); - if (m_IsPublic) - { - m_PublishVerificationTimer.cancel (); - Publish (); - } } void LeaseSetDestination::Publish () @@ -642,36 +640,16 @@ namespace client else it++; } - } - - void LeaseSetDestination::PersistTemporaryKeys () - { - std::string ident = GetIdentHash().ToBase32(); - std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat")); - std::ifstream f(path, std::ifstream::binary); - - if (f) { - f.read ((char *)m_EncryptionPublicKey, 256); - f.read ((char *)m_EncryptionPrivateKey, 256); - return; - } - - LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p"); - i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); - - std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); - if (f1) { - f1.write ((char *)m_EncryptionPublicKey, 256); - f1.write ((char *)m_EncryptionPrivateKey, 256); - return; - } - LogPrint(eLogError, "Destinations: Can't save keys to ", path); } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (isPublic, params), m_Keys (keys), m_DatagramDestination (nullptr) { + if (isPublic) + PersistTemporaryKeys (); + else + i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); } @@ -840,5 +818,37 @@ namespace client ret.push_back (it1.second); return ret; } + + void ClientDestination::PersistTemporaryKeys () + { + std::string ident = GetIdentHash().ToBase32(); + std::string path = i2p::fs::DataDirPath("destinations", (ident + ".dat")); + std::ifstream f(path, std::ifstream::binary); + + if (f) { + f.read ((char *)m_EncryptionPublicKey, 256); + f.read ((char *)m_EncryptionPrivateKey, 256); + return; + } + + LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p"); + i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); + + std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); + if (f1) { + f1.write ((char *)m_EncryptionPublicKey, 256); + f1.write ((char *)m_EncryptionPrivateKey, 256); + return; + } + LogPrint(eLogError, "Destinations: Can't save keys to ", path); + } + + void ClientDestination::CreateNewLeaseSet (std::vector > tunnels) + { + auto leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels); + // sign + Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO + SetLeaseSet (leaseSet); + } } } diff --git a/Destination.h b/Destination.h index e2531699..56c83fb4 100644 --- a/Destination.h +++ b/Destination.h @@ -81,10 +81,6 @@ namespace client bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr); void CancelDestinationRequest (const i2p::data::IdentHash& dest); - // implements LocalDestination - const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; - const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; - // implements GarlicDestination std::shared_ptr GetLeaseSet (); std::shared_ptr GetTunnelPool () const { return m_Pool; } @@ -98,8 +94,10 @@ namespace client protected: + void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); // I2CP virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; + virtual void CreateNewLeaseSet (std::vector > tunnels) = 0; private: @@ -117,13 +115,9 @@ namespace client void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); - - void PersistTemporaryKeys (); private: - uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; - volatile bool m_IsRunning; std::thread * m_Thread; boost::asio::io_service m_Service; @@ -156,7 +150,8 @@ namespace client bool Stop (); const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; + // streaming std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional std::shared_ptr GetStreamingDestination (int port = 0) const; @@ -166,28 +161,32 @@ namespace client void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor); void StopAcceptingStreams (); bool IsAcceptingStreams () const; - + // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; i2p::datagram::DatagramDestination * CreateDatagramDestination (); - // implements LocalDestination - std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; - void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; + // implements LocalDestination + const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; + const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; + std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; protected: // I2CP void HandleDataMessage (const uint8_t * buf, size_t len); + void CreateNewLeaseSet (std::vector > tunnels); private: std::shared_ptr GetSharedFromThis () - { return std::static_pointer_cast(shared_from_this ()); } + { return std::static_pointer_cast(shared_from_this ()); } + void PersistTemporaryKeys (); private: i2p::data::PrivateKeys m_Keys; + uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; diff --git a/I2CP.cpp b/I2CP.cpp index fbd3e51b..ee329d37 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -152,6 +152,7 @@ namespace client // echo vesrion back PutString (payload + 8, l - 8, version); SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); + delete[] payload; } void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) diff --git a/I2CP.h b/I2CP.h index c495d34e..f677b9ee 100644 --- a/I2CP.h +++ b/I2CP.h @@ -32,16 +32,19 @@ namespace client protected: // implements LocalDestination + const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; + const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; std::shared_ptr GetIdentity () const { return m_Identity; }; - void Sign (const uint8_t * buf, int len, uint8_t * signature) const { /* TODO */}; // I2CP - void HandleDataMessage (const uint8_t * buf, size_t len) {}; + void HandleDataMessage (const uint8_t * buf, size_t len) { /* TODO */ }; + void CreateNewLeaseSet (std::vector > tunnels) { /* TODO */ }; private: I2CPSession& m_Owner; std::shared_ptr m_Identity; + uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; }; class I2CPServer; diff --git a/Identity.h b/Identity.h index 541a7801..2a60ddd3 100644 --- a/Identity.h +++ b/Identity.h @@ -181,7 +181,6 @@ namespace data virtual const uint8_t * GetEncryptionPrivateKey () const = 0; virtual const uint8_t * GetEncryptionPublicKey () const = 0; virtual std::shared_ptr GetIdentity () const = 0; - virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; }; From 09a80ed6541ad69ad8a47c29cba14c056aea148d Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 29 May 2016 16:35:57 -0400 Subject: [PATCH 17/69] RequestVariableLeaseSetMessage --- I2CP.cpp | 17 +++++++++++++++-- I2CP.h | 13 ++++++++----- LeaseSet.cpp | 1 + LeaseSet.h | 5 ++++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index ee329d37..bb7c956b 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -2,6 +2,7 @@ #include "I2PEndian.h" #include "Log.h" #include "Timestamp.h" +#include "LeaseSet.h" #include "I2CP.h" namespace i2p @@ -14,13 +15,25 @@ namespace client { } + void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) + { + i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPublicKey, tunnels); + uint8_t * leases = ls.GetLeases (); + leases[-1] = tunnels.size (); + htobe16buf (leases - 3, m_Owner.GetSessionID ()); + size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); + m_Owner.SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); + + } + I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), - m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0) + m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), + m_SessionID (0) { ReadProtocolByte (); } - + I2CPSession::~I2CPSession () { delete[] m_NextMessage; diff --git a/I2CP.h b/I2CP.h index f677b9ee..3de7d73e 100644 --- a/I2CP.h +++ b/I2CP.h @@ -21,7 +21,8 @@ namespace client const uint8_t I2CP_GET_DATE_MESSAGE = 32; const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; - + const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; + class I2CPSession; class I2CPDestination: public LeaseSetDestination { @@ -38,7 +39,7 @@ namespace client // I2CP void HandleDataMessage (const uint8_t * buf, size_t len) { /* TODO */ }; - void CreateNewLeaseSet (std::vector > tunnels) { /* TODO */ }; + void CreateNewLeaseSet (std::vector > tunnels); private: @@ -55,6 +56,9 @@ namespace client I2CPSession (I2CPServer& owner, std::shared_ptr socket); ~I2CPSession (); + uint16_t GetSessionID () const { return m_SessionID; }; + void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); + // message handlers void GetDateMessageHandler (const uint8_t * buf, size_t len); void CreateSessionMessageHandler (const uint8_t * buf, size_t len); @@ -66,10 +70,8 @@ namespace client void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleNextMessage (const uint8_t * buf); void Terminate (); - - void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); + void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); - std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); @@ -81,6 +83,7 @@ namespace client size_t m_NextMessageLen, m_NextMessageOffset; std::shared_ptr m_Destination; + uint16_t m_SessionID; }; typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 5efe2b16..20861677 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -213,6 +213,7 @@ namespace data m_Buffer[offset] = num; offset++; // leases + m_Leases = m_Buffer + offset; auto currentTime = i2p::util::GetMillisecondsSinceEpoch (); for (int i = 0; i < num; i++) { diff --git a/LeaseSet.h b/LeaseSet.h index 289ae25c..6688fbf8 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "Identity.h" @@ -94,6 +95,8 @@ namespace data uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; size_t GetBufferLen () const { return m_BufferLen; }; size_t GetSignatureLen () const { return m_Identity->GetSignatureLen (); }; + uint8_t * GetLeases () { return m_Leases; }; + const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; bool IsExpired () const; bool operator== (const LeaseSet& other) const @@ -104,7 +107,7 @@ namespace data uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; - uint8_t * m_Buffer; + uint8_t * m_Buffer, * m_Leases; size_t m_BufferLen; }; } From 5a2c4919c6c415bcb22aeae8cbd5f579aa90bcea Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 May 2016 09:41:45 -0400 Subject: [PATCH 18/69] close previous file first upon repon --- Log.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Log.cpp b/Log.cpp index 36fcebf3..0518fb2e 100644 --- a/Log.cpp +++ b/Log.cpp @@ -130,10 +130,13 @@ namespace log { Process(); } - void Log::SendTo (const std::string& path) { + void Log::SendTo (const std::string& path) + { + if (m_LogStream) m_LogStream = nullptr; // close previous auto flags = std::ofstream::out | std::ofstream::app; auto os = std::make_shared (path, flags); - if (os->is_open ()) { + if (os->is_open ()) + { m_Logfile = path; m_Destination = eLogFile; m_LogStream = os; From 6a453bcc8a51c740a6a23edbae683f01aa5ba54c Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 May 2016 12:08:20 -0400 Subject: [PATCH 19/69] check for null pointer --- Log.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Log.cpp b/Log.cpp index 0518fb2e..155efbe8 100644 --- a/Log.cpp +++ b/Log.cpp @@ -56,7 +56,7 @@ namespace log { #endif case eLogFile: case eLogStream: - m_LogStream->flush(); + if (m_LogStream) m_LogStream->flush(); break; default: /* do nothing */ @@ -107,10 +107,11 @@ namespace log { #endif case eLogFile: case eLogStream: - *m_LogStream << TimeAsString(msg->timestamp) - << "@" << short_tid - << "/" << g_LogLevelStr[msg->level] - << " - " << msg->text << std::endl; + if (m_LogStream) + *m_LogStream << TimeAsString(msg->timestamp) + << "@" << short_tid + << "/" << g_LogLevelStr[msg->level] + << " - " << msg->text << std::endl; break; case eLogStdout: default: From a062bca431e5ca9d36f79837b06956e78ea2ba27 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 May 2016 12:56:42 -0400 Subject: [PATCH 20/69] CreateLeaseSetMessage --- Destination.h | 1 - I2CP.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++--- I2CP.h | 21 +++++++++++++++++---- Identity.h | 1 - LeaseSet.cpp | 8 ++++++++ LeaseSet.h | 3 +++ 6 files changed, 70 insertions(+), 9 deletions(-) diff --git a/Destination.h b/Destination.h index 56c83fb4..e64508c9 100644 --- a/Destination.h +++ b/Destination.h @@ -168,7 +168,6 @@ namespace client // implements LocalDestination const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; - const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; protected: diff --git a/I2CP.cpp b/I2CP.cpp index bb7c956b..b0e889ac 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -1,3 +1,11 @@ +/* +* 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 #include "I2PEndian.h" #include "Log.h" @@ -15,9 +23,15 @@ namespace client { } + void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key) + { + memcpy (m_EncryptionPrivateKey, key, 256); + } + void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) { - i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPublicKey, tunnels); + i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPrivateKey, tunnels); // we don't care about encryption key + m_LeaseSetExpirationTime = ls.GetExpirationTime (); uint8_t * leases = ls.GetLeases (); leases[-1] = tunnels.size (); htobe16buf (leases - 3, m_Owner.GetSessionID ()); @@ -25,7 +39,14 @@ namespace client m_Owner.SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); } - + + void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) + { + auto ls = new i2p::data::LocalLeaseSet (m_Identity, buf, len); + ls->SetExpirationTime (m_LeaseSetExpirationTime); + SetLeaseSet (ls); + } + I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), @@ -174,11 +195,29 @@ namespace client m_Destination = std::make_shared(*this, nullptr, false); } + void I2CPSession::CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len) + { + uint16_t sessionID = bufbe16toh (buf); + if (sessionID == m_SessionID) + { + size_t offset = 2; + if (m_Destination) + { + m_Destination->SetEncryptionPrivateKey (buf + offset); + offset += 256; + m_Destination->LeaseSetCreated (buf + offset, len - offset); + } + } + else + LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); + } + I2CPServer::I2CPServer (const std::string& interface, int port) { memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers)); m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; - m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE ] = &I2CPSession::CreateSessionMessageHandler; + m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE] = &I2CPSession::CreateSessionMessageHandler; + m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; } } } diff --git a/I2CP.h b/I2CP.h index 3de7d73e..73f63432 100644 --- a/I2CP.h +++ b/I2CP.h @@ -1,3 +1,11 @@ +/* +* Copyright (c) 2013-2016, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +*/ + #ifndef I2CP_H__ #define I2CP_H__ @@ -22,7 +30,8 @@ namespace client const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; - + const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; + class I2CPSession; class I2CPDestination: public LeaseSetDestination { @@ -30,11 +39,13 @@ namespace client I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic); + void SetEncryptionPrivateKey (const uint8_t * key); + void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession + protected: // implements LocalDestination const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; - const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionPublicKey; }; std::shared_ptr GetIdentity () const { return m_Identity; }; // I2CP @@ -45,7 +56,8 @@ namespace client I2CPSession& m_Owner; std::shared_ptr m_Identity; - uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; + uint8_t m_EncryptionPrivateKey[256]; + uint64_t m_LeaseSetExpirationTime; }; class I2CPServer; @@ -62,6 +74,7 @@ namespace client // message handlers void GetDateMessageHandler (const uint8_t * buf, size_t len); void CreateSessionMessageHandler (const uint8_t * buf, size_t len); + void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); private: @@ -95,7 +108,7 @@ namespace client private: - I2CPMessageHandler m_MessagesHandlers[256]; + I2CPMessageHandler m_MessagesHandlers[256]; public: diff --git a/Identity.h b/Identity.h index 2a60ddd3..841acf65 100644 --- a/Identity.h +++ b/Identity.h @@ -179,7 +179,6 @@ namespace data virtual ~LocalDestination() {}; virtual const uint8_t * GetEncryptionPrivateKey () const = 0; - virtual const uint8_t * GetEncryptionPublicKey () const = 0; virtual std::shared_ptr GetIdentity () const = 0; const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); }; diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 20861677..16a470e0 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -232,6 +232,14 @@ namespace data // we don't sign it yet. must be signed later on } + LocalLeaseSet::LocalLeaseSet (std::shared_ptr identity, const uint8_t * buf, size_t len): + m_ExpirationTime (0), m_Identity (identity) + { + m_BufferLen = len; + m_Buffer = new uint8_t[m_BufferLen]; + memcpy (m_Buffer, buf, len); + } + bool LocalLeaseSet::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); diff --git a/LeaseSet.h b/LeaseSet.h index 6688fbf8..c174ac39 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -89,6 +89,7 @@ namespace data public: LocalLeaseSet (std::shared_ptr identity, const uint8_t * encryptionPublicKey, std::vector > tunnels); + LocalLeaseSet (std::shared_ptr identity, const uint8_t * buf, size_t len); ~LocalLeaseSet () { delete[] m_Buffer; }; const uint8_t * GetBuffer () const { return m_Buffer; }; @@ -99,6 +100,8 @@ namespace data const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; bool IsExpired () const; + uint64_t GetExpirationTime () const { return m_ExpirationTime; }; + void SetExpirationTime (uint64_t expirationTime) { m_ExpirationTime = expirationTime; }; bool operator== (const LeaseSet& other) const { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; From ae10793d0f2f559727d38b8e3769ac0e8b019824 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 May 2016 14:31:56 -0400 Subject: [PATCH 21/69] SendMessageMessage --- I2CP.cpp | 31 ++++++++++++++++++++++++++++++- I2CP.h | 3 +++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/I2CP.cpp b/I2CP.cpp index b0e889ac..b74e9cc8 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -47,6 +47,17 @@ namespace client SetLeaseSet (ls); } + void I2CPDestination::SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident) + { + auto msg = NewI2NPMessage (); + uint8_t * buf = msg->GetPayload (); + htobe32buf (buf, len); + memcpy (buf + 4, payload, len); + msg->len += len + 4; + msg->FillI2NPMessageHeader (eI2NPData); + // TODO: send + } + I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), @@ -212,12 +223,30 @@ namespace client LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } + void I2CPSession::SendMessageMessageHandler (const uint8_t * buf, size_t len) + { + uint16_t sessionID = bufbe16toh (buf); + if (sessionID == m_SessionID) + { + size_t offset = 2; + if (m_Destination) + { + i2p::data::IdentityEx identity; + offset += identity.FromBuffer (buf + offset, len - offset); + m_Destination->SendMsgTo (buf + offset, len - offset, identity.GetIdentHash ()); + } + } + else + LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); + } + I2CPServer::I2CPServer (const std::string& interface, int port) { memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers)); m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE] = &I2CPSession::CreateSessionMessageHandler; - m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; + m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; + m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; } } } diff --git a/I2CP.h b/I2CP.h index 73f63432..4e0f1caf 100644 --- a/I2CP.h +++ b/I2CP.h @@ -31,6 +31,7 @@ namespace client const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; + const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; class I2CPSession; class I2CPDestination: public LeaseSetDestination @@ -41,6 +42,7 @@ namespace client void SetEncryptionPrivateKey (const uint8_t * key); void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession + void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident); // called from I2CPSession protected: @@ -75,6 +77,7 @@ namespace client void GetDateMessageHandler (const uint8_t * buf, size_t len); void CreateSessionMessageHandler (const uint8_t * buf, size_t len); void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); + void SendMessageMessageHandler (const uint8_t * buf, size_t len); private: From eeffcea69e6fdabcc530ac6eb7f773bd728b5678 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 May 2016 15:19:22 -0400 Subject: [PATCH 22/69] CreateSessionMessage --- I2CP.cpp | 28 ++++++++++++++++++++++++++-- I2CP.h | 3 +++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index b74e9cc8..8d0bedf1 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -7,6 +7,7 @@ */ #include +#include #include "I2PEndian.h" #include "Log.h" #include "Timestamp.h" @@ -202,8 +203,31 @@ namespace client void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) { - // TODO - m_Destination = std::make_shared(*this, nullptr, false); + auto identity = std::make_shared(); + size_t offset = identity->FromBuffer (buf, len); + uint16_t optionsSize = bufbe16toh (buf + offset); + // TODO: extract options + offset += optionsSize; + offset += 8; // date + if (identity->Verify (buf, offset, buf + offset)) // signature + { + m_Destination = std::make_shared(*this, identity, false); + RAND_bytes ((uint8_t *)&m_SessionID, 2); + SendSessionStatusMessage (1); // created + } + else + { + LogPrint (eLogError, "I2CP: create session signature verification falied"); + SendSessionStatusMessage (3); // invalid + } + } + + void I2CPSession::SendSessionStatusMessage (uint8_t status) + { + uint8_t buf[3]; + htobe16buf (buf, m_SessionID); + buf[2] = status; + SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); } void I2CPSession::CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len) diff --git a/I2CP.h b/I2CP.h index 4e0f1caf..fca3317d 100644 --- a/I2CP.h +++ b/I2CP.h @@ -29,6 +29,7 @@ namespace client const uint8_t I2CP_GET_DATE_MESSAGE = 32; const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; + const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; @@ -91,6 +92,8 @@ namespace client std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); + void SendSessionStatusMessage (uint8_t status); + private: I2CPServer& m_Owner; From 23e019ec83db38b3f0b0f27aaa2eb02ba953469e Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 31 May 2016 00:00:00 +0000 Subject: [PATCH 23/69] * debian/i2pd.openrc (working version) --- debian/i2pd.openrc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/debian/i2pd.openrc b/debian/i2pd.openrc index ddcb4003..6253cfa6 100644 --- a/debian/i2pd.openrc +++ b/debian/i2pd.openrc @@ -5,11 +5,9 @@ logfile="/var/log/i2pd.log" mainconf="/etc/i2pd/i2pd.conf" tunconf="/etc/i2pd/tunnels.conf" -. /etc/default/i2pd - name="i2pd" command="/usr/sbin/i2pd" -command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf" +command_args="--service --daemon --log=file --logfile=$logfile --conf=$mainconf --tunconf=$tunconf --pidfile=$pidfile" description="i2p router written in C++" required_dirs="/var/lib/i2pd" required_files="$mainconf" @@ -22,6 +20,22 @@ depend() { } start_pre() { - checkpath -f -o i2pd:adm -w $pidfile - checkpath -f -o i2pd:adm -w $logfile + if [ -r /etc/default/i2pd ]; then + . /etc/default/i2pd + fi + + if [ "x$I2PD_ENABLED" != "xyes" ]; then + ewarn "i2pd disabled in /etc/default/i2pd" + exit 1 + fi + + checkpath -f -o i2pd:adm $logfile + checkpath -f -o i2pd:adm $pidfile + + if [ -n "$I2PD_PORT" -a "$I2PD_PORT" -gt 0 ]; then + command_args="$command_args --port=$I2PD_PORT" + fi + if [ -n "$DAEMON_OPTS" ]; then + command_args="$command_args $DAEMON_OPTS" + fi } From 289b679e3c6153a70ae3193fba93dc7242f2c24e Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 31 May 2016 00:00:00 +0000 Subject: [PATCH 24/69] * add doxygen support --- Makefile | 5 + docs/Doxyfile | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 264 insertions(+) create mode 100644 docs/Doxyfile diff --git a/Makefile b/Makefile index e3807d93..4cc313a9 100644 --- a/Makefile +++ b/Makefile @@ -76,6 +76,7 @@ $(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) clean: rm -rf obj + rm -rf docs/generated $(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB) @@ -86,9 +87,13 @@ dist: git archive --format=tar.gz -9 --worktree-attributes \ --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz +doxygen: + doxygen -s docs/Doxyfile + .PHONY: all .PHONY: clean .PHONY: deps +.PHONY: doxygen .PHONY: dist .PHONY: api .PHONY: api_client diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 00000000..f2e29995 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,259 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "i2pd" +PROJECT_NUMBER = +PROJECT_BRIEF = "load-balanced unspoofable packet switching network" +PROJECT_LOGO = +OUTPUT_DIRECTORY = docs/generated +CREATE_SUBDIRS = NO +ALLOW_UNICODE_NAMES = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +INPUT = +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.cpp *.h +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +CLANG_ASSISTED_PARSING = NO +CLANG_OPTIONS = +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_SUBDIR = +MAN_LINKS = NO +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +DOCBOOK_PROGRAMLISTING = NO +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +PLANTUML_JAR_PATH = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES From c9836cf0f787c7ee8a0b3553653b80148299becb Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 31 May 2016 00:00:00 +0000 Subject: [PATCH 25/69] * fix doxygen warnings --- Config.h | 4 ++-- HTTP.h | 16 +++++++++------- Log.cpp | 2 +- Log.h | 7 ++++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Config.h b/Config.h index d79a9c47..6b2af717 100644 --- a/Config.h +++ b/Config.h @@ -68,7 +68,7 @@ namespace config { * @param value Variable where to store option * @return this function returns false if parameter not found * - * @example uint16_t port; GetOption("sam.port", port); + * Example: uint16_t port; GetOption("sam.port", port); */ template bool GetOption(const char *name, T& value) { @@ -84,7 +84,7 @@ namespace config { * @param value New parameter value * @return true if value set up successful, false otherwise * - * @example uint16_t port = 2827; SetOption("bob.port", port); + * Example: uint16_t port = 2827; SetOption("bob.port", port); */ template bool SetOption(const char *name, const T& value) { diff --git a/HTTP.h b/HTTP.h index f227271f..8d10c231 100644 --- a/HTTP.h +++ b/HTTP.h @@ -38,7 +38,7 @@ namespace http { * @brief Tries to parse url from string * @return true on success, false on invalid url */ - bool parse (const char *str, size_t len = 0); + bool parse (const char *str, std::size_t len = 0); bool parse (const std::string& url); /** @@ -89,10 +89,12 @@ namespace http { std::string version; std::string status; unsigned short int code; - /** simplifies response generation - * If this variable is set: - * a) Content-Length header will be added if missing - * b) contents of body will be included in response + /** + * @brief Simplifies response generation + * + * If this variable is set, on @a to_string() call: + * * Content-Length header will be added if missing, + * * contents of @a body will be included in generated response */ std::string body; @@ -108,9 +110,9 @@ namespace http { /** * @brief Serialize HTTP response to string - * @note If version is set to HTTP/1.1, and Date header is missing, + * @note If @a version is set to HTTP/1.1, and Date header is missing, * it will be generated based on current time and added to headers - * @note If body member is set and Content-Length header is missing, + * @note If @a body is set and Content-Length header is missing, * this header will be added, based on body's length */ std::string to_string(); diff --git a/Log.cpp b/Log.cpp index 155efbe8..590f3d0f 100644 --- a/Log.cpp +++ b/Log.cpp @@ -12,7 +12,7 @@ namespace i2p { namespace log { Log logger; /** - * @enum Maps our loglevel to their symbolic name + * @brief Maps our loglevel to their symbolic name */ static const char * g_LogLevelStr[eNumLogLevels] = { diff --git a/Log.h b/Log.h index 33bd5868..6762899f 100644 --- a/Log.h +++ b/Log.h @@ -86,7 +86,7 @@ namespace log { LogLevel GetLogLevel () { return m_MinLevel; }; /** - * @brief Sets minimal alloed level for log messages + * @brief Sets minimal allowed level for log messages * @param level String with wanted minimal msg level */ void SetLogLevel (const std::string& level); @@ -101,7 +101,7 @@ namespace log { * @brief Sets log destination to given output stream * @param os Output stream */ - void SendTo (std::shared_ptr s); + void SendTo (std::shared_ptr os); #ifndef _WIN32 /** @@ -129,7 +129,8 @@ namespace log { }; /** - * @struct Log message container + * @struct LogMsg + * @brief Log message container * * We creating it somewhere with LogPrint(), * then put in MsgQueue for later processing. From a47417ff49f46c5a1f92819b54c43960607e206e Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 31 May 2016 00:00:00 +0000 Subject: [PATCH 26/69] * I2PService.cpp: tune logs --- I2PService.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/I2PService.cpp b/I2PService.cpp index 0aefc172..6a0cd291 100644 --- a/I2PService.cpp +++ b/I2PService.cpp @@ -3,7 +3,6 @@ #include "ClientContext.h" #include "I2PService.h" - namespace i2p { namespace client @@ -71,7 +70,7 @@ namespace client std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else { - LogPrint(eLogError, "TCPIPPipe: no upstream socket for read"); + LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket"); } } @@ -82,14 +81,14 @@ namespace client std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } else { - LogPrint(eLogError, "TCPIPPipe: no downstream socket for read"); + LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket"); } } void TCPIPPipe::UpstreamWrite(const uint8_t * buf, size_t len) { if (m_up) { - LogPrint(eLogDebug, "TCPIPPipe: write upstream ", (int)len); + LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_up, boost::asio::buffer(buf, len), boost::asio::transfer_all(), std::bind(&TCPIPPipe::HandleUpstreamWrite, @@ -97,14 +96,14 @@ namespace client std::placeholders::_1) ); } else { - LogPrint(eLogError, "tcpip pipe upstream socket null"); + LogPrint(eLogError, "TCPIPPipe: upstream write: no socket"); } } void TCPIPPipe::DownstreamWrite(const uint8_t * buf, size_t len) { if (m_down) { - LogPrint(eLogDebug, "TCPIPPipe: write downstream ", (int)len); + LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written"); boost::asio::async_write(*m_down, boost::asio::buffer(buf, len), boost::asio::transfer_all(), std::bind(&TCPIPPipe::HandleDownstreamWrite, @@ -112,16 +111,16 @@ namespace client std::placeholders::_1) ); } else { - LogPrint(eLogError, "tcpip pipe downstream socket null"); + LogPrint(eLogError, "TCPIPPipe: downstream write: no socket"); } } void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe downstream got ", (int) bytes_transfered); + LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received"); if (ecode) { - LogPrint(eLogError, "TCPIPPipe Downstream read error:" , ecode.message()); + LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); } else { @@ -135,7 +134,7 @@ namespace client void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) { if (ecode) { - LogPrint(eLogError, "TCPIPPipe Downstream write error:" , ecode.message()); + LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); } @@ -143,7 +142,7 @@ namespace client void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { if (ecode) { - LogPrint(eLogError, "TCPIPPipe Upstream write error:" , ecode.message()); + LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); } @@ -151,9 +150,9 @@ namespace client void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe upstream got ", (int) bytes_transfered); + LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int) bytes_transfered, , " bytes received"); if (ecode) { - LogPrint(eLogError, "TCPIPPipe Upstream read error:" , ecode.message()); + LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) Terminate(); } else { @@ -206,6 +205,5 @@ namespace client LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ()); } } - } } From f66f4ffee6f845ecf4c3c6218051bec393e724bd Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 31 May 2016 00:00:00 +0000 Subject: [PATCH 27/69] * add generic changelog (#502) --- ChangeLog | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 ChangeLog diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..9a32e42f --- /dev/null +++ b/ChangeLog @@ -0,0 +1,86 @@ +# for this file format description, +# see https://github.com/olivierlacan/keep-a-changelog + +## [2.8.0] - UNRELEASED +### Changed +- Proxy refactoring & speedup +- I2PControl refactoring & fixes (proper jsonrpc responses on errors) +- boost::regex no more needed + +### Fixed +- initscripts: added openrc one, in sysv-ish make I2PD_PORT optional + +## [2.7.0] - 2016-05-18 +### Added +- Precomputed El-Gamal/DH tables +- Configurable limit of transit tunnels + +### Changed +- Speed-up of assymetric crypto for non-x64 platforms +- Refactoring of web-console + +## [2.6.0] - 2016-03-31 +### Added +- Gracefull shutdown on SIGINT +- Numeric bandwidth limits (was: by router class) +- Jumpservices in web-console +- Logging to syslog +- Tray icon for windows application + +### Changed +- Logs refactoring +- Improved statistics in web-console + +### Deprecated: +- Renamed main/tunnels config files (will use old, if found, but emits warning) + +## [2.5.1] - 2016-03-10 +### Fixed +- Doesn't create ~/.i2pd dir if missing + +## [2.5.0] - 2016-03-04 +### Added +- IRC server tunnels +- SOCKS outproxy support +- Support for gzipped addressbook updates +- Support for router families + +### Changed +- Shared RTT/RTO between streams +- Filesystem work refactoring + +## [2.4.0] - 2016-02-03 +### Added +- X-I2P-* headers for server http-tunnels +- I2CP options for I2P tunnels +- Show I2P tunnels in webconsole + +### Changed +- Refactoring of cmdline/config parsing + +## [2.3.0] - 2016-01-12 +### Added +- Support for new router bandwidth class codes (P and X) +- I2PControl supports external webui +- Added --pidfile and --notransit parameters +- Ability to specify signature type for i2p tunnel + +### Changed +- Fixed multiple floodfill-related bugs +- New webconsole layout + +## [2.2.0] - 2015-12-22 +### Added +- Ability to connect to router without ip via introducer + +### Changed +- Persist temporary encryption keys for local destinations +- Performance improvements for EdDSA +- New addressbook structure + +## [2.1.0] - 2015-11-12 +### Added +- Implementation of EdDSA + +### Changed +- EdDSA is default signature type for new RouterInfos From f9718bccb9c06e94ee412afdb5a378f8acfbeff6 Mon Sep 17 00:00:00 2001 From: hagen Date: Tue, 31 May 2016 00:00:00 +0000 Subject: [PATCH 28/69] * update debian changelog (closes #502) --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index 52bca793..5ac732e0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.7.0-1) unstable; urgency=low + + * updated to version 2.7.0/0.9.25 + + -- hagen Wed, 18 May 2016 01:11:04 +0000 + i2pd (2.2.0-2) unstable; urgency=low * updated to version 2.2.0 From 846ff46b2e2bf243411bfc2586f37b08e2e725ec Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 30 May 2016 21:42:25 -0400 Subject: [PATCH 29/69] fixed build error --- I2PService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2PService.cpp b/I2PService.cpp index 6a0cd291..9bbe1521 100644 --- a/I2PService.cpp +++ b/I2PService.cpp @@ -150,7 +150,7 @@ namespace client void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { - LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int) bytes_transfered, , " bytes received"); + LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received"); if (ecode) { LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message()); if (ecode != boost::asio::error::operation_aborted) From 025eec1782994d01c46a28ac9be973be5a8200dd Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 31 May 2016 11:54:45 -0400 Subject: [PATCH 30/69] I2CP configuration --- ClientContext.cpp | 26 +++++++++++++ Config.cpp | 8 ++++ I2CP.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++-- I2CP.h | 23 +++++++++++ 4 files changed, 151 insertions(+), 4 deletions(-) diff --git a/ClientContext.cpp b/ClientContext.cpp index df0de4e5..db1c8e6a 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -114,6 +114,24 @@ namespace client } } + // I2CP + bool i2cp; i2p::config::GetOption("i2cp.enabled", i2cp); + if (i2cp) + { + std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr); + uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort); + LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort); + try + { + m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort); + m_I2CPServer->Start (); + } + catch (std::exception& e) + { + LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what()); + } + } + m_AddressBook.StartResolvers (); } @@ -165,6 +183,14 @@ namespace client m_BOBCommandChannel = nullptr; } + if (m_I2CPServer) + { + LogPrint(eLogInfo, "Clients: stopping I2CP"); + m_I2CPServer->Stop (); + delete m_I2CPServer; + m_I2CPServer = nullptr; + } + LogPrint(eLogInfo, "Clients: stopping AddressBook"); m_AddressBook.Stop (); for (auto it: m_Destinations) diff --git a/Config.cpp b/Config.cpp index 44dec286..d9b4091d 100644 --- a/Config.cpp +++ b/Config.cpp @@ -178,6 +178,13 @@ namespace config { ("bob.port", value()->default_value(2827), "BOB listen port") ; + options_description i2cp("I2CP options"); + bob.add_options() + ("i2cp.enabled", value()->default_value(false), "Enable or disable I2CP") + ("i2cp.address", value()->default_value("127.0.0.1"), "I2CP listen address") + ("i2cp.port", value()->default_value(7654), "I2CP listen port") + ; + options_description i2pcontrol("I2PControl options"); i2pcontrol.add_options() ("i2pcontrol.enabled", value()->default_value(false), "Enable or disable I2P Control Protocol") @@ -207,6 +214,7 @@ namespace config { .add(socksproxy) .add(sam) .add(bob) + .add(i2cp) .add(i2pcontrol) .add(precomputation) ; diff --git a/I2CP.cpp b/I2CP.cpp index 8d0bedf1..94d5db7f 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -61,9 +61,9 @@ namespace client I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), - m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), - m_SessionID (0) + m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0) { + RAND_bytes ((uint8_t *)&m_SessionID, 2); ReadProtocolByte (); } @@ -72,6 +72,10 @@ namespace client delete[] m_NextMessage; } + void I2CPSession::Close () + { + } + void I2CPSession::ReadProtocolByte () { if (m_Socket) @@ -148,6 +152,12 @@ namespace client void I2CPSession::Terminate () { + if (m_Destination) + { + m_Destination->Stop (); + m_Destination = nullptr; + } + m_Owner.RemoveSession (GetSessionID ()); } void I2CPSession::SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len) @@ -212,7 +222,7 @@ namespace client if (identity->Verify (buf, offset, buf + offset)) // signature { m_Destination = std::make_shared(*this, identity, false); - RAND_bytes ((uint8_t *)&m_SessionID, 2); + m_Destination->Start (); SendSessionStatusMessage (1); // created } else @@ -264,7 +274,9 @@ namespace client LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } - I2CPServer::I2CPServer (const std::string& interface, int port) + I2CPServer::I2CPServer (const std::string& interface, int port): + m_IsRunning (false), m_Thread (nullptr), + m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port)) { memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers)); m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; @@ -272,6 +284,84 @@ namespace client m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; } + + I2CPServer::~I2CPServer () + { + if (m_IsRunning) + Stop (); + } + + void I2CPServer::Start () + { + Accept (); + m_IsRunning = true; + m_Thread = new std::thread (std::bind (&I2CPServer::Run, this)); + } + + void I2CPServer::Stop () + { + m_IsRunning = false; + m_Acceptor.cancel (); + for (auto it: m_Sessions) + it.second->Close (); + m_Sessions.clear (); + m_Service.stop (); + if (m_Thread) + { + m_Thread->join (); + delete m_Thread; + m_Thread = nullptr; + } + } + + void I2CPServer::Run () + { + while (m_IsRunning) + { + try + { + m_Service.run (); + } + catch (std::exception& ex) + { + LogPrint (eLogError, "I2CP: runtime exception: ", ex.what ()); + } + } + } + + void I2CPServer::Accept () + { + auto newSocket = std::make_shared (m_Service); + m_Acceptor.async_accept (*newSocket, std::bind (&I2CPServer::HandleAccept, this, + std::placeholders::_1, newSocket)); + } + + void I2CPServer::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket) + { + if (!ecode && socket) + { + boost::system::error_code ec; + auto ep = socket->remote_endpoint (ec); + if (!ec) + { + LogPrint (eLogDebug, "I2CP: new connection from ", ep); + auto session = std::make_shared(*this, socket); + m_Sessions[session->GetSessionID ()] = session; + } + else + LogPrint (eLogError, "I2CP: incoming connection error ", ec.message ()); + } + else + LogPrint (eLogError, "I2CP: accept error: ", ecode.message ()); + + if (ecode != boost::asio::error::operation_aborted) + Accept (); + } + + void I2CPServer::RemoveSession (uint16_t sessionID) + { + m_Sessions.erase (sessionID); + } } } diff --git a/I2CP.h b/I2CP.h index fca3317d..74ccb3f2 100644 --- a/I2CP.h +++ b/I2CP.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include "Destination.h" @@ -72,6 +74,7 @@ namespace client ~I2CPSession (); uint16_t GetSessionID () const { return m_SessionID; }; + void Close (); void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); // message handlers @@ -111,10 +114,30 @@ namespace client public: I2CPServer (const std::string& interface, int port); + ~I2CPServer (); + + void Start (); + void Stop (); + boost::asio::io_service& GetService () { return m_Service; }; + + void RemoveSession (uint16_t sessionID); + + private: + + void Run (); + + void Accept (); + void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); private: I2CPMessageHandler m_MessagesHandlers[256]; + std::map > m_Sessions; + + bool m_IsRunning; + std::thread * m_Thread; + boost::asio::io_service m_Service; + boost::asio::ip::tcp::acceptor m_Acceptor; public: From f62d25fa5f9fc36c9e048df43eaf88169f18339b Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 1 Jun 2016 00:00:00 +0000 Subject: [PATCH 31/69] * Config.cpp : fix wrong group for options & code style --- Config.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Config.cpp b/Config.cpp index d9b4091d..da4f160b 100644 --- a/Config.cpp +++ b/Config.cpp @@ -178,11 +178,11 @@ namespace config { ("bob.port", value()->default_value(2827), "BOB listen port") ; - options_description i2cp("I2CP options"); - bob.add_options() + options_description i2cp("I2CP options"); + i2cp.add_options() ("i2cp.enabled", value()->default_value(false), "Enable or disable I2CP") ("i2cp.address", value()->default_value("127.0.0.1"), "I2CP listen address") - ("i2cp.port", value()->default_value(7654), "I2CP listen port") + ("i2cp.port", value()->default_value(7654), "I2CP listen port") ; options_description i2pcontrol("I2PControl options"); @@ -208,15 +208,15 @@ namespace config { m_OptionsDesc .add(general) - .add(limits) .add(httpserver) .add(httpproxy) .add(socksproxy) .add(sam) .add(bob) - .add(i2cp) + .add(i2cp) .add(i2pcontrol) - .add(precomputation) + .add(precomputation) + .add(limits) ; } From 1b2ac38a507c16a47474145b53f865084f5229dd Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 1 Jun 2016 00:00:00 +0000 Subject: [PATCH 32/69] * fix compilation warnings --- AddressBook.cpp | 2 +- Daemon.cpp | 4 ++-- Daemon.h | 2 -- DaemonLinux.cpp | 2 +- DaemonWin32.cpp | 2 +- HTTP.cpp | 3 +-- HTTPServer.cpp | 2 +- NetDb.cpp | 3 ++- RouterInfo.cpp | 2 +- Transports.cpp | 2 +- Tunnel.cpp | 2 +- Tunnel.h | 2 +- 12 files changed, 13 insertions(+), 15 deletions(-) diff --git a/AddressBook.cpp b/AddressBook.cpp index 5a07b3c8..0dbb42d7 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -159,7 +159,7 @@ namespace client int AddressBookFilesystemStorage::Save (const std::map& addresses) { - if (addresses.size() == 0) { + if (addresses.empty()) { LogPrint(eLogWarning, "Addressbook: not saving empty addressbook"); return 0; } diff --git a/Daemon.cpp b/Daemon.cpp index c98bce05..7ca28a6f 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -45,10 +45,10 @@ namespace i2p #endif }; - Daemon_Singleton::Daemon_Singleton() : running(1), d(*new Daemon_Singleton_Private()) {}; + Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {} Daemon_Singleton::~Daemon_Singleton() { delete &d; - }; + } bool Daemon_Singleton::IsService () const { diff --git a/Daemon.h b/Daemon.h index 031686f7..977d9258 100644 --- a/Daemon.h +++ b/Daemon.h @@ -22,9 +22,7 @@ namespace i2p virtual bool stop(); virtual void run () {}; - bool isLogging; bool isDaemon; - bool running; protected: diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index b408fc70..a3848c8b 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -45,7 +45,7 @@ namespace i2p { bool DaemonLinux::start() { - if (isDaemon == 1) + if (isDaemon) { pid_t pid; pid = fork(); diff --git a/DaemonWin32.cpp b/DaemonWin32.cpp index a6d91da4..3afb70ce 100644 --- a/DaemonWin32.cpp +++ b/DaemonWin32.cpp @@ -45,7 +45,7 @@ namespace i2p return false; } - if (isDaemon == 1) + if (isDaemon) { LogPrint(eLogDebug, "Daemon: running as service"); I2PService service(SERVICE_NAME); diff --git a/HTTP.cpp b/HTTP.cpp index 3f6fd937..ee1010ec 100644 --- a/HTTP.cpp +++ b/HTTP.cpp @@ -406,11 +406,10 @@ namespace http { bool MergeChunkedResponse (std::istream& in, std::ostream& out) { std::string hexLen; - long int len; while (!in.eof ()) { std::getline (in, hexLen); errno = 0; - len = strtoul(hexLen.c_str(), (char **) NULL, 16); + long int len = strtoul(hexLen.c_str(), (char **) NULL, 16); if (errno != 0) return false; /* conversion error */ if (len == 0) diff --git a/HTTPServer.cpp b/HTTPServer.cpp index 2af92057..fba4a1be 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -667,7 +667,7 @@ namespace http { i2p::config::GetOption("http.auth", needAuth); i2p::config::GetOption("http.user", user); i2p::config::GetOption("http.pass", pass); - }; + } void HTTPConnection::Receive () { diff --git a/NetDb.cpp b/NetDb.cpp index 3aeff92f..d2afc50a 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -849,7 +849,8 @@ namespace data template std::shared_ptr NetDb::GetRandomRouter (Filter filter) const { - if (!m_RouterInfos.size ()) return 0; + if (m_RouterInfos.empty()) + return 0; uint32_t ind = rand () % m_RouterInfos.size (); for (int j = 0; j < 2; j++) { diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 2e76127c..0ef2f623 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -353,7 +353,7 @@ namespace data if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable - SetProperty ("caps", caps.c_str ()); + SetProperty ("caps", caps); } void RouterInfo::WriteToStream (std::ostream& s) diff --git a/Transports.cpp b/Transports.cpp index 057e2472..2d3d423f 100644 --- a/Transports.cpp +++ b/Transports.cpp @@ -606,7 +606,7 @@ namespace transport std::shared_ptr Transports::GetRandomPeer () const { - if (!m_Peers.size ()) return nullptr; + if (m_Peers.empty ()) return nullptr; std::unique_lock l(m_PeersMutex); auto it = m_Peers.begin (); std::advance (it, rand () % m_Peers.size ()); diff --git a/Tunnel.cpp b/Tunnel.cpp index ebaf98c8..1403330b 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -358,7 +358,7 @@ namespace tunnel std::shared_ptr Tunnels::GetNextOutboundTunnel () { - if (!m_OutboundTunnels.size ()) return nullptr; + if (m_OutboundTunnels.empty ()) return nullptr; uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0; std::shared_ptr tunnel; for (auto it: m_OutboundTunnels) diff --git a/Tunnel.h b/Tunnel.h index fe6022ac..43417e5d 100644 --- a/Tunnel.h +++ b/Tunnel.h @@ -73,7 +73,7 @@ namespace tunnel bool HandleTunnelBuildResponse (uint8_t * msg, size_t len); - virtual void Print (std::stringstream& s) const {}; + virtual void Print (std::stringstream&) const {}; // implements TunnelBase void SendTunnelDataMsg (std::shared_ptr msg); From f7ca44cad833060de81008d06a4928be101ac440 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 1 Jun 2016 00:00:00 +0000 Subject: [PATCH 33/69] * fix compile warnings: reopen() usage --- DaemonLinux.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DaemonLinux.cpp b/DaemonLinux.cpp index a3848c8b..1cc0fa85 100644 --- a/DaemonLinux.cpp +++ b/DaemonLinux.cpp @@ -73,10 +73,10 @@ namespace i2p return false; } - // close stdin/stdout/stderr descriptors - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); + // point std{in,out,err} descriptors to /dev/null + stdin = freopen("/dev/null", "r", stdin); + stdout = freopen("/dev/null", "w", stdout); + stderr = freopen("/dev/null", "w", stderr); } // Pidfile From ca2e148ad7388c68891b7ec7684bb7d240913002 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 1 Jun 2016 00:00:00 +0000 Subject: [PATCH 34/69] * enable -Wextra for linux builds --- Makefile.linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.linux b/Makefile.linux index 70307267..e00fd705 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -1,5 +1,5 @@ # set defaults instead redefine -CXXFLAGS ?= -g -Wall +CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic INCFLAGS ?= ## NOTE: The NEEDED_CXXFLAGS are here so that custom CXXFLAGS can be specified at build time From 8589493581b761c5764a233b2fb246e7a58e1d94 Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 1 Jun 2016 00:00:00 +0000 Subject: [PATCH 35/69] * add test for MergeChunkedResponse() (#432) --- tests/Makefile | 3 ++- tests/test-http-merge_chunked.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/test-http-merge_chunked.cpp diff --git a/tests/Makefile b/tests/Makefile index 199b7353..957d4632 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,7 @@ CXXFLAGS += -Wall -Wextra -pedantic -O0 -g -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1 -TESTS = test-http-url test-http-req test-http-res test-http-url_decode +TESTS = test-http-url test-http-req test-http-res test-http-url_decode \ + test-http-merge_chunked all: $(TESTS) run diff --git a/tests/test-http-merge_chunked.cpp b/tests/test-http-merge_chunked.cpp new file mode 100644 index 00000000..ba587a45 --- /dev/null +++ b/tests/test-http-merge_chunked.cpp @@ -0,0 +1,25 @@ +#include +#include "../HTTP.h" + +using namespace i2p::http; + +int main() { + const char *buf = + "4\r\n" + "HTTP\r\n" + "A\r\n" + " response \r\n" + "E\r\n" + "with \r\n" + "chunks.\r\n" + "0\r\n" + "\r\n" + ; + std::stringstream in(buf); + std::stringstream out; + + assert(MergeChunkedResponse(in, out) == true); + assert(out.str() == "HTTP response with \r\nchunks."); + + return 0; +} From cd237219e451b9bec8e13bc852c6726da92e02bc Mon Sep 17 00:00:00 2001 From: hagen Date: Wed, 1 Jun 2016 00:00:00 +0000 Subject: [PATCH 36/69] * extract unused image to separate file --- HTTPServer.cpp | 150 ------------------------------------------ HTTPServer.h | 1 - docs/itoopieImage.png | Bin 0 -> 8712 bytes 3 files changed, 151 deletions(-) create mode 100644 docs/itoopieImage.png diff --git a/HTTPServer.cpp b/HTTPServer.cpp index fba4a1be..7b7b8bcc 100644 --- a/HTTPServer.cpp +++ b/HTTPServer.cpp @@ -27,156 +27,6 @@ namespace i2p { namespace http { - const char *itoopieImage = - "\"ICToopie"; - const char *itoopieFavicon = "data:image/png;base64," "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv" diff --git a/HTTPServer.h b/HTTPServer.h index 2635c3be..bf7f5c65 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -3,7 +3,6 @@ namespace i2p { namespace http { - extern const char *itoopieImage; extern const char *itoopieFavicon; const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; diff --git a/docs/itoopieImage.png b/docs/itoopieImage.png new file mode 100644 index 0000000000000000000000000000000000000000..a5dc7b680ba9dee30161ffb1c9fcd17bbd6ddd84 GIT binary patch literal 8712 zcmV+jBKO^iP)#iZS6wU+M?20 zYwb(xf+$t%hC*Gcf>03@K~O*el_l&;SQ0|WKAD;OJikBgoyjbBCIJ$XkQ`t0BF=K} zbI9(t4FIPG^#{fQ7XZV7F30fO zZ-GyNCBR~!tW96E3>pT^1j+$rzvKzL0@v69`~}EsV{!AOUjX|XK;ZQO!xmst8_Syq z{Q>YbvfyKZp$hnAn+?!3bPF&GNU()bFG@~8_Q{1#8HkKjl&*uv3r8!^b{@psQ;2qq zd=Ws2J)Za50MPi91$+#gQ6Isd*#~*`c`)WoICmhzoq~oLqAvnm5P$|4r~~_vpMQt= z=qq?<1*-5UT0MEW)HXUjZ2)K-ngqO9m*8_dB7b`w+&&JGoPuV0k3mI*kfwo_0NZzC z&iVlHi9vBo$`0Y|qum2u3ZX~+@Bq(1a5%to1-WQ|r_nDQ5)%Ydfos~9fY>w?SnFi%XQZMIz6rY4Y_(Rc zUEqe{KS!?4k7*Nhz=|HW0U&~kf%ZsYDt99Cz!AqWud~74wgiOG zU+kF?MgO@UmD7a6H{75U=9+xe+siTMF2h{*4btmJ8txd&fr(i6ELx1%#aX~jZ5p7K z(t%PZW=$A{ocAYmzeB)92+)&Y&tBx`8<7Qv(Y=1i>45zHU_`I(X#VOG5PSma`S(yy zy@%Sc!x@0X`XT>%E8?PIXij5%X9ecxrucbt(^QgWZcZT7r*aAROoBPQ{e14=26ilBmmf?XpwL@O} zTeI-5!XcF_BNbCEMTRkOAu`cjEBw5?yv<4}vku{?`|i7Me&{{cJRL2Z!0VZ*VFIez zv}w~?RX;ic6a;?TuPc7FGy(t%QNOv)5daD}v$ZY(KXFq3zqt-&*3_zSO~C#CMtN*2 zyIs3>d$w-f+PgmEpD|;`xQP=dt`b5BfIFW?Ik|3z8)kkG9E+GfefsVJ0|wOBS8u;+ z)v6X!xYS*Db7VQoj(n=&&qHy0Nd_Xn6U2{rA8 zaDWZ6ot?es7=;hunlfdIKLGf- zpGJf3+nu%dy#D&@4H3F8dZ`M5J&WE~`xu9W!Rkab*}>dF7QkfxmYhL^^Tz+L1A} z?uD%l0OvcY|0~alQq64NA6!qxph1IV9oOB7RTUIQg9i`x1^(Vv0FgO7hF*JLm&fBtk)WoRWLIs@D+5m8-Q{*qNcR1Sw;PZzE>YOh2*=L{a$;`~$ zErjSLghIMW*r`*e0wKhg z6DCa9rj#mo8bf(`d3w+uNJn?{{Jk*pbVn_4Mr#8=kH|O9%0uA~XO5JRoe_Lbeg669 zQAL^y7A!b8YSgH%#l^+l?b&1$7Z(p1GGs`Xg$oxR2H3W3TX3T(H3<$6v~NgMZ^@F#9m9iHTyaILY98(K%P-e}s+V4RDJYKKogKty zBF3C)!NTM5bpQJ6uXpF=eTg-H+$%zhpGeL9XkxobXcsEg5EhX z4Z&6e07sXnTb4CLqU?fmYlT}>RMctp>eU-UX1|X(S;Ihw+i$=9>t~;Rwp~CtBTu)o zcfu@mA55tYJ*%NZhkDA&$_6_6u1cw=o_Z?GYG1Ty(N`NcZtNfU%EZyJUF@6=#Ij>@ zS_=Ri_x(Ghp*by^2`u$c-Svc2@LCekv z3a6h^DqcZRZ(t9=iWMuijvYI;ZvbHTOhhRa8vyN7W2TX}8UQ5WENDlD`%QReYN)X& zdSz#4AFQmbEE+g)V0t|RP5}JBb5WTY&d=@l!2B8Y502&M=YKwC%$RRSjvUz+tJ?^j zGLV1yDY}dU9Zkf%M@DM_faAWL&y3Cd>{{8z;T)K4W=>dSHB%;1~4$be2|3g#8TmoFJ1ptmLs*IDp zqZHga4&$%4h6yKa&YU?Tsb}rys((USQv4b2H{n+kFrK-Sy5bE%uK~+Yl?UE{jI_En zNJ!8r3LC8j0F_Q}?kU35iQ2puQCf+a z*$(5h9>`0EBGS^Ve8u{voCyJ23s5oK)k#cHK#NkIDm8zK3HYsv?c(ocY5=^mDUd6 zsY>s!ifM|hY;6Eo?X(2F`3Y!=r>5`?7re1F=2HA|YXg8ID@rQRR)2$eDgwacK`vb% zljrkW8vs6!^}*BswQ2xPHJbT;Ty3aY8vwv+q7+5{{s_(IZyJU)n)**f{drDI_5X5H zjjO2v@UK{|=mW1JwNt2<`Mi&j#bq(w?%7Q>uI9kvSaCm9GasR8Ex)C`k%;R21Jt1s z$7flH)m^kzY5;&oVgOOx{sgAc!b3trz!P(kF@!IG8BIFAX27EatlqkgYyO5=sDa&S zu_j@q2bpnAOkQurI@E&JtO06(M`MBU(tA*bt7Qt`NI;FdFQ)JX@T;aCV{@5V)39RU zQFQPK+Kmt6Z)qUVHF)?{%+EK*)Uum^1x-HAX2i4I#Au=R%}%r)S(s<#p{W+)9Ip5d zdD9~?Cz!yhj5^fR<7{pg_8Q{k$1i&fb^dA19|YU>V-CDEZubwLZTmDiH8px6 zhOV*!zpl*&0Ornx4?aM={4&aR598YYqXr{C{4>IBG+`4-7wU&IFyHv(xF?eU?g9SV zW&{F4Fj6UA$2#7%P9?7i)GO0aKf3JXoE8!~>zA*`f5jir%BsTnsLtnXI+7s|P^hip zoBHrs08e9`eb{ON;1+_pN^v#Eu{AohFKYQez}3jwz;MB?1E|SQpcbtO=ijxAl|SSv z4U~{5bTo8y*7B|Th|kn2*41^+(0jnutq}lM0`JyyJi!9a$PcbQ5Bcr`4S#}2pe5}W z>oFgA1tPnCX46qUz^_Cm8A8Uuu8xi$zj}pt)qIwSIM246813>;RRFvN{6GlemSX0R zEypq1cMfOzI+3Ziu}iy$M^n5ZMMh`zLT;Gt+*dfzug5g&m)30Z!$mOZ59SosqelP`RHxog_(vMX1#~}a5YLwM4w#Lpzes?IjD?OwDe?@Cam)S zk5CP_`e%Y%{0xM7(hE9l$elO(&+S@fct8b}{8m;s_A?X?=bC=?!Q8jK-cd|bn2;t`&W z^%Vs?1>D$@0pPaXo690C_YmQWA9Jvcx@FMHs1@5LmFQGJWB8R&C{O|%z!+?38 z)dC=o9`aZGpJ5^~(2+=0PNnqX6#_v5Zk0}&E|I#4i60YXkE0=l9!cM0a9zvOk6SVT zMgU9fh@NtScLwR|A?~j1M5e64TW?GHJ^tqoTyw$&DEtwTI2Y>um9?|~7OoWmLE73y zxN+(3kYHmK)tqcH&_#RN`AaC(>oAx%G{*h4Mg-OywomJdVd98UYMB289;wKtqg2Nb z`_T}5#OJ~5PQDTm>H9BURXh7TlcfeTpjoDsNhH~HtSgMXp(Sa63BcS~!I}X5R^3*4 z9z)G&|5?@PoP5BNpzza^Q5OwIgqD;WI=rwb)cClxQPuc~kOExs#qeQE@&f)1+#FBv zoyn3j_;pnpDe8EHpG2a1kHtaX|CiUGOizR+(@}G33(wTWj1c~2T5TqPI6))o#;#2uksPKcm*dp@)+ohr|IWO8^cxzeh zS~8k*n#A}^B!Nem74`n7tWxd>r)VQvc1V}amr;@PC=xV|EA61*F?TFF{h*vwbq5yQ~dF;lNbL>hmlAGP4i;4`Vy z=+`91-Ep zNZXbh&<)usD|+nDEvU8jhBG8)yuUF?M`tJd96xhmggyONd?#Z}7!TH_S&IXJwT#2x zBOgowM=29i`BSQii6Zpb6<)mD#ZRikA_AfoK%sQwMbV8JjYN3j-P(Je!p`x(hso87 z@LfWs!mlxYMD(m#w;6NG-rD!iZ-N6jBvQS?J8}nm9Y3$6TC2jN08FG>&YD=(|H~~M z006H5XF;?XUO|<(o%>QZu}#+_Qt204zJJ*IAG(wPy!tV+ssCGK|4FLcBYLq86Dw+1h}DbO{o*5VHZs9kF(Vrha<;RBRXe$t$O7X~X>8&(*y ztuN+NIdqwpNyh(r(z|jX^2T=Ts^^3|ax#~$1_i(f9%pWhhrE}bh9C8YfT03JK={F6 zkL~6K1e~nle=>*7D|?~lc4OZ!JF>rro8rjAOD7%s0ZWuPN%^iidRRDjcoK)Yx#$oW zlV5>^l;^w9^W`pVuLlSYw@3hd0=&X6#SNh5hP*$ETxQcptV78c5IkZPLiP>Vbb%Qk z`Y#|J?!=x+84Nf*5$*C+x;~Um?)E$~H|4SS@-zy9zjqkR8@w+nsX8fIAOdLO(o_<> z4tMq|n9z&}Vv69&Xn&4;b=UeuR1?-m3kRiI#O{}KZHWy;J zvNb`3@IgSLh(24eT0vJA-QMm-*G+j8b#+k~gPG#j{8>pFzm&!x@`+wZ%@uQfXAtp0C!>XBlgNK(6s4ff8`chJD?y`_(Grr zs9zt%n)4Do*)Ra@wzC6mB*j)>|pN@kyTh@!)2vu1Iz z5G;h+`aoMN2%z+i4)|}(fMJPL7{WetSinIadzM$BEvi6&y%bd?;~u=IE@lMhGnCWl zM*?omk4b&Q#X33(xY)@)xrCMckIw?GW>~Rmn#O^$f#g<1=q{Ilqb3FC?jUiO&-vg? ztn{y&TND5Q-U00zkdZFnbo=!^EQREo@i z3mE1OD$7=|=_uB@I;qq)S~}*nK9lyc7u`fJy3vVD)rm|kjT90|Py&GuKNVDp!<5MV z91>gE$p*G44>f_%WjWoD^uVByqvX>i;Mv}n#nu_wWcn2an``K~q>`#vOYyF*CN~bx zg{?g2(Nbs@@NW)kYxT#-(YNitUQNop!a3?kV0>u;*KW4A}dF1y)U-h}iNv9J^3Huo^m%-ZQY%n*0 zSjp0`hq#(fVleH@pOd1EpsRY2BiaHA%}Xyu|NFm?Kfe^c$9hWxXd3xSA(XPJb%Ps0 z@nWj+w3>?|a?ugME)>wQo|h09l+qa;Fwv-?3n_HPOD@UyNk9?a*0LjAN#g+JbUt2< zWY4FQPA9YkEFf2mW50Tt!Q9M-U}Wz)pc6gCQ|wZc$QD1PQ2i0BL?}RaUV#43&n)5J zF$I0*v)myiPiO)qRZ!p}BElU1IZ`O$biABF5-Fqymv;j%8z^QenW(s+7j)w=*OG=m zq>o>Ha!RYI;YB;L9X?i3&+(^VbxCVE8ekmz)hEDcI|D`pP1)0Mvxh&>S$t|0Vu_Eb z&CP!7Cd3!7SZtj(4Wq<^l#*1EN%YQ^F)VaH5AzY9X4#0G?z!%F*=` zSdFrO*Hm`g2|LDffh!`^+Z&*g*rxp_Lii7!jkb3qs;C&X5%}xlu=oXQ4AL(KnDMlv zvIXq}y!Ok-v7fW4lg`)}5yTF78>EClhAbPFI*WD0{Todw{00GlQxB7C=%US|O1@J{_(aihlKN0iLNrQM1F#?nZg)zT}eXaDH)0J=gnV=Ws0b z-?gbdxdzV&x{fo1L6y1=_z5t*0~|bv&~uR9+zZ7q;pbQQc_!IBv2bVu{IWgbop2Qi3jE7p#o9 za60>x13>V}A|9=O0j$}9oIV<^-wvNXia68@p%j^p7dU{?Xzi>e&?RE;z}+ZCgev4O zjr1r>x9=$nfVFEOH@EixKi+IT{Pa)YR)M(hJw$malIY`Ntk7sV?eS33D1%dgPI=gS z`(wrjP9)M&6SOrH8j1KL9N8|XEC2xZ$0&YX<3lX}47qkK07YS*dZ@R*z7eZC!lQzU zWt28}%Zy07#zjIzR50z720$!YzrkJ$ZwFvYn5Q1PiL#nxT=nc8b*v$<(uiJkrF0>` zfphW>2MtSsL5*FmEE+l(*Wv&WVkALmB7_Le4$WQ+l35owh3fc7$3q#ZQ95BEiFg~x z7<6H>!VU%L_;8U(4Mv0pC~e&Ucq#bTQdwhVdf@jbwZrp(7tscFabh0jy#hi|GU?-1z8Z=Or8tZq2f zMSHuJd=5VJ6U>|uR590Hhh0c=L$+=Fc#uFY1_qLCbYwOAk3sWP@is-QAfDwm9r?~3N+H`7`FdTSQzOj+kq97QA+oqX6c3(x1IGPfPH|+7FQk`%D%S% z4&kR99q@7?M;T0eByKdke8XWrAstC7)~>>PnNtN3k2}ApBooodrM}0G#PMYKx6) zsSk?7R8tzqM|tP6HhQIGXyEQk~4QFdqq+ zBqB*f1+~+OUGpbx8o-&#gVyz_O#}twEG`Dkfo`9$=+EbMjC$S-9OV9uYR>HQT z^^l;|Cxq0}#jVT&5?BXmwrK#H+F><+P)*DO)yO<6!RiFI4){?U0KzF3cpUfvjlWT~ z82A#aHXx9vlLlnkuWX=$ZIc*wV5$IEZ~vwoYx63!Qqdpss>W*j?twuRb1 literal 0 HcmV?d00001 From 689432f627125644c8589e98577f700880bf8e5f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 31 May 2016 21:37:32 -0400 Subject: [PATCH 37/69] fixed typo --- Config.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Config.cpp b/Config.cpp index da4f160b..e6d44d59 100644 --- a/Config.cpp +++ b/Config.cpp @@ -178,11 +178,11 @@ namespace config { ("bob.port", value()->default_value(2827), "BOB listen port") ; - options_description i2cp("I2CP options"); + options_description i2cp("I2CP options"); i2cp.add_options() ("i2cp.enabled", value()->default_value(false), "Enable or disable I2CP") ("i2cp.address", value()->default_value("127.0.0.1"), "I2CP listen address") - ("i2cp.port", value()->default_value(7654), "I2CP listen port") + ("i2cp.port", value()->default_value(7654), "I2CP listen port") ; options_description i2pcontrol("I2PControl options"); @@ -208,15 +208,15 @@ namespace config { m_OptionsDesc .add(general) + .add(limits) .add(httpserver) .add(httpproxy) .add(socksproxy) .add(sam) .add(bob) - .add(i2cp) + .add(i2cp) .add(i2pcontrol) - .add(precomputation) - .add(limits) + .add(precomputation) ; } From 153d883aebffc2066def97802d7dc1f6571c3df1 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Jun 2016 10:05:40 -0400 Subject: [PATCH 38/69] SessionDestoryedMessage --- I2CP.cpp | 21 ++++++++++++++++++--- I2CP.h | 5 ++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 94d5db7f..fd98ce44 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -64,7 +64,6 @@ namespace client m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0) { RAND_bytes ((uint8_t *)&m_SessionID, 2); - ReadProtocolByte (); } I2CPSession::~I2CPSession () @@ -72,7 +71,12 @@ namespace client delete[] m_NextMessage; } - void I2CPSession::Close () + void I2CPSession::Start () + { + ReadProtocolByte (); + } + + void I2CPSession::Stop () { } @@ -216,6 +220,7 @@ namespace client auto identity = std::make_shared(); size_t offset = identity->FromBuffer (buf, len); uint16_t optionsSize = bufbe16toh (buf + offset); + offset += 2; // TODO: extract options offset += optionsSize; offset += 8; // date @@ -224,6 +229,7 @@ namespace client m_Destination = std::make_shared(*this, identity, false); m_Destination->Start (); SendSessionStatusMessage (1); // created + LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); } else { @@ -232,6 +238,13 @@ namespace client } } + void I2CPSession::DestroySessionMessageHandler (const uint8_t * buf, size_t len) + { + SendSessionStatusMessage (0); // destroy + LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " destroyed"); + Terminate (); + } + void I2CPSession::SendSessionStatusMessage (uint8_t status) { uint8_t buf[3]; @@ -281,6 +294,7 @@ namespace client memset (m_MessagesHandlers, 0, sizeof (m_MessagesHandlers)); m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE] = &I2CPSession::CreateSessionMessageHandler; + m_MessagesHandlers[I2CP_DESTROY_SESSION_MESSAGE] = &I2CPSession::DestroySessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; } @@ -303,7 +317,7 @@ namespace client m_IsRunning = false; m_Acceptor.cancel (); for (auto it: m_Sessions) - it.second->Close (); + it.second->Stop (); m_Sessions.clear (); m_Service.stop (); if (m_Thread) @@ -347,6 +361,7 @@ namespace client LogPrint (eLogDebug, "I2CP: new connection from ", ep); auto session = std::make_shared(*this, socket); m_Sessions[session->GetSessionID ()] = session; + session->Start (); } else LogPrint (eLogError, "I2CP: incoming connection error ", ec.message ()); diff --git a/I2CP.h b/I2CP.h index 74ccb3f2..f68c4809 100644 --- a/I2CP.h +++ b/I2CP.h @@ -32,6 +32,7 @@ namespace client const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; + const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; @@ -73,13 +74,15 @@ namespace client I2CPSession (I2CPServer& owner, std::shared_ptr socket); ~I2CPSession (); + void Start (); + void Stop (); uint16_t GetSessionID () const { return m_SessionID; }; - void Close (); void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); // message handlers void GetDateMessageHandler (const uint8_t * buf, size_t len); void CreateSessionMessageHandler (const uint8_t * buf, size_t len); + void DestroySessionMessageHandler (const uint8_t * buf, size_t len); void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); void SendMessageMessageHandler (const uint8_t * buf, size_t len); From 6538a2e673bbf14a56e9fbf52679b039bd4eee20 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Jun 2016 11:11:18 -0400 Subject: [PATCH 39/69] HostLookupMessage --- I2CP.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- I2CP.h | 6 +++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index fd98ce44..7cef9013 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -287,6 +287,66 @@ namespace client LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } + void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len) + { + uint16_t sessionID = bufbe16toh (buf); + if (sessionID == m_SessionID) + { + uint32_t requestID = bufbe32toh (buf + 2); + //uint32_t timeout = bufbe32toh (buf + 6); + if (!buf[10]) // request type = 0 (hash) + { + if (m_Destination) + { + auto ls = m_Destination->FindLeaseSet (buf + 11); + if (ls) + SendHostReplyMessage (requestID, ls->GetIdentity ()); + else + { + auto s = shared_from_this (); + m_Destination->RequestDestination (buf + 11, + [s, requestID](std::shared_ptr leaseSet) + { + s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); + }); + } + } + else + SendHostReplyMessage (requestID, nullptr); + } + else + { + LogPrint (eLogError, "I2CP: request type ", (int)buf[8], " is not supported"); + SendHostReplyMessage (requestID, nullptr); + } + } + else + LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); + } + + void I2CPSession::SendHostReplyMessage (uint32_t requestID, std::shared_ptr identity) + { + if (identity) + { + size_t l = identity->GetFullLen () + 7; + uint8_t * buf = new uint8_t[l]; + htobe16buf (buf, m_SessionID); + htobe32buf (buf + 2, requestID); + buf[6] = 0; // result code + identity->ToBuffer (buf + 7, l - 7); + SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, l); + delete[] buf; + } + else + { + uint8_t buf[7]; + htobe16buf (buf, m_SessionID); + htobe32buf (buf + 2, requestID); + buf[6] = 1; // result code + SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, 7); + } + } + I2CPServer::I2CPServer (const std::string& interface, int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port)) @@ -296,7 +356,8 @@ namespace client m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE] = &I2CPSession::CreateSessionMessageHandler; m_MessagesHandlers[I2CP_DESTROY_SESSION_MESSAGE] = &I2CPSession::DestroySessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; - m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; + m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; + m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; } I2CPServer::~I2CPServer () diff --git a/I2CP.h b/I2CP.h index f68c4809..f3a88c9a 100644 --- a/I2CP.h +++ b/I2CP.h @@ -35,7 +35,9 @@ namespace client const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; - const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; + const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; + const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; + const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; class I2CPSession; class I2CPDestination: public LeaseSetDestination @@ -85,6 +87,7 @@ namespace client void DestroySessionMessageHandler (const uint8_t * buf, size_t len); void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); void SendMessageMessageHandler (const uint8_t * buf, size_t len); + void HostLookupMessageHandler (const uint8_t * buf, size_t len); private: @@ -99,6 +102,7 @@ namespace client size_t PutString (uint8_t * buf, size_t len, const std::string& str); void SendSessionStatusMessage (uint8_t status); + void SendHostReplyMessage (uint32_t requestID, std::shared_ptr identity); private: From d79c6b8f06d4435016ccee337a1de9a1ddf5b6da Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Jun 2016 14:38:13 -0400 Subject: [PATCH 40/69] MessagePayloadMessage --- I2CP.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- I2CP.h | 14 ++++++++++-- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 7cef9013..5d0f2865 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include "I2PEndian.h" #include "Log.h" @@ -29,6 +30,13 @@ namespace client memcpy (m_EncryptionPrivateKey, key, 256); } + void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len) + { + uint32_t length = bufbe32toh (buf); + if (length > len - 4) length = len - 4; + m_Owner.SendMessagePayloadMessage (buf + 4, length); + } + void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) { i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPrivateKey, tunnels); // we don't care about encryption key @@ -38,7 +46,6 @@ namespace client htobe16buf (leases - 3, m_Owner.GetSessionID ()); size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); m_Owner.SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); - } void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) @@ -56,12 +63,50 @@ namespace client memcpy (buf + 4, payload, len); msg->len += len + 4; msg->FillI2NPMessageHeader (eI2NPData); - // TODO: send + auto remote = FindLeaseSet (ident); + if (remote) + GetService ().post (std::bind (&I2CPDestination::SendMsg, GetSharedFromThis (), msg, remote)); + else + { + auto s = GetSharedFromThis (); + RequestDestination (ident, + [s, msg](std::shared_ptr ls) + { + if (ls) s->SendMsg (msg, ls); + }); + } + } + + void I2CPDestination::SendMsg (std::shared_ptr msg, std::shared_ptr remote) + { + auto outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (); + auto leases = remote->GetNonExpiredLeases (); + if (!leases.empty () && outboundTunnel) + { + std::vector msgs; + uint32_t i = rand () % leases.size (); + auto garlic = WrapMessage (remote, msg, true); + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { + i2p::tunnel::eDeliveryTypeTunnel, + leases[i]->tunnelGateway, leases[i]->tunnelID, + garlic + }); + outboundTunnel->SendTunnelDataMsg (msgs); + } + else + { + if (outboundTunnel) + LogPrint (eLogWarning, "I2CP: Failed to send message. All leases expired"); + else + LogPrint (eLogWarning, "I2CP: Failed to send message. No outbound tunnels"); + } } I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), - m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0) + m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), + m_MessageID (0) { RAND_bytes ((uint8_t *)&m_SessionID, 2); } @@ -347,6 +392,21 @@ namespace client } } + void I2CPSession::SendMessagePayloadMessage (const uint8_t * payload, size_t len) + { + // we don't use SendI2CPMessage to eliminate additional copy + auto l = len + 6 + I2CP_HEADER_SIZE; + uint8_t * buf = new uint8_t[l]; + htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len + 6); + buf[I2CP_HEADER_TYPE_OFFSET] = I2CP_MESSAGE_PAYLOAD_MESSAGE; + htobe16buf (buf + I2CP_HEADER_SIZE, m_SessionID); + htobe32buf (buf + I2CP_HEADER_SIZE + 2, m_MessageID++); + memcpy (buf + I2CP_HEADER_SIZE + 6, payload, len); + boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), + std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2, buf)); + } + I2CPServer::I2CPServer (const std::string& interface, int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(interface), port)) diff --git a/I2CP.h b/I2CP.h index f3a88c9a..b3693d3d 100644 --- a/I2CP.h +++ b/I2CP.h @@ -36,6 +36,7 @@ namespace client const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; + const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31; const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; @@ -57,9 +58,15 @@ namespace client std::shared_ptr GetIdentity () const { return m_Identity; }; // I2CP - void HandleDataMessage (const uint8_t * buf, size_t len) { /* TODO */ }; + void HandleDataMessage (const uint8_t * buf, size_t len); void CreateNewLeaseSet (std::vector > tunnels); + private: + + std::shared_ptr GetSharedFromThis () + { return std::static_pointer_cast(shared_from_this ()); } + void SendMsg (std::shared_ptr msg, std::shared_ptr remote); + private: I2CPSession& m_Owner; @@ -79,8 +86,10 @@ namespace client void Start (); void Stop (); uint16_t GetSessionID () const { return m_SessionID; }; + void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); - + void SendMessagePayloadMessage (const uint8_t * payload, size_t len); // called from I2CPDestination + // message handlers void GetDateMessageHandler (const uint8_t * buf, size_t len); void CreateSessionMessageHandler (const uint8_t * buf, size_t len); @@ -113,6 +122,7 @@ namespace client std::shared_ptr m_Destination; uint16_t m_SessionID; + uint32_t m_MessageID; }; typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); From ace3e86546efcca0f96ced93a02f31f93344901d Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 1 Jun 2016 15:30:57 -0400 Subject: [PATCH 41/69] MessageStatusMessage --- I2CP.cpp | 44 ++++++++++++++++++++++++++++++++++---------- I2CP.h | 17 ++++++++++++++--- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 5d0f2865..77330af4 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -55,7 +55,7 @@ namespace client SetLeaseSet (ls); } - void I2CPDestination::SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident) + void I2CPDestination::SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce) { auto msg = NewI2NPMessage (); uint8_t * buf = msg->GetPayload (); @@ -70,14 +70,20 @@ namespace client { auto s = GetSharedFromThis (); RequestDestination (ident, - [s, msg](std::shared_ptr ls) + [s, msg, nonce](std::shared_ptr ls) { - if (ls) s->SendMsg (msg, ls); + if (ls) + { + bool sent = s->SendMsg (msg, ls); + s->m_Owner.SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); + } + else + s->m_Owner.SendMessageStatusMessage (nonce, eI2CPMessageStatusNoLeaseSet); }); } } - void I2CPDestination::SendMsg (std::shared_ptr msg, std::shared_ptr remote) + bool I2CPDestination::SendMsg (std::shared_ptr msg, std::shared_ptr remote) { auto outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (); auto leases = remote->GetNonExpiredLeases (); @@ -93,6 +99,7 @@ namespace client garlic }); outboundTunnel->SendTunnelDataMsg (msgs); + return true; } else { @@ -100,13 +107,14 @@ namespace client LogPrint (eLogWarning, "I2CP: Failed to send message. All leases expired"); else LogPrint (eLogWarning, "I2CP: Failed to send message. No outbound tunnels"); + return false; } } I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), - m_MessageID (0) + m_MessageID (0) { RAND_bytes ((uint8_t *)&m_SessionID, 2); } @@ -298,6 +306,17 @@ namespace client SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); } + void I2CPSession::SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status) + { + uint8_t buf[15]; + htobe16buf (buf, m_SessionID); + htobe32buf (buf + 2, m_MessageID++); + buf[6] = (uint8_t)status; + memset (buf + 7, 0, 4); // size + htobe32buf (buf + 11, nonce); + SendI2CPMessage (I2CP_MESSAGE_STATUS_MESSAGE, buf, 15); + } + void I2CPSession::CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len) { uint16_t sessionID = bufbe16toh (buf); @@ -325,7 +344,11 @@ namespace client { i2p::data::IdentityEx identity; offset += identity.FromBuffer (buf + offset, len - offset); - m_Destination->SendMsgTo (buf + offset, len - offset, identity.GetIdentHash ()); + uint32_t payloadLen = bufbe32toh (buf + offset); + offset += 4; + uint32_t nonce = bufbe32toh (buf + offset + payloadLen); + SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted + m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); } } else @@ -395,13 +418,14 @@ namespace client void I2CPSession::SendMessagePayloadMessage (const uint8_t * payload, size_t len) { // we don't use SendI2CPMessage to eliminate additional copy - auto l = len + 6 + I2CP_HEADER_SIZE; + auto l = len + 10 + I2CP_HEADER_SIZE; uint8_t * buf = new uint8_t[l]; - htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len + 6); + htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len + 10); buf[I2CP_HEADER_TYPE_OFFSET] = I2CP_MESSAGE_PAYLOAD_MESSAGE; htobe16buf (buf + I2CP_HEADER_SIZE, m_SessionID); - htobe32buf (buf + I2CP_HEADER_SIZE + 2, m_MessageID++); - memcpy (buf + I2CP_HEADER_SIZE + 6, payload, len); + htobe32buf (buf + I2CP_HEADER_SIZE + 2, m_MessageID++); + htobe32buf (buf + I2CP_HEADER_SIZE + 6, len); + memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len); boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, buf)); diff --git a/I2CP.h b/I2CP.h index b3693d3d..4d50b5ef 100644 --- a/I2CP.h +++ b/I2CP.h @@ -37,9 +37,18 @@ namespace client const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31; + const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; + enum I2CPMessageStatus + { + eI2CPMessageStatusAccepted = 1, + eI2CPMessageStatusGuaranteedSuccess = 4, + eI2CPMessageStatusGuaranteedFailure = 5, + eI2CPMessageStatusNoLeaseSet = 21 + }; + class I2CPSession; class I2CPDestination: public LeaseSetDestination { @@ -49,7 +58,7 @@ namespace client void SetEncryptionPrivateKey (const uint8_t * key); void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession - void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident); // called from I2CPSession + void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession protected: @@ -65,7 +74,7 @@ namespace client std::shared_ptr GetSharedFromThis () { return std::static_pointer_cast(shared_from_this ()); } - void SendMsg (std::shared_ptr msg, std::shared_ptr remote); + bool SendMsg (std::shared_ptr msg, std::shared_ptr remote); private: @@ -87,8 +96,10 @@ namespace client void Stop (); uint16_t GetSessionID () const { return m_SessionID; }; + // called from I2CPDestination void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); - void SendMessagePayloadMessage (const uint8_t * payload, size_t len); // called from I2CPDestination + void SendMessagePayloadMessage (const uint8_t * payload, size_t len); + void SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status); // message handlers void GetDateMessageHandler (const uint8_t * buf, size_t len); From 26a6c9e932837a3c54e235bd8a9b6327e85e033c Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 2 Jun 2016 13:26:41 -0400 Subject: [PATCH 42/69] procee session options --- I2CP.cpp | 38 +++++++++++++++++++++++++++++++++----- I2CP.h | 8 ++++++-- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 77330af4..13a658a1 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -20,8 +20,8 @@ namespace i2p namespace client { - I2CPDestination::I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic): - LeaseSetDestination (isPublic), m_Owner (owner), m_Identity (identity) + I2CPDestination::I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic, const std::map& params): + LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity) { } @@ -141,7 +141,7 @@ namespace client m_Socket->async_read_some (boost::asio::buffer (m_Buffer, 1), [s](const boost::system::error_code& ecode, std::size_t bytes_transferred) { - if (!ecode && bytes_transferred > 0 && s->m_Buffer[0] == I2CP_PRTOCOL_BYTE) + if (!ecode && bytes_transferred > 0 && s->m_Buffer[0] == I2CP_PROTOCOL_BYTE) s->Receive (); else s->Terminate (); @@ -253,6 +253,30 @@ namespace client return l + 1; } + void I2CPSession::ExtractMapping (const uint8_t * buf, size_t len, std::map& mapping) + // TODO: move to Base.cpp + { + size_t offset = 0; + while (offset < len) + { + auto semicolon = (const uint8_t *)memchr (buf + offset, ';', len - offset); + if (semicolon) + { + auto l = semicolon - buf - offset + 1; + auto equal = (const uint8_t *)memchr (buf + offset, '=', l); + if (equal) + { + auto l1 = equal - buf - offset + 1; + mapping.insert (std::make_pair (std::string ((const char *)(buf + offset), l1 -1), + std::string ((const char *)(buf + offset + l1), l - l1 - 2))); + } + offset += l; + } + else + break; + } + } + void I2CPSession::GetDateMessageHandler (const uint8_t * buf, size_t len) { // get version @@ -274,12 +298,16 @@ namespace client size_t offset = identity->FromBuffer (buf, len); uint16_t optionsSize = bufbe16toh (buf + offset); offset += 2; - // TODO: extract options + + std::map params; + ExtractMapping (buf + offset, optionsSize, params); offset += optionsSize; offset += 8; // date if (identity->Verify (buf, offset, buf + offset)) // signature { - m_Destination = std::make_shared(*this, identity, false); + bool isPublic = true; + if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "false") isPublic = false; + m_Destination = std::make_shared(*this, identity, isPublic, params); m_Destination->Start (); SendSessionStatusMessage (1); // created LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); diff --git a/I2CP.h b/I2CP.h index 4d50b5ef..47e6f750 100644 --- a/I2CP.h +++ b/I2CP.h @@ -21,7 +21,7 @@ namespace i2p { namespace client { - const uint8_t I2CP_PRTOCOL_BYTE = 0x2A; + const uint8_t I2CP_PROTOCOL_BYTE = 0x2A; const size_t I2CP_SESSION_BUFFER_SIZE = 4096; const size_t I2CP_HEADER_LENGTH_OFFSET = 0; @@ -49,12 +49,15 @@ namespace client eI2CPMessageStatusNoLeaseSet = 21 }; + // params + const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet "; + class I2CPSession; class I2CPDestination: public LeaseSetDestination { public: - I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic); + I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic, const std::map& params); void SetEncryptionPrivateKey (const uint8_t * key); void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession @@ -120,6 +123,7 @@ namespace client void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); + void ExtractMapping (const uint8_t * buf, size_t len, std::map& mapping); void SendSessionStatusMessage (uint8_t status); void SendHostReplyMessage (uint32_t requestID, std::shared_ptr identity); From aa6bc8042a5edc8beeaa20edfaec7ab2f6ab9bf0 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 2 Jun 2016 15:49:14 -0400 Subject: [PATCH 43/69] address lookup --- I2CP.cpp | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 13a658a1..6cdc4ec9 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -13,6 +13,7 @@ #include "Log.h" #include "Timestamp.h" #include "LeaseSet.h" +#include "ClientContext.h" #include "I2CP.h" namespace i2p @@ -390,31 +391,46 @@ namespace client { uint32_t requestID = bufbe32toh (buf + 2); //uint32_t timeout = bufbe32toh (buf + 6); - if (!buf[10]) // request type = 0 (hash) + i2p::data::IdentHash ident; + switch (buf[10]) { - if (m_Destination) + case 0: // hash + ident = i2p::data::IdentHash (buf + 11); + break; + case 1: // address { - auto ls = m_Destination->FindLeaseSet (buf + 11); - if (ls) - SendHostReplyMessage (requestID, ls->GetIdentity ()); - else + auto name = ExtractString (buf + 11, len - 11); + if (!i2p::client::context.GetAddressBook ().GetIdentHash (name, ident)) { - auto s = shared_from_this (); - m_Destination->RequestDestination (buf + 11, - [s, requestID](std::shared_ptr leaseSet) - { - s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); - }); - } + LogPrint (eLogError, "I2CP: address ", name, " not found"); + SendHostReplyMessage (requestID, nullptr); + return; + } + break; } - else + default: + LogPrint (eLogError, "I2CP: request type ", (int)buf[10], " is not supported"); SendHostReplyMessage (requestID, nullptr); + return; } - else + + if (m_Destination) { - LogPrint (eLogError, "I2CP: request type ", (int)buf[8], " is not supported"); - SendHostReplyMessage (requestID, nullptr); + auto ls = m_Destination->FindLeaseSet (ident); + if (ls) + SendHostReplyMessage (requestID, ls->GetIdentity ()); + else + { + auto s = shared_from_this (); + m_Destination->RequestDestination (ident, + [s, requestID](std::shared_ptr leaseSet) + { + s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); + }); + } } + else + SendHostReplyMessage (requestID, nullptr); } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); From 26284260840d6eaefbe6e33dc9442e907095fb2c Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 3 Jun 2016 00:00:00 +0000 Subject: [PATCH 44/69] * http proxy : fix converted request (#508) --- HTTPProxy.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index cc534470..265d36e5 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -189,6 +189,12 @@ namespace proxy { return true; } SanitizeHTTPRequest(req); + /* convert proxy-style http req to ordinary one: */ + /* 1) replace Host header, 2) make relative url */ + req.add_header("Host", url.host, true); + url.schema = ""; + url.host = ""; + req.uri = url.to_string(); /* drop original request from input buffer */ m_recv_buf.erase(m_recv_buf.begin(), m_recv_buf.begin() + req_len); From aa764fbd1ccb50ce8ec58c2345eed4f4f4849f5b Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 3 Jun 2016 00:00:00 +0000 Subject: [PATCH 45/69] * HTTPProxy: fix converted request (#508) * I2PService: reword log message, to avoid ambiguity --- HTTPProxy.cpp | 5 ++++- I2PService.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 265d36e5..6bf33664 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -189,6 +189,9 @@ namespace proxy { return true; } SanitizeHTTPRequest(req); + + std::string dest_host = url.host; + uint16_t dest_host = url.port; /* convert proxy-style http req to ordinary one: */ /* 1) replace Host header, 2) make relative url */ req.add_header("Host", url.host, true); @@ -206,7 +209,7 @@ namespace proxy { /* connect to destination */ GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete, - shared_from_this(), std::placeholders::_1), url.host, url.port); + shared_from_this(), std::placeholders::_1), dest_host, dest_port); return true; } diff --git a/I2PService.cpp b/I2PService.cpp index 9bbe1521..4f907f18 100644 --- a/I2PService.cpp +++ b/I2PService.cpp @@ -27,7 +27,7 @@ namespace client m_LocalDestination->CreateStream (streamRequestComplete, identHash, port); else { - LogPrint (eLogWarning, "I2PService: Remote destination ", dest, " not found"); + LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest); streamRequestComplete (nullptr); } } From e50c35d38c81314be5d674a197334da3df5e86fa Mon Sep 17 00:00:00 2001 From: hagen Date: Fri, 3 Jun 2016 00:00:00 +0000 Subject: [PATCH 46/69] * fix mistype --- HTTPProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 6bf33664..934dbbf5 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -191,7 +191,7 @@ namespace proxy { SanitizeHTTPRequest(req); std::string dest_host = url.host; - uint16_t dest_host = url.port; + uint16_t dest_port = url.port; /* convert proxy-style http req to ordinary one: */ /* 1) replace Host header, 2) make relative url */ req.add_header("Host", url.host, true); From c8d6425123e00083d6fb3d674348b9c298dde733 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Jun 2016 11:49:39 -0400 Subject: [PATCH 47/69] DestLookupMessage --- I2CP.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- I2CP.h | 3 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 6cdc4ec9..afd10466 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -307,7 +307,7 @@ namespace client if (identity->Verify (buf, offset, buf + offset)) // signature { bool isPublic = true; - if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "false") isPublic = false; + if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false; m_Destination = std::make_shared(*this, identity, isPublic, params); m_Destination->Start (); SendSessionStatusMessage (1); // created @@ -459,6 +459,43 @@ namespace client } } + void I2CPSession::DestLookupMessageHandler (const uint8_t * buf, size_t len) + { + if (m_Destination) + { + auto ls = m_Destination->FindLeaseSet (buf); + if (ls) + { + auto l = ls->GetIdentity ()->GetFullLen (); + uint8_t * identBuf = new uint8_t[l]; + ls->GetIdentity ()->ToBuffer (identBuf, l); + SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, identBuf, l); + delete[] identBuf; + } + else + { + auto s = shared_from_this (); + i2p::data::IdentHash ident (buf); + m_Destination->RequestDestination (ident, + [s, ident](std::shared_ptr leaseSet) + { + if (leaseSet) // found + { + auto l = leaseSet->GetIdentity ()->GetFullLen (); + uint8_t * identBuf = new uint8_t[l]; + leaseSet->GetIdentity ()->ToBuffer (identBuf, l); + s->SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, identBuf, l); + delete[] identBuf; + } + else + s->SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, ident, 32); // not found + }); + } + } + else + SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32); + } + void I2CPSession::SendMessagePayloadMessage (const uint8_t * payload, size_t len) { // we don't use SendI2CPMessage to eliminate additional copy @@ -485,7 +522,8 @@ namespace client m_MessagesHandlers[I2CP_DESTROY_SESSION_MESSAGE] = &I2CPSession::DestroySessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; - m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; + m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; + m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; } I2CPServer::~I2CPServer () diff --git a/I2CP.h b/I2CP.h index 47e6f750..a3e0dde0 100644 --- a/I2CP.h +++ b/I2CP.h @@ -40,6 +40,8 @@ namespace client const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; + const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34; + const uint8_t I2CP_DEST_REPLY_MESSAGE = 35; enum I2CPMessageStatus { @@ -111,6 +113,7 @@ namespace client void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); void SendMessageMessageHandler (const uint8_t * buf, size_t len); void HostLookupMessageHandler (const uint8_t * buf, size_t len); + void DestLookupMessageHandler (const uint8_t * buf, size_t len); private: From 444539b8263d899927e26ecc8cf25915ec009eed Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Jun 2016 12:03:36 -0400 Subject: [PATCH 48/69] SendMessageExpires --- I2CP.cpp | 6 ++++++ I2CP.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/I2CP.cpp b/I2CP.cpp index afd10466..b2685e80 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -384,6 +384,11 @@ namespace client LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } + void I2CPSession::SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len) + { + SendMessageMessageHandler (buf, len - 8); // ignore flags(2) and expiration(6) + } + void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len) { uint16_t sessionID = bufbe16toh (buf); @@ -522,6 +527,7 @@ namespace client m_MessagesHandlers[I2CP_DESTROY_SESSION_MESSAGE] = &I2CPSession::DestroySessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; + m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; } diff --git a/I2CP.h b/I2CP.h index a3e0dde0..273dcb65 100644 --- a/I2CP.h +++ b/I2CP.h @@ -36,6 +36,7 @@ namespace client const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; + const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36; const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31; const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; @@ -112,6 +113,7 @@ namespace client void DestroySessionMessageHandler (const uint8_t * buf, size_t len); void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); void SendMessageMessageHandler (const uint8_t * buf, size_t len); + void SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len); void HostLookupMessageHandler (const uint8_t * buf, size_t len); void DestLookupMessageHandler (const uint8_t * buf, size_t len); From d6bfe7810a3e06fdedb5f1bfeac09db18ada6ae7 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Jun 2016 13:01:12 -0400 Subject: [PATCH 49/69] skip SigningPrivateKey --- I2CP.cpp | 1 + I2CP.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index b2685e80..ba6825b8 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -354,6 +354,7 @@ namespace client size_t offset = 2; if (m_Destination) { + offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); // skip signing private key m_Destination->SetEncryptionPrivateKey (buf + offset); offset += 256; m_Destination->LeaseSetCreated (buf + offset, len - offset); diff --git a/I2CP.h b/I2CP.h index 273dcb65..20bd33a5 100644 --- a/I2CP.h +++ b/I2CP.h @@ -66,12 +66,12 @@ namespace client void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession - protected: - // implements LocalDestination const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; }; std::shared_ptr GetIdentity () const { return m_Identity; }; + protected: + // I2CP void HandleDataMessage (const uint8_t * buf, size_t len); void CreateNewLeaseSet (std::vector > tunnels); From 667ea43b3ca9b4e711be7e17455b0974d51a6243 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Jun 2016 13:48:21 -0400 Subject: [PATCH 50/69] GetBandwidthLimitMessage --- I2CP.cpp | 13 ++++++++++++- I2CP.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/I2CP.cpp b/I2CP.cpp index ba6825b8..8faa07e7 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -14,6 +14,7 @@ #include "Timestamp.h" #include "LeaseSet.h" #include "ClientContext.h" +#include "Transports.h" #include "I2CP.h" namespace i2p @@ -241,7 +242,7 @@ namespace client { uint8_t l = buf[0]; if (l > len) l = len; - return std::string ((const char *)buf, l); + return std::string ((const char *)(buf + 1), l); } size_t I2CPSession::PutString (uint8_t * buf, size_t len, const std::string& str) @@ -502,6 +503,15 @@ namespace client SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32); } + void I2CPSession::GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len) + { + uint8_t limits[64]; + memset (limits, 0, 64); + htobe32buf (limits, i2p::transport::transports.GetInBandwidth ()); // inbound + htobe32buf (limits + 4, i2p::transport::transports.GetOutBandwidth ()); // outbound + SendI2CPMessage (I2CP_BANDWIDTH_LIMITS_MESSAGE, limits, 64); + } + void I2CPSession::SendMessagePayloadMessage (const uint8_t * payload, size_t len) { // we don't use SendI2CPMessage to eliminate additional copy @@ -531,6 +541,7 @@ namespace client m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; + m_MessagesHandlers[I2CP_GET_BANDWIDTH_LIMITS_MESSAGE] = &I2CPSession::GetBandwidthLimitsMessageHandler; } I2CPServer::~I2CPServer () diff --git a/I2CP.h b/I2CP.h index 20bd33a5..453c5d40 100644 --- a/I2CP.h +++ b/I2CP.h @@ -43,6 +43,8 @@ namespace client const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34; const uint8_t I2CP_DEST_REPLY_MESSAGE = 35; + const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8; + const uint8_t I2CP_BANDWIDTH_LIMITS_MESSAGE = 23; enum I2CPMessageStatus { @@ -116,6 +118,7 @@ namespace client void SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len); void HostLookupMessageHandler (const uint8_t * buf, size_t len); void DestLookupMessageHandler (const uint8_t * buf, size_t len); + void GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len); private: From e4edc59689cee2ad15c02d901952a04dd28e49c4 Mon Sep 17 00:00:00 2001 From: hagen Date: Sat, 4 Jun 2016 00:00:00 +0000 Subject: [PATCH 51/69] * HTTPProxy.cpp : force clean recv buffer (#508) --- HTTPProxy.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 934dbbf5..0d305a47 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -224,8 +224,10 @@ namespace proxy { return; } - if (HandleRequest(len)) + if (HandleRequest(len)) { + m_recv_buf.clear(); return; /* request processed */ + } AsyncSockRead(); } From 66c301c03109088dc7b44f5708fa50b58440cdb6 Mon Sep 17 00:00:00 2001 From: hagen Date: Sat, 4 Jun 2016 00:00:00 +0000 Subject: [PATCH 52/69] * HTTPProxy.cpp : allow "tranparent" proxy (#508) --- HTTPProxy.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index 0d305a47..e8926dc6 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -192,9 +192,28 @@ namespace proxy { std::string dest_host = url.host; uint16_t dest_port = url.port; - /* convert proxy-style http req to ordinary one: */ - /* 1) replace Host header, 2) make relative url */ - req.add_header("Host", url.host, true); + /* set proper 'Host' header in upstream request */ + auto h = req.headers.find("Host"); + if (dest_host != "") { + /* absolute url, replace 'Host' header */ + std::string h = dest_host; + if (dest_port != 0 && dest_port != 80) + h += ":" + std::to_string(dest_port); + req.add_header("Host", h, true); + } else if (h != req.headers.end()) { + /* relative url and 'Host' header provided. transparent proxy mode? */ + i2p::http::URL u; + std::string t = "http://" + h->second; + u.parse(t); + dest_host = u.host; + dest_port = u.port; + } else { + /* relative url and missing 'Host' header */ + std::string message = "Can't detect destination host from request"; + HTTPRequestFailed(message.c_str()); + return true; + } + /* make relative url */ url.schema = ""; url.host = ""; req.uri = url.to_string(); From 03973cc6d4fa6cf17681b5a7f514bc8a8d781368 Mon Sep 17 00:00:00 2001 From: hagen Date: Sat, 4 Jun 2016 00:00:00 +0000 Subject: [PATCH 53/69] * HTTPProxy.cpp : drop X-Forwarded-*, Proxy-*, Via headers from request --- HTTPProxy.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index e8926dc6..a2bc4828 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -137,8 +137,24 @@ namespace proxy { void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) { req.del_header("Referer"); - req.add_header("Connection", "close", true); - req.add_header("User-Agent", "MYOB/6.66 (AN/ON)", true); + req.del_header("Via"); + req.del_header("Forwarded"); + std::vector toErase; + for (auto it : req.headers) { + if (it.first.compare(0, 12, "X-Forwarded-")) { + toErase.push_back(it.first); + } else if (it.first.compare(0, 6, "Proxy-")) { + toErase.push_back(it.first); + } else { + /* allow this header */ + } + } + for (auto header : toErase) { + req.headers.erase(header); + } + /* replace headers */ + req.add_header("Connection", "close", true); /* keep-alive conns not supported yet */ + req.add_header("User-Agent", "MYOB/6.66 (AN/ON)", true); /* privacy */ } /** From a4dc67cba0b85e266b69778fa27a84618bca39bf Mon Sep 17 00:00:00 2001 From: hagen Date: Sat, 4 Jun 2016 00:00:00 +0000 Subject: [PATCH 54/69] * HTTP.{cpp,h} : drop HTTPReq.host --- HTTP.cpp | 9 --------- HTTP.h | 1 - 2 files changed, 10 deletions(-) diff --git a/HTTP.cpp b/HTTP.cpp index ee1010ec..a23f5a72 100644 --- a/HTTP.cpp +++ b/HTTP.cpp @@ -253,21 +253,12 @@ namespace http { if (pos >= eoh) break; } - auto it = headers.find("Host"); - if (it != headers.end ()) { - host = it->second; - } else if (version == "HTTP/1.1") { - return -1; /* 'Host' header required for HTTP/1.1 */ - } else if (url.host != "") { - host = url.host; - } return eoh + strlen(HTTP_EOH); } std::string HTTPReq::to_string() { std::stringstream ss; ss << method << " " << uri << " " << version << CRLF; - ss << "Host: " << host << CRLF; for (auto & h : headers) { ss << h.first << ": " << h.second << CRLF; } diff --git a/HTTP.h b/HTTP.h index 8d10c231..19d0612e 100644 --- a/HTTP.h +++ b/HTTP.h @@ -69,7 +69,6 @@ namespace http { std::string version; std::string method; std::string uri; - std::string host; HTTPReq (): version("HTTP/1.0"), method("GET"), uri("/") {}; From 4d7c089b099fbc7b3a4db58b215fab136fd7de16 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 5 Jun 2016 10:31:55 -0400 Subject: [PATCH 55/69] I2CP config --- docs/configuration.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 11e8b4a8..9ab85b46 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -58,7 +58,11 @@ All options below still possible in cmdline, but better write it in config file: * --bob.address= - The address to listen on (BOB command channel) * --bob.port= - Port of BOB command channel. Usually 2827. BOB is off if not specified -* --sam.enabled= - If BOB is enabled. false by default +* --bob.enabled= - If BOB is enabled. false by default + +* --i2cp.address= - The address to listen on +* --i2cp.port= - Port of I2CP server. Usually 7654. IPCP is off if not specified +* --i2cp.enabled= - If I2CP is enabled. false by default. Other services don't requeire I2CP * --i2pcontrol.address= - The address to listen on (I2P control service) * --i2pcontrol.port= - Port of I2P control service. Usually 7650. I2PControl is off if not specified From e481ed37ce38ec46d8d2405362bb6d6a03430e26 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 6 Jun 2016 15:36:02 -0400 Subject: [PATCH 56/69] ReconfigureSessionMessage --- I2CP.cpp | 7 +++++++ I2CP.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/I2CP.cpp b/I2CP.cpp index 8faa07e7..44abdf8b 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -328,6 +328,12 @@ namespace client Terminate (); } + void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len) + { + // TODO: implement actual reconfiguration + SendSessionStatusMessage (2); // updated + } + void I2CPSession::SendSessionStatusMessage (uint8_t status) { uint8_t buf[3]; @@ -536,6 +542,7 @@ namespace client m_MessagesHandlers[I2CP_GET_DATE_MESSAGE] = &I2CPSession::GetDateMessageHandler; m_MessagesHandlers[I2CP_CREATE_SESSION_MESSAGE] = &I2CPSession::CreateSessionMessageHandler; m_MessagesHandlers[I2CP_DESTROY_SESSION_MESSAGE] = &I2CPSession::DestroySessionMessageHandler; + m_MessagesHandlers[I2CP_RECONFIGURE_SESSION_MESSAGE] = &I2CPSession::ReconfigureSessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; diff --git a/I2CP.h b/I2CP.h index 453c5d40..436b1ad6 100644 --- a/I2CP.h +++ b/I2CP.h @@ -31,6 +31,7 @@ namespace client const uint8_t I2CP_GET_DATE_MESSAGE = 32; const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; + const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2; const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; @@ -113,6 +114,7 @@ namespace client void GetDateMessageHandler (const uint8_t * buf, size_t len); void CreateSessionMessageHandler (const uint8_t * buf, size_t len); void DestroySessionMessageHandler (const uint8_t * buf, size_t len); + void ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len); void CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len); void SendMessageMessageHandler (const uint8_t * buf, size_t len); void SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len); From 5e068c3af5a2764aa3a7e78463142e46656ddf18 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 7 Jun 2016 13:05:44 -0400 Subject: [PATCH 57/69] 0.9.26 --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index bee17044..5d07c596 100644 --- a/version.h +++ b/version.h @@ -16,7 +16,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 25 +#define I2P_VERSION_MICRO 26 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From 37fc21f3cf2dce4d1fb9f8ebcfc5fda8f90c423a Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 8 Jun 2016 09:33:25 -0400 Subject: [PATCH 58/69] always assume 20 bytes for signing private key --- I2CP.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/I2CP.cpp b/I2CP.cpp index 44abdf8b..ec06895f 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -15,6 +15,7 @@ #include "LeaseSet.h" #include "ClientContext.h" #include "Transports.h" +#include "Signature.h" #include "I2CP.h" namespace i2p @@ -361,7 +362,10 @@ namespace client size_t offset = 2; if (m_Destination) { - offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); // skip signing private key + offset += i2p::crypto::DSA_PRIVATE_KEY_LENGTH; // skip signing private key + // we always assume this field as 20 bytes (DSA) regardless actual size + // instead of + //offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); m_Destination->SetEncryptionPrivateKey (buf + offset); offset += 256; m_Destination->LeaseSetCreated (buf + offset, len - offset); From 4d2b535b047ace4b219379dc3c632d3ac9f74ce3 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 8 Jun 2016 10:29:48 -0400 Subject: [PATCH 59/69] correct concatenation of long I2CP messages --- I2CP.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/I2CP.cpp b/I2CP.cpp index ec06895f..f7ad7dfd 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -164,25 +164,34 @@ namespace client Terminate (); else { - size_t offset = 0; + size_t offset = 0; // from m_Buffer if (m_NextMessage) { if (m_NextMessageOffset + bytes_transferred <= m_NextMessageLen) { memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred); m_NextMessageOffset += bytes_transferred; + offset = bytes_transferred; } else { + // m_NextMessage complete offset = m_NextMessageLen - m_NextMessageOffset; memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, offset); HandleNextMessage (m_NextMessage); delete[] m_NextMessage; + m_NextMessage = nullptr; } } while (offset < bytes_transferred) { auto msgLen = bufbe32toh (m_Buffer + offset + I2CP_HEADER_LENGTH_OFFSET) + I2CP_HEADER_SIZE; + if (msgLen > 0xFFFF) // 64K + { + LogPrint (eLogError, "I2CP: message length ", msgLen, " exceeds 64K. Terminated"); + Terminate (); + return; + } if (msgLen <= bytes_transferred - offset) { HandleNextMessage (m_Buffer + offset); @@ -217,6 +226,11 @@ namespace client m_Destination->Stop (); m_Destination = nullptr; } + if (m_Socket) + { + m_Socket->close (); + m_Socket = nullptr; + } m_Owner.RemoveSession (GetSessionID ()); } From d8f24b442bfa57d9d426560280e9896b05864882 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 8 Jun 2016 14:05:20 -0400 Subject: [PATCH 60/69] fixed mapping --- I2CP.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index f7ad7dfd..5447a622 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -276,21 +276,24 @@ namespace client size_t offset = 0; while (offset < len) { - auto semicolon = (const uint8_t *)memchr (buf + offset, ';', len - offset); - if (semicolon) + std::string param = ExtractString (buf + offset, len - offset); + offset += param.length (); + if (buf[offset] != '=') { - auto l = semicolon - buf - offset + 1; - auto equal = (const uint8_t *)memchr (buf + offset, '=', l); - if (equal) - { - auto l1 = equal - buf - offset + 1; - mapping.insert (std::make_pair (std::string ((const char *)(buf + offset), l1 -1), - std::string ((const char *)(buf + offset + l1), l - l1 - 2))); - } - offset += l; - } - else - break; + LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead '=' after ", param); + break; + } + offset++; + + std::string value = ExtractString (buf + offset, len - offset); + offset += value.length (); + if (buf[offset] != ';') + { + LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead ';' after ", value); + break; + } + offset++; + mapping.insert (std::make_pair (param, value)); } } From 21b5f2c96ab80631c85f9f2e1097ad9f90bc3bd8 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 8 Jun 2016 14:14:19 -0400 Subject: [PATCH 61/69] fixed crash upon I2CP session disconnect --- I2CP.cpp | 15 ++++++++------- I2CP.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 5447a622..e0ab180a 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -23,7 +23,7 @@ namespace i2p namespace client { - I2CPDestination::I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic, const std::map& params): + I2CPDestination::I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity) { } @@ -37,7 +37,7 @@ namespace client { uint32_t length = bufbe32toh (buf); if (length > len - 4) length = len - 4; - m_Owner.SendMessagePayloadMessage (buf + 4, length); + m_Owner->SendMessagePayloadMessage (buf + 4, length); } void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) @@ -46,9 +46,9 @@ namespace client m_LeaseSetExpirationTime = ls.GetExpirationTime (); uint8_t * leases = ls.GetLeases (); leases[-1] = tunnels.size (); - htobe16buf (leases - 3, m_Owner.GetSessionID ()); + htobe16buf (leases - 3, m_Owner->GetSessionID ()); size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); - m_Owner.SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); + m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); } void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) @@ -78,10 +78,10 @@ namespace client if (ls) { bool sent = s->SendMsg (msg, ls); - s->m_Owner.SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); + s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); } else - s->m_Owner.SendMessageStatusMessage (nonce, eI2CPMessageStatusNoLeaseSet); + s->m_Owner->SendMessageStatusMessage (nonce, eI2CPMessageStatusNoLeaseSet); }); } } @@ -134,6 +134,7 @@ namespace client void I2CPSession::Stop () { + Terminate (); } void I2CPSession::ReadProtocolByte () @@ -327,7 +328,7 @@ namespace client { bool isPublic = true; if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false; - m_Destination = std::make_shared(*this, identity, isPublic, params); + m_Destination = std::make_shared(shared_from_this (), identity, isPublic, params); m_Destination->Start (); SendSessionStatusMessage (1); // created LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); diff --git a/I2CP.h b/I2CP.h index 436b1ad6..62a9a729 100644 --- a/I2CP.h +++ b/I2CP.h @@ -63,7 +63,7 @@ namespace client { public: - I2CPDestination (I2CPSession& owner, std::shared_ptr identity, bool isPublic, const std::map& params); + I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params); void SetEncryptionPrivateKey (const uint8_t * key); void LeaseSetCreated (const uint8_t * buf, size_t len); // called from I2CPSession @@ -87,7 +87,7 @@ namespace client private: - I2CPSession& m_Owner; + std::shared_ptr m_Owner; std::shared_ptr m_Identity; uint8_t m_EncryptionPrivateKey[256]; uint64_t m_LeaseSetExpirationTime; From b786576bcb6b8d4778429a3afbc351ba5426da38 Mon Sep 17 00:00:00 2001 From: hagen Date: Thu, 9 Jun 2016 14:30:36 +0000 Subject: [PATCH 62/69] * HTTPProxy.cpp : always set dest_port --- HTTPProxy.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index a2bc4828..ec3dcffa 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -223,6 +223,8 @@ namespace proxy { u.parse(t); dest_host = u.host; dest_port = u.port; + if (dest_port == 0) + dest_port = 80; /* always set port for CreateStream() */ } else { /* relative url and missing 'Host' header */ std::string message = "Can't detect destination host from request"; From 88561c22d361ccaf3330fa5f73b24154294200c4 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Jun 2016 14:34:38 -0400 Subject: [PATCH 63/69] make sure ackThrough is correct --- Streaming.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Streaming.cpp b/Streaming.cpp index ab0a6df0..a258eef1 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -232,6 +232,11 @@ namespace stream bool acknowledged = false; auto ts = i2p::util::GetMillisecondsSinceEpoch (); uint32_t ackThrough = packet->GetAckThrough (); + if (ackThrough > m_SequenceNumber) + { + LogPrint (eLogError, "Streaming: Unexpected ackThrough=", ackThrough, " > seqn=", m_SequenceNumber); + return; + } int nackCount = packet->GetNACKCount (); for (auto it = m_SentPackets.begin (); it != m_SentPackets.end ();) { @@ -521,7 +526,7 @@ namespace stream size += 4; // receiveStreamID htobe32buf (packet + size, m_SequenceNumber++); size += 4; // sequenceNum - htobe32buf (packet + size, m_LastReceivedSequenceNumber); + htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0); size += 4; // ack Through packet[size] = 0; size++; // NACK count From d5d501875ea5ad08730279e45b09432cb5d7a119 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Jun 2016 14:56:12 -0400 Subject: [PATCH 64/69] send correct ackThrough --- Streaming.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Streaming.cpp b/Streaming.cpp index a258eef1..1a6fdbca 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -341,9 +341,9 @@ namespace stream htobe32buf (packet + size, m_SequenceNumber++); size += 4; // sequenceNum if (isNoAck) - htobe32buf (packet + size, m_LastReceivedSequenceNumber); - else htobuf32 (packet + size, 0); + else + htobe32buf (packet + size, m_LastReceivedSequenceNumber); size += 4; // ack Through packet[size] = 0; size++; // NACK count From f6d7f7d984a5b4e1bb9c6471fd938193af90b94a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 9 Jun 2016 15:48:31 -0400 Subject: [PATCH 65/69] set port to 80 is not specified --- HTTPProxy.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index ec3dcffa..c1ebc4e8 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -223,14 +223,13 @@ namespace proxy { u.parse(t); dest_host = u.host; dest_port = u.port; - if (dest_port == 0) - dest_port = 80; /* always set port for CreateStream() */ } else { /* relative url and missing 'Host' header */ std::string message = "Can't detect destination host from request"; HTTPRequestFailed(message.c_str()); return true; } + if (!dest_port) dest_port = 80; /* always set port for CreateStream() */ //TODO: 443 for https /* make relative url */ url.schema = ""; url.host = ""; From 6de7cd5063fcd7c4ec40d902a7e3da609b6b1b0f Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Jun 2016 11:39:20 -0400 Subject: [PATCH 66/69] don't send 'accepted' if not requested --- I2CP.cpp | 39 +++++++++++++++++++++++++++++++-------- I2CP.h | 4 +++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index e0ab180a..20f9dcee 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -117,7 +117,7 @@ namespace client I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), - m_MessageID (0) + m_MessageID (0), m_IsSendAccepted (true) { RAND_bytes ((uint8_t *)&m_SessionID, 2); } @@ -317,21 +317,42 @@ namespace client { auto identity = std::make_shared(); size_t offset = identity->FromBuffer (buf, len); + if (!offset) + { + LogPrint (eLogError, "I2CP: create session maformed identity"); + SendSessionStatusMessage (3); // invalid + return; + } uint16_t optionsSize = bufbe16toh (buf + offset); offset += 2; - + if (optionsSize > len - offset) + { + LogPrint (eLogError, "I2CP: options size ", optionsSize, "exceeds message size"); + SendSessionStatusMessage (3); // invalid + return; + } std::map params; ExtractMapping (buf + offset, optionsSize, params); - offset += optionsSize; + offset += optionsSize; // options + if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false; + offset += 8; // date if (identity->Verify (buf, offset, buf + offset)) // signature { bool isPublic = true; if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false; - m_Destination = std::make_shared(shared_from_this (), identity, isPublic, params); - m_Destination->Start (); - SendSessionStatusMessage (1); // created - LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); + if (!m_Destination) + { + m_Destination = std::make_shared(shared_from_this (), identity, isPublic, params); + SendSessionStatusMessage (1); // created + LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); + m_Destination->Start (); + } + else + { + LogPrint (eLogError, "I2CP: session already exists"); + SendSessionStatusMessage (4); // refused + } } else { @@ -363,6 +384,7 @@ namespace client void I2CPSession::SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status) { + if (!nonce) return; // don't send status with zero nonce uint8_t buf[15]; htobe16buf (buf, m_SessionID); htobe32buf (buf + 2, m_MessageID++); @@ -406,7 +428,8 @@ namespace client uint32_t payloadLen = bufbe32toh (buf + offset); offset += 4; uint32_t nonce = bufbe32toh (buf + offset + payloadLen); - SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted + if (m_IsSendAccepted) + SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); } } diff --git a/I2CP.h b/I2CP.h index 62a9a729..f77607ba 100644 --- a/I2CP.h +++ b/I2CP.h @@ -56,7 +56,8 @@ namespace client }; // params - const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet "; + const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet"; + const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability"; class I2CPSession; class I2CPDestination: public LeaseSetDestination @@ -148,6 +149,7 @@ namespace client std::shared_ptr m_Destination; uint16_t m_SessionID; uint32_t m_MessageID; + bool m_IsSendAccepted; }; typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); From ecd3a49d48378ac5156caafd43f98e421afc8f9a Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Jun 2016 11:47:22 -0400 Subject: [PATCH 67/69] handle DestroySession properly --- I2CP.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/I2CP.cpp b/I2CP.cpp index 20f9dcee..d3ad2350 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -117,9 +117,8 @@ namespace client I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): m_Owner (owner), m_Socket (socket), m_NextMessage (nullptr), m_NextMessageLen (0), m_NextMessageOffset (0), - m_MessageID (0), m_IsSendAccepted (true) + m_SessionID (0), m_MessageID (0), m_IsSendAccepted (true) { - RAND_bytes ((uint8_t *)&m_SessionID, 2); } I2CPSession::~I2CPSession () @@ -315,6 +314,7 @@ namespace client void I2CPSession::CreateSessionMessageHandler (const uint8_t * buf, size_t len) { + RAND_bytes ((uint8_t *)&m_SessionID, 2); auto identity = std::make_shared(); size_t offset = identity->FromBuffer (buf, len); if (!offset) @@ -365,7 +365,11 @@ namespace client { SendSessionStatusMessage (0); // destroy LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " destroyed"); - Terminate (); + if (m_Destination) + { + m_Destination->Stop (); + m_Destination = 0; + } } void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len) From 8feca6874a1f76704273c6afe1d60ec8969fa098 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Jun 2016 12:18:19 -0400 Subject: [PATCH 68/69] process complete message --- I2CP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2CP.cpp b/I2CP.cpp index d3ad2350..71188ec8 100644 --- a/I2CP.cpp +++ b/I2CP.cpp @@ -167,7 +167,7 @@ namespace client size_t offset = 0; // from m_Buffer if (m_NextMessage) { - if (m_NextMessageOffset + bytes_transferred <= m_NextMessageLen) + if (m_NextMessageOffset + bytes_transferred < m_NextMessageLen) { memcpy (m_NextMessage + m_NextMessageOffset, m_Buffer, bytes_transferred); m_NextMessageOffset += bytes_transferred; From b15b38868d391892f8adcc3f565a7f8dab286066 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 10 Jun 2016 14:01:39 -0400 Subject: [PATCH 69/69] rolled back to previous implementation --- HTTPProxy.cpp | 439 ++++++++++++++++++++++++++++---------------------- HTTPProxy.h | 25 ++- 2 files changed, 260 insertions(+), 204 deletions(-) diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index c1ebc4e8..056e3170 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -1,14 +1,8 @@ #include #include +#include #include #include -#include -#include -#include -#include - -#include "I2PService.h" -#include "Destination.h" #include "HTTPProxy.h" #include "util.h" #include "Identity.h" @@ -20,57 +14,71 @@ #include "Config.h" #include "HTTP.h" -namespace i2p { -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; - } - - class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this +namespace i2p +{ +namespace proxy +{ + static const size_t http_buffer_size = 8192; + class HTTPProxyHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: - - bool HandleRequest(std::size_t len); + enum state + { + GET_METHOD, + GET_HOSTNAME, + GET_HTTPV, + GET_HTTPVNL, //TODO: fallback to finding HOst: header if needed + DONE + }; + + void EnterState(state nstate); + bool HandleData(uint8_t *http_buff, std::size_t len); void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void Terminate(); void AsyncSockRead(); - void HTTPRequestFailed(const char *message); - void RedirectToJumpService(std::string & host); - bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64); - void SanitizeHTTPRequest(i2p::http::HTTPReq & req); + void HTTPRequestFailed(/*std::string message*/); + void RedirectToJumpService(); + void ExtractRequest(); + bool IsI2PAddress(); + bool ValidateHTTPRequest(); + void HandleJumpServices(); + bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); + uint8_t m_http_buff[http_buffer_size]; std::shared_ptr m_sock; - std::vector m_recv_buf; /* as "downstream recieve buffer", from client to me */ - std::vector m_send_buf; /* as "upstream send buffer", from me to remote host */ + std::string m_request; //Data left to be sent + std::string m_url; //URL + std::string m_method; //Method + std::string m_version; //HTTP version + std::string m_address; //Address + std::string m_path; //Path + int m_port; //Port + state m_state;//Parsing state public: - HTTPReqHandler(HTTPProxy * parent, std::shared_ptr sock) : - I2PServiceHandler(parent), m_sock(sock), m_recv_buf(8192), m_send_buf(0) {}; - ~HTTPReqHandler() { Terminate(); } + HTTPProxyHandler(HTTPProxyServer * parent, std::shared_ptr sock) : + I2PServiceHandler(parent), m_sock(sock) + { EnterState(GET_METHOD); } + ~HTTPProxyHandler() { Terminate(); } void Handle () { AsyncSockRead(); } }; - void HTTPReqHandler::AsyncSockRead() + void HTTPProxyHandler::AsyncSockRead() { 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"); - return; } - m_sock->async_receive(boost::asio::buffer(m_recv_buf), - std::bind(&HTTPReqHandler::HandleSockRecv, shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); } - void HTTPReqHandler::Terminate() { + void HTTPProxyHandler::Terminate() { if (Kill()) return; if (m_sock) { @@ -81,176 +89,203 @@ namespace proxy { Done(shared_from_this()); } - void HTTPReqHandler::HTTPRequestFailed(const char *message) + /* All hope is lost beyond this point */ + //TODO: handle this apropriately + void HTTPProxyHandler::HTTPRequestFailed(/*HTTPProxyHandler::errTypes error*/) { - i2p::http::HTTPRes res; - res.code = 500; - 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, response.size()), - std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); + static std::string response = "HTTP/1.0 500 Internal Server Error\r\nContent-type: text/html\r\nContent-length: 0\r\n"; + boost::asio::async_write(*m_sock, boost::asio::buffer(response,response.size()), + std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - void HTTPReqHandler::RedirectToJumpService(std::string & host) + void HTTPProxyHandler::RedirectToJumpService(/*HTTPProxyHandler::errTypes error*/) { - i2p::http::HTTPRes res; - i2p::http::URL url; + std::stringstream response; + std::string httpAddr; i2p::config::GetOption("http.address", httpAddr); + uint16_t httpPort; i2p::config::GetOption("http.port", httpPort); - i2p::config::GetOption("http.address", url.host); - i2p::config::GetOption("http.port", url.port); - url.schema = "http"; - url.path = "/"; - url.query = "page=jumpservices&address="; - url.query += host; - - res.code = 302; /* redirect */ - res.add_header("Location", url.to_string().c_str()); - res.add_header("Connection", "close"); + response << "HTTP/1.1 302 Found\r\nLocation: http://" << httpAddr << ":" << httpPort << "/?page=jumpservices&address=" << m_address << "\r\n\r\n"; + boost::asio::async_write(*m_sock, boost::asio::buffer(response.str (),response.str ().length ()), + std::bind(&HTTPProxyHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); + } - std::string response = res.to_string(); - boost::asio::async_write(*m_sock, boost::asio::buffer(response, response.length()), - std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); + void HTTPProxyHandler::EnterState(HTTPProxyHandler::state nstate) + { + m_state = nstate; } - bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64) + void HTTPProxyHandler::ExtractRequest() { - const char *param = "i2paddresshelper="; - std::size_t pos = url.query.find(param); - std::size_t len = std::strlen(param); - std::map params; + LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url); + i2p::http::URL url; + url.parse (m_url); + m_address = url.host; + m_port = url.port; + m_path = url.path; + if (!m_port) m_port = 80; + LogPrint(eLogDebug, "HTTPProxy: server: ", m_address, ", port: ", m_port, ", path: ", m_path); + } - if (pos == std::string::npos) - return false; /* not found */ - if (!url.parse_query(params)) + bool HTTPProxyHandler::ValidateHTTPRequest() + { + if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" ) + { + LogPrint(eLogError, "HTTPProxy: unsupported version: ", m_version); + HTTPRequestFailed(); //TODO: send right stuff return false; - - std::string value = params["i2paddresshelper"]; - len += value.length(); - b64 = i2p::http::UrlDecode(value); - url.query.replace(pos, len, ""); + } return true; } - void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) + void HTTPProxyHandler::HandleJumpServices() { - req.del_header("Referer"); - req.del_header("Via"); - req.del_header("Forwarded"); - std::vector toErase; - for (auto it : req.headers) { - if (it.first.compare(0, 12, "X-Forwarded-")) { - toErase.push_back(it.first); - } else if (it.first.compare(0, 6, "Proxy-")) { - toErase.push_back(it.first); - } else { - /* allow this header */ - } + static const char * helpermark1 = "?i2paddresshelper="; + static const char * helpermark2 = "&i2paddresshelper="; + size_t addressHelperPos1 = m_path.rfind (helpermark1); + size_t addressHelperPos2 = m_path.rfind (helpermark2); + size_t addressHelperPos; + if (addressHelperPos1 == std::string::npos) + { + if (addressHelperPos2 == std::string::npos) + return; //Not a jump service + else + addressHelperPos = addressHelperPos2; } - for (auto header : toErase) { - req.headers.erase(header); + else + { + if (addressHelperPos2 == std::string::npos) + addressHelperPos = addressHelperPos1; + else if ( addressHelperPos1 > addressHelperPos2 ) + addressHelperPos = addressHelperPos1; + else + addressHelperPos = addressHelperPos2; } - /* replace headers */ - req.add_header("Connection", "close", true); /* keep-alive conns not supported yet */ - req.add_header("User-Agent", "MYOB/6.66 (AN/ON)", true); /* privacy */ + auto base64 = m_path.substr (addressHelperPos + strlen(helpermark1)); + base64 = i2p::util::http::urlDecode(base64); //Some of the symbols may be urlencoded + LogPrint (eLogInfo, "HTTPProxy: jump service for ", m_address, ", inserting to address book"); + //TODO: this is very dangerous and broken. We should ask the user before doing anything see http://pastethis.i2p/raw/pn5fL4YNJL7OSWj3Sc6N/ + //TODO: we could redirect the user again to avoid dirtiness in the browser + i2p::client::context.GetAddressBook ().InsertAddress (m_address, base64); + m_path.erase(addressHelperPos); } - /** - * @param len length of data in m_recv_buf - * @return true on processed request or false if more data needed - */ - bool HTTPReqHandler::HandleRequest(std::size_t len) + bool HTTPProxyHandler::IsI2PAddress() { - i2p::http::HTTPReq req; - i2p::http::URL url; - std::string b64; - - int req_len = 0; - - req_len = req.parse((const char *) m_recv_buf.data(), len); - if (req_len == 0) - return false; /* need more data */ - if (req_len < 0) { - LogPrint(eLogError, "HTTPProxy: unable to parse request"); - HTTPRequestFailed("invalid request"); - return true; /* parse error */ + auto pos = m_address.rfind (".i2p"); + if (pos != std::string::npos && (pos+4) == m_address.length ()) + { + return true; } + return false; + } - /* parsing success, now let's look inside request */ - LogPrint(eLogDebug, "HTTPProxy: requested: ", req.uri); - url.parse(req.uri); - - if (ExtractAddressHelper(url, b64)) { - i2p::client::context.GetAddressBook ().InsertAddress (url.host, b64); - std::string message = "added b64 from addresshelper for " + url.host + " to address book"; - LogPrint (eLogInfo, "HTTPProxy: ", message); - message += ", please reload page"; - HTTPRequestFailed(message.c_str()); - return true; /* request processed */ - } + bool HTTPProxyHandler::CreateHTTPRequest(uint8_t *http_buff, std::size_t len) + { + ExtractRequest(); //TODO: parse earlier + if (!ValidateHTTPRequest()) return false; + HandleJumpServices(); i2p::data::IdentHash identHash; - if (str_rmatch(url.host, ".i2p")) { - if (!i2p::client::context.GetAddressBook ().GetIdentHash (url.host, identHash)) { - RedirectToJumpService(url.host); - return true; /* request processed */ + if (IsI2PAddress ()) + { + if (!i2p::client::context.GetAddressBook ().GetIdentHash (m_address, identHash)){ + RedirectToJumpService(); + return false; } - /* TODO: outproxy handler here */ - } else { - std::string message = "Host " + url.host + " not inside i2p network, but outproxy support still missing"; - HTTPRequestFailed(message.c_str()); - LogPrint (eLogWarning, "HTTPProxy: ", message); - return true; } - SanitizeHTTPRequest(req); + + + m_request = m_method; + m_request.push_back(' '); + m_request += m_path; + m_request.push_back(' '); + m_request += m_version; + m_request.push_back('\r'); + m_request.push_back('\n'); + m_request.append("Connection: close\r\n"); + // TODO: temporary shortcut. Must be implemented properly + uint8_t * eol = nullptr; + bool isEndOfHeader = false; + while (!isEndOfHeader && len && (eol = (uint8_t *)memchr (http_buff, '\r', len))) + { + if (eol) + { + *eol = 0; eol++; + if (strncmp ((const char *)http_buff, "Referer", 7) && strncmp ((const char *)http_buff, "Connection", 10)) // strip out referer and connection + { + if (!strncmp ((const char *)http_buff, "User-Agent", 10)) // replace UserAgent + m_request.append("User-Agent: MYOB/6.66 (AN/ON)"); + else + m_request.append ((const char *)http_buff); + m_request.append ("\r\n"); + } + isEndOfHeader = !http_buff[0]; + auto l = eol - http_buff; + http_buff = eol; + len -= l; + if (len > 0) // \r + { + http_buff++; + len--; + } + } + } + m_request.append(reinterpret_cast(http_buff),len); + return true; + } - std::string dest_host = url.host; - uint16_t dest_port = url.port; - /* set proper 'Host' header in upstream request */ - auto h = req.headers.find("Host"); - if (dest_host != "") { - /* absolute url, replace 'Host' header */ - std::string h = dest_host; - if (dest_port != 0 && dest_port != 80) - h += ":" + std::to_string(dest_port); - req.add_header("Host", h, true); - } else if (h != req.headers.end()) { - /* relative url and 'Host' header provided. transparent proxy mode? */ - i2p::http::URL u; - std::string t = "http://" + h->second; - u.parse(t); - dest_host = u.host; - dest_port = u.port; - } else { - /* relative url and missing 'Host' header */ - std::string message = "Can't detect destination host from request"; - HTTPRequestFailed(message.c_str()); - return true; + bool HTTPProxyHandler::HandleData(uint8_t *http_buff, std::size_t len) + { + while (len > 0) + { + //TODO: fallback to finding HOst: header if needed + switch (m_state) + { + case GET_METHOD: + switch (*http_buff) + { + case ' ': EnterState(GET_HOSTNAME); break; + default: m_method.push_back(*http_buff); break; + } + break; + case GET_HOSTNAME: + switch (*http_buff) + { + case ' ': EnterState(GET_HTTPV); break; + default: m_url.push_back(*http_buff); break; + } + break; + case GET_HTTPV: + switch (*http_buff) + { + case '\r': EnterState(GET_HTTPVNL); break; + default: m_version.push_back(*http_buff); break; + } + break; + case GET_HTTPVNL: + switch (*http_buff) + { + case '\n': EnterState(DONE); break; + default: + LogPrint(eLogError, "HTTPProxy: rejected invalid request ending with: ", ((int)*http_buff)); + HTTPRequestFailed(); //TODO: add correct code + return false; + } + break; + default: + LogPrint(eLogError, "HTTPProxy: invalid state: ", m_state); + HTTPRequestFailed(); //TODO: add correct code 500 + return false; + } + http_buff++; + len--; + if (m_state == DONE) + return CreateHTTPRequest(http_buff,len); } - if (!dest_port) dest_port = 80; /* always set port for CreateStream() */ //TODO: 443 for https - /* make relative url */ - url.schema = ""; - url.host = ""; - req.uri = url.to_string(); - - /* drop original request from input buffer */ - m_recv_buf.erase(m_recv_buf.begin(), m_recv_buf.begin() + req_len); - - /* build new buffer from modified request and data from original request */ - std::string request = req.to_string(); - m_send_buf.assign(request.begin(), request.end()); - m_send_buf.insert(m_send_buf.end(), m_recv_buf.begin(), m_recv_buf.end()); - - /* connect to destination */ - GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete, - shared_from_this(), std::placeholders::_1), dest_host, dest_port); - return true; } - void HTTPReqHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len) + void HTTPProxyHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len) { LogPrint(eLogDebug, "HTTPProxy: sock recv: ", len, " bytes"); if(ecode) @@ -260,44 +295,54 @@ namespace proxy { return; } - if (HandleRequest(len)) { - m_recv_buf.clear(); - return; /* request processed */ + if (HandleData(m_http_buff, len)) + { + if (m_state == DONE) + { + LogPrint(eLogDebug, "HTTPProxy: requested: ", m_url); + GetOwner()->CreateStream (std::bind (&HTTPProxyHandler::HandleStreamRequestComplete, + shared_from_this(), std::placeholders::_1), m_address, m_port); + } + else + AsyncSockRead(); } - AsyncSockRead(); + } - void HTTPReqHandler::SentHTTPFailed(const boost::system::error_code & ecode) + void HTTPProxyHandler::SentHTTPFailed(const boost::system::error_code & ecode) { if (ecode) LogPrint (eLogError, "HTTPProxy: Closing socket after sending failure because: ", ecode.message ()); Terminate(); } - void HTTPReqHandler::HandleStreamRequestComplete (std::shared_ptr stream) + void HTTPProxyHandler::HandleStreamRequestComplete (std::shared_ptr stream) { - if (!stream) { + if (stream) + { + if (Kill()) return; + LogPrint (eLogInfo, "HTTPProxy: New I2PTunnel connection"); + auto connection = std::make_shared(GetOwner(), m_sock, stream); + GetOwner()->AddHandler (connection); + connection->I2PConnect (reinterpret_cast(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"); - HTTPRequestFailed("error when creating the stream, check logs"); - return; + HTTPRequestFailed(); // TODO: Send correct error message host unreachable } - if (Kill()) - return; - LogPrint (eLogDebug, "HTTPProxy: New I2PTunnel connection"); - auto connection = std::make_shared(GetOwner(), m_sock, stream); - GetOwner()->AddHandler (connection); - connection->I2PConnect (m_send_buf.data(), m_send_buf.size()); - Done (shared_from_this()); } - HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination): + HTTPProxyServer::HTTPProxyServer(const std::string& address, int port, std::shared_ptr localDestination): TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) { } - std::shared_ptr HTTPProxy::CreateHandler(std::shared_ptr socket) + std::shared_ptr HTTPProxyServer::CreateHandler(std::shared_ptr socket) { - return std::make_shared (this, socket); + return std::make_shared (this, socket); } -} // http -} // i2p + +} +} diff --git a/HTTPProxy.h b/HTTPProxy.h index 29b997eb..b5ed77b9 100644 --- a/HTTPProxy.h +++ b/HTTPProxy.h @@ -1,21 +1,32 @@ #ifndef HTTP_PROXY_H__ #define HTTP_PROXY_H__ -namespace i2p { -namespace proxy { - class HTTPProxy: public i2p::client::TCPIPAcceptor +#include +#include +#include +#include +#include "I2PService.h" +#include "Destination.h" + +namespace i2p +{ +namespace proxy +{ + class HTTPProxyServer: public i2p::client::TCPIPAcceptor { public: - HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination = nullptr); - ~HTTPProxy() {}; + HTTPProxyServer(const std::string& address, int port, std::shared_ptr localDestination = nullptr); + ~HTTPProxyServer() {}; protected: // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); const char* GetName() { return "HTTP Proxy"; } }; -} // http -} // i2p + + typedef HTTPProxyServer HTTPProxy; +} +} #endif