From 05918a67e8509a2b2df6509039a801affd3444eb Mon Sep 17 00:00:00 2001
From: John Hodge <tpg@ucc.gu.uwa.edu.au>
Date: Sun, 21 Nov 2010 02:11:07 +0800
Subject: [PATCH] Cleanups of bugs and segfaults

---
 RunServerTest             |  6 +++-
 proto.txt                 | 14 ++++----
 src/cokebank_basic/main.c |  2 ++
 src/server/common.h       |  2 ++
 src/server/dispense.c     | 43 ++++++++++++-------------
 src/server/main.c         |  8 +++++
 src/server/server.c       | 68 ++++++++++++++++++++++++++++++---------
 7 files changed, 97 insertions(+), 46 deletions(-)

diff --git a/RunServerTest b/RunServerTest
index d0c2fa3..d4f7d6e 100755
--- a/RunServerTest
+++ b/RunServerTest
@@ -1,3 +1,7 @@
 #!/bin/sh
 
-LD_LIBRARY_PATH=. ./dispsrv --itemsfile items.cfg -p 11020
+if [ "x$1" != "x" ]; then 
+	LD_LIBRARY_PATH=. gdb --args ./dispsrv --itemsfile items.cfg -p 11020
+else
+	LD_LIBRARY_PATH=. ./dispsrv --itemsfile items.cfg -p 11020	
+fi
diff --git a/proto.txt b/proto.txt
index e8d235c..8c5e1f6 100644
--- a/proto.txt
+++ b/proto.txt
@@ -16,6 +16,7 @@ All server responses are on one line and are prefixed by a three digit response
 404	Bad other username
 406	Bad Item ID
 500	Unknown Dispense Failure
+501	Action Rejected
 
 == Item IDs ==
 <item_id> represents the item ID
@@ -35,12 +36,6 @@ c	AUTOAUTH <username>\n
 s	200 Auth OK\n or 401 Auth Failure\n or 401 Untrusted\n
 
 === Commands ===
---- Get Item list ---
-c	ENUM_ITEMS\n
-s	201 Items <count> <item_id> <item_id> ...\n
---- Get Item Information ---
-c	ITEM_INFO <item_id>\n
-s	202 Item <item_id> <price> <description>\n
 --- Dispense an item ---
 c	DISPENSE <item_id>\n
 s	200 Dispense OK\n or 402 Poor You\n or 500 Dispense Error\n or 406 Bad Item\n
@@ -50,6 +45,13 @@ s	200 Give OK\n or 402 Poor You\n or 404 Bad User\n
 --- Update balance ---
 c	ADD <user> <ammount> <reason>\n
 s	200 Add OK\n or 403 Not Coke\n or 404 Bad User\n
+
+--- Get Item list ---
+c	ENUM_ITEMS\n
+s	201 Items <count> <item_id> <item_id> ...\n
+--- Get Item Information ---
+c	ITEM_INFO <item_id>\n
+s	202 Item <item_id> <price> <description>\n
 --- Set Balance ---
 c	SET <user> <balance> <reason>\n
 s	200 Set OK\n or 403 Not allowed\n or 404 Bad User\n
diff --git a/src/cokebank_basic/main.c b/src/cokebank_basic/main.c
index 11b822c..fbc8f6e 100644
--- a/src/cokebank_basic/main.c
+++ b/src/cokebank_basic/main.c
@@ -13,6 +13,8 @@
 #include <string.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 9105db1..d790c82 100644
--- a/src/server/common.h
+++ b/src/server/common.h
@@ -62,6 +62,8 @@ extern int	giNumHandlers;
 extern int	giDebugLevel;
 
 // === FUNCTIONS ===
+extern int	DispenseItem(int User, tItem *Item);
+
 // --- Logging ---
 extern void	Log_Error(const char *Format, ...);
 extern void	Log_Info(const char *Format, ...);
diff --git a/src/server/dispense.c b/src/server/dispense.c
index f851731..884c541 100644
--- a/src/server/dispense.c
+++ b/src/server/dispense.c
@@ -9,50 +9,47 @@
  * 
  * The core of the dispense system, I kinda like it :)
  */
