From 914ac748b96ec98aba6acebded790cb8954ecc0e Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Thu, 17 Nov 2016 23:44:42 +1000 Subject: [PATCH] * add draft of source/mcast --- src/sources/mcast.c | 162 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 src/sources/mcast.c diff --git a/src/sources/mcast.c b/src/sources/mcast.c new file mode 100644 index 0000000..f55e698 --- /dev/null +++ b/src/sources/mcast.c @@ -0,0 +1,162 @@ +/* Copyright 2016 Alex 'AdUser' Z (ad_user@runbox.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "source.h" + +#include +#include +#include +#include +#include +#include + +#define DEFAULT_MCAST_ADDR "239.255.186.1" +#define DEFAULT_MCAST_PORT 3370 + +struct _config { + char name[32]; + char error[256]; + void (*errcb)(char *errstr); + char addr[INET_STRADDRLEN]; + char iface[16]; + uint16_t port; + int sock; +}; + +static void +errcb_stub(char *str) { + assert(str != NULL); + (void)(str); +} + +cfg_t * +create(const char *init) { + cfg_t *cfg = NULL; + assert(init != NULL); + if ((cfg = calloc(1, sizeof(cfg_t))) == NULL) + return NULL; + strlcpy(cfg->name, init, sizeof(cfg->name)); + strlcpy(cfg->addr, DEFAULT_MCAST_ADDR, sizeof(cfg->addr)); + cfg->port = DEFAULT_MCAST_PORT; + cfg->errcb = &errcb_stub; + return cfg; +} + +bool +config(cfg_t *cfg, const char *key, const char *value) { + assert(cfg != NULL); + assert(key != NULL); + assert(value != NULL); + + if (strcmp(key, "address") == 0) { + if (strncmp(value, "239.255.", 8) != 0) { + strlcpy(cfg->error, "mcast address should be inside 239.255.0.0/16 block"); + return false; + } + strlcpy(cfg->addr, value, sizeof(cfg->addr)); + return true; + } + if (strcmp(key, "port") == 0) { + cfg->port = atoi(value); + return true; + } + if (strcmp(key, "iface") == 0) { + strlcpy(cfg->iface, value, sizeof(cfg->iface)); + return true; + } + + return false; +} + +bool +ready(cfg_t *cfg) { + assert(cfg != NULL); + + if (cfg->addr[0] != '\0') + return true; + + return false; +} + +char * +error(cfg_t *cfg) { + assert(cfg != NULL); + + return cfg->error; +} + +void +errcb(cfg_t *cfg, void (*cb)(char *errstr)) { + assert(cfg != NULL); + assert(cb != NULL); + + cfg->errcb = cb; +} + +bool +start(cfg_t *cfg) { + struct addrinfo hints; + struct addrinfo *result; + int opt; + + assert(cfg != NULL); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = 0; + + int ret = getaddrinfo(cfg->addr, cfg->port, &hints, &result); + for (struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next) { + cfg->sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (cfg->sock == -1) + continue; + if ((opt = fcntl(cfg->sock, F_GETFL, 0)) < 0) + continue; + fcntl(cfg->sock, F_SETFL, opt | O_NONBLOCK); + opt = 1; + setsockopt(cfg->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + if (connect(cfg->sock, rp->ai_addr, rp->ai_addrlen) == 0) { + break; /* success */ + } + freeaddrinfo(result); + + /* setsockopt -- socket(7) -- SO_BINDTODEVICE */ + + if (cfg->sock < 0) { + snprintf(cfg->error, sizeof(cfg->error), "can't bind to %s:%s", cfg->host, cfg->port); + return false; + } + + /* TODO */ + return true; +} + +bool +stop(cfg_t *cfg) { + assert(cfg != NULL); + + /* TODO */ + return true; +} + +bool +next(cfg_t *cfg, char *buf, size_t bufsize, bool reset) { + assert(cfg != NULL); + assert(buf != NULL); + assert(bufsize > 0); + + /* TODO */ + return false; +} + +void +destroy(cfg_t *cfg) { + f2b_port_t *next; + assert(cfg != NULL); + + free(cfg); +}