diff --git a/src/Makefile b/src/Makefile index 55bf2ddf25f03a8335f536465d052e37d9e64921..c1073d9dd7d1220bdcb02c6dfc315e0b94c55cc9 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 c82d12d793f1bad6334452d23df3f3b0139d5b8f..ed7d1a22bbcf5fda3975fabf7548bb57174ea909 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 62d49b85d1d7e313b76905c6cb9dafec74943e3f..ae111d4d88ecd2e226f6c118705247fc5771ecde 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 f2eea0cdb066b4cca63a024b834cf2f47b24cce7..0d97ad5f968e465f579757a773b3a5db140d1eb2 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 978e3f5fe538d00c3dba7bb5ed973decdf82eded..3ab46c59d189f7c9279b33748cd8b39afa514097 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 80183ba3638f117b5ae398e7b33e58aad3a15a59..ac6dd27f61bc754945cfe66c4239a169d7e738fe 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 5d375ee7130719d7ef42a0555cd1c56ce43ab343..e0fcafa64b2511173f37de18229901842690af14 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