Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d0f2b5e8a6 |
@@ -12,7 +12,6 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
struct Selection
|
||||
{
|
||||
@@ -1814,9 +1813,9 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
(void)TRY_REF(get_window(client_info, wid, X_SendEvent));
|
||||
|
||||
Client* target_client = nullptr;
|
||||
for (auto& [_, thingy] : g_epoll_thingies)
|
||||
for (auto& [_, thingy] : g_pollables)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
if (thingy.type != Pollable::Type::Client)
|
||||
continue;
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
if (!other_client.objects.contains(wid))
|
||||
@@ -1938,47 +1937,11 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
case X_GrabServer:
|
||||
{
|
||||
g_server_grabber_fd = client_info.fd;
|
||||
|
||||
for (const auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
if (client_info.fd == other_client.fd)
|
||||
continue;
|
||||
|
||||
uint32_t events = 0;
|
||||
if (other_client.has_epollout)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case X_UngrabServer:
|
||||
{
|
||||
g_server_grabber_fd = -1;
|
||||
|
||||
for (const auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
if (client_info.fd == other_client.fd)
|
||||
continue;
|
||||
|
||||
uint32_t events = EPOLLIN;
|
||||
if (other_client.has_epollout)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case X_QueryPointer:
|
||||
|
||||
@@ -140,7 +140,6 @@ struct Client
|
||||
};
|
||||
int fd;
|
||||
State state;
|
||||
bool has_epollout { false };
|
||||
bool has_bigrequests { false };
|
||||
CARD16 sequence { 0 };
|
||||
BAN::Optional<uint32_t> pid;
|
||||
@@ -149,7 +148,7 @@ struct Client
|
||||
BAN::HashSet<CARD32> objects;
|
||||
};
|
||||
|
||||
struct EpollThingy
|
||||
struct Pollable
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
@@ -172,7 +171,6 @@ extern BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
|
||||
extern BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name;
|
||||
extern ATOM g_atom_value;
|
||||
|
||||
extern int g_epoll_fd;
|
||||
extern BAN::HashMap<int, EpollThingy> g_epoll_thingies;
|
||||
extern BAN::HashMap<int, Pollable> g_pollables;
|
||||
|
||||
extern int g_server_grabber_fd;
|
||||
|
||||
@@ -7,23 +7,18 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
void register_event_fd(int fd, void* data)
|
||||
{
|
||||
epoll_event event { .events = EPOLLIN, .data = { .fd = fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &event);
|
||||
|
||||
MUST(g_epoll_thingies.insert(fd, {
|
||||
.type = EpollThingy::Type::Event,
|
||||
MUST(g_pollables.insert(fd, {
|
||||
.type = Pollable::Type::Event,
|
||||
.value = data,
|
||||
}));
|
||||
}
|
||||
|
||||
void unregister_event_fd(int fd)
|
||||
{
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, fd, nullptr);
|
||||
g_epoll_thingies.remove(fd);
|
||||
g_pollables.remove(fd);
|
||||
}
|
||||
|
||||
void on_window_close_event(WINDOW wid)
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
template<typename F>
|
||||
static BAN::ErrorOr<void> for_each_client(uint32_t target_spec, const F& callback)
|
||||
{
|
||||
for (auto [fd, thingy] : g_epoll_thingies)
|
||||
for (auto [fd, thingy] : g_pollables)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
if (thingy.type != Pollable::Type::Client)
|
||||
continue;
|
||||
|
||||
Client& client_info = thingy.value.get<Client>();
|
||||
|
||||
162
xbanan/main.cpp
162
xbanan/main.cpp
@@ -5,8 +5,8 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <locale.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@@ -92,8 +92,7 @@ BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
|
||||
BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name;
|
||||
ATOM g_atom_value = XA_LAST_PREDEFINED + 1;
|
||||
|
||||
int g_epoll_fd;
|
||||
BAN::HashMap<int, EpollThingy> g_epoll_thingies;
|
||||
BAN::HashMap<int, Pollable> g_pollables;
|
||||
|
||||
int g_server_grabber_fd = -1;
|
||||
|
||||
@@ -155,22 +154,6 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_epoll_fd = epoll_create1(0);
|
||||
if (g_epoll_fd == -1)
|
||||
{
|
||||
perror("xbanan: epoll_create1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
epoll_event event { .events = EPOLLIN, .data = { .ptr = nullptr } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, server_sock, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define APPEND_ATOM(name) do { \
|
||||
MUST(g_atoms_id_to_name.insert(name, #name##_sv.substring(3))); \
|
||||
MUST(g_atoms_name_to_id.insert(#name##_sv.substring(3), name)); \
|
||||
@@ -274,9 +257,9 @@ int main()
|
||||
const auto close_client =
|
||||
[](int client_fd)
|
||||
{
|
||||
auto& epoll_thingy = g_epoll_thingies[client_fd];
|
||||
ASSERT(epoll_thingy.type == EpollThingy::Type::Client);
|
||||
auto& client_info = epoll_thingy.value.get<Client>();
|
||||
auto& pollable = g_pollables[client_fd];
|
||||
ASSERT(pollable.type == Pollable::Type::Client);
|
||||
auto& client_info = pollable.value.get<Client>();
|
||||
|
||||
dprintln("client {} disconnected", client_fd);
|
||||
|
||||
@@ -328,29 +311,11 @@ int main()
|
||||
g_objects.remove(it);
|
||||
}
|
||||
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr);
|
||||
g_epoll_thingies.remove(client_fd);
|
||||
g_pollables.remove(client_fd);
|
||||
close(client_fd);
|
||||
|
||||
if (client_fd == g_server_grabber_fd)
|
||||
{
|
||||
if (g_server_grabber_fd == client_fd)
|
||||
g_server_grabber_fd = -1;
|
||||
|
||||
for (const auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& other_client = thingy.value.get<Client>();
|
||||
|
||||
uint32_t events = EPOLLIN;
|
||||
if (other_client.has_epollout)
|
||||
events |= EPOLLOUT;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
|
||||
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Client dummy_client {};
|
||||
@@ -377,12 +342,37 @@ int main()
|
||||
|
||||
for (;;)
|
||||
{
|
||||
epoll_event events[16];
|
||||
const int event_count = epoll_wait(g_epoll_fd, events, 16, -1);
|
||||
|
||||
for (int i = 0; i < event_count; i++)
|
||||
BAN::Vector<pollfd> pollfds;
|
||||
MUST(pollfds.reserve(g_pollables.size() + 1));
|
||||
MUST(pollfds.push_back({
|
||||
.fd = server_sock,
|
||||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
}));
|
||||
for (auto& [fd, pollable] : g_pollables)
|
||||
{
|
||||
if (events[i].data.ptr == nullptr)
|
||||
short events = 0;
|
||||
if (g_server_grabber_fd == -1 || g_server_grabber_fd == fd)
|
||||
events |= POLLIN;
|
||||
if (pollable.type == Pollable::Type::Client && !pollable.value.get<Client>().output_buffer.empty())
|
||||
events |= POLLOUT;
|
||||
if (events == 0)
|
||||
continue;
|
||||
MUST(pollfds.push_back(pollfd {
|
||||
.fd = fd,
|
||||
.events = events,
|
||||
.revents = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
const int event_count = poll(pollfds.data(), pollfds.size(), -1);
|
||||
|
||||
for (const auto& pollfd : pollfds)
|
||||
{
|
||||
if (pollfd.revents == 0)
|
||||
continue;
|
||||
|
||||
if (pollfd.fd == server_sock)
|
||||
{
|
||||
int client_sock = accept(server_sock, nullptr, nullptr);
|
||||
if (client_sock == -1)
|
||||
@@ -400,8 +390,8 @@ int main()
|
||||
client_pid = client_cred.pid;
|
||||
#endif
|
||||
|
||||
MUST(g_epoll_thingies.insert(client_sock, {
|
||||
.type = EpollThingy::Type::Client,
|
||||
MUST(g_pollables.insert(client_sock, {
|
||||
.type = Pollable::Type::Client,
|
||||
.value = Client {
|
||||
.fd = client_sock,
|
||||
.state = Client::State::ConnectionSetup,
|
||||
@@ -409,44 +399,32 @@ int main()
|
||||
}
|
||||
}));
|
||||
|
||||
uint32_t events = 0;
|
||||
if (g_server_grabber_fd == -1)
|
||||
events |= EPOLLIN;
|
||||
|
||||
epoll_event event = { .events = events, .data = { .fd = client_sock } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, client_sock, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
close(client_sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintln("client {} connected", client_sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto it = g_epoll_thingies.find(events[i].data.fd);
|
||||
if (it == g_epoll_thingies.end())
|
||||
auto it = g_pollables.find(pollfd.fd);
|
||||
if (it == g_pollables.end())
|
||||
continue;
|
||||
auto& epoll_thingy = it->value;
|
||||
auto& pollable = it->value;
|
||||
|
||||
if (epoll_thingy.type == EpollThingy::Type::Event)
|
||||
if (pollable.type == Pollable::Type::Event)
|
||||
{
|
||||
g_platform_ops.poll_events(epoll_thingy.value.get<void*>());
|
||||
g_platform_ops.poll_events(pollable.value.get<void*>());
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(epoll_thingy.type == EpollThingy::Type::Client);
|
||||
ASSERT(pollable.type == Pollable::Type::Client);
|
||||
|
||||
auto& client_info = epoll_thingy.value.get<Client>();
|
||||
auto& client_info = pollable.value.get<Client>();
|
||||
|
||||
if (events[i].events & EPOLLHUP)
|
||||
if (pollfd.revents & POLLHUP)
|
||||
{
|
||||
close_client(client_info.fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].events & EPOLLOUT)
|
||||
if (pollfd.revents & POLLOUT)
|
||||
{
|
||||
const ssize_t nsend = send(
|
||||
client_info.fd,
|
||||
@@ -473,28 +451,11 @@ int main()
|
||||
);
|
||||
MUST(client_info.output_buffer.resize(client_info.output_buffer.size() - nsend));
|
||||
|
||||
if (client_info.output_buffer.empty())
|
||||
{
|
||||
uint32_t events = 0;
|
||||
if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd)
|
||||
events |= EPOLLIN;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = client_info.fd } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
close_client(client_info.fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
client_info.has_epollout = false;
|
||||
}
|
||||
|
||||
send_done:
|
||||
(void)0;
|
||||
}
|
||||
|
||||
if (!(events[i].events & EPOLLIN))
|
||||
if (!(pollfd.revents & POLLIN))
|
||||
continue;
|
||||
|
||||
if (g_server_grabber_fd != -1 && g_server_grabber_fd != client_info.fd)
|
||||
@@ -606,30 +567,5 @@ int main()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterator_invalidated:
|
||||
for (auto& [_, thingy] : g_epoll_thingies)
|
||||
{
|
||||
if (thingy.type != EpollThingy::Type::Client)
|
||||
continue;
|
||||
|
||||
auto& client_info = thingy.value.get<Client>();
|
||||
if (client_info.output_buffer.empty() || client_info.has_epollout)
|
||||
continue;
|
||||
|
||||
uint32_t events = EPOLLOUT;
|
||||
if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd)
|
||||
events |= EPOLLIN;
|
||||
|
||||
epoll_event event { .events = events, .data = { .fd = client_info.fd } };
|
||||
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1)
|
||||
{
|
||||
perror("xbanan: epoll_ctl");
|
||||
close_client(client_info.fd);
|
||||
goto iterator_invalidated;
|
||||
}
|
||||
|
||||
client_info.has_epollout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user