aboutsummaryrefslogtreecommitdiff
path: root/bikewedge/software/RetoolingForOpenSprints/serproxy-0.1.3.src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'bikewedge/software/RetoolingForOpenSprints/serproxy-0.1.3.src/main.c')
-rw-r--r--bikewedge/software/RetoolingForOpenSprints/serproxy-0.1.3.src/main.c538
1 files changed, 538 insertions, 0 deletions
diff --git a/bikewedge/software/RetoolingForOpenSprints/serproxy-0.1.3.src/main.c b/bikewedge/software/RetoolingForOpenSprints/serproxy-0.1.3.src/main.c
new file mode 100644
index 0000000..2411920
--- /dev/null
+++ b/bikewedge/software/RetoolingForOpenSprints/serproxy-0.1.3.src/main.c
@@ -0,0 +1,538 @@
+/*
+ * main.c
+ *
+ * main module for serproxy
+ *
+ * (C)1999 Stefano Busti
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__UNIX__)
+# include <unistd.h>
+# include <fcntl.h>
+# include <sys/time.h>
+#elif defined(__WIN32__)
+# include <windows.h>
+# include <io.h>
+#endif
+
+#include "string.h"
+#include "sio.h"
+#include "sock.h"
+#include "pipe.h"
+#include "thread.h"
+#include "vlist.h"
+#include "cfglib.h"
+#include "config.h"
+#include "error.h"
+
+int readcfg(char *);
+void cleanup(void);
+int waitclients(void);
+thr_startfunc_t serve_pipe(void *data);
+void debug(void);
+
+#if defined(__UNIX__)
+char defcfgfile[] = "/etc/serproxy.cfg";
+#elif defined(__WIN32__)
+char defcfgfile[] = "serproxy.cfg";
+#endif
+
+cfg_s cfg;
+vlist_s pipes;
+
+int main(int argc, char **argv)
+{
+ char *cfgfile;
+
+ if (sock_start())
+ return -1;
+ vlist_init(&pipes, pipe_destroy);
+ cfg_init(&cfg, 0);
+ atexit(cleanup);
+
+ /* Look for the config file in the executable directory. Windows
+ * uses it as the working directory, so we can use a relative
+ * filename. On UNIX or the Mac, use the executable path and
+ * filename from argv[0].
+ */
+#ifdef __WIN32__
+ cfgfile = defcfgfile;
+#else
+ cfgfile = malloc(strlen(argv[0]) + 4 + 1);
+ strcpy(cfgfile, argv[0]);
+ strcat(cfgfile, ".cfg");
+#endif
+ /* Prefer a config file specified on the command line */
+ readcfg(argc > 1 ? argv[argc - 1] : cfgfile);
+#ifdef DEBUG
+ debug();
+#endif
+ waitclients();
+
+ return 0;
+}
+
+void cleanup(void)
+{
+ cfg_cleanup(&cfg);
+ vlist_cleanup(&pipes);
+ sock_finish();
+}
+
+int readcfg(char *cfgfile)
+{
+ char ports[BUFSIZ], *p;
+ int port;
+ pipe_s *pipe;
+ cfg_s local;
+ serialinfo_s sinfo;
+ char *parity, *newlines;
+
+ /* Read the global config settings */
+ cfg_fromfile(&cfg, cfgfile);
+
+ /* Read the comm port list */
+ if (cfg_readbuf(cfgfile, "comm_ports", ports, sizeof(ports)) == NULL)
+ errend("Couldn't find 'comm_ports' entry in config file '%s'", cfgfile);
+
+ vlist_clear(&pipes);
+
+ /* Parse the comm ports list */
+ p = strtok(ports, ",");
+ while (p)
+ {
+ if (sscanf(p, "%d", &port) > 0)
+ {
+ pipe = malloc(sizeof(pipe_s));
+ //pipe_init(pipe);
+ if (pipe == NULL)
+ perrend("malloc(pipe_s)");
+
+ cfg_init(&local, port);
+
+ /* Copy global settings to those for current pipe */
+ cfg_assign(&local, &cfg);
+
+ /* Set the comm port */
+ local.ints[CFG_IPORT].val = port;
+
+ /* Load this pipe's config */
+ cfg_fromfile(&local, cfgfile);
+
+ /* Try initializing the pipe */
+ if (pipe_init(pipe, local.ints[CFG_INETPORT].val))
+ perrend("pipe_init");
+
+ /* Copy over the rest of the pipe's config */
+ pipe->timeout = local.ints[CFG_ITIMEOUT].val;
+ serialinfo_init(&sinfo);
+ sinfo.port = port;
+ sinfo.baud = local.ints[CFG_IBAUD].val;
+ sinfo.stopbits = local.ints[CFG_ISTOP].val;
+ sinfo.databits = local.ints[CFG_IDATA].val;
+ str_assign(&sinfo.device, local.strs[CFG_SDEVICE].val);
+
+ parity = local.strs[CFG_SPARITY].val;
+
+ if (strcmp(parity, "none") == 0)
+ {
+ sinfo.parity = SIO_PARITY_NONE;
+ }
+ else if (strcmp(parity, "even") == 0)
+ {
+ sinfo.parity = SIO_PARITY_EVEN;
+ }
+ else if (strcmp(parity, "odd") == 0)
+ {
+ sinfo.parity = SIO_PARITY_ODD;
+ }
+ else
+ {
+ errend("Unknown parity string '%s'", parity);
+ }
+
+ newlines = local.strs[CFG_SNEWLINES].val;
+
+ if (strcmp(newlines, "true") == 0)
+ {
+ pipe->newlines = 1;
+ }
+ else if (strcmp(newlines, "false") == 0)
+ {
+ pipe->newlines = 0;
+ }
+ else
+ {
+ errend("Unknown value '%s' for newlines to nils (must be 'true' or 'false')", newlines);
+ }
+
+ if (sio_setinfo(&pipe->sio, &sinfo))
+ errend("Unable to configure comm port %d", port);
+
+ /* Finally add the pipe to the pipes list */
+ vlist_add(&pipes, pipes.tail, pipe);
+
+ serialinfo_cleanup(&sinfo);
+
+ cfg_cleanup(&local);
+ }
+
+ p = strtok(NULL, ",");
+ }
+
+ /* Clean up local cfg struct */
+ cfg_cleanup(&local);
+
+ return 0;
+}
+
+int waitclients(void)
+{
+ int fd_max;
+ fd_set fds;
+ vlist_i *it;
+ pipe_s *pit, *newpipe;
+ tcpsock_s *newsock;
+ thr_t thread;
+
+ fd_max = 0;
+ FD_ZERO(&fds);
+
+ /* Set all sockets to listen */
+ for (it = pipes.head; it; it = it->next)
+ {
+ pit = (pipe_s *)it->data;
+
+ if (tcp_listen(&pit->sock))
+ perror("waitclients() - tcp_listen()");
+ }
+
+ printf("Serproxy - (C)1999 Stefano Busti, (C)2005 David A. Mellis - Waiting for clients\n");
+
+ while (1)
+ {
+ /* Iterate through the pipe list */
+ for (it = pipes.head; it; it = it->next)
+ {
+ pit = (pipe_s *)it->data;
+
+ /* Monitor socket fd of each */
+ FD_SET(pit->sock.fd, &fds);
+
+ /* Track max fd */
+ if (pit->sock.fd > fd_max)
+ fd_max = pit->sock.fd;
+ }
+
+ /* Wait for a read ( == accept() in this case) */
+ if (select(fd_max + 1, &fds, NULL, NULL, NULL) == -1)
+ perrend("waitclients() - select()");
+
+
+ /* Find which sockets are involved */
+ for (it = pipes.head; it; it = it->next)
+ {
+ pit = (pipe_s *)it->data;
+
+ if (FD_ISSET(pit->sock.fd, &fds))
+ {
+ /* Create a new pipe struct for the new thread */
+ newpipe = malloc(sizeof(pipe_s));
+ if (!newpipe)
+ perrend("waitclients() - malloc(pipe_s)");
+
+ sio_init(&newpipe->sio);
+ sio_assign(&newpipe->sio, &pit->sio);
+
+ /* Try to open serial port */
+ if (sio_open(&newpipe->sio))
+ {
+ tcp_refuse(&pit->sock);
+ error("Failed to open comm port - connection refused");
+ free(newpipe);
+ continue;
+ }
+
+ /* Accept the connection */
+ newsock = tcp_accept(&pit->sock);
+
+ /* All ok? */
+ if (newsock)
+ {
+ newpipe->sock = *newsock;
+ free(newsock);
+
+ newpipe->newlines = pit->newlines;
+ newpipe->timeout = pit->timeout;
+ newpipe->mutex = pit->mutex;
+
+ /* Create the server thread */
+ if (thr_create(&thread, 1, serve_pipe, newpipe))
+ {
+ error("Feck - thread creation failed");
+ free(newpipe);
+ }
+ else
+ {
+ fprintf(stderr, "Server thread launched\n");
+ }
+ }
+ else
+ {
+ perror("waitclients() - accept()");
+ free(newpipe);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* Main routine for the server threads */
+thr_startfunc_t serve_pipe(void *data)
+{
+ char sio_buf[BUFSIZ], sock_buf[BUFSIZ];
+ int fd_max, sio_fd, sock_fd;
+ int sio_count, sock_count;
+ int res, port;
+ int i;
+ fd_set rfds, wfds;
+ pipe_s *pipe = (pipe_s *)data;
+#if defined(__UNIX__)
+ struct timeval tv = {pipe->timeout, 0};
+ struct timeval *ptv = &tv;
+#elif defined(__WIN32__)
+ struct timeval tv = {0,10000};
+ struct timeval *ptv = &tv;
+ DWORD msecs = 0, timeout = pipe->timeout * 1000;
+#endif
+
+ port = pipe->sio.info.port;
+
+ /* Only proceed if we can lock the mutex */
+ if (thr_mutex_trylock(pipe->mutex))
+ {
+ error("server(%d) - resource is locked", port);
+ }
+ else
+ {
+
+ sio_count = 0;
+ sock_count = 0;
+ sio_fd = pipe->sio.fd;
+ sock_fd = pipe->sock.fd;
+#if defined(__UNIX__)
+ fd_max = sio_fd > sock_fd ? sio_fd : sock_fd;
+#elif defined(__WIN32__)
+ fd_max = sock_fd;
+ msecs = GetTickCount();
+#endif
+ fprintf(stderr, "server(%d) - thread started\n", port);
+
+ while (1)
+ {
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+
+#if defined(__UNIX__)
+ /* Always ask for read notification to check for EOF */
+ FD_SET(sio_fd, &rfds);
+ /* Only ask for write notification if we have something to write */
+ if (sock_count > 0)
+ FD_SET(sio_fd, &wfds);
+
+ /* Reset timeout values */
+ tv.tv_sec = pipe->timeout;
+ tv.tv_usec = 0;
+
+#endif
+ /* Always ask for read notification to check for EOF */
+ FD_SET(sock_fd, &rfds);
+ /* Only ask for write notification if we have something to write */
+ if (sio_count > 0)
+ FD_SET(sock_fd, &wfds);
+
+ //DBG_MSG2("server(%d) waiting for events", port);
+
+ /* Wait for read/write events */
+ res = select(fd_max + 1, &rfds, &wfds, NULL, ptv);
+ if (res == -1)
+ {
+ perror2("server(%d) - select()", port);
+ break;
+ }
+#if defined(__UNIX__)
+
+ /* Use the select result for timeout detection */
+ if (res == 0)
+ {
+ fprintf(stderr, "server(%d) - timed out\n", port);
+ break;
+ }
+
+ /* Input from serial port? */
+ if (FD_ISSET(sio_fd, &rfds))
+#elif defined(__WIN32__)
+
+ if (1)
+#endif
+ {
+ /* Only read input if buffer is empty */
+ if (sio_count == 0)
+ {
+ sio_count = sio_read(&pipe->sio, sio_buf, sizeof(sio_buf));
+ if (sio_count <= 0)
+ {
+ if (sio_count == 0)
+ {
+#if defined(__UNIX__)
+ fprintf(stderr, "server(%d) - EOF from sio\n", port);
+ break;
+#endif
+ }
+ else
+ {
+ perror2("server(%d) - read(sio)", port);
+ break;
+ }
+ }
+ else
+ {
+ DBG_MSG3("server(%d) - read %d bytes from sio", port, sio_count);
+ }
+ }
+ }
+
+ if (pipe->newlines)
+ {
+ /* Replace incoming newlines with nils. */
+ for (i = 0; i < sio_count; i++)
+ {
+ if (sio_buf[i] == '\n')
+ sio_buf[i] = 0;
+ }
+ }
+
+ /* Write to socket possible? */
+ if (FD_ISSET(sock_fd, &wfds))
+ {
+ if (sio_count > 0)
+ {
+ if ((res = tcp_write(&pipe->sock, sio_buf, sio_count)) < 0)
+ {
+ perror2("server(%d) - write(sock)", port);
+ break;
+ }
+ DBG_MSG3("server(%d) - Wrote %d bytes to sock", port, res);
+ sio_count -= res;
+ }
+ }
+
+
+ /* Input from socket? */
+ if (FD_ISSET(sock_fd, &rfds))
+ {
+ /* Only read input if buffer is empty */
+ if (sock_count == 0)
+ {
+ sock_count = tcp_read(&pipe->sock, sock_buf, sizeof(sock_buf));
+ if (sock_count <= 0)
+ {
+ if (sock_count == 0)
+ {
+ fprintf(stderr, "server(%d) - EOF from sock\n", port);
+ break;
+ }
+ else
+ {
+ perror2("server(%d) - read(sock)", port);
+ break;
+ }
+ }
+ DBG_MSG3("server(%d) - read %d bytes from sock", port, sock_count);
+ }
+ }
+
+#if defined(__UNIX__)
+ /* Write to serial port possible? */
+ if (FD_ISSET(sio_fd, &wfds))
+#elif defined(__WIN32__)
+
+ /* No socket IO performed? */
+ if ((!FD_ISSET(sock_fd, &rfds)) && (!FD_ISSET(sock_fd, &wfds)))
+ {
+ /* Break on a time out */
+ if (GetTickCount() - msecs > timeout)
+ {
+ fprintf(stderr, "server(%d) - timed out\n", port);
+ break;
+ }
+ }
+ else
+ {
+ msecs = GetTickCount();
+ }
+
+ if (1)
+#endif
+ {
+ if (sock_count > 0)
+ {
+ if ((res = sio_write(&pipe->sio, sock_buf, sock_count)) < 0)
+ {
+ perror2("server(%d) - write(sio)", port);
+ break;
+ }
+ DBG_MSG3("server(%d) - wrote %d bytes to sio", port, res);
+ sock_count -= res;
+ }
+ }
+
+ }
+
+ /* Unlock our mutex */
+ thr_mutex_unlock(pipe->mutex);
+ }
+
+ fprintf(stderr, "server(%d) exiting\n", port);
+
+ /* Clean up - don't call pipe_cleanup() as that would nuke our mutex */
+ sio_cleanup(&pipe->sio);
+ tcp_cleanup(&pipe->sock);
+
+
+ free(pipe);
+
+ thr_exit((thr_exitcode_t)0);
+
+ return (thr_exitcode_t)0;
+}
+
+void debug(void)
+{
+ vlist_i *it;
+ pipe_s *pit;
+ int i = 1;
+
+ fprintf(stderr, "pipes:\n\n");
+ vlist_debug(&pipes, stderr);
+
+ for (it = pipes.head; it; it = it->next)
+ {
+ pit = (pipe_s *)it->data;
+
+ fprintf(stderr, "sio[%d]:\n\n", i);
+ sio_debug(&pit->sio, stderr);
+
+ fprintf(stderr, "sock[%d]:\n\n", i);
+ tcp_debug(&pit->sock, stderr);
+
+ i++;
+ }
+}