mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 00:00:29 +03:00
add web socket ui
This commit is contained in:
parent
3d4e2a275c
commit
b4e9ed7d18
13
Config.cpp
13
Config.cpp
@ -176,9 +176,21 @@ namespace config {
|
||||
trust.add_options()
|
||||
("trust.enabled", value<bool>()->default_value(false), "Enable explicit trust options")
|
||||
("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops")
|
||||
<<<<<<< HEAD
|
||||
("trust.routers", value<std::string>()->default_value(""), "Only Connect to these routers")
|
||||
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?");
|
||||
|
||||
=======
|
||||
("trust.routerInfo", value<std::string>()->default_value(""), "Path to routerInfo of floodfill to use with floodfill friend mode")
|
||||
("trust.hidden", value<bool>()->default_value(true), "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");
|
||||
|
||||
>>>>>>> bda4170... add web socket ui
|
||||
m_OptionsDesc
|
||||
.add(general)
|
||||
.add(limits)
|
||||
@ -194,6 +206,7 @@ namespace config {
|
||||
.add(reseed)
|
||||
.add(addressbook)
|
||||
.add(trust)
|
||||
.add(websocket)
|
||||
;
|
||||
}
|
||||
|
||||
|
23
Daemon.cpp
23
Daemon.cpp
@ -25,6 +25,9 @@
|
||||
#include "UPnP.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "Event.h"
|
||||
#include "Websocket.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace util
|
||||
@ -38,6 +41,7 @@ namespace i2p
|
||||
std::unique_ptr<i2p::http::HTTPServer> httpServer;
|
||||
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
|
||||
std::unique_ptr<i2p::transport::UPnP> UPnP;
|
||||
std::unique_ptr<i2p::event::WebsocketServer> m_WebsocketServer;
|
||||
};
|
||||
|
||||
Daemon_Singleton::Daemon_Singleton() : isDaemon(false), running(true), d(*new Daemon_Singleton_Private()) {}
|
||||
@ -291,11 +295,23 @@ namespace i2p
|
||||
d.m_I2PControlService->Start ();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Daemon_Singleton::stop()
|
||||
{
|
||||
i2p::event::core.SetListener(nullptr);
|
||||
LogPrint(eLogInfo, "Daemon: shutting down");
|
||||
LogPrint(eLogInfo, "Daemon: stopping Client");
|
||||
i2p::client::context.Stop();
|
||||
@ -322,6 +338,13 @@ namespace i2p
|
||||
d.m_I2PControlService->Stop ();
|
||||
d.m_I2PControlService = nullptr;
|
||||
}
|
||||
|
||||
if (d.m_WebsocketServer) {
|
||||
LogPrint(eLogInfo, "Daemon: stopping Websocket server");
|
||||
d.m_WebsocketServer->Stop();
|
||||
d.m_WebsocketServer = nullptr;
|
||||
}
|
||||
|
||||
i2p::crypto::TerminateCrypto ();
|
||||
|
||||
return true;
|
||||
|
28
Event.cpp
Normal file
28
Event.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "Event.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace event
|
||||
{
|
||||
EventCore core;
|
||||
|
||||
void EventCore::SetListener(EventListener * l)
|
||||
{
|
||||
m_listener = l;
|
||||
LogPrint(eLogInfo, "Event: listener set");
|
||||
}
|
||||
|
||||
void EventCore::QueueEvent(const EventType & ev)
|
||||
{
|
||||
if(m_listener)
|
||||
m_listener->HandleEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmitEvent(const EventType & e)
|
||||
{
|
||||
i2p::event::core.QueueEvent(e);
|
||||
}
|
||||
|
37
Event.h
Normal file
37
Event.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef EVENT_H__
|
||||
#define EVENT_H__
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
typedef std::map<std::string, std::string> EventType;
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
namespace event
|
||||
{
|
||||
class EventListener {
|
||||
public:
|
||||
virtual ~EventListener() {};
|
||||
virtual void HandleEvent(const EventType & ev) = 0;
|
||||
};
|
||||
|
||||
class EventCore
|
||||
{
|
||||
public:
|
||||
void QueueEvent(const EventType & ev);
|
||||
void SetListener(EventListener * l);
|
||||
|
||||
private:
|
||||
EventListener * m_listener = nullptr;
|
||||
};
|
||||
|
||||
extern EventCore core;
|
||||
}
|
||||
}
|
||||
|
||||
void EmitEvent(const EventType & ev);
|
||||
|
||||
#endif
|
@ -547,7 +547,6 @@ namespace i2p
|
||||
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
|
||||
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
|
||||
LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
|
||||
|
||||
uint8_t * buf = msg + I2NP_HEADER_SIZE;
|
||||
int size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
|
||||
switch (typeID)
|
||||
|
2
Log.h
2
Log.h
@ -158,7 +158,7 @@ namespace log {
|
||||
|
||||
Log & Logger();
|
||||
} // log
|
||||
} // i2p
|
||||
}
|
||||
|
||||
/** internal usage only -- folding args array to single string */
|
||||
template<typename TValue>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Transports.h"
|
||||
#include "NetDb.h"
|
||||
#include "NTCPSession.h"
|
||||
#include "Event.h"
|
||||
|
||||
using namespace i2p::crypto;
|
||||
|
||||
@ -604,7 +605,10 @@ namespace transport
|
||||
if (!memcmp (m_NextMessage->buf + m_NextMessageOffset - 4, checksum, 4))
|
||||
{
|
||||
if (!m_NextMessage->IsExpired ())
|
||||
{
|
||||
EmitEvent({{"type", "transport.recvmsg"} , {"ident", GetIdentHashBase64()}, {"number", "1"}});
|
||||
m_Handler.PutNextMessage (m_NextMessage);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogInfo, "NTCP: message expired");
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "NetDb.h"
|
||||
#include "SSU.h"
|
||||
#include "SSUData.h"
|
||||
#include "Event.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -233,9 +234,16 @@ namespace transport
|
||||
if (!m_ReceivedMessages.count (msgID))
|
||||
{
|
||||
m_ReceivedMessages.insert (msgID);
|
||||
<<<<<<< HEAD
|
||||
m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (!msg->IsExpired ())
|
||||
=======
|
||||
m_LastMessageReceivedTime = i2p::util::GetSinceEpoch<Time> ();
|
||||
if (!msg->IsExpired ()) {
|
||||
EmitEvent({{"type", "transport.recvmsg"} , {"ident", m_Session.GetIdentHashBase64()}, {"number", "1"}});
|
||||
>>>>>>> bda4170... add web socket ui
|
||||
m_Handler.PutNextMessage (msg);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogDebug, "SSU: message expired");
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ namespace transport
|
||||
virtual ~TransportSession () {};
|
||||
virtual void Done () = 0;
|
||||
|
||||
std::string GetIdentHashBase64() const { return m_RemoteIdentity->GetIdentHash().ToBase64(); }
|
||||
|
||||
std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity () { return m_RemoteIdentity; };
|
||||
void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident) { m_RemoteIdentity = ident; };
|
||||
|
||||
|
@ -4,7 +4,11 @@
|
||||
#include "I2NPProtocol.h"
|
||||
#include "NetDb.h"
|
||||
#include "Transports.h"
|
||||
<<<<<<< HEAD
|
||||
#include "Config.h"
|
||||
=======
|
||||
#include "Event.h"
|
||||
>>>>>>> bda4170... add web socket ui
|
||||
|
||||
using namespace i2p::data;
|
||||
|
||||
@ -230,6 +234,8 @@ namespace transport
|
||||
|
||||
void Transports::SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs)
|
||||
{
|
||||
|
||||
EmitEvent({{"type" , "transport.sendmsg"}, {"ident", ident.ToBase64()}, {"number", std::to_string(msgs.size())}});
|
||||
m_Service.post (std::bind (&Transports::PostMessages, this, ident, msgs));
|
||||
}
|
||||
|
||||
@ -569,6 +575,8 @@ namespace transport
|
||||
auto it = m_Peers.find (ident);
|
||||
if (it != m_Peers.end ())
|
||||
{
|
||||
EmitEvent({{"type" , "transport.connected"}, {"ident", ident.ToBase64()}, {"inbound", "false"}});
|
||||
|
||||
bool sendDatabaseStore = true;
|
||||
if (it->second.delayedMessages.size () > 0)
|
||||
{
|
||||
@ -588,12 +596,16 @@ namespace transport
|
||||
}
|
||||
else // incoming connection
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
if(RoutesRestricted() && ! IsRestrictedPeer(ident)) {
|
||||
// not trusted
|
||||
LogPrint(eLogWarning, "Transports: closing untrusted inbound connection from ", ident.ToBase64());
|
||||
session->Done();
|
||||
return;
|
||||
}
|
||||
=======
|
||||
EmitEvent({{"type" , "transport.connected"}, {"ident", ident.ToBase64()}, {"inbound", "true"}});
|
||||
>>>>>>> bda4170... add web socket ui
|
||||
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 (), {} }));
|
||||
@ -608,6 +620,7 @@ namespace transport
|
||||
auto remoteIdentity = session->GetRemoteIdentity ();
|
||||
if (!remoteIdentity) return;
|
||||
auto ident = remoteIdentity->GetIdentHash ();
|
||||
EmitEvent({{"type" , "transport.disconnected"}, {"ident", ident.ToBase64()}});
|
||||
auto it = m_Peers.find (ident);
|
||||
if (it != m_Peers.end ())
|
||||
{
|
||||
|
136
Websocket.cpp
Normal file
136
Websocket.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
#include "Websocket.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#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_thread(nullptr)
|
||||
{
|
||||
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_thread = new std::thread([&] () {
|
||||
while(m_run) {
|
||||
try {
|
||||
m_server.run();
|
||||
} catch (std::exception & e ) {
|
||||
LogPrint(eLogError, "Websocket server: ", e.what());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Stop() {
|
||||
m_run = false;
|
||||
if(m_thread) {
|
||||
m_thread->join();
|
||||
delete m_thread;
|
||||
}
|
||||
m_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 HandleEvent(const EventType & ev)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_connsMutex);
|
||||
LogPrint(eLogDebug, "websocket event");
|
||||
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_thread;
|
||||
std::mutex m_connsMutex;
|
||||
ConnList m_conns;
|
||||
ServerImpl m_server;
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
30
Websocket.h
Normal file
30
Websocket.h
Normal file
@ -0,0 +1,30 @@
|
||||
#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
|
@ -18,7 +18,12 @@ option(WITH_GUI "Include GUI (currently MS Windows only)" ON)
|
||||
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)
|
||||
<<<<<<< HEAD
|
||||
option(WITH_I2LUA "Build for i2lua" OFF)
|
||||
=======
|
||||
option(WITH_WEBSOCKETS "Build with websocket ui" OFF)
|
||||
|
||||
>>>>>>> bda4170... add web socket ui
|
||||
|
||||
# paths
|
||||
set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" )
|
||||
@ -61,6 +66,14 @@ set (LIBI2PD_SRC
|
||||
"${CMAKE_SOURCE_DIR}/api.cpp"
|
||||
)
|
||||
|
||||
if (WITH_WEBSOCKETS)
|
||||
add_definitions(-DWITH_EVENTS)
|
||||
find_package(websocketpp REQUIRED)
|
||||
endif ()
|
||||
if (WITH_WEBSOCKETS)
|
||||
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/Event.cpp")
|
||||
endif ()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS)
|
||||
list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp")
|
||||
endif ()
|
||||
@ -92,6 +105,9 @@ set (CLIENT_SRC
|
||||
"${CMAKE_SOURCE_DIR}/I2CP.cpp"
|
||||
)
|
||||
|
||||
if(WITH_WEBSOCKETS)
|
||||
list (APPEND CLIENT_SRC "${CMAKE_SOURCE_DIR}/Websocket.cpp")
|
||||
endif ()
|
||||
add_library(i2pdclient ${CLIENT_SRC})
|
||||
|
||||
set (DAEMON_SRC
|
||||
@ -366,7 +382,11 @@ message(STATUS " PCH : ${WITH_PCH}")
|
||||
message(STATUS " MESHNET : ${WITH_MESHNET}")
|
||||
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
||||
message(STATUS " THEADSANITIZER : ${WITH_THREADSANITIZER}")
|
||||
<<<<<<< HEAD
|
||||
message(STATUS " I2LUA : ${WITH_I2LUA}")
|
||||
=======
|
||||
message(STATUS " WEBSOCKETS : ${WITH_WEBSOCKETS}")
|
||||
>>>>>>> bda4170... add web socket ui
|
||||
message(STATUS "---------------------------------------")
|
||||
|
||||
#Handle paths nicely
|
||||
|
Loading…
Reference in New Issue
Block a user