#include "./common.h" const uint32_t TCPALIVE_IDLE_TIME = 3; const uint32_t TCPALIVE_CHECK_INTVL = 1; const uint32_t TCPALIVE_CHECK_CNT = 2; struct sockaddr_in* get_addr(const char* addr, const char* port) { struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; struct addrinfo* res; if (getaddrinfo(addr, port, &hints, &res) != 0) { fprintf(stderr, "[client_create_socket] Unable to call getaddrinfo()\n"); exit(EXIT_FAILURE); } if (res->ai_next != NULL) { fprintf(stderr, "[client_create_socket] Ambigous result of getaddrinfo()\n"); exit(EXIT_FAILURE); } struct sockaddr_in* result = calloc(1, sizeof(*result)); memcpy(result, res->ai_addr, sizeof(*res->ai_addr)); freeaddrinfo(res); return result; } void conn_close(conn_t* conn) { if (close(conn->conn_socket_fd) == -1) { fprintf(stderr, "[conn_close] Unable to close connection socket\n"); exit(EXIT_FAILURE); } } int conn_configure_tcpalive(conn_t* conn) { int setsockopt_arg = 1; if (setsockopt(conn->conn_socket_fd, SOL_SOCKET, SO_KEEPALIVE, &setsockopt_arg, sizeof(setsockopt_arg)) == -1) { return -1; } struct timeval tv = { .tv_sec = TCPALIVE_IDLE_TIME, }; if (setsockopt(conn->conn_socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { return -1; } setsockopt_arg = TCPALIVE_IDLE_TIME; if (setsockopt(conn->conn_socket_fd, IPPROTO_TCP, TCP_KEEPIDLE, &setsockopt_arg, sizeof(setsockopt_arg)) == -1) { return -1; } setsockopt_arg = TCPALIVE_CHECK_INTVL; if (setsockopt(conn->conn_socket_fd, IPPROTO_TCP, TCP_KEEPINTVL, &setsockopt_arg, sizeof(setsockopt_arg)) == -1) { return -1; } setsockopt_arg = TCPALIVE_CHECK_CNT; if (setsockopt(conn->conn_socket_fd, IPPROTO_TCP, TCP_KEEPCNT, &setsockopt_arg, sizeof(setsockopt_arg)) == -1) { return -1; } return 1; } char* conn_read(conn_t* conn, size_t* size) { size_t sz; size_t n = recv(conn->conn_socket_fd, &sz, sizeof(sz), 0); if (n == 0) { *size = 0; return NULL; } if (n != sizeof(sz)) { fprintf(stderr, "[conn_read] Failed to read size of msg %lu %d\n", n, errno); exit(EXIT_FAILURE); } char* buf = calloc(sz, sizeof(*buf)); n = recv(conn->conn_socket_fd, buf, sz, MSG_WAITALL); if ((size_t) n != sz) { fprintf(stderr, "[conn_read] Failed to read msg\n"); exit(EXIT_FAILURE); } *size = sz; return buf; } void conn_write(conn_t* conn, const char* value, size_t sz) { size_t n = send(conn->conn_socket_fd, &sz, sizeof(sz), MSG_MORE); if (n != sizeof(sz)) { fprintf(stderr, "[conn_write] Failed to write size of msg\n"); exit(EXIT_FAILURE); } n = send(conn->conn_socket_fd, value, sz, 0); if (n != sz) { fprintf(stderr, "[conn_write] Failed to write msg\n"); exit(EXIT_FAILURE); } }