diff --git a/.travis.yml b/.travis.yml index e52c53a7..d83cdbc0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew unlink boost openssl && brew link boost openssl -f ; fi env: matrix: -# - BUILD_TYPE=Release UPNP=ON + - BUILD_TYPE=Release UPNP=ON - BUILD_TYPE=Release UPNP=OFF script: - cd build && cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DWITH_UPNP=${UPNP} && make diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index e11d430d..af914b47 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -20,10 +20,18 @@ #include "I2PTunnel.h" #include "Config.h" #include "HTTP.h" -#include "HTTPServer.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; + } + static const size_t http_buffer_size = 8192; class HTTPReqHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { @@ -43,9 +51,8 @@ namespace proxy { void Terminate(); void AsyncSockRead(); void HTTPRequestFailed(const char *message); - void RedirectToJumpService(); + void RedirectToJumpService(std::string & host); void ExtractRequest(); - bool IsI2PAddress(); bool ValidateHTTPRequest(); void HandleJumpServices(); bool CreateHTTPRequest(uint8_t *http_buff, std::size_t len); @@ -99,23 +106,34 @@ 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), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - void HTTPReqHandler::RedirectToJumpService(/*HTTPReqHandler::errTypes error*/) + void HTTPReqHandler::RedirectToJumpService(std::string & host) { - std::stringstream ss; - i2p::http::ShowJumpServices (ss, m_address); - boost::asio::async_write(*m_sock, boost::asio::buffer(ss.str ()), + i2p::http::HTTPRes res; + i2p::http::URL url; + + /* TODO: don't redirect to webconsole, it's not always work, handle jumpservices here */ + 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), std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } @@ -180,16 +198,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 @@ -197,14 +205,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(); + RedirectToJumpService(m_address); return false; } } - m_request = m_method; m_request.push_back(' '); @@ -317,7 +324,6 @@ namespace proxy { else AsyncSockRead(); } - } void HTTPReqHandler::SentHTTPFailed(const boost::system::error_code & ecode) diff --git a/HTTPServer.h b/HTTPServer.h index 6aa0d792..bf7f5c65 100644 --- a/HTTPServer.h +++ b/HTTPServer.h @@ -61,8 +61,6 @@ namespace http { boost::asio::io_service::work m_Work; boost::asio::ip::tcp::acceptor m_Acceptor; }; - - void ShowJumpServices (std::stringstream& s, const std::string& address); } // http } // i2p diff --git a/Makefile.linux b/Makefile.linux index da72a41a..324d9467 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -33,10 +33,10 @@ ifeq ($(USE_STATIC),yes) LDLIBS += $(LIBDIR)/libboost_date_time.a LDLIBS += $(LIBDIR)/libboost_filesystem.a LDLIBS += $(LIBDIR)/libboost_program_options.a - LDLIBS += $(LIBDIR)/libcrypto.a LDLIBS += $(LIBDIR)/libssl.a + LDLIBS += $(LIBDIR)/libcrypto.a LDLIBS += $(LIBDIR)/libz.a - LDLIBS += -lpthread -static-libstdc++ -static-libgcc + LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt USE_AESNI := no else LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread diff --git a/SSUData.cpp b/SSUData.cpp index 0ccf25a8..4ce7451d 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -425,6 +425,7 @@ namespace transport if (ecode != boost::asio::error::operation_aborted) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); + int numResent = 0; for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();) { if (ts >= it->second->nextResendTime) @@ -437,6 +438,7 @@ namespace transport try { m_Session.Send (f->buf, f->len); // resend + numResent++; } catch (boost::system::system_error& ec) { @@ -457,7 +459,13 @@ namespace transport else it++; } - ScheduleResend (); + if (numResent < MAX_OUTGOING_WINDOW_SIZE) + ScheduleResend (); + else + { + LogPrint (eLogError, "SSU: resend window exceeds max size. Session terminated"); + m_Session.Close (); + } } } diff --git a/SSUData.h b/SSUData.h index 392bfce6..02135350 100644 --- a/SSUData.h +++ b/SSUData.h @@ -29,6 +29,7 @@ namespace transport const int DECAY_INTERVAL = 20; // in seconds const int INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds const unsigned int MAX_NUM_RECEIVED_MESSAGES = 1000; // how many msgID we store for duplicates check + const int MAX_OUTGOING_WINDOW_SIZE = 200; // how many unacked message we can store // data flags const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02; const uint8_t DATA_FLAG_WANT_REPLY = 0x04; diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 4a1bfe2b..61e05e83 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -338,6 +338,10 @@ if (WITH_BINARY) set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now" ) endif () + if (WITH_UPNP) + target_link_libraries("${PROJECT_NAME}" "miniupnpc") + endif () + # FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04 list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES) if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*") diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 9f579ffc..b2cafdeb 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -151,7 +151,7 @@ DISTFILES += \ ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android -SOURCES += $$IFADDRS_PATH/ifaddrs.c ../../UPnP.cpp +SOURCES += $$IFADDRS_PATH/ifaddrs.c HEADERS += $$IFADDRS_PATH/ifaddrs.h equals(ANDROID_TARGET_ARCH, armeabi-v7a){ diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index 3f220a8c..0e2ca01c 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -9,8 +9,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)/*, - ui(new Ui::MainWindow)*/, + ui(new Ui::MainWindow)*/ +#ifndef ANDROID + , quitting(false) +#endif { //ui->setupUi(this); if (objectName().isEmpty())