diff options
| -rw-r--r-- | main.c | 58 | 
1 files changed, 54 insertions, 4 deletions
| @@ -15,10 +15,14 @@   * along with receiver.  If not, see <https://www.gnu.org/licenses/>.   */ +#include <arpa/inet.h>  #include <errno.h> +#include <netinet/in.h> +#include <netinet/tcp.h>  #include <poll.h>  #include <signal.h>  #include <stddef.h> +#include <stdint.h>  #include <stdio.h>  #include <stdlib.h>  #include <string.h> @@ -31,6 +35,48 @@  static volatile sig_atomic_t g_signal;  static void OnSignal(int status) { g_signal = status; } +static void SocketDtor(int* sock) { +  if (*sock == -1) return; +  close(*sock); +  *sock = -1; +} + +static int ConnectSocket(const char* arg) { +  uint16_t port; +  char ip[sizeof("xxx.xxx.xxx.xxx")]; +  if (sscanf(arg, "%[0-9.]:%hu", ip, &port) != 2) { +    LOG("Failed to parse address"); +    return -1; +  } + +  int sock = socket(AF_INET, SOCK_STREAM, 0); +  if (sock == -1) { +    LOG("Failed to create socket (%s)", strerror(errno)); +    return -1; +  } +  static const int one = 1; +  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one))) { +    LOG("Failed to set TCP_NODELAY (%s)", strerror(errno)); +    goto rollback_sock; +  } + +  // TODO(mburakov): Set and maintain TCP_QUICKACK. +  const struct sockaddr_in addr = { +      .sin_family = AF_INET, +      .sin_port = htons(port), +      .sin_addr.s_addr = inet_addr(ip), +  }; +  if (connect(sock, (const struct sockaddr*)&addr, sizeof(addr))) { +    LOG("Failed to connect socket (%s)", strerror(errno)); +    goto rollback_sock; +  } +  return sock; + +rollback_sock: +  close(sock); +  return -1; +} +  static void OnWindowClose(void* user) {    (void)user;    g_signal = SIGINT; @@ -53,8 +99,12 @@ static void DecodeContextDtor(struct DecodeContext** decode_context) {  }  int main(int argc, char* argv[]) { -  (void)argc; -  (void)argv; +  if (argc < 2) { +    LOG("Usage: %s <ip>:<port>", argv[0]); +    return EXIT_FAILURE; +  } +  int __attribute__((cleanup(SocketDtor))) sock = ConnectSocket(argv[1]); +  if (sock == -1) return EXIT_FAILURE;    static const struct WindowEventHandlers window_event_handlers = {        .OnClose = OnWindowClose, @@ -89,7 +139,7 @@ int main(int argc, char* argv[]) {    while (!g_signal) {      struct pollfd pfds[] = { -        {.fd = STDIN_FILENO, .events = POLLIN}, +        {.fd = sock, .events = POLLIN},          {.fd = events_fd, .events = POLLIN},      };      switch (poll(pfds, LENGTH(pfds), -1)) { @@ -104,7 +154,7 @@ int main(int argc, char* argv[]) {        default:          break;      } -    if (pfds[0].revents && !DecodeContextDecode(decode_context, STDIN_FILENO)) { +    if (pfds[0].revents && !DecodeContextDecode(decode_context, sock)) {        LOG("Failed to decode incoming data");        return EXIT_FAILURE;      } | 
