mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 08:30:46 +00:00 
			
		
		
		
	drop websockets support
Signed-off-by: R4SAS <r4sas@i2pmail.org>
This commit is contained in:
		
							parent
							
								
									a0d6c654cc
								
							
						
					
					
						commit
						00db527377
					
				
					 19 changed files with 57 additions and 1041 deletions
				
			
		
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -27,10 +27,6 @@ else
 | 
			
		|||
	LD_DEBUG = -s
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(WEBSOCKETS),1)
 | 
			
		||||
	NEEDED_CXXFLAGS += -DWITH_EVENTS
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifneq (, $(findstring darwin, $(SYS)))
 | 
			
		||||
	DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
 | 
			
		||||
	ifeq ($(HOMEBREW),1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@ option(WITH_MESHNET "Build for cjdns test network" OFF)
 | 
			
		|||
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
 | 
			
		||||
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
 | 
			
		||||
option(WITH_I2LUA "Build for i2lua" OFF)
 | 
			
		||||
option(WITH_WEBSOCKETS "Build with websocket ui" OFF)
 | 
			
		||||
 | 
			
		||||
# paths
 | 
			
		||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
 | 
			
		||||
| 
						 | 
				
			
			@ -86,11 +85,6 @@ set (LIBI2PD_SRC
 | 
			
		|||
  "${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp"    
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if (WITH_WEBSOCKETS)
 | 
			
		||||
  add_definitions(-DWITH_EVENTS)
 | 
			
		||||
  find_package(websocketpp REQUIRED)
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
if (WIN32 OR MSYS)
 | 
			
		||||
  list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
 | 
			
		||||
endif ()
 | 
			
		||||
| 
						 | 
				
			
			@ -127,10 +121,6 @@ set (CLIENT_SRC
 | 
			
		|||
  "${LIBI2PD_CLIENT_SRC_DIR}/WebSocks.cpp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if(WITH_WEBSOCKETS)
 | 
			
		||||
  list (APPEND CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/Websocket.cpp")
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
add_library(libi2pdclient ${CLIENT_SRC})
 | 
			
		||||
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -427,7 +417,6 @@ message(STATUS "  MESHNET          : ${WITH_MESHNET}")
 | 
			
		|||
message(STATUS "  ADDRSANITIZER    : ${WITH_ADDRSANITIZER}")
 | 
			
		||||
message(STATUS "  THREADSANITIZER  : ${WITH_THREADSANITIZER}")
 | 
			
		||||
message(STATUS "  I2LUA            : ${WITH_I2LUA}")
 | 
			
		||||
message(STATUS "  WEBSOCKETS       : ${WITH_WEBSOCKETS}")
 | 
			
		||||
message(STATUS "---------------------------------------")
 | 
			
		||||
 | 
			
		||||
#Handle paths nicely
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,9 +26,6 @@
 | 
			
		|||
#include "Timestamp.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
#include "Websocket.h"
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
	namespace util
 | 
			
		||||
| 
						 | 
				
			
			@ -43,9 +40,6 @@ namespace i2p
 | 
			
		|||
			std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
 | 
			
		||||
			std::unique_ptr<i2p::transport::UPnP> UPnP;
 | 
			
		||||
			std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			std::unique_ptr<i2p::event::WebsocketServer> m_WebsocketServer;
 | 
			
		||||
#endif
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -62,12 +56,12 @@ namespace i2p
 | 
			
		|||
			return service;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        bool Daemon_Singleton::init(int argc, char* argv[]) {
 | 
			
		||||
            return init(argc, argv, nullptr);
 | 
			
		||||
        }
 | 
			
		||||
		bool Daemon_Singleton::init(int argc, char* argv[]) {
 | 
			
		||||
			return init(argc, argv, nullptr);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream)
 | 
			
		||||
        {
 | 
			
		||||
		bool Daemon_Singleton::init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream)
 | 
			
		||||
		{
 | 
			
		||||
			i2p::config::Init();
 | 
			
		||||
			i2p::config::ParseCmdline(argc, argv);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,10 +104,10 @@ namespace i2p
 | 
			
		|||
				logs = "file";
 | 
			
		||||
 | 
			
		||||
			i2p::log::Logger().SetLogLevel(loglevel);
 | 
			
		||||
            if (logstream) {
 | 
			
		||||
                LogPrint(eLogInfo, "Log: will send messages to std::ostream");
 | 
			
		||||
                i2p::log::Logger().SendTo (logstream);
 | 
			
		||||
            } else if (logs == "file") {
 | 
			
		||||
			if (logstream) {
 | 
			
		||||
				LogPrint(eLogInfo, "Log: will send messages to std::ostream");
 | 
			
		||||
				i2p::log::Logger().SendTo (logstream);
 | 
			
		||||
			} else if (logs == "file") {
 | 
			
		||||
				if (logfile == "")
 | 
			
		||||
					logfile = i2p::fs::DataDirPath("i2pd.log");
 | 
			
		||||
				LogPrint(eLogInfo, "Log: will send messages to ", logfile);
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +121,7 @@ namespace i2p
 | 
			
		|||
				// use stdout -- default
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			LogPrint(eLogInfo,	"i2pd v", VERSION, " starting");
 | 
			
		||||
			LogPrint(eLogInfo,  "i2pd v", VERSION, " starting");
 | 
			
		||||
			LogPrint(eLogDebug, "FS: main config file: ", config);
 | 
			
		||||
			LogPrint(eLogDebug, "FS: data directory: ", datadir);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -151,8 +145,8 @@ namespace i2p
 | 
			
		|||
				LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
 | 
			
		||||
				i2p::context.UpdatePort (port);
 | 
			
		||||
			}
 | 
			
		||||
			i2p::context.SetSupportsV6		 (ipv6);
 | 
			
		||||
			i2p::context.SetSupportsV4		 (ipv4);
 | 
			
		||||
			i2p::context.SetSupportsV6 (ipv6);
 | 
			
		||||
			i2p::context.SetSupportsV4 (ipv4);
 | 
			
		||||
 | 
			
		||||
			bool ntcp;   i2p::config::GetOption("ntcp", ntcp);
 | 
			
		||||
			i2p::context.PublishNTCPAddress (ntcp, !ipv6);  
 | 
			
		||||
| 
						 | 
				
			
			@ -233,15 +227,15 @@ namespace i2p
 | 
			
		|||
			if (family.length () > 0)
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: family set to ", family);
 | 
			
		||||
 | 
			
		||||
      bool trust; i2p::config::GetOption("trust.enabled", trust);
 | 
			
		||||
      if (trust)
 | 
			
		||||
      {
 | 
			
		||||
        LogPrint(eLogInfo, "Daemon: explicit trust enabled");
 | 
			
		||||
        std::string fam; i2p::config::GetOption("trust.family", fam);
 | 
			
		||||
			bool trust; i2p::config::GetOption("trust.enabled", trust);
 | 
			
		||||
			if (trust)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: explicit trust enabled");
 | 
			
		||||
				std::string fam; i2p::config::GetOption("trust.family", fam);
 | 
			
		||||
				std::string routers; i2p::config::GetOption("trust.routers", routers);
 | 
			
		||||
				bool restricted = false;
 | 
			
		||||
        if (fam.length() > 0)
 | 
			
		||||
        {
 | 
			
		||||
				if (fam.length() > 0)
 | 
			
		||||
				{
 | 
			
		||||
					std::set<std::string> fams;
 | 
			
		||||
					size_t pos = 0, comma;
 | 
			
		||||
					do
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +247,7 @@ namespace i2p
 | 
			
		|||
					while (comma != std::string::npos);
 | 
			
		||||
					i2p::transport::transports.RestrictRoutesToFamilies(fams);
 | 
			
		||||
					restricted  = fams.size() > 0;
 | 
			
		||||
        }
 | 
			
		||||
				}
 | 
			
		||||
				if (routers.length() > 0) {
 | 
			
		||||
					std::set<i2p::data::IdentHash> idents;
 | 
			
		||||
					size_t pos = 0, comma;
 | 
			
		||||
| 
						 | 
				
			
			@ -272,14 +266,15 @@ namespace i2p
 | 
			
		|||
				}
 | 
			
		||||
				if(!restricted)
 | 
			
		||||
					LogPrint(eLogError, "Daemon: no trusted routers of families specififed");
 | 
			
		||||
      }
 | 
			
		||||
      bool hidden; i2p::config::GetOption("trust.hidden", hidden);
 | 
			
		||||
      if (hidden)
 | 
			
		||||
      {
 | 
			
		||||
        LogPrint(eLogInfo, "Daemon: using hidden mode");
 | 
			
		||||
        i2p::data::netdb.SetHidden(true);
 | 
			
		||||
      }
 | 
			
		||||
      return true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bool hidden; i2p::config::GetOption("trust.hidden", hidden);
 | 
			
		||||
			if (hidden)
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: using hidden mode");
 | 
			
		||||
				i2p::data::netdb.SetHidden(true);
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool Daemon_Singleton::start()
 | 
			
		||||
| 
						 | 
				
			
			@ -322,7 +317,7 @@ namespace i2p
 | 
			
		|||
			bool http; i2p::config::GetOption("http.enabled", http);
 | 
			
		||||
			if (http) {
 | 
			
		||||
				std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
 | 
			
		||||
				uint16_t		httpPort; i2p::config::GetOption("http.port",		 httpPort);
 | 
			
		||||
				uint16_t    httpPort; i2p::config::GetOption("http.port",		 httpPort);
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: starting HTTP Server at ", httpAddr, ":", httpPort);
 | 
			
		||||
				d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
 | 
			
		||||
				d.httpServer->Start();
 | 
			
		||||
| 
						 | 
				
			
			@ -344,26 +339,11 @@ namespace i2p
 | 
			
		|||
				d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
 | 
			
		||||
				d.m_I2PControlService->Start ();
 | 
			
		||||
			}
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
 | 
			
		||||
			bool websocket; i2p::config::GetOption("websockets.enabled", websocket);
 | 
			
		||||
			if(websocket) {
 | 
			
		||||
				std::string websocketAddr; i2p::config::GetOption("websockets.address", websocketAddr);
 | 
			
		||||
				uint16_t		websocketPort; i2p::config::GetOption("websockets.port",		websocketPort);
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: starting Websocket server at ", websocketAddr, ":", websocketPort);
 | 
			
		||||
				d.m_WebsocketServer = std::unique_ptr<i2p::event::WebsocketServer>(new i2p::event::WebsocketServer (websocketAddr, websocketPort));
 | 
			
		||||
				d.m_WebsocketServer->Start();
 | 
			
		||||
				i2p::event::core.SetListener(d.m_WebsocketServer->ToListener());
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool Daemon_Singleton::stop()
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			i2p::event::core.SetListener(nullptr);
 | 
			
		||||
#endif
 | 
			
		||||
			LogPrint(eLogInfo, "Daemon: shutting down");
 | 
			
		||||
			LogPrint(eLogInfo, "Daemon: stopping Client");
 | 
			
		||||
			i2p::client::context.Stop();
 | 
			
		||||
| 
						 | 
				
			
			@ -397,13 +377,6 @@ namespace i2p
 | 
			
		|||
				d.m_I2PControlService->Stop ();
 | 
			
		||||
				d.m_I2PControlService = nullptr;
 | 
			
		||||
			}
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			if (d.m_WebsocketServer) {
 | 
			
		||||
				LogPrint(eLogInfo, "Daemon: stopping Websocket server");
 | 
			
		||||
				d.m_WebsocketServer->Stop();
 | 
			
		||||
				d.m_WebsocketServer = nullptr;
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
			i2p::crypto::TerminateCrypto ();
 | 
			
		||||
			i2p::log::Logger().Stop();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -218,13 +218,6 @@ namespace config {
 | 
			
		|||
			("trust.hidden", value<bool>()->default_value(false),      "Should we hide our router from other routers?")
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
		options_description websocket("Websocket Options");
 | 
			
		||||
		websocket.add_options()
 | 
			
		||||
			("websockets.enabled", value<bool>()->default_value(false),              "Enable websocket server")
 | 
			
		||||
			("websockets.address", value<std::string>()->default_value("127.0.0.1"), "Address to bind websocket server on")
 | 
			
		||||
			("websockets.port", value<uint16_t>()->default_value(7666),              "Port to bind websocket server on")
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
		options_description exploratory("Exploratory Options");
 | 
			
		||||
		exploratory.add_options()
 | 
			
		||||
			("exploratory.inbound.length", value<int>()->default_value(2),    "Exploratory inbound tunnel length")
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +267,6 @@ namespace config {
 | 
			
		|||
			.add(reseed)
 | 
			
		||||
			.add(addressbook)
 | 
			
		||||
			.add(trust)
 | 
			
		||||
			.add(websocket)
 | 
			
		||||
			.add(exploratory)
 | 
			
		||||
			.add(ntcp2)
 | 
			
		||||
			.add(nettime)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,6 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
	namespace event
 | 
			
		||||
	{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
		EventCore core;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		void EventCore::SetListener(EventListener * l)
 | 
			
		||||
		{
 | 
			
		||||
			m_listener = l;
 | 
			
		||||
| 
						 | 
				
			
			@ -44,18 +40,3 @@ namespace i2p
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QueueIntEvent(const std::string & type, const std::string & ident, uint64_t val)
 | 
			
		||||
{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
	i2p::event::core.CollectEvent(type, ident, val);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmitEvent(const EventType & e)
 | 
			
		||||
{
 | 
			
		||||
#if WITH_EVENTS
 | 
			
		||||
	i2p::event::core.QueueEvent(e);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,40 +14,33 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
	namespace event
 | 
			
		||||
	{
 | 
			
		||||
		class EventListener	 {
 | 
			
		||||
		class EventListener {
 | 
			
		||||
		public:
 | 
			
		||||
			virtual ~EventListener() {};
 | 
			
		||||
			virtual void HandleEvent(const EventType & ev) = 0;
 | 
			
		||||
      /** @brief handle collected event when pumped */
 | 
			
		||||
      virtual void HandlePumpEvent(const EventType & ev, const uint64_t & val) = 0;
 | 
			
		||||
		/** @brief handle collected event when pumped */
 | 
			
		||||
		virtual void HandlePumpEvent(const EventType & ev, const uint64_t & val) = 0;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		class EventCore
 | 
			
		||||
		{
 | 
			
		||||
		public:
 | 
			
		||||
			void QueueEvent(const EventType & ev);
 | 
			
		||||
      void CollectEvent(const std::string & type, const std::string & ident, uint64_t val);
 | 
			
		||||
		void CollectEvent(const std::string & type, const std::string & ident, uint64_t val);
 | 
			
		||||
			void SetListener(EventListener * l);
 | 
			
		||||
      void PumpCollected(EventListener * l);
 | 
			
		||||
		void PumpCollected(EventListener * l);
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
      std::mutex m_collect_mutex;
 | 
			
		||||
      struct CollectedEvent
 | 
			
		||||
      {
 | 
			
		||||
        std::string Key;
 | 
			
		||||
        std::string Ident;
 | 
			
		||||
        uint64_t Val;
 | 
			
		||||
      };
 | 
			
		||||
      std::map<std::string, CollectedEvent> m_collected;
 | 
			
		||||
		std::mutex m_collect_mutex;
 | 
			
		||||
		struct CollectedEvent
 | 
			
		||||
		{
 | 
			
		||||
			std::string Key;
 | 
			
		||||
			std::string Ident;
 | 
			
		||||
			uint64_t Val;
 | 
			
		||||
		};
 | 
			
		||||
		std::map<std::string, CollectedEvent> m_collected;
 | 
			
		||||
			EventListener * m_listener = nullptr;
 | 
			
		||||
		};
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
		extern EventCore core;
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QueueIntEvent(const std::string & type, const std::string & ident, uint64_t val);
 | 
			
		||||
void EmitEvent(const EventType & ev);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,9 +14,6 @@
 | 
			
		|||
#include "NTCPSession.h"
 | 
			
		||||
#include "HTTP.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace i2p::crypto;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -649,9 +646,6 @@ namespace transport
 | 
			
		|||
			{
 | 
			
		||||
				if (!m_NextMessage->IsExpired ())
 | 
			
		||||
				{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
					QueueIntEvent("transport.recvmsg", GetIdentHashBase64(), 1);
 | 
			
		||||
#endif
 | 
			
		||||
					m_Handler.PutNextMessage (m_NextMessage);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,9 +5,6 @@
 | 
			
		|||
#include "NetDb.hpp"
 | 
			
		||||
#include "SSU.h"
 | 
			
		||||
#include "SSUData.h"
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -241,9 +238,6 @@ namespace transport
 | 
			
		|||
						m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch ();
 | 
			
		||||
						if (!msg->IsExpired ())
 | 
			
		||||
						{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
							QueueIntEvent("transport.recvmsg", m_Session.GetIdentHashBase64(), 1);
 | 
			
		||||
#endif
 | 
			
		||||
							m_Handler.PutNextMessage (msg);
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,10 +6,6 @@
 | 
			
		|||
#include "Transports.h"
 | 
			
		||||
#include "Config.h"
 | 
			
		||||
#include "HTTP.h"
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace i2p::data;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -346,9 +342,6 @@ namespace transport
 | 
			
		|||
 | 
			
		||||
	void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs)
 | 
			
		||||
	{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
		QueueIntEvent("transport.send", ident.ToBase64(), msgs.size());
 | 
			
		||||
#endif
 | 
			
		||||
		m_Service->post (std::bind (&Transports::PostMessages, this, ident, msgs));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -597,9 +590,6 @@ namespace transport
 | 
			
		|||
			auto it = m_Peers.find (ident);
 | 
			
		||||
			if (it != m_Peers.end ())
 | 
			
		||||
			{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
				EmitEvent({{"type" , "transport.connected"}, {"ident", ident.ToBase64()}, {"inbound", "false"}});
 | 
			
		||||
#endif
 | 
			
		||||
				bool sendDatabaseStore = true;
 | 
			
		||||
				if (it->second.delayedMessages.size () > 0)
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -625,9 +615,6 @@ namespace transport
 | 
			
		|||
					session->Done();
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
				EmitEvent({{"type" , "transport.connected"}, {"ident", ident.ToBase64()}, {"inbound", "true"}});
 | 
			
		||||
#endif
 | 
			
		||||
				session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
 | 
			
		||||
				std::unique_lock<std::mutex>	l(m_PeersMutex);
 | 
			
		||||
				m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} }));
 | 
			
		||||
| 
						 | 
				
			
			@ -642,9 +629,6 @@ namespace transport
 | 
			
		|||
			auto remoteIdentity = session->GetRemoteIdentity ();
 | 
			
		||||
			if (!remoteIdentity) return;
 | 
			
		||||
			auto ident = remoteIdentity->GetIdentHash ();
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitEvent({{"type" , "transport.disconnected"}, {"ident", ident.ToBase64()}});
 | 
			
		||||
#endif
 | 
			
		||||
			auto it = m_Peers.find (ident);
 | 
			
		||||
			if (it != m_Peers.end ())
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,9 +14,6 @@
 | 
			
		|||
#include "Config.h"
 | 
			
		||||
#include "Tunnel.h"
 | 
			
		||||
#include "TunnelPool.h"
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -35,9 +32,6 @@ namespace tunnel
 | 
			
		|||
 | 
			
		||||
	void Tunnel::Build (uint32_t replyMsgID, std::shared_ptr<OutboundTunnel> outboundTunnel)
 | 
			
		||||
	{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
		std::string peers = i2p::context.GetIdentity()->GetIdentHash().ToBase64();
 | 
			
		||||
#endif
 | 
			
		||||
		auto numHops = m_Config->GetNumHops ();
 | 
			
		||||
		int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops;
 | 
			
		||||
		auto msg = NewI2NPShortMessage ();
 | 
			
		||||
| 
						 | 
				
			
			@ -64,15 +58,9 @@ namespace tunnel
 | 
			
		|||
			hop->CreateBuildRequestRecord (records + idx*TUNNEL_BUILD_RECORD_SIZE, msgID, ctx);
 | 
			
		||||
			hop->recordIndex = idx;
 | 
			
		||||
			i++;
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			peers += ":" + hop->ident->GetIdentHash().ToBase64();
 | 
			
		||||
#endif
 | 
			
		||||
			hop = hop->next;
 | 
			
		||||
		}
 | 
			
		||||
		BN_CTX_free (ctx);
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
		EmitTunnelEvent("tunnel.build", this, peers);
 | 
			
		||||
#endif
 | 
			
		||||
		// fill up fake records with random data
 | 
			
		||||
		for (int i = numHops; i < numRecords; i++)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -207,9 +195,6 @@ namespace tunnel
 | 
			
		|||
	void Tunnel::SetState(TunnelState state)
 | 
			
		||||
	{
 | 
			
		||||
		m_State = state;
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
		EmitTunnelEvent("tunnel.state", this, state);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -614,9 +599,6 @@ namespace tunnel
 | 
			
		|||
								hop = hop->next;
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
						EmitTunnelEvent("tunnel.state", tunnel.get(), eTunnelStateBuildFailed);
 | 
			
		||||
#endif
 | 
			
		||||
						// for i2lua
 | 
			
		||||
						if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultTimeout);
 | 
			
		||||
						// delete
 | 
			
		||||
| 
						 | 
				
			
			@ -628,9 +610,6 @@ namespace tunnel
 | 
			
		|||
				break;
 | 
			
		||||
				case eTunnelStateBuildFailed:
 | 
			
		||||
					LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " failed, deleted");
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
					EmitTunnelEvent("tunnel.state", tunnel.get(), eTunnelStateBuildFailed);
 | 
			
		||||
#endif
 | 
			
		||||
					// for i2lua
 | 
			
		||||
					if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultRejected);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,42 +25,28 @@ namespace i2p
 | 
			
		|||
{
 | 
			
		||||
namespace tunnel
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
  template<typename TunnelT>
 | 
			
		||||
  static void EmitTunnelEvent(const std::string & ev, const TunnelT & t)
 | 
			
		||||
  {
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
    EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}});
 | 
			
		||||
#else
 | 
			
		||||
	template<typename TunnelT>
 | 
			
		||||
	static void EmitTunnelEvent(const std::string & ev, const TunnelT & t)
 | 
			
		||||
	{
 | 
			
		||||
		(void) ev;
 | 
			
		||||
		(void) t;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  template<typename TunnelT, typename T>
 | 
			
		||||
  static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val)
 | 
			
		||||
  {
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
    EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}, {"value", std::to_string(val)}, {"inbound", std::to_string(t->IsInbound())}});
 | 
			
		||||
#else
 | 
			
		||||
	template<typename TunnelT, typename T>
 | 
			
		||||
	static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val)
 | 
			
		||||
	{
 | 
			
		||||
		(void) ev;
 | 
			
		||||
		(void) t;
 | 
			
		||||
		(void) val;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  template<typename TunnelT>
 | 
			
		||||
  static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const std::string & val)
 | 
			
		||||
  {
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
    EmitEvent({{"type", ev}, {"tid", std::to_string(t->GetTunnelID())}, {"value", val}, {"inbound", std::to_string(t->IsInbound())}});
 | 
			
		||||
#else
 | 
			
		||||
	template<typename TunnelT>
 | 
			
		||||
	static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const std::string & val)
 | 
			
		||||
	{
 | 
			
		||||
		(void) ev;
 | 
			
		||||
		(void) t;
 | 
			
		||||
		(void) val;
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes
 | 
			
		||||
	const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,6 @@
 | 
			
		|||
#include "Tunnel.h"
 | 
			
		||||
#include "TunnelPool.h"
 | 
			
		||||
#include "Destination.h"
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -86,9 +83,6 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		if (!m_IsActive) return;
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.created", createdTunnel);
 | 
			
		||||
#endif
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
 | 
			
		||||
			m_InboundTunnels.insert (createdTunnel);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -102,9 +96,6 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		if (expiredTunnel)
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.expired", expiredTunnel);
 | 
			
		||||
#endif
 | 
			
		||||
			expiredTunnel->SetTunnelPool (nullptr);
 | 
			
		||||
			for (auto& it: m_Tests)
 | 
			
		||||
				if (it.second.second == expiredTunnel) it.second.second = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -118,9 +109,6 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		if (!m_IsActive) return;
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.created", createdTunnel);
 | 
			
		||||
#endif
 | 
			
		||||
			std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
 | 
			
		||||
			m_OutboundTunnels.insert (createdTunnel);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -133,9 +121,6 @@ namespace tunnel
 | 
			
		|||
	{
 | 
			
		||||
		if (expiredTunnel)
 | 
			
		||||
		{
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
			EmitTunnelEvent("tunnels.expired", expiredTunnel);
 | 
			
		||||
#endif
 | 
			
		||||
			expiredTunnel->SetTunnelPool (nullptr);
 | 
			
		||||
			for (auto& it: m_Tests)
 | 
			
		||||
				if (it.second.first == expiredTunnel) it.second.first = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ namespace client
 | 
			
		|||
	const char I2P_CLIENT_TUNNEL_CRYPTO_TYPE[] = "cryptotype";
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels";
 | 
			
		||||
  const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout";
 | 
			
		||||
	const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_HOST[] = "host";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
 | 
			
		||||
	const char I2P_SERVER_TUNNEL_PORT[] = "port";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,491 +2,6 @@
 | 
			
		|||
#include "Log.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "ClientContext.h"
 | 
			
		||||
#include "Identity.h"
 | 
			
		||||
#include "Destination.h"
 | 
			
		||||
#include "Streaming.h"
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
#include <websocketpp/config/asio_no_tls.hpp>
 | 
			
		||||
#include <websocketpp/server.hpp>
 | 
			
		||||
 | 
			
		||||
#include <boost/property_tree/ini_parser.hpp>
 | 
			
		||||
#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))
 | 
			
		||||
#if !GCC47_BOOST149
 | 
			
		||||
#include <boost/property_tree/json_parser.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
namespace client
 | 
			
		||||
{
 | 
			
		||||
	typedef websocketpp::server<websocketpp::config::asio> WebSocksServerImpl;
 | 
			
		||||
 | 
			
		||||
	typedef std::function<void(std::shared_ptr<i2p::stream::Stream>)> StreamConnectFunc;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	struct IWebSocksConn : public I2PServiceHandler
 | 
			
		||||
	{
 | 
			
		||||
		IWebSocksConn(I2PService * parent) : I2PServiceHandler(parent) {}
 | 
			
		||||
		virtual void Close() = 0;
 | 
			
		||||
		virtual void GotMessage(const websocketpp::connection_hdl & conn, WebSocksServerImpl::message_ptr msg) = 0;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	typedef std::shared_ptr<IWebSocksConn> WebSocksConn_ptr;
 | 
			
		||||
 | 
			
		||||
	WebSocksConn_ptr CreateWebSocksConn(const websocketpp::connection_hdl & conn, WebSocksImpl * parent);
 | 
			
		||||
 | 
			
		||||
	class WebSocksImpl
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		typedef std::mutex mutex_t;
 | 
			
		||||
		typedef std::unique_lock<mutex_t> lock_t;
 | 
			
		||||
 | 
			
		||||
		typedef std::shared_ptr<ClientDestination> Destination_t;
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
		typedef WebSocksServerImpl ServerImpl;
 | 
			
		||||
		typedef ServerImpl::message_ptr MessagePtr;
 | 
			
		||||
 | 
			
		||||
		WebSocksImpl(const std::string & addr, int port) :
 | 
			
		||||
			Parent(nullptr),
 | 
			
		||||
			m_Run(false),
 | 
			
		||||
			m_Addr(addr),
 | 
			
		||||
			m_Port(port),
 | 
			
		||||
			m_Thread(nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			m_Server.init_asio();
 | 
			
		||||
			m_Server.set_open_handler(std::bind(&WebSocksImpl::ConnOpened, this, std::placeholders::_1));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void InitializeDestination(WebSocks * parent)
 | 
			
		||||
		{
 | 
			
		||||
			Parent = parent;
 | 
			
		||||
			m_Dest = Parent->GetLocalDestination();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ServerImpl::connection_ptr GetConn(const websocketpp::connection_hdl & conn)
 | 
			
		||||
		{
 | 
			
		||||
			return m_Server.get_con_from_hdl(conn);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void CloseConn(const websocketpp::connection_hdl & conn)
 | 
			
		||||
		{
 | 
			
		||||
			auto c = GetConn(conn);
 | 
			
		||||
			if(c) c->close(websocketpp::close::status::normal, "closed");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void CreateStreamTo(const std::string & addr, int port, StreamConnectFunc complete)
 | 
			
		||||
		{
 | 
			
		||||
			auto & addressbook = i2p::client::context.GetAddressBook();
 | 
			
		||||
			auto a = addressbook.GetAddress (addr);
 | 
			
		||||
			if (a && a->IsIdentHash ())
 | 
			
		||||
			{
 | 
			
		||||
				// address found				
 | 
			
		||||
				m_Dest->CreateStream(complete, a->identHash, port);
 | 
			
		||||
			}
 | 
			
		||||
			else 
 | 
			
		||||
			{
 | 
			
		||||
				// not found
 | 
			
		||||
				complete(nullptr);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void ConnOpened(websocketpp::connection_hdl conn)
 | 
			
		||||
		{
 | 
			
		||||
			auto ptr = CreateWebSocksConn(conn, this);
 | 
			
		||||
			Parent->AddHandler(ptr);
 | 
			
		||||
			m_Conns.push_back(ptr);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void Start()
 | 
			
		||||
		{
 | 
			
		||||
			if(m_Run) return; // already started
 | 
			
		||||
			m_Server.listen(boost::asio::ip::address::from_string(m_Addr), m_Port);
 | 
			
		||||
			m_Server.start_accept();
 | 
			
		||||
			m_Run = true;
 | 
			
		||||
			m_Thread = new std::thread([&] (){
 | 
			
		||||
					while(m_Run) {
 | 
			
		||||
						try {
 | 
			
		||||
							m_Server.run();
 | 
			
		||||
						} catch( std::exception & ex) {
 | 
			
		||||
							LogPrint(eLogError, "Websocks runtime exception: ", ex.what());
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
			});
 | 
			
		||||
			m_Dest->Start();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void Stop()
 | 
			
		||||
		{
 | 
			
		||||
			for(const auto & conn : m_Conns)
 | 
			
		||||
				conn->Close();
 | 
			
		||||
 | 
			
		||||
			m_Dest->Stop();
 | 
			
		||||
			m_Run = false;
 | 
			
		||||
			m_Server.stop();
 | 
			
		||||
			if(m_Thread) {
 | 
			
		||||
				m_Thread->join();
 | 
			
		||||
				delete m_Thread;
 | 
			
		||||
			}
 | 
			
		||||
			m_Thread = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		boost::asio::ip::tcp::endpoint GetLocalEndpoint()
 | 
			
		||||
		{
 | 
			
		||||
			return boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(m_Addr), m_Port);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		i2p::datagram::DatagramDestination * GetDatagramDest() const
 | 
			
		||||
		{
 | 
			
		||||
			auto dgram = m_Dest->GetDatagramDestination();
 | 
			
		||||
			if(!dgram) dgram = m_Dest->CreateDatagramDestination();
 | 
			
		||||
			return dgram;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		WebSocks * Parent;
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
		std::vector<WebSocksConn_ptr> m_Conns;
 | 
			
		||||
		bool m_Run;
 | 
			
		||||
		ServerImpl m_Server;
 | 
			
		||||
		std::string m_Addr;
 | 
			
		||||
		int m_Port;
 | 
			
		||||
		std::thread * m_Thread;
 | 
			
		||||
		Destination_t m_Dest;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct WebSocksConn : public IWebSocksConn , public std::enable_shared_from_this<WebSocksConn>
 | 
			
		||||
	{
 | 
			
		||||
		enum ConnState
 | 
			
		||||
		{
 | 
			
		||||
			eWSCInitial,
 | 
			
		||||
			eWSCTryConnect,
 | 
			
		||||
			eWSCFailConnect,
 | 
			
		||||
			eWSCOkayConnect,
 | 
			
		||||
			eWSCDatagram,
 | 
			
		||||
			eWSCClose,
 | 
			
		||||
			eWSCEnd
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		typedef WebSocksServerImpl ServerImpl;
 | 
			
		||||
		typedef ServerImpl::message_ptr Message_t;
 | 
			
		||||
		typedef websocketpp::connection_hdl ServerConn;
 | 
			
		||||
		typedef std::shared_ptr<ClientDestination> Destination_t;
 | 
			
		||||
		typedef std::shared_ptr<i2p::stream::StreamingDestination> StreamDest_t;
 | 
			
		||||
		typedef std::shared_ptr<i2p::stream::Stream> Stream_t;
 | 
			
		||||
 | 
			
		||||
		ServerConn m_Conn;
 | 
			
		||||
		Stream_t m_Stream;
 | 
			
		||||
		ConnState m_State;
 | 
			
		||||
		WebSocksImpl * m_Parent;
 | 
			
		||||
		std::string m_RemoteAddr;
 | 
			
		||||
		int m_RemotePort;
 | 
			
		||||
		uint8_t m_RecvBuf[2048];
 | 
			
		||||
		bool m_IsDatagram;
 | 
			
		||||
		i2p::datagram::DatagramDestination * m_Datagram;
 | 
			
		||||
 | 
			
		||||
		WebSocksConn(const ServerConn & conn, WebSocksImpl * parent) :
 | 
			
		||||
			IWebSocksConn(parent->Parent),
 | 
			
		||||
			m_Conn(conn),
 | 
			
		||||
			m_Stream(nullptr),
 | 
			
		||||
			m_State(eWSCInitial),
 | 
			
		||||
			m_Parent(parent),
 | 
			
		||||
			m_IsDatagram(false),
 | 
			
		||||
			m_Datagram(nullptr)
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		~WebSocksConn()
 | 
			
		||||
		{
 | 
			
		||||
			Close();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void HandleDatagram(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
 | 
			
		||||
		{
 | 
			
		||||
			auto conn = m_Parent->GetConn(m_Conn);
 | 
			
		||||
			if(conn)
 | 
			
		||||
			{
 | 
			
		||||
				std::stringstream ss;
 | 
			
		||||
				ss << from.GetIdentHash().ToBase32();
 | 
			
		||||
				ss << ".b32.i2p:";
 | 
			
		||||
				ss << std::to_string(fromPort);
 | 
			
		||||
				ss << "\n";
 | 
			
		||||
				ss.write((char *)buf, len);
 | 
			
		||||
				conn->send(ss.str());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		void BeginDatagram()
 | 
			
		||||
		{
 | 
			
		||||
			m_Datagram = m_Parent->GetDatagramDest();
 | 
			
		||||
			m_Datagram->SetReceiver(
 | 
			
		||||
				std::bind(
 | 
			
		||||
					&WebSocksConn::HandleDatagram,
 | 
			
		||||
					this,
 | 
			
		||||
					std::placeholders::_1,
 | 
			
		||||
					std::placeholders::_2,
 | 
			
		||||
					std::placeholders::_3,
 | 
			
		||||
					std::placeholders::_4,
 | 
			
		||||
					std::placeholders::_5), m_RemotePort);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void EnterState(ConnState state)
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogDebug, "websocks: state ", m_State, " -> ", state);
 | 
			
		||||
			switch(m_State)
 | 
			
		||||
			{
 | 
			
		||||
			case eWSCInitial:
 | 
			
		||||
				if (state == eWSCClose) {
 | 
			
		||||
					m_State = eWSCClose;
 | 
			
		||||
					// connection was opened but never used
 | 
			
		||||
					LogPrint(eLogInfo, "websocks: connection closed but never used");
 | 
			
		||||
					Close();
 | 
			
		||||
					return;
 | 
			
		||||
				} else if (state == eWSCTryConnect) {
 | 
			
		||||
					// we will try to connect
 | 
			
		||||
					m_State = eWSCTryConnect;
 | 
			
		||||
					m_Parent->CreateStreamTo(m_RemoteAddr, m_RemotePort, std::bind(&WebSocksConn::ConnectResult, this, std::placeholders::_1));
 | 
			
		||||
				} else if (state == eWSCDatagram) {
 | 
			
		||||
					if (m_RemotePort >= 0 && m_RemotePort <= 65535)
 | 
			
		||||
					{
 | 
			
		||||
						LogPrint(eLogDebug, "websocks: datagram mode initiated");
 | 
			
		||||
						m_State = eWSCDatagram;
 | 
			
		||||
						BeginDatagram();
 | 
			
		||||
						SendResponse("");
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
						SendResponse("invalid port");
 | 
			
		||||
				} else {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state);
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
			case eWSCTryConnect:
 | 
			
		||||
				if(state == eWSCOkayConnect) {
 | 
			
		||||
					// we connected okay
 | 
			
		||||
					LogPrint(eLogDebug, "websocks: connected to ", m_RemoteAddr, ":", m_RemotePort);
 | 
			
		||||
					SendResponse("");
 | 
			
		||||
					m_State = eWSCOkayConnect;
 | 
			
		||||
				} else if(state == eWSCFailConnect) {
 | 
			
		||||
					// we did not connect okay
 | 
			
		||||
					LogPrint(eLogDebug, "websocks: failed to connect to ", m_RemoteAddr, ":", m_RemotePort);
 | 
			
		||||
					SendResponse("failed to connect");
 | 
			
		||||
					m_State = eWSCFailConnect;
 | 
			
		||||
					EnterState(eWSCInitial);
 | 
			
		||||
				} else if(state == eWSCClose) {
 | 
			
		||||
					// premature close
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: websocket connection closed prematurely");
 | 
			
		||||
					m_State = eWSCClose;
 | 
			
		||||
				} else {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state);
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
			case eWSCFailConnect:
 | 
			
		||||
				if (state == eWSCInitial) {
 | 
			
		||||
					// reset to initial state so we can try connecting again
 | 
			
		||||
					m_RemoteAddr = "";
 | 
			
		||||
					m_RemotePort = 0;
 | 
			
		||||
					LogPrint(eLogDebug, "websocks: reset websocket conn to initial state");
 | 
			
		||||
					m_State = eWSCInitial;
 | 
			
		||||
				} else if (state == eWSCClose) {
 | 
			
		||||
					// we are going to close the connection
 | 
			
		||||
					m_State = eWSCClose;
 | 
			
		||||
					Close();
 | 
			
		||||
				} else {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state);
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
			case eWSCDatagram:
 | 
			
		||||
				if(state != eWSCClose) {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state);
 | 
			
		||||
				}
 | 
			
		||||
				m_State = eWSCClose;
 | 
			
		||||
				Close();
 | 
			
		||||
				return;
 | 
			
		||||
			case eWSCOkayConnect:
 | 
			
		||||
				if(state == eWSCClose) {
 | 
			
		||||
					// graceful close
 | 
			
		||||
					m_State = eWSCClose;
 | 
			
		||||
					Close();
 | 
			
		||||
				} else {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state);
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
			case eWSCClose:
 | 
			
		||||
				if(state == eWSCEnd) {
 | 
			
		||||
					LogPrint(eLogDebug, "websocks: socket ended");
 | 
			
		||||
					Kill();
 | 
			
		||||
					auto me = shared_from_this();
 | 
			
		||||
					Done(me);
 | 
			
		||||
				} else {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: invalid state change ", m_State, " -> ", state);
 | 
			
		||||
				}
 | 
			
		||||
				return;
 | 
			
		||||
			default:
 | 
			
		||||
				LogPrint(eLogError, "websocks: bad state ", m_State);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void StartForwarding()
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogDebug, "websocks: begin forwarding data");
 | 
			
		||||
			uint8_t b[1];
 | 
			
		||||
			m_Stream->Send(b, 0);
 | 
			
		||||
			AsyncRecv();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void HandleAsyncRecv(const boost::system::error_code &ec, std::size_t n)
 | 
			
		||||
		{
 | 
			
		||||
			if(ec) {
 | 
			
		||||
				// error
 | 
			
		||||
				LogPrint(eLogWarning, "websocks: connection error ", ec.message());
 | 
			
		||||
				EnterState(eWSCClose);
 | 
			
		||||
			} else {
 | 
			
		||||
				// forward data
 | 
			
		||||
				LogPrint(eLogDebug, "websocks recv ", n);
 | 
			
		||||
 | 
			
		||||
				std::string str((char*)m_RecvBuf, n);
 | 
			
		||||
				auto conn = m_Parent->GetConn(m_Conn);
 | 
			
		||||
				if(!conn)	 {
 | 
			
		||||
					LogPrint(eLogWarning, "websocks: connection is gone");
 | 
			
		||||
					EnterState(eWSCClose);
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				conn->send(str);
 | 
			
		||||
				AsyncRecv();
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void AsyncRecv()
 | 
			
		||||
		{
 | 
			
		||||
			m_Stream->AsyncReceive(
 | 
			
		||||
				boost::asio::buffer(m_RecvBuf, sizeof(m_RecvBuf)),
 | 
			
		||||
				std::bind(&WebSocksConn::HandleAsyncRecv, this, std::placeholders::_1, std::placeholders::_2), 60);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/** @brief send error message or empty string for success */
 | 
			
		||||
		void SendResponse(const std::string & errormsg)
 | 
			
		||||
		{
 | 
			
		||||
			boost::property_tree::ptree resp;
 | 
			
		||||
			if(errormsg.size()) {
 | 
			
		||||
				resp.put("error", errormsg);
 | 
			
		||||
				resp.put("success", 0);
 | 
			
		||||
			} else {
 | 
			
		||||
				resp.put("success", 1);
 | 
			
		||||
			}
 | 
			
		||||
			std::ostringstream ss;
 | 
			
		||||
			write_json(ss, resp);
 | 
			
		||||
			auto conn = m_Parent->GetConn(m_Conn);
 | 
			
		||||
			if(conn) conn->send(ss.str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void ConnectResult(Stream_t stream)
 | 
			
		||||
		{
 | 
			
		||||
			m_Stream = stream;
 | 
			
		||||
			if(m_State == eWSCClose) {
 | 
			
		||||
				// premature close of websocket
 | 
			
		||||
				Close();
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			if(m_Stream) {
 | 
			
		||||
				// connect good
 | 
			
		||||
				EnterState(eWSCOkayConnect);
 | 
			
		||||
				StartForwarding();
 | 
			
		||||
			} else {
 | 
			
		||||
				// connect failed
 | 
			
		||||
				EnterState(eWSCFailConnect);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		virtual void GotMessage(const websocketpp::connection_hdl & conn, WebSocksServerImpl::message_ptr msg)
 | 
			
		||||
		{
 | 
			
		||||
			(void) conn;
 | 
			
		||||
			std::string payload = msg->get_payload();
 | 
			
		||||
			if(m_State == eWSCOkayConnect)
 | 
			
		||||
			{
 | 
			
		||||
				// forward to server
 | 
			
		||||
				LogPrint(eLogDebug, "websocks: forward ", payload.size());
 | 
			
		||||
				m_Stream->Send((uint8_t*)payload.c_str(), payload.size());
 | 
			
		||||
			} else if (m_State == eWSCInitial) {
 | 
			
		||||
				// recv connect request
 | 
			
		||||
				auto itr = payload.find(":");
 | 
			
		||||
				if(itr == std::string::npos) {
 | 
			
		||||
					// no port
 | 
			
		||||
					m_RemotePort = 0;
 | 
			
		||||
					m_RemoteAddr = payload;
 | 
			
		||||
				} else {
 | 
			
		||||
					// includes port
 | 
			
		||||
					m_RemotePort = std::stoi(payload.substr(itr+1));
 | 
			
		||||
					m_RemoteAddr = payload.substr(0, itr);
 | 
			
		||||
				}
 | 
			
		||||
				m_IsDatagram = m_RemoteAddr == "DATAGRAM";
 | 
			
		||||
				if(m_IsDatagram)
 | 
			
		||||
					EnterState(eWSCDatagram);
 | 
			
		||||
				else
 | 
			
		||||
					EnterState(eWSCTryConnect);
 | 
			
		||||
			} else if (m_State == eWSCDatagram) {
 | 
			
		||||
				// send datagram
 | 
			
		||||
				// format is "host:port\npayload"
 | 
			
		||||
				auto idx = payload.find("\n");
 | 
			
		||||
				std::string line = payload.substr(0, idx);
 | 
			
		||||
				auto itr = line.find(":");
 | 
			
		||||
				auto & addressbook = i2p::client::context.GetAddressBook();
 | 
			
		||||
				std::string addr;
 | 
			
		||||
				int port = 0;
 | 
			
		||||
				if (itr == std::string::npos)
 | 
			
		||||
				{
 | 
			
		||||
					addr = line;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					addr = line.substr(0, itr);
 | 
			
		||||
					port = std::atoi(line.substr(itr+1).c_str());
 | 
			
		||||
				}
 | 
			
		||||
				auto a = addressbook.GetAddress (addr);
 | 
			
		||||
				if (a && a->IsIdentHash ())
 | 
			
		||||
				{
 | 
			
		||||
					const char * data = payload.c_str() + idx + 1;
 | 
			
		||||
					size_t len = payload.size() - (1 + line.size());
 | 
			
		||||
					m_Datagram->SendDatagramTo((const uint8_t*)data, len, a->identHash, m_RemotePort, port);
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				// wtf?
 | 
			
		||||
				LogPrint(eLogWarning, "websocks: got message in invalid state ", m_State);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		virtual void Close()
 | 
			
		||||
		{
 | 
			
		||||
			if(m_State == eWSCClose) {
 | 
			
		||||
				LogPrint(eLogDebug, "websocks: closing connection");
 | 
			
		||||
				if(m_Stream) m_Stream->Close();
 | 
			
		||||
				if(m_Datagram) m_Datagram->ResetReceiver(m_RemotePort);
 | 
			
		||||
				m_Parent->CloseConn(m_Conn);
 | 
			
		||||
				EnterState(eWSCEnd);
 | 
			
		||||
			} else {
 | 
			
		||||
				EnterState(eWSCClose);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	WebSocksConn_ptr CreateWebSocksConn(const websocketpp::connection_hdl & conn, WebSocksImpl * parent)
 | 
			
		||||
	{
 | 
			
		||||
		auto ptr = std::make_shared<WebSocksConn>(conn, parent);
 | 
			
		||||
		auto c = parent->GetConn(conn);
 | 
			
		||||
		c->set_message_handler(std::bind(&WebSocksConn::GotMessage, ptr.get(), std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
		return ptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
// no websocket support
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
namespace client
 | 
			
		||||
| 
						 | 
				
			
			@ -504,7 +19,7 @@ namespace client
 | 
			
		|||
 | 
			
		||||
		void Start()
 | 
			
		||||
		{
 | 
			
		||||
			LogPrint(eLogInfo, "WebSockets not enabled on compile time");
 | 
			
		||||
			LogPrint(eLogInfo, "[Tunnels] starting websocks tunnel at %s:%d is rejected: WebSockets is deprecated", m_Addr, m_Port);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void Stop()
 | 
			
		||||
| 
						 | 
				
			
			@ -527,7 +42,6 @@ namespace client
 | 
			
		|||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
namespace client
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,195 +0,0 @@
 | 
			
		|||
#ifdef WITH_EVENTS
 | 
			
		||||
#include "Websocket.h"
 | 
			
		||||
#include "Log.h"
 | 
			
		||||
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
#include <websocketpp/config/asio_no_tls.hpp>
 | 
			
		||||
#include <websocketpp/server.hpp>
 | 
			
		||||
#include <boost/property_tree/ini_parser.hpp>
 | 
			
		||||
#define GCC47_BOOST149 ((BOOST_VERSION == 104900) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))
 | 
			
		||||
#if !GCC47_BOOST149
 | 
			
		||||
#include <boost/property_tree/json_parser.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
	namespace event
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		typedef websocketpp::server<websocketpp::config::asio> ServerImpl;
 | 
			
		||||
		typedef websocketpp::connection_hdl ServerConn;
 | 
			
		||||
 | 
			
		||||
		class WebsocketServerImpl : public EventListener
 | 
			
		||||
		{
 | 
			
		||||
		private:
 | 
			
		||||
			typedef ServerImpl::message_ptr MessagePtr;
 | 
			
		||||
		public:
 | 
			
		||||
 | 
			
		||||
			WebsocketServerImpl(const std::string & addr, int port) :
 | 
			
		||||
				m_run(false),
 | 
			
		||||
				m_ws_thread(nullptr),
 | 
			
		||||
				m_ev_thread(nullptr),
 | 
			
		||||
				m_WebsocketTicker(m_Service)
 | 
			
		||||
			{
 | 
			
		||||
				m_server.init_asio();
 | 
			
		||||
				m_server.set_open_handler(std::bind(&WebsocketServerImpl::ConnOpened, this, std::placeholders::_1));
 | 
			
		||||
				m_server.set_close_handler(std::bind(&WebsocketServerImpl::ConnClosed, this, std::placeholders::_1));
 | 
			
		||||
				m_server.set_message_handler(std::bind(&WebsocketServerImpl::OnConnMessage, this, std::placeholders::_1, std::placeholders::_2));
 | 
			
		||||
 | 
			
		||||
				m_server.listen(boost::asio::ip::address::from_string(addr), port);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			~WebsocketServerImpl()
 | 
			
		||||
			{
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void Start() {
 | 
			
		||||
				m_run = true;
 | 
			
		||||
				m_server.start_accept();
 | 
			
		||||
				m_ws_thread = new std::thread([&] () {
 | 
			
		||||
						while(m_run) {
 | 
			
		||||
							try {
 | 
			
		||||
								m_server.run();
 | 
			
		||||
							} catch (std::exception & e ) {
 | 
			
		||||
								LogPrint(eLogError, "Websocket server: ", e.what());
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					});
 | 
			
		||||
				m_ev_thread = new std::thread([&] () {
 | 
			
		||||
						while(m_run) {
 | 
			
		||||
							try {
 | 
			
		||||
								m_Service.run();
 | 
			
		||||
								break;
 | 
			
		||||
							} catch (std::exception & e ) {
 | 
			
		||||
								LogPrint(eLogError, "Websocket service: ", e.what());
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					});
 | 
			
		||||
				ScheduleTick();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void Stop() {
 | 
			
		||||
				m_run = false;
 | 
			
		||||
				m_Service.stop();
 | 
			
		||||
				m_server.stop();
 | 
			
		||||
 | 
			
		||||
				if(m_ev_thread) {
 | 
			
		||||
					m_ev_thread->join();
 | 
			
		||||
					delete m_ev_thread;
 | 
			
		||||
				}
 | 
			
		||||
				m_ev_thread = nullptr;
 | 
			
		||||
 | 
			
		||||
				if(m_ws_thread) {
 | 
			
		||||
					m_ws_thread->join();
 | 
			
		||||
					delete m_ws_thread;
 | 
			
		||||
				}
 | 
			
		||||
				m_ws_thread = nullptr;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void ConnOpened(ServerConn c)
 | 
			
		||||
			{
 | 
			
		||||
				std::lock_guard<std::mutex> lock(m_connsMutex);
 | 
			
		||||
				m_conns.insert(c);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void ConnClosed(ServerConn c)
 | 
			
		||||
			{
 | 
			
		||||
				std::lock_guard<std::mutex> lock(m_connsMutex);
 | 
			
		||||
				m_conns.erase(c);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void OnConnMessage(ServerConn conn, ServerImpl::message_ptr msg)
 | 
			
		||||
			{
 | 
			
		||||
				(void) conn;
 | 
			
		||||
				(void) msg;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void HandleTick(const boost::system::error_code & ec)
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
				if(ec != boost::asio::error::operation_aborted)
 | 
			
		||||
					LogPrint(eLogError, "Websocket ticker: ", ec.message());
 | 
			
		||||
				// pump collected events to us
 | 
			
		||||
				i2p::event::core.PumpCollected(this);
 | 
			
		||||
				ScheduleTick();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			void ScheduleTick()
 | 
			
		||||
			{
 | 
			
		||||
				LogPrint(eLogDebug, "Websocket schedule tick");
 | 
			
		||||
				boost::posix_time::seconds dlt(1);
 | 
			
		||||
				m_WebsocketTicker.expires_from_now(dlt);
 | 
			
		||||
				m_WebsocketTicker.async_wait(std::bind(&WebsocketServerImpl::HandleTick, this, std::placeholders::_1));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/** @brief called from m_ev_thread */
 | 
			
		||||
			void HandlePumpEvent(const EventType & ev, const uint64_t & val)
 | 
			
		||||
			{
 | 
			
		||||
				EventType e;
 | 
			
		||||
				for (const auto & i : ev)
 | 
			
		||||
					e[i.first] = i.second;
 | 
			
		||||
 | 
			
		||||
				e["number"] = std::to_string(val);
 | 
			
		||||
				HandleEvent(e);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/** @brief called from m_ws_thread */
 | 
			
		||||
			void HandleEvent(const EventType & ev)
 | 
			
		||||
			{
 | 
			
		||||
				std::lock_guard<std::mutex> lock(m_connsMutex);
 | 
			
		||||
				boost::property_tree::ptree event;
 | 
			
		||||
				for (const auto & item : ev) {
 | 
			
		||||
					event.put(item.first, item.second);
 | 
			
		||||
				}
 | 
			
		||||
				std::ostringstream ss;
 | 
			
		||||
				write_json(ss, event);
 | 
			
		||||
				std::string s = ss.str();
 | 
			
		||||
 | 
			
		||||
				 ConnList::iterator it;
 | 
			
		||||
				 for (it = m_conns.begin(); it != m_conns.end(); ++it) {
 | 
			
		||||
					 ServerImpl::connection_ptr con = m_server.get_con_from_hdl(*it);
 | 
			
		||||
					 con->send(s);
 | 
			
		||||
				 }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
			typedef std::set<ServerConn, std::owner_less<ServerConn> > ConnList;
 | 
			
		||||
			bool m_run;
 | 
			
		||||
			std::thread * m_ws_thread;
 | 
			
		||||
			std::thread * m_ev_thread;
 | 
			
		||||
			std::mutex m_connsMutex;
 | 
			
		||||
			ConnList m_conns;
 | 
			
		||||
			ServerImpl m_server;
 | 
			
		||||
			boost::asio::io_service m_Service;
 | 
			
		||||
			boost::asio::deadline_timer m_WebsocketTicker;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		WebsocketServer::WebsocketServer(const std::string & addr, int port) : m_impl(new WebsocketServerImpl(addr, port)) {}
 | 
			
		||||
		WebsocketServer::~WebsocketServer()
 | 
			
		||||
		{
 | 
			
		||||
			delete m_impl;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		void WebsocketServer::Start()
 | 
			
		||||
		{
 | 
			
		||||
			m_impl->Start();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void WebsocketServer::Stop()
 | 
			
		||||
		{
 | 
			
		||||
			m_impl->Stop();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		EventListener * WebsocketServer::ToListener()
 | 
			
		||||
		{
 | 
			
		||||
			return m_impl;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,28 +0,0 @@
 | 
			
		|||
#ifndef WEBSOCKET_H__
 | 
			
		||||
#define WEBSOCKET_H__
 | 
			
		||||
#include "Event.h"
 | 
			
		||||
namespace i2p
 | 
			
		||||
{
 | 
			
		||||
	namespace event
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
		class WebsocketServerImpl;
 | 
			
		||||
 | 
			
		||||
		class WebsocketServer
 | 
			
		||||
		{
 | 
			
		||||
		public:
 | 
			
		||||
			WebsocketServer(const std::string & addr, int port);
 | 
			
		||||
			~WebsocketServer();
 | 
			
		||||
 | 
			
		||||
			void Start();
 | 
			
		||||
			void Stop();
 | 
			
		||||
 | 
			
		||||
			EventListener * ToListener();
 | 
			
		||||
 | 
			
		||||
		private:
 | 
			
		||||
			WebsocketServerImpl * m_impl;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -2135,121 +2135,6 @@ Comma separated list of base64 identities:</string>
 | 
			
		|||
      </widget>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item row="25" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="groupBox_websock">
 | 
			
		||||
      <property name="sizePolicy">
 | 
			
		||||
       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
			
		||||
        <horstretch>0</horstretch>
 | 
			
		||||
        <verstretch>0</verstretch>
 | 
			
		||||
       </sizepolicy>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="minimumSize">
 | 
			
		||||
       <size>
 | 
			
		||||
        <width>0</width>
 | 
			
		||||
        <height>105</height>
 | 
			
		||||
       </size>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="maximumSize">
 | 
			
		||||
       <size>
 | 
			
		||||
        <width>16777215</width>
 | 
			
		||||
        <height>105</height>
 | 
			
		||||
       </size>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Websockets server</string>
 | 
			
		||||
      </property>
 | 
			
		||||
      <widget class="QCheckBox" name="checkBoxWebsocketsEnable">
 | 
			
		||||
       <property name="geometry">
 | 
			
		||||
        <rect>
 | 
			
		||||
         <x>0</x>
 | 
			
		||||
         <y>20</y>
 | 
			
		||||
         <width>85</width>
 | 
			
		||||
         <height>21</height>
 | 
			
		||||
        </rect>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Enable</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
      <widget class="QWidget" name="horizontalLayoutWidget_32">
 | 
			
		||||
       <property name="geometry">
 | 
			
		||||
        <rect>
 | 
			
		||||
         <x>0</x>
 | 
			
		||||
         <y>40</y>
 | 
			
		||||
         <width>661</width>
 | 
			
		||||
         <height>31</height>
 | 
			
		||||
        </rect>
 | 
			
		||||
       </property>
 | 
			
		||||
       <layout class="QHBoxLayout" name="horizontalLayout_38">
 | 
			
		||||
        <item>
 | 
			
		||||
         <widget class="QLabel" name="label_40">
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Address to bind websocket server on:</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <widget class="QLineEdit" name="lineEdit_webSock_addr"/>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <spacer name="horizontalSpacer_26">
 | 
			
		||||
          <property name="orientation">
 | 
			
		||||
           <enum>Qt::Horizontal</enum>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="sizeHint" stdset="0">
 | 
			
		||||
           <size>
 | 
			
		||||
            <width>40</width>
 | 
			
		||||
            <height>20</height>
 | 
			
		||||
           </size>
 | 
			
		||||
          </property>
 | 
			
		||||
         </spacer>
 | 
			
		||||
        </item>
 | 
			
		||||
       </layout>
 | 
			
		||||
      </widget>
 | 
			
		||||
      <widget class="QWidget" name="horizontalLayoutWidget_33">
 | 
			
		||||
       <property name="geometry">
 | 
			
		||||
        <rect>
 | 
			
		||||
         <x>0</x>
 | 
			
		||||
         <y>70</y>
 | 
			
		||||
         <width>661</width>
 | 
			
		||||
         <height>31</height>
 | 
			
		||||
        </rect>
 | 
			
		||||
       </property>
 | 
			
		||||
       <layout class="QHBoxLayout" name="horizontalLayout_39">
 | 
			
		||||
        <item>
 | 
			
		||||
         <widget class="QLabel" name="label_41">
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>Port to bind websocket server on:</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <widget class="QLineEdit" name="lineEdit_webSock_port">
 | 
			
		||||
          <property name="maximumSize">
 | 
			
		||||
           <size>
 | 
			
		||||
            <width>80</width>
 | 
			
		||||
            <height>16777215</height>
 | 
			
		||||
           </size>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <spacer name="horizontalSpacer_27">
 | 
			
		||||
          <property name="orientation">
 | 
			
		||||
           <enum>Qt::Horizontal</enum>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="sizeHint" stdset="0">
 | 
			
		||||
           <size>
 | 
			
		||||
            <width>40</width>
 | 
			
		||||
            <height>20</height>
 | 
			
		||||
           </size>
 | 
			
		||||
          </property>
 | 
			
		||||
         </spacer>
 | 
			
		||||
        </item>
 | 
			
		||||
       </layout>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item row="11" column="0">
 | 
			
		||||
     <widget class="QGroupBox" name="webconsoleGroupBox">
 | 
			
		||||
      <property name="minimumSize">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,7 +74,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
 | 
			
		|||
    ../../libi2pd_client/MatchedDestination.cpp \
 | 
			
		||||
    ../../libi2pd_client/SAM.cpp \
 | 
			
		||||
    ../../libi2pd_client/SOCKS.cpp \
 | 
			
		||||
    ../../libi2pd_client/Websocket.cpp \
 | 
			
		||||
    ../../libi2pd_client/WebSocks.cpp \
 | 
			
		||||
    ../../daemon/Daemon.cpp \
 | 
			
		||||
    ../../daemon/HTTPServer.cpp \
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +160,6 @@ HEADERS  += DaemonQT.h mainwindow.h \
 | 
			
		|||
    ../../libi2pd_client/MatchedDestination.h \
 | 
			
		||||
    ../../libi2pd_client/SAM.h \
 | 
			
		||||
    ../../libi2pd_client/SOCKS.h \
 | 
			
		||||
    ../../libi2pd_client/Websocket.h \
 | 
			
		||||
    ../../libi2pd_client/WebSocks.h \
 | 
			
		||||
    ../../daemon/Daemon.h \
 | 
			
		||||
    ../../daemon/HTTPServer.h \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,10 +258,6 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
 | 
			
		|||
    initStringBox(      OPTION("trust","routers",[]{return "";}), uiSettings->lineEditTrustRouters);
 | 
			
		||||
    initCheckBox(       OPTION("trust","hidden",[]{return "false";}), uiSettings->checkBoxTrustHidden);
 | 
			
		||||
 | 
			
		||||
    initCheckBox(       OPTION("websockets","enabled",[]{return "false";}), uiSettings->checkBoxWebsocketsEnable);
 | 
			
		||||
    initIPAddressBox(   OPTION("websockets","address",[]{return "127.0.0.1";}), uiSettings->lineEdit_webSock_addr, tr("Websocket server -> IP address"));
 | 
			
		||||
    initTCPPortBox(     OPTION("websockets","port",[]{return "7666";}), uiSettings->lineEdit_webSock_port, tr("Websocket server -> Port"));
 | 
			
		||||
 | 
			
		||||
#   undef OPTION
 | 
			
		||||
 | 
			
		||||
    //widgetlocks.add(new widgetlock(widget,lockbtn));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue