From e34f1f5d1812b412055e8de822842bbbe3224beb Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fl.fischer@fau.de>
Date: Fri, 15 Jan 2021 12:38:53 +0100
Subject: [PATCH] [IO] add a simple echo server app

---
 apps/EchoServer.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++
 apps/meson.build    |  6 ++++
 2 files changed, 78 insertions(+)
 create mode 100644 apps/EchoServer.cpp

diff --git a/apps/EchoServer.cpp b/apps/EchoServer.cpp
new file mode 100644
index 00000000..4d21dac6
--- /dev/null
+++ b/apps/EchoServer.cpp
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright © 2020-2021 Florian Fischer
+#include <sys/types.h>
+
+#include <cassert>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <string>
+
+#include "Common.hpp"
+#include "Runtime.hpp"
+#include "emper-common.h"
+#include "io.hpp"
+
+const int DECIMAL = 10;
+const std::string HOST = "0.0.0.0";
+const int PORT = 12345;
+
+auto main(int argc, char* argv[]) -> int {
+	int port = PORT;
+	std::string host = HOST;
+
+	if (argc > 2) {
+		std::cerr << "Usage: " << argv[0] << " [port]" << std::endl;
+		exit(EXIT_FAILURE);
+	}
+
+	if (argc > 1) {
+		long aport = strtol(argv[1], nullptr, DECIMAL);
+		assert(aport <= INT_MAX && aport >= INT_MIN);
+		port = (int)aport;
+	}
+
+	std::cout << "Echoserver listening on " << host << ":" << port << std::endl;
+
+	Runtime runtime;
+	auto* listener = emper::io::tcp_listener(host, port, [](int socket) {
+		// NOLINTNEXTLINE(modernize-avoid-c-arrays)
+		char buf[1024];
+		for (;;) {
+			ssize_t bytes_recv = emper::io::recvAndWait(socket, buf, sizeof(buf), 0);
+			if (unlikely(bytes_recv <= 0)) {
+				// socket was shutdown
+				if (bytes_recv < 0) {
+					DIE_MSG_ERRNO("server read failed");
+				}
+
+				emper::io::closeAndForget(socket);
+				return;
+			}
+
+			if (unlikely(bytes_recv == 5 && strncmp("quit\n", buf, bytes_recv) == 0)) {
+				exit(EXIT_SUCCESS);
+			}
+
+			ATTR_UNUSED ssize_t bytes_send = emper::io::sendAndWait(socket, buf, bytes_recv, 0);
+			assert(bytes_recv == bytes_send);
+		}
+	});
+
+	if (!listener) {
+		exit(EXIT_FAILURE);
+	}
+
+	runtime.scheduleFromAnywhere(*listener);
+
+	runtime.waitUntilFinished();
+
+	return EXIT_FAILURE;
+}
diff --git a/apps/meson.build b/apps/meson.build
index 7ed455b2..82a23a56 100644
--- a/apps/meson.build
+++ b/apps/meson.build
@@ -9,3 +9,9 @@ worker_sleep_example_exe = executable(
   'WorkerSleepExample.cpp',
   dependencies: emper_dep,
 )
+
+echoserver_exe = executable(
+  'echoserver',
+  'EchoServer.cpp',
+  dependencies: emper_dep,
+)
-- 
GitLab