From 92d669a4096fd8d5efd158e9ead7fde698bc4cdc Mon Sep 17 00:00:00 2001 From: hanez Date: Mon, 13 Oct 2025 02:18:32 +0200 Subject: [PATCH] Added some more server socket fun and examples. (0.27.0) --- CMakeLists.txt | 4 +- examples/debug_reporting.fun | 13 +++++- .../extra}/pcsc2_example.fun | 0 .../examples => examples/extra}/pcsc_demo.fun | 0 examples/extra/tcp_echo_server.fun | 37 ++++++++++++++++ examples/extra/tcp_echo_server_class.fun | 32 ++++++++++++++ examples/repl_on_error.fun | 0 lib/io/socket.fun | 43 ++++++++++++++++++- 8 files changed, 125 insertions(+), 4 deletions(-) mode change 100644 => 100755 examples/debug_reporting.fun rename {extra/examples => examples/extra}/pcsc2_example.fun (100%) rename {extra/examples => examples/extra}/pcsc_demo.fun (100%) create mode 100755 examples/extra/tcp_echo_server.fun create mode 100755 examples/extra/tcp_echo_server_class.fun mode change 100644 => 100755 examples/repl_on_error.fun diff --git a/CMakeLists.txt b/CMakeLists.txt index fa9c46e..6731b83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.16) -project(fun VERSION 0.26.6 LANGUAGES C) +cmake_minimum_required(VERSION 3.5) +project(fun VERSION 0.27.0 LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/examples/debug_reporting.fun b/examples/debug_reporting.fun old mode 100644 new mode 100755 index 9abb9f8..4daa009 --- a/examples/debug_reporting.fun +++ b/examples/debug_reporting.fun @@ -1,4 +1,15 @@ -//!/usr/bin/env fun +#!/usr/bin/env fun + +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-10-06 + */ /* * Debugging and error reporting demo for Fun. diff --git a/extra/examples/pcsc2_example.fun b/examples/extra/pcsc2_example.fun similarity index 100% rename from extra/examples/pcsc2_example.fun rename to examples/extra/pcsc2_example.fun diff --git a/extra/examples/pcsc_demo.fun b/examples/extra/pcsc_demo.fun similarity index 100% rename from extra/examples/pcsc_demo.fun rename to examples/extra/pcsc_demo.fun diff --git a/examples/extra/tcp_echo_server.fun b/examples/extra/tcp_echo_server.fun new file mode 100755 index 0000000..6fb995c --- /dev/null +++ b/examples/extra/tcp_echo_server.fun @@ -0,0 +1,37 @@ +#!/usr/bin/env fun + +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-10-13 + */ + +// Simple TCP echo server using built-in socket ops. +// Listens on localhost:12345 and echoes a single line/request back to each client. + +port = 12345 +backlog = 16 + +listen_fd = tcp_listen(port, backlog) +if (listen_fd <= 0) + print("tcp_listen failed") + exit(1) + +print("Echo server listening on port " + to_string(port)) + +while (true) + client = tcp_accept(listen_fd) + if (client > 0) + data = sock_recv(client, 4096) + if (len(data) > 0) + // Echo back exactly what we received + sock_send(client, data) + sock_close(client) + +// Not reached in this example, but here for completeness +sock_close(listen_fd) diff --git a/examples/extra/tcp_echo_server_class.fun b/examples/extra/tcp_echo_server_class.fun new file mode 100755 index 0000000..1be9385 --- /dev/null +++ b/examples/extra/tcp_echo_server_class.fun @@ -0,0 +1,32 @@ +#!/usr/bin/env fun + +/* + * This file is part of the Fun programming language. + * https://fun-lang.xyz/ + * + * Copyright 2025 Johannes Findeisen + * Licensed under the terms of the Apache-2.0 license. + * https://opensource.org/license/apache-2-0 + * + * Added: 2025-10-13 + */ + +// Echo server using the stdlib TcpServer class. +// Make sure FUN_LIB_DIR points to the ./lib directory containing io/socket.fun. +// Example: +// FUN_LIB_DIR="$(pwd)/lib" ./build/fun ./examples/tcp_echo_server_class.fun + +include + +print("Starting echo server at localhost:12345") + +server = TcpServer(12345, 16) + +if (server.listen() <= 0) + print("Listen failed!") + exit(1) +else + print("Echo server (class) listening on port 12345") + +// Serve clients forever, echoing back what they send. +server.serve_forever(4096) diff --git a/examples/repl_on_error.fun b/examples/repl_on_error.fun old mode 100644 new mode 100755 diff --git a/lib/io/socket.fun b/lib/io/socket.fun index 10d1630..0f3d848 100644 --- a/lib/io/socket.fun +++ b/lib/io/socket.fun @@ -25,7 +25,6 @@ * print(resp) * c.close() */ - class TcpClient() // file descriptor or 0 if not connected fd = 0 @@ -72,6 +71,48 @@ class TcpClient() this.fd = 0 return 1 +// TcpServer: simple wrapper around TCP socket built-ins. +// Exposes listen(), accept(), echo_once(maxlen), serve_forever(maxlen), close(). +class TcpServer(number port, number backlog) + + fun _construct(this, port, backlog) + this.port = port + this.backlog = backlog + this.listen_fd = 0 + + fun listen(this) + this.listen_fd = tcp_listen(this.port, this.backlog) + return this.listen_fd + + fun accept(this) + return tcp_accept(this.listen_fd) + + fun close(this) + if (this.listen_fd > 0) + sock_close(this.listen_fd) + this.listen_fd = 0 + + fun echo_once(this, maxlen) + c = this.accept() + if (c <= 0) + return 0 + + data = sock_recv(c, maxlen) + if (len(data) > 0) + sock_send(c, data) + + sock_close(c) + return 1 + + fun serve_forever(this, maxlen) + if (this.listen_fd <= 0) + if (this.listen() <= 0) + print("TcpServer: listen failed on port " + to_string(this.port)) + return 0 + print("TcpServer: listening on port " + to_string(this.port)) + while (true) + this.echo_once(maxlen) + class UnixClient() fd = 0