Fawkes API  Fawkes Development Version
webview_thread.cpp
1 
2 /***************************************************************************
3  * webview_thread.cpp - Thread that handles web interface requests
4  *
5  * Created: Mon Oct 13 17:51:31 2008 (I5 Developer's Day)
6  * Copyright 2006-2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "webview_thread.h"
24 #include "static_processor.h"
25 #include "blackboard_processor.h"
26 #include "startpage_processor.h"
27 #include "plugins_processor.h"
28 #include "service_browse_handler.h"
29 #include "header_generator.h"
30 #include "footer_generator.h"
31 #include "user_verifier.h"
32 
33 #include <core/version.h>
34 #include <core/exceptions/system.h>
35 #include <utils/system/file.h>
36 #include <utils/system/hostinfo.h>
37 #include <webview/request_dispatcher.h>
38 #include <webview/page_reply.h>
39 #include <webview/server.h>
40 #include <webview/url_manager.h>
41 #include <webview/nav_manager.h>
42 
43 #include <sys/wait.h>
44 
45 using namespace fawkes;
46 
47 
48 /** Prefix for the WebStaticRequestProcessor. */
49 const char *WebviewThread::STATIC_URL_PREFIX = "/static";
50 /** Prefix for the WebBlackBoardRequestProcessor. */
51 const char *WebviewThread::BLACKBOARD_URL_PREFIX = "/blackboard";
52 /** Prefix for the WebPluginsRequestProcessor. */
53 const char *WebviewThread::PLUGINS_URL_PREFIX = "/plugins";
54 
55 /** @class WebviewThread "webview_thread.h"
56  * Webview Thread.
57  * This thread runs the HTTP server and handles requests via the
58  * WebRequestDispatcher.
59  * @author Tim Niemueller
60  */
61 
62 
63 /** Constructor. */
65  : Thread("WebviewThread", Thread::OPMODE_CONTINUOUS),
66  LoggerAspect(&__cache_logger)
67 {
69 }
70 
71 
72 WebviewThread::~WebviewThread()
73 {
74 }
75 
76 void
78 {
79  __cfg_port = config->get_uint("/webview/port");
80 
81  bool __cfg_use_ssl = false;
82  try {
83  __cfg_use_ssl = config->get_bool("/webview/use_ssl");
84  } catch (Exception &e) {}
85 
86  if (__cfg_use_ssl) {
87  __cfg_ssl_create = false;
88  try {
89  __cfg_ssl_create = config->get_bool("/webview/ssl_create");
90  } catch (Exception &e) {}
91 
92  __cfg_ssl_key = config->get_string("/webview/ssl_key");
93  __cfg_ssl_cert = config->get_string("/webview/ssl_cert");
94 
95  if (__cfg_ssl_key[0] != '/')
96  __cfg_ssl_key = std::string(CONFDIR"/") + __cfg_ssl_key;
97 
98  if (__cfg_ssl_cert[0] != '/')
99  __cfg_ssl_cert = std::string(CONFDIR"/") + __cfg_ssl_cert;
100 
101  logger->log_debug(name(), "Key: %s Cert: %s", __cfg_ssl_key.c_str(),
102  __cfg_ssl_cert.c_str());
103 
104  if (! File::exists(__cfg_ssl_key.c_str())) {
105  if (File::exists(__cfg_ssl_cert.c_str())) {
106  throw Exception("Key file %s does not exist, but certificate file %s "
107  "does", __cfg_ssl_key.c_str(), __cfg_ssl_cert.c_str());
108  } else if (__cfg_ssl_create) {
109  ssl_create(__cfg_ssl_key.c_str(), __cfg_ssl_cert.c_str());
110  } else {
111  throw Exception("Key file %s does not exist", __cfg_ssl_key.c_str());
112  }
113  } else if (! File::exists(__cfg_ssl_cert.c_str())) {
114  throw Exception("Certificate file %s does not exist, but key file %s "
115  "does", __cfg_ssl_key.c_str(), __cfg_ssl_cert.c_str());
116  }
117  }
118 
119  bool __cfg_use_basic_auth = false;
120  try {
121  __cfg_use_basic_auth = config->get_bool("/webview/use_basic_auth");
122  } catch (Exception &e) {}
123  __cfg_basic_auth_realm = "Fawkes Webview";
124  try {
125  __cfg_basic_auth_realm = config->get_bool("/webview/basic_auth_realm");
126  } catch (Exception &e) {}
127 
128 
129  __cache_logger.clear();
130 
131  __webview_service = new NetworkService(nnresolver, "Fawkes Webview on %h",
132  "_http._tcp", __cfg_port);
133  __webview_service->add_txt("fawkesver=%u.%u.%u",
134  FAWKES_VERSION_MAJOR, FAWKES_VERSION_MINOR,
135  FAWKES_VERSION_MICRO);
136  __service_browse_handler = new WebviewServiceBrowseHandler(logger, __webview_service);
137 
138  __header_gen = new WebviewHeaderGenerator(webview_nav_manager);
139  __footer_gen = new WebviewFooterGenerator(__service_browse_handler);
140 
141  __dispatcher = new WebRequestDispatcher(webview_url_manager,
142  __header_gen, __footer_gen);
143 
144 
145  try {
146  if (__cfg_use_ssl) {
147  __webserver = new WebServer(__cfg_port, __dispatcher, __cfg_ssl_key.c_str(),
148  __cfg_ssl_cert.c_str(), logger);
149  } else {
150  __webserver = new WebServer(__cfg_port, __dispatcher, logger);
151  }
152 
153  if (__cfg_use_basic_auth) {
154  __user_verifier = new WebviewUserVerifier(config, logger);
155  __webserver->setup_basic_auth(__cfg_basic_auth_realm.c_str(),
156  __user_verifier);
157  }
158  } catch (Exception &e) {
159  delete __webview_service;
160  delete __service_browse_handler;
161  delete __header_gen;
162  delete __footer_gen;
163  delete __dispatcher;
164  throw;
165  }
166 
167 
168  __startpage_processor = new WebviewStartPageRequestProcessor(&__cache_logger);
169  __static_processor = new WebviewStaticRequestProcessor(STATIC_URL_PREFIX, RESDIR"/webview", logger);
172  webview_url_manager->register_baseurl("/", __startpage_processor);
176 
179 
180  logger->log_info("WebviewThread", "Listening for HTTP connections on port %u", __cfg_port);
181 
182  service_publisher->publish_service(__webview_service);
183  service_browser->watch_service("_http._tcp", __service_browse_handler);
184 
185 }
186 
187 void
189 {
190  service_publisher->unpublish_service(__webview_service);
191  service_browser->unwatch_service("_http._tcp", __service_browse_handler);
192 
197 
200 
201  delete __webserver;
202 
203  delete __webview_service;
204  delete __service_browse_handler;
205 
206  delete __dispatcher;
207  delete __static_processor;
208  delete __blackboard_processor;
209  delete __startpage_processor;
210  delete __plugins_processor;
211  delete __footer_gen;
212  delete __header_gen;
213  __dispatcher = NULL;
214 }
215 
216 
217 void
219 {
220  __webserver->process();
221 }
222 
223 
224 void
225 WebviewThread::ssl_create(const char *ssl_key_file, const char *ssl_cert_file)
226 {
227  logger->log_info(name(), "Creating SSL key and certificate. "
228  "This may take a while...");
229  HostInfo h;
230 
231  char *cmd;
232  if (asprintf(&cmd, "openssl req -new -x509 -batch -nodes -days 365 "
233  "-subj \"/C=XX/L=World/O=Fawkes/CN=%s.local\" "
234  "-out \"%s\" -keyout \"%s\" >/dev/null 2>&1",
235  h.short_name(), ssl_cert_file, ssl_key_file) == -1)
236  {
237  throw OutOfMemoryException("Webview/SSL: Could not generate OpenSSL string");
238  }
239 
240  int status = system(cmd);
241  free(cmd);
242 
243  if (WEXITSTATUS(status) != 0) {
244  throw Exception("Failed to auto-generate key/certificate pair");
245  }
246 }
WebNavManager * webview_nav_manager
Webview navigation manager.
Definition: webview.h:50
Thread aspect that allows to provide a logger to Fawkes.
Definition: logger.h:36
void setup_basic_auth(const char *realm, WebUserVerifier *verifier)
Setup basic authentication.
Definition: server.cpp:170
virtual void unwatch_service(const char *service_type, ServiceBrowseHandler *h)=0
Remove browse handler for specific service.
Web request dispatcher.
PluginManager * plugin_manager
This is the member used to access the PluginManager.
Encapsulation of the libmicrohttpd webserver.
Definition: server.h:39
const char * short_name()
Get short hostname (up to first dot).
Definition: hostinfo.cpp:114
virtual void init()
Initialize the thread.
virtual void finalize()
Finalize the thread.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
void clear()
Clear messages.
Definition: cache.cpp:75
WebviewThread()
Constructor.
ServicePublisher * service_publisher
Service publisher to publish services on the network.
Definition: network.h:49
virtual void unpublish_service(NetworkService *service)=0
Revoke service publication.
virtual void publish_service(NetworkService *service)=0
Publish service.
static const char * STATIC_URL_PREFIX
Prefix for the WebStaticRequestProcessor.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
void process()
Process requests.
Definition: server.cpp:180
Thread class encapsulation of pthreads.
Definition: thread.h:42
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
Definition: thread.cpp:715
Static file web processor.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:44
Host information.
Definition: hostinfo.h:31
Base class for exceptions in Fawkes.
Definition: exception.h:36
WebUrlManager * webview_url_manager
Webview request processor manager.
Definition: webview.h:48
void unregister_baseurl(const char *url_prefix)
Remove a request processor.
Definition: url_manager.cpp:87
BlackBoard web request processor.
void add_txt(const char *format,...)
Add a TXT record.
Definition: service.cpp:278
NetworkNameResolver * nnresolver
Network name resolver to lookup IP addresses of hostnames and vice versa.
Definition: network.h:48
Webview user verification.
Definition: user_verifier.h:34
static const char * BLACKBOARD_URL_PREFIX
Prefix for the WebBlackBoardRequestProcessor.
void add_nav_entry(std::string baseurl, std::string name)
Add a navigation entry.
Definition: nav_manager.cpp:61
const char * name() const
Get name of thread.
Definition: thread.h:95
Representation of a service announced or found via service discovery (i.e.
Definition: service.h:37
Web request processor for the start page.
ServiceBrowser * service_browser
Service browser to browse services on the network.
Definition: network.h:50
static const char * PLUGINS_URL_PREFIX
Prefix for the WebPluginsRequestProcessor.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
Webview page footer.
Browse handler to detect other Webview instances on the network.
void remove_nav_entry(std::string baseurl)
Remove a navigation entry.
Definition: nav_manager.cpp:76
Webview page header.
virtual unsigned int get_uint(const char *path)=0
Get value from configuration which is of type unsigned int.
virtual void loop()
Code to execute in the thread.
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:44
virtual void watch_service(const char *service_type, ServiceBrowseHandler *h)=0
Add browse handler for specific service.
void register_baseurl(const char *url_prefix, WebRequestProcessor *processor)
Add a request processor.
Definition: url_manager.cpp:64
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:43
Plugins web request processor.