diff --git a/apps/EchoServer.cpp b/apps/EchoServer.cpp index 8c1e8e722665bd676e455bd3b17dc64b2d97496c..e0c96ef13f18961e94533e9c0cd6db25fb3f4563 100644 --- a/apps/EchoServer.cpp +++ b/apps/EchoServer.cpp @@ -1,5 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020-2021 Florian Fischer +#include <sys/socket.h> #include <sys/types.h> #include <cerrno> @@ -9,17 +10,16 @@ #include <string> #include "Common.hpp" +#include "Debug.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; +const std::string HOST = "::"; +const std::string PORT = "12345"; auto main(int argc, char* argv[]) -> int { - int port = PORT; std::string host = HOST; + std::string port = PORT; if (argc > 2) { std::cerr << "Usage: " << argv[0] << " [port]" << std::endl; @@ -27,9 +27,7 @@ auto main(int argc, char* argv[]) -> int { } if (argc > 1) { - long aport = strtol(argv[1], nullptr, DECIMAL); - assert(aport <= INT_MAX && aport >= INT_MIN); - port = (int)aport; + port = std::string(argv[1]); } std::cout << "Echoserver listening on " << host << ":" << port << std::endl; diff --git a/emper/io.hpp b/emper/io.hpp index 4addc610e9c80b0b7132736ae78a1471ef85cd61..10b228781b31067b7ed3b74ea391816372e8f01e 100644 --- a/emper/io.hpp +++ b/emper/io.hpp @@ -466,6 +466,6 @@ inline void closeAndForget(int fd) { * * @return nullptr on error, otherwise the TCP listener Fiber */ -auto tcp_listener(std::string &host, int &port, const std::function<void(int)> &handler, +auto tcp_listener(std::string &host, std::string &port, const std::function<void(int)> &handler, int backlog = 1024) -> Fiber *; } // namespace emper::io diff --git a/emper/io/io.cpp b/emper/io/io.cpp index 140f91c9513cb84e1e3695fbeaec3997d0b062b9..83c1abeb739c090179b8a6e8eeb1c79b8065e7b7 100644 --- a/emper/io/io.cpp +++ b/emper/io/io.cpp @@ -2,8 +2,7 @@ // Copyright © 2020-2021 Florian Fischer #include "io.hpp" -#include <arpa/inet.h> -#include <netinet/in.h> +#include <netdb.h> #include <sys/socket.h> #include <cerrno> @@ -19,23 +18,28 @@ #endif namespace emper::io { -auto tcp_listener(std::string& host, int& port, const std::function<void(int)>& handler, +auto tcp_listener(std::string& host, std::string& port, const std::function<void(int)>& handler, int backlog) -> Fiber* { int listen_socket; - struct sockaddr_in servaddr; + struct addrinfo* servaddr; + + int err = getaddrinfo(host.c_str(), port.c_str(), nullptr, &servaddr); + if (err) { + if (err == EAI_SYSTEM) { + LOGE("getaddrinfo failed: " << strerror(errno)); + return nullptr; + } + + LOGE("error in getaddrinfo: " << gai_strerror(err)); + return nullptr; + } // socket creation and verification - listen_socket = socket(AF_INET, SOCK_STREAM, 0); + listen_socket = socket(servaddr->ai_family, servaddr->ai_socktype, servaddr->ai_protocol); if (listen_socket == -1) { LOGE("listen socket creation failed: " << strerror(errno)); return nullptr; } - memset(&servaddr, 0, sizeof(servaddr)); - - // assign IP, PORT - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = inet_addr(host.c_str()); - servaddr.sin_port = htons(port); int reuseaddr = 1; if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) == -1) { @@ -43,7 +47,7 @@ auto tcp_listener(std::string& host, int& port, const std::function<void(int)>& return nullptr; } - if (bind(listen_socket, (sockaddr*)&servaddr, sizeof(servaddr)) == -1) { + if (bind(listen_socket, servaddr->ai_addr, servaddr->ai_addrlen) == -1) { LOGE("bind failed: " << strerror(errno)); return nullptr; } diff --git a/tests/ConcurrentNetworkEchoTest.cpp b/tests/ConcurrentNetworkEchoTest.cpp index 0ccfddabd741ac38be3ecad82dbaa08826f6f35a..3a2583c3cc1ac5294ace91244414ab4214962eb0 100644 --- a/tests/ConcurrentNetworkEchoTest.cpp +++ b/tests/ConcurrentNetworkEchoTest.cpp @@ -13,7 +13,6 @@ #include "fixtures/network.hpp" #include "io.hpp" -#define PORT 4241 #define BUF_SIZE 1024 auto main(int argc, char* argv[]) -> int { @@ -23,7 +22,7 @@ auto main(int argc, char* argv[]) -> int { unsigned int client_count = 10; unsigned int echos = 1000; - int port = PORT; + std::string port = "4241"; std::string host = "127.0.0.1"; if (argc > 3) { @@ -50,7 +49,7 @@ auto main(int argc, char* argv[]) -> int { spawn( [&] { const std::vector<std::string> msgs = {"foo"}; - echo_client("127.0.0.1", PORT, msgs, echos); + echo_client(host, port, msgs, echos); }, cps); } diff --git a/tests/SimpleDiskAndNetworkTest.cpp b/tests/SimpleDiskAndNetworkTest.cpp index 60a2e569580ac658e8ad878fe4d4393f2039e102..182bcdbfce52463de6d2850aaa299f87e51131e6 100644 --- a/tests/SimpleDiskAndNetworkTest.cpp +++ b/tests/SimpleDiskAndNetworkTest.cpp @@ -170,7 +170,9 @@ void emperTest() { spawn( [] { const std::vector<std::string> msgs{"foo", "bar"}; - echo_client("127.0.0.1", PORT, msgs); + std::string port = std::to_string(PORT); + std::string host("127.0.0.1"); + echo_client(host, port, msgs); }, cps); diff --git a/tests/SimpleNetworkTest.cpp b/tests/SimpleNetworkTest.cpp index 3515862506fe6ebafc4d78fe3785d3f502419dd1..d3161bc5166dd2a51febe2c06ba67a7e613ce380 100644 --- a/tests/SimpleNetworkTest.cpp +++ b/tests/SimpleNetworkTest.cpp @@ -9,17 +9,18 @@ #include "io.hpp" // for tcp_listener #define MAX 1024 -int PORT = 4242; -std::string ADDR = "127.0.0.1"; void emperTest() { + std::string port = "4242"; + std::string addr = "127.0.0.1"; + CPS cps; - async(emper::io::tcp_listener(ADDR, PORT, echo_serve)); + async(emper::io::tcp_listener(addr, port, echo_serve)); spawn( - [] { + [&] { const std::vector<std::string> strings = {"foo", "bar", std::string(MAX, 'a'), "quit\n"}; - echo_client(ADDR.c_str(), PORT, strings); + echo_client(addr, port, strings); }, cps); diff --git a/tests/fixtures/network.cpp b/tests/fixtures/network.cpp index 97858086292faeb42e314308209f90ef53b86e52..7ca1c6ce7b15585d6815c306b57816cd9d5e3835 100644 --- a/tests/fixtures/network.cpp +++ b/tests/fixtures/network.cpp @@ -2,17 +2,18 @@ // Copyright © 2020-2021 Florian Fischer #include "network.hpp" -#include <arpa/inet.h> -#include <netinet/in.h> +#include <netdb.h> #include <sys/socket.h> #include <sys/types.h> #include <cassert> #include <cstdlib> #include <cstring> +#include <ostream> #include <vector> #include "Common.hpp" +#include "Debug.hpp" #include "io.hpp" #define MAX 1024 @@ -47,22 +48,26 @@ void echo_serve(int client_socket) { } } -void echo_client(const char* addr, int port, const std::vector<std::string>& msgs, +void echo_client(std::string& host, std::string& port, const std::vector<std::string>& msgs, size_t iterations) { - int sockfd = socket(AF_INET, SOCK_STREAM, 0); + struct addrinfo* server; + + int err = getaddrinfo(host.c_str(), port.c_str(), nullptr, &server); + if (err) { + if (err == EAI_SYSTEM) { + DIE_MSG_ERRNO("getaddrinfo failed"); + } else { + LOGE("error in getaddrinfo: " << gai_strerror(err)); + exit(EXIT_FAILURE); + } + } + + int sockfd = socket(server->ai_family, server->ai_socktype, server->ai_protocol); if (sockfd == -1) { DIE_MSG_ERRNO("client socket creation failed"); } - struct sockaddr_in server_addr; - // assign IP, PORT - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = inet_addr(addr); - server_addr.sin_port = htons(port); - - if (emper::io::connectAndWait(sockfd, reinterpret_cast<struct sockaddr*>(&server_addr), - sizeof(server_addr)) == -1) { + if (emper::io::connectAndWait(sockfd, server->ai_addr, server->ai_addrlen) == -1) { DIE_MSG_ERRNO("connect failed"); } diff --git a/tests/fixtures/network.hpp b/tests/fixtures/network.hpp index 271cb2d37375e7417f012d47a5f3ff0ef78d89dc..8c50c1532c6d2bb5c72a384804d61af7f0146336 100644 --- a/tests/fixtures/network.hpp +++ b/tests/fixtures/network.hpp @@ -8,5 +8,5 @@ void echo_serve(int client_socket); -void echo_client(const char* addr, int port, const std::vector<std::string>& msgs, +void echo_client(std::string& host, std::string& port, const std::vector<std::string>& msgs, size_t iterations = 1);