aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2015-12-24 19:18:45 -0500
committerFranklin Wei <git@fwei.tk>2015-12-24 19:18:45 -0500
commit53c15b0461ee39a4c32e61ff484389efb1e91d84 (patch)
treec26e64930e1d73960eebc26b02d9d2185d2e1aef /src
parent28f94a54984fa7aa46fcb25e7991c1136329670f (diff)
downloadnetcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.zip
netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.tar.gz
netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.tar.bz2
netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.tar.xz
stuff
Diffstat (limited to 'src')
-rw-r--r--src/auth.c2
-rw-r--r--src/client.c75
-rw-r--r--src/hash.c100
-rw-r--r--src/hash.h18
-rw-r--r--src/netcosm.h7
-rw-r--r--src/room.c84
-rw-r--r--src/server.c13
-rw-r--r--src/test.c10
-rw-r--r--src/util.c7
9 files changed, 293 insertions, 23 deletions
diff --git a/src/auth.c b/src/auth.c
index dcc89d8..03f0ad3 100644
--- a/src/auth.c
+++ b/src/auth.c
@@ -1,9 +1,7 @@
#include "netcosm.h"
#define SALT_LEN 12
-
#define ALGO GCRY_MD_SHA512
-
#define HASH_ITERS 500000
static bool valid_login_name(const char *name);
diff --git a/src/client.c b/src/client.c
index 96f8150..ee40e5c 100644
--- a/src/client.c
+++ b/src/client.c
@@ -181,30 +181,59 @@ static void client_change_room(room_id id)
static void client_move(const char *dir)
{
- struct {
+ const struct dir_pair {
const char *text;
enum direction_t val;
} dirs[] = {
- { "N", DIR_N },
- { "NE", DIR_NE },
- { "E", DIR_E },
- { "SE", DIR_SE },
- { "S", DIR_S },
- { "SW", DIR_SW },
- { "W", DIR_W },
- { "NW", DIR_NW },
- { "UP", DIR_UP },
- { "DOWN", DIR_DOWN }
+ { "N", DIR_N },
+ { "NORTH", DIR_N },
+ { "NE", DIR_NE },
+ { "NORTHEAST", DIR_N },
+ { "E", DIR_E },
+ { "EAST", DIR_E },
+ { "SE", DIR_SE },
+ { "SOUTHEAST", DIR_SE },
+ { "S", DIR_S },
+ { "SOUTH", DIR_S },
+ { "SW", DIR_SW },
+ { "SOUTHWEST", DIR_SW },
+ { "W", DIR_W },
+ { "WEST", DIR_W },
+ { "NW", DIR_NW },
+ { "NORTHWEST", DIR_NW },
+ { "U", DIR_UP },
+ { "UP", DIR_UP },
+ { "D", DIR_DOWN },
+ { "DOWN", DIR_DOWN },
};
- for(unsigned i = 0; i < ARRAYLEN(dirs); ++i)
+ static void *map = NULL;
+ if(!map)
{
- if(!strcmp(dir, dirs[i].text))
+ map = hash_init(ARRAYLEN(dirs), hash_djb, strcmp);
+ for(unsigned i = 0; i < ARRAYLEN(dirs); ++i)
{
- send_master(REQ_MOVE, &dirs[i].val, sizeof(dirs[i].val));
- return;
+ hash_insert(map, dirs[i].text, dirs + i);
+
+ void *new = hash_lookup(map, dirs[i].text);
+ if(new != dirs + i)
+ error("weird %p %p", new, dirs + i);
}
}
- out("Unknown direction.\n");
+
+ struct dir_pair *pair = hash_lookup(map, dir);
+ if(pair)
+ {
+ send_master(REQ_MOVE, &pair->val, sizeof(pair->val));
+ }
+ else
+ out("Unknown direction.\n");
+}
+
+static void client_look(void)
+{
+ send_master(REQ_GETROOMNAME, NULL, 0);
+ out("\n");
+ send_master(REQ_GETROOMDESC, NULL, 0);
}
#define WSPACE " \t\r\n"
@@ -292,7 +321,9 @@ auth:
/* authenticated */
printf("Authenticated as %s\n", current_user);
client_change_user(current_user);
+ current_room = 0;
client_change_room(current_room);
+ client_look();
while(1)
{
out(">> ");
@@ -451,7 +482,7 @@ auth:
}
else if(!strcmp(tok, "LOOK"))
{
- send_master(REQ_LOOK, NULL, 0);
+ client_look();
}
else if(!strcmp(tok, "WAIT"))
{
@@ -460,8 +491,14 @@ auth:
else if(!strcmp(tok, "GO"))
{
char *dir = strtok_r(NULL, WSPACE, &save);
- all_upper(dir);
- client_move(dir);
+ if(dir)
+ {
+ all_upper(dir);
+ client_move(dir);
+ client_look();
+ }
+ else
+ out("Expected direction after GO.\n");
}
next_cmd:
diff --git a/src/hash.c b/src/hash.c
new file mode 100644
index 0000000..2ca757c
--- /dev/null
+++ b/src/hash.c
@@ -0,0 +1,100 @@
+#include "hash.h"
+
+struct hash_node {
+ const void *key;
+ const void *data;
+ struct hash_node *next;
+};
+
+struct hash_map {
+ unsigned (*hash)(const void *data);
+ int (*compare)(const void *a, const void *b);
+ struct hash_node **table;
+ size_t table_sz;
+};
+
+unsigned hash_djb(const char *str)
+{
+ unsigned hash = 5381;
+ char c;
+ while((c = *str++))
+ {
+ hash = ((hash << 5) + hash) ^ c;
+ }
+
+ return hash;
+}
+
+void *hash_init(size_t sz, unsigned (*hash_fn)(const void*),
+ int (*compare_keys)(const void*, const void*))
+{
+ struct hash_map *ret = calloc(sizeof(struct hash_map), 1);
+ ret->table = calloc(sizeof(struct hash_node), sz);
+ ret->table_sz = sz;
+ ret->hash = hash_fn;
+ ret->compare = compare_keys;
+
+ return ret;
+}
+
+void hash_free(void *ptr)
+{
+ struct hash_map *map = ptr;
+ for(unsigned i = 0; i < map->table_sz; ++i)
+ {
+ struct hash_node *node = map->table[i];
+ while(node)
+ {
+ struct hash_node *next = node->next;
+ free(node);
+ node = next;
+ }
+ }
+ free(map->table);
+ free(map);
+}
+
+void *hash_insert(void *ptr, const void *key, const void *data)
+{
+ struct hash_map *map = ptr;
+ unsigned hash = map->hash(key) % map->table_sz;
+
+ struct hash_node *iter = map->table[hash];
+ struct hash_node *last = NULL;
+
+ while(iter)
+ {
+ if(map->compare(key, iter->key) == 0)
+ return (void*)(iter->data);
+ last = iter;
+ iter = iter->next;
+ }
+
+ /* insert */
+ struct hash_node *new = calloc(sizeof(struct hash_node), 1);
+ new->key = key;
+ new->data = data;
+ new->next = NULL;
+ if(!last)
+ map->table[hash] = new;
+ else
+ last->next = new;
+
+ return NULL;
+}
+
+void *hash_lookup(void *ptr, const void *key)
+{
+ struct hash_map *map = ptr;
+ unsigned hash = map->hash(key) % map->table_sz;
+
+ struct hash_node *iter = map->table[hash];
+
+ while(iter)
+ {
+ if(map->compare(key, iter->key) == 0)
+ return (void*)(iter->data);
+ iter = iter->next;
+ }
+ return NULL;
+}
diff --git a/src/hash.h b/src/hash.h
new file mode 100644
index 0000000..7713885
--- /dev/null
+++ b/src/hash.h
@@ -0,0 +1,18 @@
+#include <stddef.h>
+#include <stdlib.h>
+
+/* simple, generic hash map implementation */
+
+unsigned hash_djb(const char*);
+
+void *hash_init(size_t tabsz, unsigned (*hash_fn)(const void*),
+ int (*compare_key)(const void*, const void*));
+
+void hash_free(void*);
+
+/* insert a pair, returns null if not already found, otherwise
+ return the existing data pointer */
+void *hash_insert(void*, const void *key, const void *data);
+
+/* returns NULL if not found */
+void *hash_lookup(void*, const void *key);
diff --git a/src/netcosm.h b/src/netcosm.h
index 1712539..fb50600 100644
--- a/src/netcosm.h
+++ b/src/netcosm.h
@@ -20,6 +20,7 @@
#include <time.h>
#include <unistd.h>
+#include "hash.h"
#include "telnet.h"
#define USERFILE "users.dat"
@@ -42,9 +43,10 @@
#define REQ_HANG 5 /* <UNIMP> server: loop forever */
#define REQ_KICK 6 /* server: kick PID with message; child: print message, quit */
#define REQ_WAIT 7 /* server: sleep 10s */
-#define REQ_LOOK 8 /* server: send child room description */
+#define REQ_GETROOMDESC 8 /* server: send child room description */
#define REQ_SETROOM 9 /* server: set child room */
#define REQ_MOVE 10 /* server: move child based on direction; child: success or failure */
+#define REQ_GETROOMNAME 11 /* server: send child's room name */
/* child states */
#define STATE_INIT 0 /* initial state */
@@ -152,3 +154,6 @@ void auth_list_users(void);
void world_init(const struct roomdata_t *data, size_t sz);
void sig_printf(const char *fmt, ...);
void world_free(void);
+
+/* only the master calls this */
+struct room_t *room_get(room_id id);
diff --git a/src/room.c b/src/room.c
new file mode 100644
index 0000000..e459ac8
--- /dev/null
+++ b/src/room.c
@@ -0,0 +1,84 @@
+#include "netcosm.h"
+
+static struct room_t *world;
+static size_t world_sz;
+
+static struct room_t *room_linear_search(const char *id)
+{
+ printf("Looking for room with id '%s'\n", id);
+ for(size_t i = 0; i < world_sz; ++i)
+ if(!strcmp(world[i].data.uniq_id, id))
+ return world + i;
+ else
+ printf("Iterating over room '%s'\n", world[i].data.uniq_id);
+ return NULL;
+}
+
+struct room_t *room_get(room_id id)
+{
+ return world + id;
+}
+
+void world_free(void)
+{
+ free(world);
+}
+
+/* loads room data (supplied by the world module) into our internal format */
+void world_init(const struct roomdata_t *data, size_t sz)
+{
+ printf("Loading world with %lu rooms.\n", sz);
+ world = calloc(sz, sizeof(struct room_t));
+ world_sz = 0;
+
+ void *map = hash_init(1, hash_djb, strcmp);
+
+ for(size_t i = 0; i < sz; ++i)
+ {
+ world[i].id = i;
+ memcpy(&world[i].data, &data[i], sizeof(data[i]));
+ printf("Loading room '%s'\n", world[i].data.uniq_id);
+
+ if(hash_insert(map, world[i].data.uniq_id, world + i))
+ error("Duplicate room ID '%s'\n", world[i].data.uniq_id);
+
+ for(int dir = 0; dir < NUM_DIRECTIONS; ++dir)
+ {
+ const char *adjacent_room = world[i].data.adjacent[dir];
+ if(adjacent_room)
+ {
+ struct room_t *room = hash_lookup(map, adjacent_room);
+ if(room)
+ world[i].adjacent[dir] = room->id;
+ }
+ }
+
+ world_sz = i + 1;
+ }
+
+ /* second pass to fill in missing references */
+ for(size_t i = 0; i < sz; ++i)
+ {
+ for(int dir = 0; dir < NUM_DIRECTIONS; ++dir)
+ {
+ const char *adjacent_room = world[i].data.adjacent[dir];
+ if(adjacent_room)
+ {
+ struct room_t *room = room_linear_search(adjacent_room);
+ if(room)
+ world[i].adjacent[dir] = room->id;
+ else
+ error("unknown room '%s' referenced from '%s'", adjacent_room, world[i].data.uniq_id);
+ }
+ else
+ world[i].adjacent[dir] = ROOM_NONE;
+ }
+ }
+
+ /* third pass to call all the init handlers */
+ for(size_t i = 0; i < world_sz; ++i)
+ if(world[i].data.hook_init)
+ world[i].data.hook_init(world[i].id);
+
+ hash_free(map);
+}
diff --git a/src/server.c b/src/server.c
index 598dd8d..a276a02 100644
--- a/src/server.c
+++ b/src/server.c
@@ -215,6 +215,15 @@ static void req_send_desc(unsigned char *data, size_t len, struct child_data *se
write(sender->outpipe[1], &newline, 1);
}
+static void req_send_roomname(unsigned char *data, size_t len, struct child_data *sender)
+{
+ struct room_t *room = room_get(sender->room);
+ write(sender->outpipe[1], room->data.name, strlen(room->data.name) + 1);
+
+ char newline = '\n';
+ write(sender->outpipe[1], &newline, 1);
+}
+
static void req_set_room(unsigned char *data, size_t len, struct child_data *sender)
{
room_id id = *((room_id*)data);
@@ -228,6 +237,7 @@ static void req_move_room(unsigned char *data, size_t len, struct child_data *se
struct room_t *current = room_get(sender->room);
/* TODO: checking */
+ sig_printf("Moving in direction %d\n", dir);
room_id new = current->adjacent[dir];
int status;
if(new != ROOM_NONE)
@@ -266,7 +276,8 @@ static const struct child_request {
{ REQ_CHANGEUSER, true, CHILD_SENDER, req_change_user, NULL, REQ_NOP },
{ REQ_KICK, true, CHILD_ALL, req_kick_client, NULL, REQ_NOP },
{ REQ_WAIT, false, CHILD_NONE, NULL, req_wait, REQ_NOP },
- { REQ_LOOK, false, CHILD_NONE, NULL, req_send_desc, REQ_BCASTMSG },
+ { REQ_GETROOMDESC, false, CHILD_NONE, NULL, req_send_desc, REQ_BCASTMSG },
+ { REQ_GETROOMNAME, false, CHILD_NONE, NULL, req_send_roomname, REQ_BCASTMSG },
{ REQ_SETROOM, true, CHILD_NONE, NULL, req_set_room, REQ_NOP },
{ REQ_MOVE, true, CHILD_NONE, NULL, req_move_room, REQ_MOVE },
};
diff --git a/src/test.c b/src/test.c
new file mode 100644
index 0000000..23a7530
--- /dev/null
+++ b/src/test.c
@@ -0,0 +1,10 @@
+#include "hash.h"
+#include <string.h>
+
+int main()
+{
+ struct hash_map *map = hash_init(10, hash_djb, strcmp);
+ hash_insert(map, "a", 42);
+ hash_insert(map, "b", 32);
+ printf("weird. %d\n", hash_lookup(map, "a"));
+}
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..6efcb76
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,7 @@
+#include "netcosm.h"
+
+void remove_cruft(char *str)
+{
+ char *junk;
+ strtok_r(str, "\r\n", &junk);
+}