Commit 0d20ba85 authored by Florian Fischer's avatar Florian Fischer
Browse files

add cpp variant

parent bc4c70ac
...@@ -8,6 +8,8 @@ project('emper-echo-server', 'c', 'cpp', ...@@ -8,6 +8,8 @@ project('emper-echo-server', 'c', 'cpp',
'werror=true', 'werror=true',
]) ])
add_project_arguments('-Wno-non-virtual-dtor', language: 'cpp')
run_target('iwyu', command: 'tools/check-iwyu') run_target('iwyu', command: 'tools/check-iwyu')
conf_data = configuration_data() conf_data = configuration_data()
......
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2020 Florian Fischer
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include "AsyncLibrary.hpp"
#include "Common.hpp"
#include "Fiber.hpp"
#include "Runtime.hpp"
#include "config.h"
static int port = 12345;
[[noreturn]] static void die(const char* msg) {
perror(msg);
exit(EXIT_FAILURE);
}
#define BUF_MAX 4096
void client_func(void* arg) {
int client_fd = *(int*)arg;
free(arg);
char buf[BUF_MAX];
for (;;) {
#ifdef USE_ASYNC_IO
ssize_t bytes_recv = io::sync_recv(client_fd, (void*)&buf, BUF_MAX, MSG_WAITALL);
#else
ssize_t bytes_recv = recv(client_fd, (void*)&buf, BUF_MAX, MSG_WAITALL);
#endif
// socket was shutdown
if (unlikely(bytes_recv == 0)) {
return;
}
if (unlikely(bytes_recv == -1)) {
perror("recv failed");
if (errno != EINTR) {
return;
}
}
// send echo
ssize_t bytes_send = 0;
while (bytes_send < bytes_recv) {
#ifdef USE_ASYNC_IO
ssize_t new_bytes_send = io::sync_send(client_fd, buf, bytes_recv - bytes_send, MSG_NOSIGNAL);
#else
ssize_t new_bytes_send = send(client_fd, buf, bytes_recv - bytes_send, MSG_NOSIGNAL);
#endif
// socket was shutdown
if (unlikely(bytes_send == 0)) {
return;
}
if (unlikely(new_bytes_send == -1)) {
if (errno != EINTR) {
perror("send failed");
return;
}
}
bytes_send += new_bytes_send;
}
}
}
#define BACKLOG 5
static void welcome_func() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
die("socket failed");
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr)); // NOLINT
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(port);
int reuseaddr = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1) {
die("setsockopt failed");
}
if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
die("bind failed");
}
if (listen(sockfd, BACKLOG) != 0) {
die("listen failed");
}
Runtime* runtime = Runtime::getRuntime();
for (;;) {
#ifdef USE_ASYNC_IO
int client_fd = io::sync_accept(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
#else
socklen_t address_len = sizeof(servaddr);
int client_fd = accept(sockfd, (struct sockaddr*)&servaddr, &address_len);
#endif
if (unlikely(client_fd < 0)) {
perror("accept failed");
}
int* passable_fd = reinterpret_cast<int*>(malloc(sizeof(int)));
if (unlikely(!passable_fd)) {
die("allocating passable fd failed");
}
*passable_fd = client_fd;
Fiber* client_fiber = Fiber::from(client_func, (void*)passable_fd);
runtime->schedule(*client_fiber);
}
}
int main(int argc, char* argv[]) {
if (argc > 2) {
const int decimal = 10;
port = (int)strtol(argv[1], nullptr, decimal);
}
Runtime runtime;
Fiber* welcome_fiber = Fiber::from(&welcome_func);
runtime.schedule(*welcome_fiber);
runtime.waitUntilFinished();
}
configure_file(output: 'config.h', configuration: conf_data) configure_file(output: 'config.h', configuration: conf_data)
include_dir = include_directories('.') inc = include_directories('.')
cpp_exe = executable('emper-echo-server',
'emper-echo-server.cpp',
include_directories : [inc],
dependencies: dependencies)
emper_c = emper_proj.get_variable('emper_c') emper_c = emper_proj.get_variable('emper_c')
emper_library_include = emper_proj.get_variable('emper_library_include')
sources = ['emper-echo-server.c'] c_exe = executable('emper-echo-server-c',
exe = executable('emper-echo-server', 'emper-echo-server.c',
sources, include_directories : [inc],
include_directories : [include_dir, emper_library_include],
dependencies: dependencies, dependencies: dependencies,
link_with: emper_c) link_with: emper_c)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment