diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d9a0f9..f07cb83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,8 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ssl crypto) target_include_directories(${PROJECT_NAME} PRIVATE "${EXTERN}/openssl/include") # libevent +set(EVENT__DISABLE_TESTS ON CACHE BOOL "" FORCE) +set(EVENT__DISABLE_REGRESS ON CACHE BOOL "" FORCE) add_subdirectory("${EXTERN}/libevent") target_include_directories(${PROJECT_NAME} PRIVATE "${EXTERN}/libevent/include") diff --git a/server b/server new file mode 100755 index 0000000..f146051 Binary files /dev/null and b/server differ diff --git a/src/main.c b/src/main.c index 91d3640..69783d8 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -14,27 +15,17 @@ #include #include "log.h" -void -die(const char *errstr, ...) { - va_list ap; +#define DIE(...) do {\ + log_error(__VA_ARGS__); \ + exit(1); \ +} while(0) - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(1); -} -void -die_ssl(const char *errstr, ...) { - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - - ERR_print_errors_fp(stderr); - exit(1); -} +#define DIE_SSL(...) do {\ + log_error(__VA_ARGS__); \ + ERR_print_errors_fp(stderr); \ + exit(1); \ +} while(0) typedef struct { int fd; @@ -67,7 +58,7 @@ connect_tcp(char *hostname, char *port, int *clientfd) { hints.ai_flags = AI_PASSIVE; if ((rv = getaddrinfo(hostname, port, &hints, &res)) != 0) { - die("error getting address info: %s\n", gai_strerror(rv)); + DIE("error getting address info: %s\n", gai_strerror(rv)); } int fd; @@ -93,20 +84,72 @@ connect_tcp(char *hostname, char *port, int *clientfd) { return err; } + freeaddrinfo(res); - + *clientfd = fd; + return nullptr; } +// Returns error or nullptr char* -bind_tcp(char *port) { - +bind_tcp(char *port, int *bound_fd) { + int rv; + struct addrinfo hints, *res, *p; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + if ((rv = getaddrinfo(NULL, port, &hints, &res)) != 0) { + DIE("error getting address info: %s\n", gai_strerror(rv)); + } + + int fd; + char ip_str[INET6_ADDRSTRLEN]; + for (p = res; p != nullptr; p = p->ai_next) { + if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + inet_ntop(p->ai_family, get_in_addr(p->ai_addr), ip_str, sizeof(ip_str)); + log_warn("Failed to create a socket"); + close(fd); + continue; + } + + int yes = 1; + if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) != 0) { + log_warn("Unable to set SO_REUSEADDR on the socket"); + } + + + if ((rv = bind(fd, p->ai_addr, p->ai_addrlen))) { + inet_ntop(p->ai_family, get_in_addr(p->ai_addr), ip_str, sizeof(ip_str)); + log_warn("Failed to bind to %s:%s. %s", ip_str, port, strerror(errno)); + continue; + } + + inet_ntop(p->ai_family, get_in_addr(p->ai_addr), ip_str, sizeof(ip_str)); + log_info("Bound to %s:%s", ip_str, port); + break; + } + + if (p == nullptr) { + DIE("Failed to bind"); + } + + if ((listen(fd, 1)) == -1) { + DIE("listen: %s", strerror(errno)); + } + + *bound_fd = fd; + + return nullptr; } int main() { - + return 0; }