diff --git a/server/src/Makefile b/server/src/Makefile
index 9df8c06844714edf15d3e94d0bf5f6a444dd58f2..3fee2f07c1a5871396f2f636ccd809b2694282f9 100644
--- a/server/src/Makefile
+++ b/server/src/Makefile
@@ -1,7 +1,8 @@
 # OpenDispense 2
 #
 
-OBJ := main.o logging.o dispense.o cokebank.o itemdb.o
+OBJ := main.o server.o logging.o
+OBJ += dispense.o cokebank.o itemdb.o
 BIN := ../dispsrv
 
 LINKFLAGS := 
diff --git a/server/src/common.h b/server/src/common.h
index 3e47fb7914326075571116cbaab0350d04977fff..f310e9a580de26333cdad22af7360e002d94ae3d 100644
--- a/server/src/common.h
+++ b/server/src/common.h
@@ -12,6 +12,10 @@
 // === CONSTANTS ===
 #define	DEFAULT_CONFIG_FILE	"/etc/opendispense/main.cfg"
 
+// === HELPER MACROS ===
+#define _EXPSTR(x)	#x
+#define EXPSTR(x)	_EXPSTR(x)
+
 // === STRUCTURES ===
 typedef struct sItem	tItem;
 struct sItem
@@ -54,5 +58,6 @@ extern void	Log_Info(const char *Format, ...);
 extern int	AlterBalance(int User, int Ammount);
 extern int	GetBalance(int User);
 extern char	*GetUserName(int User);
+extern int	GetUserID(const char *Username);
 
 #endif
diff --git a/server/src/main.c b/server/src/main.c
index 5b8e8b52f90af6433e996f2117b23f4d138803ff..2d9f70e3c35304af4b65349c55a0988c446758a2 100644
--- a/server/src/main.c
+++ b/server/src/main.c
@@ -19,9 +19,9 @@ extern void	Server_Start(void);
 // === CODE ===
 int main(int argc, char *argv[])
 {
-	Cokebank_Init();
+	//Init_Cokebank();
 	
-	Load_Itemlist();
+	//Load_Itemlist();
 	
 	Server_Start();
 	
diff --git a/server/src/server.c b/server/src/server.c
index 6d1ed5ddf486921114210af617e2c73030b85ac3..8c87c6548c59e83d6346fb6e7c28df629152dd71 100644
--- a/server/src/server.c
+++ b/server/src/server.c
@@ -11,27 +11,57 @@
 #include <stdlib.h>
 #include "common.h"
 #include <sys/socket.h>
+#include <string.h>
 
 #define MAX_CONNECTION_QUEUE	5
-#define INPUT_BUFFER_SIZE	100
+#define INPUT_BUFFER_SIZE	128
 
-#define MSG_STR_TOO_LONG	"499 Malformed Command String"
+#define MSG_STR_TOO_LONG	"499 Command too long (limit "EXPSTR(INPUT_BUFFER_SIZE)")\n"
+
+// === TYPES ===
+typedef struct sClient
+{
+	 int	UID;
+	 int	bIsAuthed;
+}	tClient;
+
+// === PROTOTYPES ===
+void	Server_Start(void);
+void	Server_HandleClient(int Socket);
+char	*Server_ParseClientCommand(tClient *Client, char *CommandString);
+char	*Server_Cmd_USER(tClient *Client, char *Args);
 
 // === GLOBALS ===
  int	giServer_Port = 1020;
+ int	giServer_NextClientID = 1;
+// - Commands
+struct sClientCommand {
+	char	*Name;
+	char	*(*Function)(tClient *Client, char *Arguments);
+}	gaServer_Commands[] = {
+	{"USER", Server_Cmd_USER}
+};
+#define NUM_COMMANDS	(sizeof(gaServer_Commands)/sizeof(gaServer_Commands[0]))
 
 // === CODE ===
+/**
+ * \brief Open listenting socket and serve connections
+ */
 void Server_Start(void)
 {
 	// Create Server
 }
 
+/**
+ * \brief Reads from a client socket and parses the command strings
+ */
 void Server_HandleClient(int Socket)
 {
 	char	inbuf[INPUT_BUFFER_SIZE];
 	char	*buf = inbuf;
 	 int	remspace = INPUT_BUFFER_SIZE-1;
 	 int	bytes = -1;
+	tClient	clientInfo = {0};
 		
 	// Read from client
 	while( (bytes = recv(Socket, buf, remspace, 0)) > 0 )
@@ -43,8 +73,12 @@ void Server_HandleClient(int Socket)
 		start = inbuf;
 		while( (eol = strchr(start, '\n')) )
 		{
+			char	*ret;
 			*eol = '\0';
-			Server_ParseClientCommand(Socket, start);
+			ret = Server_ParseClientCommand(&clientInfo, start);
+			// `ret` is a string on the heap
+			send(Socket, ret, strlen(ret), 0);
+			free(ret);
 			start = eol + 1;
 		}
 		
@@ -55,7 +89,9 @@ void Server_HandleClient(int Socket)
 			memcpy(inbuf, start, tailBytes);
 			remspace -= tailBytes;
 			if(remspace == 0) {
-				send(Socket, MSG_STR_TOO_LONG, sizeof(MSG_STR_TOO_LONG));
+				send(Socket, MSG_STR_TOO_LONG, sizeof(MSG_STR_TOO_LONG), 0);
+				buf = inbuf;
+				remspace = INPUT_BUFFER_SIZE - 1;
 			}
 		}
 		else {
@@ -70,3 +106,70 @@ void Server_HandleClient(int Socket)
 		return ;
 	}
 }
