aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2015-12-30 15:10:05 -0500
committerFranklin Wei <git@fwei.tk>2015-12-30 15:10:05 -0500
commit954fffd4845642e2fa3af0ee75e845ef68497766 (patch)
tree234219215e2fc86d62cdafa50daaea24ec439f69 /src
parent22f5eaa809a8daac6ce8bf421b89290f7258b42e (diff)
downloadnetcosm-954fffd4845642e2fa3af0ee75e845ef68497766.zip
netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.tar.gz
netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.tar.bz2
netcosm-954fffd4845642e2fa3af0ee75e845ef68497766.tar.xz
docs and stuff
Diffstat (limited to 'src')
-rw-r--r--src/hash.h23
-rw-r--r--src/netcosm.h54
-rw-r--r--src/room.c32
-rw-r--r--src/server.c15
4 files changed, 79 insertions, 45 deletions
diff --git a/src/hash.h b/src/hash.h
index 3abba9a..28a5352 100644
--- a/src/hash.h
+++ b/src/hash.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
diff --git a/src/room.c b/src/room.c
index 80447ac..b874f77 100644
--- a/src/room.c
+++ b/src/room.c
@@ -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)