From d40b4a892a6b06e2ef0cb72e90ebf7b023577d03 Mon Sep 17 00:00:00 2001
From: John Hodge <tpg@mutabah.net>
Date: Sat, 4 Dec 2010 18:08:01 +0800
Subject: [PATCH] Fixing coke handler and login (a nice cleanup)

---
 src/Makefile              |  2 ++
 src/client/main.c         | 17 +++++++++--------
 src/cokebank_basic/main.c |  2 --
 src/server/common.h       |  7 +++++++
 src/server/handler_coke.c | 18 ++++++++++++++----
 src/server/main.c         | 30 ++++++++++++++++++++++++++++++
 src/server/server.c       | 32 ++++++++++++++++++++++++--------
 7 files changed, 86 insertions(+), 22 deletions(-)

diff --git a/src/Makefile b/src/Makefile
index 55bf2dd..c1073d9 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,8 +4,10 @@
 all:
 	@make -C cokebank all
 	@make -C server all
+	@make -C client all
 
 clean:
 	@make -C cokebank clean
 	@make -C server clean
+	@make -C client clean
 
diff --git a/src/client/main.c b/src/client/main.c
index c82d12d..ed7d1a2 100644
--- a/src/client/main.c
+++ b/src/client/main.c
@@ -24,6 +24,8 @@
 #include <arpa/inet.h>
 #include <openssl/sha.h>	// SHA1
 
+#define	USE_NCURSES_INTERFACE	0
+
 // === TYPES ===
 typedef struct sItem {
 	char	*Ident;
@@ -159,11 +161,8 @@ int main(int argc, char *argv[])
 	}
 	
 	// and choose what to dispense
-	// TODO: ncurses interface (with separation between item classes)
-	// - Hmm... that would require standardising the item ID to be <class>:<index>
-	// Oh, why not :)
 	
-	#if 1
+	#if USE_NCURSES_INTERFACE
 	i = ShowNCursesUI();
 	#else
 	
@@ -224,7 +223,7 @@ int main(int argc, char *argv[])
 			printf("Item failed to dispense, is the slot empty?\n");
 			break;
 		default:
-			printf("Unknown response code %i\n", responseCode);
+			printf("Unknown response code %i ('%s')\n", responseCode, buffer);
 			break;
 		}
 	}
@@ -257,6 +256,9 @@ void ShowItemAt(int Row, int Col, int Width, int Index)
  */
 int ShowNCursesUI(void)
 {
+	// TODO: ncurses interface (with separation between item classes)
+	// - Hmm... that would require standardising the item ID to be <class>:<index>
+	// Oh, why not :)
 	 int	ch;
 	 int	i, times;
 	 int	xBase, yBase;
@@ -512,7 +514,6 @@ void Authenticate(int Socket)
 		// TODO: Get Salt
 		// Expected format: 100 SALT <something> ...
 		// OR             : 100 User Set
-		printf("string = '%s'\n", buf);
 		RunRegex(&gSaltRegex, buf, 4, matches, "Malformed server response");
 		if( atoi(buf) != 100 ) {
 			exit(-1);	// ERROR
@@ -521,7 +522,7 @@ void Authenticate(int Socket)
 			// Set salt
 			memcpy( salt, buf + matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so );
 			salt[ matches[3].rm_eo - matches[3].rm_so ] = 0;
-			printf("Salt: '%s'\n", salt);
+//			printf("Salt: '%s'\n", salt);
 		}
 		
 		fflush(stdout);
@@ -542,7 +543,7 @@ void Authenticate(int Socket)
 				h[ 0], h[ 1], h[ 2], h[ 3], h[ 4], h[ 5], h[ 6], h[ 7], h[ 8], h[ 9],
 				h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19]
 				);
-			printf("Final hash: '%s'\n", buf);
+//			printf("Final hash: '%s'\n", buf);
 			fflush(stdout);	// Debug
 		}
 		