+
+/**
+ * \brief Parses a client command and calls the required helper function
+ * \param Client	Pointer to client state structure
+ */
+char *Server_ParseClientCommand(tClient *Client, char *CommandString)
+{
+	char	*space, *args;
+	 int	i;
+	
+	// Split at first space
+	space = strchr(CommandString, ' ');
+	if(space == NULL) {
+		args = NULL;
+	}
+	else {
+		*space = '\0';
+		args = space + 1;
+	}
+	
+	// Find command
+	for( i = 0; i < NUM_COMMANDS; i++ )
+	{
+		if(strcmp(CommandString, gaServer_Commands[i].Name) == 0)
+			return gaServer_Commands[i].Function(Client, args);
+	}
+	
+	return strdup("400	Unknown Command\n");
+}
+
+// ---
+// Commands
+// ---
+/**
+ * \brief Set client username
+ */
+char *Server_Cmd_USER(tClient *Client, char *Args)
+{
+	char	*ret;
+	
+	// Debug!
+	if( gbDebugLevel )
+		printf("Client %i authenticating as '%s'\n", Args);
+	
+	// Save username
+	if(Client->Username)
+		free(Client->Username);
+	Client->Username = strdup(Args);
+	
+	// Create a salt (that changes if the username is changed)
+	if(!Client->Salt)
+		Client->Salt = malloc(9);
+	Client->Salt[0] = 0x21 + (rand()&0x3F);
+	Client->Salt[1] = 0x21 + (rand()&0x3F);
+	Client->Salt[2] = 0x21 + (rand()&0x3F);
+	Client->Salt[3] = 0x21 + (rand()&0x3F);
+	Client->Salt[4] = 0x21 + (rand()&0x3F);
+	Client->Salt[5] = 0x21 + (rand()&0x3F);
+	Client->Salt[6] = 0x21 + (rand()&0x3F);
+	Client->Salt[7] = 0x21 + (rand()&0x3F);
+	
+	// "100 Salt xxxxXXXX\n"
+	ret = strdup("100 SALT xxxxXXXX\n");
+	sprintf(ret, "100 SALT %s\n", Client->Salt);
+	
+	return ret;
+}