summaryrefslogtreecommitdiffstats
path: root/src/socket/ingen_socket_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/socket/ingen_socket_server.cpp')
-rw-r--r--src/socket/ingen_socket_server.cpp118
1 files changed, 110 insertions, 8 deletions
diff --git a/src/socket/ingen_socket_server.cpp b/src/socket/ingen_socket_server.cpp
index 37b05bae..0a9d7494 100644
--- a/src/socket/ingen_socket_server.cpp
+++ b/src/socket/ingen_socket_server.cpp
@@ -14,31 +14,133 @@
along with Ingen. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <errno.h>
+#include <poll.h>
+
+#include <sstream>
+#include <thread>
+
+#include "ingen/Configuration.hpp"
#include "ingen/Module.hpp"
#include "ingen/World.hpp"
#include "../server/Engine.hpp"
#include "../server/EventWriter.hpp"
-#include "SocketListener.hpp"
+#include "Socket.hpp"
+#include "SocketServer.hpp"
+
+#define UNIX_SCHEME "unix://"
+
+namespace Ingen {
+namespace Socket {
+
+static void
+ingen_listen(Ingen::World* world, Socket* unix_sock, Socket* net_sock)
+{
+ const std::string unix_path(world->conf().option("socket").ptr<char>());
+
+ SPtr<Server::Engine> engine = dynamic_ptr_cast<Server::Engine>(
+ world->engine());
+
+ // Bind UNIX socket
+ const Raul::URI unix_uri(UNIX_SCHEME + unix_path);
+ if (!unix_sock->bind(unix_uri) || !unix_sock->listen()) {
+ world->log().error("Failed to create UNIX socket\n");
+ unix_sock->close();
+ }
+ world->log().info(Raul::fmt("Listening on socket %1%\n") % unix_uri);
-using namespace Ingen;
+ // Bind TCP socket
+ const int port = world->conf().option("engine-port").get<int32_t>();
+ std::ostringstream ss;
+ ss << "tcp://localhost:";
+ ss << port;
+ if (!net_sock->bind(Raul::URI(ss.str())) || !net_sock->listen()) {
+ world->log().error("Failed to create TCP socket\n");
+ net_sock->close();
+ }
+ world->log().info(Raul::fmt("Listening on TCP port %1%\n") % port);
-struct IngenSocketServerModule : public Ingen::Module {
- void load(Ingen::World* world) {
- listener = SPtr<Ingen::Socket::SocketListener>(
- new Ingen::Socket::SocketListener(*world));
+ struct pollfd pfds[2];
+ int nfds = 0;
+ if (unix_sock->fd() != -1) {
+ pfds[nfds].fd = unix_sock->fd();
+ pfds[nfds].events = POLLIN;
+ pfds[nfds].revents = 0;
+ ++nfds;
+ }
+ if (net_sock->fd() != -1) {
+ pfds[nfds].fd = net_sock->fd();
+ pfds[nfds].events = POLLIN;
+ pfds[nfds].revents = 0;
+ ++nfds;
}
- SPtr<Ingen::Socket::SocketListener> listener;
+ while (true) {
+ // Wait for input to arrive at a socket
+ const int ret = poll(pfds, nfds, -1);
+ if (ret == -1) {
+ world->log().error(Raul::fmt("Poll error: %1%\n") % strerror(errno));
+ break;
+ } else if ((pfds[0].revents & POLLHUP) || pfds[1].revents & POLLHUP) {
+ break;
+ } else if (ret == 0) {
+ world->log().error("Poll returned with no data\n");
+ continue;
+ }
+
+ if (pfds[0].revents & POLLIN) {
+ SPtr<Socket> conn = unix_sock->accept();
+ if (conn) {
+ new SocketServer(*world, *engine, conn);
+ }
+ }
+
+ if (pfds[1].revents & POLLIN) {
+ SPtr<Socket> conn = net_sock->accept();
+ if (conn) {
+ new SocketServer(*world, *engine, conn);
+ }
+ }
+ }
+}
+
+struct ServerModule : public Ingen::Module
+{
+ ServerModule()
+ : unix_sock(Socket::Type::UNIX)
+ , net_sock(Socket::Type::TCP)
+ {}
+
+ ~ServerModule() {
+ unix_sock.shutdown();
+ net_sock.shutdown();
+ thread->join();
+ unlink(unix_sock.uri().substr(strlen(UNIX_SCHEME)).c_str());
+ }
+
+ void load(World* world) {
+ world = world;
+ thread = std::unique_ptr<std::thread>(
+ new std::thread(ingen_listen, world, &unix_sock, &net_sock));
+ }
+
+ World* world;
+ Socket unix_sock;
+ Socket net_sock;
+ std::unique_ptr<std::thread> thread;
};
+} // namespace Socket
+} // namespace Ingen
+
extern "C" {
Ingen::Module*
ingen_module_load()
{
- return new IngenSocketServerModule();
+ return new Ingen::Socket::ServerModule();
}
} // extern "C"