#include #include #include #include #include #include #include #include "util.h" #include "sia.h" void msg (char *account, char *event, char *ascii) { printf ("%s %64s %s\n", account, event, ascii); } static int new_block (int fd, SIA_Block *b) { static int have_ascii_messages = 0; /*SIA level 3 doesn't have ascii, SIA level 4 does */ static char account[SIA_MAX_DATA_LENGTH + 1]; static char event[SIA_MAX_DATA_LENGTH + 1]; static char ascii[SIA_MAX_DATA_LENGTH + 1]; unsigned len = sia_data_length (b); if (sia_ack_if_needed (fd, b)) return -1; switch (b->function) { case SIA_FN_ACCOUNT_ID: memcpy (account, b->data, len); account[len] = 0; break; case SIA_FN_NEW_EVENT: case SIA_FN_OLD_EVENT: memcpy (event, b->data, len); event[len] = 0; if (!have_ascii_messages) msg (account, event, ""); break; case SIA_FN_ASCII: have_ascii_messages = 1; memcpy (ascii, b->data, len); ascii[len] = 0; msg (account, event, ascii); break; } return 0; } static void periodic_task (void) { } static int usage (const char *name) { fprintf (stderr, "Usage:\n"); fprintf (stderr, "%s [ -p listen_port ]\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}; unsigned char buf[SIA_MAX_BLOCK_LENGTH]; unsigned ptr = 0; while ((opt = getopt (argc, argv, "p:")) != -1) { switch (opt) { case 'p': port = atoi (optarg); break; default: /* '?' */ return usage (argv[0]); } } fd = open_tcp_server (port); if (fd < 0) { perror ("open socket"); return -1; } set_blocking (fd); // 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); ptr = 0; break; } if (ptr == SIA_MAX_BLOCK_LENGTH) { close (afd); afd = -1; } } } }