Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * webview_thread.cpp - Thread that handles web interface requests 00004 * 00005 * Created: Mon Oct 13 17:51:31 2008 (I5 Developer's Day) 00006 * Copyright 2006-2008 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include "webview_thread.h" 00024 #include "static_processor.h" 00025 #include "blackboard_processor.h" 00026 #include "startpage_processor.h" 00027 #include "plugins_processor.h" 00028 #include "service_browse_handler.h" 00029 #include "header_generator.h" 00030 #include "footer_generator.h" 00031 #include "user_verifier.h" 00032 00033 #include <core/version.h> 00034 #include <core/exceptions/system.h> 00035 #include <utils/system/file.h> 00036 #include <utils/system/hostinfo.h> 00037 #include <webview/request_dispatcher.h> 00038 #include <webview/page_reply.h> 00039 #include <webview/server.h> 00040 #include <webview/url_manager.h> 00041 #include <webview/nav_manager.h> 00042 00043 #include <sys/wait.h> 00044 00045 using namespace fawkes; 00046 00047 00048 /** Prefix for the WebStaticRequestProcessor. */ 00049 const char *WebviewThread::STATIC_URL_PREFIX = "/static"; 00050 /** Prefix for the WebBlackBoardRequestProcessor. */ 00051 const char *WebviewThread::BLACKBOARD_URL_PREFIX = "/blackboard"; 00052 /** Prefix for the WebPluginsRequestProcessor. */ 00053 const char *WebviewThread::PLUGINS_URL_PREFIX = "/plugins"; 00054 00055 /** @class WebviewThread "webview_thread.h" 00056 * Webview Thread. 00057 * This thread runs the HTTP server and handles requests via the 00058 * WebRequestDispatcher. 00059 * @author Tim Niemueller 00060 */ 00061 00062 00063 /** Constructor. */ 00064 WebviewThread::WebviewThread() 00065 : Thread("WebviewThread", Thread::OPMODE_CONTINUOUS), 00066 LoggerAspect(&__cache_logger) 00067 { 00068 set_prepfin_conc_loop(true); 00069 } 00070 00071 00072 WebviewThread::~WebviewThread() 00073 { 00074 } 00075 00076 void 00077 WebviewThread::init() 00078 { 00079 __cfg_port = config->get_uint("/webview/port"); 00080 00081 bool __cfg_use_ssl = false; 00082 try { 00083 __cfg_use_ssl = config->get_bool("/webview/use_ssl"); 00084 } catch (Exception &e) {} 00085 00086 if (__cfg_use_ssl) { 00087 __cfg_ssl_create = false; 00088 try { 00089 __cfg_ssl_create = config->get_bool("/webview/ssl_create"); 00090 } catch (Exception &e) {} 00091 00092 __cfg_ssl_key = config->get_string("/webview/ssl_key"); 00093 __cfg_ssl_cert = config->get_string("/webview/ssl_cert"); 00094 00095 if (__cfg_ssl_key[0] != '/') 00096 __cfg_ssl_key = std::string(CONFDIR"/") + __cfg_ssl_key; 00097 00098 if (__cfg_ssl_cert[0] != '/') 00099 __cfg_ssl_cert = std::string(CONFDIR"/") + __cfg_ssl_cert; 00100 00101 logger->log_debug(name(), "Key: %s Cert: %s", __cfg_ssl_key.c_str(), 00102 __cfg_ssl_cert.c_str()); 00103 00104 if (! File::exists(__cfg_ssl_key.c_str())) { 00105 if (File::exists(__cfg_ssl_cert.c_str())) { 00106 throw Exception("Key file %s does not exist, but certificate file %s " 00107 "does", __cfg_ssl_key.c_str(), __cfg_ssl_cert.c_str()); 00108 } else if (__cfg_ssl_create) { 00109 ssl_create(__cfg_ssl_key.c_str(), __cfg_ssl_cert.c_str()); 00110 } else { 00111 throw Exception("Key file %s does not exist", __cfg_ssl_key.c_str()); 00112 } 00113 } else if (! File::exists(__cfg_ssl_cert.c_str())) { 00114 throw Exception("Certificate file %s does not exist, but key file %s " 00115 "does", __cfg_ssl_key.c_str(), __cfg_ssl_cert.c_str()); 00116 } 00117 } 00118 00119 bool __cfg_use_basic_auth = false; 00120 try { 00121 __cfg_use_basic_auth = config->get_bool("/webview/use_basic_auth"); 00122 } catch (Exception &e) {} 00123 __cfg_basic_auth_realm = "Fawkes Webview"; 00124 try { 00125 __cfg_basic_auth_realm = config->get_bool("/webview/basic_auth_realm"); 00126 } catch (Exception &e) {} 00127 00128 00129 __cache_logger.clear(); 00130 00131 __webview_service = new NetworkService(nnresolver, "Fawkes Webview on %h", 00132 "_http._tcp", __cfg_port); 00133 __webview_service->add_txt("fawkesver=%u.%u.%u", 00134 FAWKES_VERSION_MAJOR, FAWKES_VERSION_MINOR, 00135 FAWKES_VERSION_MICRO); 00136 __service_browse_handler = new WebviewServiceBrowseHandler(logger, __webview_service); 00137 00138 __header_gen = new WebviewHeaderGenerator(webview_nav_manager); 00139 __footer_gen = new WebviewFooterGenerator(__service_browse_handler); 00140 00141 __dispatcher = new WebRequestDispatcher(webview_url_manager, 00142 __header_gen, __footer_gen); 00143 00144 00145 try { 00146 if (__cfg_use_ssl) { 00147 __webserver = new WebServer(__cfg_port, __dispatcher, __cfg_ssl_key.c_str(), 00148 __cfg_ssl_cert.c_str(), logger); 00149 } else { 00150 __webserver = new WebServer(__cfg_port, __dispatcher, logger); 00151 } 00152 00153 if (__cfg_use_basic_auth) { 00154 __user_verifier = new WebviewUserVerifier(config, logger); 00155 __webserver->setup_basic_auth(__cfg_basic_auth_realm.c_str(), 00156 __user_verifier); 00157 } 00158 } catch (Exception &e) { 00159 delete __webview_service; 00160 delete __service_browse_handler; 00161 delete __header_gen; 00162 delete __footer_gen; 00163 delete __dispatcher; 00164 throw; 00165 } 00166 00167 00168 __startpage_processor = new WebviewStartPageRequestProcessor(&__cache_logger); 00169 __static_processor = new WebviewStaticRequestProcessor(STATIC_URL_PREFIX, RESDIR"/webview", logger); 00170 __blackboard_processor = new WebviewBlackBoardRequestProcessor(BLACKBOARD_URL_PREFIX, blackboard); 00171 __plugins_processor = new WebviewPluginsRequestProcessor(PLUGINS_URL_PREFIX, plugin_manager); 00172 webview_url_manager->register_baseurl("/", __startpage_processor); 00173 webview_url_manager->register_baseurl(STATIC_URL_PREFIX, __static_processor); 00174 webview_url_manager->register_baseurl(BLACKBOARD_URL_PREFIX, __blackboard_processor); 00175 webview_url_manager->register_baseurl(PLUGINS_URL_PREFIX, __plugins_processor); 00176 00177 webview_nav_manager->add_nav_entry(BLACKBOARD_URL_PREFIX, "BlackBoard"); 00178 webview_nav_manager->add_nav_entry(PLUGINS_URL_PREFIX, "Plugins"); 00179 00180 logger->log_info("WebviewThread", "Listening for HTTP connections on port %u", __cfg_port); 00181 00182 service_publisher->publish_service(__webview_service); 00183 service_browser->watch_service("_http._tcp", __service_browse_handler); 00184 00185 } 00186 00187 void 00188 WebviewThread::finalize() 00189 { 00190 service_publisher->unpublish_service(__webview_service); 00191 service_browser->unwatch_service("_http._tcp", __service_browse_handler); 00192 00193 webview_url_manager->unregister_baseurl("/"); 00194 webview_url_manager->unregister_baseurl(STATIC_URL_PREFIX); 00195 webview_url_manager->unregister_baseurl(BLACKBOARD_URL_PREFIX); 00196 webview_url_manager->unregister_baseurl(PLUGINS_URL_PREFIX); 00197 00198 webview_nav_manager->remove_nav_entry(BLACKBOARD_URL_PREFIX); 00199 webview_nav_manager->remove_nav_entry(PLUGINS_URL_PREFIX); 00200 00201 delete __webserver; 00202 00203 delete __webview_service; 00204 delete __service_browse_handler; 00205 00206 delete __dispatcher; 00207 delete __static_processor; 00208 delete __blackboard_processor; 00209 delete __startpage_processor; 00210 delete __plugins_processor; 00211 delete __footer_gen; 00212 delete __header_gen; 00213 __dispatcher = NULL; 00214 } 00215 00216 00217 void 00218 WebviewThread::loop() 00219 { 00220 __webserver->process(); 00221 } 00222 00223 00224 void 00225 WebviewThread::ssl_create(const char *ssl_key_file, const char *ssl_cert_file) 00226 { 00227 logger->log_info(name(), "Creating SSL key and certificate. " 00228 "This may take a while..."); 00229 HostInfo h; 00230 00231 char *cmd; 00232 if (asprintf(&cmd, "openssl req -new -x509 -batch -nodes -days 365 " 00233 "-subj \"/C=XX/L=World/O=Fawkes/CN=%s.local\" " 00234 "-out \"%s\" -keyout \"%s\" >/dev/null 2>&1", 00235 h.short_name(), ssl_cert_file, ssl_key_file) == -1) 00236 { 00237 throw OutOfMemoryException("Webview/SSL: Could not generate OpenSSL string"); 00238 } 00239 00240 int status = system(cmd); 00241 free(cmd); 00242 00243 if (WEXITSTATUS(status) != 0) { 00244 throw Exception("Failed to auto-generate key/certificate pair"); 00245 } 00246 }