Initial server code added

Sun, 18 May 2014 22:56:43 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 18 May 2014 22:56:43 +0200
changeset 43
24e731bb2e08
parent 42
01b96a24ae7c
child 44
f37d73940699

Initial server code added

lib/mbselib.h file | annotate | diff | comparison | revisions
lib/rdconfig.c file | annotate | diff | comparison | revisions
thermferm/Makefile file | annotate | diff | comparison | revisions
thermferm/server.c file | annotate | diff | comparison | revisions
thermferm/server.h file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
--- 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 <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdarg.h>
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
@@ -20,7 +21,8 @@
 #include <getopt.h>
 #include <limits.h>
 #include <sys/socket.h>
-#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netdb.h>
 #include <poll.h>
 
 
@@ -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		*/
--- 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;
--- 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
--- 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;
+	}
+
+    }
+}
+
+
+
--- 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
--- 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);
 

mercurial