-int DispenseItem(int User, int Item)
+int DispenseItem(int User, tItem *Item)
 {
 	 int	ret;
-	tItem	*item;
 	tHandler	*handler;
 	char	*username;
 	
-	// Sanity check please?
-	if(Item < 0 || Item >= giNumItems)
-		return -1;
-	
-	// Get item pointers
-	item = &gaItems[Item];
-	handler = item->Handler;
+	handler = Item->Handler;
 	
 	// Check if the dispense is possible
-	ret = handler->CanDispense( User, item->ID );
-	if(!ret)	return ret;
+	if( handler->CanDispense ) {
+		ret = handler->CanDispense( User, Item->ID );
+		if(!ret)	return 1;	// 1: Unknown Error
+	}
 	
 	// Subtract the balance
-	ret = Transfer( User, GetUserID(">sales"), item->Price, "" );
+	ret = Transfer( User, GetUserID(">sales"), Item->Price, "" );
 	// What value should I use for this error?
 	// AlterBalance should return the final user balance
-	if(ret == 0)	return 1;
+	if(ret != 0)	return 2;	// 2: No balance
 	
 	// Get username for debugging
 	username = GetUserName(User);
 	
 	// Actually do the dispense
-	ret = handler->DoDispense( User, item->ID );
-	if(ret) {
-		Log_Error("Dispense failed after deducting cost (%s dispensing %s - %ic)",
-			username, item->Name, item->Price);
-		Transfer( GetUserID(">sales"), User, item->Price, "rollback" );
-		free( username );
-		return 1;
+	if( handler->DoDispense ) {
+		ret = handler->DoDispense( User, Item->ID );
+		if(ret) {
+			Log_Error("Dispense failed after deducting cost (%s dispensing %s - %ic)",
+				username, Item->Name, Item->Price);
+			Transfer( GetUserID(">sales"), User, Item->Price, "rollback" );
+			free( username );
+			return -1;	// 1: Unkown Error again
+		}
 	}
 	
 	// And log that it happened
 	Log_Info("Dispensed %s (%i:%i) for %s [cost %i, balance %i cents]",
-		item->Name, handler->Name, item->ID,
-		username, item->Price, GetBalance(User)
+		Item->Name, handler->Name, Item->ID,
+		username, Item->Price, GetBalance(User)
 		);
 	
 	free( username );
-	return 0;
+	return 0;	// 0: EOK
 }
diff --git a/src/server/main.c b/src/server/main.c
index d327db3..76e720b 100644
--- a/src/server/main.c
+++ b/src/server/main.c
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <signal.h>
 #include "common.h"
 
 // === IMPORTS ===
@@ -25,6 +26,11 @@ extern char*	gsCoke_SerialPort;
 char	*gsCokebankPath = "cokebank.db";
 
 // === CODE ===
+void sigint_handler()
+{
+	exit(0);
+}
+
 int main(int argc, char *argv[])
 {
 	 int	i;
@@ -70,6 +76,8 @@ int main(int argc, char *argv[])
 	
 	Server_Start();
 	
+	signal(SIGINT, sigint_handler);
+
 	return 0;
 }
 
diff --git a/src/server/server.c b/src/server/server.c
index c9ab63e..9f59489 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -48,6 +48,7 @@ char	*Server_Cmd_PASS(tClient *Client, char *Args);
 char	*Server_Cmd_AUTOAUTH(tClient *Client, char *Args);
 char	*Server_Cmd_ENUMITEMS(tClient *Client, char *Args);
 char	*Server_Cmd_ITEMINFO(tClient *Client, char *Args);
+char	*Server_Cmd_DISPENSE(tClient *Client, char *Args);
 // --- Helpers ---
 void	HexBin(uint8_t *Dest, char *Src, int BufSize);
 
@@ -63,7 +64,8 @@ struct sClientCommand {
 	{"PASS", Server_Cmd_PASS},
 	{"AUTOAUTH", Server_Cmd_AUTOAUTH},
 	{"ENUM_ITEMS", Server_Cmd_ENUMITEMS},
-	{"ITEM_INFO", Server_Cmd_ITEMINFO}
+	{"ITEM_INFO", Server_Cmd_ITEMINFO},
+	{"DISPENSE", Server_Cmd_DISPENSE}
 };
 #define NUM_COMMANDS	(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0]))
 
@@ -302,6 +304,15 @@ char *Server_Cmd_PASS(tClient *Client, char *Args)
 	// Read user's hash
 	HexBin(clienthash, Args, HASH_LENGTH);
 	
+	// TODO: Decrypt password passed
+	
+	Client->UID = GetUserAuth(Client->Username, "");
+
+	if( Client->UID != -1 ) {
+		Client->bIsAuthed = 1;
+		return strdup("200 Auth OK\n");
+	}
+
 	if( giDebugLevel ) {
 		 int	i;
 		printf("Client %i: Password hash ", Client->ID);
@@ -374,21 +385,15 @@ char *Server_Cmd_ENUMITEMS(tClient *Client, char *Args)
 	return ret;
 }
 
-/**
- * \brief Fetch information on a specific item
- */
-char *Server_Cmd_ITEMINFO(tClient *Client, char *Args)
+tItem *_GetItemFromString(char *String)
 {
-	 int	retLen = 0;
-	char	*ret;
-	tItem	*item;
 	tHandler	*handler;
-	char	*type = Args;
-	char	*colon = strchr(Args, ':');
+	char	*type = String;
+	char	*colon = strchr(String, ':');
 	 int	num, i;
 	
 	if( !colon ) {
-		return strdup("406 Bad Item ID\n");
+		return NULL;
 	}
 
 	num = atoi(colon+1);
@@ -404,7 +409,7 @@ char *Server_Cmd_ITEMINFO(tClient *Client, char *Args)
 		}
 	}
 	if( !handler ) {
-		return strdup("406 Bad Item ID\n");
+		return NULL;
 	}
 
 	// Find item
