This commit is contained in:
Alex
2018-08-20 14:50:45 +02:00
committed by GitHub
parent b7e3d10fb7
commit 49232eed8d
30 changed files with 261 additions and 235 deletions

View File

@ -1,14 +1,17 @@
#define _POSIX_C_SOURCE 200809L
#include "modules/sway/ipc/client.hpp"
#include <cstdio>
#include <string>
#include <sys/socket.h>
#include <sys/un.h>
static const std::string ipc_magic("i3-ipc");
static const size_t ipc_header_size = ipc_magic.size() + 8;
waybar::modules::sway::Ipc::Ipc()
: fd_(-1), fd_event_(-1)
{}
std::string getSocketPath() {
waybar::modules::sway::Ipc::~Ipc()
{
close(fd_);
close(fd_event_);
}
const std::string waybar::modules::sway::Ipc::getSocketPath() const
{
const char *env = getenv("SWAYSOCK");
if (env != nullptr) {
return std::string(env);
@ -33,31 +36,41 @@ std::string getSocketPath() {
return str;
}
int ipcOpenSocket(const std::string &socketPath) {
int waybar::modules::sway::Ipc::open(const std::string& socketPath) const
{
struct sockaddr_un addr = {0};
int socketfd;
if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
int fd = -1;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
throw std::runtime_error("Unable to open Unix socket");
}
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
int l = sizeof(struct sockaddr_un);
if (connect(socketfd, reinterpret_cast<struct sockaddr *>(&addr), l) == -1) {
if (::connect(fd, reinterpret_cast<struct sockaddr *>(&addr), l) == -1) {
throw std::runtime_error("Unable to connect to " + socketPath);
}
return socketfd;
return fd;
}
struct ipc_response ipcRecvResponse(int socketfd) {
void waybar::modules::sway::Ipc::connect()
{
const std::string& socketPath = getSocketPath();
fd_ = open(socketPath);
fd_event_ = open(socketPath);
}
struct waybar::modules::sway::Ipc::ipc_response
waybar::modules::sway::Ipc::recv(int fd) const
{
std::string header;
header.reserve(ipc_header_size);
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic.size());
header.reserve(ipc_header_size_);
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic_.size());
size_t total = 0;
while (total < ipc_header_size) {
while (total < ipc_header_size_) {
ssize_t res =
::recv(socketfd, header.data() + total, ipc_header_size - total, 0);
::recv(fd, header.data() + total, ipc_header_size_ - total, 0);
if (res <= 0) {
throw std::runtime_error("Unable to receive IPC response");
}
@ -66,32 +79,56 @@ struct ipc_response ipcRecvResponse(int socketfd) {
total = 0;
std::string payload;
payload.reserve(data32[0]);
payload.reserve(data32[0] + 1);
while (total < data32[0]) {
ssize_t res =
::recv(socketfd, payload.data() + total, data32[0] - total, 0);
::recv(fd, payload.data() + total, data32[0] - total, 0);
if (res < 0) {
throw std::runtime_error("Unable to receive IPC response");
}
total += res;
}
payload[data32[0]] = 0;
return { data32[0], data32[1], &payload.front() };
}
struct ipc_response ipcSingleCommand(int socketfd, uint32_t type,
const std::string& payload) {
struct waybar::modules::sway::Ipc::ipc_response
waybar::modules::sway::Ipc::send(int fd, uint32_t type,
const std::string& payload) const
{
std::string header;
header.reserve(ipc_header_size);
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic.size());
memcpy(header.data(), ipc_magic.c_str(), ipc_magic.size());
header.reserve(ipc_header_size_);
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic_.size());
memcpy(header.data(), ipc_magic_.c_str(), ipc_magic_.size());
data32[0] = payload.size();
data32[1] = type;
if (send(socketfd, header.data(), ipc_header_size, 0) == -1) {
if (::send(fd, header.data(), ipc_header_size_, 0) == -1) {
throw std::runtime_error("Unable to send IPC header");
}
if (send(socketfd, payload.c_str(), payload.size(), 0) == -1) {
if (::send(fd, payload.c_str(), payload.size(), 0) == -1) {
throw std::runtime_error("Unable to send IPC payload");
}
return ipcRecvResponse(socketfd);
return recv(fd);
}
struct waybar::modules::sway::Ipc::ipc_response
waybar::modules::sway::Ipc::sendCmd(uint32_t type,
const std::string& payload) const
{
return send(fd_, type, payload);
}
void waybar::modules::sway::Ipc::subscribe(const std::string& payload) const
{
auto res = send(fd_event_, IPC_SUBSCRIBE, payload);
if (res.payload != "{\"success\": true}") {
throw std::runtime_error("Unable to subscribe ipc event");
}
}
struct waybar::modules::sway::Ipc::ipc_response
waybar::modules::sway::Ipc::handleEvent() const
{
return recv(fd_event_);
}