int evhtp::bind_socket(const char * baddr, uint16_t port, int backlog){ struct sockaddr_in sin; struct sockaddr * sa; size_t sin_len; memset(&sin, 0, sizeof(sin)); sin_len = sizeof(struct sockaddr_in); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = inet_addr(baddr); sa = (struct sockaddr *)&sin; return evhtp_bind_sockaddr(this, sa, sin_len, backlog); }
int main(int argc, char **argv) { init_config(argc, argv); open_authorizations("r"); init_webfinger(); /** OPEN MAGIC DATABASE **/ magic_cookie = magic_open(MAGIC_MIME); if(magic_load(magic_cookie, RS_MAGIC_DATABASE) != 0) { log_error("Failed to load magic database: %s", magic_error(magic_cookie)); exit(EXIT_FAILURE); } log_info("starting process: main"); if(prctl(PR_SET_NAME, "rs-serve [main]", 0, 0, 0) != 0) { log_error("Failed to set process name: %s", strerror(errno)); } /** SETUP EVENT BASE **/ rs_event_base = event_base_new(); ASSERT_NOT_NULL(rs_event_base, "event_base_new()"); log_debug("libevent method: %s", event_base_get_method(rs_event_base)); event_set_log_callback(log_event_base_message); // TODO: add error cb to base /** SETUP AUTH TOKENS HASH TABLE **/ auth_sessions = sm_new(1024); // FIXME: this a hardcoded value. /** SETUP MAIN LISTENER **/ struct sockaddr_in sin; memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(RS_PORT); evhtp_t *server = evhtp_new(rs_event_base, NULL); if(RS_USE_SSL) { evhtp_ssl_cfg_t ssl_config = { .pemfile = RS_SSL_CERT_PATH, .privfile = RS_SSL_KEY_PATH, .cafile = RS_SSL_CA_PATH, // what's this??? .capath = NULL, .ciphers = "RC4+RSA:HIGH:+MEDIUM:+LOW", .ssl_opts = SSL_OP_NO_SSLv2, .ssl_ctx_timeout = 60*60*48, .verify_peer = SSL_VERIFY_PEER, .verify_depth = 42, .x509_verify_cb = dummy_ssl_verify_callback, .x509_chk_issued_cb = dummy_check_issued_cb, .scache_type = evhtp_ssl_scache_type_internal, .scache_size = 1024, .scache_timeout = 1024, .scache_init = NULL, .scache_add = NULL, .scache_get = NULL, .scache_del = NULL }; if(evhtp_ssl_init(server, &ssl_config) != 0) { log_error("evhtp_ssl_init() failed"); exit(EXIT_FAILURE); } } /* WEBFINGER */ evhtp_callback_cb webfinger_cb = (RS_WEBFINGER_ENABLED ? handle_webfinger : reject_webfinger); evhtp_set_cb(server, "/.well-known/webfinger", webfinger_cb, NULL); // support legacy webfinger clients (we don't support XRD though): evhtp_set_cb(server, "/.well-known/host-meta", webfinger_cb, NULL); evhtp_set_cb(server, "/.well-known/host-meta.json", webfinger_cb, NULL); /* REMOTESTORAGE */ evhtp_callback_t *storage_cb = evhtp_set_regex_cb(server, "^/storage/([^/]+)/.*$", handle_storage, NULL); evhtp_set_hook(&storage_cb->hooks, evhtp_hook_on_request_fini, finish_request, NULL); if(evhtp_bind_sockaddr(server, (struct sockaddr*)&sin, sizeof(sin), 1024) != 0) { log_error("evhtp_bind_sockaddr() failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /** SETUP AUTH LISTENER **/ memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(RS_AUTH_PORT); evhtp_t *server_auth = evhtp_new(rs_event_base, NULL); if(RS_USE_SSL) { evhtp_ssl_cfg_t ssl_config = { .pemfile = RS_SSL_CERT_PATH, .privfile = RS_SSL_KEY_PATH, .cafile = RS_SSL_CA_PATH, // what's this??? .capath = NULL, .ciphers = "RC4+RSA:HIGH:+MEDIUM:+LOW", .ssl_opts = SSL_OP_NO_SSLv2, .ssl_ctx_timeout = 60*60*48, .verify_peer = SSL_VERIFY_PEER, .verify_depth = 42, .x509_verify_cb = dummy_ssl_verify_callback, .x509_chk_issued_cb = dummy_check_issued_cb, .scache_type = evhtp_ssl_scache_type_internal, .scache_size = 1024, .scache_timeout = 1024, .scache_init = NULL, .scache_add = NULL, .scache_get = NULL, .scache_del = NULL }; if(evhtp_ssl_init(server_auth, &ssl_config) != 0) { log_error("evhtp_ssl_init() failed"); exit(EXIT_FAILURE); } } /* AUTH */ evhtp_set_cb(server_auth, "/authenticate", handle_authenticate, NULL); evhtp_set_cb(server_auth, "/authorizations", handle_authorizations, NULL); evhtp_set_hook(&storage_cb->hooks, evhtp_hook_on_request_fini, finish_request, NULL); if(evhtp_bind_sockaddr(server_auth, (struct sockaddr*)&sin, sizeof(sin), 1024) != 0) { log_error("evhtp_bind_sockaddr() failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /** SETUP SIGNALS **/ sigset_t sigmask; sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGTERM); sigaddset(&sigmask, SIGCHLD); ASSERT_ZERO(sigprocmask(SIG_BLOCK, &sigmask, NULL), "sigprocmask()"); int sfd = signalfd(-1, &sigmask, SFD_NONBLOCK); ASSERT_NOT_EQ(sfd, -1, "signalfd()"); struct event *signal_event = event_new(rs_event_base, sfd, EV_READ | EV_PERSIST, handle_signal, NULL); event_add(signal_event, NULL); /** RUN EVENT LOOP **/ if(RS_DETACH) { int pid = fork(); if(pid == 0) { event_reinit(rs_event_base); if(RS_LOG_FILE == stdout) { log_warn("No --log-file option given. Future output will be lost."); freopen("/dev/null", "r", stdout); freopen("/dev/null", "r", stderr); } return event_base_dispatch(rs_event_base); } else { printf("rs-serve detached with pid %d\n", pid); if(RS_PID_FILE) { fprintf(RS_PID_FILE, "%d", pid); fflush(RS_PID_FILE); } _exit(EXIT_SUCCESS); } } else { if(RS_PID_FILE) { fprintf(RS_PID_FILE, "%d", getpid()); fflush(RS_PID_FILE); } return event_base_dispatch(rs_event_base); } }