2016-11-02 19:22:45 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
2016-11-20 22:04:31 +00:00
|
|
|
#include <unistd.h>
|
2016-11-02 19:22:45 +00:00
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
#include "errors.hpp"
|
2016-11-02 19:22:45 +00:00
|
|
|
#include "utils/file.hpp"
|
|
|
|
#include "utils/mixins.hpp"
|
|
|
|
#include "utils/socket.hpp"
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
using std::snprintf;
|
|
|
|
using std::strlen;
|
|
|
|
|
|
|
|
namespace socket_util {
|
|
|
|
/**
|
|
|
|
* Constructor: establishing socket connection
|
|
|
|
*/
|
|
|
|
unix_connection::unix_connection(string&& path) : m_socketpath(path) {
|
2016-12-15 08:29:14 +00:00
|
|
|
struct sockaddr_un socket_addr {};
|
2016-11-02 19:22:45 +00:00
|
|
|
socket_addr.sun_family = AF_UNIX;
|
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
if ((m_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
2016-11-02 19:22:45 +00:00
|
|
|
throw system_error("Failed to open unix connection");
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
snprintf(socket_addr.sun_path, sizeof(socket_addr.sun_path), "%s", m_socketpath.c_str());
|
|
|
|
auto len = sizeof(socket_addr);
|
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
if (connect(m_fd, reinterpret_cast<struct sockaddr*>(&socket_addr), len) == -1) {
|
2016-11-02 19:22:45 +00:00
|
|
|
throw system_error("Failed to connect to socket");
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor: closes file descriptor
|
|
|
|
*/
|
|
|
|
unix_connection::~unix_connection() noexcept {
|
2016-11-25 12:55:15 +00:00
|
|
|
if (m_fd != -1) {
|
2016-11-02 19:22:45 +00:00
|
|
|
close(m_fd);
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Close reading end of connection
|
|
|
|
*/
|
|
|
|
int unix_connection::disconnect() {
|
|
|
|
return shutdown(m_fd, SHUT_RD);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Transmit fixed size data
|
|
|
|
*/
|
|
|
|
ssize_t unix_connection::send(const void* data, size_t len, int flags) {
|
|
|
|
ssize_t bytes_sent = 0;
|
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
if ((bytes_sent = ::send(m_fd, data, len, flags)) == -1) {
|
2016-11-02 19:22:45 +00:00
|
|
|
throw system_error("Failed to transmit data");
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
return bytes_sent;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Transmit string data
|
|
|
|
*/
|
2016-11-25 12:55:15 +00:00
|
|
|
ssize_t unix_connection::send(const string& data, int flags) {
|
2016-11-02 19:22:45 +00:00
|
|
|
return send(data.c_str(), data.length(), flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Receive data
|
|
|
|
*/
|
2016-12-14 06:13:07 +00:00
|
|
|
string unix_connection::receive(const ssize_t receive_bytes, ssize_t* bytes_received, int flags) {
|
2016-11-02 19:22:45 +00:00
|
|
|
char buffer[BUFSIZ];
|
|
|
|
|
2016-12-14 06:13:07 +00:00
|
|
|
if ((*bytes_received = ::recv(m_fd, buffer, receive_bytes, flags)) == -1) {
|
2016-11-02 19:22:45 +00:00
|
|
|
throw system_error("Failed to receive data");
|
2016-12-14 06:13:07 +00:00
|
|
|
} else {
|
|
|
|
buffer[*bytes_received] = 0;
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
return string{buffer};
|
|
|
|
}
|
|
|
|
|
2016-12-14 06:45:29 +00:00
|
|
|
/**
|
2018-11-04 15:08:54 +00:00
|
|
|
* \see receive
|
2016-12-14 06:45:29 +00:00
|
|
|
*/
|
|
|
|
string unix_connection::receive(const ssize_t receive_bytes, int flags) {
|
|
|
|
ssize_t bytes{0};
|
|
|
|
return receive(receive_bytes, &bytes, flags);
|
|
|
|
}
|
|
|
|
|
2016-12-14 06:13:07 +00:00
|
|
|
/**
|
|
|
|
* Peek at the specified number of bytes
|
|
|
|
*/
|
|
|
|
bool unix_connection::peek(const size_t peek_bytes) {
|
|
|
|
ssize_t bytes_seen{0};
|
|
|
|
receive(peek_bytes, &bytes_seen, MSG_PEEK);
|
|
|
|
return bytes_seen > 0;
|
|
|
|
}
|
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
/**
|
|
|
|
* Poll file descriptor for to check for available data
|
|
|
|
*/
|
|
|
|
bool unix_connection::poll(short int events, int timeout_ms) {
|
|
|
|
struct pollfd fds[1];
|
|
|
|
fds[0].fd = m_fd;
|
|
|
|
fds[0].events = events;
|
|
|
|
|
2016-11-25 12:55:15 +00:00
|
|
|
if (::poll(fds, 1, timeout_ms) == -1) {
|
2016-11-02 19:22:45 +00:00
|
|
|
throw system_error("Failed to poll file descriptor");
|
2016-11-25 12:55:15 +00:00
|
|
|
}
|
2016-11-02 19:22:45 +00:00
|
|
|
|
|
|
|
return fds[0].revents & events;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS_END
|