#include #include #include #include #include #include #include #include #include "util.h" #include "sia.h" extern int new_block (int fd, SIA_Block *b, int log, const char *email, const char *state_file, const char *mqtt_host); extern void periodic_task (void); extern void dump_state (const char *); static int usage (const char *name) { fprintf (stderr, "Usage:\n"); fprintf (stderr, "%s [ -l ] [ -p listen_port ] [ -e email address] [ -s state_file ] [ -m mqtt_host ]\n\n", name); fprintf (stderr, "listen_port defaults to 10002\n"); return 1; } #define TICK 5 int main (int argc, char *argv[]) { int port = 10002; unsigned opt; int fd; int afd = -1; SIA_Block b; struct timeval tv = {0}; int log = 0; unsigned char buf[SIA_MAX_BLOCK_LENGTH]; unsigned ptr = 0; const char *email = NULL; const char *state_file = NULL; const char *mqtt_host = NULL; while ((opt = getopt (argc, argv, "p:le:s:m:")) != -1) { switch (opt) { case 'p': port = atoi (optarg); break; case 'l': log++; break; case 'e': email = optarg; break; case 's': state_file = optarg; break; case 'm': mqtt_host = optarg; break; default: /* '?' */ return usage (argv[0]); } } if (log) openlog ("net_rx", 0, LOG_USER); fd = open_tcp_server (port); if (fd < 0) { perror ("open socket"); return -1; } set_blocking (fd); if (state_file) dump_state (state_file); // Epically budget TCP server tv.tv_sec = TICK; for (;;) { fd_set rfds; int rc; FD_ZERO (&rfds); FD_SET (fd, &rfds); if (afd > 0) FD_SET (afd, &rfds); rc = select (afd > fd ? afd + 1 : fd + 1, &rfds, NULL, NULL, &tv); if (!rc) periodic_task(); if (!tv.tv_sec && !tv.tv_usec) tv.tv_sec = TICK; if (FD_ISSET (fd, &rfds)) { if (afd > 0) close (afd); afd = accept (fd, NULL, NULL); ptr = 0; } if ((afd > 0) && (FD_ISSET (afd, &rfds))) { if (read (afd, &buf[ptr], 1) != 1) { close (afd); afd = -1; ptr = 0; continue; } ptr++; switch (sia_parse (buf, ptr, &b)) { case -1: /*Parse errror, form here is top drop connexion*/ close (afd); afd = -1; break; case 0: /*More data needed*/ break; default: /*Valid block */ new_block (afd, &b, log, email, state_file, mqtt_host); ptr = 0; break; } if (ptr == SIA_MAX_BLOCK_LENGTH) { close (afd); afd = -1; } } } }