4 #include "boost/bind.hpp"
5 #include "boost/thread.hpp"
6 #include "boost/version.hpp"
8 #include "zypp/base/Logger.h"
9 #include "zypp/base/String.h"
10 #include "zypp/base/Exception.h"
11 #include "zypp/ExternalProgram.h"
12 #include "WebServer.h"
19 #if ( BOOST_VERSION >= 105000 )
20 // https://svn.boost.org/trac/boost/ticket/7085
25 class fake_error_category : public error_category
27 virtual const char * name() const noexcept(true)
28 { return "falke_name"; }
29 virtual std::string message( int ev ) const
30 { return "falke_message"; }
32 const error_category & generic_category()
34 static fake_error_category _e;
36 throw std::exception(/*"boost/ticket/7085 workaound sucks :("*/);
38 const error_category & system_category()
40 static fake_error_category _e;
42 throw std::exception(/*"boost/ticket/7085 workaound sucks :("*/);
48 static inline string hostname()
52 if (!::gethostname(buf, 255))
53 result += string(buf);
70 virtual string log() const
79 virtual void worker_thread()
82 virtual int port() const
90 friend Impl * rwcowClone<Impl>( const Impl * rhs );
91 /** clone for RWCOW_pointer */
93 { return new Impl( *this ); }
96 class WebServerWebrickImpl : public WebServer::Impl
99 WebServerWebrickImpl(const Pathname &root, unsigned int port)
100 : _docroot(root), _port(port), _stop(false), _stopped(true)
104 ~WebServerWebrickImpl()
110 virtual int port() const
116 virtual void worker_thread()
120 stringstream strlog(_log);
122 string webrick_code = str::form("require \"webrick\"; s = WEBrick::HTTPServer.new(:Port => %d, :DocumentRoot => \"%s\"); trap(\"INT\"){ s.shutdown }; trap(\"SIGKILL\") { s.shutdown }; s.start;", _port, _docroot.c_str());
128 webrick_code.c_str(),
132 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
139 MIL << "Thread end requested" << endl;
141 if ( prog.running() )
143 MIL << "Thread about to finish" << endl;
146 virtual string log() const
153 MIL << "Waiting for Webrick thread to finish" << endl;
156 MIL << "Webrick thread finished" << endl;
163 //_thrd.reset( new boost::thread( boost::bind(&WebServerWebrickImpl::worker_thread, this) ) );
166 zypp::Pathname _docroot;
168 zypp::shared_ptr<boost::thread> _thrd;
174 class WebServerMongooseImpl : public WebServer::Impl
177 WebServerMongooseImpl(const Pathname &root, unsigned int port)
178 : _ctx(0L), _docroot(root)
184 ~WebServerMongooseImpl()
186 MIL << "Destroying web server" << endl;
196 MIL << "mongoose server already running, stopping." << endl;
200 MIL << "Starting shttpd (mongoose)" << endl;
205 ret = mg_set_option(_ctx, "ports", str::form("%d", _port).c_str());
207 ZYPP_THROW(Exception(str::form("Failed to set port: %d", ret)));
209 MIL << "Setting root directory to : '" << _docroot << "'" << endl;
210 ret = mg_set_option(_ctx, "root", _docroot.c_str());
212 ZYPP_THROW(Exception(str::form("Failed to set docroot: %d", ret)));
217 virtual int port() const
223 virtual string log() const
230 MIL << "Stopping shttpd" << endl;
232 MIL << "shttpd finished" << endl;
238 zypp::Pathname _docroot;
245 WebServer::WebServer(const Pathname &root, unsigned int port)
247 : _pimpl(new WebServerWebrickImpl(root, port))
249 : _pimpl(new WebServerMongooseImpl(root, port))
254 void WebServer::start()
260 std::string WebServer::log() const
262 return _pimpl->log();
265 int WebServer::port() const
267 return _pimpl->port();
271 Url WebServer::url() const
274 url.setHost("localhost");
275 url.setPort(str::numstring(port()));
276 url.setScheme("http");
280 void WebServer::stop()
285 WebServer::~WebServer()