summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-03-13 19:59:39 +0100
committerMaxime Coste <frrrwww@gmail.com>2013-03-14 10:23:35 +0100
commit0b45a725e4aa5129339f225ed75fbff1a04dbf09 (patch)
tree76c337816bf1f7a904633001abbb5eabe3c3a8f5 /src
parentb309d1df61cbcdbd5c409836a524b22434d295e1 (diff)
move remoting code to remote.cc
ClientAccepter is now Server's implementation detail and all socket logic are isolated in remote.cc
Diffstat (limited to 'src')
-rw-r--r--src/main.cc75
-rw-r--r--src/remote.cc135
-rw-r--r--src/remote.hh35
3 files changed, 123 insertions, 122 deletions
diff --git a/src/main.cc b/src/main.cc
index daac24b5..a4f21e33 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -27,14 +27,8 @@
#endif
#include <unordered_map>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-
#include <locale>
+#include <signal.h>
using namespace Kakoune;
using namespace std::placeholders;
@@ -686,50 +680,6 @@ std::unordered_map<Key, std::function<void (Context& context)>> keymap =
void run_unit_tests();
-struct Server : public Singleton<Server>
-{
- Server()
- {
- m_filename = "/tmp/kak-" + int_to_str(getpid());
-
- int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
- fcntl(listen_sock, F_SETFD, FD_CLOEXEC);
- sockaddr_un addr;
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, m_filename.c_str(), sizeof(addr.sun_path) - 1);
-
- if (bind(listen_sock, (sockaddr*) &addr, sizeof(sockaddr_un)) == -1)
- throw runtime_error("unable to bind listen socket " + m_filename);
-
- if (listen(listen_sock, 4) == -1)
- throw runtime_error("unable to listen on socket " + m_filename);
-
- auto accepter = [](FDWatcher& watcher) {
- sockaddr_un client_addr;
- socklen_t client_addr_len = sizeof(sockaddr_un);
- int sock = accept(watcher.fd(), (sockaddr*) &client_addr, &client_addr_len);
- if (sock == -1)
- throw runtime_error("accept failed");
- fcntl(sock, F_SETFD, FD_CLOEXEC);
-
- new ClientAccepter{sock};
- };
- m_listener.reset(new FDWatcher{listen_sock, accepter});
- }
-
- ~Server()
- {
- unlink(m_filename.c_str());
- close(m_listener->fd());
- }
-
- const String& filename() const { return m_filename; }
-
-private:
- String m_filename;
- std::unique_ptr<FDWatcher> m_listener;
-};
-
void register_env_vars()
{
ShellManager& shell_manager = ShellManager::instance();
@@ -804,24 +754,6 @@ void create_local_client(const String& init_command)
std::unique_ptr<UserInterface>{ui}, init_command);
}
-RemoteClient* connect_to(const String& pid, const String& init_command)
-{
- auto filename = "/tmp/kak-" + pid;
-
- int sock = socket(AF_UNIX, SOCK_STREAM, 0);
- fcntl(sock, F_SETFD, FD_CLOEXEC);
- sockaddr_un addr;
- addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, filename.c_str(), sizeof(addr.sun_path) - 1);
- if (connect(sock, (sockaddr*)&addr, sizeof(addr.sun_path)) == -1)
- throw runtime_error("connect to " + filename + " failed");
-
- NCursesUI* ui = new NCursesUI{};
- RemoteClient* remote_client = new RemoteClient{sock, ui, init_command};
-
- return remote_client;
-}
-
void signal_handler(int signal)
{
endwin();
@@ -862,8 +794,9 @@ int main(int argc, char* argv[])
{
try
{
- std::unique_ptr<RemoteClient> client(
- connect_to(parser.option_value("c"), init_command));
+ auto client = connect_to(parser.option_value("c"),
+ std::unique_ptr<UserInterface>{new NCursesUI{}},
+ init_command);
while (true)
event_manager.handle_next_events();
}
diff --git a/src/remote.cc b/src/remote.cc
index 0b50b670..d8e7949a 100644
--- a/src/remote.cc
+++ b/src/remote.cc
@@ -9,6 +9,11 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
namespace Kakoune
{
@@ -303,9 +308,9 @@ void RemoteUI::set_input_callback(InputCallback callback)
m_input_callback = std::move(callback);
}
-RemoteClient::RemoteClient(int socket, UserInterface* ui,
+RemoteClient::RemoteClient(int socket, std::unique_ptr<UserInterface>&& ui,
const String& init_command)
- : m_ui(ui), m_dimensions(ui->dimensions()),
+ : m_ui(std::move(ui)), m_dimensions(m_ui->dimensions()),
m_socket_watcher{socket, [this](FDWatcher&){ process_next_message(); }}
{
Message msg(socket);
@@ -380,46 +385,112 @@ void RemoteClient::write_next_key()
}
}
-ClientAccepter::ClientAccepter(int socket)
- : m_socket_watcher(socket, [this](FDWatcher&) { handle_available_input(); }) {}
+std::unique_ptr<RemoteClient> connect_to(const String& pid, std::unique_ptr<UserInterface>&& ui,
+ const String& init_command)
+{
+ auto filename = "/tmp/kak-" + pid;
+
+ int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ fcntl(sock, F_SETFD, FD_CLOEXEC);
+ sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, filename.c_str(), sizeof(addr.sun_path) - 1);
+ if (connect(sock, (sockaddr*)&addr, sizeof(addr.sun_path)) == -1)
+ throw runtime_error("connect to " + filename + " failed");
+
+ return std::unique_ptr<RemoteClient>{new RemoteClient{sock, std::move(ui), init_command}};
+}
+
-void ClientAccepter::handle_available_input()
+// A client accepter handle a connection until it closes or a nul byte is
+// recieved. Everything recieved before is considered to be a command.
+//
+// * When a nul byte is recieved, the socket is handed to a new Client along
+// with the command.
+// * When the connection is closed, the command is run in an empty context.
+class ClientAccepter
{
- int socket = m_socket_watcher.fd();
- timeval tv{ 0, 0 };
- fd_set rfds;
- do
+public:
+ ClientAccepter(int socket)
+ : m_socket_watcher(socket, [this](FDWatcher&) { handle_available_input(); }) {}
+
+private:
+ void handle_available_input()
{
- char c;
- int res = ::read(socket, &c, 1);
- if (res <= 0)
+ int socket = m_socket_watcher.fd();
+ timeval tv{ 0, 0 };
+ fd_set rfds;
+ do
{
- if (not m_buffer.empty()) try
+ char c;
+ int res = ::read(socket, &c, 1);
+ if (res <= 0)
{
- Context context{};
- CommandManager::instance().execute(m_buffer, context);
+ if (not m_buffer.empty()) try
+ {
+ Context context{};
+ CommandManager::instance().execute(m_buffer, context);
+ }
+ catch (runtime_error& e)
+ {
+ write_debug("error running command '" + m_buffer + "' : " + e.description());
+ }
+ delete this;
+ return;
}
- catch (runtime_error& e)
+ if (c == 0) // end of initial command stream, go to interactive ui mode
{
- write_debug("error running command '" + m_buffer + "' : " + e.description());
+ ClientManager::instance().create_client(
+ std::unique_ptr<UserInterface>{new RemoteUI{socket}}, m_buffer);
+ delete this;
+ return;
}
- delete this;
- return;
- }
- if (c == 0) // end of initial command stream, go to interactive ui mode
- {
- ClientManager::instance().create_client(
- std::unique_ptr<UserInterface>{new RemoteUI{socket}}, m_buffer);
- delete this;
- return;
- }
- else
- m_buffer += c;
+ else
+ m_buffer += c;
- FD_ZERO(&rfds);
- FD_SET(socket, &rfds);
+ FD_ZERO(&rfds);
+ FD_SET(socket, &rfds);
+ }
+ while (select(socket+1, &rfds, NULL, NULL, &tv) == 1);
}
- while (select(socket+1, &rfds, NULL, NULL, &tv) == 1);
+
+ String m_buffer;
+ FDWatcher m_socket_watcher;
+};
+
+Server::Server()
+{
+ m_filename = "/tmp/kak-" + int_to_str(getpid());
+
+ int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ fcntl(listen_sock, F_SETFD, FD_CLOEXEC);
+ sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, m_filename.c_str(), sizeof(addr.sun_path) - 1);
+
+ if (bind(listen_sock, (sockaddr*) &addr, sizeof(sockaddr_un)) == -1)
+ throw runtime_error("unable to bind listen socket " + m_filename);
+
+ if (listen(listen_sock, 4) == -1)
+ throw runtime_error("unable to listen on socket " + m_filename);
+
+ auto accepter = [](FDWatcher& watcher) {
+ sockaddr_un client_addr;
+ socklen_t client_addr_len = sizeof(sockaddr_un);
+ int sock = accept(watcher.fd(), (sockaddr*) &client_addr, &client_addr_len);
+ if (sock == -1)
+ throw runtime_error("accept failed");
+ fcntl(sock, F_SETFD, FD_CLOEXEC);
+
+ new ClientAccepter{sock};
+ };
+ m_listener.reset(new FDWatcher{listen_sock, accepter});
+}
+
+Server::~Server()
+{
+ unlink(m_filename.c_str());
+ close(m_listener->fd());
}
}
diff --git a/src/remote.hh b/src/remote.hh
index b9b6e14c..b9576a6f 100644
--- a/src/remote.hh
+++ b/src/remote.hh
@@ -10,39 +10,36 @@ namespace Kakoune
struct peer_disconnected {};
-// A client accepter handle a connection until it closes or a nul byte is
-// recieved. Everything recieved before is considered to be a command.
-//
-// * When a nul byte is recieved, the socket is handed to a new Client along
-// with the command.
-// * When the connection is closed, the command is run in an empty context.
-class ClientAccepter
-{
-public:
- ClientAccepter(int socket);
-private:
- void handle_available_input();
-
- String m_buffer;
- FDWatcher m_socket_watcher;
-};
-
// A remote client handle communication between a client running on the server
// and a user interface running on the local process.
class RemoteClient
{
public:
- RemoteClient(int socket, UserInterface* ui,
+ RemoteClient(int socket, std::unique_ptr<UserInterface>&& ui,
const String& init_command);
+private:
void process_next_message();
void write_next_key();
-private:
std::unique_ptr<UserInterface> m_ui;
DisplayCoord m_dimensions;
FDWatcher m_socket_watcher;
};
+std::unique_ptr<RemoteClient> connect_to(const String& pid,
+ std::unique_ptr<UserInterface>&& ui,
+ const String& init_command);
+
+struct Server : public Singleton<Server>
+{
+ Server();
+ ~Server();
+ const String& filename() const { return m_filename; }
+
+private:
+ String m_filename;
+ std::unique_ptr<FDWatcher> m_listener;
+};
}