mirror of
https://github.com/Mercantec-GHC/h5-projekt-mst.git
synced 2026-08-27 05:37:39 +02:00
epoll
This commit is contained in:
parent
d311a20c53
commit
3646c5bf90
@ -1,3 +1,5 @@
|
||||
#include "tcp.hpp"
|
||||
#include <print>
|
||||
#include <stdio.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
@ -7,6 +9,15 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("hello\n");
|
||||
auto x = mst::TcpListener::bind("0.0.0.0", PORT);
|
||||
if (!x) {
|
||||
std::println("{}", x.error());
|
||||
return 1;
|
||||
}
|
||||
std::println("starting");
|
||||
auto listener = x.value();
|
||||
{
|
||||
auto x = listener.loop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
0
backend/src/server.cpp
Normal file
0
backend/src/server.cpp
Normal file
1
backend/src/server.hpp
Normal file
1
backend/src/server.hpp
Normal file
@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@ -1,5 +1,6 @@
|
||||
#include "tcp.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <cstdlib>
|
||||
#include <errno.h>
|
||||
#include <expected>
|
||||
#include <format>
|
||||
@ -15,6 +16,29 @@
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mst {
|
||||
|
||||
auto event::make_listener_event(int fd) -> Event*
|
||||
{
|
||||
auto ev = (Event*)malloc(sizeof(Event));
|
||||
|
||||
ev->variant = Listener;
|
||||
ev->data.listener_fd = fd;
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
auto event::make_connection_event(TcpConnection connection) -> Event*
|
||||
{
|
||||
auto ev = (Event*)malloc(sizeof(Event));
|
||||
auto ptr = (TcpConnection*)std::malloc(sizeof(TcpConnection));
|
||||
*ptr = connection;
|
||||
|
||||
ev->variant = Connection;
|
||||
ev->data.connection = ptr;
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
auto errno_shim(std::string_view message) -> std::string
|
||||
{
|
||||
auto x = strerror(errno);
|
||||
@ -62,24 +86,61 @@ auto TcpListener::bind(const std::string& host, uint16_t port)
|
||||
return std::unexpected(errno_shim("could not listen"));
|
||||
}
|
||||
|
||||
auto epoll_fd = ::epoll_create(0);
|
||||
auto epoll_fd = ::epoll_create1(0);
|
||||
|
||||
auto events_accepted = epoll_event { .events = EPOLLIN, .data = { } };
|
||||
if (::epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &events_accepted) < 0) {
|
||||
auto context = event::make_listener_event(socket_fd);
|
||||
|
||||
auto event = epoll_event { .events = EPOLLIN, .data = { .ptr = context } };
|
||||
if (::epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event) < 0) {
|
||||
return std::unexpected(errno_shim("could not connect to epoll"));
|
||||
}
|
||||
|
||||
return TcpListener(socket_fd, epoll_fd, address);
|
||||
return TcpListener(epoll_fd, address);
|
||||
}
|
||||
|
||||
auto TcpListener::accept() -> Result<TcpConnection>
|
||||
auto TcpListener::start() -> Result<void>
|
||||
{
|
||||
socklen_t size = sizeof(address);
|
||||
int socket = ::accept(this->listener_fd, (struct sockaddr*)&address, &size);
|
||||
if (socket < 0) {
|
||||
return std::unexpected(errno_shim("could not accept"));
|
||||
epoll_event events[128] = { };
|
||||
while (true) {
|
||||
|
||||
auto events_len = ::epoll_wait(this->epoll_fd, events, 128, -1);
|
||||
if (events_len < 0) {
|
||||
return std::unexpected(errno_shim("could not poll"));
|
||||
}
|
||||
for (int i = 0; i < events_len; ++i) {
|
||||
auto event = (event::Event*)events[i].data.ptr;
|
||||
|
||||
switch (event->variant) {
|
||||
case event::Listener: {
|
||||
socklen_t size = sizeof(address);
|
||||
int client = ::accept(
|
||||
events[0].data.fd, (struct sockaddr*)&address, &size);
|
||||
if (client < 0) {
|
||||
return std::unexpected(errno_shim("could not accept"));
|
||||
}
|
||||
|
||||
auto context = event::make_connection_event(
|
||||
TcpConnection(*this, client));
|
||||
|
||||
auto poll_event = epoll_event { .events = EPOLLIN,
|
||||
.data = { .ptr = context } };
|
||||
|
||||
if (::epoll_ctl(
|
||||
epoll_fd, EPOLL_CTL_ADD, client, &poll_event)
|
||||
< 0) {
|
||||
return std::unexpected(
|
||||
errno_shim("could not add connection to epoll"));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case event::Connection: {
|
||||
event->data.connection.wake();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TcpConnection(*this, socket);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,11 +4,29 @@
|
||||
#include <expected>
|
||||
#include <netinet/in.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mst {
|
||||
|
||||
template <typename T> using Result = std::expected<T, std::string>;
|
||||
|
||||
class TcpConnection;
|
||||
|
||||
namespace event {
|
||||
enum Variant { Listener, Connection };
|
||||
typedef union {
|
||||
int listener_fd;
|
||||
TcpConnection* connection;
|
||||
} Data;
|
||||
struct Event {
|
||||
Variant variant;
|
||||
Data data;
|
||||
};
|
||||
|
||||
auto make_listener_event(int fd) -> Event*;
|
||||
auto make_connection_event(TcpConnection connection) -> Event*;
|
||||
}
|
||||
|
||||
class TcpListener;
|
||||
|
||||
class TcpConnection {
|
||||
@ -20,6 +38,7 @@ public:
|
||||
|
||||
private:
|
||||
int fd;
|
||||
event::Event event;
|
||||
};
|
||||
|
||||
class TcpListener {
|
||||
@ -27,16 +46,13 @@ class TcpListener {
|
||||
public:
|
||||
static auto bind(const std::string& host, uint16_t port)
|
||||
-> Result<TcpListener>;
|
||||
auto accept() -> Result<TcpConnection>;
|
||||
auto start() -> Result<void>;
|
||||
|
||||
private:
|
||||
TcpListener(int listener_fd, int epoll_fd, sockaddr_in address)
|
||||
: listener_fd(listener_fd)
|
||||
, epoll_fd(epoll_fd)
|
||||
TcpListener(int epoll_fd, sockaddr_in address)
|
||||
: epoll_fd(epoll_fd)
|
||||
, address(address) { };
|
||||
int listener_fd;
|
||||
int epoll_fd;
|
||||
sockaddr_in address;
|
||||
std::vector<int> epoll_fds;
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user