Skip to content

Commit

Permalink
ipc: Use AF_INET to accept remote connections
Browse files Browse the repository at this point in the history
Locally, this should change nothing, with the corresponding pywayfire patch.
Remotely, you can set WAYFIRE_IPC_IP nd WAYFIRE_IPC_PORT to connect with
a pywayfire script.
  • Loading branch information
soreau committed Aug 29, 2024
1 parent c0621a3 commit 1f33ed9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 20 deletions.
5 changes: 5 additions & 0 deletions metadata/ipc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@
<_short>IPC protocol</_short>
<_long>Allow external programs to interact with Wayfire plugins.</_long>
<category>Utility</category>
<option name="port" type="int">
<_short>Starting port</_short>
<_long>Sets the port number that the first instance of wayfire will use for IPC. Each subsequent instance will increment the port number by one.</_long>
<default>7777</default>
</option>
</plugin>
</wayfire>
42 changes: 25 additions & 17 deletions plugins/ipc/ipc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
#include <wayfire/util/log.hpp>
#include <wayfire/core.hpp>
#include <wayfire/plugin.hpp>
#include <wayfire/option-wrapper.hpp>

#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <arpa/inet.h>

/**
* Handle WL_EVENT_READABLE on the socket.
Expand All @@ -28,9 +30,9 @@ wf::ipc::server_t::server_t()
};
}

void wf::ipc::server_t::init(std::string socket_path)
void wf::ipc::server_t::init(int port)
{
this->fd = setup_socket(socket_path.c_str());
this->fd = setup_socket(port);
if (fd == -1)
{
LOGE("Failed to create debug IPC socket!");
Expand All @@ -47,14 +49,13 @@ wf::ipc::server_t::~server_t()
if (fd != -1)
{
close(fd);
unlink(saddr.sun_path);
wl_event_source_remove(source);
}
}

int wf::ipc::server_t::setup_socket(const char *address)
int wf::ipc::server_t::setup_socket(int port)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
{
return -1;
Expand All @@ -70,17 +71,14 @@ int wf::ipc::server_t::setup_socket(const char *address)
return -1;
}

// Ensure no old instance left after a crash or similar
unlink(address);

saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, address, sizeof(saddr.sun_path) - 1);
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons(port);

int r = bind(fd, (sockaddr*)&saddr, sizeof(saddr));
if (r != 0)
{
LOGE("Failed to bind debug IPC socket at address ", address, " !");
// TODO: shutdown socket?
LOGE("Failed to bind IPC socket to localhost!");
return -1;
}

Expand Down Expand Up @@ -318,15 +316,25 @@ class ipc_plugin_t : public wf::plugin_interface_t
{
private:
shared_data::ref_ptr_t<ipc::server_t> server;
wf::option_wrapper_t<int> starting_port{"ipc/port"};

public:
void init() override
{
char *pre_socket = getenv("_WAYFIRE_SOCKET");
const auto& dname = wf::get_core().wayland_display;
std::string socket = pre_socket ?: "/tmp/wayfire-" + dname + ".socket";
setenv("WAYFIRE_SOCKET", socket.c_str(), 1);
server->init(socket);
char *pre_port = getenv("WAYFIRE_IPC_PORT");
int port;
if (pre_port)
{
port = atoi(pre_port);
port++;
} else
{
port = int(starting_port);
}

std::string socket = std::to_string(port);
setenv("WAYFIRE_IPC_PORT", socket.c_str(), 1);
server->init(port);
}

bool is_unloadable() override
Expand Down
7 changes: 4 additions & 3 deletions plugins/ipc/ipc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <wayland-server.h>
#include <wayfire/plugins/common/shared-core-data.hpp>
#include "ipc-method-repository.hpp"
#include <netinet/in.h>

namespace wf
{
Expand Down Expand Up @@ -44,7 +45,7 @@ class server_t
{
public:
server_t();
void init(std::string socket_path);
void init(int port);
~server_t();

private:
Expand All @@ -60,8 +61,8 @@ class server_t
/**
* Setup a socket at the given address, and set it as CLOEXEC and non-blocking.
*/
int setup_socket(const char *address);
sockaddr_un saddr;
int setup_socket(int port);
sockaddr_in saddr;
wl_event_source *source;
std::vector<std::unique_ptr<client_t>> clients;

Expand Down

0 comments on commit 1f33ed9

Please sign in to comment.