diff options
| author | Franklin Wei <git@fwei.tk> | 2015-12-30 15:10:05 -0500 |
|---|---|---|
| committer | Franklin Wei <git@fwei.tk> | 2015-12-30 15:10:05 -0500 |
| commit | 954fffd4845642e2fa3af0ee75e845ef68497766 (patch) | |
| tree | 234219215e2fc86d62cdafa50daaea24ec439f69 | |
| parent | 22f5eaa809a8daac6ce8bf421b89290f7258b42e (diff) | |
| download | netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.zip netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.tar.gz netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.tar.bz2 netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.tar.xz | |
docs and stuff
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | src/hash.h | 23 | ||||
| -rw-r--r-- | src/netcosm.h | 54 | ||||
| -rw-r--r-- | src/room.c | 32 | ||||
| -rw-r--r-- | src/server.c | 15 | ||||
| -rw-r--r-- | worlds/test.c | 13 |
6 files changed, 81 insertions, 58 deletions
@@ -4,7 +4,7 @@ PLATFORM = unix NETCOSM_OBJ = src/server.o src/client.o src/auth.o src/telnet.o src/util.o src/room.o worlds/test.o src/hash.o -CFLAGS = -O3 -g -I src/ -I target/$(PLATFORM) -Wall -Wextra -Wshadow -std=gnu99 +CFLAGS = -Og -g -I src/ -I target/$(PLATFORM) -Wall -Wextra -Wshadow -std=gnu99 LDFLAGS = -lgcrypt HEADERS = src/netcosm.h src/hash.h src/telnet.h @@ -30,10 +30,18 @@ void *hash_init(size_t tabsz, unsigned (*hash_fn)(const void*), void hash_setfreedata_cb(void*, void (*cb)(void *data)); void hash_setfreekey_cb(void*, void (*cb)(void *key)); +/* + * free all data associated with a map handle + * + * if callbacks for free'ing keys or data are installed, they will be + * called. + */ void hash_free(void*); -/* insert a pair, returns null if not already found, otherwise - return the existing data pointer */ +/* + * insert a pair, returns null if not already found, otherwise returns + * the existing data pointer + */ void *hash_insert(void*, const void *key, const void *data); /* returns NULL if not found */ @@ -41,8 +49,15 @@ void *hash_lookup(void*, const void *key); bool hash_remove(void *ptr, const void *key); -/* use like you would strtok_r */ -/* allocates a buffer that's freed once all elements are processed */ +/* + * use like you would strtok_r + * + * allocates a buffer that's freed once all elements are processed if + * you must stop iteration without processing every element, + * free(*saved) + * + * if keyptr!=NULL, the key pointer will be saved to *keyptr + */ void *hash_iterate(void *map, void **saved, void **keyptr); struct hash_pair { diff --git a/src/netcosm.h b/src/netcosm.h index 31edb50..3e056d2 100644 --- a/src/netcosm.h +++ b/src/netcosm.h @@ -16,6 +16,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#ifndef _NC_H_ +#define _NC_H_ #include <arpa/inet.h> #include <ctype.h> #include <errno.h> @@ -39,6 +41,7 @@ #include <time.h> #include <unistd.h> +#include "auth.h" #include "hash.h" #include "telnet.h" @@ -55,18 +58,19 @@ /* child<->master commands */ /* children might not implement all of these */ /* meanings might be different for the server and child, see comments */ -#define REQ_NOP 0 /* server, child: do nothing */ -#define REQ_BCASTMSG 1 /* server: broadcast text; child: print following text */ -#define REQ_LISTCLIENTS 2 /* server: list childs */ -#define REQ_CHANGESTATE 3 /* server: change child state flag */ -#define REQ_CHANGEUSER 4 /* server: change child login name */ -#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_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 */ +#define REQ_NOP 0 /* server, child: do nothing */ +#define REQ_BCASTMSG 1 /* server: broadcast text; child: print following text */ +#define REQ_LISTCLIENTS 2 /* server: list childs */ +#define REQ_CHANGESTATE 3 /* server: change child state flag */ +#define REQ_CHANGEUSER 4 /* server: change child login name */ +#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_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 */ +#define REQ_LISTROOMCLIENTS 12 /* server: list clients in child's room */ /* child states, sent as an int to the master */ #define STATE_INIT 0 /* initial state */ @@ -108,12 +112,6 @@ typedef int room_id; -struct authinfo_t { - bool success; - const char *user; - int authlevel; -}; - /* used by the room module to keep track of users in rooms */ struct user_t { struct child_data *data; @@ -178,21 +176,16 @@ struct room_t { /* linked list for users, random access is rare */ struct user_t *users; + int num_users; }; +extern const struct roomdata_t netcosm_world[]; +extern const size_t netcosm_world_sz; +extern const char *netcosm_world_name; + /* called for every client */ void client_main(int sock, struct sockaddr_in *addr, int, int to_parent, int from_parent); -void first_run_setup(void); - -/* authorization */ -struct authinfo_t auth_check(const char *user, const char *pass); - -/* add or change a user, NOT reentrant */ -bool auth_user_add(const char *user, const char *pass, int authlevel); -bool auth_user_del(const char *user); -void auth_user_list(void); - void out(const char *fmt, ...) __attribute__((format(printf,1,2))); void out_raw(const unsigned char*, size_t); @@ -201,8 +194,8 @@ void telnet_handle_command(const unsigned char*); void telnet_echo_on(void); void telnet_echo_off(void); -void world_init(const struct roomdata_t *data, size_t sz); -bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz); +void world_init(const struct roomdata_t *data, size_t sz, const char *name); +bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz, const char *world_name); void world_save(const char *fname); struct room_t *room_get(room_id id); @@ -215,3 +208,4 @@ void world_free(void); void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, ...); void debugf_real(const char *fmt, ...); void remove_cruft(char*); +#endif @@ -21,6 +21,7 @@ /* processed world data */ static struct room_t *world; static size_t world_sz; +static char *world_name; struct room_t *room_get(room_id id) { @@ -32,6 +33,9 @@ bool room_user_add(room_id id, struct child_data *child) struct room_t *room = room_get(id); /* make sure there are no duplicates */ + if(!room) + error("unknown room %d", id); + struct user_t *iter = room->users, *last = NULL; while(iter) { @@ -50,6 +54,9 @@ bool room_user_add(room_id id, struct child_data *child) last->next = new; else room->users = new; + + ++room->num_users; + return true; } @@ -67,6 +74,7 @@ bool room_user_del(room_id id, struct child_data *child) else room->users = iter->next; free(iter); + --room->num_users; return true; } last = iter; @@ -112,6 +120,7 @@ void world_save(const char *fname) uint32_t magic = WORLD_MAGIC; write(fd, &magic, sizeof(magic)); write(fd, &world_sz, sizeof(world_sz)); + write_string(fd, world_name); for(unsigned i = 0; i < world_sz; ++i) { write_roomid(fd, &world[i].id); @@ -153,7 +162,14 @@ void world_free(void) } } -bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz) +/** + * Loads a world using data on disk and in memory. + * + * @param fname world file + * @param data world module data + * @param data_sz number of rooms in world module + */ +bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz, const char *name) { int fd = open(fname, O_RDONLY); if(fd < 0) @@ -162,16 +178,25 @@ bool world_load(const char *fname, const struct roomdata_t *data, size_t data_sz read(fd, &magic, sizeof(magic)); if(magic != WORLD_MAGIC) return false; - read(fd, &world_sz, sizeof(world_sz)); if(world) world_free(); + read(fd, &world_sz, sizeof(world_sz)); + if(world_sz != data_sz) return false; world = calloc(world_sz, sizeof(struct room_t)); + world_name = read_string(fd); + if(strcmp(name, world_name)) + { + free(world_name); + debugf("Incompatible world state.\n"); + return false; + } + for(unsigned i = 0; i < world_sz; ++i) { world[i].id = read_roomid(fd); @@ -190,11 +215,12 @@ static SIMP_HASH(enum direction_t, dir_hash); static SIMP_EQUAL(enum direction_t, dir_equal); /* loads room data (supplied by the world module) into our internal format */ -void world_init(const struct roomdata_t *data, size_t sz) +void world_init(const struct roomdata_t *data, size_t sz, const char *name) { printf("Loading world with %lu rooms.\n", sz); world = calloc(sz, sizeof(struct room_t)); world_sz = 0; + world_name = strdup(name); void *map = hash_init(1, hash_djb, compare_strings); diff --git a/src/server.c b/src/server.c index 3f4e9cc..da26279 100644 --- a/src/server.c +++ b/src/server.c @@ -318,7 +318,8 @@ static void empty_pipe(int fd) /** * Here's how child-parent requests work * 1. Child writes its PID and length of request to the parent's pipe, followed - * by up to MSG_MAX bytes of data. + * by up to MSG_MAX bytes of data. If the length exceeds MSG_MAX bytes, the + * request will be ignored. * 1.1 Child spins until parent response. * 2. Parent handles the request. * 3. Parent writes its PID and length of message back to the child(ren). @@ -492,7 +493,7 @@ void init_signals(void) sigaddset(&sa.sa_mask, SIGCHLD); sa.sa_sigaction = sigchld_handler; // reap all dead processes sa.sa_flags = SA_RESTART | SA_SIGINFO; - if (sigaction(SIGCHLD, &sa, NULL) < 0) + if(sigaction(SIGCHLD, &sa, NULL) < 0) error("sigaction"); sigemptyset(&sa.sa_mask); @@ -512,6 +513,7 @@ void init_signals(void) error("sigaction"); sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGPIPE); sa.sa_handler = SIG_IGN; sa.sa_flags = SA_RESTART; if(sigaction(SIGPIPE, &sa, NULL) < 0) @@ -536,22 +538,19 @@ static void check_userfile(void) error("cannot access "USERFILE); } -/* "raw" world data, provided by the world module */ -extern const struct roomdata_t netcosm_world[]; -extern const size_t netcosm_world_sz; - static void load_worldfile(void) { if(access(WORLDFILE, F_OK) < 0) { - world_init(netcosm_world, netcosm_world_sz); + world_init(netcosm_world, netcosm_world_sz, netcosm_world_name); world_save(WORLDFILE); } else if(access(WORLDFILE, R_OK | W_OK) < 0) error("cannot access "WORLDFILE); else - world_load(WORLDFILE, netcosm_world, netcosm_world_sz); + if(!world_load(WORLDFILE, netcosm_world, netcosm_world_sz, netcosm_world_name)) + error("Failed to load world from disk.\nTry removing "WORLDFILE".\n"); } static int server_bind(void) diff --git a/worlds/test.c b/worlds/test.c index 35ad50d..498e31c 100644 --- a/worlds/test.c +++ b/worlds/test.c @@ -33,18 +33,7 @@ const struct roomdata_t netcosm_world[] = { NULL, NULL, }, - - { - "test", - "blah", - "blah", - { "starting_room", NONE_NE, NONE_E, NONE_SE, NONE_S, NONE_SW, "starting_room", NONE_NW, NONE_UP, NONE_DN, NONE_IN, NONE_OT }, - NULL, - NULL, - NULL, - NULL - }, - }; const size_t netcosm_world_sz = ARRAYLEN(netcosm_world); +const char *netcosm_world_name = "Test World 1.1"; |