diff --git a/src/cokebank_basic/main.c b/src/cokebank_basic/main.c
index 62d49b8..ae111d4 100644
--- a/src/cokebank_basic/main.c
+++ b/src/cokebank_basic/main.c
@@ -14,8 +14,6 @@
 #include <openssl/sha.h>
 #include "common.h"
 
-#define HACK_TPG_NOAUTH	1
-
 // === IMPORTS ===
 extern int	Bank_GetMinAllowedBalance(int ID);
 extern int	Bank_GetUserBalance(int ID);
diff --git a/src/server/common.h b/src/server/common.h
index f2eea0c..0d97ad5 100644
--- a/src/server/common.h
+++ b/src/server/common.h
@@ -9,6 +9,8 @@
 #ifndef _COMMON_H_
 #define _COMMON_H_
 
+#include <regex.h>
+
 // === CONSTANTS ===
 #define	DEFAULT_CONFIG_FILE	"/etc/opendispense/main.cfg"
 #define	DEFAULT_ITEM_FILE	"/etc/opendispense/items.cfg"
@@ -62,6 +64,11 @@ extern int	giNumHandlers;
 extern int	giDebugLevel;
 
 // === FUNCTIONS ===
+// --- Helpers --
+extern void	CompileRegex(regex_t *Regex, const char *Pattern, int Flags);
+extern int	RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage);
+
+// --- Dispense ---
 extern int	DispenseItem(int User, tItem *Item);
 
 // --- Logging ---
diff --git a/src/server/handler_coke.c b/src/server/handler_coke.c
index 978e3f5..3ab46c5 100644
--- a/src/server/handler_coke.c
+++ b/src/server/handler_coke.c
@@ -41,7 +41,7 @@ int Coke_InitHandler()
 	if( giCoke_SerialFD == -1 ) {
 		fprintf(stderr, "ERROR: Unable to open coke serial port ('%s')\n", gsCoke_SerialPort);
 	}
-	regcomp(&gCoke_StatusRegex, "^slot\\s+(\\d)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
+	CompileRegex(&gCoke_StatusRegex, "^slot\\s+(\\d)\\s+([^:]+):([a-zA-Z]+)\\s*", REG_EXTENDED);
 	return 0;
 }
 
@@ -49,17 +49,27 @@ int Coke_CanDispense(int User, int Item)
 {
 	char	tmp[32], *status;
 	regmatch_t	matches[4];
+	 int	ret;
 
 	// Sanity please
-	if( Item < 0 || Item > 6 )	return -1;
+	if( Item < 0 || Item > 6 )	return -1;	// -EYOURBAD
 	
 	// Ask the coke machine
 	sprintf(tmp, "s%i\n", Item);
 	write(giCoke_SerialFD, tmp, 2);
 
 	// Read the response
-	read(giCoke_SerialFD, tmp, sizeof(tmp)-1);
-	regexec(&gCoke_StatusRegex, tmp, sizeof(matches)/sizeof(matches[0]), matches, 0);
+	tmp[0] = '\0';
+	ret = read(giCoke_SerialFD, tmp, sizeof(tmp)-1);
+	//printf("ret = %i\n", ret);
+	if( ret <= 0 ) {
+		fprintf(stderr, "Coke machine is not being chatty (read = %i)\n", ret);
+		return -1;
+	}
+	ret = RunRegex(&gCoke_StatusRegex, tmp, sizeof(matches)/sizeof(matches[0]), matches, "Bad Response");
+	if( ret ) {
+		return -1;
+	}
 
 	tmp[ matches[3].rm_eo ] = '\0';
 	status = &tmp[ matches[3].rm_so ];
diff --git a/src/server/main.c b/src/server/main.c
index 80183ba..ac6dd27 100644
--- a/src/server/main.c
+++ b/src/server/main.c
@@ -89,3 +89,33 @@ int main(int argc, char *argv[])
 	return 0;
 }
 
