# HG changeset patch # User Michiel Broek # Date 1400446603 -7200 # Node ID 24e731bb2e08c8173ca97c8a403f022bfc8184e3 # Parent 01b96a24ae7cf5e0a5a0c21fee85e6590a11d4fd Initial server code added diff -r 01b96a24ae7c -r 24e731bb2e08 lib/mbselib.h --- a/lib/mbselib.h Sun May 18 21:27:07 2014 +0200 +++ b/lib/mbselib.h Sun May 18 22:56:43 2014 +0200 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,8 @@ #include #include #include -#include +#include +#include #include @@ -68,6 +70,7 @@ char *name; /* Configuration name */ char *mosq_host; /* mosquitto server hostname */ int mosq_port; /* mosquitto server port */ + int my_port; /* my client/server port */ w1_therm *w1therms; /* 1-wire temp sensors */ #ifdef HAVE_WIRINGPI_H int lcd_cols; /* LCD display columns */ diff -r 01b96a24ae7c -r 24e731bb2e08 lib/rdconfig.c --- a/lib/rdconfig.c Sun May 18 21:27:07 2014 +0200 +++ b/lib/rdconfig.c Sun May 18 22:56:43 2014 +0200 @@ -90,6 +90,7 @@ free(tmp1); } Config.w1therms = NULL; + Config.my_port = 6554; #ifdef HAVE_WIRINGPI_H Config.lcd_cols = 16; diff -r 01b96a24ae7c -r 24e731bb2e08 thermferm/Makefile --- a/thermferm/Makefile Sun May 18 21:27:07 2014 +0200 +++ b/thermferm/Makefile Sun May 18 22:56:43 2014 +0200 @@ -54,7 +54,8 @@ # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT # Dependencies generated by make depend -thermferm.o: ../lib/mbselib.h thermferm.h mosquitto.h sensors.h +thermferm.o: ../lib/mbselib.h thermferm.h mosquitto.h sensors.h server.h sensors.o: ../lib/mbselib.h sensors.h mosquitto.o: ../lib/mbselib.h mosquitto.h +server.o: ../lib/mbselib.h server.h # End of generated dependencies diff -r 01b96a24ae7c -r 24e731bb2e08 thermferm/server.c --- a/thermferm/server.c Sun May 18 21:27:07 2014 +0200 +++ b/thermferm/server.c Sun May 18 22:56:43 2014 +0200 @@ -29,9 +29,19 @@ extern bool debug; extern int lcdHandle; extern unsigned char lcdbuf[MAX_LCDS][20][4]; +extern sys_config Config; +extern int clients; +int s; /* connected socket */ +int ls; /* listen socket */ -int sock = -1; +struct sockaddr_in myaddr_in; /* for local socket address */ +struct sockaddr_in peeraddr_in; /* for peer socket address */ + +struct hostent *hp; + +#define SS_BUFSIZE 1024 +#define SS_TIMEOUT 300 char *exe_cmd(char *); @@ -58,36 +68,244 @@ -void do_cmd(char *cmd) +int server_init(void) { - char buf[1024]; - int slen, tries = 0; + int optval = 1; + + memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in)); + memset((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in)); + myaddr_in.sin_family = AF_INET; + myaddr_in.sin_addr.s_addr = INADDR_ANY; + myaddr_in.sin_port = htons(Config.my_port); + + ls = socket(AF_INET, SOCK_STREAM, 0); + if (ls == -1) { + syslog(LOG_NOTICE, "Can't create listen socket: %s", strerror(errno)); + fprintf(stderr, "Can't create listen socket: %s\n", strerror(errno)); + return 1; + } + if (setsockopt(ls, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) { + syslog(LOG_NOTICE, "Can't setsockopt SO_KEEPALIVE socket: %s", strerror(errno)); + close(ls); + return 1; + } + + if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { + syslog(LOG_NOTICE, "Can't setsockopt SO_REUSEADDR socket: %s", strerror(errno)); + close(ls); + return 1; + } + + if (bind(ls, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in)) == -1) { + syslog(LOG_NOTICE, "Can't bind to listen socket: %s", strerror(errno)); + close(ls); + return 1; + } + + syslog(LOG_NOTICE, "listen socket created %d", ls); if (debug) - fprintf(stdout, "do_cmd(%s)\n", cmd); + fprintf(stdout, "listen socket created %d\n", ls); + + + return 0; +} + + + +/* + * Send message to client + */ +int srv_send(const char *format, ...) +{ + char out[SS_BUFSIZE]; + va_list va_ptr; + + if (s == -1) + return -1; - snprintf(buf, 1024, "%s", exe_cmd(cmd)); + va_start(va_ptr, format); + vsnprintf(out, SS_BUFSIZE-1, format, va_ptr); + va_end(va_ptr); + + if (send(s, out, strlen(out), 0) != strlen(out)) { + syslog(LOG_NOTICE, "srv_send failed"); + return -1; + } + + if (send(s, (char *)"\r\n", 2, 0) != 2) { + syslog(LOG_NOTICE, "srv_send failed"); + return -1; + } + + syslog(LOG_NOTICE, "send: \"%s\"", out); + return 0; +} + + - if (debug) - fprintf(stdout, "do_cmd() reply=\"%s\" len=%d\n", buf, strlen(buf)); +void cmd_die(int onsig) +{ + syslog(LOG_NOTICE, "Server process die on signal %d", onsig); + close(s); + exit(0); +} + + + +void cmd_server(void) +{ + char *hostname, buf[SS_BUFSIZE]; + int i, rc, rlen, timer; + socklen_t fromlen; + struct pollfd pfd[1]; + /* + * Close listen socket + */ + close(ls); + /* + * Install private signal handler. + */ + for (i = 0; i < NSIG; i++) { + if ((i == SIGHUP) || (i == SIGPIPE) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV)) + signal(i, (void (*))cmd_die); + else + signal(i, SIG_IGN); + } + + hp = gethostbyaddr ((char *) &peeraddr_in.sin_addr, sizeof(struct in_addr), peeraddr_in.sin_family); + if (hp == NULL) { + hostname = inet_ntoa(peeraddr_in.sin_addr); + } else { + hostname = hp->h_name; + } + + clients++; + syslog(LOG_NOTICE, "Start new client connection (%d) from %s port %u", clients, hostname, ntohs(peeraddr_in.sin_port)); + timer = SS_TIMEOUT * 4; + + /* + * Receive loop + */ for (;;) { -// slen = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&from, fromlen); + /* + * Poll socket until a define timeout of 0,25 second. + */ + pfd[0].fd = s; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + rc = poll(pfd, 1, 250); - if (debug) - fprintf(stdout, "do_cmd() slen=%d tries=%d %s\n", slen, tries, strerror(errno)); -// if (slen == -1) -// syslog(LOG_NOTICE, "do_cmd(): sendto error %d %s", tries, from.sun_path); - else if (slen != strlen(buf)) - syslog(LOG_NOTICE, "do_cmd(): send %d of %d bytes, try=%d", slen, strlen(buf), tries); - else - return; - tries++; - if (tries == 3) - return; - else - sleep(1); + if (rc == -1) { + /* + * Poll can be interrupted by a finished child so that's not a real error. + */ + if (errno != EINTR) { + syslog(LOG_NOTICE, "poll() rc=%d sock=%d events=%04x", rc, s, pfd[0].revents); + } + } else if (rc) { + if (pfd[0].revents & POLLIN) { + memset((char *)&buf, 0, SS_BUFSIZE); + fromlen = sizeof(peeraddr_in); + rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + if (rlen == -1) { + syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); + } else { + for (i = 0; i < strlen(buf); i++) { + if (buf[i] == '\n') + buf[i] = '\0'; + if (buf[i] == '\r') + buf[i] = '\0'; + } + timer = SS_TIMEOUT * 4; + if (strlen(buf)) { + syslog(LOG_NOTICE, "recv: \"%s\"", buf); + + /* + * Process command from the client + */ + srv_send(exe_cmd(buf)); + } + } + } else { + syslog(LOG_NOTICE, "poll other event"); + } + + } else { + /* + * Poll timeout, do some housekeeping + */ + if (timer) { + timer--; + } else { + /* Inactivity timeout */ + break; + } + if (my_shutdown) { + break; + } + } } } + +PI_THREAD (my_server_loop) +{ + socklen_t addrlen; + + syslog(LOG_NOTICE, "Thread my_server_loop started"); + if (debug) + fprintf(stdout, "Thread my_server_loop started\n"); + + /* + * Loop forever until the external shutdown variable is set. + */ + for (;;) { + + addrlen = sizeof(struct sockaddr_in); + /* + * This call will block until a new connection + * arrives. Then it will return the address of + * the connecting peer, and a new socket + * descriptor, s, for that connection. + */ + s = accept(ls, (struct sockaddr *)&peeraddr_in, &addrlen); + if (s == -1) { + syslog(LOG_NOTICE, "my_server_loop accept failed %s", strerror(errno)); + if (debug) + fprintf(stdout, "my_server_loop accept failed %s\n", strerror(errno)); + return 1; + } + + switch (fork()) { + case -1: /* + * Can't fork, just continue. + */ + return 1; + case 0: /* + * Child process, the commandline server. + */ + cmd_server(); + return 0; + default: /* + * Daemon process comes here. The daemon + * needs to remember to close the new + * accept socket after forking the child. + */ + close(s); + } + + if (my_shutdown) { + syslog(LOG_NOTICE, "Thread my_server_loop stopped"); + if (debug) + fprintf(stdout, "Thread my_server_loop stopped\n"); + return 0; + } + + } +} + + + diff -r 01b96a24ae7c -r 24e731bb2e08 thermferm/server.h --- a/thermferm/server.h Sun May 18 21:27:07 2014 +0200 +++ b/thermferm/server.h Sun May 18 22:56:43 2014 +0200 @@ -2,5 +2,7 @@ #define MY_SERVER_H +int server_init(void); +PI_THREAD (my_server_loop); #endif diff -r 01b96a24ae7c -r 24e731bb2e08 thermferm/thermferm.c --- a/thermferm/thermferm.c Sun May 18 21:27:07 2014 +0200 +++ b/thermferm/thermferm.c Sun May 18 22:56:43 2014 +0200 @@ -24,6 +24,7 @@ #include "thermferm.h" #include "mosquitto.h" #include "sensors.h" +#include "server.h" #ifdef HAVE_WIRINGPI_H @@ -35,6 +36,7 @@ bool my_shutdown = false; static pid_t pgrp, mypid; +int clients = 0; extern bool debug; extern sys_config Config; @@ -154,6 +156,9 @@ if (wiringPiSetup () ) return 1; + if (server_init() ) + return 1; + if ((rc = initLCD (16, 2))) { fprintf(stderr, "Cannot initialize LCD display, rc=%d\n", rc); return 1; @@ -258,6 +263,12 @@ syslog(LOG_NOTICE, "my_sensors_loop thread didn't start rc=%d", rc); } + rc = piThreadCreate(my_server_loop); + if (rc) { + fprintf(stderr, "my_server_loop thread didn't start rc=%d\n", rc); + syslog(LOG_NOTICE, "my_server_loop thread didn't start rc=%d", rc); + } + snprintf(buf, 1023, "tempA,coolerA,tempB,coolerB"); logger((char *)"thermferm.log", (char *)"thermferm", buf);