/* WebROaR - Ruby Application Server - http://webroar.in/ * Copyright (C) 2009 Goonj LLC * * This file is part of WebROaR. * * WebROaR 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. * * WebROaR 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 WebROaR. If not, see . */ #include extern config_t *Config; static struct ev_loop *loop; //Event loop struct ev_idle idle_watcher; //Ideal watcher /************ Private functions **************************/ /** Create Server */ wr_svr_t* wr_svr_new(struct ev_loop* loop) { LOG_FUNCTION wr_svr_t* server = wr_malloc(wr_svr_t); if(!server) { LOG_ERROR(WARN, "Server object allocation failed. Returning ..."); return NULL; } //Get ebb server object ebb_server_init(&(server->ebb_svr),loop); #ifdef HAVE_GNUTLS if(Config->Server.flag & SERVER_SSL_SUPPORT) { //Initialize ebb server for SSL support ebb_server_init(&(server->secure_ebb_svr),loop); // Add GnuTLS support if(ebb_server_set_secure(&(server->secure_ebb_svr), Config->Server.SSL.certificate.str, Config->Server.SSL.key.str) < 0) { ebb_server_unlisten(&(server->secure_ebb_svr)); //free(server); //return NULL; LOG_ERROR(SEVERE,"ebb_server_set_secure() failed. Server can not run on SSL."); } else { server->secure_ebb_svr.data = server; server->secure_ebb_svr.new_connection = wr_new_conn_cb; } } #endif server->ebb_svr.data = server; server->ebb_svr.new_connection = wr_new_conn_cb; //Create Server Control object server->ctl = wr_svr_ctl_new(); if(!server->ctl) { ebb_server_unlisten(&(server->ebb_svr)); #ifdef HAVE_GNUTLS if(Config->Server.flag & SERVER_SSL_SUPPORT) { ebb_server_unlisten(&(server->secure_ebb_svr)); } #endif free(server); LOG_ERROR(WARN, "%s() control object allocation failed. Returning ...",__FUNCTION__); return NULL; } server->apps = NULL; server->default_app = NULL; server->resolver = wr_req_resolver_new(); if(server->resolver == NULL) { ebb_server_unlisten(&(server->ebb_svr)); #ifdef HAVE_GNUTLS if(Config->Server.flag & SERVER_SSL_SUPPORT) { ebb_server_unlisten(&(server->secure_ebb_svr)); } #endif free(server); LOG_ERROR(WARN, "Resolver object allocation failed. Returning ..."); return NULL; } return server; } /** Attach ideal watcher with event loop */ void attach_idle_watcher() { if(!ev_is_active(&idle_watcher)) { ev_idle_start (loop, &idle_watcher); } } /** Detach Ideal watcher from event loop*/ void detach_idle_watcher() { ev_idle_stop(loop, &idle_watcher); } /** Callback function for Ideal watcher */ void idle_cb (struct ev_loop *loop, struct ev_idle *w, int revents) { /*if(clients_in_use_p()) { rb_thread_schedule(); } else if(!rb_thread_alone()) {*/ /* if you have another long running thread running besides the ones used * for the webapp's requests you will run into performance problems in * ruby 1.8.x because rb_thread_select is slow. * (Don't worry - you're probably not doing this.) */ /* struct timeval select_timeout = { tv_sec: 0, tv_usec: 50000 }; fd_set server_fd_set; FD_ZERO(&server_fd_set); FD_SET(server->fd, &server_fd_set); rb_thread_select(server->fd+1, &server_fd_set, 0, 0, &select_timeout); } else { detach_idle_watcher(); }*/ } /***************************************************** * Server API Definition * *****************************************************/ /** Starts listening for requests */ int wr_svr_init(wr_svr_t** server) { //TODO: attach idle watcher //ev_idle_init (&idle_watcher, idle_cb); //attach_idle_watcher(); //Create and initialize Server object loop = ev_default_loop (0); *server = wr_svr_new(loop); if(*server == NULL) { LOG_ERROR(SEVERE,"Server is NULL"); return -1; } #ifdef HAVE_GNUTLS if(Config->Server.flag & SERVER_SSL_SUPPORT) { LOG_DEBUG(DEBUG,"SSL port = %d", Config->Server.SSL.port); if(ebb_server_listen_on_port(&(*server)->secure_ebb_svr, Config->Server.SSL.port) < 0) { LOG_ERROR(SEVERE,"ebb_server_listen_on_port(): failed. Port number = %d",Config->Server.SSL.port); printf("Port %d is already in use.\n", Config->Server.SSL.port); return -1; } } #endif LOG_DEBUG(DEBUG,"port = %d", Config->Server.port); //ebb server starts listening for request if(ebb_server_listen_on_port(&(*server)->ebb_svr, Config->Server.port) < 1) { printf("Port %d is already in use.\n", Config->Server.port); return -1; } (*server)->on_app_add = wr_app_add_cb; (*server)->on_app_remove = wr_app_remove_cb; (*server)->on_app_reload = wr_app_reload_cb; (*server)->on_wkr_add = wr_wkr_add_cb; (*server)->on_wkr_add_error = wr_wkr_add_error_cb; (*server)->on_wkr_remove = wr_wkr_remove_cb; (*server)->on_wkr_ping = wr_wkr_ping_cb; (*server)->on_wkr_conf_req = wr_app_conf_req_cb; (*server)->default_app = (*server)->static_app = NULL; return 0; } /** Destroy Server */ void wr_svr_free(wr_svr_t* server) { LOG_FUNCTION //Destroy ebb server object ebb_server_unlisten(&(server->ebb_svr)); #ifdef HAVE_GNUTLS //Destroy ebb server object used for SSL if(Config->Server.flag & SERVER_SSL_SUPPORT) ebb_server_unlisten(&(server->secure_ebb_svr)); #endif // Destroy application list if(server->apps) { wr_app_free(server->apps); server->apps = NULL; } if(server->static_app) { wr_app_free(server->static_app); server->apps = NULL; } //Destroy Server Control object wr_svr_ctl_free(server->ctl); wr_req_resolver_free(server->resolver); free(server); } /*********************************************************/