diff --git a/src/common/api/LowLevelAPISession.h b/src/common/api/LowLevelAPISession.h
new file mode 100644
index 0000000..6d8e8b4
--- /dev/null
+++ b/src/common/api/LowLevelAPISession.h
@@ -0,0 +1,37 @@
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef APIPROCESSOR_H_
+#define APIPROCESSOR_H_
+
+#include "APIMessage.pb.h"
+
+namespace p2pnet {
+namespace api {
+
+/**
+ * APIProcessor is an interface that is used to have just `process(APIMessage message)` fuinction.
+ * Its meaning is 'something that could process API requests'.
+ */
+class LowLevelAPISession {
+public:
+ virtual ~LowLevelAPISession(){};
+
+ virtual void process(APIMessage message) = 0;
+ virtual void shutdown() = 0; // This signal is generated if remote endpoint is disconnected.
+};
+
+} /* namespace api */
+} /* namespace p2pnet */
+
+#endif /* APIPROCESSOR_H_ */
diff --git a/src/common/api/UnixAPISocket.cpp b/src/common/api/UnixAPISocket.cpp
new file mode 100644
index 0000000..e73e2db
--- /dev/null
+++ b/src/common/api/UnixAPISocket.cpp
@@ -0,0 +1,89 @@
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include "UnixAPISocket.h"
+#include "../Config.h"
+
+namespace p2pnet {
+namespace api {
+namespace unix {
+
+std::string getSocketPath() {
+ return ConfigManager::getInstance()->getValue("api.unix.system_sock");
+}
+
+std::string getFallbackSocketPath() {
+ return ConfigManager::getInstance()->getDirectory()+"unix_api.sock";
+}
+
+/* UnixSocket */
+UnixAPISocket::UnixAPISocket(boost::asio::io_service& io_service, LowLevelAPISession* session) : session_socket(io_service) {
+ session_ptr = session;
+}
+UnixAPISocket::~UnixAPISocket() {}
+
+stream_protocol::socket& UnixAPISocket::getSocket() {
+ return session_socket;
+}
+
+void UnixAPISocket::startReceive() {
+ char* buffer = new char[MESSAGE_SIZE_LENGTH];
+ boost::asio::async_read(session_socket, boost::asio::buffer(buffer, MESSAGE_SIZE_LENGTH),
+ std::bind(&UnixAPISocket::handleReceiveSize, this, std::placeholders::_1, buffer));
+}
+
+void UnixAPISocket::handleReceiveSize(const boost::system::error_code& error, char* char_message_size) {
+ if(error){
+ session_ptr->shutdown();
+ return;
+ }
+ MESSAGE_SIZE_TYPE size = ntohl(*reinterpret_cast(char_message_size));
+ delete[] char_message_size;
+
+ char* buffer = new char[size];
+ boost::asio::async_read(session_socket, boost::asio::buffer(buffer, size),
+ std::bind(&UnixAPISocket::handleReceive, this, std::placeholders::_1, buffer, std::placeholders::_2));
+}
+
+void UnixAPISocket::handleReceive(const boost::system::error_code& error, char* message, uint32_t size) {
+ if(error){
+ session_ptr->shutdown();
+ return;
+ }
+ APIMessage message_proto;
+ message_proto.ParseFromArray(message, size);
+ delete[] message;
+ session_ptr->process(message_proto);
+ startReceive();
+}
+
+void UnixAPISocket::send(APIMessage message) {
+ auto native_size = message.ByteSize();
+ MESSAGE_SIZE_TYPE size_netlong = htonl(native_size);
+
+ std::cout << size_netlong;
+
+ auto charlen_s = std::string(reinterpret_cast(&size_netlong), MESSAGE_SIZE_LENGTH);
+ boost::asio::async_write(session_socket, boost::asio::buffer(charlen_s+message.SerializeAsString()),
+ std::bind(&UnixAPISocket::handleSend, this, std::placeholders::_1));
+}
+
+void UnixAPISocket::handleSend(const boost::system::error_code& error) {
+ if(error){
+ session_ptr->shutdown();
+ }
+}
+
+} /* namespace unix */
+} /* namespace api */
+} /* namespace p2pnet */
diff --git a/src/common/api/UnixAPISocket.h b/src/common/api/UnixAPISocket.h
new file mode 100644
index 0000000..013faf9
--- /dev/null
+++ b/src/common/api/UnixAPISocket.h
@@ -0,0 +1,55 @@
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef UNIXAPISOCKET_H_
+#define UNIXAPISOCKET_H_
+
+#include
+#include "LowLevelAPISession.h"
+
+#define MESSAGE_SIZE_TYPE uint32_t
+#define MESSAGE_SIZE_LENGTH sizeof(MESSAGE_SIZE_TYPE)
+
+using boost::asio::local::stream_protocol;
+
+namespace p2pnet {
+namespace api {
+namespace unix {
+
+std::string getSocketPath();
+std::string getFallbackSocketPath();
+
+class UnixAPISocket {
+ stream_protocol::socket session_socket;
+ LowLevelAPISession* session_ptr;
+
+public:
+ UnixAPISocket(boost::asio::io_service& io_service, LowLevelAPISession* session);
+ virtual ~UnixAPISocket();
+
+ stream_protocol::socket& getSocket();
+
+ void startReceive();
+ void handleReceiveSize(const boost::system::error_code& error, char* char_message_size);
+ void handleReceive(const boost::system::error_code& error, char* message, uint32_t size);
+
+ void handleSend(const boost::system::error_code& error);
+
+ void send(APIMessage message);
+};
+
+} /* namespace unix */
+} /* namespace api */
+} /* namespace p2pnet */
+
+#endif /* UNIXAPISOCKET_H_ */
diff --git a/src/daemon/Daemon.cpp b/src/daemon/Daemon.cpp
index 1d756cf..bab38aa 100644
--- a/src/daemon/Daemon.cpp
+++ b/src/daemon/Daemon.cpp
@@ -42,7 +42,7 @@ int Daemon::run() {
void Daemon::initAPI() {
if(config_manager->getValue("api.unix.enabled")){
try {
- api_unix = std::unique_ptr(new api::UnixAPIServer(AsioIOService::getIOService()));
+ api_unix = std::make_shared(AsioIOService::getIOService());
} catch (boost::system::system_error& e) {
log() << "Unable to initialize Unix Socket API. Exception caught: " << e.what() << std::endl;
}
diff --git a/src/daemon/Daemon.h b/src/daemon/Daemon.h
index 354d801..5c6b198 100644
--- a/src/daemon/Daemon.h
+++ b/src/daemon/Daemon.h
@@ -48,7 +48,7 @@ class Daemon : public Loggable {
std::unique_ptr discovery_udpv4;
std::unique_ptr discovery_udpv6;
- std::unique_ptr api_unix;
+ std::shared_ptr api_unix;
Daemon();
virtual ~Daemon();
diff --git a/src/daemon/api/APISession.cpp b/src/daemon/api/APISession.cpp
index 708e0e5..21165d0 100644
--- a/src/daemon/api/APISession.cpp
+++ b/src/daemon/api/APISession.cpp
@@ -19,22 +19,21 @@ namespace p2pnet {
namespace api {
APISession::APISession() {
- log() << "New API session started.";
+ log() << "New API session started" << std::endl;
+}
+APISession::~APISession() {
+ log() << "API session shut down" << std::endl;
}
-APISession::~APISession() {}
-
-void APISession::process(std::string message) {
- APIMessage message_received;
- message_received.ParseFromString(message);
- switch(message_received.type()){
+void APISession::process(APIMessage message) {
+ switch(message.type()){
case APIMessage::GENERATE_PRIVATE_KEY:
auto privkey = crypto::PrivateKeyDSA::generateNewKey();
APIMessage message_reply;
message_reply.set_type(APIMessage::GENERATE_PRIVATE_KEY_CALLBACK);
message_reply.set_privkey_cert(privkey.toPEM());
- send(message_reply.SerializeAsString());
+ send(message_reply);
}
}
diff --git a/src/daemon/api/APISession.h b/src/daemon/api/APISession.h
index 9361cce..6f8651b 100644
--- a/src/daemon/api/APISession.h
+++ b/src/daemon/api/APISession.h
@@ -15,18 +15,21 @@
#define APISESSION_H_
#include "../endpoint/LocalEndpoint.h"
+#include "../../common/api/LowLevelAPISession.h"
namespace p2pnet {
namespace api {
-class APISession : Loggable {
+class APISession : Loggable, public LowLevelAPISession {
std::map> endpoints;
public:
APISession();
virtual ~APISession();
- virtual void send(std::string message) = 0;
- void process(std::string message);
+ virtual void send(APIMessage message) = 0;
+ void process(APIMessage message);
+
+ std::string getComponentName(){return "APISession";}
};
} /* namespace api */
diff --git a/src/daemon/api/UnixAPIServer.cpp b/src/daemon/api/UnixAPIServer.cpp
index be82a6f..00da43f 100644
--- a/src/daemon/api/UnixAPIServer.cpp
+++ b/src/daemon/api/UnixAPIServer.cpp
@@ -13,63 +13,40 @@
*/
#include "UnixAPIServer.h"
#include
+#include
namespace p2pnet {
namespace api {
+namespace unix {
/* UnixAPISession */
-UnixAPISession::UnixAPISession(boost::asio::io_service& io_service) : session_socket(io_service) {
+UnixAPISession::UnixAPISession(boost::asio::io_service& io_service, UnixAPIServer* parent) : socket(io_service, this) {
+ parent_apiserver = parent;
}
UnixAPISession::~UnixAPISession() {
}
-stream_protocol::socket& UnixAPISession::getSocket() {
- return session_socket;
+void UnixAPISession::send(APIMessage message) {
+ socket.send(message);
}
-void UnixAPISession::startReceive() {
- char* buffer = new char[4];
- boost::asio::async_read(session_socket, boost::asio::buffer(buffer, 4),
- std::bind(&UnixAPISession::handleReceiveSize, this, buffer));
+void UnixAPISession::shutdown(){
+ parent_apiserver->unix_sessions.erase(shared_from_this());
}
-void UnixAPISession::handleReceiveSize(char* char_message_size) {
- MESSAGE_SIZE_TYPE size = ntohl(*reinterpret_cast(char_message_size));
- delete[] char_message_size;
-
- char* buffer = new char[size];
- boost::asio::async_read(session_socket, boost::asio::buffer(buffer, MESSAGE_SIZE_LENGTH),
- std::bind(&UnixAPISession::handleReceive, this, buffer, std::placeholders::_2));
-}
-
-void UnixAPISession::handleReceive(char* message, uint32_t size) {
- std::string message_s(message, size);
- delete[] message;
- process(message_s);
-}
-
-void UnixAPISession::send(std::string message) {
- MESSAGE_SIZE_TYPE size_netlong = htonl(message.length());
- auto charlen_s = std::string(reinterpret_cast(&size_netlong), MESSAGE_SIZE_LENGTH);
- boost::asio::async_write(session_socket, boost::asio::buffer(charlen_s+message),
- std::bind(&UnixAPISession::handleSend, this));
-}
-
-void UnixAPISession::handleSend() {}
-
/* UnixAPIServer */
UnixAPIServer::UnixAPIServer(boost::asio::io_service& io_service) :
asio_io_service(io_service) {
- socket_path = getSocketPath();
-
try {
- // Try default path (i.e. that, from config: api.unix.system_sock)
+ socket_path = getSocketPath(); // Try default path (i.e. that, from config: api.unix.system_sock)
+ std::remove(socket_path.c_str());
acceptor_ptr = std::unique_ptr(new stream_protocol::acceptor(asio_io_service, stream_protocol::endpoint(socket_path)));
} catch(boost::system::system_error& e){
socket_path = getFallbackSocketPath();
+ std::remove(socket_path.c_str());
acceptor_ptr = std::unique_ptr(new stream_protocol::acceptor(asio_io_service, stream_protocol::endpoint(socket_path)));
}
log() << "Unix API initialized at: " << socket_path << std::endl;
@@ -79,23 +56,16 @@ UnixAPIServer::UnixAPIServer(boost::asio::io_service& io_service) :
UnixAPIServer::~UnixAPIServer() {}
void UnixAPIServer::accept() {
- auto new_session = std::make_shared(asio_io_service);
+ auto new_session = std::make_shared(asio_io_service, this);
unix_sessions.insert(new_session);
- acceptor_ptr->async_accept(new_session->getSocket(), std::bind(&UnixAPISession::startReceive, new_session));
+ acceptor_ptr->async_accept(new_session->getUnixSocket().getSocket(), std::bind(&UnixAPIServer::handleAccept, this, new_session));
}
void UnixAPIServer::handleAccept(std::shared_ptr new_session) {
- new_session->startReceive();
+ new_session->getUnixSocket().startReceive();
accept();
}
-std::string UnixAPIServer::getSocketPath() const {
- return getValue("api.unix.system_sock");
-}
-
-std::string UnixAPIServer::getFallbackSocketPath() const {
- return ConfigManager::getInstance()->getDirectory()+"unix_api.sock";
-}
-
+} /* namespace unix */
} /* namespace api */
} /* namespace p2pnet */
diff --git a/src/daemon/api/UnixAPIServer.h b/src/daemon/api/UnixAPIServer.h
index 47142ed..5ae7c1e 100644
--- a/src/daemon/api/UnixAPIServer.h
+++ b/src/daemon/api/UnixAPIServer.h
@@ -18,6 +18,10 @@
#include "APIServer.h"
#include "../../common/Config.h"
+#include "../../common/api/UnixAPISocket.h"
+
+#include "../../library/export.h"
+
#include
#include
@@ -28,25 +32,31 @@ using boost::asio::local::stream_protocol;
namespace p2pnet {
namespace api {
+namespace unix {
-class UnixAPISession : public APISession {
- stream_protocol::socket session_socket;
+class UnixAPIServer;
+class UnixAPISession : public APISession, public std::enable_shared_from_this {
+ UnixAPISocket socket;
+ UnixAPIServer* parent_apiserver;
public:
- UnixAPISession(boost::asio::io_service& io_service);
+ UnixAPISession(boost::asio::io_service& io_service, UnixAPIServer* parent);
virtual ~UnixAPISession();
- stream_protocol::socket& getSocket();
+ void send(APIMessage message);
+ //void process(APIMessage message); <--- Inherited from APISession.
+
+ void shutdown(); // Careful! Acts like `delete this;`
- void startReceive();
- void handleReceiveSize(char* char_message_size);
- void handleReceive(char* message, uint32_t size);
+ UnixAPISocket& getUnixSocket(){return socket;}
- void send(std::string message);
- void handleSend();
+ std::string getComponentName() const {
+ return "UnixAPISession";
+ }
};
class UnixAPIServer : public APIServer, ConfigClient, Loggable {
+ friend class UnixAPISession;
std::set> unix_sessions;
std::unique_ptr acceptor_ptr;
@@ -66,10 +76,12 @@ class UnixAPIServer : public APIServer, ConfigClient, Loggable {
void accept();
void handleAccept(std::shared_ptr new_session);
- std::string getSocketPath() const;
- std::string getFallbackSocketPath() const;
+ std::string getComponentName() {
+ return "UnixAPIServer";
+ }
};
+} /* namespace unix */
} /* namespace api */
} /* namespace p2pnet */
diff --git a/src/library/UnixAPI.cpp b/src/library/UnixAPI.cpp
new file mode 100644
index 0000000..39bcf61
--- /dev/null
+++ b/src/library/UnixAPI.cpp
@@ -0,0 +1,43 @@
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include "UnixAPI.h"
+#include "../common/api/APIMessage.pb.h"
+#include "export.h"
+
+namespace p2pnet {
+namespace api {
+
+UnixAPI::UnixAPI(boost::asio::io_service& io_service) : UnixAPISocket(io_service, this) {}
+
+UnixAPI::~UnixAPI() {}
+
+void UnixAPI::process(APIMessage message) {}
+
+void UnixAPI::connect() {
+ try {
+ socket_path = unix::getSocketPath();
+ getSocket().connect(stream_protocol::endpoint(socket_path));
+ } catch (boost::system::system_error& e) {
+ socket_path = unix::getFallbackSocketPath();
+ getSocket().connect(stream_protocol::endpoint(socket_path));
+ } // TODO: Yep, uncatched for now.
+ log() << "Connected to daemon on: " << socket_path << std::endl;
+}
+
+void UnixAPI::shutdown(){
+ getSocket().shutdown(getSocket().shutdown_both);
+};
+
+} /* namespace api */
+} /* namespace p2pnet */
diff --git a/src/library/UnixAPI.h b/src/library/UnixAPI.h
new file mode 100644
index 0000000..9beed5f
--- /dev/null
+++ b/src/library/UnixAPI.h
@@ -0,0 +1,40 @@
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef UNIXAPI_H_
+#define UNIXAPI_H_
+
+#include "../common/Loggable.h"
+#include "../common/api/UnixAPISocket.h"
+#include "../common/api/LowLevelAPISession.h"
+
+namespace p2pnet {
+namespace api {
+
+class UnixAPI : public unix::UnixAPISocket, public LowLevelAPISession, Loggable {
+ std::string socket_path;
+public:
+ UnixAPI(boost::asio::io_service& io_service);
+ virtual ~UnixAPI();
+
+ void process(APIMessage message);
+
+ void shutdown();
+
+ void connect();
+};
+
+} /* namespace api */
+} /* namespace p2pnet */
+
+#endif /* UNIXAPI_H_ */