output/httpd: throw C++ exception on init error
This commit is contained in:
		| @@ -150,9 +150,13 @@ private: | |||||||
| 	unsigned clients_max; | 	unsigned clients_max; | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	HttpdOutput(EventLoop &_loop); | 	HttpdOutput(EventLoop &_loop, const ConfigBlock &block); | ||||||
| 	~HttpdOutput(); | 	~HttpdOutput(); | ||||||
|  |  | ||||||
|  | 	operator AudioOutput *() { | ||||||
|  | 		return &base; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| #if CLANG_OR_GCC_VERSION(4,7) | #if CLANG_OR_GCC_VERSION(4,7) | ||||||
| 	constexpr | 	constexpr | ||||||
| #endif | #endif | ||||||
| @@ -162,21 +166,6 @@ public: | |||||||
|  |  | ||||||
| 	using DeferredMonitor::GetEventLoop; | 	using DeferredMonitor::GetEventLoop; | ||||||
|  |  | ||||||
| 	bool Init(const ConfigBlock &block, Error &error); |  | ||||||
|  |  | ||||||
| 	bool Configure(const ConfigBlock &block, Error &error); |  | ||||||
|  |  | ||||||
| 	AudioOutput *InitAndConfigure(const ConfigBlock &block, |  | ||||||
| 				       Error &error) { |  | ||||||
| 		if (!Init(block, error)) |  | ||||||
| 			return nullptr; |  | ||||||
|  |  | ||||||
| 		if (!Configure(block, error)) |  | ||||||
| 			return nullptr; |  | ||||||
|  |  | ||||||
| 		return &base; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void Bind(); | 	void Bind(); | ||||||
| 	void Unbind(); | 	void Unbind(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ | |||||||
| #include "system/fd_util.h" | #include "system/fd_util.h" | ||||||
| #include "IOThread.hxx" | #include "IOThread.hxx" | ||||||
| #include "event/Call.hxx" | #include "event/Call.hxx" | ||||||
|  | #include "util/RuntimeError.hxx" | ||||||
| #include "util/Error.hxx" | #include "util/Error.hxx" | ||||||
| #include "util/Domain.hxx" | #include "util/Domain.hxx" | ||||||
| #include "util/DeleteDisposer.hxx" | #include "util/DeleteDisposer.hxx" | ||||||
| @@ -50,12 +51,43 @@ | |||||||
| const Domain httpd_output_domain("httpd_output"); | const Domain httpd_output_domain("httpd_output"); | ||||||
|  |  | ||||||
| inline | inline | ||||||
| HttpdOutput::HttpdOutput(EventLoop &_loop) | HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block) | ||||||
| 	:ServerSocket(_loop), DeferredMonitor(_loop), | 	:ServerSocket(_loop), DeferredMonitor(_loop), | ||||||
| 	 base(httpd_output_plugin), | 	 base(httpd_output_plugin, block), | ||||||
| 	 encoder(nullptr), unflushed_input(0), | 	 encoder(nullptr), unflushed_input(0), | ||||||
| 	 metadata(nullptr) | 	 metadata(nullptr) | ||||||
| { | { | ||||||
|  | 	/* read configuration */ | ||||||
|  | 	name = block.GetBlockValue("name", "Set name in config"); | ||||||
|  | 	genre = block.GetBlockValue("genre", "Set genre in config"); | ||||||
|  | 	website = block.GetBlockValue("website", "Set website in config"); | ||||||
|  |  | ||||||
|  | 	unsigned port = block.GetBlockValue("port", 8000u); | ||||||
|  |  | ||||||
|  | 	const char *encoder_name = | ||||||
|  | 		block.GetBlockValue("encoder", "vorbis"); | ||||||
|  | 	const auto encoder_plugin = encoder_plugin_get(encoder_name); | ||||||
|  | 	if (encoder_plugin == nullptr) | ||||||
|  | 		throw FormatRuntimeError("No such encoder: %s", encoder_name); | ||||||
|  |  | ||||||
|  | 	clients_max = block.GetBlockValue("max_clients", 0u); | ||||||
|  |  | ||||||
|  | 	/* set up bind_to_address */ | ||||||
|  |  | ||||||
|  | 	const char *bind_to_address = block.GetBlockValue("bind_to_address"); | ||||||
|  | 	if (bind_to_address != nullptr && strcmp(bind_to_address, "any") != 0) | ||||||
|  | 		AddHost(bind_to_address, port); | ||||||
|  | 	else | ||||||
|  | 		AddPort(port); | ||||||
|  |  | ||||||
|  | 	/* initialize encoder */ | ||||||
|  |  | ||||||
|  | 	prepared_encoder = encoder_init(*encoder_plugin, block); | ||||||
|  |  | ||||||
|  | 	/* determine content type */ | ||||||
|  | 	content_type = prepared_encoder->GetMimeType(); | ||||||
|  | 	if (content_type == nullptr) | ||||||
|  | 		content_type = "application/octet-stream"; | ||||||
| } | } | ||||||
|  |  | ||||||
| HttpdOutput::~HttpdOutput() | HttpdOutput::~HttpdOutput() | ||||||
| @@ -86,68 +118,10 @@ HttpdOutput::Unbind() | |||||||
| 		}); | 		}); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline bool |  | ||||||
| HttpdOutput::Configure(const ConfigBlock &block, Error &error) |  | ||||||
| { |  | ||||||
| 	/* read configuration */ |  | ||||||
| 	name = block.GetBlockValue("name", "Set name in config"); |  | ||||||
| 	genre = block.GetBlockValue("genre", "Set genre in config"); |  | ||||||
| 	website = block.GetBlockValue("website", "Set website in config"); |  | ||||||
|  |  | ||||||
| 	unsigned port = block.GetBlockValue("port", 8000u); |  | ||||||
|  |  | ||||||
| 	const char *encoder_name = |  | ||||||
| 		block.GetBlockValue("encoder", "vorbis"); |  | ||||||
| 	const auto encoder_plugin = encoder_plugin_get(encoder_name); |  | ||||||
| 	if (encoder_plugin == nullptr) { |  | ||||||
| 		error.Format(httpd_output_domain, |  | ||||||
| 			     "No such encoder: %s", encoder_name); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	clients_max = block.GetBlockValue("max_clients", 0u); |  | ||||||
|  |  | ||||||
| 	/* set up bind_to_address */ |  | ||||||
|  |  | ||||||
| 	const char *bind_to_address = block.GetBlockValue("bind_to_address"); |  | ||||||
| 	if (bind_to_address != nullptr && strcmp(bind_to_address, "any") != 0) |  | ||||||
| 		AddHost(bind_to_address, port); |  | ||||||
| 	else |  | ||||||
| 		AddPort(port); |  | ||||||
|  |  | ||||||
| 	/* initialize encoder */ |  | ||||||
|  |  | ||||||
| 	prepared_encoder = encoder_init(*encoder_plugin, block); |  | ||||||
|  |  | ||||||
| 	/* determine content type */ |  | ||||||
| 	content_type = prepared_encoder->GetMimeType(); |  | ||||||
| 	if (content_type == nullptr) |  | ||||||
| 		content_type = "application/octet-stream"; |  | ||||||
|  |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool |  | ||||||
| HttpdOutput::Init(const ConfigBlock &block, Error &error) |  | ||||||
| { |  | ||||||
| 	return base.Configure(block, error); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static AudioOutput * | static AudioOutput * | ||||||
| httpd_output_init(const ConfigBlock &block, Error &error) | httpd_output_init(const ConfigBlock &block, Error &) | ||||||
| { | { | ||||||
| 	HttpdOutput *httpd = new HttpdOutput(io_thread_get()); | 	return *new HttpdOutput(io_thread_get(), block); | ||||||
|  |  | ||||||
| 	try { |  | ||||||
| 		AudioOutput *result = httpd->InitAndConfigure(block, error); |  | ||||||
| 		if (result == nullptr) |  | ||||||
| 			delete httpd; |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} catch (const std::runtime_error &e) { |  | ||||||
| 		delete httpd; |  | ||||||
| 		throw; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann