diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/auth.c | 6 | ||||
| -rw-r--r-- | src/auth.h | 2 | ||||
| -rw-r--r-- | src/client.c | 14 | ||||
| -rw-r--r-- | src/client.h | 45 | ||||
| -rw-r--r-- | src/globals.h | 89 | ||||
| -rw-r--r-- | src/hash.c | 6 | ||||
| -rw-r--r-- | src/netcosm.h | 214 | ||||
| -rw-r--r-- | src/room.c | 6 | ||||
| -rw-r--r-- | src/room.h | 88 | ||||
| -rw-r--r-- | src/server.c | 32 | ||||
| -rw-r--r-- | src/server.h | 47 | ||||
| -rw-r--r-- | src/server_reqs.c | 6 | ||||
| -rw-r--r-- | src/telnet.c | 5 | ||||
| -rw-r--r-- | src/userdb.c | 7 | ||||
| -rw-r--r-- | src/userdb.h | 28 | ||||
| -rw-r--r-- | src/util.c | 2 | ||||
| -rw-r--r-- | src/util.h | 26 |
17 files changed, 391 insertions, 232 deletions
@@ -16,7 +16,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "globals.h" + +#include "auth.h" +#include "client.h" +#include "userdb.h" static bool valid_login_name(const char *name); @@ -33,6 +33,8 @@ struct authinfo_t { /* makes admin account */ void first_run_setup(void); +struct userdata_t; + /* NULL on failure, user data struct on success */ struct userdata_t *auth_check(const char *user, const char *pass); diff --git a/src/client.c b/src/client.c index 7b4a9cc..37f9c23 100644 --- a/src/client.c +++ b/src/client.c @@ -16,7 +16,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "globals.h" + +#include "auth.h" +#include "client.h" +#include "hash.h" +#include "server.h" +#include "room.h" +#include "telnet.h" +#include "util.h" static bool admin = false; @@ -178,6 +186,9 @@ void sig_rt_0_handler(int s, siginfo_t *info, void *v) (void) s; (void) v; + if(!are_child) + return; + /* we only listen to requests from our parent */ if(info->si_pid != getppid()) { @@ -212,6 +223,7 @@ void sig_rt_0_handler(int s, siginfo_t *info, void *v) returned_reqdata.boolean = status; if(!status) out("Cannot go that way.\n"); + break; } case REQ_GETUSERDATA: { diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..be75c03 --- /dev/null +++ b/src/client.h @@ -0,0 +1,45 @@ +/* + * NetCosm - a MUD server + * Copyright (C) 2016 Franklin Wei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* You should use #pragma once everywhere. */ +#pragma once + +#include "room.h" +#include "userdb.h" + +enum reqdata_typespec { TYPE_NONE = 0, TYPE_USERDATA, TYPE_BOOLEAN } reqdata_type; + +union reqdata_t { + struct userdata_t userdata; + bool boolean; +}; + +extern enum reqdata_typespec reqdata_type; +extern union reqdata_t returned_reqdata; + +/* call from child process ONLY */ +void send_master(unsigned char cmd, const void *data, size_t sz); + +/* the master sends the child SIGRTMIN+0 */ +void sig_rt_0_handler(int s, siginfo_t *info, void *v); + +void out(const char *fmt, ...) __attribute__((format(printf,1,2))); +void out_raw(const unsigned char*, size_t); + +/* called for every client */ +void client_main(int sock, struct sockaddr_in *addr, int, int to_parent, int from_parent); diff --git a/src/globals.h b/src/globals.h new file mode 100644 index 0000000..35db514 --- /dev/null +++ b/src/globals.h @@ -0,0 +1,89 @@ +/* + * NetCosm - a MUD server + * Copyright (C) 2016 Franklin Wei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* You should use #pragma once everywhere. */ +#pragma once + +#define _GNU_SOURCE + +#include <ev.h> +#include <gcrypt.h> + +#include <arpa/inet.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <poll.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/file.h> +#include <sys/ipc.h> +#include <sys/mman.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +/* convenience macros */ +#define ARRAYLEN(x) (sizeof(x)/sizeof(x[0])) +#define MAX(a,b) ((a>b)?(a):(b)) +#define MIN(a,b) ((a<b)?(a):(b)) + +/* global constants */ +#define USERFILE "users.dat" +#define WORLDFILE "world.dat" +#define WORLD_MAGIC 0xff467777 +#define MAX_FAILURES 3 +#define NETCOSM_VERSION "0.2" + +/* username length */ +#define MAX_NAME_LEN 32 + +/* for convenience when writing world specs */ +#define NONE_N NULL +#define NONE_NE NULL +#define NONE_E NULL +#define NONE_SE NULL +#define NONE_S NULL +#define NONE_SW NULL +#define NONE_W NULL +#define NONE_NW NULL +#define NONE_UP NULL +#define NONE_DN NULL +#define NONE_IN NULL +#define NONE_OT NULL + +#include "util.h" + +/* needs to be less than PIPE_BUF, which is 4096 */ +#define MSG_MAX 2048 +#ifndef NDEBUG +#define debugf(fmt,...) debugf_real(__func__, __LINE__, __FILE__, fmt, ##__VA_ARGS__) +#define sig_debugf debugf +#else +#define debugf(fmt,...) +#define sig_debugf debugf +#endif @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "hash.h" #include <stdlib.h> #include <string.h> @@ -83,7 +83,6 @@ void hash_setfreedata_cb(void *ptr, void (*cb)(void *data)) void hash_free(void *ptr) { - sig_debugf("freeing map\n"); if(ptr) { struct hash_map *map = ptr; @@ -95,10 +94,7 @@ void hash_free(void *ptr) struct hash_node *next = node->next; if(map->free_data) - { - debugf("freeing data\n"); map->free_data((void*)node->data); - } if(map->free_key) map->free_key((void*)node->key); free(node); diff --git a/src/netcosm.h b/src/netcosm.h deleted file mode 100644 index 34e2f3d..0000000 --- a/src/netcosm.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * NetCosm - a MUD server - * Copyright (C) 2016 Franklin Wei - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* You should use #pragma once everywhere. */ -#pragma once - -#define _GNU_SOURCE - -#include <ev.h> -#include <gcrypt.h> - -#include <arpa/inet.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <netdb.h> -#include <netinet/in.h> -#include <poll.h> -#include <signal.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/file.h> -#include <sys/ipc.h> -#include <sys/mman.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <time.h> -#include <unistd.h> - -#define USERFILE "users.dat" -#define WORLDFILE "world.dat" -#define WORLD_MAGIC 0xff467777 -#define MAX_FAILURES 3 -#define NETCOSM_VERSION "0.2" - -#define MAX_NAME_LEN 32 - -#define PRIV_NONE -1 -#define PRIV_USER 0 -#define PRIV_ADMIN 1337 - -/* for convenience when writing world specs */ -#define NONE_N NULL -#define NONE_NE NULL -#define NONE_E NULL -#define NONE_SE NULL -#define NONE_S NULL -#define NONE_SW NULL -#define NONE_W NULL -#define NONE_NW NULL -#define NONE_UP NULL -#define NONE_DN NULL -#define NONE_IN NULL -#define NONE_OT NULL - -/* needs to be less than PIPE_BUF, which is 4096 */ -#define MSG_MAX 2048 - -#define ARRAYLEN(x) (sizeof(x)/sizeof(x[0])) -#define MAX(a,b) ((a>b)?(a):(b)) -#define MIN(a,b) ((a<b)?(a):(b)) - -#ifndef NDEBUG -#define debugf(fmt,...) debugf_real(__func__, __LINE__, __FILE__, fmt, ##__VA_ARGS__) -#define sig_debugf debugf -#else -#define debugf(fmt,...) -#define sig_debugf debugf -#endif - -#define ROOM_NONE -1 - -typedef int room_id; - -enum direction_t { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_UP, DIR_DN, DIR_IN, DIR_OT, NUM_DIRECTIONS }; - -/* the data we get from a world module */ -struct roomdata_t { - /* the non-const pointers can be modified by the world module */ - const char * const uniq_id; - - /* mutable properties */ - char *name; - char *desc; - - const char * const adjacent[NUM_DIRECTIONS]; - - void (* const hook_init)(room_id id); - void (* const hook_enter)(room_id room, pid_t player); - void (* const hook_say)(room_id room, pid_t player, const char *msg); - void (* const hook_leave)(room_id room, pid_t player); -}; - -struct room_t { - room_id id; - struct roomdata_t data; - - room_id adjacent[NUM_DIRECTIONS]; - - /* arrays instead of linked lists because insertion should be rare for these */ - size_t objects_sz; - struct object_t *objects; - - size_t verbs_sz; - struct verb_t *verbs; - - /* linked list for users, random access is rare */ - struct user_t *users; - int num_users; -}; - -/* used by the room module to keep track of users in rooms */ -struct user_t { - struct child_data *data; - struct user_t *next; -}; - -struct object_t { - const char *class; - -}; - -struct verb_t { - const char *name; - - /* toks is strtok_r's pointer */ - void (*execute)(const char *toks); -}; - -struct child_data { - pid_t pid; - int readpipe[2]; - int outpipe[2]; - - int state; - room_id room; - char *user; - - ev_io *io_watcher; - ev_child *sigchld_watcher; - struct ev_loop *loop; - - struct in_addr addr; -}; - -#include "auth.h" -#include "hash.h" -#include "server_reqs.h" -#include "telnet.h" -#include "userdb.h" - -/* globals */ -extern const struct roomdata_t netcosm_world[]; -extern const size_t netcosm_world_sz; -extern const char *netcosm_world_name; - -extern volatile int num_clients; -extern void *child_map; - -extern enum reqdata_typespec { TYPE_NONE = 0, TYPE_USERDATA, TYPE_BOOLEAN } reqdata_type; -extern union reqdata_t { - struct userdata_t userdata; - bool boolean; -} returned_reqdata; - -extern bool are_child; - -/* called for every client */ -void client_main(int sock, struct sockaddr_in *addr, int, int to_parent, int from_parent); - -void out(const char *fmt, ...) __attribute__((format(printf,1,2))); -void out_raw(const unsigned char*, size_t); - -/* room/world */ -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); -bool room_user_add(room_id id, struct child_data *child); -bool room_user_del(room_id id, struct child_data *child); - -void world_free(void); - -/* utility functions */ -void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, ...); -void debugf_real(const char*, int, const char*, const char *fmt, ...); -void remove_cruft(char*); -void all_upper(char*); - -/* call from child process ONLY */ -void send_master(unsigned char cmd, const void *data, size_t sz); - -/* the master sends the child SIGRTMIN+0 */ -void sig_rt_0_handler(int s, siginfo_t *info, void *v); @@ -16,7 +16,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "globals.h" + +#include "hash.h" +#include "server.h" +#include "room.h" /* processed world data */ static struct room_t *world; diff --git a/src/room.h b/src/room.h new file mode 100644 index 0000000..ad7898f --- /dev/null +++ b/src/room.h @@ -0,0 +1,88 @@ +/* + * NetCosm - a MUD server + * Copyright (C) 2016 Franklin Wei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +typedef enum room_id { ROOM_NONE = -1 } room_id; + +typedef enum obj_id { OBJ_NONE = -1 } obj_id; + +enum direction_t { DIR_N = 0, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_UP, DIR_DN, DIR_IN, DIR_OT, NUM_DIRECTIONS }; + +/* the data we get from a world module */ +struct roomdata_t { + /* the non-const pointers can be modified by the world module */ + const char * const uniq_id; + + /* mutable properties */ + char *name; + char *desc; + + const char * const adjacent[NUM_DIRECTIONS]; + + void (* const hook_init)(room_id id); + void (* const hook_enter)(room_id room, pid_t player); + void (* const hook_say)(room_id room, pid_t player, const char *msg); + void (* const hook_leave)(room_id room, pid_t player); +}; + +struct user_t { + struct child_data *data; + struct user_t *next; +}; + +struct object_t { + const char *class; + obj_id id; +}; + +struct verb_t { + const char *name; + + /* toks is strtok_r's pointer */ + void (*execute)(const char *toks); +}; + +struct room_t { + room_id id; + struct roomdata_t data; + + room_id adjacent[NUM_DIRECTIONS]; + + /* arrays instead of linked lists because insertion should be rare for these */ + size_t objects_sz; + struct object_t *objects; + + size_t verbs_sz; + struct verb_t *verbs; + + /* linked list for users, random access is rare */ + struct user_t *users; + int num_users; +}; + +/* room/world */ +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); +bool room_user_add(room_id id, struct child_data *child); +bool room_user_del(room_id id, struct child_data *child); + +void world_free(void); diff --git a/src/server.c b/src/server.c index b04e7d1..5b963b6 100644 --- a/src/server.c +++ b/src/server.c @@ -16,7 +16,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "globals.h" + +#include "client.h" +#include "hash.h" +#include "server.h" +#include "userdb.h" +#include "util.h" #define PORT 1234 #define BACKLOG 100 @@ -97,6 +103,21 @@ static void __attribute__((noreturn)) serv_cleanup(void) { sig_debugf("Shutdown server.\n"); + /* kill all our children (usually init claims them and wait()'s + for them, but not always) */ + struct sigaction sa; + sigfillset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGCHLD); + sigaction(SIGCHLD, &sa, NULL); /* kill all children */ + void *ptr = child_map, *save; + do { + struct child_data *child = hash_iterate(ptr, &save, NULL); + if(!child) + break; + ptr = NULL; + kill(child->pid, SIGKILL); + } while(1); + handle_disconnects(); + if(shutdown(server_socket, SHUT_RDWR) > 0) error("shutdown"); @@ -179,6 +200,10 @@ static void check_userfile(void) static void load_worldfile(void) { + extern const struct roomdata_t netcosm_world[]; + extern const size_t netcosm_world_sz; + extern const char *netcosm_world_name; + if(access(WORLDFILE, F_OK) < 0) { world_init(netcosm_world, netcosm_world_sz, netcosm_world_name); @@ -323,6 +348,9 @@ static void new_connection_cb(EV_P_ ev_io *w, int revents) int main(int argc, char *argv[]) { + assert(ev_version_major() == EV_VERSION_MAJOR && + ev_version_minor() >= EV_VERSION_MINOR); + if(argc != 2) port = PORT; else @@ -353,7 +381,7 @@ int main(int argc, char *argv[]) ev_io server_watcher; ev_io_init(&server_watcher, new_connection_cb, server_socket, EV_READ); - //ev_set_priority(&server_watcher, EV_MAXPRI); + ev_set_priority(&server_watcher, EV_MAXPRI); ev_io_start(EV_A_ &server_watcher); ev_loop(loop, 0); diff --git a/src/server.h b/src/server.h new file mode 100644 index 0000000..3117955 --- /dev/null +++ b/src/server.h @@ -0,0 +1,47 @@ +/* + * NetCosm - a MUD server + * Copyright (C) 2016 Franklin Wei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* You should use #pragma once everywhere. */ +#pragma once + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "server_reqs.h" +#include "room.h" + +struct child_data { + pid_t pid; + int readpipe[2]; + int outpipe[2]; + + int state; + room_id room; + char *user; + + ev_io *io_watcher; + ev_child *sigchld_watcher; + struct ev_loop *loop; + + struct in_addr addr; +}; + +extern volatile int num_clients; +extern void *child_map; +extern bool are_child; diff --git a/src/server_reqs.c b/src/server_reqs.c index cdafe7b..fd92b00 100644 --- a/src/server_reqs.c +++ b/src/server_reqs.c @@ -1,4 +1,8 @@ -#include "netcosm.h" +#include "globals.h" + +#include "hash.h" +#include "server.h" +#include "userdb.h" static volatile sig_atomic_t num_acks_wanted, num_acks_recvd, inc_acks = 0; diff --git a/src/telnet.c b/src/telnet.c index 038c54c..9e664ea 100644 --- a/src/telnet.c +++ b/src/telnet.c @@ -16,7 +16,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "globals.h" + +#include "client.h" +#include "telnet.h" int telnet_handle_command(const unsigned char *buf) { diff --git a/src/userdb.c b/src/userdb.c index ddf1ced..a98a33e 100644 --- a/src/userdb.c +++ b/src/userdb.c @@ -1,4 +1,9 @@ -#include "netcosm.h" +#include "globals.h" + +#include "client.h" +#include "hash.h" +#include "server.h" +#include "userdb.h" static void *map = NULL; static char *db_file = NULL; diff --git a/src/userdb.h b/src/userdb.h index a941e9a..36c4558 100644 --- a/src/userdb.h +++ b/src/userdb.h @@ -1,7 +1,29 @@ +/* + * NetCosm - a MUD server + * Copyright (C) 2016 Franklin Wei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once -#include "netcosm.h" #include "auth.h" +#include "room.h" + +/*** functions for the master process ONLY ***/ + +typedef enum priv_t { PRIV_NONE = -1, PRIV_USER = 0, PRIV_ADMIN = 1337 } priv_t; struct userdata_t { char username[MAX_NAME_LEN + 1]; @@ -11,12 +33,10 @@ struct userdata_t { /* in hex + NULL terminator */ char passhash[AUTH_HASHLEN * 2 + 1]; - int priv; + priv_t priv; room_id room; }; -/*** functions for the master process ONLY ***/ - /* call before using anything else */ void userdb_init(const char *dbfile); @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "netcosm.h" +#include "globals.h" void remove_cruft(char *str) { diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..8cc44d5 --- /dev/null +++ b/src/util.h @@ -0,0 +1,26 @@ +/* + * NetCosm - a MUD server + * Copyright (C) 2016 Franklin Wei + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* You should use #pragma once everywhere. */ +#pragma once + +/* utility functions */ +void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, ...); +void debugf_real(const char*, int, const char*, const char *fmt, ...); +void remove_cruft(char*); +void all_upper(char*); |