+int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
+{
+	 int	ret;
+	
+	ret = regexec(regex, string, nMatches, matches, 0);
+	if( ret ) {
+		size_t  len = regerror(ret, regex, NULL, 0);
+		char    errorStr[len];
+		regerror(ret, regex, errorStr, len);
+		printf("string = '%s'\n", string);
+		fprintf(stderr, "%s\n%s", errorMessage, errorStr);
+		exit(-1);
+	}
+	
+	return ret;
+}
+
+void CompileRegex(regex_t *regex, const char *pattern, int flags)
+{
+	 int	ret = regcomp(regex, pattern, flags);
+	if( ret ) {
+		size_t	len = regerror(ret, regex, NULL, 0);
+		char    errorStr[len];
+		regerror(ret, regex, errorStr, len);
+		fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
+		exit(-1);
+	}
+}
+
+
diff --git a/src/server/server.c b/src/server/server.c
index 5d375ee..e0fcafa 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -16,11 +16,15 @@
 #include <unistd.h>
 #include <string.h>
 
+// HACKS
+#define HACK_TPG_NOAUTH	1
+
+// Statistics
 #define MAX_CONNECTION_QUEUE	5
 #define INPUT_BUFFER_SIZE	256
 
-#define HASH_TYPE	SHA512
-#define HASH_LENGTH	64
+#define HASH_TYPE	SHA1
+#define HASH_LENGTH	20
 
 #define MSG_STR_TOO_LONG	"499 Command too long (limit "EXPSTR(INPUT_BUFFER_SIZE)")\n"
 
@@ -40,6 +44,7 @@ typedef struct sClient
 
 // === PROTOTYPES ===
 void	Server_Start(void);
+void	Server_Cleanup(void);
 void	Server_HandleClient(int Socket, int bTrusted);
 char	*Server_ParseClientCommand(tClient *Client, char *CommandString);
 // --- Commands ---
@@ -69,6 +74,7 @@ struct sClientCommand {
 	{"DISPENSE", Server_Cmd_DISPENSE}
 };
 #define NUM_COMMANDS	(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0]))
+ int	giServer_Socket;
 
 // === CODE ===
 /**
@@ -76,12 +82,14 @@ struct sClientCommand {
  */
 void Server_Start(void)
 {
-	 int	server_socket, client_socket;
+	 int	client_socket;
 	struct sockaddr_in	server_addr, client_addr;
 
+	atexit(Server_Cleanup);
+
 	// Create Server
-	server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if( server_socket < 0 ) {
+	giServer_Socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if( giServer_Socket < 0 ) {
 		fprintf(stderr, "ERROR: Unable to create server socket\n");
 		return ;
 	}
@@ -93,14 +101,16 @@ void Server_Start(void)
 	server_addr.sin_port = htons(giServer_Port);	// Port
 
 	// Bind
-	if( bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) {
+	if( bind(giServer_Socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0 ) {
 		fprintf(stderr, "ERROR: Unable to bind to 0.0.0.0:%i\n", giServer_Port);
+		perror("Binding");
 		return ;
 	}
 	
 	// Listen
-	if( listen(server_socket, MAX_CONNECTION_QUEUE) < 0 ) {
+	if( listen(giServer_Socket, MAX_CONNECTION_QUEUE) < 0 ) {
 		fprintf(stderr, "ERROR: Unable to listen to socket\n");
+		perror("Listen");
 		return ;
 	}
 	
@@ -111,7 +121,7 @@ void Server_Start(void)
 		uint	len = sizeof(client_addr);
 		 int	bTrusted = 0;
 		
-		client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &len);
+		client_socket = accept(giServer_Socket, (struct sockaddr *) &client_addr, &len);
 		if(client_socket < 0) {
 			fprintf(stderr, "ERROR: Unable to accept client connection\n");
 			return ;
@@ -148,6 +158,12 @@ void Server_Start(void)
 	}
 }
 
+void Server_Cleanup(void)
+{
+	printf("Close(%i)\n", giServer_Socket);
+	close(giServer_Socket);
+}
+
 /**
  * \brief Reads from a client socket and parses the command strings
  * \param Socket	Client socket number/handle
-- 
GitLab