@@ -412,23 +417,54 @@ char *Server_Cmd_ITEMINFO(tClient *Client, char *Args)
 	{
 		if( gaItems[i].Handler != handler )	continue;
 		if( gaItems[i].ID != num )	continue;
-		item = &gaItems[i];
-		break;
+		return &gaItems[i];
 	}
+	return NULL;
+}
+
+/**
+ * \brief Fetch information on a specific item
+ */
+char *Server_Cmd_ITEMINFO(tClient *Client, char *Args)
+{
+	 int	retLen = 0;
+	char	*ret;
+	tItem	*item = _GetItemFromString(Args);
+	
 	if( !item ) {
 		return strdup("406 Bad Item ID\n");
 	}
 
 	// Create return
 	retLen = snprintf(NULL, 0, "202 Item %s:%i %i %s\n",
-		handler->Name, item->ID, item->Price, item->Name);
+		item->Handler->Name, item->ID, item->Price, item->Name);
 	ret = malloc(retLen+1);
 	sprintf(ret, "202 Item %s:%i %i %s\n",
-		handler->Name, item->ID, item->Price, item->Name);
+		item->Handler->Name, item->ID, item->Price, item->Name);
 
 	return ret;
 }
 
+char *Server_Cmd_DISPENSE(tClient *Client, char *Args)
+{
+	tItem	*item;
+	if( !Client->bIsAuthed )	return strdup("401 Not Authenticated\n");
+
+	item = _GetItemFromString(Args);
+	if( !item ) {
+		return strdup("406 Bad Item ID\n");
+	}
+
+	switch( DispenseItem( Client->UID, item ) )
+	{
+	case 0:	return strdup("200 Dispense OK\n");
+	case 1:	return strdup("501 Unable to dispense\n");
+	case 2:	return strdup("402 Poor You\n");
+	default:
+		return strdup("500 Dispense Error\n");
+	}
+}
+
 // --- INTERNAL HELPERS ---
 // TODO: Move to another file
 void HexBin(uint8_t *Dest, char *Src, int BufSize)
-- 
GitLab