#define _GNU_SOURCE
#include "login.h"
#include "data.h"
#include "server.h"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <argon2.h>
void handle_player(int conn_fd) {
debug("Let's make a new player object\n");
playerc_t plrc = {0};
plrc.state = LoggedOut;
plrc.conn = conn_fd;
player_t plr = {0};
plrc.plr = plr;
debug("No sense in having a player if they can't log in!\n");
int err = step_login(&plrc, conn_fd);
if (err) {
err = send_to_fd(conn_fd, "Error in login process, exiting");
if (err) {
error("Could not send error message");
}
close(conn_fd);
return;
}
close(conn_fd);
}
int step_login(playerc_t *player, int conn_fd) {
int err = 0;
for (;;) {
switch (player->state) {
case LoggedOut: ; /* the player has yet to log in, this is a fresh connection!
*/
debug("The player is logged out\n");
send_to_fd(player->conn,
"Welcome! Please enter your **username** below\n");
char *buf = (char *)malloc(1 << 10);
debug("Waiting to receive...\n");
recv(player->conn, buf, 1024, 0);
debug("Received!\n");
char* playername = trimwhitespace(buf);
err = try_load_plr(playername, player);
debug("Finished trying to load the player\n");
if (err) {
// File doesn't exist, let's create a player!
player->plr.name = (char *)malloc(32);
strcpy(player->plr.name, playername);
send_to_fd(player->conn, "Howdy! Want to introduce yourself? [y|n]\n");
recv(player->conn, buf, sizeof(buf), 0);
if (buf[0] == 'y') {
player->state = WantMakeAccount;
break;
} else if (buf[0] == 'n') {
send_to_fd(player->conn,
"Awww :(. Oh well, hope to see you again soon!\n");
return 4;
}
break;
} else {
player->state = EnterPassword;
break;
}
case EnterPassword: ;
asprintf(&buf, "Welcome back %s! Please enter your password, so we can confirm it.\n", player->plr.name);
send_to_fd(player->conn, buf);
memset(buf, '\0', 1 << 9);
recv(player->conn, buf, sizeof(buf), 0);
char* pw = trimwhitespace(buf);
int res = argon2i_verify(player->plr.pw_hash, pw, strlen(pw));
if (res == ARGON2_OK) {
// The password is good!
send_to_fd(player->conn, "That looks good to me! Let's get you loaded in\n");
player->state = Complete;
} else {
// Password is incorrect
send_to_fd(player->conn, "Password incorrect, please try again\n");
break;
}
break;
case WantMakeAccount:
asprintf(&buf, "Welcome aboard %s! Why don't you start us off by giving me a password.\n", player->plr.name);
send_to_fd(player->conn, buf);
memset(buf, '\0', 1 << 9);
recv(player->conn, buf, sizeof(buf), 0);
if (strlen(buf) <= 5) {
send_to_fd(player->conn, "We're sorry, but passwords need to be at least 5 characters");
} else {
player->plr.pw_hash = (char *)malloc(512);
char* pw = trimwhitespace(buf);
err = argon2i_hash_encoded(32, 512, 1, pw, strlen(pw), "adSAaVWIueBwP2jHfAl7diRJ9ijC1Ysb9e920d6d9+I=", strlen("adSAaVWIueBwP2jHfAl7diRJ9ijC1Ysb9e920d6d9+I="), 32, player->plr.pw_hash, 512);
if (err != ARGON2_OK) {
send_to_fd(player->conn, "Uhhh, something happened. Try again.");
player->state = LoggedOut;
break;
} else {
send_to_fd(player->conn, "Sounds good! let's drop you into a world!");
player->state = Complete;
player->plr.hp = player->plr.max_hp = 20;
player->plr.level = 1;
player->plr.xp = 0;
player->plr.location_id = 0;
debug("Trying to write player\n");
try_write_plr(&player->plr);
debug("Done\n");
player->state = Complete;
}
}
case Complete: ;
return 0;
}
}
return err;
}