diff options
| author | Franklin Wei <git@fwei.tk> | 2015-12-24 19:18:45 -0500 |
|---|---|---|
| committer | Franklin Wei <git@fwei.tk> | 2015-12-24 19:18:45 -0500 |
| commit | 53c15b0461ee39a4c32e61ff484389efb1e91d84 (patch) | |
| tree | c26e64930e1d73960eebc26b02d9d2185d2e1aef /src | |
| parent | 28f94a54984fa7aa46fcb25e7991c1136329670f (diff) | |
| download | netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.zip netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.tar.gz netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.tar.bz2 netcosm-53c15b0461ee39a4c32e61ff484389efb1e91d84.tar.xz | |
stuff
Diffstat (limited to 'src')
| -rw-r--r-- | src/auth.c | 2 | ||||
| -rw-r--r-- | src/client.c | 75 | ||||
| -rw-r--r-- | src/hash.c | 100 | ||||
| -rw-r--r-- | src/hash.h | 18 | ||||
| -rw-r--r-- | src/netcosm.h | 7 | ||||
| -rw-r--r-- | src/room.c | 84 | ||||
| -rw-r--r-- | src/server.c | 13 | ||||
| -rw-r--r-- | src/test.c | 10 | ||||
| -rw-r--r-- | src/util.c | 7 |
9 files changed, 293 insertions, 23 deletions
@@ -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); +} |