1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:47:34 +00:00

WSEventLoop: Move message processing into WSClientConnection

Tidier encapsulation than splitting messages between two classes.
This commit is contained in:
Robin Burchell 2019-07-14 12:50:13 +02:00 committed by Andreas Kling
parent 7b75632e5c
commit 818a29c964
3 changed files with 266 additions and 262 deletions

View file

@ -13,6 +13,7 @@
#include <WindowServer/WSWindowSwitcher.h> #include <WindowServer/WSWindowSwitcher.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
@ -145,6 +146,267 @@ void WSClientConnection::did_misbehave()
delete_later(); delete_later();
} }
static Vector<Rect, 32> get_rects(const WSAPI_ClientMessage& message, const ByteBuffer& extra_data)
{
Vector<Rect, 32> rects;
if (message.rect_count > (int)(WSAPI_ClientMessage::max_inline_rect_count + extra_data.size() / sizeof(WSAPI_Rect))) {
return {};
}
for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, message.rect_count); ++i)
rects.append(message.rects[i]);
if (!extra_data.is_empty()) {
auto* extra_rects = reinterpret_cast<const WSAPI_Rect*>(extra_data.data());
for (int i = 0; i < (int)(extra_data.size() / sizeof(WSAPI_Rect)); ++i)
rects.append(extra_rects[i]);
}
return rects;
}
void WSClientConnection::on_ready_read()
{
unsigned messages_received = 0;
for (;;) {
WSAPI_ClientMessage message;
// FIXME: Don't go one message at a time, that's so much context switching, oof.
ssize_t nread = recv(fd(), &message, sizeof(WSAPI_ClientMessage), MSG_DONTWAIT);
if (nread == 0 || (nread == -1 && errno == EAGAIN)) {
if (!messages_received)
CEventLoop::current().post_event(*this, make<WSClientDisconnectedNotification>(client_id()));
break;
}
if (nread < 0) {
perror("recv");
ASSERT_NOT_REACHED();
}
ByteBuffer extra_data;
if (message.extra_size) {
if (message.extra_size >= 32768) {
dbgprintf("message.extra_size is way too large\n");
return did_misbehave();
}
extra_data = ByteBuffer::create_uninitialized(message.extra_size);
// FIXME: We should allow this to time out. Maybe use a socket timeout?
int extra_nread = read(fd(), extra_data.data(), extra_data.size());
if (extra_nread != (int)message.extra_size) {
dbgprintf("extra_nread(%d) != extra_size(%d)\n", extra_nread, extra_data.size());
if (extra_nread < 0)
perror("read");
return did_misbehave();
}
}
if (!handle_message(message, move(extra_data)))
return;
++messages_received;
}
}
bool WSClientConnection::handle_message(const WSAPI_ClientMessage& message, ByteBuffer&& extra_data)
{
switch (message.type) {
case WSAPI_ClientMessage::Type::Greeting:
set_client_pid(message.greeting.client_pid);
break;
case WSAPI_ClientMessage::Type::CreateMenubar:
CEventLoop::current().post_event(*this, make<WSAPICreateMenubarRequest>(m_client_id));
break;
case WSAPI_ClientMessage::Type::DestroyMenubar:
CEventLoop::current().post_event(*this, make<WSAPIDestroyMenubarRequest>(m_client_id, message.menu.menubar_id));
break;
case WSAPI_ClientMessage::Type::SetApplicationMenubar:
CEventLoop::current().post_event(*this, make<WSAPISetApplicationMenubarRequest>(m_client_id, message.menu.menubar_id));
break;
case WSAPI_ClientMessage::Type::AddMenuToMenubar:
CEventLoop::current().post_event(*this, make<WSAPIAddMenuToMenubarRequest>(m_client_id, message.menu.menubar_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::CreateMenu:
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPICreateMenuRequest>(m_client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::PopupMenu:
CEventLoop::current().post_event(*this, make<WSAPIPopupMenuRequest>(m_client_id, message.menu.menu_id, message.menu.position));
break;
case WSAPI_ClientMessage::Type::DismissMenu:
CEventLoop::current().post_event(*this, make<WSAPIDismissMenuRequest>(m_client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::SetWindowIcon:
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPISetWindowIconRequest>(m_client_id, message.window_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::DestroyMenu:
CEventLoop::current().post_event(*this, make<WSAPIDestroyMenuRequest>(m_client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::AddMenuItem:
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPIAddMenuItemRequest>(m_client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked));
break;
case WSAPI_ClientMessage::Type::UpdateMenuItem:
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPIUpdateMenuItemRequest>(m_client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked));
break;
case WSAPI_ClientMessage::Type::AddMenuSeparator:
CEventLoop::current().post_event(*this, make<WSAPIAddMenuSeparatorRequest>(m_client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::CreateWindow: {
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
auto ws_window_type = WSWindowType::Invalid;
switch (message.window.type) {
case WSAPI_WindowType::Normal:
ws_window_type = WSWindowType::Normal;
break;
case WSAPI_WindowType::Menu:
ws_window_type = WSWindowType::Menu;
break;
case WSAPI_WindowType::WindowSwitcher:
ws_window_type = WSWindowType::WindowSwitcher;
break;
case WSAPI_WindowType::Taskbar:
ws_window_type = WSWindowType::Taskbar;
break;
case WSAPI_WindowType::Tooltip:
ws_window_type = WSWindowType::Tooltip;
break;
case WSAPI_WindowType::Menubar:
ws_window_type = WSWindowType::Menubar;
break;
case WSAPI_WindowType::Launcher:
ws_window_type = WSWindowType::Launcher;
break;
case WSAPI_WindowType::Invalid:
default:
dbgprintf("Unknown WSAPI_WindowType: %d\n", message.window.type);
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this,
make<WSAPICreateWindowRequest>(m_client_id,
message.window.rect,
String(message.text, message.text_length),
message.window.has_alpha_channel,
message.window.modal,
message.window.resizable,
message.window.fullscreen,
message.window.show_titlebar,
message.window.opacity,
message.window.base_size,
message.window.size_increment,
ws_window_type,
Color::from_rgba(message.window.background_color)));
break;
}
case WSAPI_ClientMessage::Type::DestroyWindow:
CEventLoop::current().post_event(*this, make<WSAPIDestroyWindowRequest>(m_client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowTitle:
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPISetWindowTitleRequest>(m_client_id, message.window_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::GetWindowTitle:
CEventLoop::current().post_event(*this, make<WSAPIGetWindowTitleRequest>(m_client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowRect:
CEventLoop::current().post_event(*this, make<WSAPISetWindowRectRequest>(m_client_id, message.window_id, message.window.rect));
break;
case WSAPI_ClientMessage::Type::GetWindowRect:
CEventLoop::current().post_event(*this, make<WSAPIGetWindowRectRequest>(m_client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetClipboardContents:
CEventLoop::current().post_event(*this, make<WSAPISetClipboardContentsRequest>(m_client_id, message.clipboard.shared_buffer_id, message.clipboard.contents_size));
break;
case WSAPI_ClientMessage::Type::GetClipboardContents:
CEventLoop::current().post_event(*this, make<WSAPIGetClipboardContentsRequest>(m_client_id));
break;
case WSAPI_ClientMessage::Type::InvalidateRect: {
auto rects = get_rects(message, extra_data);
if (rects.is_empty()) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPIInvalidateRectRequest>(m_client_id, message.window_id, rects));
break;
}
case WSAPI_ClientMessage::Type::DidFinishPainting: {
auto rects = get_rects(message, extra_data);
if (rects.is_empty()) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPIDidFinishPaintingNotification>(m_client_id, message.window_id, rects));
break;
}
case WSAPI_ClientMessage::Type::GetWindowBackingStore:
CEventLoop::current().post_event(*this, make<WSAPIGetWindowBackingStoreRequest>(m_client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowBackingStore:
CEventLoop::current().post_event(*this, make<WSAPISetWindowBackingStoreRequest>(m_client_id, message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel, message.backing.flush_immediately));
break;
case WSAPI_ClientMessage::Type::SetGlobalCursorTracking:
CEventLoop::current().post_event(*this, make<WSAPISetGlobalCursorTrackingRequest>(m_client_id, message.window_id, message.value));
break;
case WSAPI_ClientMessage::Type::SetWallpaper:
if (message.text_length > (int)sizeof(message.text)) {
did_misbehave();
return false;
}
CEventLoop::current().post_event(*this, make<WSAPISetWallpaperRequest>(m_client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::GetWallpaper:
CEventLoop::current().post_event(*this, make<WSAPIGetWallpaperRequest>(m_client_id));
break;
case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
CEventLoop::current().post_event(*this, make<WSAPISetWindowOverrideCursorRequest>(m_client_id, message.window_id, (WSStandardCursor)message.cursor.cursor));
break;
case WSAPI_ClientMessage::SetWindowHasAlphaChannel:
CEventLoop::current().post_event(*this, make<WSAPISetWindowHasAlphaChannelRequest>(m_client_id, message.window_id, message.value));
break;
case WSAPI_ClientMessage::Type::WM_SetActiveWindow:
CEventLoop::current().post_event(*this, make<WSWMAPISetActiveWindowRequest>(m_client_id, message.wm.client_id, message.wm.window_id));
break;
case WSAPI_ClientMessage::Type::WM_SetWindowMinimized:
CEventLoop::current().post_event(*this, make<WSWMAPISetWindowMinimizedRequest>(m_client_id, message.wm.client_id, message.wm.window_id, message.wm.minimized));
break;
case WSAPI_ClientMessage::Type::WM_StartWindowResize:
CEventLoop::current().post_event(*this, make<WSWMAPIStartWindowResizeRequest>(m_client_id, message.wm.client_id, message.wm.window_id));
break;
case WSAPI_ClientMessage::Type::WM_PopupWindowMenu:
CEventLoop::current().post_event(*this, make<WSWMAPIPopupWindowMenuRequest>(m_client_id, message.wm.client_id, message.wm.window_id, message.wm.position));
break;
case WSAPI_ClientMessage::Type::MoveWindowToFront:
CEventLoop::current().post_event(*this, make<WSAPIMoveWindowToFrontRequest>(m_client_id, message.window_id));
break;
default:
break;
}
return true;
}
void WSClientConnection::handle_request(const WSAPICreateMenubarRequest&) void WSClientConnection::handle_request(const WSAPICreateMenubarRequest&)
{ {
int menubar_id = m_next_menubar_id++; int menubar_id = m_next_menubar_id++;

View file

@ -43,9 +43,12 @@ public:
void did_misbehave(); void did_misbehave();
void on_ready_read();
private: private:
virtual void event(CEvent&) override; virtual void event(CEvent&) override;
bool handle_message(const WSAPI_ClientMessage& message, ByteBuffer&& extra_data);
void on_request(const WSAPIClientRequest&); void on_request(const WSAPIClientRequest&);
void handle_request(const WSAPICreateMenubarRequest&); void handle_request(const WSAPICreateMenubarRequest&);
void handle_request(const WSAPIDestroyMenubarRequest&); void handle_request(const WSAPIDestroyMenubarRequest&);

View file

@ -102,230 +102,6 @@ void WSEventLoop::drain_keyboard()
} }
} }
static Vector<Rect, 32> get_rects(const WSAPI_ClientMessage& message, const ByteBuffer& extra_data)
{
Vector<Rect, 32> rects;
if (message.rect_count > (int)(WSAPI_ClientMessage::max_inline_rect_count + extra_data.size() / sizeof(WSAPI_Rect))) {
return {};
}
for (int i = 0; i < min(WSAPI_ClientMessage::max_inline_rect_count, message.rect_count); ++i)
rects.append(message.rects[i]);
if (!extra_data.is_empty()) {
auto* extra_rects = reinterpret_cast<const WSAPI_Rect*>(extra_data.data());
for (int i = 0; i < (int)(extra_data.size() / sizeof(WSAPI_Rect)); ++i)
rects.append(extra_rects[i]);
}
return rects;
}
bool WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessage& message, ByteBuffer&& extra_data)
{
WSClientConnection& client = *WSClientConnection::from_client_id(client_id);
switch (message.type) {
case WSAPI_ClientMessage::Type::Greeting:
client.set_client_pid(message.greeting.client_pid);
break;
case WSAPI_ClientMessage::Type::CreateMenubar:
post_event(client, make<WSAPICreateMenubarRequest>(client_id));
break;
case WSAPI_ClientMessage::Type::DestroyMenubar:
post_event(client, make<WSAPIDestroyMenubarRequest>(client_id, message.menu.menubar_id));
break;
case WSAPI_ClientMessage::Type::SetApplicationMenubar:
post_event(client, make<WSAPISetApplicationMenubarRequest>(client_id, message.menu.menubar_id));
break;
case WSAPI_ClientMessage::Type::AddMenuToMenubar:
post_event(client, make<WSAPIAddMenuToMenubarRequest>(client_id, message.menu.menubar_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::CreateMenu:
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::PopupMenu:
post_event(client, make<WSAPIPopupMenuRequest>(client_id, message.menu.menu_id, message.menu.position));
break;
case WSAPI_ClientMessage::Type::DismissMenu:
post_event(client, make<WSAPIDismissMenuRequest>(client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::SetWindowIcon:
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPISetWindowIconRequest>(client_id, message.window_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::DestroyMenu:
post_event(client, make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::AddMenuItem:
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked));
break;
case WSAPI_ClientMessage::Type::UpdateMenuItem:
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
if (message.menu.shortcut_text_length > (int)sizeof(message.menu.shortcut_text)) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPIUpdateMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled, message.menu.checkable, message.menu.checked));
break;
case WSAPI_ClientMessage::Type::AddMenuSeparator:
post_event(client, make<WSAPIAddMenuSeparatorRequest>(client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::CreateWindow: {
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
auto ws_window_type = WSWindowType::Invalid;
switch (message.window.type) {
case WSAPI_WindowType::Normal:
ws_window_type = WSWindowType::Normal;
break;
case WSAPI_WindowType::Menu:
ws_window_type = WSWindowType::Menu;
break;
case WSAPI_WindowType::WindowSwitcher:
ws_window_type = WSWindowType::WindowSwitcher;
break;
case WSAPI_WindowType::Taskbar:
ws_window_type = WSWindowType::Taskbar;
break;
case WSAPI_WindowType::Tooltip:
ws_window_type = WSWindowType::Tooltip;
break;
case WSAPI_WindowType::Menubar:
ws_window_type = WSWindowType::Menubar;
break;
case WSAPI_WindowType::Launcher:
ws_window_type = WSWindowType::Launcher;
break;
case WSAPI_WindowType::Invalid:
default:
dbgprintf("Unknown WSAPI_WindowType: %d\n", message.window.type);
client.did_misbehave();
return false;
}
post_event(client,
make<WSAPICreateWindowRequest>(client_id,
message.window.rect,
String(message.text, message.text_length),
message.window.has_alpha_channel,
message.window.modal,
message.window.resizable,
message.window.fullscreen,
message.window.show_titlebar,
message.window.opacity,
message.window.base_size,
message.window.size_increment,
ws_window_type,
Color::from_rgba(message.window.background_color)));
break;
}
case WSAPI_ClientMessage::Type::DestroyWindow:
post_event(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowTitle:
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPISetWindowTitleRequest>(client_id, message.window_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::GetWindowTitle:
post_event(client, make<WSAPIGetWindowTitleRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowRect:
post_event(client, make<WSAPISetWindowRectRequest>(client_id, message.window_id, message.window.rect));
break;
case WSAPI_ClientMessage::Type::GetWindowRect:
post_event(client, make<WSAPIGetWindowRectRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetClipboardContents:
post_event(client, make<WSAPISetClipboardContentsRequest>(client_id, message.clipboard.shared_buffer_id, message.clipboard.contents_size));
break;
case WSAPI_ClientMessage::Type::GetClipboardContents:
post_event(client, make<WSAPIGetClipboardContentsRequest>(client_id));
break;
case WSAPI_ClientMessage::Type::InvalidateRect: {
auto rects = get_rects(message, extra_data);
if (rects.is_empty()) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPIInvalidateRectRequest>(client_id, message.window_id, rects));
break;
}
case WSAPI_ClientMessage::Type::DidFinishPainting: {
auto rects = get_rects(message, extra_data);
if (rects.is_empty()) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, rects));
break;
}
case WSAPI_ClientMessage::Type::GetWindowBackingStore:
post_event(client, make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowBackingStore:
post_event(client, make<WSAPISetWindowBackingStoreRequest>(client_id, message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel, message.backing.flush_immediately));
break;
case WSAPI_ClientMessage::Type::SetGlobalCursorTracking:
post_event(client, make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.window_id, message.value));
break;
case WSAPI_ClientMessage::Type::SetWallpaper:
if (message.text_length > (int)sizeof(message.text)) {
client.did_misbehave();
return false;
}
post_event(client, make<WSAPISetWallpaperRequest>(client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::GetWallpaper:
post_event(client, make<WSAPIGetWallpaperRequest>(client_id));
break;
case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
post_event(client, make<WSAPISetWindowOverrideCursorRequest>(client_id, message.window_id, (WSStandardCursor)message.cursor.cursor));
break;
case WSAPI_ClientMessage::SetWindowHasAlphaChannel:
post_event(client, make<WSAPISetWindowHasAlphaChannelRequest>(client_id, message.window_id, message.value));
break;
case WSAPI_ClientMessage::Type::WM_SetActiveWindow:
post_event(client, make<WSWMAPISetActiveWindowRequest>(client_id, message.wm.client_id, message.wm.window_id));
break;
case WSAPI_ClientMessage::Type::WM_SetWindowMinimized:
post_event(client, make<WSWMAPISetWindowMinimizedRequest>(client_id, message.wm.client_id, message.wm.window_id, message.wm.minimized));
break;
case WSAPI_ClientMessage::Type::WM_StartWindowResize:
post_event(client, make<WSWMAPIStartWindowResizeRequest>(client_id, message.wm.client_id, message.wm.window_id));
break;
case WSAPI_ClientMessage::Type::WM_PopupWindowMenu:
post_event(client, make<WSWMAPIPopupWindowMenuRequest>(client_id, message.wm.client_id, message.wm.window_id, message.wm.position));
break;
case WSAPI_ClientMessage::Type::MoveWindowToFront:
post_event(client, make<WSAPIMoveWindowToFrontRequest>(client_id, message.window_id));
break;
default:
break;
}
return true;
}
void WSEventLoop::add_file_descriptors_for_select(fd_set& fds, int& max_fd_added) void WSEventLoop::add_file_descriptors_for_select(fd_set& fds, int& max_fd_added)
{ {
auto add_fd_to_set = [&max_fd_added](int fd, auto& set) { auto add_fd_to_set = [&max_fd_added](int fd, auto& set) {
@ -348,44 +124,7 @@ void WSEventLoop::process_file_descriptors_after_select(const fd_set& fds)
drain_mouse(); drain_mouse();
WSClientConnection::for_each_client([&](WSClientConnection& client) { WSClientConnection::for_each_client([&](WSClientConnection& client) {
if (FD_ISSET(client.fd(), &fds)) if (FD_ISSET(client.fd(), &fds))
drain_client(client); client.on_ready_read();
}); });
} }
void WSEventLoop::drain_client(WSClientConnection& client)
{
unsigned messages_received = 0;
for (;;) {
WSAPI_ClientMessage message;
// FIXME: Don't go one message at a time, that's so much context switching, oof.
ssize_t nread = recv(client.fd(), &message, sizeof(WSAPI_ClientMessage), MSG_DONTWAIT);
if (nread == 0 || (nread == -1 && errno == EAGAIN)) {
if (!messages_received)
post_event(client, make<WSClientDisconnectedNotification>(client.client_id()));
break;
}
if (nread < 0) {
perror("recv");
ASSERT_NOT_REACHED();
}
ByteBuffer extra_data;
if (message.extra_size) {
if (message.extra_size >= 32768) {
dbgprintf("message.extra_size is way too large\n");
return client.did_misbehave();
}
extra_data = ByteBuffer::create_uninitialized(message.extra_size);
// FIXME: We should allow this to time out. Maybe use a socket timeout?
int extra_nread = read(client.fd(), extra_data.data(), extra_data.size());
if (extra_nread != (int)message.extra_size) {
dbgprintf("extra_nread(%d) != extra_size(%d)\n", extra_nread, extra_data.size());
if (extra_nread < 0)
perror("read");
return client.did_misbehave();
}
}
if (!on_receive_from_client(client.client_id(), message, move(extra_data)))
return;
++messages_received;
}
}