changeset 95:1125d90b3b44

Misc: switch to .hpp, #477
author David Demelier <markand@malikania.fr>
date Wed, 20 Apr 2016 19:45:00 +0200
parents 339808b0c007
children 3b24366c7213
files cmake/IrccdSystem.cmake cmake/internal/sysconfig.h.in cmake/internal/sysconfig.hpp.in doc/procs/60.new-command.md irccd/main.cpp irccdctl/main.cpp lib/irccd/CMakeSources.cmake lib/irccd/alias.cpp lib/irccd/alias.h lib/irccd/alias.hpp lib/irccd/application.cpp lib/irccd/application.h lib/irccd/application.hpp lib/irccd/cmd-help.cpp lib/irccd/cmd-help.h lib/irccd/cmd-help.hpp lib/irccd/cmd-plugin-info.cpp lib/irccd/cmd-plugin-info.h lib/irccd/cmd-plugin-info.hpp lib/irccd/cmd-plugin-list.cpp lib/irccd/cmd-plugin-list.h lib/irccd/cmd-plugin-list.hpp lib/irccd/cmd-plugin-load.cpp lib/irccd/cmd-plugin-load.h lib/irccd/cmd-plugin-load.hpp lib/irccd/cmd-plugin-reload.cpp lib/irccd/cmd-plugin-reload.h lib/irccd/cmd-plugin-reload.hpp lib/irccd/cmd-plugin-unload.cpp lib/irccd/cmd-plugin-unload.h lib/irccd/cmd-plugin-unload.hpp lib/irccd/cmd-server-cmode.cpp lib/irccd/cmd-server-cmode.h lib/irccd/cmd-server-cmode.hpp lib/irccd/cmd-server-cnotice.cpp lib/irccd/cmd-server-cnotice.h lib/irccd/cmd-server-cnotice.hpp lib/irccd/cmd-server-connect.cpp lib/irccd/cmd-server-connect.h lib/irccd/cmd-server-connect.hpp lib/irccd/cmd-server-disconnect.cpp lib/irccd/cmd-server-disconnect.h lib/irccd/cmd-server-disconnect.hpp lib/irccd/cmd-server-info.cpp lib/irccd/cmd-server-info.h lib/irccd/cmd-server-info.hpp lib/irccd/cmd-server-invite.cpp lib/irccd/cmd-server-invite.h lib/irccd/cmd-server-invite.hpp lib/irccd/cmd-server-join.cpp lib/irccd/cmd-server-join.h lib/irccd/cmd-server-join.hpp lib/irccd/cmd-server-kick.cpp lib/irccd/cmd-server-kick.h lib/irccd/cmd-server-kick.hpp lib/irccd/cmd-server-list.cpp lib/irccd/cmd-server-list.h lib/irccd/cmd-server-list.hpp lib/irccd/cmd-server-me.cpp lib/irccd/cmd-server-me.h lib/irccd/cmd-server-me.hpp lib/irccd/cmd-server-message.cpp lib/irccd/cmd-server-message.h lib/irccd/cmd-server-message.hpp lib/irccd/cmd-server-mode.cpp lib/irccd/cmd-server-mode.h lib/irccd/cmd-server-mode.hpp lib/irccd/cmd-server-nick.cpp lib/irccd/cmd-server-nick.h lib/irccd/cmd-server-nick.hpp lib/irccd/cmd-server-notice.cpp lib/irccd/cmd-server-notice.h lib/irccd/cmd-server-notice.hpp lib/irccd/cmd-server-part.cpp lib/irccd/cmd-server-part.h lib/irccd/cmd-server-part.hpp lib/irccd/cmd-server-reconnect.cpp lib/irccd/cmd-server-reconnect.h lib/irccd/cmd-server-reconnect.hpp lib/irccd/cmd-server-topic.cpp lib/irccd/cmd-server-topic.h lib/irccd/cmd-server-topic.hpp lib/irccd/cmd-watch.cpp lib/irccd/cmd-watch.h lib/irccd/cmd-watch.hpp lib/irccd/command.cpp lib/irccd/command.h lib/irccd/command.hpp lib/irccd/config.cpp lib/irccd/config.h lib/irccd/config.hpp lib/irccd/connection.cpp lib/irccd/connection.h lib/irccd/connection.hpp lib/irccd/elapsed-timer.cpp lib/irccd/elapsed-timer.h lib/irccd/elapsed-timer.hpp lib/irccd/fs.cpp lib/irccd/fs.h lib/irccd/fs.hpp lib/irccd/ini.cpp lib/irccd/ini.h lib/irccd/ini.hpp lib/irccd/irccd.cpp lib/irccd/irccd.h lib/irccd/irccd.hpp lib/irccd/irccdctl.cpp lib/irccd/irccdctl.h lib/irccd/irccdctl.hpp lib/irccd/js-directory.cpp lib/irccd/js-directory.h lib/irccd/js-directory.hpp lib/irccd/js-elapsed-timer.cpp lib/irccd/js-elapsed-timer.h lib/irccd/js-elapsed-timer.hpp lib/irccd/js-file.cpp lib/irccd/js-file.h lib/irccd/js-file.hpp lib/irccd/js-irccd.cpp lib/irccd/js-irccd.h lib/irccd/js-irccd.hpp lib/irccd/js-logger.cpp lib/irccd/js-logger.h lib/irccd/js-logger.hpp lib/irccd/js-plugin.cpp lib/irccd/js-plugin.h lib/irccd/js-plugin.hpp lib/irccd/js-server.cpp lib/irccd/js-server.h lib/irccd/js-server.hpp lib/irccd/js-system.cpp lib/irccd/js-system.h lib/irccd/js-system.hpp lib/irccd/js-timer.cpp lib/irccd/js-timer.h lib/irccd/js-timer.hpp lib/irccd/js-unicode.cpp lib/irccd/js-unicode.h lib/irccd/js-unicode.hpp lib/irccd/js-util.cpp lib/irccd/js-util.h lib/irccd/js-util.hpp lib/irccd/js.h lib/irccd/js.hpp lib/irccd/json.cpp lib/irccd/json.h lib/irccd/json.hpp lib/irccd/logger.cpp lib/irccd/logger.h lib/irccd/logger.hpp lib/irccd/options.cpp lib/irccd/options.h lib/irccd/options.hpp lib/irccd/path.cpp lib/irccd/path.h lib/irccd/path.hpp lib/irccd/plugin.cpp lib/irccd/plugin.h lib/irccd/plugin.hpp lib/irccd/rule.cpp lib/irccd/rule.h lib/irccd/rule.hpp lib/irccd/server-private.h lib/irccd/server-private.hpp lib/irccd/server-state.cpp lib/irccd/server-state.h lib/irccd/server-state.hpp lib/irccd/server.cpp lib/irccd/server.h lib/irccd/server.hpp lib/irccd/signals.h lib/irccd/signals.hpp lib/irccd/sockets.cpp lib/irccd/sockets.h lib/irccd/sockets.hpp lib/irccd/system.cpp lib/irccd/system.h lib/irccd/system.hpp lib/irccd/timer.cpp lib/irccd/timer.h lib/irccd/timer.hpp lib/irccd/transport-client.cpp lib/irccd/transport-client.h lib/irccd/transport-client.hpp lib/irccd/transport-server.cpp lib/irccd/transport-server.h lib/irccd/transport-server.hpp lib/irccd/unicode.cpp lib/irccd/unicode.h lib/irccd/unicode.hpp lib/irccd/util.cpp lib/irccd/util.h lib/irccd/util.hpp lib/irccd/xdg.h lib/irccd/xdg.hpp tests/elapsedtimer/main.cpp tests/js-elapsedtimer/main.cpp tests/js-file/main.cpp tests/js-irccd/main.cpp tests/js-logger/main.cpp tests/js-system/main.cpp tests/js-timer/main.cpp tests/js-unicode/main.cpp tests/js-util/main.cpp tests/path/main.cpp tests/rules/main.cpp tests/timer/main.cpp tests/util/main.cpp
diffstat 208 files changed, 16355 insertions(+), 16356 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/IrccdSystem.cmake	Tue Apr 19 10:17:52 2016 +0200
+++ b/cmake/IrccdSystem.cmake	Wed Apr 20 19:45:00 2016 +0200
@@ -253,19 +253,19 @@
 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/irccd)
 
 configure_file(
-	${CMAKE_CURRENT_LIST_DIR}/internal/sysconfig.h.in
-	${CMAKE_BINARY_DIR}/irccd/sysconfig.h
+	${CMAKE_CURRENT_LIST_DIR}/internal/sysconfig.hpp.in
+	${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
 )
 
 install(
-	FILES ${CMAKE_BINARY_DIR}/irccd/sysconfig.h
+	FILES ${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
 	DESTINATION include/irccd
 )
 
 # Also copy to fakedir if possible
 if (IRCCD_RELOCATABLE)
 	file(
-		COPY ${CMAKE_BINARY_DIR}/irccd/sysconfig.h
+		COPY ${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
 		DESTINATION ${IRCCD_FAKEDIR}/include/irccd
 	)
 endif ()
--- a/cmake/internal/sysconfig.h.in	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * sysconfig.h -- configuration for irccd
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SYSCONFIG_H
-#define IRCCD_SYSCONFIG_H
-
-/*
- * Fix annoying "Please include winsock2.h before windows.h"
- */
-#if defined(_WIN32)
-#  include <winsock2.h>
-#  include <windows.h>
-#endif
-
-/*
- * Auto generated from CMake.
- * ------------------------------------------------------------------
- */
-
-#define PREFIX			"@CMAKE_INSTALL_PREFIX@"
-
-#define IRCCD_VERSION_MAJOR	@IRCCD_VERSION_MAJOR@
-#define IRCCD_VERSION_MINOR	@IRCCD_VERSION_MINOR@
-#define IRCCD_VERSION_PATCH	@IRCCD_VERSION_PATCH@
-
-#cmakedefine IRCCD_RELOCATABLE
-
-/*
- * System identification.
- * ------------------------------------------------------------------
- */
-
-#cmakedefine IRCCD_SYSTEM_WINDOWS
-#cmakedefine IRCCD_SYSTEM_MAC
-#cmakedefine IRCCD_SYSTEM_FREEBSD
-#cmakedefine IRCCD_SYSTEM_NETBSD
-#cmakedefine IRCCD_SYSTEM_OPENBSD
-#cmakedefine IRCCD_SYSTEM_LINUX
-#cmakedefine IRCCD_SYSTEM_UNKNOWN
-
-/*
- * User definable options.
- * ------------------------------------------------------------------
- */
-
-#define WITH_BINDIR		"@WITH_BINDIR@"
-#define WITH_DATADIR		"@WITH_DATADIR@"
-#define WITH_CONFDIR		"@WITH_CONFDIR@"
-#define WITH_PLUGINDIR		"@WITH_PLUGINDIR@"
-#define WITH_CACHEDIR		"@WITH_CACHEDIR@"
-
-#cmakedefine WITH_JS
-#cmakedefine WITH_SSL
-
-/*
- * Platform checks.
- * ------------------------------------------------------------------
- */
-
-#cmakedefine HAVE_ACCESS
-#cmakedefine HAVE_DAEMON
-#cmakedefine HAVE_GETPID
-#cmakedefine HAVE_POPEN
-#cmakedefine HAVE_SETGID
-#cmakedefine HAVE_SETPROGNAME
-#cmakedefine HAVE_SETUID
-#cmakedefine HAVE_STD_PUT_TIME
-#cmakedefine HAVE_STAT
-#cmakedefine HAVE_STAT_ST_ATIME
-#cmakedefine HAVE_STAT_ST_BLKSIZE
-#cmakedefine HAVE_STAT_ST_BLOCKS
-#cmakedefine HAVE_STAT_ST_CTIME
-#cmakedefine HAVE_STAT_ST_DEV
-#cmakedefine HAVE_STAT_ST_GID
-#cmakedefine HAVE_STAT_ST_INO
-#cmakedefine HAVE_STAT_ST_MODE
-#cmakedefine HAVE_STAT_ST_MTIME
-#cmakedefine HAVE_STAT_ST_NLINK
-#cmakedefine HAVE_STAT_ST_RDEV
-#cmakedefine HAVE_STAT_ST_SIZE
-#cmakedefine HAVE_STAT_ST_UID
-#cmakedefine HAVE_SYSLOG
-
-#endif // !IRCCD_SYSCONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/internal/sysconfig.hpp.in	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,99 @@
+/*
+ * sysconfig.h -- configuration for irccd
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SYSCONFIG_H
+#define IRCCD_SYSCONFIG_H
+
+/*
+ * Fix annoying "Please include winsock2.h before windows.h"
+ */
+#if defined(_WIN32)
+#  include <winsock2.h>
+#  include <windows.h>
+#endif
+
+/*
+ * Auto generated from CMake.
+ * ------------------------------------------------------------------
+ */
+
+#define PREFIX			"@CMAKE_INSTALL_PREFIX@"
+
+#define IRCCD_VERSION_MAJOR	@IRCCD_VERSION_MAJOR@
+#define IRCCD_VERSION_MINOR	@IRCCD_VERSION_MINOR@
+#define IRCCD_VERSION_PATCH	@IRCCD_VERSION_PATCH@
+
+#cmakedefine IRCCD_RELOCATABLE
+
+/*
+ * System identification.
+ * ------------------------------------------------------------------
+ */
+
+#cmakedefine IRCCD_SYSTEM_WINDOWS
+#cmakedefine IRCCD_SYSTEM_MAC
+#cmakedefine IRCCD_SYSTEM_FREEBSD
+#cmakedefine IRCCD_SYSTEM_NETBSD
+#cmakedefine IRCCD_SYSTEM_OPENBSD
+#cmakedefine IRCCD_SYSTEM_LINUX
+#cmakedefine IRCCD_SYSTEM_UNKNOWN
+
+/*
+ * User definable options.
+ * ------------------------------------------------------------------
+ */
+
+#define WITH_BINDIR		"@WITH_BINDIR@"
+#define WITH_DATADIR		"@WITH_DATADIR@"
+#define WITH_CONFDIR		"@WITH_CONFDIR@"
+#define WITH_PLUGINDIR		"@WITH_PLUGINDIR@"
+#define WITH_CACHEDIR		"@WITH_CACHEDIR@"
+
+#cmakedefine WITH_JS
+#cmakedefine WITH_SSL
+
+/*
+ * Platform checks.
+ * ------------------------------------------------------------------
+ */
+
+#cmakedefine HAVE_ACCESS
+#cmakedefine HAVE_DAEMON
+#cmakedefine HAVE_GETPID
+#cmakedefine HAVE_POPEN
+#cmakedefine HAVE_SETGID
+#cmakedefine HAVE_SETPROGNAME
+#cmakedefine HAVE_SETUID
+#cmakedefine HAVE_STD_PUT_TIME
+#cmakedefine HAVE_STAT
+#cmakedefine HAVE_STAT_ST_ATIME
+#cmakedefine HAVE_STAT_ST_BLKSIZE
+#cmakedefine HAVE_STAT_ST_BLOCKS
+#cmakedefine HAVE_STAT_ST_CTIME
+#cmakedefine HAVE_STAT_ST_DEV
+#cmakedefine HAVE_STAT_ST_GID
+#cmakedefine HAVE_STAT_ST_INO
+#cmakedefine HAVE_STAT_ST_MODE
+#cmakedefine HAVE_STAT_ST_MTIME
+#cmakedefine HAVE_STAT_ST_NLINK
+#cmakedefine HAVE_STAT_ST_RDEV
+#cmakedefine HAVE_STAT_ST_SIZE
+#cmakedefine HAVE_STAT_ST_UID
+#cmakedefine HAVE_SYSLOG
+
+#endif // !IRCCD_SYSCONFIG_H
--- a/doc/procs/60.new-command.md	Tue Apr 19 10:17:52 2016 +0200
+++ b/doc/procs/60.new-command.md	Wed Apr 20 19:45:00 2016 +0200
@@ -30,7 +30,7 @@
 
 Inherit from `TransportCommand` and override the `exec` function.
 
-    #include "transport-command.h"
+    #include "transport-command.hpp"
 
     namespace irccd {
 
@@ -57,7 +57,7 @@
 
 Inherit from `Command` and override both `usage` and `exec` functions.
 
-    #include "command.h"
+    #include "command.hpp"
 
     namespace irccd {
 
--- a/irccd/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/irccd/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,15 +18,15 @@
 
 #include <csignal>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include <irccd/logger.h>
-#include <irccd/options.h>
-#include <irccd/path.h>
-#include <irccd/system.h>
+#include <irccd/logger.hpp>
+#include <irccd/options.hpp>
+#include <irccd/path.hpp>
+#include <irccd/system.hpp>
 
-#include <irccd/config.h>
-#include <irccd/irccd.h>
+#include <irccd/config.hpp>
+#include <irccd/irccd.hpp>
 
 using namespace irccd;
 
--- a/irccdctl/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/irccdctl/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,9 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/irccdctl.h>
-#include <irccd/logger.h>
-#include <irccd/path.h>
+#include <irccd/irccdctl.hpp>
+#include <irccd/logger.hpp>
+#include <irccd/path.hpp>
 
 using namespace irccd;
 
--- a/lib/irccd/CMakeSources.cmake	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/CMakeSources.cmake	Wed Apr 20 19:45:00 2016 +0200
@@ -3,68 +3,68 @@
 	${COMMAND_HEADERS}
 	${JS_HEADERS}
 	${PRIVATE_HEADERS}
-	${CMAKE_CURRENT_LIST_DIR}/alias.h
-	${CMAKE_CURRENT_LIST_DIR}/application.h
-	${CMAKE_CURRENT_LIST_DIR}/connection.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-help.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-info.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-list.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-load.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-reload.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-unload.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-cmode.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-cnotice.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-connect.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-disconnect.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-info.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-invite.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-join.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-kick.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-list.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-me.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-message.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-mode.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-nick.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-notice.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-part.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-reconnect.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-server-topic.h
-	${CMAKE_CURRENT_LIST_DIR}/cmd-watch.h
-	${CMAKE_CURRENT_LIST_DIR}/command.h
-	${CMAKE_CURRENT_LIST_DIR}/config.h
-	${CMAKE_CURRENT_LIST_DIR}/elapsed-timer.h
-	${CMAKE_CURRENT_LIST_DIR}/fs.h
-	${CMAKE_CURRENT_LIST_DIR}/ini.h
-	${CMAKE_CURRENT_LIST_DIR}/irccd.h
-	${CMAKE_CURRENT_LIST_DIR}/irccdctl.h
-	${CMAKE_CURRENT_LIST_DIR}/js.h
-	${CMAKE_CURRENT_LIST_DIR}/json.h
-	${CMAKE_CURRENT_LIST_DIR}/js-directory.h
-	${CMAKE_CURRENT_LIST_DIR}/js-elapsed-timer.h
-	${CMAKE_CURRENT_LIST_DIR}/js-file.h
-	${CMAKE_CURRENT_LIST_DIR}/js-irccd.h
-	${CMAKE_CURRENT_LIST_DIR}/js-logger.h
-	${CMAKE_CURRENT_LIST_DIR}/js-plugin.h
-	${CMAKE_CURRENT_LIST_DIR}/js-server.h
-	${CMAKE_CURRENT_LIST_DIR}/js-system.h
-	${CMAKE_CURRENT_LIST_DIR}/js-timer.h
-	${CMAKE_CURRENT_LIST_DIR}/js-unicode.h
-	${CMAKE_CURRENT_LIST_DIR}/js-util.h
-	${CMAKE_CURRENT_LIST_DIR}/logger.h
-	${CMAKE_CURRENT_LIST_DIR}/options.h
-	${CMAKE_CURRENT_LIST_DIR}/path.h
-	${CMAKE_CURRENT_LIST_DIR}/plugin.h
-	${CMAKE_CURRENT_LIST_DIR}/rule.h
-	${CMAKE_CURRENT_LIST_DIR}/server.h
-	${CMAKE_CURRENT_LIST_DIR}/server-private.h
-	${CMAKE_CURRENT_LIST_DIR}/server-state.h
-	${CMAKE_CURRENT_LIST_DIR}/sockets.h
-	${CMAKE_CURRENT_LIST_DIR}/system.h
-	${CMAKE_CURRENT_LIST_DIR}/timer.h
-	${CMAKE_CURRENT_LIST_DIR}/transport-client.h
-	${CMAKE_CURRENT_LIST_DIR}/transport-server.h
-	${CMAKE_CURRENT_LIST_DIR}/unicode.h
-	${CMAKE_CURRENT_LIST_DIR}/util.h
+	${CMAKE_CURRENT_LIST_DIR}/alias.hpp
+	${CMAKE_CURRENT_LIST_DIR}/application.hpp
+	${CMAKE_CURRENT_LIST_DIR}/connection.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-help.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-info.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-list.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-load.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-reload.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-plugin-unload.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-cmode.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-cnotice.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-connect.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-disconnect.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-info.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-invite.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-join.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-kick.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-list.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-me.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-message.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-mode.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-nick.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-notice.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-part.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-reconnect.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-server-topic.hpp
+	${CMAKE_CURRENT_LIST_DIR}/cmd-watch.hpp
+	${CMAKE_CURRENT_LIST_DIR}/command.hpp
+	${CMAKE_CURRENT_LIST_DIR}/config.hpp
+	${CMAKE_CURRENT_LIST_DIR}/elapsed-timer.hpp
+	${CMAKE_CURRENT_LIST_DIR}/fs.hpp
+	${CMAKE_CURRENT_LIST_DIR}/ini.hpp
+	${CMAKE_CURRENT_LIST_DIR}/irccd.hpp
+	${CMAKE_CURRENT_LIST_DIR}/irccdctl.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js.hpp
+	${CMAKE_CURRENT_LIST_DIR}/json.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-directory.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-elapsed-timer.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-file.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-irccd.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-logger.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-plugin.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-server.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-system.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-timer.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-unicode.hpp
+	${CMAKE_CURRENT_LIST_DIR}/js-util.hpp
+	${CMAKE_CURRENT_LIST_DIR}/logger.hpp
+	${CMAKE_CURRENT_LIST_DIR}/options.hpp
+	${CMAKE_CURRENT_LIST_DIR}/path.hpp
+	${CMAKE_CURRENT_LIST_DIR}/plugin.hpp
+	${CMAKE_CURRENT_LIST_DIR}/rule.hpp
+	${CMAKE_CURRENT_LIST_DIR}/server.hpp
+	${CMAKE_CURRENT_LIST_DIR}/server-private.hpp
+	${CMAKE_CURRENT_LIST_DIR}/server-state.hpp
+	${CMAKE_CURRENT_LIST_DIR}/sockets.hpp
+	${CMAKE_CURRENT_LIST_DIR}/system.hpp
+	${CMAKE_CURRENT_LIST_DIR}/timer.hpp
+	${CMAKE_CURRENT_LIST_DIR}/transport-client.hpp
+	${CMAKE_CURRENT_LIST_DIR}/transport-server.hpp
+	${CMAKE_CURRENT_LIST_DIR}/unicode.hpp
+	${CMAKE_CURRENT_LIST_DIR}/util.hpp
 )
 
 set(
@@ -132,6 +132,6 @@
 )
 
 if (NOT IRCCD_SYSTEM_WINDOWS)
-	list(APPEND HEADERS ${CMAKE_CURRENT_LIST_DIR}/xdg.h)
+	list(APPEND HEADERS ${CMAKE_CURRENT_LIST_DIR}/xdg.hpp)
 	list(APPEND SOURCES ${CMAKE_CURRENT_LIST_DIR}/xdg.cpp)
 endif ()
--- a/lib/irccd/alias.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/alias.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -19,7 +19,7 @@
 #include <cassert>
 #include <regex>
 
-#include "alias.h"
+#include "alias.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/alias.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * alias.h -- create irccdctl aliases
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_ALIAS_H
-#define IRCCD_ALIAS_H
-
-/**
- * @file alias.h
- * @brief Create irccdctl aliases.
- */
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-namespace irccd {
-
-/**
- * @class AliasArg
- * @brief Describe an alias argument.
- *
- * When the user specify arguments, it can precise an applied argument or a placeholder that will be substituted
- * during command line invocation.
- *
- * Placeholders are placed using %n where n is an integer starting from 0.
- */
-class AliasArg {
-private:
-	std::string m_value;
-	bool m_isPlaceholder;
-
-public:
-	/**
-	 * Construct an argument.
-	 *
-	 * @pre value must not be empty
-	 * @param value the value
-	 */
-	AliasArg(std::string value);
-
-	/**
-	 * Check if the argument is a placeholder.
-	 *
-	 * @return true if the argument is a placeholder
-	 */
-	inline bool isPlaceholder() const noexcept
-	{
-		return m_isPlaceholder;
-	}
-
-	/**
-	 * Get the placeholder index (e.g %0 returns 0)
-	 *
-	 * @pre isPlaceholder() must return true
-	 * @return the position
-	 */
-	unsigned index() const noexcept;
-
-	/**
-	 * Get the real value.
-	 *
-	 * @pre isPlaceholder() must return false
-	 * @return the value
-	 */
-	const std::string &value() const noexcept;
-
-	/**
-	 * Output the alias to the stream.
-	 *
-	 * @param out the output stream
-	 * @return out
-	 */
-	friend std::ostream &operator<<(std::ostream &out, const AliasArg &);
-};
-
-/**
- * @class AliasCommand
- * @brief Describe a user-provided alias command.
- *
- * An alias command is just a command with a set of applied or placeholders arguments.
- */
-class AliasCommand {
-private:
-	std::string m_command;
-	std::vector<AliasArg> m_args;
-
-public:
-	/**
-	 * Create an alias command.
-	 *
-	 * @param command the command
-	 * @param args the arguments
-	 */
-	inline AliasCommand(std::string command, std::vector<AliasArg> args = {}) noexcept
-		: m_command(std::move(command))
-		, m_args(std::move(args))
-	{
-	}
-
-	/**
-	 * Get the command to execute.
-	 *
-	 * @return the command name
-	 */
-	inline const std::string &command() const noexcept
-	{
-		return m_command;
-	}
-
-	/**
-	 * Get the arguments.
-	 *
-	 * @return the arguments
-	 */
-	inline const std::vector<AliasArg> &args() const noexcept
-	{
-		return m_args;
-	}
-};
-
-/**
- * @class Alias
- * @brief A set of commands to execute with their arguments.
- *
- * An alias is a composition of AliasCommand, typically, the user is able to set an alias that execute a list of
- * specified commands in order they are defined.
- */
-class Alias : public std::vector<AliasCommand> {
-private:
-	std::string m_name;
-
-public:
-	/**
-	 * Create an alias.
-	 *
-	 * @param name the alias name
-	 */
-	inline Alias(std::string name) noexcept
-		: m_name(std::move(name))
-	{
-	}
-
-	/**
-	 * Get the alias name.
-	 *
-	 * @return the name
-	 */
-	inline const std::string &name() const noexcept
-	{
-		return m_name;
-	}
-};
-
-} // !irccd
-
-#endif // !IRCCD_ALIAS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/alias.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,171 @@
+/*
+ * alias.hpp -- create irccdctl aliases
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_ALIAS_HPP
+#define IRCCD_ALIAS_HPP
+
+/**
+ * @file alias.hpp
+ * @brief Create irccdctl aliases.
+ */
+
+#include <ostream>
+#include <string>
+#include <vector>
+
+namespace irccd {
+
+/**
+ * @class AliasArg
+ * @brief Describe an alias argument.
+ *
+ * When the user specify arguments, it can precise an applied argument or a placeholder that will be substituted
+ * during command line invocation.
+ *
+ * Placeholders are placed using %n where n is an integer starting from 0.
+ */
+class AliasArg {
+private:
+	std::string m_value;
+	bool m_isPlaceholder;
+
+public:
+	/**
+	 * Construct an argument.
+	 *
+	 * @pre value must not be empty
+	 * @param value the value
+	 */
+	AliasArg(std::string value);
+
+	/**
+	 * Check if the argument is a placeholder.
+	 *
+	 * @return true if the argument is a placeholder
+	 */
+	inline bool isPlaceholder() const noexcept
+	{
+		return m_isPlaceholder;
+	}
+
+	/**
+	 * Get the placeholder index (e.g %0 returns 0)
+	 *
+	 * @pre isPlaceholder() must return true
+	 * @return the position
+	 */
+	unsigned index() const noexcept;
+
+	/**
+	 * Get the real value.
+	 *
+	 * @pre isPlaceholder() must return false
+	 * @return the value
+	 */
+	const std::string &value() const noexcept;
+
+	/**
+	 * Output the alias to the stream.
+	 *
+	 * @param out the output stream
+	 * @return out
+	 */
+	friend std::ostream &operator<<(std::ostream &out, const AliasArg &);
+};
+
+/**
+ * @class AliasCommand
+ * @brief Describe a user-provided alias command.
+ *
+ * An alias command is just a command with a set of applied or placeholders arguments.
+ */
+class AliasCommand {
+private:
+	std::string m_command;
+	std::vector<AliasArg> m_args;
+
+public:
+	/**
+	 * Create an alias command.
+	 *
+	 * @param command the command
+	 * @param args the arguments
+	 */
+	inline AliasCommand(std::string command, std::vector<AliasArg> args = {}) noexcept
+		: m_command(std::move(command))
+		, m_args(std::move(args))
+	{
+	}
+
+	/**
+	 * Get the command to execute.
+	 *
+	 * @return the command name
+	 */
+	inline const std::string &command() const noexcept
+	{
+		return m_command;
+	}
+
+	/**
+	 * Get the arguments.
+	 *
+	 * @return the arguments
+	 */
+	inline const std::vector<AliasArg> &args() const noexcept
+	{
+		return m_args;
+	}
+};
+
+/**
+ * @class Alias
+ * @brief A set of commands to execute with their arguments.
+ *
+ * An alias is a composition of AliasCommand, typically, the user is able to set an alias that execute a list of
+ * specified commands in order they are defined.
+ */
+class Alias : public std::vector<AliasCommand> {
+private:
+	std::string m_name;
+
+public:
+	/**
+	 * Create an alias.
+	 *
+	 * @param name the alias name
+	 */
+	inline Alias(std::string name) noexcept
+		: m_name(std::move(name))
+	{
+	}
+
+	/**
+	 * Get the alias name.
+	 *
+	 * @return the name
+	 */
+	inline const std::string &name() const noexcept
+	{
+		return m_name;
+	}
+};
+
+} // !irccd
+
+#endif // !IRCCD_ALIAS_HPP
--- a/lib/irccd/application.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/application.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,31 +16,31 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "application.h"
-#include "cmd-help.h"
-#include "cmd-plugin-info.h"
-#include "cmd-plugin-list.h"
-#include "cmd-plugin-load.h"
-#include "cmd-plugin-reload.h"
-#include "cmd-plugin-unload.h"
-#include "cmd-server-cmode.h"
-#include "cmd-server-cnotice.h"
-#include "cmd-server-connect.h"
-#include "cmd-server-disconnect.h"
-#include "cmd-server-info.h"
-#include "cmd-server-invite.h"
-#include "cmd-server-join.h"
-#include "cmd-server-kick.h"
-#include "cmd-server-list.h"
-#include "cmd-server-me.h"
-#include "cmd-server-message.h"
-#include "cmd-server-mode.h"
-#include "cmd-server-nick.h"
-#include "cmd-server-notice.h"
-#include "cmd-server-part.h"
-#include "cmd-server-reconnect.h"
-#include "cmd-server-topic.h"
-#include "cmd-watch.h"
+#include "application.hpp"
+#include "cmd-help.hpp"
+#include "cmd-plugin-info.hpp"
+#include "cmd-plugin-list.hpp"
+#include "cmd-plugin-load.hpp"
+#include "cmd-plugin-reload.hpp"
+#include "cmd-plugin-unload.hpp"
+#include "cmd-server-cmode.hpp"
+#include "cmd-server-cnotice.hpp"
+#include "cmd-server-connect.hpp"
+#include "cmd-server-disconnect.hpp"
+#include "cmd-server-info.hpp"
+#include "cmd-server-invite.hpp"
+#include "cmd-server-join.hpp"
+#include "cmd-server-kick.hpp"
+#include "cmd-server-list.hpp"
+#include "cmd-server-me.hpp"
+#include "cmd-server-message.hpp"
+#include "cmd-server-mode.hpp"
+#include "cmd-server-nick.hpp"
+#include "cmd-server-notice.hpp"
+#include "cmd-server-part.hpp"
+#include "cmd-server-reconnect.hpp"
+#include "cmd-server-topic.hpp"
+#include "cmd-watch.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/application.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * application.h -- super base class to create irccd front ends
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_APPLICATION_H
-#define IRCCD_APPLICATION_H
-
-/**
- * @file application.h
- * @brief Base class for irccd and irccdctl.
- */
-
-#include <cassert>
-#include <memory>
-#include <unordered_map>
-
-#include "command.h"
-
-namespace irccd {
-
-/**
- * Map of commands.
- */
-using RemoteCommands = std::unordered_map<std::string, std::unique_ptr<RemoteCommand>>;
-
-/**
- * @brief Base class for creating irccd front ends.
- */
-class Application {
-protected:
-	/**
-	 * Map of commands.
-	 */
-	RemoteCommands m_commands;
-
-public:
-	/**
-	 * Create the application and fill the commands with predefined commands.
-	 */
-	Application();
-
-	/**
-	 * Access the remote commands.
-	 *
-	 * @return the commands
-	 */
-	inline const RemoteCommands &commands() const noexcept
-	{
-		return m_commands;
-	}
-
-	/**
-	 * Add a new command.
-	 *
-	 * @pre command must not be null
-	 * @pre the command must not exist
-	 * @param command the command
-	 */
-	inline void addCommand(std::unique_ptr<RemoteCommand> command)
-	{
-		assert(command);
-		assert(m_commands.count(command->name()) == 0);
-
-		m_commands.emplace(command->name(), std::move(command));
-	}
-};
-
-} // !irccd
-
-#endif // !_IRCCD_APPLICATION_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/application.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,84 @@
+/*
+ * application.hpp -- super base class to create irccd front ends
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_APPLICATION_HPP
+#define IRCCD_APPLICATION_HPP
+
+/**
+ * @file application.hpp
+ * @brief Base class for irccd and irccdctl.
+ */
+
+#include <cassert>
+#include <memory>
+#include <unordered_map>
+
+#include "command.hpp"
+
+namespace irccd {
+
+/**
+ * Map of commands.
+ */
+using RemoteCommands = std::unordered_map<std::string, std::unique_ptr<RemoteCommand>>;
+
+/**
+ * @brief Base class for creating irccd front ends.
+ */
+class Application {
+protected:
+	/**
+	 * Map of commands.
+	 */
+	RemoteCommands m_commands;
+
+public:
+	/**
+	 * Create the application and fill the commands with predefined commands.
+	 */
+	Application();
+
+	/**
+	 * Access the remote commands.
+	 *
+	 * @return the commands
+	 */
+	inline const RemoteCommands &commands() const noexcept
+	{
+		return m_commands;
+	}
+
+	/**
+	 * Add a new command.
+	 *
+	 * @pre command must not be null
+	 * @pre the command must not exist
+	 * @param command the command
+	 */
+	inline void addCommand(std::unique_ptr<RemoteCommand> command)
+	{
+		assert(command);
+		assert(m_commands.count(command->name()) == 0);
+
+		m_commands.emplace(command->name(), std::move(command));
+	}
+};
+
+} // !irccd
+
+#endif // !_IRCCD_APPLICATION_HPP_
--- a/lib/irccd/cmd-help.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-help.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/irccdctl.h>
-#include <irccd/logger.h>
+#include <irccd/irccdctl.hpp>
+#include <irccd/logger.hpp>
 
-#include "cmd-help.h"
+#include "cmd-help.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-help.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * cmd-help.h -- implementation of irccdctl help
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_HELP_H
-#define IRCCD_CMD_HELP_H
-
-/**
- * @file cmd-help.h
- * @brief Implementation of irccdctl help.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class Help
- * @brief Implementation of irccdctl help.
- */
-class Help : public RemoteCommand {
-public:
-	Help();
-
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_HELP_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-help.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,58 @@
+/*
+ * cmd-help.hpp -- implementation of irccdctl help
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_HPPELP_HPP
+#define IRCCD_CMD_HPPELP_HPP
+
+/**
+ * @file cmd-help.hpp
+ * @brief Implementation of irccdctl help.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class Help
+ * @brief Implementation of irccdctl help.
+ */
+class Help : public RemoteCommand {
+public:
+	Help();
+
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_HPPELP_HPP
--- a/lib/irccd/cmd-plugin-info.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-plugin-info.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,10 +18,10 @@
 
 #include <iostream>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "cmd-plugin-info.h"
-#include "irccd.h"
+#include "cmd-plugin-info.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-plugin-info.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * cmd-plugin-info.h -- implementation of plugin-info command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_PLUGIN_INFO_H
-#define IRCCD_CMD_PLUGIN_INFO_H
-
-/**
- * @file cmd-plugin-info.h
- * @brief Implementation of plugin-info transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class PluginInfo
- * @brief Implementation of plugin-info transport command.
- */
-class PluginInfo : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	PluginInfo();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-
-	/**
-	 * @copydoc RemoteCommand::result
-	 */
-	void result(Irccdctl &irccdctl, const json::Value &response) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_PLUGIN_INFO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-plugin-info.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,74 @@
+/*
+ * cmd-plugin-info.hpp -- implementation of plugin-info command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_PLUGIN_INFO_HPP
+#define IRCCD_CMD_PLUGIN_INFO_HPP
+
+/**
+ * @file cmd-plugin-info.hpp
+ * @brief Implementation of plugin-info transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class PluginInfo
+ * @brief Implementation of plugin-info transport command.
+ */
+class PluginInfo : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	PluginInfo();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+
+	/**
+	 * @copydoc RemoteCommand::result
+	 */
+	void result(Irccdctl &irccdctl, const json::Value &response) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_PLUGIN_INFO_HPP
--- a/lib/irccd/cmd-plugin-list.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-plugin-list.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,10 +18,10 @@
 
 #include <iostream>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "cmd-plugin-list.h"
-#include "irccd.h"
+#include "cmd-plugin-list.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-plugin-list.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * cmd-plugin-list.h -- implementation of plugin-list transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_PLUGIN_LIST_H
-#define IRCCD_CMD_PLUGIN_LIST_H
-
-/**
- * @file cmd-plugin-list.h
- * @brief Implementation of plugin-list transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class PluginList
- * @brief Implementation of plugin-list transport command.
- */
-class PluginList : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	PluginList();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-
-	/**
-	 * @copydoc RemoteCommand::result
-	 */
-	void result(Irccdctl &irccdctl, const json::Value &response) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_PLUGIN_LIST_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-plugin-list.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,64 @@
+/*
+ * cmd-plugin-list.hpp -- implementation of plugin-list transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_PLUGIN_LIST_HPP
+#define IRCCD_CMD_PLUGIN_LIST_HPP
+
+/**
+ * @file cmd-plugin-list.hpp
+ * @brief Implementation of plugin-list transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class PluginList
+ * @brief Implementation of plugin-list transport command.
+ */
+class PluginList : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	PluginList();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+
+	/**
+	 * @copydoc RemoteCommand::result
+	 */
+	void result(Irccdctl &irccdctl, const json::Value &response) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_PLUGIN_LIST_HPP
--- a/lib/irccd/cmd-plugin-load.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-plugin-load.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "cmd-plugin-load.h"
-#include "irccd.h"
+#include "cmd-plugin-load.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-plugin-load.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * cmd-plugin-load.h -- implementation of plugin-load transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_PLUGIN_LOAD_H
-#define IRCCD_CMD_PLUGIN_LOAD_H
-
-/**
- * @file cmd-plugin-load.h
- * @brief Implementation of plugin-load transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class PluginLoad
- * @brief Implementation of plugin-load transport command.
- */
-class PluginLoad : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	PluginLoad();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_PLUGIN_LOAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-plugin-load.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,64 @@
+/*
+ * cmd-plugin-load.hpp -- implementation of plugin-load transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_PLUGIN_LOAD_HPP
+#define IRCCD_CMD_PLUGIN_LOAD_HPP
+
+/**
+ * @file cmd-plugin-load.hpp
+ * @brief Implementation of plugin-load transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class PluginLoad
+ * @brief Implementation of plugin-load transport command.
+ */
+class PluginLoad : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	PluginLoad();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_PLUGIN_LOAD_HPP
--- a/lib/irccd/cmd-plugin-reload.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-plugin-reload.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "cmd-plugin-reload.h"
-#include "irccd.h"
+#include "cmd-plugin-reload.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-plugin-reload.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * cmd-plugin-reload.h -- implementation of plugin-reload transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_PLUGIN_RELOAD_H
-#define IRCCD_CMD_PLUGIN_RELOAD_H
-
-/**
- * @file cmd-plugin-reload.h
- * @brief Implementation of plugin-reload transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class PluginReload
- * @brief Implementation of plugin-reload transport command.
- */
-class PluginReload : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	PluginReload();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_PLUGIN_RELOAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-plugin-reload.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,64 @@
+/*
+ * cmd-plugin-reload.hpp -- implementation of plugin-reload transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_PLUGIN_RELOAD_HPP
+#define IRCCD_CMD_PLUGIN_RELOAD_HPP
+
+/**
+ * @file cmd-plugin-reload.hpp
+ * @brief Implementation of plugin-reload transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class PluginReload
+ * @brief Implementation of plugin-reload transport command.
+ */
+class PluginReload : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	PluginReload();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_PLUGIN_RELOAD_HPP
--- a/lib/irccd/cmd-plugin-unload.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-plugin-unload.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "cmd-plugin-unload.h"
-#include "irccd.h"
+#include "cmd-plugin-unload.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-plugin-unload.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * cmd-plugin-unload.h -- implementation of plugin-unload transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_PLUGIN_UNLOAD_H
-#define IRCCD_CMD_PLUGIN_UNLOAD_H
-
-/**
- * @file cmd-plugin-unload.h
- * @brief Implementation of plugin-unload transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class PluginUnload
- * @brief Implementation of plugin-unload transport command.
- */
-class PluginUnload : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	PluginUnload();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_PLUGIN_UNLOAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-plugin-unload.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,64 @@
+/*
+ * cmd-plugin-unload.hpp -- implementation of plugin-unload transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_PLUGIN_UNLOAD_HPP
+#define IRCCD_CMD_PLUGIN_UNLOAD_HPP
+
+/**
+ * @file cmd-plugin-unload.hpp
+ * @brief Implementation of plugin-unload transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class PluginUnload
+ * @brief Implementation of plugin-unload transport command.
+ */
+class PluginUnload : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	PluginUnload();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_PLUGIN_UNLOAD_HPP
--- a/lib/irccd/cmd-server-cmode.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-cmode.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-cmode.h"
-#include "irccd.h"
+#include "cmd-server-cmode.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-cmode.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * cmd-server-cmode.h -- implementation of server-cmode transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_CMODE_H
-#define IRCCD_CMD_SERVER_CMODE_H
-
-/**
- * @file cmd-server-cmode.h
- * @brief Implementation of server-cmode transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerChannelMode
- * @brief Implementation of server-cmode transport command.
- */
-class ServerChannelMode : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	ServerChannelMode();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-	 
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_CMODE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-cmode.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,64 @@
+/*
+ * cmd-server-cmode.hpp -- implementation of server-cmode transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_CMODE_HPP
+#define IRCCD_CMD_SERVER_CMODE_HPP
+
+/**
+ * @file cmd-server-cmode.hpp
+ * @brief Implementation of server-cmode transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerChannelMode
+ * @brief Implementation of server-cmode transport command.
+ */
+class ServerChannelMode : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	ServerChannelMode();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+	 
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_CMODE_HPP
--- a/lib/irccd/cmd-server-cnotice.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-cnotice.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-cnotice.h"
-#include "irccd.h"
+#include "cmd-server-cnotice.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-cnotice.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * cmd-server-cnotice.h -- implementation of server-cnotice transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_CNOTICE_H
-#define IRCCD_CMD_SERVER_CNOTICE_H
-
-/**
- * @file cmd-server-cnotice.h
- * @brief Implementation of server-cnotice transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerChannelNotice
- * @brief Implementation of server-cnotice transport command.
- *
- * Send a channel notice to the specified channel.
- *
- * {
- *   "command": "server-cnotice",
- *   "server": "the server name",
- *   "channel": "name",
- *   "message": "the message"
- * }
- */
-class ServerChannelNotice : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	ServerChannelNotice();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_CNOTICE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-cnotice.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,73 @@
+/*
+ * cmd-server-cnotice.hpp -- implementation of server-cnotice transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_CNOTICE_HPP
+#define IRCCD_CMD_SERVER_CNOTICE_HPP
+
+/**
+ * @file cmd-server-cnotice.hpp
+ * @brief Implementation of server-cnotice transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerChannelNotice
+ * @brief Implementation of server-cnotice transport command.
+ *
+ * Send a channel notice to the specified channel.
+ *
+ * {
+ *   "command": "server-cnotice",
+ *   "server": "the server name",
+ *   "channel": "name",
+ *   "message": "the message"
+ * }
+ */
+class ServerChannelNotice : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	ServerChannelNotice();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_CNOTICE_HPP
--- a/lib/irccd/cmd-server-connect.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-connect.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,10 +18,10 @@
 
 #include <limits>
 
-#include "cmd-server-connect.h"
-#include "irccd.h"
-#include "server.h"
-#include "util.h"
+#include "cmd-server-connect.hpp"
+#include "irccd.hpp"
+#include "server.hpp"
+#include "util.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-connect.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * cmd-server-connect.h -- implementation of server-connect transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_CONNECT_H
-#define IRCCD_CMD_SERVER_CONNECT_H
-
-/**
- * @file cmd-server-connect.h
- * @brief Implementation of server-connect transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerConnect
- * @brief Implementation of server-connect transport command.
- */
-class ServerConnect : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	ServerConnect();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::options
-	 */
-	std::vector<Option> options() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_CONNECT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-connect.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,69 @@
+/*
+ * cmd-server-connect.hpp -- implementation of server-connect transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_CONNECT_HPP
+#define IRCCD_CMD_SERVER_CONNECT_HPP
+
+/**
+ * @file cmd-server-connect.hpp
+ * @brief Implementation of server-connect transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerConnect
+ * @brief Implementation of server-connect transport command.
+ */
+class ServerConnect : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	ServerConnect();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::options
+	 */
+	std::vector<Option> options() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_CONNECT_HPP
--- a/lib/irccd/cmd-server-disconnect.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-disconnect.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-disconnect.h"
-#include "irccd.h"
+#include "cmd-server-disconnect.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-disconnect.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-disconnect.h -- implementation of server-disconnect transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_DISCONNECT_H
-#define IRCCD_CMD_SERVER_DISCONNECT_H
-
-/**
- * @file cmd-server-disconnect.h
- * @brief Implementation of server-disconnect transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerDisconnect
- * @brief Implementation of server-disconnect transport command.
- */
-class ServerDisconnect : public RemoteCommand {
-public:
-	/**
-	 * Constructor.
-	 */
-	ServerDisconnect();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * Get list of arguments required.
-	 *
-	 * @return the arguments required
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_DISCONNECT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-disconnect.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-disconnect.hpp -- implementation of server-disconnect transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_DISCONNECT_HPP
+#define IRCCD_CMD_SERVER_DISCONNECT_HPP
+
+/**
+ * @file cmd-server-disconnect.hpp
+ * @brief Implementation of server-disconnect transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerDisconnect
+ * @brief Implementation of server-disconnect transport command.
+ */
+class ServerDisconnect : public RemoteCommand {
+public:
+	/**
+	 * Constructor.
+	 */
+	ServerDisconnect();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * Get list of arguments required.
+	 *
+	 * @return the arguments required
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_DISCONNECT_HPP
--- a/lib/irccd/cmd-server-info.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-info.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,8 +18,8 @@
 
 #include <iostream>
 
-#include "cmd-server-info.h"
-#include "irccd.h"
+#include "cmd-server-info.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-info.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * cmd-server-info.h -- implementation of server-info transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_INFO_H
-#define IRCCD_CMD_SERVER_INFO_H
-
-/**
- * @file cmd-server-info.h
- * @brief Implementation of server-info transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerInfo
- * @brief Implementation of server-info transport command.
- */
-class ServerInfo : public RemoteCommand {
-public:
-	ServerInfo();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-
-	/**
-	 * @copydoc RemoteCommand::result
-	 */
-	void result(Irccdctl &irccdctl, const json::Value &response) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_INFO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-info.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,71 @@
+/*
+ * cmd-server-info.hpp -- implementation of server-info transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_INFO_HPP
+#define IRCCD_CMD_SERVER_INFO_HPP
+
+/**
+ * @file cmd-server-info.hpp
+ * @brief Implementation of server-info transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerInfo
+ * @brief Implementation of server-info transport command.
+ */
+class ServerInfo : public RemoteCommand {
+public:
+	ServerInfo();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+
+	/**
+	 * @copydoc RemoteCommand::result
+	 */
+	void result(Irccdctl &irccdctl, const json::Value &response) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_INFO_HPP
--- a/lib/irccd/cmd-server-invite.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-invite.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-invite.h"
-#include "irccd.h"
+#include "cmd-server-invite.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-invite.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * cmd-server-invite.h -- implementation of server-invite transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_INVITE_H
-#define IRCCD_CMD_SERVER_INVITE_H
-
-/**
- * @file cmd-server-invite.h
- * @brief Implementation of server-invite transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerInvite
- * @brief Implementation of server-invite transport command.
- */
-class ServerInvite : public RemoteCommand {
-public:
-	ServerInvite();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-
-	
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_INVITE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-invite.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,68 @@
+/*
+ * cmd-server-invite.hpp -- implementation of server-invite transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_INVITE_HPP
+#define IRCCD_CMD_SERVER_INVITE_HPP
+
+/**
+ * @file cmd-server-invite.hpp
+ * @brief Implementation of server-invite transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerInvite
+ * @brief Implementation of server-invite transport command.
+ */
+class ServerInvite : public RemoteCommand {
+public:
+	ServerInvite();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+
+	
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_INVITE_HPP
--- a/lib/irccd/cmd-server-join.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-join.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-join.h"
-#include "irccd.h"
+#include "cmd-server-join.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-join.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-join.h -- implementation of server-join transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_JOIN_H
-#define IRCCD_CMD_SERVER_JOIN_H
-
-/**
- * @file cmd-server-join.h
- * @brief Implementation of server-join transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerJoin
- * @brief Implementation of server-join transport command.
- */
-class ServerJoin : public RemoteCommand {
-public:
-	ServerJoin();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_JOIN_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-join.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-join.hpp -- implementation of server-join transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_JOIN_HPP
+#define IRCCD_CMD_SERVER_JOIN_HPP
+
+/**
+ * @file cmd-server-join.hpp
+ * @brief Implementation of server-join transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerJoin
+ * @brief Implementation of server-join transport command.
+ */
+class ServerJoin : public RemoteCommand {
+public:
+	ServerJoin();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_JOIN_HPP
--- a/lib/irccd/cmd-server-kick.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-kick.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-kick.h"
-#include "irccd.h"
+#include "cmd-server-kick.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-kick.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-kick.h -- implementation of server-kick transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_KICK_H
-#define IRCCD_CMD_SERVER_KICK_H
-
-/**
- * @file cmd-server-kick.h
- * @brief Implementation of server-kick transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerKick
- * @brief Implementation of server-kick transport command.
- */
-class ServerKick : public RemoteCommand {
-public:
-	ServerKick();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_KICK_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-kick.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-kick.hpp -- implementation of server-kick transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_KICK_HPP
+#define IRCCD_CMD_SERVER_KICK_HPP
+
+/**
+ * @file cmd-server-kick.hpp
+ * @brief Implementation of server-kick transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerKick
+ * @brief Implementation of server-kick transport command.
+ */
+class ServerKick : public RemoteCommand {
+public:
+	ServerKick();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_KICK_HPP
--- a/lib/irccd/cmd-server-list.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-list.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,8 +18,8 @@
 
 #include <iostream>
 
-#include "cmd-server-list.h"
-#include "irccd.h"
+#include "cmd-server-list.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-list.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * cmd-server-list.h -- implementation of server-list transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_LIST_H
-#define IRCCD_CMD_SERVER_LIST_H
-
-/**
- * @file cmd-server-list.h
- * @brief Implementation of server-list transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerList
- * @brief Implementation of server-list transport command.
- */
-class ServerList : public RemoteCommand {
-public:
-	ServerList();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-
-	void result(Irccdctl &irccdctl, const json::Value &response) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_LIST_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-list.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,55 @@
+/*
+ * cmd-server-list.hpp -- implementation of server-list transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_LIST_HPP
+#define IRCCD_CMD_SERVER_LIST_HPP
+
+/**
+ * @file cmd-server-list.hpp
+ * @brief Implementation of server-list transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerList
+ * @brief Implementation of server-list transport command.
+ */
+class ServerList : public RemoteCommand {
+public:
+	ServerList();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+
+	void result(Irccdctl &irccdctl, const json::Value &response) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_LIST_HPP
--- a/lib/irccd/cmd-server-me.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-me.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-me.h"
-#include "irccd.h"
+#include "cmd-server-me.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-me.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-me.h -- implementation of server-me transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_ME_H
-#define IRCCD_CMD_SERVER_ME_H
-
-/**
- * @file cmd-server-me.h
- * @brief Implementation of server-me transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerMe
- * @brief Implementation of server-me transport command.
- */
-class ServerMe : public RemoteCommand {
-public:
-	ServerMe();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_ME_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-me.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-me.hpp -- implementation of server-me transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_ME_HPP
+#define IRCCD_CMD_SERVER_ME_HPP
+
+/**
+ * @file cmd-server-me.hpp
+ * @brief Implementation of server-me transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerMe
+ * @brief Implementation of server-me transport command.
+ */
+class ServerMe : public RemoteCommand {
+public:
+	ServerMe();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_ME_HPP
--- a/lib/irccd/cmd-server-message.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-message.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-message.h"
-#include "irccd.h"
+#include "cmd-server-message.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-message.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-message.h -- implementation of server-message transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_MESSAGE_H
-#define IRCCD_CMD_SERVER_MESSAGE_H
-
-/**
- * @file cmd-server-message.h
- * @brief Implementation of server-message transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerMessage
- * @brief Implementation of server-message transport command.
- */
-class ServerMessage : public RemoteCommand {
-public:
-	ServerMessage();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_MESSAGE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-message.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-message.hpp -- implementation of server-message transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_MESSAGE_HPP
+#define IRCCD_CMD_SERVER_MESSAGE_HPP
+
+/**
+ * @file cmd-server-message.hpp
+ * @brief Implementation of server-message transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerMessage
+ * @brief Implementation of server-message transport command.
+ */
+class ServerMessage : public RemoteCommand {
+public:
+	ServerMessage();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_MESSAGE_HPP
--- a/lib/irccd/cmd-server-mode.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-mode.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-mode.h"
-#include "irccd.h"
+#include "cmd-server-mode.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-mode.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-mode.h -- implementation of server-mode transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_MODE_H
-#define IRCCD_CMD_SERVER_MODE_H
-
-/**
- * @file cmd-server-mode.h
- * @brief Implementation of server-mode transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerMode
- * @brief Implementation of server-mode transport command.
- */
-class ServerMode : public RemoteCommand {
-public:
-	ServerMode();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_MODE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-mode.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-mode.hpp -- implementation of server-mode transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_MODE_HPP
+#define IRCCD_CMD_SERVER_MODE_HPP
+
+/**
+ * @file cmd-server-mode.hpp
+ * @brief Implementation of server-mode transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerMode
+ * @brief Implementation of server-mode transport command.
+ */
+class ServerMode : public RemoteCommand {
+public:
+	ServerMode();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_MODE_HPP
--- a/lib/irccd/cmd-server-nick.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-nick.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-nick.h"
-#include "irccd.h"
+#include "cmd-server-nick.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-nick.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-nick.h -- implementation of server-nick transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_NICK_H
-#define IRCCD_CMD_SERVER_NICK_H
-
-/**
- * @file cmd-server-nick.h
- * @brief Implementation of server-nick transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerNick
- * @brief Implementation of server-nick transport command.
- */
-class ServerNick : public RemoteCommand {
-public:
-	ServerNick();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_NICK_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-nick.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-nick.hpp -- implementation of server-nick transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_NICK_HPP
+#define IRCCD_CMD_SERVER_NICK_HPP
+
+/**
+ * @file cmd-server-nick.hpp
+ * @brief Implementation of server-nick transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerNick
+ * @brief Implementation of server-nick transport command.
+ */
+class ServerNick : public RemoteCommand {
+public:
+	ServerNick();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_NICK_HPP
--- a/lib/irccd/cmd-server-notice.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-notice.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-notice.h"
-#include "irccd.h"
+#include "cmd-server-notice.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-notice.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-notice.h -- implementation of server-notice transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_NOTICE_H
-#define IRCCD_CMD_SERVER_NOTICE_H
-
-/**
- * @file cmd-server-notice.h
- * @brief Implementation of server-notice transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerNotice
- * @brief Implementation of server-notice transport command.
- */
-class ServerNotice : public RemoteCommand {
-public:
-	ServerNotice();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_NOTICE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-notice.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-notice.hpp -- implementation of server-notice transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_NOTICE_HPP
+#define IRCCD_CMD_SERVER_NOTICE_HPP
+
+/**
+ * @file cmd-server-notice.hpp
+ * @brief Implementation of server-notice transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerNotice
+ * @brief Implementation of server-notice transport command.
+ */
+class ServerNotice : public RemoteCommand {
+public:
+	ServerNotice();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_NOTICE_HPP
--- a/lib/irccd/cmd-server-part.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-part.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-part.h"
-#include "irccd.h"
+#include "cmd-server-part.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-part.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-part.h -- implementation of server-part transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_PART_H
-#define IRCCD_CMD_SERVER_PART_H
-
-/**
- * @file cmd-server-part.h
- * @brief Implementation of server-part transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerPart
- * @brief Implementation of server-part transport command.
- */
-class ServerPart : public RemoteCommand {
-public:
-	ServerPart();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_PART_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-part.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-part.hpp -- implementation of server-part transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_PART_HPP
+#define IRCCD_CMD_SERVER_PART_HPP
+
+/**
+ * @file cmd-server-part.hpp
+ * @brief Implementation of server-part transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerPart
+ * @brief Implementation of server-part transport command.
+ */
+class ServerPart : public RemoteCommand {
+public:
+	ServerPart();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_PART_HPP
--- a/lib/irccd/cmd-server-reconnect.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-reconnect.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-reconnect.h"
-#include "irccd.h"
+#include "cmd-server-reconnect.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-reconnect.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-reconnect.h -- implementation of server-reconnect transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_RECONNECT_H
-#define IRCCD_CMD_SERVER_RECONNECT_H
-
-/**
- * @file cmd-server-reconnect.h
- * @brief Implementation of server-reconnect transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerReconnect
- * @brief Implementation of server-reconnect transport command.
- */
-class ServerReconnect : public RemoteCommand {
-public:
-	ServerReconnect();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_RECONNECT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-reconnect.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-reconnect.hpp -- implementation of server-reconnect transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_RECONNECT_HPP
+#define IRCCD_CMD_SERVER_RECONNECT_HPP
+
+/**
+ * @file cmd-server-reconnect.hpp
+ * @brief Implementation of server-reconnect transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerReconnect
+ * @brief Implementation of server-reconnect transport command.
+ */
+class ServerReconnect : public RemoteCommand {
+public:
+	ServerReconnect();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_RECONNECT_HPP
--- a/lib/irccd/cmd-server-topic.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-server-topic.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "cmd-server-topic.h"
-#include "irccd.h"
+#include "cmd-server-topic.hpp"
+#include "irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-server-topic.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * cmd-server-topic.h -- implementation of server-topic transport command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_SERVER_TOPIC_H
-#define IRCCD_CMD_SERVER_TOPIC_H
-
-/**
- * @file cmd-server-topic.h
- * @brief Implementation of server-topic transport command.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class ServerTopic
- * @brief Implementation of server-topic transport command.
- */
-class ServerTopic : public RemoteCommand {
-public:
-	ServerTopic();
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::args
-	 */
-	std::vector<Arg> args() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
-
-	/**
-	 * @copydoc RemoteCommand::exec
-	 */
-	json::Value exec(Irccd &irccd, const json::Value &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_SERVER_TOPIC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-server-topic.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,66 @@
+/*
+ * cmd-server-topic.hpp -- implementation of server-topic transport command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_SERVER_TOPIC_HPP
+#define IRCCD_CMD_SERVER_TOPIC_HPP
+
+/**
+ * @file cmd-server-topic.hpp
+ * @brief Implementation of server-topic transport command.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class ServerTopic
+ * @brief Implementation of server-topic transport command.
+ */
+class ServerTopic : public RemoteCommand {
+public:
+	ServerTopic();
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::args
+	 */
+	std::vector<Arg> args() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const override;
+
+	/**
+	 * @copydoc RemoteCommand::exec
+	 */
+	json::Value exec(Irccd &irccd, const json::Value &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_SERVER_TOPIC_HPP
--- a/lib/irccd/cmd-watch.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/cmd-watch.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -21,8 +21,8 @@
 #include <sstream>
 #include <unordered_map>
 
-#include "cmd-watch.h"
-#include "irccdctl.h"
+#include "cmd-watch.hpp"
+#include "irccdctl.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/cmd-watch.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * cmd-watch.h -- implementation of irccdctl watch
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CMD_WATCH_H
-#define IRCCD_CMD_WATCH_H
-
-/**
- * @file cmd-watch.h
- * @brief Implementation of irccdctl watch.
- */
-
-#include "command.h"
-
-namespace irccd {
-
-namespace command {
-
-/**
- * @class Watch
- * @brief Implementation of irccdctl watch.
- */
-class Watch : public RemoteCommand {
-public:
-	Watch();
-
-	std::vector<Option> options() const override;
-
-	/**
-	 * @copydoc RemoteCommand::help
-	 */
-	std::string help() const override;
-
-	/**
-	 * @copydoc RemoteCommand::request
-	 */
-	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &request) const override;
-};
-
-} // !command
-
-} // !irccd
-
-#endif // !IRCCD_CMD_WATCH_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/cmd-watch.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,58 @@
+/*
+ * cmd-watch.hpp -- implementation of irccdctl watch
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CMD_WATCH_HPP
+#define IRCCD_CMD_WATCH_HPP
+
+/**
+ * @file cmd-watch.hpp
+ * @brief Implementation of irccdctl watch.
+ */
+
+#include "command.hpp"
+
+namespace irccd {
+
+namespace command {
+
+/**
+ * @class Watch
+ * @brief Implementation of irccdctl watch.
+ */
+class Watch : public RemoteCommand {
+public:
+	Watch();
+
+	std::vector<Option> options() const override;
+
+	/**
+	 * @copydoc RemoteCommand::help
+	 */
+	std::string help() const override;
+
+	/**
+	 * @copydoc RemoteCommand::request
+	 */
+	json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &request) const override;
+};
+
+} // !command
+
+} // !irccd
+
+#endif // !IRCCD_CMD_WATCH_HPP
--- a/lib/irccd/command.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/command.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -20,10 +20,10 @@
 #include <iomanip>
 #include <sstream>
 
-#include <irccd/logger.h>
-#include <irccd/system.h>
+#include <irccd/logger.hpp>
+#include <irccd/system.hpp>
 
-#include "command.h"
+#include "command.hpp"
 
 using namespace std::string_literals;
 
--- a/lib/irccd/command.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,493 +0,0 @@
-/*
- * command.h -- remote command
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_COMMAND_H
-#define IRCCD_COMMAND_H
-
-/**
- * @file command.h
- * @brief Remote commands.
- */
-
-#include <cassert>
-#include <map>
-#include <vector>
-
-#include <irccd/json.h>
-
-namespace irccd {
-
-class Irccd;
-class Irccdctl;
-
-/**
- * @brief Command line arguments to irccdctl.
- *
- * This class contains the resolved arguments from command line that can apply to the command.
- */
-class RemoteCommandRequest {
-public:
-	/**
-	 * The options given by command line.
-	 */
-	using Options = std::multimap<std::string, std::string>;
-
-	/**
-	 * Command line arguments in the same order.
-	 */
-	using Args = std::vector<std::string>;
-
-private:
-	Options m_options;
-	Args m_args;
-
-public:
-	/**
-	 * Construct the request.
-	 *
-	 * @param options the options
-	 * @param args the arguments
-	 */
-	inline RemoteCommandRequest(Options options, Args args) noexcept
-		: m_options(std::move(options))
-		, m_args(std::move(args))
-	{
-	}
-
-	/**
-	 * Get the arguments.
-	 *
-	 * @return the arguments
-	 */
-	inline const Args &args() const noexcept
-	{
-		return m_args;
-	}
-
-	/**
-	 * Get the options.
-	 *
-	 * @return the options
-	 */
-	inline const Options &options() const noexcept
-	{
-		return m_options;
-	}
-
-	/**
-	 * Get the number of arguments.
-	 *
-	 * @return the number of arguments
-	 */
-	inline unsigned length() const noexcept
-	{
-		return (unsigned)m_args.size();
-	}
-
-	/**
-	 * Check if the request has the given option id.
-	 *
-	 * @param option the option id
-	 * @return true if the option is available
-	 */
-	inline bool has(const std::string &option) const noexcept
-	{
-		return m_options.count(option) != 0;
-	}
-
-	/**
-	 * Get the argument at the specified index.
-	 *
-	 * @pre index < length()
-	 * @param index the argument index
-	 * @return the argument
-	 */
-	inline const std::string &arg(unsigned index) const noexcept
-	{
-		assert(index < m_args.size());
-
-		return m_args[index];
-	}
-
-	/**
-	 * Get the argument or default value if not available.
-	 *
-	 * @param index the index
-	 * @param defaultValue the value if index is out of range
-	 * @return the argument
-	 */
-	inline std::string argOr(unsigned index, std::string defaultValue) const noexcept
-	{
-		return index < m_args.size() ? m_args[index] : defaultValue;
-	}
-
-	/**
-	 * Get the given option by its id.
-	 *
-	 * @pre has(key)
-	 * @param key the option id
-	 * @return the option
-	 */
-	inline const std::string &option(const std::string &key) const noexcept
-	{
-		assert(m_options.count(key) != 0);
-
-		return m_options.find(key)->second;
-	}
-
-	/**
-	 * Get the given option by its id or defaultValue if not found.
-	 *
-	 * @param key the option id
-	 * @param defaultValue the value replacement
-	 * @return the option
-	 */
-	inline std::string optionOr(const std::string &key, std::string defaultValue) const noexcept
-	{
-		auto it = m_options.find(key);
-
-		if (it == m_options.end())
-			return defaultValue;
-
-		return it->second;
-	}
-};
-
-/**
- * @brief Invokable command.
- *
- * A remote command is a invokable command in the irccd daemon. You can register dynamically any remote command you
- * like using Application::addCommand.
- *
- * The remote command will be usable directly from irccdctl without any other code.
- *
- * A remote command can have options and arguments. Options always come first, before arguments.
- *
- * The command workflow is defined as follow:
- *
- * 1. User wants to invoke a command, request() is called and return a JSON object containaing the request, it it send
- *    to the daemon.
- *
- * 2. The daemon receive the request and execute it using exec(). It returns a JSON object containint the request result
- *    or error if any.
- *
- * 3. Finally, the command receives the result in result() function and user can manipulate it. For convenience, the
- *    default implementation shows the error if any.
- */
-class RemoteCommand {
-public:
-	/**
-	 * @brief Defines available options for this command.
-	 */
-	class Option;
-
-	/**
-	 * @brief Defines available arguments for this command.
-	 */
-	class Arg;
-
-private:
-	std::string m_name;
-	std::string m_category;
-	bool m_visible;
-
-public:
-	/**
-	 * Create the remote command.
-	 *
-	 * @pre name must not be empty
-	 * @pre category must not be empty
-	 * @param name the command name (e.g. server-list)
-	 * @param category the category (e.g. Server)
-	 * @param visible true if the command should be visible without verbosity
-	 */
-	inline RemoteCommand(std::string name, std::string category, bool visible = true) noexcept
-		: m_name(std::move(name))
-		, m_category(std::move(category))
-		, m_visible(visible)
-	{
-		assert(!m_name.empty());
-		assert(!m_category.empty());
-	}
-
-	/**
-	 * Default destructor virtual.
-	 */
-	virtual ~RemoteCommand() = default;
-
-	/**
-	 * Return the command name, must not have spaces.
-	 *
-	 * @return the command name
-	 */
-	inline const std::string &name() const noexcept
-	{
-		return m_name;
-	}
-
-	/**
-	 * Get the command category.
-	 *
-	 * Irccdctl will sort commands by categories.
-	 *
-	 * @return the category
-	 */
-	inline const std::string &category() const noexcept
-	{
-		return m_category;
-	}
-
-	/**
-	 * Hide the command in non-verbose mode.
-	 *
-	 * @return true if the command should be visible in non-verbose mode
-	 */
-	inline bool visible() const noexcept
-	{
-		return m_visible;
-	}
-
-	/**
-	 * Return the command documentation usage.
-	 *
-	 * @return the usage
-	 */
-	std::string usage() const;
-
-	/**
-	 * Return the help message.
-	 *
-	 * @return the help message
-	 */
-	virtual std::string help() const = 0;
-
-	/**
-	 * Get the supported irccdctl options.
-	 *
-	 * @return the options
-	 */
-	virtual std::vector<Option> options() const
-	{
-		return {};
-	}
-
-	/**
-	 * Get the supported arguments.
-	 *
-	 * @return the arguments
-	 */
-	virtual std::vector<Arg> args() const
-	{
-		return {};
-	}
-
-	/**
-	 * Get the minimum number of arguments required.
-	 *
-	 * @return the minimum
-	 */
-	unsigned min() const noexcept;
-
-	/**
-	 * Get the maximum number of arguments required.
-	 *
-	 * @return the maximum
-	 */
-	unsigned max() const noexcept;
-
-	/**
-	 * Prepare a JSON request to the daemon.
-	 *
-	 * If the command is local and does not need to send anything to irccd's instance, return a null JSON value.
-	 *
-	 * The default implementation just send the command name with no arguments.
-	 *
-	 * @param irccdctl the irccdctl instance
-	 * @param args the command line arguments and options
-	 * @return the JSON object to send to the daemon
-	 * @post the returned JSON value must be an object
-	 */
-	virtual json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const;
-
-	/**
-	 * Execute the command in the daemon.
-	 *
-	 * The user can return an object with any properties to forward to the client. Irccd will automatically
-	 * add the command name and the appropriate status code.
-	 *
-	 * The default return an empty object which indicates success.
-	 *
-	 * If any exception is thrown from this function, it is forwarded to the client as error status.
-	 *
-	 * @param irccd the instance
-	 * @param request the JSON request
-	 * @return the response
-	 */
-	virtual json::Value exec(Irccd &irccd, const json::Value &request) const;
-
-	/**
-	 * What to do when receiving the response from irccd.
-	 *
-	 * This default implementation just check for an error string and shows it if any.
-	 * 
-	 * @param irccdctl the irccdctl instan e
-	 * @param response the JSON response
-	 */
-	virtual void result(Irccdctl &irccdctl, const json::Value &response) const;
-};
-
-/**
- * @brief Option description for a command.
- */
-class RemoteCommand::Option {
-private:
-	std::string m_id;
-	std::string m_simple;
-	std::string m_long;
-	std::string m_arg;
-	std::string m_description;
-
-public:
-	/**
-	 * Constructor an option description.
-	 *
-	 * Simple and long keys must not start with '-' or '--', they will be added automatically.
-	 *
-	 * If arg is not empty, the option takes an argument.
-	 *
-	 * @pre id must not be empty
-	 * @pre at least simpleKey or longKey must not be empty
-	 * @pre description must not be empty
-	 * @param id the option id
-	 * @param simpleKey the key the option key
-	 * @param longKey the long option name
-	 * @param arg the argument name if needed
-	 * @param description the description
-	 */
-	inline Option(std::string id,
-		      std::string simpleKey,
-		      std::string longKey,
-		      std::string arg,
-		      std::string description) noexcept
-		: m_id(std::move(id))
-		, m_simple(std::move(simpleKey))
-		, m_long(std::move(longKey))
-		, m_arg(std::move(arg))
-		, m_description(std::move(description))
-	{
-		assert(!m_id.empty());
-		assert(!m_simple.empty() || !m_long.empty());
-		assert(!m_description.empty());
-	}
-
-	/**
-	 * Get the id.
-	 *
-	 * @return the id
-	 */
-	inline const std::string &id() const noexcept
-	{
-		return m_id;
-	}
-
-	/**
-	 * Get the option key.
-	 *
-	 * @return the key
-	 */
-	inline const std::string &simpleKey() const noexcept
-	{
-		return m_simple;
-	}
-
-	/**
-	 * Get the long option.
-	 *
-	 * @return the long option
-	 */
-	inline const std::string &longKey() const noexcept
-	{
-		return m_long;
-	}
-
-	/**
-	 * Get the option description.
-	 *
-	 * @return the description
-	 */
-	inline const std::string &description() const noexcept
-	{
-		return m_description;
-	}
-
-	/**
-	 * Get the option argument name.
-	 *
-	 * @return the argument name if any
-	 */
-	inline const std::string &arg() const noexcept
-	{
-		return m_arg;
-	}
-};
-
-/**
- * @brief Argument description for command.
- */
-class RemoteCommand::Arg {
-private:
-	std::string m_name;
-	bool m_required;
-
-public:
-	/**
-	 * Construct an argument.
-	 *
-	 * @param name the name
-	 * @param required true if the argument is required
-	 */
-	inline Arg(std::string name, bool required) noexcept
-		: m_name(std::move(name))
-		, m_required(required)
-	{
-	}
-
-	/**
-	 * Get the argument name.
-	 *
-	 * @return the name
-	 */
-	inline const std::string &name() const noexcept
-	{
-		return m_name;
-	}
-
-	/**
-	 * Tells if the argument is required.
-	 *
-	 * @return true if required
-	 */
-	inline bool required() const noexcept
-	{
-		return m_required;
-	}
-};
-
-} // !irccd
-
-#endif // !IRCCD_COMMAND_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/command.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,493 @@
+/*
+ * command.hpp -- remote command
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_COMMAND_HPP
+#define IRCCD_COMMAND_HPP
+
+/**
+ * @file command.hpp
+ * @brief Remote commands.
+ */
+
+#include <cassert>
+#include <map>
+#include <vector>
+
+#include <irccd/json.hpp>
+
+namespace irccd {
+
+class Irccd;
+class Irccdctl;
+
+/**
+ * @brief Command line arguments to irccdctl.
+ *
+ * This class contains the resolved arguments from command line that can apply to the command.
+ */
+class RemoteCommandRequest {
+public:
+	/**
+	 * The options given by command line.
+	 */
+	using Options = std::multimap<std::string, std::string>;
+
+	/**
+	 * Command line arguments in the same order.
+	 */
+	using Args = std::vector<std::string>;
+
+private:
+	Options m_options;
+	Args m_args;
+
+public:
+	/**
+	 * Construct the request.
+	 *
+	 * @param options the options
+	 * @param args the arguments
+	 */
+	inline RemoteCommandRequest(Options options, Args args) noexcept
+		: m_options(std::move(options))
+		, m_args(std::move(args))
+	{
+	}
+
+	/**
+	 * Get the arguments.
+	 *
+	 * @return the arguments
+	 */
+	inline const Args &args() const noexcept
+	{
+		return m_args;
+	}
+
+	/**
+	 * Get the options.
+	 *
+	 * @return the options
+	 */
+	inline const Options &options() const noexcept
+	{
+		return m_options;
+	}
+
+	/**
+	 * Get the number of arguments.
+	 *
+	 * @return the number of arguments
+	 */
+	inline unsigned length() const noexcept
+	{
+		return (unsigned)m_args.size();
+	}
+
+	/**
+	 * Check if the request has the given option id.
+	 *
+	 * @param option the option id
+	 * @return true if the option is available
+	 */
+	inline bool has(const std::string &option) const noexcept
+	{
+		return m_options.count(option) != 0;
+	}
+
+	/**
+	 * Get the argument at the specified index.
+	 *
+	 * @pre index < length()
+	 * @param index the argument index
+	 * @return the argument
+	 */
+	inline const std::string &arg(unsigned index) const noexcept
+	{
+		assert(index < m_args.size());
+
+		return m_args[index];
+	}
+
+	/**
+	 * Get the argument or default value if not available.
+	 *
+	 * @param index the index
+	 * @param defaultValue the value if index is out of range
+	 * @return the argument
+	 */
+	inline std::string argOr(unsigned index, std::string defaultValue) const noexcept
+	{
+		return index < m_args.size() ? m_args[index] : defaultValue;
+	}
+
+	/**
+	 * Get the given option by its id.
+	 *
+	 * @pre has(key)
+	 * @param key the option id
+	 * @return the option
+	 */
+	inline const std::string &option(const std::string &key) const noexcept
+	{
+		assert(m_options.count(key) != 0);
+
+		return m_options.find(key)->second;
+	}
+
+	/**
+	 * Get the given option by its id or defaultValue if not found.
+	 *
+	 * @param key the option id
+	 * @param defaultValue the value replacement
+	 * @return the option
+	 */
+	inline std::string optionOr(const std::string &key, std::string defaultValue) const noexcept
+	{
+		auto it = m_options.find(key);
+
+		if (it == m_options.end())
+			return defaultValue;
+
+		return it->second;
+	}
+};
+
+/**
+ * @brief Invokable command.
+ *
+ * A remote command is a invokable command in the irccd daemon. You can register dynamically any remote command you
+ * like using Application::addCommand.
+ *
+ * The remote command will be usable directly from irccdctl without any other code.
+ *
+ * A remote command can have options and arguments. Options always come first, before arguments.
+ *
+ * The command workflow is defined as follow:
+ *
+ * 1. User wants to invoke a command, request() is called and return a JSON object containaing the request, it it send
+ *    to the daemon.
+ *
+ * 2. The daemon receive the request and execute it using exec(). It returns a JSON object containint the request result
+ *    or error if any.
+ *
+ * 3. Finally, the command receives the result in result() function and user can manipulate it. For convenience, the
+ *    default implementation shows the error if any.
+ */
+class RemoteCommand {
+public:
+	/**
+	 * @brief Defines available options for this command.
+	 */
+	class Option;
+
+	/**
+	 * @brief Defines available arguments for this command.
+	 */
+	class Arg;
+
+private:
+	std::string m_name;
+	std::string m_category;
+	bool m_visible;
+
+public:
+	/**
+	 * Create the remote command.
+	 *
+	 * @pre name must not be empty
+	 * @pre category must not be empty
+	 * @param name the command name (e.g. server-list)
+	 * @param category the category (e.g. Server)
+	 * @param visible true if the command should be visible without verbosity
+	 */
+	inline RemoteCommand(std::string name, std::string category, bool visible = true) noexcept
+		: m_name(std::move(name))
+		, m_category(std::move(category))
+		, m_visible(visible)
+	{
+		assert(!m_name.empty());
+		assert(!m_category.empty());
+	}
+
+	/**
+	 * Default destructor virtual.
+	 */
+	virtual ~RemoteCommand() = default;
+
+	/**
+	 * Return the command name, must not have spaces.
+	 *
+	 * @return the command name
+	 */
+	inline const std::string &name() const noexcept
+	{
+		return m_name;
+	}
+
+	/**
+	 * Get the command category.
+	 *
+	 * Irccdctl will sort commands by categories.
+	 *
+	 * @return the category
+	 */
+	inline const std::string &category() const noexcept
+	{
+		return m_category;
+	}
+
+	/**
+	 * Hide the command in non-verbose mode.
+	 *
+	 * @return true if the command should be visible in non-verbose mode
+	 */
+	inline bool visible() const noexcept
+	{
+		return m_visible;
+	}
+
+	/**
+	 * Return the command documentation usage.
+	 *
+	 * @return the usage
+	 */
+	std::string usage() const;
+
+	/**
+	 * Return the help message.
+	 *
+	 * @return the help message
+	 */
+	virtual std::string help() const = 0;
+
+	/**
+	 * Get the supported irccdctl options.
+	 *
+	 * @return the options
+	 */
+	virtual std::vector<Option> options() const
+	{
+		return {};
+	}
+
+	/**
+	 * Get the supported arguments.
+	 *
+	 * @return the arguments
+	 */
+	virtual std::vector<Arg> args() const
+	{
+		return {};
+	}
+
+	/**
+	 * Get the minimum number of arguments required.
+	 *
+	 * @return the minimum
+	 */
+	unsigned min() const noexcept;
+
+	/**
+	 * Get the maximum number of arguments required.
+	 *
+	 * @return the maximum
+	 */
+	unsigned max() const noexcept;
+
+	/**
+	 * Prepare a JSON request to the daemon.
+	 *
+	 * If the command is local and does not need to send anything to irccd's instance, return a null JSON value.
+	 *
+	 * The default implementation just send the command name with no arguments.
+	 *
+	 * @param irccdctl the irccdctl instance
+	 * @param args the command line arguments and options
+	 * @return the JSON object to send to the daemon
+	 * @post the returned JSON value must be an object
+	 */
+	virtual json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const;
+
+	/**
+	 * Execute the command in the daemon.
+	 *
+	 * The user can return an object with any properties to forward to the client. Irccd will automatically
+	 * add the command name and the appropriate status code.
+	 *
+	 * The default return an empty object which indicates success.
+	 *
+	 * If any exception is thrown from this function, it is forwarded to the client as error status.
+	 *
+	 * @param irccd the instance
+	 * @param request the JSON request
+	 * @return the response
+	 */
+	virtual json::Value exec(Irccd &irccd, const json::Value &request) const;
+
+	/**
+	 * What to do when receiving the response from irccd.
+	 *
+	 * This default implementation just check for an error string and shows it if any.
+	 * 
+	 * @param irccdctl the irccdctl instan e
+	 * @param response the JSON response
+	 */
+	virtual void result(Irccdctl &irccdctl, const json::Value &response) const;
+};
+
+/**
+ * @brief Option description for a command.
+ */
+class RemoteCommand::Option {
+private:
+	std::string m_id;
+	std::string m_simple;
+	std::string m_long;
+	std::string m_arg;
+	std::string m_description;
+
+public:
+	/**
+	 * Constructor an option description.
+	 *
+	 * Simple and long keys must not start with '-' or '--', they will be added automatically.
+	 *
+	 * If arg is not empty, the option takes an argument.
+	 *
+	 * @pre id must not be empty
+	 * @pre at least simpleKey or longKey must not be empty
+	 * @pre description must not be empty
+	 * @param id the option id
+	 * @param simpleKey the key the option key
+	 * @param longKey the long option name
+	 * @param arg the argument name if needed
+	 * @param description the description
+	 */
+	inline Option(std::string id,
+		      std::string simpleKey,
+		      std::string longKey,
+		      std::string arg,
+		      std::string description) noexcept
+		: m_id(std::move(id))
+		, m_simple(std::move(simpleKey))
+		, m_long(std::move(longKey))
+		, m_arg(std::move(arg))
+		, m_description(std::move(description))
+	{
+		assert(!m_id.empty());
+		assert(!m_simple.empty() || !m_long.empty());
+		assert(!m_description.empty());
+	}
+
+	/**
+	 * Get the id.
+	 *
+	 * @return the id
+	 */
+	inline const std::string &id() const noexcept
+	{
+		return m_id;
+	}
+
+	/**
+	 * Get the option key.
+	 *
+	 * @return the key
+	 */
+	inline const std::string &simpleKey() const noexcept
+	{
+		return m_simple;
+	}
+
+	/**
+	 * Get the long option.
+	 *
+	 * @return the long option
+	 */
+	inline const std::string &longKey() const noexcept
+	{
+		return m_long;
+	}
+
+	/**
+	 * Get the option description.
+	 *
+	 * @return the description
+	 */
+	inline const std::string &description() const noexcept
+	{
+		return m_description;
+	}
+
+	/**
+	 * Get the option argument name.
+	 *
+	 * @return the argument name if any
+	 */
+	inline const std::string &arg() const noexcept
+	{
+		return m_arg;
+	}
+};
+
+/**
+ * @brief Argument description for command.
+ */
+class RemoteCommand::Arg {
+private:
+	std::string m_name;
+	bool m_required;
+
+public:
+	/**
+	 * Construct an argument.
+	 *
+	 * @param name the name
+	 * @param required true if the argument is required
+	 */
+	inline Arg(std::string name, bool required) noexcept
+		: m_name(std::move(name))
+		, m_required(required)
+	{
+	}
+
+	/**
+	 * Get the argument name.
+	 *
+	 * @return the name
+	 */
+	inline const std::string &name() const noexcept
+	{
+		return m_name;
+	}
+
+	/**
+	 * Tells if the argument is required.
+	 *
+	 * @return true if required
+	 */
+	inline bool required() const noexcept
+	{
+		return m_required;
+	}
+};
+
+} // !irccd
+
+#endif // !IRCCD_COMMAND_HPP
--- a/lib/irccd/config.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/config.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if defined(HAVE_GETPID)
 #  include <sys/types.h>
@@ -30,14 +30,14 @@
 #  include <cstdlib>
 #endif
 
-#include "config.h"
-#include "ini.h"
-#include "logger.h"
-#include "path.h"
-#include "sockets.h"
-#include "system.h"
-#include "util.h"
-#include "irccd.h"
+#include "config.hpp"
+#include "ini.hpp"
+#include "logger.hpp"
+#include "path.hpp"
+#include "sockets.hpp"
+#include "system.hpp"
+#include "util.hpp"
+#include "irccd.hpp"
 
 using namespace std;
 using namespace std::string_literals;
--- a/lib/irccd/config.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * config.h -- irccd configuration loader
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CONFIG_H
-#define IRCCD_CONFIG_H
-
-/**
- * @file config.h
- * @brief Read .ini configuration file for irccd
- */
-
-#include <irccd/options.h>
-
-namespace irccd {
-
-namespace ini {
-
-class Document;
-class Section;
-
-} // !ini
-
-class Irccd;
-
-/**
- * @class Config
- * @brief Read .ini configuration file for irccd
- */
-class Config {
-private:
-	parser::Result m_options;
-
-	void loadGeneral(const ini::Document &config) const;
-	void loadLogFile(const ini::Section &sc) const;
-	void loadLogSyslog() const;
-	void loadLogs(const ini::Document &config) const;
-	void loadPlugins(Irccd &irccd, const ini::Section &sc) const;
-	void loadPluginConfig(Irccd &irccd, const ini::Section &sc, std::string name) const;
-	void loadPlugins(Irccd &irccd, const ini::Document &config) const;
-	void loadServer(Irccd &irccd, const ini::Section &sc) const;
-	void loadServers(Irccd &irccd, const ini::Document &config) const;
-	void loadIdentity(Irccd &irccd, const ini::Section &sc) const;
-	void loadIdentities(Irccd &irccd, const ini::Document &config) const;
-	void loadRule(Irccd &irccd, const ini::Section &sc) const;
-	void loadRules(Irccd &irccd, const ini::Document &config) const;
-	void loadTransportIp(Irccd &irccd, const ini::Section &sc) const;
-	void loadTransportUnix(Irccd &irccd, const ini::Section &sc) const;
-	void loadTransports(Irccd &irccd, const ini::Document &config) const;
-	bool openConfig(Irccd &irccd, const std::string &path) const;
-
-public:
-	/**
-	 * Construct the configuration file loader. If path is empty, then the configuration file is searched through
-	 * the standard directories.
-	 *
-	 * @param options the option parsed at command line
-	 */
-	Config(parser::Result options) noexcept;
-
-	/**
-	 * Load the config into irccd.
-	 *
-	 * @param irccd the irccd instance
-	 */
-	void load(Irccd &irccd);
-};
-
-} // !irccd
-
-#endif // !IRCCD_CONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/config.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,85 @@
+/*
+ * config.hpp -- irccd configuration loader
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CONFIG_HPP
+#define IRCCD_CONFIG_HPP
+
+/**
+ * @file config.hpp
+ * @brief Read .ini configuration file for irccd
+ */
+
+#include <irccd/options.hpp>
+
+namespace irccd {
+
+namespace ini {
+
+class Document;
+class Section;
+
+} // !ini
+
+class Irccd;
+
+/**
+ * @class Config
+ * @brief Read .ini configuration file for irccd
+ */
+class Config {
+private:
+	parser::Result m_options;
+
+	void loadGeneral(const ini::Document &config) const;
+	void loadLogFile(const ini::Section &sc) const;
+	void loadLogSyslog() const;
+	void loadLogs(const ini::Document &config) const;
+	void loadPlugins(Irccd &irccd, const ini::Section &sc) const;
+	void loadPluginConfig(Irccd &irccd, const ini::Section &sc, std::string name) const;
+	void loadPlugins(Irccd &irccd, const ini::Document &config) const;
+	void loadServer(Irccd &irccd, const ini::Section &sc) const;
+	void loadServers(Irccd &irccd, const ini::Document &config) const;
+	void loadIdentity(Irccd &irccd, const ini::Section &sc) const;
+	void loadIdentities(Irccd &irccd, const ini::Document &config) const;
+	void loadRule(Irccd &irccd, const ini::Section &sc) const;
+	void loadRules(Irccd &irccd, const ini::Document &config) const;
+	void loadTransportIp(Irccd &irccd, const ini::Section &sc) const;
+	void loadTransportUnix(Irccd &irccd, const ini::Section &sc) const;
+	void loadTransports(Irccd &irccd, const ini::Document &config) const;
+	bool openConfig(Irccd &irccd, const std::string &path) const;
+
+public:
+	/**
+	 * Construct the configuration file loader. If path is empty, then the configuration file is searched through
+	 * the standard directories.
+	 *
+	 * @param options the option parsed at command line
+	 */
+	Config(parser::Result options) noexcept;
+
+	/**
+	 * Load the config into irccd.
+	 *
+	 * @param irccd the irccd instance
+	 */
+	void load(Irccd &irccd);
+};
+
+} // !irccd
+
+#endif // !IRCCD_CONFIG_HPP
--- a/lib/irccd/connection.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/connection.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,9 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/logger.h>
+#include <irccd/logger.hpp>
 
-#include "connection.h"
+#include "connection.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/connection.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * connection.h -- value wrapper for connecting to irccd
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_CONNECTION_H
-#define IRCCD_CONNECTION_H
-
-/**
- * @file connection.h
- * @brief Connection to irccd instance.
- */
-
-#include <cassert>
-#include <stdexcept>
-
-#include <irccd/json.h>
-#include <irccd/system.h>
-#include <irccd/util.h>
-
-#include "elapsed-timer.h"
-#include "sockets.h"
-
-namespace irccd {
-
-/**
- * @class Connection
- * @brief Abstract class for connecting to irccd from Ip or Local addresses.
- */
-class Connection {
-protected:
-	/**
-	 * Timer to track elapsed time.
-	 */
-	ElapsedTimer m_timer;
-
-	/**
-	 * Clamp the time to wait to be sure that it will be never less than 0.
-	 */
-	inline int clamp(int timeout) noexcept
-	{
-		return timeout < 0 ? -1 : (timeout - (int)m_timer.elapsed() < 0) ? 0 : (timeout - m_timer.elapsed());
-	}
-
-public:
-	/**
-	 * Default constructor.
-	 */
-	Connection() = default;
-
-	/**
-	 * Default destructor.
-	 */
-	virtual ~Connection() = default;
-
-	/**
-	 * Wait for the next requested response.
-	 *
-	 * @param name the response name
-	 * @param timeout the optional timeout
-	 * @return the object
-	 * @throw net::Error on errors or on timeout
-	 */
-	json::Value next(const std::string &name, int timeout = 30000);
-
-	/**
-	 * Just wait if the operation succeeded.
-	 *
-	 * @param name the response name
-	 * @param timeout the timeout
-	 */
-	void verify(const std::string &name, int timeout = 30000);
-
-	/**
-	 * Check if the socket is still connected.
-	 *
-	 * @return true if connected
-	 */
-	virtual bool isConnected() const noexcept = 0;
-
-	/**
-	 * Try to connect to the host.
-	 *
-	 * @param timeout the maximum time in milliseconds
-	 * @throw net::Error on errors or timeout
-	 */
-	virtual void connect(int timeout = 30000) = 0;
-
-	/**
-	 * Try to send the message in 30 seconds. The message must not end with \\r\\n\\r\\n, it is added automatically.
-	 *
-	 * @pre msg must not be empty
-	 * @param msg the message to send
-	 * @param timeout the maximum time in milliseconds
-	 * @throw net::Error on errors
-	 */
-	virtual void send(std::string msg, int timeout = 30000) = 0;
-
-	/**
-	 * Get the next event from irccd.
-	 *
-	 * This functions throws if the connection is lost.
-	 *
-	 * @param timeout the maximum time in milliseconds
-	 * @return the next event
-	 * @throw net::Error on errors or disconnection
-	 */
-	virtual json::Value next(int timeout = 30000) = 0;
-};
-
-/**
- * @class ConnectionBase
- * @brief Implementation for Ip or Local.
- */
-template <typename Address>
-class ConnectionBase : public Connection {
-private:
-	net::SocketTcp<Address> m_socket;
-	net::Listener<> m_listener;
-	Address m_address;
-
-	/* Input buffer */
-	std::string m_input;
-
-public:
-	/**
-	 * Construct the socket but do not connect immediately.
-	 *
-	 * @param address the address
-	 */
-	ConnectionBase(Address address)
-		: m_address(std::move(address))
-	{
-		m_socket.set(net::option::SockBlockMode{false});
-		m_listener.set(m_socket.handle(), net::Condition::Readable);
-	}
-
-	/**
-	 * @copydoc Connection::isConnected
-	 */
-	bool isConnected() const noexcept override
-	{
-		return m_socket.state() == net::State::Connected;
-	}
-
-	/**
-	 * @copydoc Connection::connect
-	 */
-	void connect(int timeout) override;
-
-	/**
-	 * @copydoc Connection::send
-	 */
-	void send(std::string msg, int timeout) override;
-
-	/**
-	 * @copydoc Connection::next
-	 */
-	json::Value next(int timeout) override;
-};
-
-template <typename Address>
-void ConnectionBase<Address>::connect(int timeout)
-{
-	m_socket.connect(m_address);
-
-	if (m_socket.state() == net::State::Connecting) {
-		m_listener.set(m_socket.handle(), net::Condition::Writable);
-		m_listener.wait(timeout);
-		m_socket.connect();
-		m_listener.unset(m_socket.handle(), net::Condition::Writable);
-	}
-}
-
-template <typename Address>
-void ConnectionBase<Address>::send(std::string msg, int timeout)
-{
-	assert(!msg.empty());
-
-	/* Add termination */
-	msg += "\r\n\r\n";
-
-	m_listener.remove(m_socket.handle());
-	m_listener.set(m_socket.handle(), net::Condition::Writable);
-	m_timer.reset();
-
-	while (!msg.empty()) {
-		/* Do not wait the time that is already passed */
-		m_listener.wait(clamp(timeout));
-
-		/* Try to send at most as possible */
-		msg.erase(0, m_socket.send(msg));
-	}
-
-	/* Timeout? */
-	if (!msg.empty())
-		throw std::runtime_error("operation timed out while sending to irccd");
-}
-
-template <typename Address>
-json::Value ConnectionBase<Address>::next(int timeout)
-{
-	/* Maybe there is already something */
-	std::string buffer = util::nextNetwork(m_input);
-
-	m_listener.remove(m_socket.handle());
-	m_listener.set(m_socket.handle(), net::Condition::Readable);
-	m_timer.reset();
-
-	/* Read if there is nothing */
-	while (buffer.empty() && isConnected()) {
-		/* Wait and read */
-		m_listener.wait(clamp(timeout));
-		m_input += m_socket.recv(512);
-
-		/* Finally try */
-		buffer = util::nextNetwork(m_input);
-	}
-
-	if (!isConnected())
-		throw std::runtime_error("connection lost");
-
-	json::Value value(json::Buffer{buffer});
-
-	if (!value.isObject())
-		throw std::invalid_argument("invalid message received");
-
-	return value;
-}
-
-} // !irccd
-
-#endif // !IRCCD_CONNECTION_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/connection.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,246 @@
+/*
+ * connection.hpp -- value wrapper for connecting to irccd
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_CONNECTION_HPP
+#define IRCCD_CONNECTION_HPP
+
+/**
+ * @file connection.hpp
+ * @brief Connection to irccd instance.
+ */
+
+#include <cassert>
+#include <stdexcept>
+
+#include <irccd/json.hpp>
+#include <irccd/system.hpp>
+#include <irccd/util.hpp>
+
+#include "elapsed-timer.hpp"
+#include "sockets.hpp"
+
+namespace irccd {
+
+/**
+ * @class Connection
+ * @brief Abstract class for connecting to irccd from Ip or Local addresses.
+ */
+class Connection {
+protected:
+	/**
+	 * Timer to track elapsed time.
+	 */
+	ElapsedTimer m_timer;
+
+	/**
+	 * Clamp the time to wait to be sure that it will be never less than 0.
+	 */
+	inline int clamp(int timeout) noexcept
+	{
+		return timeout < 0 ? -1 : (timeout - (int)m_timer.elapsed() < 0) ? 0 : (timeout - m_timer.elapsed());
+	}
+
+public:
+	/**
+	 * Default constructor.
+	 */
+	Connection() = default;
+
+	/**
+	 * Default destructor.
+	 */
+	virtual ~Connection() = default;
+
+	/**
+	 * Wait for the next requested response.
+	 *
+	 * @param name the response name
+	 * @param timeout the optional timeout
+	 * @return the object
+	 * @throw net::Error on errors or on timeout
+	 */
+	json::Value next(const std::string &name, int timeout = 30000);
+
+	/**
+	 * Just wait if the operation succeeded.
+	 *
+	 * @param name the response name
+	 * @param timeout the timeout
+	 */
+	void verify(const std::string &name, int timeout = 30000);
+
+	/**
+	 * Check if the socket is still connected.
+	 *
+	 * @return true if connected
+	 */
+	virtual bool isConnected() const noexcept = 0;
+
+	/**
+	 * Try to connect to the host.
+	 *
+	 * @param timeout the maximum time in milliseconds
+	 * @throw net::Error on errors or timeout
+	 */
+	virtual void connect(int timeout = 30000) = 0;
+
+	/**
+	 * Try to send the message in 30 seconds. The message must not end with \\r\\n\\r\\n, it is added automatically.
+	 *
+	 * @pre msg must not be empty
+	 * @param msg the message to send
+	 * @param timeout the maximum time in milliseconds
+	 * @throw net::Error on errors
+	 */
+	virtual void send(std::string msg, int timeout = 30000) = 0;
+
+	/**
+	 * Get the next event from irccd.
+	 *
+	 * This functions throws if the connection is lost.
+	 *
+	 * @param timeout the maximum time in milliseconds
+	 * @return the next event
+	 * @throw net::Error on errors or disconnection
+	 */
+	virtual json::Value next(int timeout = 30000) = 0;
+};
+
+/**
+ * @class ConnectionBase
+ * @brief Implementation for Ip or Local.
+ */
+template <typename Address>
+class ConnectionBase : public Connection {
+private:
+	net::SocketTcp<Address> m_socket;
+	net::Listener<> m_listener;
+	Address m_address;
+
+	/* Input buffer */
+	std::string m_input;
+
+public:
+	/**
+	 * Construct the socket but do not connect immediately.
+	 *
+	 * @param address the address
+	 */
+	ConnectionBase(Address address)
+		: m_address(std::move(address))
+	{
+		m_socket.set(net::option::SockBlockMode{false});
+		m_listener.set(m_socket.handle(), net::Condition::Readable);
+	}
+
+	/**
+	 * @copydoc Connection::isConnected
+	 */
+	bool isConnected() const noexcept override
+	{
+		return m_socket.state() == net::State::Connected;
+	}
+
+	/**
+	 * @copydoc Connection::connect
+	 */
+	void connect(int timeout) override;
+
+	/**
+	 * @copydoc Connection::send
+	 */
+	void send(std::string msg, int timeout) override;
+
+	/**
+	 * @copydoc Connection::next
+	 */
+	json::Value next(int timeout) override;
+};
+
+template <typename Address>
+void ConnectionBase<Address>::connect(int timeout)
+{
+	m_socket.connect(m_address);
+
+	if (m_socket.state() == net::State::Connecting) {
+		m_listener.set(m_socket.handle(), net::Condition::Writable);
+		m_listener.wait(timeout);
+		m_socket.connect();
+		m_listener.unset(m_socket.handle(), net::Condition::Writable);
+	}
+}
+
+template <typename Address>
+void ConnectionBase<Address>::send(std::string msg, int timeout)
+{
+	assert(!msg.empty());
+
+	/* Add termination */
+	msg += "\r\n\r\n";
+
+	m_listener.remove(m_socket.handle());
+	m_listener.set(m_socket.handle(), net::Condition::Writable);
+	m_timer.reset();
+
+	while (!msg.empty()) {
+		/* Do not wait the time that is already passed */
+		m_listener.wait(clamp(timeout));
+
+		/* Try to send at most as possible */
+		msg.erase(0, m_socket.send(msg));
+	}
+
+	/* Timeout? */
+	if (!msg.empty())
+		throw std::runtime_error("operation timed out while sending to irccd");
+}
+
+template <typename Address>
+json::Value ConnectionBase<Address>::next(int timeout)
+{
+	/* Maybe there is already something */
+	std::string buffer = util::nextNetwork(m_input);
+
+	m_listener.remove(m_socket.handle());
+	m_listener.set(m_socket.handle(), net::Condition::Readable);
+	m_timer.reset();
+
+	/* Read if there is nothing */
+	while (buffer.empty() && isConnected()) {
+		/* Wait and read */
+		m_listener.wait(clamp(timeout));
+		m_input += m_socket.recv(512);
+
+		/* Finally try */
+		buffer = util::nextNetwork(m_input);
+	}
+
+	if (!isConnected())
+		throw std::runtime_error("connection lost");
+
+	json::Value value(json::Buffer{buffer});
+
+	if (!value.isObject())
+		throw std::invalid_argument("invalid message received");
+
+	return value;
+}
+
+} // !irccd
+
+#endif // !IRCCD_CONNECTION_HPP
--- a/lib/irccd/elapsed-timer.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/elapsed-timer.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "elapsed-timer.h"
+#include "elapsed-timer.hpp"
 
 using std::chrono::duration_cast;
 using std::chrono::high_resolution_clock;
--- a/lib/irccd/elapsed-timer.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * elapsed-timer.h -- measure elapsed time
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_ELAPSED_TIMER_H
-#define IRCCD_ELAPSED_TIMER_H
-
-/**
- * @file elapsed-timer.h
- * @brief Measure elapsed time
- */
-
-#include <chrono>
-
-namespace irccd {
-
-/**
- * @class ElapsedTimer
- * @brief Measure elapsed time
- *
- * This class provides an abstraction to measure elapsed time since the
- * construction of the object.
- *
- * It uses std::chrono::high_resolution_clock for more precision and uses
- * milliseconds only.
- */
-class ElapsedTimer {
-private:
-	using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
-
-	TimePoint m_last;
-	bool m_paused{false};
-	unsigned m_elapsed{0};
-
-public:
-	/**
-	 * Construct the elapsed timer, start counting.
-	 */
-	ElapsedTimer() noexcept;
-
-	/**
-	 * Virtual destructor defaulted.
-	 */
-	virtual ~ElapsedTimer() = default;
-
-	/**
-	 * Put the timer on pause, the already elapsed time is stored.
-	 */
-	void pause() noexcept;
-
-	/**
-	 * Restart the timer, does not reset it.
-	 */
-	void restart() noexcept;
-
-	/**
-	 * Reset the timer to 0.
-	 */
-	void reset() noexcept;
-
-	/**
-	 * Get the number of elapsed milliseconds.
-	 *
-	 * @return the milliseconds
-	 */
-	unsigned elapsed() noexcept;
-};
-
-} // !irccd
-
-#endif // !IRCCD_ELAPSED_TIMER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/elapsed-timer.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,85 @@
+/*
+ * elapsed-timer.hpp -- measure elapsed time
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_ELAPSED_TIMER_HPP
+#define IRCCD_ELAPSED_TIMER_HPP
+
+/**
+ * @file elapsed-timer.hpp
+ * @brief Measure elapsed time
+ */
+
+#include <chrono>
+
+namespace irccd {
+
+/**
+ * @class ElapsedTimer
+ * @brief Measure elapsed time
+ *
+ * This class provides an abstraction to measure elapsed time since the
+ * construction of the object.
+ *
+ * It uses std::chrono::high_resolution_clock for more precision and uses
+ * milliseconds only.
+ */
+class ElapsedTimer {
+private:
+	using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
+
+	TimePoint m_last;
+	bool m_paused{false};
+	unsigned m_elapsed{0};
+
+public:
+	/**
+	 * Construct the elapsed timer, start counting.
+	 */
+	ElapsedTimer() noexcept;
+
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~ElapsedTimer() = default;
+
+	/**
+	 * Put the timer on pause, the already elapsed time is stored.
+	 */
+	void pause() noexcept;
+
+	/**
+	 * Restart the timer, does not reset it.
+	 */
+	void restart() noexcept;
+
+	/**
+	 * Reset the timer to 0.
+	 */
+	void reset() noexcept;
+
+	/**
+	 * Get the number of elapsed milliseconds.
+	 *
+	 * @return the milliseconds
+	 */
+	unsigned elapsed() noexcept;
+};
+
+} // !irccd
+
+#endif // !IRCCD_ELAPSED_TIMER_HPP
--- a/lib/irccd/fs.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/fs.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -32,7 +32,7 @@
 #  include <unistd.h>
 #endif
 
-#include "fs.h"
+#include "fs.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/fs.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
- * fs.h -- filesystem operations
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_FS_H
-#define IRCCD_FS_H
-
-/**
- * @file fs.h
- * @brief Filesystem operations made easy.
- *
- * The following options can be set by the user:
- *
-  * - **HAVE_ACCESS**: (bool) Set to true if unistd.h file and access(2) function are available.
- *
- * On Windows, you must link to shlwapi library.
- */
-
-#include <sys/stat.h>
-
-#include <regex>
-#include <string>
-#include <vector>
-
-namespace irccd {
-
-namespace fs {
-
-/**
- * @enum Flags
- * @brief Flags for readdir.
- */
-enum Flags {
-	Dot	= (1 << 0),	//!< if set, also lists "."
-	DotDot	= (1 << 1)	//!< if set, also lists ".."
-};
-
-/**
- * @class Entry
- * @brief Entry in the directory list.
- */
-class Entry {
-public:
-	/**
-	 * @brief Describe the type of an entry
-	 */
-	enum Type : char {
-		Unknown,	//!< File type is unknown,
-		File,		//!< File is regular type,
-		Dir,		//!< File is directory,
-		Link		//!< File is link
-	};
-
-	std::string name;	//! name of entry (base name)
-	Type type{Unknown};	//! type of file
-};
-
-/**
- * Check if two entries are identical.
- *
- * @param e1 the first entry
- * @param e2 the second entry
- * @return true if they are identical
- */
-bool operator==(const Entry &e1, const Entry &e2) noexcept;
-
-/**
- * Check if two entries are different.
- *
- * @param e1 the first entry
- * @param e2 the second entry
- * @return true if they are different
- */
-bool operator!=(const Entry &e1, const Entry &e2) noexcept;
-
-/**
- * Get the separator for that system.
- *
- * @return \ on Windows and / otherwise
- */
-inline char separator() noexcept
-{
-#if defined(_WIN32)
-	return '\\';
-#else
-	return '/';
-#endif
-}
-
-/**
- * Clean a path by removing any extra / or \ and add a trailing one.
- *
- * @param path the path
- * @return the updated path
- */
-std::string clean(std::string path);
-
-/**
- * Get the base name from a path.
- *
- * Example, baseName("/etc/foo.conf") // foo.conf
- *
- * @param path the path
- * @return the base name
- */
-std::string baseName(std::string path);
-
-/**
- * Get the parent directory from a path.
- *
- * Example, dirName("/etc/foo.conf") // /etc
- *
- * @param path the path
- * @return the parent directory
- */
-std::string dirName(std::string path);
-
-/**
- * Get stat information.
- *
- * @param path the path
- * @return the stat information
- * @throw std::runtime_error on failure
- */
-struct stat stat(const std::string &path);
-
-/**
- * Check if a file exists.
- *
- * If HAVE_ACCESS is defined, the function access is used, otherwise stat is used.
- *
- * @param path the path to check
- * @return true if the path exists
- */
-bool exists(const std::string &path) noexcept;
-
-/**
- * Check if the path is absolute.
- *
- * @param path the path
- * @return true if the path is absolute
- */
-bool isAbsolute(const std::string &path) noexcept;
-
-/**
- * Check if the path is relative.
- *
- * @param path the path
- * @return true if the path is absolute
- */
-bool isRelative(const std::string &path) noexcept;
-
-/**
- * Check if the file is readable.
- *
- * @param path the path
- * @return true if has read access
- */
-bool isReadable(const std::string &path) noexcept;
-
-/**
- * Check if the file is writable.
- *
- * @param path the path
- * @return true if has write access
- */
-bool isWritable(const std::string &path) noexcept;
-
-/**
- * Check if the file is a regular file.
- *
- * @param path the path
- * @return true if it is a file and false if not or not readable
- */
-bool isFile(const std::string &path) noexcept;
-
-/**
- * Check if the file is a directory.
- *
- * @param path the path
- * @return true if it is a directory and false if not or not readable
- */
-bool isDirectory(const std::string &path) noexcept;
-
-/**
- * Check if the file is a symbolic link.
- *
- * @param path the path
- * @return true if it is a symbolic link and false if not or not readable
- */
-bool isSymlink(const std::string &path) noexcept;
-
-/**
- * Read a directory and return a list of entries (not recursive).
- *
- * @param path the directory path
- * @param flags the optional flags (see Flags)
- * @return the list of entries
- * @throw std::runtime_error on failure
- */
-std::vector<Entry> readdir(const std::string &path, int flags = 0);
-
-/**
- * Create a directory recursively.
- *
- * @param path the path
- * @param mode the optional mode (not always supported)
- * @throw std::runtime_error on failure
- * @post all intermediate directories are created
- */
-void mkdir(const std::string &path, int mode = 0700);
-
-/**
- * Remove a directory recursively.
- *
- * If errors happens, they are silently discarded to remove as much as possible.
- *
- * @param path the path
- */
-void rmdir(const std::string &path) noexcept;
-
-/**
- * Search an item recursively.
- *
- * The predicate must have the following signature:
- *	void f(const std::string &base, const Entry &entry)
- *
- * Where:
- *   - base is the current parent directory in the tree
- *   - entry is the current entry
- *
- * @param base the base directory
- * @param predicate the predicate
- * @return the full path name to the file or empty string if never found
- * @throw std::runtime_error on read errors
- */
-template <typename Predicate>
-std::string findIf(const std::string &base, Predicate &&predicate)
-{
-	/*
-	 * Do not go deeply to the tree before testing all files in the current directory for performances reasons, we iterate
-	 * this directory to search for the entry name and iterate again over all sub directories if not found.
-	 */
-	std::string path;
-	std::vector<Entry> entries = readdir(base);
-
-	for (const auto &entry : entries) {
-		if (predicate(base, entry)) {
-			path = base + separator() + entry.name;
-			break;
-		}
-	}
-
-	if (path.empty()) {
-		for (const auto &entry : entries) {
-			if (entry.type == Entry::Dir) {
-				path = findIf(base + separator() + entry.name, std::forward<Predicate>(predicate));
-
-				if (!path.empty())
-					break;
-			}
-		}
-	}
-
-	return path;
-}
-
-/**
- * Find a file by name recursively.
- *
- * @param base the base directory
- * @param name the file name
- * @return the full path name to the file or empty string if never found
- * @throw std::runtime_error on read errors
- */
-inline std::string find(const std::string &base, const std::string &name)
-{
-	return findIf(base, [&] (const auto &, const auto &entry) { return entry.name == name; });
-}
-
-/**
- * Overload by regular expression.
- *
- * @param base the base directory
- * @param regex the regular expression
- * @return the full path name to the file or empty string if never found
- * @throw std::runtime_error on read errors
- */
-inline std::string find(const std::string &base, const std::regex &regex)
-{
-	return findIf(base, [&] (const auto &, const auto &entry) { return std::regex_match(entry.name, regex); });
-}
-
-/**
- * Get the current working directory.
- *
- * @return the current working directory
- * @throw std::runtime_error on failure
- */
-std::string cwd();
-
-} // !fs
-
-} // !irccd
-
-#endif // !IRCCD_FS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/fs.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,320 @@
+/*
+ * fs.hpp -- filesystem operations
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_FS_HPP
+#define IRCCD_FS_HPP
+
+/**
+ * @file fs.hpp
+ * @brief Filesystem operations made easy.
+ *
+ * The following options can be set by the user:
+ *
+  * - **HAVE_ACCESS**: (bool) Set to true if unistd.h file and access(2) function are available.
+ *
+ * On Windows, you must link to shlwapi library.
+ */
+
+#include <sys/stat.h>
+
+#include <regex>
+#include <string>
+#include <vector>
+
+namespace irccd {
+
+namespace fs {
+
+/**
+ * @enum Flags
+ * @brief Flags for readdir.
+ */
+enum Flags {
+	Dot	= (1 << 0),	//!< if set, also lists "."
+	DotDot	= (1 << 1)	//!< if set, also lists ".."
+};
+
+/**
+ * @class Entry
+ * @brief Entry in the directory list.
+ */
+class Entry {
+public:
+	/**
+	 * @brief Describe the type of an entry
+	 */
+	enum Type : char {
+		Unknown,	//!< File type is unknown,
+		File,		//!< File is regular type,
+		Dir,		//!< File is directory,
+		Link		//!< File is link
+	};
+
+	std::string name;	//! name of entry (base name)
+	Type type{Unknown};	//! type of file
+};
+
+/**
+ * Check if two entries are identical.
+ *
+ * @param e1 the first entry
+ * @param e2 the second entry
+ * @return true if they are identical
+ */
+bool operator==(const Entry &e1, const Entry &e2) noexcept;
+
+/**
+ * Check if two entries are different.
+ *
+ * @param e1 the first entry
+ * @param e2 the second entry
+ * @return true if they are different
+ */
+bool operator!=(const Entry &e1, const Entry &e2) noexcept;
+
+/**
+ * Get the separator for that system.
+ *
+ * @return \ on Windows and / otherwise
+ */
+inline char separator() noexcept
+{
+#if defined(_WIN32)
+	return '\\';
+#else
+	return '/';
+#endif
+}
+
+/**
+ * Clean a path by removing any extra / or \ and add a trailing one.
+ *
+ * @param path the path
+ * @return the updated path
+ */
+std::string clean(std::string path);
+
+/**
+ * Get the base name from a path.
+ *
+ * Example, baseName("/etc/foo.conf") // foo.conf
+ *
+ * @param path the path
+ * @return the base name
+ */
+std::string baseName(std::string path);
+
+/**
+ * Get the parent directory from a path.
+ *
+ * Example, dirName("/etc/foo.conf") // /etc
+ *
+ * @param path the path
+ * @return the parent directory
+ */
+std::string dirName(std::string path);
+
+/**
+ * Get stat information.
+ *
+ * @param path the path
+ * @return the stat information
+ * @throw std::runtime_error on failure
+ */
+struct stat stat(const std::string &path);
+
+/**
+ * Check if a file exists.
+ *
+ * If HAVE_ACCESS is defined, the function access is used, otherwise stat is used.
+ *
+ * @param path the path to check
+ * @return true if the path exists
+ */
+bool exists(const std::string &path) noexcept;
+
+/**
+ * Check if the path is absolute.
+ *
+ * @param path the path
+ * @return true if the path is absolute
+ */
+bool isAbsolute(const std::string &path) noexcept;
+
+/**
+ * Check if the path is relative.
+ *
+ * @param path the path
+ * @return true if the path is absolute
+ */
+bool isRelative(const std::string &path) noexcept;
+
+/**
+ * Check if the file is readable.
+ *
+ * @param path the path
+ * @return true if has read access
+ */
+bool isReadable(const std::string &path) noexcept;
+
+/**
+ * Check if the file is writable.
+ *
+ * @param path the path
+ * @return true if has write access
+ */
+bool isWritable(const std::string &path) noexcept;
+
+/**
+ * Check if the file is a regular file.
+ *
+ * @param path the path
+ * @return true if it is a file and false if not or not readable
+ */
+bool isFile(const std::string &path) noexcept;
+
+/**
+ * Check if the file is a directory.
+ *
+ * @param path the path
+ * @return true if it is a directory and false if not or not readable
+ */
+bool isDirectory(const std::string &path) noexcept;
+
+/**
+ * Check if the file is a symbolic link.
+ *
+ * @param path the path
+ * @return true if it is a symbolic link and false if not or not readable
+ */
+bool isSymlink(const std::string &path) noexcept;
+
+/**
+ * Read a directory and return a list of entries (not recursive).
+ *
+ * @param path the directory path
+ * @param flags the optional flags (see Flags)
+ * @return the list of entries
+ * @throw std::runtime_error on failure
+ */
+std::vector<Entry> readdir(const std::string &path, int flags = 0);
+
+/**
+ * Create a directory recursively.
+ *
+ * @param path the path
+ * @param mode the optional mode (not always supported)
+ * @throw std::runtime_error on failure
+ * @post all intermediate directories are created
+ */
+void mkdir(const std::string &path, int mode = 0700);
+
+/**
+ * Remove a directory recursively.
+ *
+ * If errors happens, they are silently discarded to remove as much as possible.
+ *
+ * @param path the path
+ */
+void rmdir(const std::string &path) noexcept;
+
+/**
+ * Search an item recursively.
+ *
+ * The predicate must have the following signature:
+ *	void f(const std::string &base, const Entry &entry)
+ *
+ * Where:
+ *   - base is the current parent directory in the tree
+ *   - entry is the current entry
+ *
+ * @param base the base directory
+ * @param predicate the predicate
+ * @return the full path name to the file or empty string if never found
+ * @throw std::runtime_error on read errors
+ */
+template <typename Predicate>
+std::string findIf(const std::string &base, Predicate &&predicate)
+{
+	/*
+	 * Do not go deeply to the tree before testing all files in the current directory for performances reasons, we iterate
+	 * this directory to search for the entry name and iterate again over all sub directories if not found.
+	 */
+	std::string path;
+	std::vector<Entry> entries = readdir(base);
+
+	for (const auto &entry : entries) {
+		if (predicate(base, entry)) {
+			path = base + separator() + entry.name;
+			break;
+		}
+	}
+
+	if (path.empty()) {
+		for (const auto &entry : entries) {
+			if (entry.type == Entry::Dir) {
+				path = findIf(base + separator() + entry.name, std::forward<Predicate>(predicate));
+
+				if (!path.empty())
+					break;
+			}
+		}
+	}
+
+	return path;
+}
+
+/**
+ * Find a file by name recursively.
+ *
+ * @param base the base directory
+ * @param name the file name
+ * @return the full path name to the file or empty string if never found
+ * @throw std::runtime_error on read errors
+ */
+inline std::string find(const std::string &base, const std::string &name)
+{
+	return findIf(base, [&] (const auto &, const auto &entry) { return entry.name == name; });
+}
+
+/**
+ * Overload by regular expression.
+ *
+ * @param base the base directory
+ * @param regex the regular expression
+ * @return the full path name to the file or empty string if never found
+ * @throw std::runtime_error on read errors
+ */
+inline std::string find(const std::string &base, const std::regex &regex)
+{
+	return findIf(base, [&] (const auto &, const auto &entry) { return std::regex_match(entry.name, regex); });
+}
+
+/**
+ * Get the current working directory.
+ *
+ * @return the current working directory
+ * @throw std::runtime_error on failure
+ */
+std::string cwd();
+
+} // !fs
+
+} // !irccd
+
+#endif // !IRCCD_FS_HPP
--- a/lib/irccd/ini.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/ini.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -29,7 +29,7 @@
 #  include <Shlwapi.h>	// for PathIsRelative
 #endif
 
-#include "ini.h"
+#include "ini.hpp"
 
 namespace {
 
--- a/lib/irccd/ini.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,538 +0,0 @@
-/*
- * ini.h -- .ini file parsing
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_INI_H
-#define IRCCD_INI_H
-
-/**
- * @file ini.h
- * @brief Configuration file parser.
- */
-
-#include <algorithm>
-#include <exception>
-#include <stdexcept>
-#include <string>
-#include <vector>
-
-namespace irccd {
-
-/**
- * Namespace for ini related classes.
- */
-namespace ini {
-
-class Document;
-
-/**
- * @class Error
- * @brief Error in a file
- */
-class Error : public std::exception {
-private:
-	int m_line;		//!< line number
-	int m_column;		//!< line column
-	std::string m_message;	//!< error message
-
-public:
-	/**
-	 * Constructor.
-	 *
-	 * @param l the line
-	 * @param c the column
-	 * @param m the message
-	 */
-	inline Error(int l, int c, std::string m) noexcept
-		: m_line(l)
-		, m_column(c)
-		, m_message(std::move(m))
-	{
-	}
-
-	/**
-	 * Get the line number.
-	 *
-	 * @return the line
-	 */
-	inline int line() const noexcept
-	{
-		return m_line;
-	}
-
-	/**
-	 * Get the column number.
-	 *
-	 * @return the column
-	 */
-	inline int column() const noexcept
-	{
-		return m_column;
-	}
-
-	/**
-	 * Return the raw error message (no line and column shown).
-	 *
-	 * @return the error message
-	 */
-	const char *what() const noexcept override
-	{
-		return m_message.c_str();
-	}
-};
-
-/**
- * @class Token
- * @brief Describe a token read in the .ini source
- *
- * This class can be used when you want to parse a .ini file yourself.
- *
- * @see Document::analyze
- */
-class Token {
-public:
-	/**
-	 * @brief Token type
-	 */
-	enum Type {
-		Include,	//!< include statement
-		Section,	//!< [section]
-		Word,		//!< word without quotes
-		QuotedWord,	//!< word with quotes
-		Assign,		//!< = assignment
-		ListBegin,	//!< begin of list (
-		ListEnd,	//!< end of list )
-		Comma		//!< list separation
-	};
-
-private:
-	Type m_type;
-	int m_line;
-	int m_column;
-	std::string m_value;
-
-public:
-	/**
-	 * Construct a token.
-	 *
-	 * @param type the type
-	 * @param line the line
-	 * @param column the column
-	 * @param value the value
-	 */
-	Token(Type type, int line, int column, std::string value = "") noexcept
-		: m_type(type)
-		, m_line(line)
-		, m_column(column)
-	{
-		switch (type) {
-		case Include:
-			m_value = "@include";
-			break;
-		case Section:
-		case Word:
-		case QuotedWord:
-			m_value = value;
-			break;
-		case Assign:
-			m_value = "=";
-			break;
-		case ListBegin:
-			m_value = "(";
-			break;
-		case ListEnd:
-			m_value = ")";
-			break;
-		case Comma:
-			m_value = ",";
-			break;
-		default:
-			break;
-		}
-	}
-
-	/**
-	 * Get the type.
-	 *
-	 * @return the type
-	 */
-	inline Type type() const noexcept
-	{
-		return m_type;
-	}
-
-	/**
-	 * Get the line.
-	 *
-	 * @return the line
-	 */
-	inline int line() const noexcept
-	{
-		return m_line;
-	}
-
-	/**
-	 * Get the column.
-	 *
-	 * @return the column
-	 */
-	inline int column() const noexcept
-	{
-		return m_column;
-	}
-
-	/**
-	 * Get the value. For words, quoted words and section, the value is the content. Otherwise it's the
-	 * characters parsed.
-	 *
-	 * @return the value
-	 */
-	inline const std::string &value() const noexcept
-	{
-		return m_value;
-	}
-};
-
-/**
- * List of tokens in order they are analyzed.
- */
-using Tokens = std::vector<Token>;
-
-/**
- * @class Option
- * @brief Option definition.
- */
-class Option : public std::vector<std::string> {
-private:
-	std::string m_key;
-
-public:
-	/**
-	 * Construct an empty option.
-	 *
-	 * @param key the key
-	 * @param value the value
-	 */
-	inline Option(std::string key) noexcept
-		: std::vector<std::string>()
-		, m_key(std::move(key))
-	{
-	}
-
-	/**
-	 * Construct a single option.
-	 *
-	 * @param key the key
-	 * @param value the value
-	 */
-	inline Option(std::string key, std::string value) noexcept
-		: m_key(std::move(key))
-	{
-		push_back(std::move(value));
-	}
-
-	/**
-	 * Construct a list option.
-	 *
-	 * @param key the key
-	 * @param values the values
-	 */
-	inline Option(std::string key, std::vector<std::string> values) noexcept
-		: std::vector<std::string>(std::move(values))
-		, m_key(std::move(key))
-	{
-	}
-
-	/**
-	 * Get the option key.
-	 *
-	 * @return the key
-	 */
-	inline const std::string &key() const noexcept
-	{
-		return m_key;
-	}
-
-	/**
-	 * Get the option value.
-	 *
-	 * @return the value
-	 */
-	inline const std::string &value() const noexcept
-	{
-		static std::string dummy;
-
-		return empty() ? dummy : (*this)[0];
-	}
-};
-
-/**
- * @class Section
- * @brief Section that contains one or more options.
- */
-class Section : public std::vector<Option> {
-private:
-	std::string m_key;
-
-public:
-	/**
-	 * Construct a section with its name.
-	 *
-	 * @param key the key
-	 */
-	inline Section(std::string key) noexcept
-		: m_key(std::move(key))
-	{
-	}
-
-	/**
-	 * Get the section key.
-	 *
-	 * @return the key
-	 */
-	inline const std::string &key() const noexcept
-	{
-		return m_key;
-	}
-
-	/**
-	 * Check if the section contains a specific option.
-	 *
-	 * @param key the option key
-	 * @return true if the option exists
-	 */
-	inline bool contains(const std::string &key) const noexcept
-	{
-		return find(key) != end();
-	}
-
-	/**
-	 * Access an option at the specified key.
-	 *
-	 * @param key the key
-	 * @return the option
-	 * @throw std::out_of_range if the key does not exist
-	 */
-	inline Option &operator[](const std::string &key)
-	{
-		return *find(key);
-	}
-
-	/**
-	 * Access an option at the specified key.
-	 *
-	 * @param key the key
-	 * @return the option
-	 * @throw std::out_of_range if the key does not exist
-	 */
-	inline const Option &operator[](const std::string &key) const
-	{
-		return *find(key);
-	}
-
-	/**
-	 * Find an option by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline iterator find(const std::string &key) noexcept
-	{
-		return std::find_if(begin(), end(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Find an option by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline const_iterator find(const std::string &key) const noexcept
-	{
-		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Inherited operators.
-	 */
-	using std::vector<Option>::operator[];
-};
-
-/**
- * @class File
- * @brief Source for reading .ini files.
- */
-class File {
-public:
-	/**
-	 * Path to the file.
-	 */
-	std::string path;
-};
-
-/**
- * @class Buffer
- * @brief Source for reading ini from text.
- * @note the include statement is not supported with buffers.
- */
-class Buffer {
-public:
-	/**
-	 * The ini content.
-	 */
-	std::string text;
-};
-
-/**
- * @class Document
- * @brief Ini config file loader
- */
-class Document : public std::vector<Section> {
-private:
-	std::string m_path;
-
-public:
-	/**
-	 * Analyze a file and extract tokens. If the function succeeds, that does not mean the content is valid,
-	 * it just means that there are no syntax error.
-	 *
-	 * For example, this class does not allow adding options under no sections and this function will not
-	 * detect that issue.
-	 *
-	 * @param file the file to read
-	 * @return the list of tokens
-	 * @throws Error on errors
-	 */
-	static Tokens analyze(const File &file);
-
-	/**
-	 * Overloaded function for buffers.
-	 *
-	 * @param buffer the buffer to read
-	 * @return the list of tokens
-	 * @throws Error on errors
-	 */
-	static Tokens analyze(const Buffer &buffer);
-
-	/**
-	 * Show all tokens and their description.
-	 *
-	 * @param tokens the tokens
-	 */
-	static void dump(const Tokens &tokens);
-
-	/**
-	 * Construct a document from a file.
-	 *
-	 * @param file the file to read
-	 * @throws Error on errors
-	 */
-	Document(const File &file);
-
-	/**
-	 * Overloaded constructor for buffers.
-	 *
-	 * @param buffer the buffer to read
-	 * @throws Error on errors
-	 */
-	Document(const Buffer &buffer);
-
-	/**
-	 * Get the current document path, only useful when constructed from File source.
-	 *
-	 * @return the path
-	 */
-	inline const std::string &path() const noexcept
-	{
-		return m_path;
-	}
-
-	/**
-	 * Check if a document has a specific section.
-	 *
-	 * @param key the key
-	 */
-	inline bool contains(const std::string &key) const noexcept
-	{
-		return std::find_if(begin(), end(), [&] (const auto &sc) { return sc.key() == key; }) != end();
-	}
-
-	/**
-	 * Access a section at the specified key.
-	 *
-	 * @param key the key
-	 * @return the section
-	 * @throw std::out_of_range if the key does not exist
-	 */
-	inline Section &operator[](const std::string &key)
-	{
-		return *find(key);
-	}
-
-	/**
-	 * Access a section at the specified key.
-	 *
-	 * @param key the key
-	 * @return the section
-	 * @throw std::out_of_range if the key does not exist
-	 */
-	inline const Section &operator[](const std::string &key) const
-	{
-		return *find(key);
-	}
-
-	/**
-	 * Find a section by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline iterator find(const std::string &key) noexcept
-	{
-		return std::find_if(begin(), end(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Find a section by key and return an iterator.
-	 *
-	 * @param key the key
-	 * @return the iterator or end() if not found
-	 */
-	inline const_iterator find(const std::string &key) const noexcept
-	{
-		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
-			return o.key() == key;
-		});
-	}
-
-	/**
-	 * Inherited operators.
-	 */
-	using std::vector<Section>::operator[];
-};
-
-} // !ini
-
-} // !irccd
-
-#endif // !IRCCD_INI_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/ini.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,538 @@
+/*
+ * ini.hpp -- .ini file parsing
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_INI_HPP
+#define IRCCD_INI_HPP
+
+/**
+ * @file ini.hpp
+ * @brief Configuration file parser.
+ */
+
+#include <algorithm>
+#include <exception>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+namespace irccd {
+
+/**
+ * Namespace for ini related classes.
+ */
+namespace ini {
+
+class Document;
+
+/**
+ * @class Error
+ * @brief Error in a file
+ */
+class Error : public std::exception {
+private:
+	int m_line;		//!< line number
+	int m_column;		//!< line column
+	std::string m_message;	//!< error message
+
+public:
+	/**
+	 * Constructor.
+	 *
+	 * @param l the line
+	 * @param c the column
+	 * @param m the message
+	 */
+	inline Error(int l, int c, std::string m) noexcept
+		: m_line(l)
+		, m_column(c)
+		, m_message(std::move(m))
+	{
+	}
+
+	/**
+	 * Get the line number.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column number.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Return the raw error message (no line and column shown).
+	 *
+	 * @return the error message
+	 */
+	const char *what() const noexcept override
+	{
+		return m_message.c_str();
+	}
+};
+
+/**
+ * @class Token
+ * @brief Describe a token read in the .ini source
+ *
+ * This class can be used when you want to parse a .ini file yourself.
+ *
+ * @see Document::analyze
+ */
+class Token {
+public:
+	/**
+	 * @brief Token type
+	 */
+	enum Type {
+		Include,	//!< include statement
+		Section,	//!< [section]
+		Word,		//!< word without quotes
+		QuotedWord,	//!< word with quotes
+		Assign,		//!< = assignment
+		ListBegin,	//!< begin of list (
+		ListEnd,	//!< end of list )
+		Comma		//!< list separation
+	};
+
+private:
+	Type m_type;
+	int m_line;
+	int m_column;
+	std::string m_value;
+
+public:
+	/**
+	 * Construct a token.
+	 *
+	 * @param type the type
+	 * @param line the line
+	 * @param column the column
+	 * @param value the value
+	 */
+	Token(Type type, int line, int column, std::string value = "") noexcept
+		: m_type(type)
+		, m_line(line)
+		, m_column(column)
+	{
+		switch (type) {
+		case Include:
+			m_value = "@include";
+			break;
+		case Section:
+		case Word:
+		case QuotedWord:
+			m_value = value;
+			break;
+		case Assign:
+			m_value = "=";
+			break;
+		case ListBegin:
+			m_value = "(";
+			break;
+		case ListEnd:
+			m_value = ")";
+			break;
+		case Comma:
+			m_value = ",";
+			break;
+		default:
+			break;
+		}
+	}
+
+	/**
+	 * Get the type.
+	 *
+	 * @return the type
+	 */
+	inline Type type() const noexcept
+	{
+		return m_type;
+	}
+
+	/**
+	 * Get the line.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Get the value. For words, quoted words and section, the value is the content. Otherwise it's the
+	 * characters parsed.
+	 *
+	 * @return the value
+	 */
+	inline const std::string &value() const noexcept
+	{
+		return m_value;
+	}
+};
+
+/**
+ * List of tokens in order they are analyzed.
+ */
+using Tokens = std::vector<Token>;
+
+/**
+ * @class Option
+ * @brief Option definition.
+ */
+class Option : public std::vector<std::string> {
+private:
+	std::string m_key;
+
+public:
+	/**
+	 * Construct an empty option.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	inline Option(std::string key) noexcept
+		: std::vector<std::string>()
+		, m_key(std::move(key))
+	{
+	}
+
+	/**
+	 * Construct a single option.
+	 *
+	 * @param key the key
+	 * @param value the value
+	 */
+	inline Option(std::string key, std::string value) noexcept
+		: m_key(std::move(key))
+	{
+		push_back(std::move(value));
+	}
+
+	/**
+	 * Construct a list option.
+	 *
+	 * @param key the key
+	 * @param values the values
+	 */
+	inline Option(std::string key, std::vector<std::string> values) noexcept
+		: std::vector<std::string>(std::move(values))
+		, m_key(std::move(key))
+	{
+	}
+
+	/**
+	 * Get the option key.
+	 *
+	 * @return the key
+	 */
+	inline const std::string &key() const noexcept
+	{
+		return m_key;
+	}
+
+	/**
+	 * Get the option value.
+	 *
+	 * @return the value
+	 */
+	inline const std::string &value() const noexcept
+	{
+		static std::string dummy;
+
+		return empty() ? dummy : (*this)[0];
+	}
+};
+
+/**
+ * @class Section
+ * @brief Section that contains one or more options.
+ */
+class Section : public std::vector<Option> {
+private:
+	std::string m_key;
+
+public:
+	/**
+	 * Construct a section with its name.
+	 *
+	 * @param key the key
+	 */
+	inline Section(std::string key) noexcept
+		: m_key(std::move(key))
+	{
+	}
+
+	/**
+	 * Get the section key.
+	 *
+	 * @return the key
+	 */
+	inline const std::string &key() const noexcept
+	{
+		return m_key;
+	}
+
+	/**
+	 * Check if the section contains a specific option.
+	 *
+	 * @param key the option key
+	 * @return true if the option exists
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		return find(key) != end();
+	}
+
+	/**
+	 * Access an option at the specified key.
+	 *
+	 * @param key the key
+	 * @return the option
+	 * @throw std::out_of_range if the key does not exist
+	 */
+	inline Option &operator[](const std::string &key)
+	{
+		return *find(key);
+	}
+
+	/**
+	 * Access an option at the specified key.
+	 *
+	 * @param key the key
+	 * @return the option
+	 * @throw std::out_of_range if the key does not exist
+	 */
+	inline const Option &operator[](const std::string &key) const
+	{
+		return *find(key);
+	}
+
+	/**
+	 * Find an option by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline iterator find(const std::string &key) noexcept
+	{
+		return std::find_if(begin(), end(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Find an option by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline const_iterator find(const std::string &key) const noexcept
+	{
+		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Inherited operators.
+	 */
+	using std::vector<Option>::operator[];
+};
+
+/**
+ * @class File
+ * @brief Source for reading .ini files.
+ */
+class File {
+public:
+	/**
+	 * Path to the file.
+	 */
+	std::string path;
+};
+
+/**
+ * @class Buffer
+ * @brief Source for reading ini from text.
+ * @note the include statement is not supported with buffers.
+ */
+class Buffer {
+public:
+	/**
+	 * The ini content.
+	 */
+	std::string text;
+};
+
+/**
+ * @class Document
+ * @brief Ini config file loader
+ */
+class Document : public std::vector<Section> {
+private:
+	std::string m_path;
+
+public:
+	/**
+	 * Analyze a file and extract tokens. If the function succeeds, that does not mean the content is valid,
+	 * it just means that there are no syntax error.
+	 *
+	 * For example, this class does not allow adding options under no sections and this function will not
+	 * detect that issue.
+	 *
+	 * @param file the file to read
+	 * @return the list of tokens
+	 * @throws Error on errors
+	 */
+	static Tokens analyze(const File &file);
+
+	/**
+	 * Overloaded function for buffers.
+	 *
+	 * @param buffer the buffer to read
+	 * @return the list of tokens
+	 * @throws Error on errors
+	 */
+	static Tokens analyze(const Buffer &buffer);
+
+	/**
+	 * Show all tokens and their description.
+	 *
+	 * @param tokens the tokens
+	 */
+	static void dump(const Tokens &tokens);
+
+	/**
+	 * Construct a document from a file.
+	 *
+	 * @param file the file to read
+	 * @throws Error on errors
+	 */
+	Document(const File &file);
+
+	/**
+	 * Overloaded constructor for buffers.
+	 *
+	 * @param buffer the buffer to read
+	 * @throws Error on errors
+	 */
+	Document(const Buffer &buffer);
+
+	/**
+	 * Get the current document path, only useful when constructed from File source.
+	 *
+	 * @return the path
+	 */
+	inline const std::string &path() const noexcept
+	{
+		return m_path;
+	}
+
+	/**
+	 * Check if a document has a specific section.
+	 *
+	 * @param key the key
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		return std::find_if(begin(), end(), [&] (const auto &sc) { return sc.key() == key; }) != end();
+	}
+
+	/**
+	 * Access a section at the specified key.
+	 *
+	 * @param key the key
+	 * @return the section
+	 * @throw std::out_of_range if the key does not exist
+	 */
+	inline Section &operator[](const std::string &key)
+	{
+		return *find(key);
+	}
+
+	/**
+	 * Access a section at the specified key.
+	 *
+	 * @param key the key
+	 * @return the section
+	 * @throw std::out_of_range if the key does not exist
+	 */
+	inline const Section &operator[](const std::string &key) const
+	{
+		return *find(key);
+	}
+
+	/**
+	 * Find a section by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline iterator find(const std::string &key) noexcept
+	{
+		return std::find_if(begin(), end(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Find a section by key and return an iterator.
+	 *
+	 * @param key the key
+	 * @return the iterator or end() if not found
+	 */
+	inline const_iterator find(const std::string &key) const noexcept
+	{
+		return std::find_if(cbegin(), cend(), [&] (const auto &o) {
+			return o.key() == key;
+		});
+	}
+
+	/**
+	 * Inherited operators.
+	 */
+	using std::vector<Section>::operator[];
+};
+
+} // !ini
+
+} // !irccd
+
+#endif // !IRCCD_INI_HPP
--- a/lib/irccd/irccd.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/irccd.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -19,11 +19,11 @@
 #include <algorithm>
 #include <stdexcept>
 
-#include "irccd.h"
-#include "fs.h"
-#include "logger.h"
-#include "path.h"
-#include "util.h"
+#include "irccd.hpp"
+#include "fs.hpp"
+#include "logger.hpp"
+#include "path.hpp"
+#include "util.hpp"
 
 using namespace std;
 using namespace std::placeholders;
--- a/lib/irccd/irccd.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,543 +0,0 @@
-/*
- * irccd.h -- main irccd class
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_H
-#define IRCCD_H
-
-/**
- * @file irccd.h
- * @brief Base class for irccd front end.
- */
-
-#include <atomic>
-#include <cassert>
-#include <condition_variable>
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <vector>
-
-#include <irccd/sysconfig.h>
-
-#include "sockets.h"
-
-#if defined(WITH_JS)
-#  include "plugin.h"
-#endif
-
-#include "application.h"
-#include "logger.h"
-#include "rule.h"
-#include "server.h"
-#include "transport-server.h"
-
-namespace irccd {
-
-class Plugin;
-class TransportCommand;
-
-/**
- * Event to execute after the poll.
- */
-using Event = std::function<void ()>;
-
-/**
- * List of events.
- */
-using Events = std::vector<Event>;
-
-/**
- * Map of identities.
- */
-using Identities = std::unordered_map<std::string, ServerIdentity>;
-
-/**
- * List of rules.
- */
-using Rules = std::vector<Rule>;
-
-/**
- * @class ServerEvent
- * @brief Structure that owns several informations about an IRC event
- *
- * This structure is used to dispatch the IRC event to the plugins and the transports.
- */
-class ServerEvent {
-public:
-	std::string server;					//!< the server
-	std::string origin;					//!< the originator
-	std::string target;					//!< the target
-	std::string json;					//!< the JSON message
-#if defined(WITH_JS)
-	std::function<std::string (Plugin &)> name;		//!< the function to event name
-	std::function<void (Plugin &)> exec;			//!< the plugin function to call
-#endif
-};
-
-/**
- * Map of servers.
- */
-using Servers = std::unordered_map<std::string, std::shared_ptr<Server>>;
-
-/**
- * Map of transport command handlers.
- */
-using TransportCommands = std::unordered_map<std::string, std::unique_ptr<TransportCommand>>;
-
-#if defined(WITH_JS)
-
-/**
- * Map of plugins.
- */
-using Plugins = std::unordered_map<std::string, std::shared_ptr<Plugin>>;
-
-/**
- * Map of plugin configurations.
- */
-using PluginConfigs = std::unordered_map<std::string, PluginConfig>;
-
-#endif
-
-/**
- * @class Irccd
- * @brief Irccd main instance
- *
- * This class is used as the main application event loop, it stores servers, plugins and transports.
- *
- * In a general manner, no code in irccd is thread-safe because irccd is mono-threaded except the JavaScript timer
- * API.
- *
- * If you plan to add more threads to irccd, then the simpliest and safest way to execute thread-safe code is to
- * register an event using Irccd::post function which will be called during the event loop dispatching.
- *
- * Thus, except noticed as thread-safe, no function is assumed to be.
- */
-class Irccd : public Application {
-private:
-	template <typename T>
-	using LookupTable = std::unordered_map<net::Handle, std::shared_ptr<T>>;
-
-	/* Main loop */
-	std::atomic<bool> m_running{true};
-
-	/* Mutex for post() */
-	std::mutex m_mutex;
-
-	/* IPC */
-	net::SocketTcp<net::address::Ip> m_socketServer;
-	net::SocketTcp<net::address::Ip> m_socketClient;
-
-	/* Event loop */
-	Events m_events;
-
-	/* Servers */
-	Servers m_servers;
-
-	/* Optional JavaScript plugins */
-#if defined(WITH_JS)
-	Plugins m_plugins;
-	PluginConfigs m_pluginConf;
-#endif
-
-	/* Identities */
-	Identities m_identities;
-
-	/* Rules */
-	Rules m_rules;
-
-	/* Lookup tables */
-	LookupTable<TransportClient> m_lookupTransportClients;
-	LookupTable<TransportServer> m_lookupTransportServers;
-
-	/*
-	 * Server slots
-	 * ----------------------------------------------------------
-	 */
-
-	void handleServerChannelMode(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string mode, std::string arg);
-	void handleServerChannelNotice(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string notice);
-	void handleServerConnect(std::weak_ptr<Server> server);
-	void handleServerInvite(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string target);
-	void handleServerJoin(std::weak_ptr<Server> server, std::string origin, std::string channel);
-	void handleServerKick(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string target, std::string reason);
-	void handleServerMessage(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string message);
-	void handleServerMe(std::weak_ptr<Server> server, std::string origin, std::string target, std::string message);
-	void handleServerMode(std::weak_ptr<Server> server, std::string origin, std::string mode);
-	void handleServerNames(std::weak_ptr<Server> server, std::string channel, std::set<std::string> nicknames);
-	void handleServerNick(std::weak_ptr<Server> server, std::string origin, std::string nickname);
-	void handleServerNotice(std::weak_ptr<Server> server, std::string origin, std::string message);
-	void handleServerPart(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string reason);
-	void handleServerQuery(std::weak_ptr<Server> server, std::string origin, std::string message);
-	void handleServerTopic(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string topic);
-	void handleServerWhois(std::weak_ptr<Server> server, ServerWhois whois);
-
-	/*
-	 * Transport clients slots
-	 * ----------------------------------------------------------
-	 */
-	void handleTransportCommand(std::weak_ptr<TransportClient>, const json::Value &);
-	void handleTransportDie(std::weak_ptr<TransportClient>);
-
-	/*
-	 * Plugin timers slots
-	 * ----------------------------------------------------------
-	 *
-	 * These handlers catch the timer signals and call the plugin function or remove the timer from the plugin.
-	 */
-
-#if defined(WITH_JS)
-	void handleTimerSignal(std::weak_ptr<Plugin>, std::shared_ptr<Timer>);
-	void handleTimerEnd(std::weak_ptr<Plugin>, std::shared_ptr<Timer>);
-#endif
-
-	/*
-	 * Process the socket sets.
-	 * ----------------------------------------------------------
-	 *
-	 * These functions are called after polling which sockets are ready for reading/writing.
-	 */
-
-	void processIpc(fd_set &input);
-	void processTransportClients(fd_set &input, fd_set &output);
-	void processTransportServers(fd_set &input);
-	void processServers(fd_set &input, fd_set &output);
-	void process(fd_set &setinput, fd_set &setoutput);
-
-public:
-	/**
-	 * Constructor that instanciate IPC.
-	 */
-	Irccd();
-
-	/**
-	 * Load a configuration into irccd. Added as convenience to allow expressions like `irccd.load(Config{"foo"})`.
-	 *
-	 * @param config the configuration loader
-	 */
-	template <typename T>
-	inline void load(T &&config)
-	{
-		config.load(*this);
-	}
-
-	/**
-	 * Add an event to the queue. This will immediately signals the event loop to interrupt itself to dispatch
-	 * the pending events.
-	 *
-	 * @param ev the event
-	 * @note Thread-safe
-	 */
-	void post(Event ev) noexcept;
-
-	/**
-	 * This function wraps post() to iterate over all plugins to call the function and to send to all
-	 * connected transport the event.
-	 *
-	 * @param ev the event
-	 */
-	void postServerEvent(ServerEvent ev) noexcept;
-
-	/*
-	 * Identity management
-	 * ----------------------------------------------------------
-	 *
-	 * Functions to get or add new identities.
-	 */
-
-	/**
-	 * Add an identity.
-	 *
-	 * @param identity the identity
-	 * @note If the identity already exists, it is overriden
-	 */
-	inline void addIdentity(ServerIdentity identity) noexcept
-	{
-		m_identities.emplace(identity.name, std::move(identity));
-	}
-
-	/**
-	 * Get an identity, if not found, the default one is used.
-	 *
-	 * @param name the identity name
-	 * @return the identity or default one
-	 */
-	inline ServerIdentity findIdentity(const std::string &name) const noexcept
-	{
-		auto it = m_identities.find(name);
-
-		return it == m_identities.end() ? ServerIdentity() : it->second;
-	}
-
-	/*
-	 * Server management
-	 * ----------------------------------------------------------
-	 *
-	 * Functions to get or create new servers.
-	 *
-	 * Servers that are added to this instance are automatically polled when run() is called.
-	 */
-
-	/**
-	 * Check if a server exists.
-	 *
-	 * @param name the name
-	 * @return true if exists
-	 */
-	inline bool hasServer(const std::string &name) const noexcept
-	{
-		return m_servers.count(name) > 0;
-	}
-
-	/**
-	 * Add a new server to the application.
-	 *
-	 * @pre hasServer must return false
-	 * @param sv the server
-	 */
-	void addServer(std::shared_ptr<Server> sv) noexcept;
-
-	/**
-	 * Get a server or empty one if not found
-	 *
-	 * @param name the server name
-	 * @return the server or empty one if not found
-	 */
-	std::shared_ptr<Server> getServer(const std::string &name) const noexcept;
-
-	/**
-	 * Find a server by name.
-	 *
-	 * @param name the server name
-	 * @return the server
-	 * @throw std::out_of_range if the server does not exist
-	 */
-	std::shared_ptr<Server> requireServer(const std::string &name) const;
-
-	/**
-	 * Get the map of loaded servers.
-	 *
-	 * @return the servers
-	 */
-	inline const Servers &servers() const noexcept
-	{
-		return m_servers;
-	}
-
-	/**
-	 * Remove a server from the irccd instance.
-	 *
-	 * The server if any, will be disconnected.
-	 *
-	 * @param name the server name
-	 */
-	void removeServer(const std::string &name);
-
-	/**
-	 * Remove all servers.
-	 *
-	 * All servers will be disconnected.
-	 */
-	void clearServers() noexcept;
-
-	/*
-	 * Transport management
-	 * ----------------------------------------------------------
-	 *
-	 * Functions for adding new transport servers.
-	 */
-
-	/**
-	 * Add a transport server.
-	 *
-	 * @param ts the transport server
-	 */
-	void addTransport(std::shared_ptr<TransportServer> ts);
-
-	/*
-	 * Plugin management
-	 * ----------------------------------------------------------
-	 *
-	 * Functions for loading JavaScript plugins.
-	 */
-
-#if defined(WITH_JS)
-	/**
-	 * Check if a plugin is loaded.
-	 *
-	 * @param name the plugin id
-	 * @return true if has plugin
-	 */
-	inline bool hasPlugin(const std::string &name) const noexcept
-	{
-		return m_plugins.count(name) > 0;
-	}
-
-	/**
-	 * Get a plugin or empty one if not found.
-	 *
-	 * @param name the plugin id
-	 * @return the plugin or empty one if not found
-	 */
-	std::shared_ptr<Plugin> getPlugin(const std::string &name) const noexcept;
-
-	/**
-	 * Find a plugin.
-	 *
-	 * @param name the plugin id
-	 * @return the plugin
-	 * @throws std::out_of_range if not found
-	 */
-	std::shared_ptr<Plugin> requirePlugin(const std::string &name) const;
-
-	/**
-	 * Add plugin configuration for the specified plugin.
-	 *
-	 * @param name
-	 * @param config
-	 */
-	inline void addPluginConfig(std::string name, PluginConfig config)
-	{
-		m_pluginConf.emplace(std::move(name), std::move(config));
-	}
-
-	/**
-	 * Add a loaded plugin.
-	 *
-	 * Plugins signals will be connected to the irccd main loop. The onLoad function will also be called and the
-	 * plugin is not added on errors.
-	 *
-	 * @pre plugin must not be empty
-	 * @param plugin the plugin
-	 */
-	void addPlugin(std::shared_ptr<Plugin> plugin);
-
-	/**
-	 * Load a plugin by path or by searching through directories.
-	 *
-	 * TODO: Move this somewhere else (e.g. Plugin::find).
-	 *
-	 * @param source the path or the plugin id to search
-	 * @param find set to true for searching by id
-	 */
-	void loadPlugin(std::string name, const std::string &source, bool find);
-
-	/**
-	 * Unload a plugin and remove it.
-	 *
-	 * @param name the plugin id
-	 */
-	void unloadPlugin(const std::string &name);
-
-	/**
-	 * Reload a plugin by calling onReload.
-	 *
-	 * @param name the plugin name
-	 * @throw std::exception on failures
-	 */
-	void reloadPlugin(const std::string &name);
-
-	/**
-	 * Get the map of plugins.
-	 *
-	 * @return the map of plugins
-	 */
-	inline const Plugins &plugins() const noexcept
-	{
-		return m_plugins;
-	}
-
-#endif // !WITH_JS
-
-	/*
-	 * Rule management
-	 * ----------------------------------------------------------
-	 *
-	 * Functions for adding, creating new rules that are used to filter IRC events before being processed
-	 * by JavaScript plugins.
-	 */
-
-	/**
-	 * Append a rule.
-	 *
-	 * @param rule the rule to append
-	 */
-	inline void addRule(Rule rule)
-	{
-		m_rules.push_back(std::move(rule));
-	}
-
-	/**
-	 * Insert a new rule at the specified position.
-	 *
-	 * @param rule the rule
-	 * @param position the position
-	 */
-	inline void insertRule(Rule rule, unsigned position)
-	{
-		assert(position <= m_rules.size());
-
-		m_rules.insert(m_rules.begin() + position, std::move(rule));
-	}
-
-	/**
-	 * Get the list of rules.
-	 *
-	 * @return the list of rules
-	 */
-	inline const std::vector<Rule> &rules() const noexcept
-	{
-		return m_rules;
-	}
-
-	/**
-	 * Remove a new rule from the specified position.
-	 *
-	 * @pre position must be valid
-	 * @param position the position
-	 */
-	inline void removeRule(unsigned position)
-	{
-		assert(position < m_rules.size());
-
-		m_rules.erase(m_rules.begin() + position);
-	}
-
-	/**
-	 * Loop forever by calling poll() and dispatch() indefinitely.
-	 */
-	void run();
-
-	/**
-	 * Poll the next events without blocking (250 ms max).
-	 */
-	void poll();
-
-	/**
-	 * Dispatch the pending events, usually after calling poll().
-	 */
-	void dispatch();
-
-	/**
-	 * Request to stop, usually from a signal.
-	 */
-	void stop();
-};
-
-} // !irccd
-
-#endif // !IRCCD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/irccd.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,543 @@
+/*
+ * irccd.hpp -- main irccd class
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_HPP
+#define IRCCD_HPP
+
+/**
+ * @file irccd.hpp
+ * @brief Base class for irccd front end.
+ */
+
+#include <atomic>
+#include <cassert>
+#include <condition_variable>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <irccd/sysconfig.hpp>
+
+#include "sockets.hpp"
+
+#if defined(WITH_JS)
+#  include "plugin.hpp"
+#endif
+
+#include "application.hpp"
+#include "logger.hpp"
+#include "rule.hpp"
+#include "server.hpp"
+#include "transport-server.hpp"
+
+namespace irccd {
+
+class Plugin;
+class TransportCommand;
+
+/**
+ * Event to execute after the poll.
+ */
+using Event = std::function<void ()>;
+
+/**
+ * List of events.
+ */
+using Events = std::vector<Event>;
+
+/**
+ * Map of identities.
+ */
+using Identities = std::unordered_map<std::string, ServerIdentity>;
+
+/**
+ * List of rules.
+ */
+using Rules = std::vector<Rule>;
+
+/**
+ * @class ServerEvent
+ * @brief Structure that owns several informations about an IRC event
+ *
+ * This structure is used to dispatch the IRC event to the plugins and the transports.
+ */
+class ServerEvent {
+public:
+	std::string server;					//!< the server
+	std::string origin;					//!< the originator
+	std::string target;					//!< the target
+	std::string json;					//!< the JSON message
+#if defined(WITH_JS)
+	std::function<std::string (Plugin &)> name;		//!< the function to event name
+	std::function<void (Plugin &)> exec;			//!< the plugin function to call
+#endif
+};
+
+/**
+ * Map of servers.
+ */
+using Servers = std::unordered_map<std::string, std::shared_ptr<Server>>;
+
+/**
+ * Map of transport command handlers.
+ */
+using TransportCommands = std::unordered_map<std::string, std::unique_ptr<TransportCommand>>;
+
+#if defined(WITH_JS)
+
+/**
+ * Map of plugins.
+ */
+using Plugins = std::unordered_map<std::string, std::shared_ptr<Plugin>>;
+
+/**
+ * Map of plugin configurations.
+ */
+using PluginConfigs = std::unordered_map<std::string, PluginConfig>;
+
+#endif
+
+/**
+ * @class Irccd
+ * @brief Irccd main instance
+ *
+ * This class is used as the main application event loop, it stores servers, plugins and transports.
+ *
+ * In a general manner, no code in irccd is thread-safe because irccd is mono-threaded except the JavaScript timer
+ * API.
+ *
+ * If you plan to add more threads to irccd, then the simpliest and safest way to execute thread-safe code is to
+ * register an event using Irccd::post function which will be called during the event loop dispatching.
+ *
+ * Thus, except noticed as thread-safe, no function is assumed to be.
+ */
+class Irccd : public Application {
+private:
+	template <typename T>
+	using LookupTable = std::unordered_map<net::Handle, std::shared_ptr<T>>;
+
+	/* Main loop */
+	std::atomic<bool> m_running{true};
+
+	/* Mutex for post() */
+	std::mutex m_mutex;
+
+	/* IPC */
+	net::SocketTcp<net::address::Ip> m_socketServer;
+	net::SocketTcp<net::address::Ip> m_socketClient;
+
+	/* Event loop */
+	Events m_events;
+
+	/* Servers */
+	Servers m_servers;
+
+	/* Optional JavaScript plugins */
+#if defined(WITH_JS)
+	Plugins m_plugins;
+	PluginConfigs m_pluginConf;
+#endif
+
+	/* Identities */
+	Identities m_identities;
+
+	/* Rules */
+	Rules m_rules;
+
+	/* Lookup tables */
+	LookupTable<TransportClient> m_lookupTransportClients;
+	LookupTable<TransportServer> m_lookupTransportServers;
+
+	/*
+	 * Server slots
+	 * ----------------------------------------------------------
+	 */
+
+	void handleServerChannelMode(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string mode, std::string arg);
+	void handleServerChannelNotice(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string notice);
+	void handleServerConnect(std::weak_ptr<Server> server);
+	void handleServerInvite(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string target);
+	void handleServerJoin(std::weak_ptr<Server> server, std::string origin, std::string channel);
+	void handleServerKick(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string target, std::string reason);
+	void handleServerMessage(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string message);
+	void handleServerMe(std::weak_ptr<Server> server, std::string origin, std::string target, std::string message);
+	void handleServerMode(std::weak_ptr<Server> server, std::string origin, std::string mode);
+	void handleServerNames(std::weak_ptr<Server> server, std::string channel, std::set<std::string> nicknames);
+	void handleServerNick(std::weak_ptr<Server> server, std::string origin, std::string nickname);
+	void handleServerNotice(std::weak_ptr<Server> server, std::string origin, std::string message);
+	void handleServerPart(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string reason);
+	void handleServerQuery(std::weak_ptr<Server> server, std::string origin, std::string message);
+	void handleServerTopic(std::weak_ptr<Server> server, std::string origin, std::string channel, std::string topic);
+	void handleServerWhois(std::weak_ptr<Server> server, ServerWhois whois);
+
+	/*
+	 * Transport clients slots
+	 * ----------------------------------------------------------
+	 */
+	void handleTransportCommand(std::weak_ptr<TransportClient>, const json::Value &);
+	void handleTransportDie(std::weak_ptr<TransportClient>);
+
+	/*
+	 * Plugin timers slots
+	 * ----------------------------------------------------------
+	 *
+	 * These handlers catch the timer signals and call the plugin function or remove the timer from the plugin.
+	 */
+
+#if defined(WITH_JS)
+	void handleTimerSignal(std::weak_ptr<Plugin>, std::shared_ptr<Timer>);
+	void handleTimerEnd(std::weak_ptr<Plugin>, std::shared_ptr<Timer>);
+#endif
+
+	/*
+	 * Process the socket sets.
+	 * ----------------------------------------------------------
+	 *
+	 * These functions are called after polling which sockets are ready for reading/writing.
+	 */
+
+	void processIpc(fd_set &input);
+	void processTransportClients(fd_set &input, fd_set &output);
+	void processTransportServers(fd_set &input);
+	void processServers(fd_set &input, fd_set &output);
+	void process(fd_set &setinput, fd_set &setoutput);
+
+public:
+	/**
+	 * Constructor that instanciate IPC.
+	 */
+	Irccd();
+
+	/**
+	 * Load a configuration into irccd. Added as convenience to allow expressions like `irccd.load(Config{"foo"})`.
+	 *
+	 * @param config the configuration loader
+	 */
+	template <typename T>
+	inline void load(T &&config)
+	{
+		config.load(*this);
+	}
+
+	/**
+	 * Add an event to the queue. This will immediately signals the event loop to interrupt itself to dispatch
+	 * the pending events.
+	 *
+	 * @param ev the event
+	 * @note Thread-safe
+	 */
+	void post(Event ev) noexcept;
+
+	/**
+	 * This function wraps post() to iterate over all plugins to call the function and to send to all
+	 * connected transport the event.
+	 *
+	 * @param ev the event
+	 */
+	void postServerEvent(ServerEvent ev) noexcept;
+
+	/*
+	 * Identity management
+	 * ----------------------------------------------------------
+	 *
+	 * Functions to get or add new identities.
+	 */
+
+	/**
+	 * Add an identity.
+	 *
+	 * @param identity the identity
+	 * @note If the identity already exists, it is overriden
+	 */
+	inline void addIdentity(ServerIdentity identity) noexcept
+	{
+		m_identities.emplace(identity.name, std::move(identity));
+	}
+
+	/**
+	 * Get an identity, if not found, the default one is used.
+	 *
+	 * @param name the identity name
+	 * @return the identity or default one
+	 */
+	inline ServerIdentity findIdentity(const std::string &name) const noexcept
+	{
+		auto it = m_identities.find(name);
+
+		return it == m_identities.end() ? ServerIdentity() : it->second;
+	}
+
+	/*
+	 * Server management
+	 * ----------------------------------------------------------
+	 *
+	 * Functions to get or create new servers.
+	 *
+	 * Servers that are added to this instance are automatically polled when run() is called.
+	 */
+
+	/**
+	 * Check if a server exists.
+	 *
+	 * @param name the name
+	 * @return true if exists
+	 */
+	inline bool hasServer(const std::string &name) const noexcept
+	{
+		return m_servers.count(name) > 0;
+	}
+
+	/**
+	 * Add a new server to the application.
+	 *
+	 * @pre hasServer must return false
+	 * @param sv the server
+	 */
+	void addServer(std::shared_ptr<Server> sv) noexcept;
+
+	/**
+	 * Get a server or empty one if not found
+	 *
+	 * @param name the server name
+	 * @return the server or empty one if not found
+	 */
+	std::shared_ptr<Server> getServer(const std::string &name) const noexcept;
+
+	/**
+	 * Find a server by name.
+	 *
+	 * @param name the server name
+	 * @return the server
+	 * @throw std::out_of_range if the server does not exist
+	 */
+	std::shared_ptr<Server> requireServer(const std::string &name) const;
+
+	/**
+	 * Get the map of loaded servers.
+	 *
+	 * @return the servers
+	 */
+	inline const Servers &servers() const noexcept
+	{
+		return m_servers;
+	}
+
+	/**
+	 * Remove a server from the irccd instance.
+	 *
+	 * The server if any, will be disconnected.
+	 *
+	 * @param name the server name
+	 */
+	void removeServer(const std::string &name);
+
+	/**
+	 * Remove all servers.
+	 *
+	 * All servers will be disconnected.
+	 */
+	void clearServers() noexcept;
+
+	/*
+	 * Transport management
+	 * ----------------------------------------------------------
+	 *
+	 * Functions for adding new transport servers.
+	 */
+
+	/**
+	 * Add a transport server.
+	 *
+	 * @param ts the transport server
+	 */
+	void addTransport(std::shared_ptr<TransportServer> ts);
+
+	/*
+	 * Plugin management
+	 * ----------------------------------------------------------
+	 *
+	 * Functions for loading JavaScript plugins.
+	 */
+
+#if defined(WITH_JS)
+	/**
+	 * Check if a plugin is loaded.
+	 *
+	 * @param name the plugin id
+	 * @return true if has plugin
+	 */
+	inline bool hasPlugin(const std::string &name) const noexcept
+	{
+		return m_plugins.count(name) > 0;
+	}
+
+	/**
+	 * Get a plugin or empty one if not found.
+	 *
+	 * @param name the plugin id
+	 * @return the plugin or empty one if not found
+	 */
+	std::shared_ptr<Plugin> getPlugin(const std::string &name) const noexcept;
+
+	/**
+	 * Find a plugin.
+	 *
+	 * @param name the plugin id
+	 * @return the plugin
+	 * @throws std::out_of_range if not found
+	 */
+	std::shared_ptr<Plugin> requirePlugin(const std::string &name) const;
+
+	/**
+	 * Add plugin configuration for the specified plugin.
+	 *
+	 * @param name
+	 * @param config
+	 */
+	inline void addPluginConfig(std::string name, PluginConfig config)
+	{
+		m_pluginConf.emplace(std::move(name), std::move(config));
+	}
+
+	/**
+	 * Add a loaded plugin.
+	 *
+	 * Plugins signals will be connected to the irccd main loop. The onLoad function will also be called and the
+	 * plugin is not added on errors.
+	 *
+	 * @pre plugin must not be empty
+	 * @param plugin the plugin
+	 */
+	void addPlugin(std::shared_ptr<Plugin> plugin);
+
+	/**
+	 * Load a plugin by path or by searching through directories.
+	 *
+	 * TODO: Move this somewhere else (e.g. Plugin::find).
+	 *
+	 * @param source the path or the plugin id to search
+	 * @param find set to true for searching by id
+	 */
+	void loadPlugin(std::string name, const std::string &source, bool find);
+
+	/**
+	 * Unload a plugin and remove it.
+	 *
+	 * @param name the plugin id
+	 */
+	void unloadPlugin(const std::string &name);
+
+	/**
+	 * Reload a plugin by calling onReload.
+	 *
+	 * @param name the plugin name
+	 * @throw std::exception on failures
+	 */
+	void reloadPlugin(const std::string &name);
+
+	/**
+	 * Get the map of plugins.
+	 *
+	 * @return the map of plugins
+	 */
+	inline const Plugins &plugins() const noexcept
+	{
+		return m_plugins;
+	}
+
+#endif // !WITH_JS
+
+	/*
+	 * Rule management
+	 * ----------------------------------------------------------
+	 *
+	 * Functions for adding, creating new rules that are used to filter IRC events before being processed
+	 * by JavaScript plugins.
+	 */
+
+	/**
+	 * Append a rule.
+	 *
+	 * @param rule the rule to append
+	 */
+	inline void addRule(Rule rule)
+	{
+		m_rules.push_back(std::move(rule));
+	}
+
+	/**
+	 * Insert a new rule at the specified position.
+	 *
+	 * @param rule the rule
+	 * @param position the position
+	 */
+	inline void insertRule(Rule rule, unsigned position)
+	{
+		assert(position <= m_rules.size());
+
+		m_rules.insert(m_rules.begin() + position, std::move(rule));
+	}
+
+	/**
+	 * Get the list of rules.
+	 *
+	 * @return the list of rules
+	 */
+	inline const std::vector<Rule> &rules() const noexcept
+	{
+		return m_rules;
+	}
+
+	/**
+	 * Remove a new rule from the specified position.
+	 *
+	 * @pre position must be valid
+	 * @param position the position
+	 */
+	inline void removeRule(unsigned position)
+	{
+		assert(position < m_rules.size());
+
+		m_rules.erase(m_rules.begin() + position);
+	}
+
+	/**
+	 * Loop forever by calling poll() and dispatch() indefinitely.
+	 */
+	void run();
+
+	/**
+	 * Poll the next events without blocking (250 ms max).
+	 */
+	void poll();
+
+	/**
+	 * Dispatch the pending events, usually after calling poll().
+	 */
+	void dispatch();
+
+	/**
+	 * Request to stop, usually from a signal.
+	 */
+	void stop();
+};
+
+} // !irccd
+
+#endif // !IRCCD_HPP
--- a/lib/irccd/irccdctl.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/irccdctl.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -23,19 +23,19 @@
 #include <string>
 #include <unordered_map>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "elapsed-timer.h"
-#include "fs.h"
-#include "ini.h"
-#include "irccdctl.h"
-#include "json.h"
-#include "logger.h"
-#include "options.h"
-#include "path.h"
-#include "sockets.h"
-#include "system.h"
-#include "util.h"
+#include "elapsed-timer.hpp"
+#include "fs.hpp"
+#include "ini.hpp"
+#include "irccdctl.hpp"
+#include "json.hpp"
+#include "logger.hpp"
+#include "options.hpp"
+#include "path.hpp"
+#include "sockets.hpp"
+#include "system.hpp"
+#include "util.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/irccdctl.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * irccdctl.h -- main irccdctl class
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_IRCCDCTL_H
-#define IRCCD_IRCCDCTL_H
-
-/**
- * @file irccdctl.h
- * @brief Base class for irccdctl front end.
- */
-
-#include <cassert>
-#include <map>
-#include <memory>
-#include <string>
-
-#include "alias.h"
-#include "application.h"
-#include "connection.h"
-#include "options.h"
-
-namespace irccd {
-
-class Command;
-
-namespace ini {
-
-class Section;
-
-} // !ini
-
-/**
- * @brief Main irccdctl class.
- */
-class Irccdctl : public Application {
-private:
-	/* Irccd's information */
-	unsigned short m_major{0};
-	unsigned short m_minor{0};
-	unsigned short m_patch{0};
-
-	/* Irccd's compilation option */
-	bool m_javascript{true};
-	bool m_ssl{true};
-
-	std::unique_ptr<Connection> m_connection;
-	std::unordered_map<std::string, Alias> m_aliases;
-
-	void usage() const;
-
-	void readConnectIp(const ini::Section &sc);
-	void readConnectUnix(const ini::Section &sc);
-	void readConnect(const ini::Section &sc);
-	void readGeneral(const ini::Section &sc);
-	void readAliases(const ini::Section &sc);
-	void read(const std::string &path, const parser::Result &options);
-
-	void parseConnectIp(const parser::Result &options, bool ipv6);
-	void parseConnectUnix(const parser::Result &options);
-	void parseConnect(const parser::Result &options);
-	parser::Result parse(int &argc, char **&argv) const;
-
-	void connect();
-
-public:
-	/**
-	 * Execute the given command and wait for its result.
-	 *
-	 * @param cmd the command
-	 * @param args the arguments
-	 */
-	void exec(const RemoteCommand &cmd, std::vector<std::string> args);
-
-	/**
-	 * Execute the given alias.
-	 *
-	 * @param alias the alias
-	 * @param args the arguments
-	 */
-	void exec(const Alias &alias, std::vector<std::string> args);
-
-	/**
-	 * Resolve the command line arguments.
-	 *
-	 * @param args the main arguments
-	 */
-	void exec(std::vector<std::string> args);
-
-	/**
-	 * Get the connection.
-	 *
-	 * @return the connection
-	 */
-	inline Connection &connection() noexcept
-	{
-		return *m_connection;
-	}
-
-	/**
-	 * Run the irccdctl front end.
-	 *
-	 * @param argc the number of arguments
-	 * @param argv the arguments
-	 */
-	void run(int argc, char **argv);
-};
-
-} // !irccd
-
-#endif // !IRCCD_IRCCDCTL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/irccdctl.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,125 @@
+/*
+ * irccdctl.hpp -- main irccdctl class
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_IRCCDCTL_HPP
+#define IRCCD_IRCCDCTL_HPP
+
+/**
+ * @file irccdctl.hpp
+ * @brief Base class for irccdctl front end.
+ */
+
+#include <cassert>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "alias.hpp"
+#include "application.hpp"
+#include "connection.hpp"
+#include "options.hpp"
+
+namespace irccd {
+
+class Command;
+
+namespace ini {
+
+class Section;
+
+} // !ini
+
+/**
+ * @brief Main irccdctl class.
+ */
+class Irccdctl : public Application {
+private:
+	/* Irccd's information */
+	unsigned short m_major{0};
+	unsigned short m_minor{0};
+	unsigned short m_patch{0};
+
+	/* Irccd's compilation option */
+	bool m_javascript{true};
+	bool m_ssl{true};
+
+	std::unique_ptr<Connection> m_connection;
+	std::unordered_map<std::string, Alias> m_aliases;
+
+	void usage() const;
+
+	void readConnectIp(const ini::Section &sc);
+	void readConnectUnix(const ini::Section &sc);
+	void readConnect(const ini::Section &sc);
+	void readGeneral(const ini::Section &sc);
+	void readAliases(const ini::Section &sc);
+	void read(const std::string &path, const parser::Result &options);
+
+	void parseConnectIp(const parser::Result &options, bool ipv6);
+	void parseConnectUnix(const parser::Result &options);
+	void parseConnect(const parser::Result &options);
+	parser::Result parse(int &argc, char **&argv) const;
+
+	void connect();
+
+public:
+	/**
+	 * Execute the given command and wait for its result.
+	 *
+	 * @param cmd the command
+	 * @param args the arguments
+	 */
+	void exec(const RemoteCommand &cmd, std::vector<std::string> args);
+
+	/**
+	 * Execute the given alias.
+	 *
+	 * @param alias the alias
+	 * @param args the arguments
+	 */
+	void exec(const Alias &alias, std::vector<std::string> args);
+
+	/**
+	 * Resolve the command line arguments.
+	 *
+	 * @param args the main arguments
+	 */
+	void exec(std::vector<std::string> args);
+
+	/**
+	 * Get the connection.
+	 *
+	 * @return the connection
+	 */
+	inline Connection &connection() noexcept
+	{
+		return *m_connection;
+	}
+
+	/**
+	 * Run the irccdctl front end.
+	 *
+	 * @param argc the number of arguments
+	 * @param argv the arguments
+	 */
+	void run(int argc, char **argv);
+};
+
+} // !irccd
+
+#endif // !IRCCD_IRCCDCTL_HPP
--- a/lib/irccd/js-directory.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-directory.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -24,12 +24,12 @@
 #include <stdexcept>
 #include <string>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "fs.h"
-#include "js.h"
-#include "js-irccd.h"
-#include "path.h"
+#include "fs.hpp"
+#include "js.hpp"
+#include "js-irccd.hpp"
+#include "path.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-directory.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * js-directory.h -- Irccd.Directory API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_DIRECTORY_H
-#define IRCCD_JS_DIRECTORY_H
-
-/**
- * @file js-directory.h
- * @brief Irccd.Directory JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsDirectory(duk::ContextPtr ctx) noexcept;
-
-} // !irccd
-
-#endif // !IRCCD_JS_DIRECTORY_H
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-directory.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,41 @@
+/*
+ * js-directory.hpp -- Irccd.Directory API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_DIRECTORY_HPP
+#define IRCCD_JS_DIRECTORY_HPP
+
+/**
+ * @file js-directory.hpp
+ * @brief Irccd.Directory JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsDirectory(duk::ContextPtr ctx) noexcept;
+
+} // !irccd
+
+#endif // !IRCCD_JS_DIRECTORY_HPP
+
--- a/lib/irccd/js-elapsed-timer.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-elapsed-timer.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "elapsed-timer.h"
-#include "js.h"
+#include "elapsed-timer.hpp"
+#include "js.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-elapsed-timer.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * js-elapsed-timer.h -- Irccd.ElapsedTimer API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_ELAPSED_TIMER_H
-#define IRCCD_JS_ELAPSED_TIMER_H
-
-/**
- * @file js-elapsed-timer.h
- * @brief Irccd.ElapsedTimer JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsElapsedTimer(duk::ContextPtr ctx) noexcept;
-
-} // !irccd
-
-#endif // !IRCCD_JS_ELAPSED_TIMER_H
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-elapsed-timer.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,41 @@
+/*
+ * js-elapsed-timer.hpp -- Irccd.ElapsedTimer API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_ELAPSED_TIMER_HPP
+#define IRCCD_JS_ELAPSED_TIMER_HPP
+
+/**
+ * @file js-elapsed-timer.hpp
+ * @brief Irccd.ElapsedTimer JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsElapsedTimer(duk::ContextPtr ctx) noexcept;
+
+} // !irccd
+
+#endif // !IRCCD_JS_ELAPSED_TIMER_HPP
+
--- a/lib/irccd/js-file.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-file.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -21,16 +21,16 @@
 #include <iterator>
 #include <vector>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if defined(HAVE_STAT)
 #  include <sys/types.h>
 #  include <sys/stat.h>
 #endif
 
-#include "fs.h"
-#include "js-irccd.h"
-#include "js-file.h"
+#include "fs.hpp"
+#include "js-irccd.hpp"
+#include "js-file.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-file.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * js-file.h -- Irccd.File API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_FILE_H
-#define IRCCD_JS_FILE_H
-
-/**
- * @file js-file.h
- * @brief Irccd.File JavaScript API.
- */
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <functional>
-#include <stdexcept>
-#include <string>
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * @class File
- * @brief Object for Javascript to perform I/O.
- *
- * This class can be constructed to Javascript.
- *
- * It is used in:
- *
- * - Irccd.File [constructor]
- * - Irccd.System.popen (optional)
- */
-class File {
-private:
-	File(const File &) = delete;
-	File &operator=(const File &) = delete;
-
-	File(File &&) = delete;
-	File &operator=(File &&) = delete;
-
-private:
-	std::string m_path;
-	std::FILE *m_stream;
-	std::function<void (std::FILE *)> m_destructor;
-
-public:
-	/**
-	 * Construct a file specified by path
-	 *
-	 * @param path the path
-	 * @param mode the mode string (for std::fopen)
-	 * @throw std::runtime_error on failures
-	 */
-	inline File(std::string path, const std::string &mode)
-		: m_path(std::move(path))
-		, m_destructor([] (std::FILE *fp) { std::fclose(fp); })
-	{
-		if ((m_stream = std::fopen(m_path.c_str(), mode.c_str())) == nullptr)
-			throw std::runtime_error(std::strerror(errno));
-	}
-
-	/**
-	 * Construct a file from a already created FILE pointer (e.g. popen).
-	 *
-	 * The class takes ownership of fp and will close it.
-	 *
-	 * @pre destructor must not be null
-	 * @param fp the file pointer
-	 * @param destructor the function to close fp (e.g. std::fclose)
-	 */
-	inline File(std::FILE *fp, std::function<void (std::FILE *)> destructor) noexcept
-		: m_stream(fp)
-		, m_destructor(std::move(destructor))
-	{
-		assert(m_destructor != nullptr);
-	}
-
-	/**
-	 * Closes the file.
-	 */
-	virtual ~File() noexcept
-	{
-		close();
-	}
-
-	/**
-	 * Get the path.
-	 *
-	 * @return the path
-	 * @warning empty when constructed from the FILE constructor
-	 */
-	inline const std::string &path() const noexcept
-	{
-		return m_path;
-	}
-
-	/**
-	 * Get the handle.
-	 *
-	 * @return the handle or nullptr if the stream was closed
-	 */
-	inline std::FILE *handle() noexcept
-	{
-		return m_stream;
-	}
-
-	/**
-	 * Force close, can be safely called multiple times.
-	 */
-	inline void close() noexcept
-	{
-		if (m_stream) {
-			m_destructor(m_stream);
-			m_stream = nullptr;
-		}
-	}
-};
-
-namespace duk {
-
-/**
- * @brief JavaScript binding for File.
- */
-template <>
-class TypeTraits<File> {
-public:
-	/**
-	 * Push the File prototype.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void prototype(ContextPtr ctx)
-	{
-		getGlobal<void>(ctx, "Irccd");
-		getGlobal<void>(ctx, "File");
-		getProperty<void>(ctx, -1, "prototype");
-		remove(ctx, -2);
-		remove(ctx, -2);
-	}
-
-	/**
-	 * Get the File signature.
-	 *
-	 * @return File
-	 */
-	static inline std::string name()
-	{
-		return "\xff""\xff""File";
-	}
-
-	/**
-	 * Get the inheritance list.
-	 *
-	 * @return empty
-	 */
-	static inline std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsFile(duk::ContextPtr ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_FILE_H
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-file.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,191 @@
+/*
+ * js-file.hpp -- Irccd.File API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_FILE_HPP
+#define IRCCD_JS_FILE_HPP
+
+/**
+ * @file js-file.hpp
+ * @brief Irccd.File JavaScript API.
+ */
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <functional>
+#include <stdexcept>
+#include <string>
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * @class File
+ * @brief Object for Javascript to perform I/O.
+ *
+ * This class can be constructed to Javascript.
+ *
+ * It is used in:
+ *
+ * - Irccd.File [constructor]
+ * - Irccd.System.popen (optional)
+ */
+class File {
+private:
+	File(const File &) = delete;
+	File &operator=(const File &) = delete;
+
+	File(File &&) = delete;
+	File &operator=(File &&) = delete;
+
+private:
+	std::string m_path;
+	std::FILE *m_stream;
+	std::function<void (std::FILE *)> m_destructor;
+
+public:
+	/**
+	 * Construct a file specified by path
+	 *
+	 * @param path the path
+	 * @param mode the mode string (for std::fopen)
+	 * @throw std::runtime_error on failures
+	 */
+	inline File(std::string path, const std::string &mode)
+		: m_path(std::move(path))
+		, m_destructor([] (std::FILE *fp) { std::fclose(fp); })
+	{
+		if ((m_stream = std::fopen(m_path.c_str(), mode.c_str())) == nullptr)
+			throw std::runtime_error(std::strerror(errno));
+	}
+
+	/**
+	 * Construct a file from a already created FILE pointer (e.g. popen).
+	 *
+	 * The class takes ownership of fp and will close it.
+	 *
+	 * @pre destructor must not be null
+	 * @param fp the file pointer
+	 * @param destructor the function to close fp (e.g. std::fclose)
+	 */
+	inline File(std::FILE *fp, std::function<void (std::FILE *)> destructor) noexcept
+		: m_stream(fp)
+		, m_destructor(std::move(destructor))
+	{
+		assert(m_destructor != nullptr);
+	}
+
+	/**
+	 * Closes the file.
+	 */
+	virtual ~File() noexcept
+	{
+		close();
+	}
+
+	/**
+	 * Get the path.
+	 *
+	 * @return the path
+	 * @warning empty when constructed from the FILE constructor
+	 */
+	inline const std::string &path() const noexcept
+	{
+		return m_path;
+	}
+
+	/**
+	 * Get the handle.
+	 *
+	 * @return the handle or nullptr if the stream was closed
+	 */
+	inline std::FILE *handle() noexcept
+	{
+		return m_stream;
+	}
+
+	/**
+	 * Force close, can be safely called multiple times.
+	 */
+	inline void close() noexcept
+	{
+		if (m_stream) {
+			m_destructor(m_stream);
+			m_stream = nullptr;
+		}
+	}
+};
+
+namespace duk {
+
+/**
+ * @brief JavaScript binding for File.
+ */
+template <>
+class TypeTraits<File> {
+public:
+	/**
+	 * Push the File prototype.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void prototype(ContextPtr ctx)
+	{
+		getGlobal<void>(ctx, "Irccd");
+		getGlobal<void>(ctx, "File");
+		getProperty<void>(ctx, -1, "prototype");
+		remove(ctx, -2);
+		remove(ctx, -2);
+	}
+
+	/**
+	 * Get the File signature.
+	 *
+	 * @return File
+	 */
+	static inline std::string name()
+	{
+		return "\xff""\xff""File";
+	}
+
+	/**
+	 * Get the inheritance list.
+	 *
+	 * @return empty
+	 */
+	static inline std::vector<std::string> inherits()
+	{
+		return {};
+	}
+};
+
+} // !duk
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsFile(duk::ContextPtr ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_FILE_HPP
+
--- a/lib/irccd/js-irccd.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-irccd.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,9 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "js-irccd.h"
+#include "js-irccd.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-irccd.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * js-irccd.h -- Irccd API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_IRCCD_H
-#define IRCCD_JS_IRCCD_H
-
-/**
- * @file js-irccd.h
- * @brief Irccd.Irccd JavaScript API.
- */
-
-#include <cerrno>
-#include <cstring>
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * @brief Custom JavaScript exception for system error.
- */
-class SystemError {
-private:
-	int m_errno;
-	std::string m_message;
-
-public:
-	/**
-	 * Create a system error from the current errno value.
-	 */
-	SystemError();
-
-	/**
-	 * Create a system error with the given errno and message.
-	 *
-	 * @param e the errno number
-	 * @param message the message
-	 */
-	SystemError(int e, std::string message);
-
-	/**
-	 * Raise the SystemError.
-	 *
-	 * @param ctx the context
-	 */
-	void raise(duk::ContextPtr ctx) const;
-};
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsIrccd(duk::Context &ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_IRCCD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-irccd.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,73 @@
+/*
+ * js-irccd.hpp -- Irccd API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_IRCCD_HPP
+#define IRCCD_JS_IRCCD_HPP
+
+/**
+ * @file js-irccd.hpp
+ * @brief Irccd.Irccd JavaScript API.
+ */
+
+#include <cerrno>
+#include <cstring>
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * @brief Custom JavaScript exception for system error.
+ */
+class SystemError {
+private:
+	int m_errno;
+	std::string m_message;
+
+public:
+	/**
+	 * Create a system error from the current errno value.
+	 */
+	SystemError();
+
+	/**
+	 * Create a system error with the given errno and message.
+	 *
+	 * @param e the errno number
+	 * @param message the message
+	 */
+	SystemError(int e, std::string message);
+
+	/**
+	 * Raise the SystemError.
+	 *
+	 * @param ctx the context
+	 */
+	void raise(duk::ContextPtr ctx) const;
+};
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsIrccd(duk::Context &ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_IRCCD_HPP
--- a/lib/irccd/js-logger.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-logger.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "js-logger.h"
-#include "logger.h"
+#include "js-logger.hpp"
+#include "logger.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-logger.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * js-logger.h -- Irccd.Logger API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_LOGGER_H
-#define IRCCD_JS_LOGGER_H
-
-/**
- * @file js-logger.h
- * @brief Irccd.Logger JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsLogger(duk::ContextPtr ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_LOGGER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-logger.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,40 @@
+/*
+ * js-logger.hpp -- Irccd.Logger API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_LOGGER_HPP
+#define IRCCD_JS_LOGGER_HPP
+
+/**
+ * @file js-logger.hpp
+ * @brief Irccd.Logger JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsLogger(duk::ContextPtr ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_LOGGER_HPP
--- a/lib/irccd/js-plugin.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-plugin.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "irccd.h"
-#include "js-plugin.h"
+#include "irccd.hpp"
+#include "js-plugin.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-plugin.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * js-plugin.h -- Irccd.Plugin API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_PLUGIN_H
-#define IRCCD_JS_PLUGIN_H
-
-/**
- * @file js-plugin.h
- * @brief Irccd.Plugin JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsPlugin(duk::Context &ctx) noexcept;
-
-} // !irccd
-
-#endif // !IRCCD_JS_PLUGIN_H
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-plugin.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,41 @@
+/*
+ * js-plugin.hpp -- Irccd.Plugin API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_PLUGIN_HPP
+#define IRCCD_JS_PLUGIN_HPP
+
+/**
+ * @file js-plugin.hpp
+ * @brief Irccd.Plugin JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsPlugin(duk::Context &ctx) noexcept;
+
+} // !irccd
+
+#endif // !IRCCD_JS_PLUGIN_HPP
+
--- a/lib/irccd/js-server.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-server.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -19,9 +19,9 @@
 #include <sstream>
 #include <unordered_map>
 
-#include "irccd.h"
-#include "js-server.h"
-#include "server.h"
+#include "irccd.hpp"
+#include "js-server.hpp"
+#include "server.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-server.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * js-server.h -- Irccd.Server API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_SERVER_H
-#define IRCCD_JS_SERVER_H
-
-/**
- * @file js-server.h
- * @brief Irccd.Server JavaScript API.
- */
-
-#include <irccd/server.h>
-
-#include "js.h"
-
-namespace irccd {
-
-namespace duk {
-
-/**
- * @brief JavaScript binding for Server.
- */
-template <>
-class TypeTraits<irccd::Server> {
-public:
-	/**
-	 * Push the Server prototype.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void prototype(ContextPtr ctx)
-	{
-		getGlobal<void>(ctx, "Irccd");
-		getProperty<void>(ctx, -1, "Server");
-		getProperty<void>(ctx, -1, "prototype");
-		remove(ctx, -2);
-		remove(ctx, -2);
-	}
-
-	/**
-	 * Get the Server signature.
-	 *
-	 * @return Server
-	 */
-	static inline std::string name()
-	{
-		return "\xff""\xff""Server";
-	}
-
-	/**
-	 * Get the inheritance list.
-	 *
-	 * @return empty
-	 */
-	static inline std::vector<std::string> inherits()
-	{
-		return {};
-	}
-};
-
-} // !duk
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsServer(duk::ContextPtr ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_SERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-server.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,87 @@
+/*
+ * js-server.hpp -- Irccd.Server API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_SERVER_HPP
+#define IRCCD_JS_SERVER_HPP
+
+/**
+ * @file js-server.hpp
+ * @brief Irccd.Server JavaScript API.
+ */
+
+#include <irccd/server.hpp>
+
+#include "js.hpp"
+
+namespace irccd {
+
+namespace duk {
+
+/**
+ * @brief JavaScript binding for Server.
+ */
+template <>
+class TypeTraits<irccd::Server> {
+public:
+	/**
+	 * Push the Server prototype.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void prototype(ContextPtr ctx)
+	{
+		getGlobal<void>(ctx, "Irccd");
+		getProperty<void>(ctx, -1, "Server");
+		getProperty<void>(ctx, -1, "prototype");
+		remove(ctx, -2);
+		remove(ctx, -2);
+	}
+
+	/**
+	 * Get the Server signature.
+	 *
+	 * @return Server
+	 */
+	static inline std::string name()
+	{
+		return "\xff""\xff""Server";
+	}
+
+	/**
+	 * Get the inheritance list.
+	 *
+	 * @return empty
+	 */
+	static inline std::vector<std::string> inherits()
+	{
+		return {};
+	}
+};
+
+} // !duk
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsServer(duk::ContextPtr ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_SERVER_HPP
--- a/lib/irccd/js-system.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-system.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #include <chrono>
 
@@ -27,10 +27,10 @@
 #include <cstdlib>
 #include <thread>
 
-#include "js-file.h"
-#include "js-irccd.h"
-#include "js-system.h"
-#include "system.h"
+#include "js-file.hpp"
+#include "js-irccd.hpp"
+#include "js-system.hpp"
+#include "system.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-system.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * js-system.h -- Irccd.System API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_SYSTEM_H
-#define IRCCD_JS_SYSTEM_H
-
-/**
- * @file js-system.h
- * @brief Irccd.System JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsSystem(duk::ContextPtr ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_SYSTEM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-system.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,40 @@
+/*
+ * js-system.hpp -- Irccd.System API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_SYSTEM_HPP
+#define IRCCD_JS_SYSTEM_HPP
+
+/**
+ * @file js-system.hpp
+ * @brief Irccd.System JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsSystem(duk::ContextPtr ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_SYSTEM_HPP
--- a/lib/irccd/js-timer.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-timer.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -19,8 +19,8 @@
 #include <cassert>
 #include <cstdint>
 
-#include "js.h"
-#include "plugin.h"
+#include "js.hpp"
+#include "plugin.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-timer.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * js-timer.h -- Irccd.Timer API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_TIMER_H
-#define IRCCD_JS_TIMER_H
-
-/**
- * @file js-timer.h
- * @brief Irccd.Timer JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsTimer(duk::ContextPtr ctx) noexcept;
-
-} // !irccd
-
-#endif // !IRCCD_JS_TIMER_H
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-timer.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,41 @@
+/*
+ * js-timer.hpp -- Irccd.Timer API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_TIMER_HPP
+#define IRCCD_JS_TIMER_HPP
+
+/**
+ * @file js-timer.hpp
+ * @brief Irccd.Timer JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsTimer(duk::ContextPtr ctx) noexcept;
+
+} // !irccd
+
+#endif // !IRCCD_JS_TIMER_HPP
+
--- a/lib/irccd/js-unicode.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-unicode.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "js.h"
-#include "unicode.h"
+#include "js.hpp"
+#include "unicode.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-unicode.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * js-unicode.cpp -- Irccd.Unicode API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_UNICODE_H
-#define IRCCD_JS_UNICODE_H
-
-/**
- * @file js-unicode.h
- * @brief Irccd.Unicode JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsUnicode(duk::ContextPtr ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_UNICODE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-unicode.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,40 @@
+/*
+ * js-unicode.cpp -- Irccd.Unicode API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_UNICODE_HPP
+#define IRCCD_JS_UNICODE_HPP
+
+/**
+ * @file js-unicode.hpp
+ * @brief Irccd.Unicode JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsUnicode(duk::ContextPtr ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_UNICODE_HPP
--- a/lib/irccd/js-util.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/js-util.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,8 +18,8 @@
 
 #include <libircclient.h>
 
-#include "js-util.h"
-#include "util.h"
+#include "js-util.hpp"
+#include "util.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/js-util.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * js-util.h -- Irccd.Util API
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_UTIL_H
-#define IRCCD_JS_UTIL_H
-
-/**
- * @file js-util.h
- * @brief Irccd.Util JavaScript API.
- */
-
-#include "js.h"
-
-namespace irccd {
-
-/**
- * Load the module.
- *
- * @param ctx the context.
- */
-void loadJsUtil(duk::ContextPtr ctx);
-
-} // !irccd
-
-#endif // !IRCCD_JS_UTIL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js-util.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,40 @@
+/*
+ * js-util.hpp -- Irccd.Util API
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_UTIL_HPP
+#define IRCCD_JS_UTIL_HPP
+
+/**
+ * @file js-util.hpp
+ * @brief Irccd.Util JavaScript API.
+ */
+
+#include "js.hpp"
+
+namespace irccd {
+
+/**
+ * Load the module.
+ *
+ * @param ctx the context.
+ */
+void loadJsUtil(duk::ContextPtr ctx);
+
+} // !irccd
+
+#endif // !IRCCD_JS_UTIL_HPP
--- a/lib/irccd/js.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2381 +0,0 @@
-/*
- * js.h -- JavaScript C++14 wrapper for Duktape
- *
- * Copyright (c) 2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JS_H
-#define IRCCD_JS_H
-
-/**
- * @file js.h
- * @brief Bring JavaScript using Duktape.
- *
- * This file provides usual Duktape function renamed and placed into `duk` namespace. It also replaces error
- * code with exceptions when possible.
- *
- * For convenience, this file also provides templated functions, overloads and much more.
- */
-
-#include <cassert>
-#include <functional>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <duktape.h>
-
-namespace irccd {
-
-/**
- * Duktape C++ namespace wrapper.
- */
-namespace duk {
-
-class Context;
-
-using CodePoint = duk_codepoint_t;
-using ContextPtr = duk_context *;
-using Index = duk_idx_t;
-using Ret = duk_ret_t;
-using Size = duk_size_t;
-
-/**
- * @class StackAssert
- * @brief Stack sanity checker.
- *
- * Instanciate this class where you need to manipulate the Duktape stack outside a Duktape/C function, its destructor
- * will examinate if the stack size matches the user expected size.
- *
- * When compiled with NDEBUG, this class does nothing.
- *
- * To use it, just declare an lvalue at the beginning of your function.
- */
-class StackAssert {
-#if !defined(NDEBUG)
-private:
-	ContextPtr m_context;
-	unsigned m_expected;
-	unsigned m_begin;
-#endif
-
-public:
-	/**
-	 * Create the stack checker.
-	 *
-	 * No-op if NDEBUG is set.
-	 *
-	 * @param ctx the context
-	 * @param expected the size expected relative to the already existing values
-	 */
-	inline StackAssert(ContextPtr ctx, unsigned expected = 0) noexcept
-#if !defined(NDEBUG)
-		: m_context(ctx)
-		, m_expected(expected)
-		, m_begin(static_cast<unsigned>(duk_get_top(ctx)))
-#endif
-	{
-#if defined(NDEBUG)
-		(void)ctx;
-		(void)expected;
-#endif
-	}
-
-	/**
-	 * Verify the expected size.
-	 *
-	 * No-op if NDEBUG is set.
-	 */
-	inline ~StackAssert() noexcept
-	{
-#if !defined(NDEBUG)
-		assert((unsigned)duk_get_top(m_context) - m_begin == m_expected);
-#endif
-	}
-};
-
-/**
- * @class Object
- * @brief Empty class tag for push() function.
- */
-class Object {
-};
-
-/**
- * @class Array
- * @brief Empty class tag for push() function.
- */
-class Array {
-};
-
-/**
- * @class Global
- * @brief Empty class tag to push the global object.
- */
-class Global {
-};
-
-/**
- * @class Undefined
- * @brief Empty class tag to push undefined to the stack.
- */
-class Undefined {
-};
-
-/**
- * @class Null
- * @brief Empty class tag to push null to the stack.
- */
-class Null {
-};
-
-/**
- * @class This
- * @brief Empty class tag to push this binding to the stack.
- */
-class This {
-};
-
-/**
- * @class RawPointer
- * @brief Push a non-managed pointer to Duktape, the pointer will never be deleted.
- * @note For a managed pointer with prototype, see Pointer
- */
-template <typename T>
-class RawPointer {
-public:
-	/**
-	 * The pointer to push.
-	 */
-	T *object;
-};
-
-/**
- * @brief Manage shared_ptr from C++ and JavaScript
- *
- * This class allowed you to push and retrieve shared_ptr from C++ and JavaScript without taking care of ownership
- * and deletion.
- *
- */
-template <typename T>
-class Shared {
-public:
-	/**
-	 * The shared object.
-	 */
-	std::shared_ptr<T> object;
-};
-
-/**
- * @brief Manage pointers from C++ and JavaScript
- *
- * This class allowed you to push and retrieve C++ pointers from C++ and JavaScript. The object will be deleted when
- * the JavaScript garbage collectors collect them so never store a pointer created with this.
- *
- * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
- */
-template <typename T>
-class Pointer {
-public:
-	/**
-	 * The object.
-	 */
-	T *object{nullptr};
-};
-
-/**
- * @class Function
- * @brief Duktape/C function definition.
- *
- * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
- */
-class Function {
-public:
-	/**
-	 * The function pointer, must not be null.
-	 */
-	duk_c_function function;
-
-	/**
-	 * Number of args that the function takes
-	 */
-	duk_idx_t nargs{0};
-};
-
-/**
- * Map of functions to set on an object.
- */
-using FunctionMap = std::unordered_map<std::string, Function>;
-
-/**
- * Map of string to type, ideal for setting constants like enums.
- */
-template <typename Type>
-using Map = std::unordered_map<std::string, Type>;
-
-/**
- * @class ErrorInfo
- * @brief Error description.
- *
- * This class fills the fields got in an Error object.
- */
-class ErrorInfo : public std::exception {
-public:
-	std::string name;		//!< name of error
-	std::string message;		//!< error message
-	std::string stack;		//!< stack if available
-	std::string fileName;		//!< filename if applicable
-	int lineNumber{0};		//!< line number if applicable
-
-	/**
-	 * Get the error message. This effectively returns message field.
-	 *
-	 * @return the message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * @class TypeTraits
- * @brief Type information to implement new types in JavaScript's context.
- *
- * This class depending on your needs may have the following functions:
- *
- * - `static void construct(Context &ctx, Type value)`
- * - `static Type get(Context &ctx, int index)`
- * - `static bool is(Context &ctx, int index)`
- * - `static Type optional(Context &ctx, int index, Type defaultValue)`
- * - `static void push(Context &ctx, Type value)`
- * - `static Type require(Context &ctx, int index)`
- *
- * The `construct` function is used in Context::construct to build a new value as this (e.g. constructors).
- *
- * The `get` function is used in Context::get, Context::getProperty, Context::getGlobal to retrieve a value from the
- * stack.
- *
- * The `is` function is used in Context::is to check if the value on the stack is of type `Type`.
- *
- * The `optional` function is used in Context::optional to get a value or a replacement if not applicable.
- *
- * The `push` function is used in Context::push to usually create a new value on the stack but some specializations
- * may not (e.g. FunctionMap).
- *
- * The `require` function is used in Context::require to get a value from the stack or raise a JavaScript exception if
- * not applicable.
- *
- * This class is fully specialized for: `bool`, `const char *`, `double`, `int`, `std::string`.
- *
- * It is also partially specialized for : `Global`, `Object`, `Array`, `Undefined`, `Null`, `std::vector<Type>`.
- */
-template <typename Type>
-class TypeTraits {
-};
-
-/**
- * @class Context
- * @brief RAII based Duktape handler.
- *
- * This class is implicitly convertible to duk_context for convenience.
- */
-class Context {
-private:
-	using Deleter = void (*)(duk_context *);
-	using Handle = std::unique_ptr<duk_context, Deleter>;
-
-	Handle m_handle;
-
-	Context(const Context &) = delete;
-	Context &operator=(const Context &) = delete;
-	Context(const Context &&) = delete;
-	Context &operator=(const Context &&) = delete;
-
-public:
-	/**
-	 * Create default context.
-	 */
-	inline Context()
-		: m_handle(duk_create_heap_default(), duk_destroy_heap)
-	{
-	}
-
-	/**
-	 * Convert the context to the native Duktape/C type.
-	 *
-	 * @return the duk_context
-	 */
-	inline operator duk_context *() noexcept
-	{
-		return m_handle.get();
-	}
-
-	/**
-	 * Convert the context to the native Duktape/C type.
-	 *
-	 * @return the duk_context
-	 */
-	inline operator duk_context *() const noexcept
-	{
-		return m_handle.get();
-	}
-};
-
-/**
- * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
- *
- * @param ctx the context
- * @param index the index
- * @return the information
- */
-inline ErrorInfo error(ContextPtr ctx, int index)
-{
-	ErrorInfo error;
-
-	index = duk_normalize_index(ctx, index);
-
-	duk_get_prop_string(ctx, index, "name");
-	error.name = duk_to_string(ctx, -1);
-	duk_get_prop_string(ctx, index, "message");
-	error.message = duk_to_string(ctx, -1);
-	duk_get_prop_string(ctx, index, "fileName");
-	error.fileName = duk_to_string(ctx, -1);
-	duk_get_prop_string(ctx, index, "lineNumber");
-	error.lineNumber = duk_to_int(ctx, -1);
-	duk_get_prop_string(ctx, index, "stack");
-	error.stack = duk_to_string(ctx, -1);
-	duk_pop_n(ctx, 5);
-
-	return error;
-}
-
-/**
- * Wrapper for [duk_base64_decode](http://duktape.org/api.html#duk_base64_decode).
- *
- * @param ctx the context
- * @param index the index
- */
-inline void base64Decode(ContextPtr ctx, Index index)
-{
-	duk_base64_decode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_base64_encode](http://duktape.org/api.html#duk_base64_encode).
- *
- * @param ctx the context
- * @param index the index
- */
-inline void base64Encode(ContextPtr ctx, Index index)
-{
-	duk_base64_encode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_call](http://duktape.org/api.html#duk_call).
- *
- * @param ctx the context
- * @param nargs the number of arguments
- */
-inline void call(ContextPtr ctx, Index nargs = 0)
-{
-	duk_call(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_call_method](http://duktape.org/api.html#duk_call_method).
- *
- * @param ctx the context
- * @param nargs the number of arguments
- */
-inline void callMethod(ContextPtr ctx, Index nargs = 0)
-{
-	duk_call_method(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_call_prop](http://duktape.org/api.html#duk_call_prop).
- *
- * @param ctx the context
- * @param index the object index
- * @param nargs the number of arguments
- */
-inline void callProperty(ContextPtr ctx, Index index, Index nargs = 0)
-{
-	duk_call_prop(ctx, index, nargs);
-}
-
-/**
- * Wrapper for [duk_char_code_at](http://duktape.org/api.html#duk_char_code_at).
- *
- * @param ctx the context
- * @param index the index
- * @param charOffset the offset
- */
-inline CodePoint charCodeAt(ContextPtr ctx, Index index, Size charOffset)
-{
-	return duk_char_code_at(ctx, index, charOffset);
-}
-
-/**
- * Wrapper for [duk_check_stack](http://duktape.org/api.html#duk_check_stack).
- *
- * @param ctx the context
- * @param extra the extra space
- * @return true if space is available
- */
-inline bool checkStack(ContextPtr ctx, Index extra)
-{
-	return duk_check_stack(ctx, extra);
-}
-
-/**
- * Wrapper for [duk_check_stack_top](http://duktape.org/api.html#duk_check_stack_top).
- *
- * @param ctx the context
- * @param top the extra space
- * @return true if space is available
- */
-inline bool checkStackTop(ContextPtr ctx, Index top)
-{
-	return duk_check_stack_top(ctx, top);
-}
-
-/**
- * Wrapper for [duk_check_type](http://duktape.org/api.html#duk_check_type).
- *
- * @param ctx the context
- * @param index the value index
- * @param type the desired type
- * @return true if object is given type
- */
-inline bool checkType(ContextPtr ctx, Index index, int type)
-{
-	return duk_check_type(ctx, index, type);
-}
-
-/**
- * Wrapper for [duk_check_type_mask](http://duktape.org/api.html#duk_check_type_mask).
- *
- * @param ctx the context
- * @param index the value index
- * @param mask the desired mask
- * @return true if object is one of the type
- */
-inline bool checkTypeMask(ContextPtr ctx, Index index, unsigned mask)
-{
-	return duk_check_type_mask(ctx, index, mask);
-}
-
-/**
- * Wrapper for [duk_compact](http://duktape.org/api.html#duk_compact).
- *
- * @param ctx the context
- * @param objIndex the object index
- */
-inline void compact(ContextPtr ctx, Index objIndex)
-{
-	duk_compact(ctx, objIndex);
-}
-
-/**
- * Wrapper for [duk_concat](http://duktape.org/api.html#duk_concat).
- *
- * @param ctx the context
- * @param count the number of values
- */
-inline void concat(ContextPtr ctx, Index count)
-{
-	duk_concat(ctx, count);
-}
-
-/**
- * Wrapper for [duk_copy](http://duktape.org/api.html#duk_copy).
- *
- * @param from the from index
- * @param to the destination
- */
-inline void copy(ContextPtr ctx, Index from, Index to)
-{
-	duk_copy(ctx, from, to);
-}
-
-/**
- * Wrapper for [duk_def_prop](http://duktape.org/api.html#duk_def_prop).
- *
- * @param index the object index
- * @param flags the flags
- */
-inline void defineProperty(ContextPtr ctx, Index index, unsigned flags)
-{
-	duk_def_prop(ctx, index, flags);
-}
-
-/**
- * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
- *
- * @param index the object index
- * @return true if deleted
- */
-inline bool deleteProperty(ContextPtr ctx, Index index)
-{
-	return duk_del_prop(ctx, index);
-}
-
-/**
- * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
- *
- * @param index the object index
- * @param position the property index
- * @return true if deleted
- */
-inline bool deleteProperty(ContextPtr ctx, Index index, unsigned position)
-{
-	return duk_del_prop_index(ctx, index, position);
-}
-
-/**
- * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
- *
- * @param index the object index
- * @param name the property name
- * @return true if deleted
- */
-inline bool deleteProperty(ContextPtr ctx, Index index, const std::string &name)
-{
-	return duk_del_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Wrapper for [duk_dup](http://duktape.org/api.html#duk_dup).
- *
- * @param index the value to copy
- */
-inline void dup(ContextPtr ctx, int index = -1)
-{
-	duk_dup(ctx, index);
-}
-
-/**
- * Wrapper for [duk_equals](http://duktape.org/api.html#duk_equals).
- *
- * @param ctx the context
- * @param index1 the first value
- * @param index2 the second value
- * @return true if they equal
- */
-inline bool equals(ContextPtr ctx, Index index1, Index index2)
-{
-	return duk_equals(ctx, index1, index2);
-}
-
-/**
- * Wrapper for [duk_eval](http://duktape.org/api.html#duk_eval).
- *
- * @param ctx the context
- */
-inline void eval(ContextPtr ctx)
-{
-	duk_eval(ctx);
-}
-
-/**
- * Wrapper for [duk_eval_file](http://duktape.org/api.html#duk_eval_file).
- *
- * @param ctx the context
- * @param path the path
- * @param result true to get the result at the top of the stack
- */
-inline void evalFile(ContextPtr ctx, const std::string &path, bool result = true)
-{
-	if (result)
-		duk_eval_file(ctx, path.c_str());
-	else
-		duk_eval_file_noresult(ctx, path.c_str());
-}
-
-/**
- * Wrapper for [duk_eval_string](http://duktape.org/api.html#duk_eval_string).
- *
- * @param ctx the context
- * @param src the source script
- * @param result true to get the result at the top of the stack
- */
-inline void evalString(ContextPtr ctx, const std::string &src, bool result = true)
-{
-	if (result)
-		duk_eval_string(ctx, src.c_str());
-	else
-		duk_eval_string_noresult(ctx, src.c_str());
-}
-/**
- * Wrapper for [duk_gc](http://duktape.org/api.html#duk_gc).
- *
- * @param ctx the context
- * @param flags the flags
- */
-inline void gc(ContextPtr ctx, unsigned flags = 0)
-{
-	duk_gc(ctx, flags);
-}
-
-/**
- * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
- *
- * @param ctx the context
- * @param index the object index
- * @return true if has
- */
-inline bool hasProperty(ContextPtr ctx, Index index)
-{
-	return duk_has_prop(ctx, index);
-}
-
-/**
- * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
- *
- * @param ctx the context
- * @param index the object index
- * @param position the property index
- * @return true if has
- */
-inline bool hasProperty(ContextPtr ctx, Index index, unsigned position)
-{
-	return duk_has_prop_index(ctx, index, position);
-}
-
-/**
- * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
- *
- * @param ctx the context
- * @param index the object index
- * @param name the property name
- * @return true if has
- */
-inline bool hasProperty(ContextPtr ctx, int index, const std::string &name)
-{
-	return duk_has_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Wrapper for [duk_insert](http://duktape.org/api.html#duk_insert).
- *
- * @param ctx the context
- * @param to the destination
- * @note Wrapper of duk_insert
- */
-inline void insert(ContextPtr ctx, Index to)
-{
-	duk_insert(ctx, to);
-}
-
-/**
- * Wrapper for [duk_instanceof](http://duktape.org/api.html#duk_instanceof).
- *
- * @param ctx the context
- * @param idx1 the value to test
- * @param idx2 the instance requested
- * @return true if idx1 is instance of idx2
- */
-inline bool instanceof(ContextPtr ctx, Index idx1, Index idx2)
-{
-	return duk_instanceof(ctx, idx1, idx2);
-}
-
-/**
- * Wrapper for [duk_join](http://duktape.org/api.html#duk_join).
- *
- * @param ctx the context
- * @param count the number of values
- */
-inline void join(ContextPtr ctx, Index count)
-{
-	duk_join(ctx, count);
-}
-
-/**
- * Wrapper for [duk_json_decode](http://duktape.org/api.html#duk_json_decode).
- *
- * @param ctx the context
- * @param index the index
- */
-inline void jsonDecode(ContextPtr ctx, Index index)
-{
-	duk_json_decode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_json_encode](http://duktape.org/api.html#duk_json_encode).
- *
- * @param ctx the context
- * @param index the index
- */
-inline void jsonEncode(ContextPtr ctx, Index index)
-{
-	duk_json_encode(ctx, index);
-}
-
-/**
- * Wrapper for [duk_normalize_index](http://duktape.org/api.html#duk_normalize_index).
- *
- * @param ctx the context
- * @param index the index
- */
-inline Index normalizeIndex(ContextPtr ctx, Index index)
-{
-	return duk_normalize_index(ctx, index);
-}
-
-/**
- * Wrapper for [duk_pcall](http://duktape.org/api.html#duk_pcall).
- *
- * @param ctx the context
- * @param nargs the number of arguments
- */
-inline int pcall(ContextPtr ctx, Index nargs = 0)
-{
-	return duk_pcall(ctx, nargs);
-}
-
-/**
- * Wrapper for [duk_peval](http://duktape.org/api.html#duk_peval).
- *
- * @param ctx the context
- */
-inline int peval(ContextPtr ctx)
-{
-	return duk_peval(ctx);
-}
-
-/**
- * Wrapper for [duk_peval_file](http://duktape.org/api.html#duk_peval_file).
- *
- * @param ctx the context
- * @param path the path
- * @param result true to get the result at the top of the stack
- */
-inline int pevalFile(ContextPtr ctx, const std::string &path, bool result = true)
-{
-	return result ? duk_peval_file(ctx, path.c_str()) : duk_peval_file_noresult(ctx, path.c_str());
-}
-
-/**
- * Wrapper for [duk_peval_string](http://duktape.org/api.html#duk_peval_string).
- *
- * @param ctx the context
- * @param src the source script
- * @param result true to get the result at the top of the stack
- */
-inline int pevalString(ContextPtr ctx, const std::string &src, bool result = true)
-{
-	return result ? duk_peval_string(ctx, src.c_str()) : duk_peval_string_noresult(ctx, src.c_str());
-}
-
-/**
- * Wrapper for [duk_pop_n](http://duktape.org/api.html#duk_pop_n).
- *
- * @param ctx the context
- * @param count the number of values to pop
- */
-inline void pop(ContextPtr ctx, Index count = 1)
-{
-	duk_pop_n(ctx, count);
-}
-
-/**
- * Wrapper for [duk_remove](http://duktape.org/api.html#duk_remove).
- *
- * @param ctx the context
- * @param index the value to remove
- */
-inline void remove(ContextPtr ctx, Index index)
-{
-	duk_remove(ctx, index);
-}
-
-/**
- * Wrapper for [duk_replace](http://duktape.org/api.html#duk_replace).
- *
- * @param ctx the context
- * @param index the value to replace by the value at the top of the stack
- */
-inline void replace(ContextPtr ctx, Index index)
-{
-	duk_replace(ctx, index);
-}
-
-/**
- * Wrapper for [duk_set_prototype](http://duktape.org/api.html#duk_set_prototype).
- *
- * @param ctx the context
- * @param index the value index
- */
-inline void setPrototype(ContextPtr ctx, Index index)
-{
-	duk_set_prototype(ctx, index);
-}
-
-/**
- * Wrapper for [duk_swap](http://duktape.org/api.html#duk_swap).
- *
- * @param ctx the context
- * @param index1 the first index
- * @param index2 the second index
- */
-inline void swap(ContextPtr ctx, Index index1, Index index2)
-{
-	duk_swap(ctx, index1, index2);
-}
-
-/**
- * Wrapper for [duk_swap_top](http://duktape.org/api.html#duk_swap_top).
- *
- * @param ctx the context
- * @param index the index
- */
-inline void swapTop(ContextPtr ctx, Index index)
-{
-	duk_swap_top(ctx, index);
-}
-
-/**
- * Wrapper for [duk_get_top](http://duktape.org/api.html#duk_get_top).
- *
- * @param ctx the context
- * @return the stack size
- */
-inline int top(ContextPtr ctx) noexcept
-{
-	return duk_get_top(ctx);
-}
-
-/**
- * Wrapper for [duk_get_type](http://duktape.org/api.html#duk_get_type).
- *
- * @param ctx the context
- * @param index the idnex
- * @return the type
- */
-inline int type(ContextPtr ctx, Index index) noexcept
-{
-	return duk_get_type(ctx, index);
-}
-
-/*
- * Push / Get / Require / Is / Optional
- * ----------------------------------------------------------
- *
- * The following functions are used to push, get or check values from the stack. They use specialization
- * of TypeTraits class.
- */
-
-/**
- * Push a value into the stack. Calls TypeTraits<T>::push(*this, value);
- *
- * @param value the value to forward
- */
-template <typename Type>
-inline void push(ContextPtr ctx, Type &&value)
-{
-	TypeTraits<std::decay_t<Type>>::push(ctx, std::forward<Type>(value));
-}
-
-/**
- * Generic template function to get a value from the stack.
- *
- * @param index the index
- * @return the value
- */
-template <typename Type>
-inline auto get(ContextPtr ctx, int index) -> decltype(TypeTraits<Type>::get(ctx, 0))
-{
-	return TypeTraits<Type>::get(ctx, index);
-}
-
-/**
- * Require a type at the specified index.
- *
- * @param index the index
- * @return the value
- */
-template <typename Type>
-inline auto require(ContextPtr ctx, int index) -> decltype(TypeTraits<Type>::require(ctx, 0))
-{
-	return TypeTraits<Type>::require(ctx, index);
-}
-
-/**
- * Check if a value is a type of T.
- *
- * The TypeTraits<T> must have `static bool is(ContextPtr ptr, int index)`.
- *
- * @param index the value index
- * @return true if is the type
- */
-template <typename T>
-inline bool is(ContextPtr ctx, int index)
-{
-	return TypeTraits<T>::is(ctx, index);
-}
-
-/**
- * Get an optional value from the stack, if the value is not available of not the correct type,
- * return defaultValue instead.
- *
- * The TypeTraits<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
- *
- * @param index the value index
- * @param defaultValue the value replacement
- * @return the value or defaultValue
- */
-template <typename Type>
-inline auto optional(ContextPtr ctx, int index, Type &&defaultValue)
-{
-	return TypeTraits<std::decay_t<Type>>::optional(ctx, index, std::forward<Type>(defaultValue));
-}
-
-/*
- * Properties management
- * ----------------------------------------------------------
- *
- * The following functions are used to read or set properties on objects or globals also using TypeTraits.
- */
-
-/**
- * Get the property `name' as value from the object at the specified index.
- *
- * @param index the object index
- * @param name the property name
- * @return the value
- * @note The stack is unchanged
- */
-template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-inline auto getProperty(ContextPtr ctx, int index, const std::string &name) -> decltype(get<Type>(ctx, 0))
-{
-	duk_get_prop_string(ctx, index, name.c_str());
-	decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
-	duk_pop(ctx);
-
-	return value;
-}
-
-/**
- * Get a property by index, for arrays.
- *
- * @param index the object index
- * @param position the position int the object
- * @return the value
- * @note The stack is unchanged
- */
-template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
-inline auto getProperty(ContextPtr ctx, int index, int position) -> decltype(get<Type>(ctx, 0))
-{
-	duk_get_prop_index(ctx, index, position);
-	decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
-	duk_pop(ctx);
-
-	return value;
-}
-
-/**
- * Get the property `name' and push it to the stack from the object at the specified index.
- *
- * @param index the object index
- * @param name the property name
- * @note The stack contains the property value
- */
-template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-inline void getProperty(ContextPtr ctx, int index, const std::string &name)
-{
-	duk_get_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Get the property by index and push it to the stack from the object at the specified index.
- *
- * @param index the object index
- * @param position the position in the object
- * @note The stack contains the property value
- */
-template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
-inline void getProperty(ContextPtr ctx, int index, int position)
-{
-	duk_get_prop_index(ctx, index, position);
-}
-
-/**
- * Get an optional property `name` from the object at the specified index.
- *
- * @param index the object index
- * @param name the property name
- * @param def the default value
- * @return the value or def
- * @note The stack is unchanged
- */
-template <typename Type, typename DefaultValue>
-inline auto optionalProperty(ContextPtr ctx, int index, const std::string &name, DefaultValue &&def) -> decltype(optional(ctx, 0, std::forward<DefaultValue>(def)))
-{
-	duk_get_prop_string(ctx, index, name.c_str());
-	decltype(optional(ctx, 0, std::forward<DefaultValue>(def))) value = optional(ctx, -1, std::forward<DefaultValue>(def));
-	duk_pop(ctx);
-
-	return value;
-}
-
-/**
- * Get an optional property by index, for arrays
- *
- * @param index the object index
- * @param position the position int the object
- * @param def the default value
- * @return the value or def
- * @note The stack is unchanged
- */
-template <typename Type, typename DefaultValue>
-inline auto optionalProperty(ContextPtr ctx, int index, int position, DefaultValue &&def) -> decltype(optional(ctx, 0, std::forward<DefaultValue>(def)))
-{
-	duk_get_prop_index(ctx, index, position);
-	decltype(optional(ctx, 0, std::forward<DefaultValue>(def))) value = optional(ctx, -1, std::forward<DefaultValue>(def));
-	duk_pop(ctx);
-
-	return value;
-}
-
-/**
- * Set a property to the object at the specified index.
- *
- * @param index the object index
- * @param name the property name
- * @param value the value to forward
- * @note The stack is unchanged
- */
-template <typename Type>
-void putProperty(ContextPtr ctx, int index, const std::string &name, Type &&value)
-{
-	index = duk_normalize_index(ctx, index);
-
-	push(ctx, std::forward<Type>(value));
-	duk_put_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Set a property by index, for arrays.
- *
- * @param index the object index
- * @param position the position in the object
- * @param value the value to forward
- * @note The stack is unchanged
- */
-template <typename Type>
-void putProperty(ContextPtr ctx, int index, int position, Type &&value)
-{
-	index = duk_normalize_index(ctx, index);
-
-	push(ctx, std::forward<Type>(value));
-	duk_put_prop_index(ctx, index, position);
-}
-
-/**
- * Put the value that is at the top of the stack as property to the object.
- *
- * @param index the object index
- * @param name the property name
- */
-inline void putProperty(ContextPtr ctx, int index, const std::string &name)
-{
-	duk_put_prop_string(ctx, index, name.c_str());
-}
-
-/**
- * Put the value that is at the top of the stack to the object as index.
- *
- * @param index the object index
- * @param position the position in the object
- */
-inline void putProperty(ContextPtr ctx, int index, int position)
-{
-	duk_put_prop_index(ctx, index, position);
-}
-
-/**
- * Get a global value.
- *
- * @param name the name of the global variable
- * @return the value
- */
-template <typename Type>
-inline auto getGlobal(ContextPtr ctx, const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(ctx, 0))
-{
-	duk_get_global_string(ctx, name.c_str());
-	decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
-	duk_pop(ctx);
-
-	return value;
-}
-
-/**
- * Overload that push the value at the top of the stack instead of returning it.
- */
-template <typename Type>
-inline void getGlobal(ContextPtr ctx, const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr) noexcept
-{
-	duk_get_global_string(ctx, name.c_str());
-}
-
-/**
- * Set a global variable.
- *
- * @param name the name of the global variable
- * @param type the value to set
- */
-template <typename Type>
-inline void putGlobal(ContextPtr ctx, const std::string &name, Type&& type)
-{
-	push(ctx, std::forward<Type>(type));
-	duk_put_global_string(ctx, name.c_str());
-}
-
-/**
- * Put the value at the top of the stack as global property.
- *
- * @param name the property name
- */
-inline void putGlobal(ContextPtr ctx, const std::string &name)
-{
-	duk_put_global_string(ctx, name.c_str());
-}
-
-/*
- * Extra functions
- * ----------------------------------------------------------
- *
- * The following functions are implemented for convenience and do not exists in the native Duktape API.
- */
-
-/**
- * Enumerate an object or an array at the specified index.
- *
- * @param index the object or array index
- * @param flags the optional flags to pass to duk_enum
- * @param getvalue set to true if you want to extract the value
- * @param func the function to call for each properties
- */
-template <typename Func>
-void enumerate(ContextPtr ctx, int index, duk_uint_t flags, duk_bool_t getvalue, Func &&func)
-{
-	duk_enum(ctx, index, flags);
-
-	while (duk_next(ctx, -1, getvalue)) {
-		func(ctx);
-		duk_pop_n(ctx, 1 + (getvalue ? 1 : 0));
-	}
-
-	duk_pop(ctx);
-}
-
-/**
- * Return the this binding of the current function.
- *
- * @return the this binding as the template given
- */
-template <typename T>
-inline auto self(ContextPtr ctx) -> decltype(TypeTraits<T>::get(ctx, 0))
-{
-	duk_push_this(ctx);
-	decltype(TypeTraits<T>::get(ctx, 0)) value = TypeTraits<T>::get(ctx, -1);
-	duk_pop(ctx);
-
-	return value;
-}
-
-/**
- * Throw an ECMAScript exception.
- *
- * @param ex the exception
- */
-template <typename Exception>
-void raise(ContextPtr ctx, const Exception &ex)
-{
-	ex.raise(ctx);
-}
-
-/**
- * Wrapper for duk_throw.
- *
- * @param ctx the context
- */
-inline void raise(ContextPtr ctx)
-{
-	duk_throw(ctx);
-}
-
-/**
- * Wrapper for duk_error.
- *
- * @param ctx the context
- * @param type the error type (e.g. DUK_ERR_REFERENCE_ERROR)
- * @param fmt the format string
- * @param args the arguments
- */
-template <typename... Args>
-inline void raise(ContextPtr ctx, int type, const char *fmt, Args&&... args)
-{
-	duk_error(ctx, type, fmt, std::forward<Args>(args)...);
-}
-
-/**
- * Wrapper for duk_new.
- *
- * @param ctx the context
- * @param nargs the number of arguments
- */
-inline void create(ContextPtr ctx, int nargs = 0)
-{
-	duk_new(ctx, nargs);
-}
-
-/**
- * Construct the object in place, setting value as this binding.
- *
- * The TypeTraits<T> must have the following requirements:
- *
- * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
- *
- * @param value the value to forward
- * @see self
- */
-template <typename T>
-inline void construct(ContextPtr ctx, T &&value)
-{
-	TypeTraits<std::decay_t<T>>::construct(ctx, std::forward<T>(value));
-}
-
-/**
- * Sign the given object with the name from T.
- *
- * This is automatically done for when constructing/pushing object with Shared and Pointer helpers, however you need
- * to manually add it when using inheritance.
- */
-template <typename T>
-inline void sign(ContextPtr ctx, Index index)
-{
-	StackAssert sa(ctx, 0);
-
-	index = duk_normalize_index(ctx, index);
-
-	duk_push_string(ctx, TypeTraits<T>::name().c_str());
-	duk_push_boolean(ctx, true);
-	duk_def_prop(ctx, index < 0 ? index : index, DUK_DEFPROP_HAVE_VALUE);
-
-	/* Do for inherited classes */
-	for (const std::string &parent : TypeTraits<T>::inherits()) {
-		duk_push_string(ctx, parent.c_str());
-		duk_push_boolean(ctx, true);
-		duk_def_prop(ctx, index < 0 ? index : index, DUK_DEFPROP_HAVE_VALUE);
-	}
-}
-
-/**
- * Check if the object at the given index is signed by T or raise TypeError if not.
- *
- * @param ctx the context
- * @param index the index
- * @see sign
- */
-template <typename T>
-inline void checkSignature(ContextPtr ctx, Index index)
-{
-	StackAssert sa(ctx, 0);
-
-	if (!is<Object>(ctx, index) || !getProperty<bool>(ctx, index, TypeTraits<T>::name()))
-		raise(ctx, DUK_ERR_TYPE_ERROR, "invalid this binding");
-}
-
-/**
- * Tells if the object at the specified index is of type T.
- *
- * @param ctx the context
- * @param index the index
- */
-template <typename T>
-inline bool isSigned(ContextPtr ctx, Index index)
-{
-	StackAssert sa(ctx, 0);
-
-	return is<Object>(ctx, index) && getProperty<bool>(ctx, index, TypeTraits<T>::name());
-}
-
-/* ------------------------------------------------------------------
- * Exception handling
- * ------------------------------------------------------------------ */
-
-/**
- * @class Error
- * @brief Base ECMAScript error class.
- * @warning Override the function create for your own exceptions
- */
-class Error {
-private:
-	int m_type{DUK_ERR_ERROR};
-	std::string m_message;
-
-protected:
-	/**
-	 * Constructor with a type of error specified, specially designed for derived errors.
-	 *
-	 * @param type of error (e.g. DUK_ERR_ERROR)
-	 * @param message the message
-	 */
-	inline Error(int type, std::string message) noexcept
-		: m_type(type)
-		, m_message(std::move(message))
-	{
-	}
-
-public:
-	/**
-	 * Constructor with a message.
-	 *
-	 * @param message the message
-	 */
-	inline Error(std::string message) noexcept
-		: m_message(std::move(message))
-	{
-	}
-
-	/**
-	 * Create the exception on the stack.
-	 *
-	 * @note the default implementation search for the global variables
-	 * @param ctx the context
-	 */
-	virtual void raise(ContextPtr ctx) const noexcept
-	{
-		duk_error(ctx, m_type, "%s", m_message.c_str());
-	}
-};
-
-/**
- * @class EvalError
- * @brief Error in eval() function.
- */
-class EvalError : public Error {
-public:
-	/**
-	 * Construct an EvalError.
-	 *
-	 * @param message the message
-	 */
-	inline EvalError(std::string message) noexcept
-		: Error(DUK_ERR_EVAL_ERROR, std::move(message))
-	{
-	}
-};
-
-/**
- * @class RangeError
- * @brief Value is out of range.
- */
-class RangeError : public Error {
-public:
-	/**
-	 * Construct an RangeError.
-	 *
-	 * @param message the message
-	 */
-	inline RangeError(std::string message) noexcept
-		: Error(DUK_ERR_RANGE_ERROR, std::move(message))
-	{
-	}
-};
-
-/**
- * @class ReferenceError
- * @brief Trying to use a variable that does not exist.
- */
-class ReferenceError : public Error {
-public:
-	/**
-	 * Construct an ReferenceError.
-	 *
-	 * @param message the message
-	 */
-	inline ReferenceError(std::string message) noexcept
-		: Error(DUK_ERR_REFERENCE_ERROR, std::move(message))
-	{
-	}
-};
-
-/**
- * @class SyntaxError
- * @brief Syntax error in the script.
- */
-class SyntaxError : public Error {
-public:
-	/**
-	 * Construct an SyntaxError.
-	 *
-	 * @param message the message
-	 */
-	inline SyntaxError(std::string message) noexcept
-		: Error(DUK_ERR_SYNTAX_ERROR, std::move(message))
-	{
-	}
-};
-
-/**
- * @class TypeError
- * @brief Invalid type given.
- */
-class TypeError : public Error {
-public:
-	/**
-	 * Construct an TypeError.
-	 *
-	 * @param message the message
-	 */
-	inline TypeError(std::string message) noexcept
-		: Error(DUK_ERR_TYPE_ERROR, std::move(message))
-	{
-	}
-};
-
-/**
- * @class URIError
- * @brief URI manipulation failure.
- */
-class URIError : public Error {
-public:
-	/**
-	 * Construct an URIError.
-	 *
-	 * @param message the message
-	 */
-	inline URIError(std::string message) noexcept
-		: Error(DUK_ERR_URI_ERROR, std::move(message))
-	{
-	}
-};
-
-/* ------------------------------------------------------------------
- * Standard overloads for TypeTraits<T>
- * ------------------------------------------------------------------ */
-
-/**
- * @class TypeTraits<int>
- * @brief Default implementation for int.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<int> {
-public:
-	/**
-	 * Get an integer, return 0 if not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the integer
-	 */
-	static inline int get(ContextPtr ctx, int index)
-	{
-		return duk_get_int(ctx, index);
-	}
-
-	/**
-	 * Check if value is an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if integer
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_number(ctx, index);
-	}
-
-	/**
-	 * Get an integer, return defaultValue if the value is not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the integer or defaultValue
-	 */
-	static inline int optional(ContextPtr ctx, int index, int defaultValue)
-	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue;
-	}
-
-	/**
-	 * Push an integer.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(ContextPtr ctx, int value)
-	{
-		duk_push_int(ctx, value);
-	}
-
-	/**
-	 * Require an integer, throws a JavaScript exception if not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the integer
-	 */
-	static inline int require(ContextPtr ctx, int index)
-	{
-		return duk_require_int(ctx, index);
-	}
-};
-
-/**
- * @class TypeTraits<bool>
- * @brief Default implementation for bool.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<bool> {
-public:
-	/**
-	 * Get a boolean, return 0 if not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the boolean
-	 */
-	static inline bool get(ContextPtr ctx, int index)
-	{
-		return duk_get_boolean(ctx, index);
-	}
-
-	/**
-	 * Check if value is a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if boolean
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_boolean(ctx, index);
-	}
-
-	/**
-	 * Get a bool, return defaultValue if the value is not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the boolean or defaultValue
-	 */
-	static inline bool optional(ContextPtr ctx, int index, bool defaultValue)
-	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue;
-	}
-
-	/**
-	 * Push a boolean.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(ContextPtr ctx, bool value)
-	{
-		duk_push_boolean(ctx, value);
-	}
-
-	/**
-	 * Require a boolean, throws a JavaScript exception if not a boolean.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the boolean
-	 */
-	static inline bool require(ContextPtr ctx, int index)
-	{
-		return duk_require_boolean(ctx, index);
-	}
-};
-
-/**
- * @class TypeTraits<double>
- * @brief Default implementation for double.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<double> {
-public:
-	/**
-	 * Get a double, return 0 if not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the double
-	 */
-	static inline double get(ContextPtr ctx, int index)
-	{
-		return duk_get_number(ctx, index);
-	}
-
-	/**
-	 * Check if value is a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if double
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_number(ctx, index);
-	}
-
-	/**
-	 * Get a double, return defaultValue if the value is not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the double or defaultValue
-	 */
-	static inline double optional(ContextPtr ctx, int index, double defaultValue)
-	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue;
-	}
-
-	/**
-	 * Push a double.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(ContextPtr ctx, double value)
-	{
-		duk_push_number(ctx, value);
-	}
-
-	/**
-	 * Require a double, throws a JavaScript exception if not a double.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the double
-	 */
-	static inline double require(ContextPtr ctx, int index)
-	{
-		return duk_require_number(ctx, index);
-	}
-};
-
-/**
- * @class TypeTraits<std::string>
- * @brief Default implementation for std::string.
- *
- * Provides: get, is, optional, push, require.
- *
- * Note: the functions allows embedded '\0'.
- */
-template <>
-class TypeTraits<std::string> {
-public:
-	/**
-	 * Get a string, return 0 if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline std::string get(ContextPtr ctx, int index)
-	{
-		duk_size_t size;
-		const char *text = duk_get_lstring(ctx, index, &size);
-
-		return std::string{text, size};
-	}
-
-	/**
-	 * Check if value is a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if string
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_string(ctx, index);
-	}
-
-	/**
-	 * Get a string, return defaultValue if the value is not an string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the string or defaultValue
-	 */
-	static inline std::string optional(ContextPtr ctx, int index, std::string defaultValue)
-	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue;
-	}
-
-	/**
-	 * Push a string.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(ContextPtr ctx, const std::string &value)
-	{
-		duk_push_lstring(ctx, value.c_str(), value.length());
-	}
-
-	/**
-	 * Require a string, throws a JavaScript exception if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline std::string require(ContextPtr ctx, int index)
-	{
-		duk_size_t size;
-		const char *text = duk_require_lstring(ctx, index, &size);
-
-		return std::string{text, size};
-	}
-};
-
-/**
- * @class TypeTraits<const char *>
- * @brief Default implementation for const char literals.
- *
- * Provides: get, is, optional, push, require.
- */
-template <>
-class TypeTraits<const char *> {
-public:
-	/**
-	 * Get a string, return 0 if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline const char *get(ContextPtr ctx, int index)
-	{
-		return duk_get_string(ctx, index);
-	}
-
-	/**
-	 * Check if value is a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if string
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_string(ctx, index);
-	}
-
-	/**
-	 * Get an integer, return defaultValue if the value is not an integer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the integer or defaultValue
-	 */
-	static inline const char *optional(ContextPtr ctx, int index, const char *defaultValue)
-	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue;
-	}
-
-	/**
-	 * Push a string.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(ContextPtr ctx, const char *value)
-	{
-		duk_push_string(ctx, value);
-	}
-
-	/**
-	 * Require a string, throws a JavaScript exception if not a string.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the string
-	 */
-	static inline const char *require(ContextPtr ctx, int index)
-	{
-		return duk_require_string(ctx, index);
-	}
-};
-
-/**
- * @brief Implementation for non-managed pointers.
- *
- * Provides: get, is, optional, push, require.
- */
-template <typename T>
-class TypeTraits<RawPointer<T>> {
-public:
-	/**
-	 * Get a pointer, return nullptr if not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the pointer
-	 */
-	static inline T *get(ContextPtr ctx, int index)
-	{
-		return static_cast<T *>(duk_to_pointer(ctx, index));
-	}
-
-	/**
-	 * Check if value is a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if pointer
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_pointer(ctx, index);
-	}
-
-	/**
-	 * Get a pointer, return defaultValue if the value is not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @param defaultValue the defaultValue
-	 * @return the pointer or defaultValue
-	 */
-	static inline T *optional(ContextPtr ctx, int index, RawPointer<T> defaultValue)
-	{
-		return is(ctx, index) ? get(ctx, index) : defaultValue.object;
-	}
-
-	/**
-	 * Push a pointer.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static inline void push(ContextPtr ctx, const RawPointer<T> &value)
-	{
-		duk_push_pointer(ctx, value.object);
-	}
-
-	/**
-	 * Require a pointer, throws a JavaScript exception if not a pointer.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return the pointer
-	 */
-	static inline T *require(ContextPtr ctx, int index)
-	{
-		return static_cast<T *>(duk_require_pointer(ctx, index));
-	}
-};
-
-/**
- * @class TypeTraits<Function>
- * @brief Push C++ function to the stack.
- *
- * Provides: push.
- *
- * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
- */
-template <>
-class TypeTraits<Function> {
-public:
-	/**
-	 * Check if the value at the given index is callable.
-	 *
-	 * @param ctx the context
-	 * @param index the value index
-	 * @return true if the value is callable
-	 */
-	static bool is(ContextPtr ctx, Index index)
-	{
-		return duk_is_callable(ctx, index);
-	}
-
-	/**
-	 * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
-	 * std::function.
-	 *
-	 * @param ctx the context
-	 * @param fn the function
-	 */
-	static void push(ContextPtr ctx, Function fn)
-	{
-		duk_push_c_function(ctx, fn.function, fn.nargs);
-	}
-};
-
-/**
- * @class TypeTraits<FunctionMap>
- * @brief Put the functions to the object at the top of the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeTraits<FunctionMap> {
-public:
-	/**
-	 * Push all functions to the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param map the map of function
-	 */
-	static inline void push(ContextPtr ctx, const FunctionMap &map)
-	{
-		StackAssert sa(ctx, 0);
-
-		for (const auto &entry : map) {
-			duk_push_c_function(ctx, entry.second.function, entry.second.nargs);
-			duk_put_prop_string(ctx, -2, entry.first.c_str());
-		}
-	}
-};
-
-/**
- * @class TypeTraits<Object>
- * @brief Push empty object to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Object> {
-public:
-	/**
-	 * Check if value is an object.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if object
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_object(ctx, index);
-	}
-
-	/**
-	 * Create an empty object on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(ContextPtr ctx, const Object &)
-	{
-		duk_push_object(ctx);
-	}
-};
-
-/**
- * @class TypeTraits<Array>
- * @brief Push empty array to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Array> {
-public:
-	/**
-	 * Check if value is a array.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if array
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_array(ctx, index);
-	}
-
-	/**
-	 * Create an empty array on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(ContextPtr ctx, const Array &)
-	{
-		duk_push_array(ctx);
-	}
-};
-
-/**
- * @class TypeTraits<Undefined>
- * @brief Push undefined value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Undefined> {
-public:
-	/**
-	 * Check if value is undefined.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if undefined
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_undefined(ctx, index);
-	}
-
-	/**
-	 * Push undefined value on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(ContextPtr ctx, const Undefined &)
-	{
-		duk_push_undefined(ctx);
-	}
-};
-
-/**
- * @class TypeTraits<Null>
- * @brief Push null value to the stack.
- *
- * Provides: is, push.
- */
-template <>
-class TypeTraits<Null> {
-public:
-	/**
-	 * Check if value is null.
-	 *
-	 * @param ctx the context
-	 * @param index the index
-	 * @return true if null
-	 */
-	static inline bool is(ContextPtr ctx, int index)
-	{
-		return duk_is_null(ctx, index);
-	}
-
-	/**
-	 * Push null value on the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(ContextPtr ctx, const Null &)
-	{
-		duk_push_null(ctx);
-	}
-};
-
-/**
- * @brief Push this binding into the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeTraits<This> {
-public:
-	/**
-	 * Push this function into the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(ContextPtr ctx, const This &)
-	{
-		duk_push_this(ctx);
-	}
-};
-
-/**
- * @class TypeTraits<Global>
- * @brief Push the global object to the stack.
- *
- * Provides: push.
- */
-template <>
-class TypeTraits<Global> {
-public:
-	/**
-	 * Push the global object into the stack.
-	 *
-	 * @param ctx the context
-	 */
-	static inline void push(ContextPtr ctx, const Global &)
-	{
-		duk_push_global_object(ctx);
-	}
-};
-
-/**
- * @brief Push a map of key-value pair as objects.
- *
- * Provides: push.
- *
- * This class is convenient for settings constants such as enums, string and such.
- */
-template <typename T>
-class TypeTraits<std::unordered_map<std::string, T>> {
-public:
-	/**
-	 * Put all values from the map as properties to the object at the top of the stack.
-	 *
-	 * @param ctx the context
-	 * @param map the values
-	 * @note You need an object at the top of the stack before calling this function
-	 */
-	static void push(ContextPtr ctx, const std::unordered_map<std::string, T> &map)
-	{
-		StackAssert sa(ctx, 0);
-
-		for (const auto &pair : map) {
-			TypeTraits<T>::push(ctx, pair.second);
-			duk_put_prop_string(ctx, -2, pair.first.c_str());
-		}
-	}
-};
-
-/**
- * @brief Push or get vectors as JavaScript arrays.
- *
- * Provides: get, push.
- */
-template <typename T>
-class TypeTraits<std::vector<T>> {
-public:
-	/**
-	 * Get an array from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the array index
-	 * @return the array or empty array if the value is not an array
-	 */
-	static std::vector<T> get(ContextPtr ctx, int index)
-	{
-		StackAssert sa(ctx, 0);
-
-		std::vector<T> result;
-
-		if (!duk_is_array(ctx, -1))
-			return result;
-
-		int total = duk_get_length(ctx, index);
-
-		for (int i = 0; i < total; ++i)
-			result.push_back(getProperty<T>(ctx, index, i));
-
-		return result;
-	}
-
-	/**
-	 * Create an array with the specified values.
-	 *
-	 * @param ctx the context
-	 * @param array the values
-	 */
-	static void push(ContextPtr ctx, const std::vector<T> &array)
-	{
-		StackAssert sa(ctx, 1);
-
-		duk_push_array(ctx);
-
-		unsigned i = 0;
-		for (const auto &v : array) {
-			TypeTraits<T>::push(ctx, v);
-			duk_put_prop_index(ctx, -2, i++);
-		}
-	}
-};
-
-/**
- * @brief Implementation of managed shared_ptr
- * @see Shared
- */
-template <typename T>
-class TypeTraits<Shared<T>> {
-private:
-	static void apply(ContextPtr ctx, std::shared_ptr<T> value)
-	{
-		StackAssert sa(ctx, 0);
-
-		sign<T>(ctx, -1);
-
-		duk_push_pointer(ctx, new std::shared_ptr<T>(std::move(value)));
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> Ret {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
-			delete static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
-			duk_pop(ctx);
-			duk_push_null(ctx);
-			duk_put_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
-
-public:
-	/**
-	 * Construct the shared_ptr as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(ContextPtr ctx, Shared<T> value)
-	{
-		StackAssert sa(ctx, 0);
-
-		duk_push_this(ctx);
-		apply(ctx, std::move(value.object));
-		duk_pop(ctx);
-	}
-
-	/**
-	 * Push a managed shared_ptr as object.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void push(ContextPtr ctx, Shared<T> value)
-	{
-		StackAssert sa(ctx, 1);
-
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		TypeTraits<T>::prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
-
-	/**
-	 * Get a managed shared_ptr from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the object index
-	 * @return the shared_ptr
-	 */
-	static std::shared_ptr<T> get(ContextPtr ctx, int index)
-	{
-		StackAssert sa(ctx, 0);
-
-		checkSignature<T>(ctx, index);
-
-		duk_get_prop_string(ctx, index, "\xff""\xff""js-shared-ptr");
-		std::shared_ptr<T> value = *static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
-		duk_pop(ctx);
-
-		return value;
-	}
-};
-
-/**
- * @brief Implementation of managed pointers
- * @see Pointer
- */
-template <typename T>
-class TypeTraits<Pointer<T>> {
-private:
-	static void apply(ContextPtr ctx, T *value)
-	{
-		StackAssert sa(ctx, 0);
-
-		sign<T>(ctx, -1);
-
-		duk_push_pointer(ctx, value);
-		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
-		duk_push_c_function(ctx, [] (duk_context *ctx) -> Ret {
-			duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-			delete static_cast<T *>(duk_to_pointer(ctx, -1));
-			duk_pop(ctx);
-			duk_push_null(ctx);
-			duk_put_prop_string(ctx, 0, "\xff""\xff""js-ptr");
-
-			return 0;
-		}, 1);
-		duk_set_finalizer(ctx, -2);
-	}
-
-public:
-	/**
-	 * Construct the pointer as this.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void construct(ContextPtr ctx, Pointer<T> value)
-	{
-		StackAssert sa(ctx, 0);
-
-		duk_push_this(ctx);
-		apply(ctx, value.object);
-		duk_pop(ctx);
-	}
-
-	/**
-	 * Push a managed pointer as object.
-	 *
-	 * @param ctx the context
-	 * @param value the value
-	 */
-	static void push(ContextPtr ctx, Pointer<T> value)
-	{
-		StackAssert sa(ctx, 1);
-
-		duk_push_object(ctx);
-		apply(ctx, value.object);
-		TypeTraits<T>::prototype(ctx);
-		duk_set_prototype(ctx, -2);
-	}
-
-	/**
-	 * Get a managed pointer from the stack.
-	 *
-	 * @param ctx the context
-	 * @param index the object index
-	 * @return the pointer
-	 * @warning Do not store the pointer into the C++ side, the object can be deleted at any time
-	 */
-	static T *get(ContextPtr ctx, int index)
-	{
-		StackAssert sa(ctx, 0);
-
-		checkSignature<T>(ctx, index);
-
-		duk_get_prop_string(ctx, index, "\xff""\xff""js-ptr");
-		T *value = static_cast<T *>(duk_to_pointer(ctx, -1));
-		duk_pop(ctx);
-
-		return value;
-	}
-};
-
-} // !duk
-
-} // !irccd
-
-#endif // !IRCCD_JS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/js.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,2381 @@
+/*
+ * js.hpp -- JavaScript C++14 wrapper for Duktape
+ *
+ * Copyright (c) 2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_HPP
+#define IRCCD_JS_HPP
+
+/**
+ * @file js.hpp
+ * @brief Bring JavaScript using Duktape.
+ *
+ * This file provides usual Duktape function renamed and placed into `duk` namespace. It also replaces error
+ * code with exceptions when possible.
+ *
+ * For convenience, this file also provides templated functions, overloads and much more.
+ */
+
+#include <cassert>
+#include <functional>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <duktape.h>
+
+namespace irccd {
+
+/**
+ * Duktape C++ namespace wrapper.
+ */
+namespace duk {
+
+class Context;
+
+using CodePoint = duk_codepoint_t;
+using ContextPtr = duk_context *;
+using Index = duk_idx_t;
+using Ret = duk_ret_t;
+using Size = duk_size_t;
+
+/**
+ * @class StackAssert
+ * @brief Stack sanity checker.
+ *
+ * Instanciate this class where you need to manipulate the Duktape stack outside a Duktape/C function, its destructor
+ * will examinate if the stack size matches the user expected size.
+ *
+ * When compiled with NDEBUG, this class does nothing.
+ *
+ * To use it, just declare an lvalue at the beginning of your function.
+ */
+class StackAssert {
+#if !defined(NDEBUG)
+private:
+	ContextPtr m_context;
+	unsigned m_expected;
+	unsigned m_begin;
+#endif
+
+public:
+	/**
+	 * Create the stack checker.
+	 *
+	 * No-op if NDEBUG is set.
+	 *
+	 * @param ctx the context
+	 * @param expected the size expected relative to the already existing values
+	 */
+	inline StackAssert(ContextPtr ctx, unsigned expected = 0) noexcept
+#if !defined(NDEBUG)
+		: m_context(ctx)
+		, m_expected(expected)
+		, m_begin(static_cast<unsigned>(duk_get_top(ctx)))
+#endif
+	{
+#if defined(NDEBUG)
+		(void)ctx;
+		(void)expected;
+#endif
+	}
+
+	/**
+	 * Verify the expected size.
+	 *
+	 * No-op if NDEBUG is set.
+	 */
+	inline ~StackAssert() noexcept
+	{
+#if !defined(NDEBUG)
+		assert((unsigned)duk_get_top(m_context) - m_begin == m_expected);
+#endif
+	}
+};
+
+/**
+ * @class Object
+ * @brief Empty class tag for push() function.
+ */
+class Object {
+};
+
+/**
+ * @class Array
+ * @brief Empty class tag for push() function.
+ */
+class Array {
+};
+
+/**
+ * @class Global
+ * @brief Empty class tag to push the global object.
+ */
+class Global {
+};
+
+/**
+ * @class Undefined
+ * @brief Empty class tag to push undefined to the stack.
+ */
+class Undefined {
+};
+
+/**
+ * @class Null
+ * @brief Empty class tag to push null to the stack.
+ */
+class Null {
+};
+
+/**
+ * @class This
+ * @brief Empty class tag to push this binding to the stack.
+ */
+class This {
+};
+
+/**
+ * @class RawPointer
+ * @brief Push a non-managed pointer to Duktape, the pointer will never be deleted.
+ * @note For a managed pointer with prototype, see Pointer
+ */
+template <typename T>
+class RawPointer {
+public:
+	/**
+	 * The pointer to push.
+	 */
+	T *object;
+};
+
+/**
+ * @brief Manage shared_ptr from C++ and JavaScript
+ *
+ * This class allowed you to push and retrieve shared_ptr from C++ and JavaScript without taking care of ownership
+ * and deletion.
+ *
+ */
+template <typename T>
+class Shared {
+public:
+	/**
+	 * The shared object.
+	 */
+	std::shared_ptr<T> object;
+};
+
+/**
+ * @brief Manage pointers from C++ and JavaScript
+ *
+ * This class allowed you to push and retrieve C++ pointers from C++ and JavaScript. The object will be deleted when
+ * the JavaScript garbage collectors collect them so never store a pointer created with this.
+ *
+ * The only requirement is to have the function `void prototype(Context &ctx)` in your class T.
+ */
+template <typename T>
+class Pointer {
+public:
+	/**
+	 * The object.
+	 */
+	T *object{nullptr};
+};
+
+/**
+ * @class Function
+ * @brief Duktape/C function definition.
+ *
+ * This class wraps the std::function as a Duktape/C function by storing a copied pointer.
+ */
+class Function {
+public:
+	/**
+	 * The function pointer, must not be null.
+	 */
+	duk_c_function function;
+
+	/**
+	 * Number of args that the function takes
+	 */
+	duk_idx_t nargs{0};
+};
+
+/**
+ * Map of functions to set on an object.
+ */
+using FunctionMap = std::unordered_map<std::string, Function>;
+
+/**
+ * Map of string to type, ideal for setting constants like enums.
+ */
+template <typename Type>
+using Map = std::unordered_map<std::string, Type>;
+
+/**
+ * @class ErrorInfo
+ * @brief Error description.
+ *
+ * This class fills the fields got in an Error object.
+ */
+class ErrorInfo : public std::exception {
+public:
+	std::string name;		//!< name of error
+	std::string message;		//!< error message
+	std::string stack;		//!< stack if available
+	std::string fileName;		//!< filename if applicable
+	int lineNumber{0};		//!< line number if applicable
+
+	/**
+	 * Get the error message. This effectively returns message field.
+	 *
+	 * @return the message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * @class TypeTraits
+ * @brief Type information to implement new types in JavaScript's context.
+ *
+ * This class depending on your needs may have the following functions:
+ *
+ * - `static void construct(Context &ctx, Type value)`
+ * - `static Type get(Context &ctx, int index)`
+ * - `static bool is(Context &ctx, int index)`
+ * - `static Type optional(Context &ctx, int index, Type defaultValue)`
+ * - `static void push(Context &ctx, Type value)`
+ * - `static Type require(Context &ctx, int index)`
+ *
+ * The `construct` function is used in Context::construct to build a new value as this (e.g. constructors).
+ *
+ * The `get` function is used in Context::get, Context::getProperty, Context::getGlobal to retrieve a value from the
+ * stack.
+ *
+ * The `is` function is used in Context::is to check if the value on the stack is of type `Type`.
+ *
+ * The `optional` function is used in Context::optional to get a value or a replacement if not applicable.
+ *
+ * The `push` function is used in Context::push to usually create a new value on the stack but some specializations
+ * may not (e.g. FunctionMap).
+ *
+ * The `require` function is used in Context::require to get a value from the stack or raise a JavaScript exception if
+ * not applicable.
+ *
+ * This class is fully specialized for: `bool`, `const char *`, `double`, `int`, `std::string`.
+ *
+ * It is also partially specialized for : `Global`, `Object`, `Array`, `Undefined`, `Null`, `std::vector<Type>`.
+ */
+template <typename Type>
+class TypeTraits {
+};
+
+/**
+ * @class Context
+ * @brief RAII based Duktape handler.
+ *
+ * This class is implicitly convertible to duk_context for convenience.
+ */
+class Context {
+private:
+	using Deleter = void (*)(duk_context *);
+	using Handle = std::unique_ptr<duk_context, Deleter>;
+
+	Handle m_handle;
+
+	Context(const Context &) = delete;
+	Context &operator=(const Context &) = delete;
+	Context(const Context &&) = delete;
+	Context &operator=(const Context &&) = delete;
+
+public:
+	/**
+	 * Create default context.
+	 */
+	inline Context()
+		: m_handle(duk_create_heap_default(), duk_destroy_heap)
+	{
+	}
+
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * @return the duk_context
+	 */
+	inline operator duk_context *() noexcept
+	{
+		return m_handle.get();
+	}
+
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * @return the duk_context
+	 */
+	inline operator duk_context *() const noexcept
+	{
+		return m_handle.get();
+	}
+};
+
+/**
+ * Get the error object when a JavaScript error has been thrown (e.g. eval failure).
+ *
+ * @param ctx the context
+ * @param index the index
+ * @return the information
+ */
+inline ErrorInfo error(ContextPtr ctx, int index)
+{
+	ErrorInfo error;
+
+	index = duk_normalize_index(ctx, index);
+
+	duk_get_prop_string(ctx, index, "name");
+	error.name = duk_to_string(ctx, -1);
+	duk_get_prop_string(ctx, index, "message");
+	error.message = duk_to_string(ctx, -1);
+	duk_get_prop_string(ctx, index, "fileName");
+	error.fileName = duk_to_string(ctx, -1);
+	duk_get_prop_string(ctx, index, "lineNumber");
+	error.lineNumber = duk_to_int(ctx, -1);
+	duk_get_prop_string(ctx, index, "stack");
+	error.stack = duk_to_string(ctx, -1);
+	duk_pop_n(ctx, 5);
+
+	return error;
+}
+
+/**
+ * Wrapper for [duk_base64_decode](http://duktape.org/api.html#duk_base64_decode).
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+inline void base64Decode(ContextPtr ctx, Index index)
+{
+	duk_base64_decode(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_base64_encode](http://duktape.org/api.html#duk_base64_encode).
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+inline void base64Encode(ContextPtr ctx, Index index)
+{
+	duk_base64_encode(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_call](http://duktape.org/api.html#duk_call).
+ *
+ * @param ctx the context
+ * @param nargs the number of arguments
+ */
+inline void call(ContextPtr ctx, Index nargs = 0)
+{
+	duk_call(ctx, nargs);
+}
+
+/**
+ * Wrapper for [duk_call_method](http://duktape.org/api.html#duk_call_method).
+ *
+ * @param ctx the context
+ * @param nargs the number of arguments
+ */
+inline void callMethod(ContextPtr ctx, Index nargs = 0)
+{
+	duk_call_method(ctx, nargs);
+}
+
+/**
+ * Wrapper for [duk_call_prop](http://duktape.org/api.html#duk_call_prop).
+ *
+ * @param ctx the context
+ * @param index the object index
+ * @param nargs the number of arguments
+ */
+inline void callProperty(ContextPtr ctx, Index index, Index nargs = 0)
+{
+	duk_call_prop(ctx, index, nargs);
+}
+
+/**
+ * Wrapper for [duk_char_code_at](http://duktape.org/api.html#duk_char_code_at).
+ *
+ * @param ctx the context
+ * @param index the index
+ * @param charOffset the offset
+ */
+inline CodePoint charCodeAt(ContextPtr ctx, Index index, Size charOffset)
+{
+	return duk_char_code_at(ctx, index, charOffset);
+}
+
+/**
+ * Wrapper for [duk_check_stack](http://duktape.org/api.html#duk_check_stack).
+ *
+ * @param ctx the context
+ * @param extra the extra space
+ * @return true if space is available
+ */
+inline bool checkStack(ContextPtr ctx, Index extra)
+{
+	return duk_check_stack(ctx, extra);
+}
+
+/**
+ * Wrapper for [duk_check_stack_top](http://duktape.org/api.html#duk_check_stack_top).
+ *
+ * @param ctx the context
+ * @param top the extra space
+ * @return true if space is available
+ */
+inline bool checkStackTop(ContextPtr ctx, Index top)
+{
+	return duk_check_stack_top(ctx, top);
+}
+
+/**
+ * Wrapper for [duk_check_type](http://duktape.org/api.html#duk_check_type).
+ *
+ * @param ctx the context
+ * @param index the value index
+ * @param type the desired type
+ * @return true if object is given type
+ */
+inline bool checkType(ContextPtr ctx, Index index, int type)
+{
+	return duk_check_type(ctx, index, type);
+}
+
+/**
+ * Wrapper for [duk_check_type_mask](http://duktape.org/api.html#duk_check_type_mask).
+ *
+ * @param ctx the context
+ * @param index the value index
+ * @param mask the desired mask
+ * @return true if object is one of the type
+ */
+inline bool checkTypeMask(ContextPtr ctx, Index index, unsigned mask)
+{
+	return duk_check_type_mask(ctx, index, mask);
+}
+
+/**
+ * Wrapper for [duk_compact](http://duktape.org/api.html#duk_compact).
+ *
+ * @param ctx the context
+ * @param objIndex the object index
+ */
+inline void compact(ContextPtr ctx, Index objIndex)
+{
+	duk_compact(ctx, objIndex);
+}
+
+/**
+ * Wrapper for [duk_concat](http://duktape.org/api.html#duk_concat).
+ *
+ * @param ctx the context
+ * @param count the number of values
+ */
+inline void concat(ContextPtr ctx, Index count)
+{
+	duk_concat(ctx, count);
+}
+
+/**
+ * Wrapper for [duk_copy](http://duktape.org/api.html#duk_copy).
+ *
+ * @param from the from index
+ * @param to the destination
+ */
+inline void copy(ContextPtr ctx, Index from, Index to)
+{
+	duk_copy(ctx, from, to);
+}
+
+/**
+ * Wrapper for [duk_def_prop](http://duktape.org/api.html#duk_def_prop).
+ *
+ * @param index the object index
+ * @param flags the flags
+ */
+inline void defineProperty(ContextPtr ctx, Index index, unsigned flags)
+{
+	duk_def_prop(ctx, index, flags);
+}
+
+/**
+ * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
+ *
+ * @param index the object index
+ * @return true if deleted
+ */
+inline bool deleteProperty(ContextPtr ctx, Index index)
+{
+	return duk_del_prop(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
+ *
+ * @param index the object index
+ * @param position the property index
+ * @return true if deleted
+ */
+inline bool deleteProperty(ContextPtr ctx, Index index, unsigned position)
+{
+	return duk_del_prop_index(ctx, index, position);
+}
+
+/**
+ * Wrapper for [duk_del_prop](http://duktape.org/api.html#duk_del_prop).
+ *
+ * @param index the object index
+ * @param name the property name
+ * @return true if deleted
+ */
+inline bool deleteProperty(ContextPtr ctx, Index index, const std::string &name)
+{
+	return duk_del_prop_string(ctx, index, name.c_str());
+}
+
+/**
+ * Wrapper for [duk_dup](http://duktape.org/api.html#duk_dup).
+ *
+ * @param index the value to copy
+ */
+inline void dup(ContextPtr ctx, int index = -1)
+{
+	duk_dup(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_equals](http://duktape.org/api.html#duk_equals).
+ *
+ * @param ctx the context
+ * @param index1 the first value
+ * @param index2 the second value
+ * @return true if they equal
+ */
+inline bool equals(ContextPtr ctx, Index index1, Index index2)
+{
+	return duk_equals(ctx, index1, index2);
+}
+
+/**
+ * Wrapper for [duk_eval](http://duktape.org/api.html#duk_eval).
+ *
+ * @param ctx the context
+ */
+inline void eval(ContextPtr ctx)
+{
+	duk_eval(ctx);
+}
+
+/**
+ * Wrapper for [duk_eval_file](http://duktape.org/api.html#duk_eval_file).
+ *
+ * @param ctx the context
+ * @param path the path
+ * @param result true to get the result at the top of the stack
+ */
+inline void evalFile(ContextPtr ctx, const std::string &path, bool result = true)
+{
+	if (result)
+		duk_eval_file(ctx, path.c_str());
+	else
+		duk_eval_file_noresult(ctx, path.c_str());
+}
+
+/**
+ * Wrapper for [duk_eval_string](http://duktape.org/api.html#duk_eval_string).
+ *
+ * @param ctx the context
+ * @param src the source script
+ * @param result true to get the result at the top of the stack
+ */
+inline void evalString(ContextPtr ctx, const std::string &src, bool result = true)
+{
+	if (result)
+		duk_eval_string(ctx, src.c_str());
+	else
+		duk_eval_string_noresult(ctx, src.c_str());
+}
+/**
+ * Wrapper for [duk_gc](http://duktape.org/api.html#duk_gc).
+ *
+ * @param ctx the context
+ * @param flags the flags
+ */
+inline void gc(ContextPtr ctx, unsigned flags = 0)
+{
+	duk_gc(ctx, flags);
+}
+
+/**
+ * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
+ *
+ * @param ctx the context
+ * @param index the object index
+ * @return true if has
+ */
+inline bool hasProperty(ContextPtr ctx, Index index)
+{
+	return duk_has_prop(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
+ *
+ * @param ctx the context
+ * @param index the object index
+ * @param position the property index
+ * @return true if has
+ */
+inline bool hasProperty(ContextPtr ctx, Index index, unsigned position)
+{
+	return duk_has_prop_index(ctx, index, position);
+}
+
+/**
+ * Wrapper for [duk_has_prop](http://duktape.org/api.html#duk_has_prop).
+ *
+ * @param ctx the context
+ * @param index the object index
+ * @param name the property name
+ * @return true if has
+ */
+inline bool hasProperty(ContextPtr ctx, int index, const std::string &name)
+{
+	return duk_has_prop_string(ctx, index, name.c_str());
+}
+
+/**
+ * Wrapper for [duk_insert](http://duktape.org/api.html#duk_insert).
+ *
+ * @param ctx the context
+ * @param to the destination
+ * @note Wrapper of duk_insert
+ */
+inline void insert(ContextPtr ctx, Index to)
+{
+	duk_insert(ctx, to);
+}
+
+/**
+ * Wrapper for [duk_instanceof](http://duktape.org/api.html#duk_instanceof).
+ *
+ * @param ctx the context
+ * @param idx1 the value to test
+ * @param idx2 the instance requested
+ * @return true if idx1 is instance of idx2
+ */
+inline bool instanceof(ContextPtr ctx, Index idx1, Index idx2)
+{
+	return duk_instanceof(ctx, idx1, idx2);
+}
+
+/**
+ * Wrapper for [duk_join](http://duktape.org/api.html#duk_join).
+ *
+ * @param ctx the context
+ * @param count the number of values
+ */
+inline void join(ContextPtr ctx, Index count)
+{
+	duk_join(ctx, count);
+}
+
+/**
+ * Wrapper for [duk_json_decode](http://duktape.org/api.html#duk_json_decode).
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+inline void jsonDecode(ContextPtr ctx, Index index)
+{
+	duk_json_decode(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_json_encode](http://duktape.org/api.html#duk_json_encode).
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+inline void jsonEncode(ContextPtr ctx, Index index)
+{
+	duk_json_encode(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_normalize_index](http://duktape.org/api.html#duk_normalize_index).
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+inline Index normalizeIndex(ContextPtr ctx, Index index)
+{
+	return duk_normalize_index(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_pcall](http://duktape.org/api.html#duk_pcall).
+ *
+ * @param ctx the context
+ * @param nargs the number of arguments
+ */
+inline int pcall(ContextPtr ctx, Index nargs = 0)
+{
+	return duk_pcall(ctx, nargs);
+}
+
+/**
+ * Wrapper for [duk_peval](http://duktape.org/api.html#duk_peval).
+ *
+ * @param ctx the context
+ */
+inline int peval(ContextPtr ctx)
+{
+	return duk_peval(ctx);
+}
+
+/**
+ * Wrapper for [duk_peval_file](http://duktape.org/api.html#duk_peval_file).
+ *
+ * @param ctx the context
+ * @param path the path
+ * @param result true to get the result at the top of the stack
+ */
+inline int pevalFile(ContextPtr ctx, const std::string &path, bool result = true)
+{
+	return result ? duk_peval_file(ctx, path.c_str()) : duk_peval_file_noresult(ctx, path.c_str());
+}
+
+/**
+ * Wrapper for [duk_peval_string](http://duktape.org/api.html#duk_peval_string).
+ *
+ * @param ctx the context
+ * @param src the source script
+ * @param result true to get the result at the top of the stack
+ */
+inline int pevalString(ContextPtr ctx, const std::string &src, bool result = true)
+{
+	return result ? duk_peval_string(ctx, src.c_str()) : duk_peval_string_noresult(ctx, src.c_str());
+}
+
+/**
+ * Wrapper for [duk_pop_n](http://duktape.org/api.html#duk_pop_n).
+ *
+ * @param ctx the context
+ * @param count the number of values to pop
+ */
+inline void pop(ContextPtr ctx, Index count = 1)
+{
+	duk_pop_n(ctx, count);
+}
+
+/**
+ * Wrapper for [duk_remove](http://duktape.org/api.html#duk_remove).
+ *
+ * @param ctx the context
+ * @param index the value to remove
+ */
+inline void remove(ContextPtr ctx, Index index)
+{
+	duk_remove(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_replace](http://duktape.org/api.html#duk_replace).
+ *
+ * @param ctx the context
+ * @param index the value to replace by the value at the top of the stack
+ */
+inline void replace(ContextPtr ctx, Index index)
+{
+	duk_replace(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_set_prototype](http://duktape.org/api.html#duk_set_prototype).
+ *
+ * @param ctx the context
+ * @param index the value index
+ */
+inline void setPrototype(ContextPtr ctx, Index index)
+{
+	duk_set_prototype(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_swap](http://duktape.org/api.html#duk_swap).
+ *
+ * @param ctx the context
+ * @param index1 the first index
+ * @param index2 the second index
+ */
+inline void swap(ContextPtr ctx, Index index1, Index index2)
+{
+	duk_swap(ctx, index1, index2);
+}
+
+/**
+ * Wrapper for [duk_swap_top](http://duktape.org/api.html#duk_swap_top).
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+inline void swapTop(ContextPtr ctx, Index index)
+{
+	duk_swap_top(ctx, index);
+}
+
+/**
+ * Wrapper for [duk_get_top](http://duktape.org/api.html#duk_get_top).
+ *
+ * @param ctx the context
+ * @return the stack size
+ */
+inline int top(ContextPtr ctx) noexcept
+{
+	return duk_get_top(ctx);
+}
+
+/**
+ * Wrapper for [duk_get_type](http://duktape.org/api.html#duk_get_type).
+ *
+ * @param ctx the context
+ * @param index the idnex
+ * @return the type
+ */
+inline int type(ContextPtr ctx, Index index) noexcept
+{
+	return duk_get_type(ctx, index);
+}
+
+/*
+ * Push / Get / Require / Is / Optional
+ * ----------------------------------------------------------
+ *
+ * The following functions are used to push, get or check values from the stack. They use specialization
+ * of TypeTraits class.
+ */
+
+/**
+ * Push a value into the stack. Calls TypeTraits<T>::push(*this, value);
+ *
+ * @param value the value to forward
+ */
+template <typename Type>
+inline void push(ContextPtr ctx, Type &&value)
+{
+	TypeTraits<std::decay_t<Type>>::push(ctx, std::forward<Type>(value));
+}
+
+/**
+ * Generic template function to get a value from the stack.
+ *
+ * @param index the index
+ * @return the value
+ */
+template <typename Type>
+inline auto get(ContextPtr ctx, int index) -> decltype(TypeTraits<Type>::get(ctx, 0))
+{
+	return TypeTraits<Type>::get(ctx, index);
+}
+
+/**
+ * Require a type at the specified index.
+ *
+ * @param index the index
+ * @return the value
+ */
+template <typename Type>
+inline auto require(ContextPtr ctx, int index) -> decltype(TypeTraits<Type>::require(ctx, 0))
+{
+	return TypeTraits<Type>::require(ctx, index);
+}
+
+/**
+ * Check if a value is a type of T.
+ *
+ * The TypeTraits<T> must have `static bool is(ContextPtr ptr, int index)`.
+ *
+ * @param index the value index
+ * @return true if is the type
+ */
+template <typename T>
+inline bool is(ContextPtr ctx, int index)
+{
+	return TypeTraits<T>::is(ctx, index);
+}
+
+/**
+ * Get an optional value from the stack, if the value is not available of not the correct type,
+ * return defaultValue instead.
+ *
+ * The TypeTraits<T> must have `static T optional(Context &, int index, T &&defaultValue)`.
+ *
+ * @param index the value index
+ * @param defaultValue the value replacement
+ * @return the value or defaultValue
+ */
+template <typename Type>
+inline auto optional(ContextPtr ctx, int index, Type &&defaultValue)
+{
+	return TypeTraits<std::decay_t<Type>>::optional(ctx, index, std::forward<Type>(defaultValue));
+}
+
+/*
+ * Properties management
+ * ----------------------------------------------------------
+ *
+ * The following functions are used to read or set properties on objects or globals also using TypeTraits.
+ */
+
+/**
+ * Get the property `name' as value from the object at the specified index.
+ *
+ * @param index the object index
+ * @param name the property name
+ * @return the value
+ * @note The stack is unchanged
+ */
+template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
+inline auto getProperty(ContextPtr ctx, int index, const std::string &name) -> decltype(get<Type>(ctx, 0))
+{
+	duk_get_prop_string(ctx, index, name.c_str());
+	decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
+	duk_pop(ctx);
+
+	return value;
+}
+
+/**
+ * Get a property by index, for arrays.
+ *
+ * @param index the object index
+ * @param position the position int the object
+ * @return the value
+ * @note The stack is unchanged
+ */
+template <typename Type, typename std::enable_if_t<!std::is_void<Type>::value> * = nullptr>
+inline auto getProperty(ContextPtr ctx, int index, int position) -> decltype(get<Type>(ctx, 0))
+{
+	duk_get_prop_index(ctx, index, position);
+	decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
+	duk_pop(ctx);
+
+	return value;
+}
+
+/**
+ * Get the property `name' and push it to the stack from the object at the specified index.
+ *
+ * @param index the object index
+ * @param name the property name
+ * @note The stack contains the property value
+ */
+template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
+inline void getProperty(ContextPtr ctx, int index, const std::string &name)
+{
+	duk_get_prop_string(ctx, index, name.c_str());
+}
+
+/**
+ * Get the property by index and push it to the stack from the object at the specified index.
+ *
+ * @param index the object index
+ * @param position the position in the object
+ * @note The stack contains the property value
+ */
+template <typename Type, typename std::enable_if_t<std::is_void<Type>::value> * = nullptr>
+inline void getProperty(ContextPtr ctx, int index, int position)
+{
+	duk_get_prop_index(ctx, index, position);
+}
+
+/**
+ * Get an optional property `name` from the object at the specified index.
+ *
+ * @param index the object index
+ * @param name the property name
+ * @param def the default value
+ * @return the value or def
+ * @note The stack is unchanged
+ */
+template <typename Type, typename DefaultValue>
+inline auto optionalProperty(ContextPtr ctx, int index, const std::string &name, DefaultValue &&def) -> decltype(optional(ctx, 0, std::forward<DefaultValue>(def)))
+{
+	duk_get_prop_string(ctx, index, name.c_str());
+	decltype(optional(ctx, 0, std::forward<DefaultValue>(def))) value = optional(ctx, -1, std::forward<DefaultValue>(def));
+	duk_pop(ctx);
+
+	return value;
+}
+
+/**
+ * Get an optional property by index, for arrays
+ *
+ * @param index the object index
+ * @param position the position int the object
+ * @param def the default value
+ * @return the value or def
+ * @note The stack is unchanged
+ */
+template <typename Type, typename DefaultValue>
+inline auto optionalProperty(ContextPtr ctx, int index, int position, DefaultValue &&def) -> decltype(optional(ctx, 0, std::forward<DefaultValue>(def)))
+{
+	duk_get_prop_index(ctx, index, position);
+	decltype(optional(ctx, 0, std::forward<DefaultValue>(def))) value = optional(ctx, -1, std::forward<DefaultValue>(def));
+	duk_pop(ctx);
+
+	return value;
+}
+
+/**
+ * Set a property to the object at the specified index.
+ *
+ * @param index the object index
+ * @param name the property name
+ * @param value the value to forward
+ * @note The stack is unchanged
+ */
+template <typename Type>
+void putProperty(ContextPtr ctx, int index, const std::string &name, Type &&value)
+{
+	index = duk_normalize_index(ctx, index);
+
+	push(ctx, std::forward<Type>(value));
+	duk_put_prop_string(ctx, index, name.c_str());
+}
+
+/**
+ * Set a property by index, for arrays.
+ *
+ * @param index the object index
+ * @param position the position in the object
+ * @param value the value to forward
+ * @note The stack is unchanged
+ */
+template <typename Type>
+void putProperty(ContextPtr ctx, int index, int position, Type &&value)
+{
+	index = duk_normalize_index(ctx, index);
+
+	push(ctx, std::forward<Type>(value));
+	duk_put_prop_index(ctx, index, position);
+}
+
+/**
+ * Put the value that is at the top of the stack as property to the object.
+ *
+ * @param index the object index
+ * @param name the property name
+ */
+inline void putProperty(ContextPtr ctx, int index, const std::string &name)
+{
+	duk_put_prop_string(ctx, index, name.c_str());
+}
+
+/**
+ * Put the value that is at the top of the stack to the object as index.
+ *
+ * @param index the object index
+ * @param position the position in the object
+ */
+inline void putProperty(ContextPtr ctx, int index, int position)
+{
+	duk_put_prop_index(ctx, index, position);
+}
+
+/**
+ * Get a global value.
+ *
+ * @param name the name of the global variable
+ * @return the value
+ */
+template <typename Type>
+inline auto getGlobal(ContextPtr ctx, const std::string &name, std::enable_if_t<!std::is_void<Type>::value> * = nullptr) -> decltype(get<Type>(ctx, 0))
+{
+	duk_get_global_string(ctx, name.c_str());
+	decltype(get<Type>(ctx, 0)) value = get<Type>(ctx, -1);
+	duk_pop(ctx);
+
+	return value;
+}
+
+/**
+ * Overload that push the value at the top of the stack instead of returning it.
+ */
+template <typename Type>
+inline void getGlobal(ContextPtr ctx, const std::string &name, std::enable_if_t<std::is_void<Type>::value> * = nullptr) noexcept
+{
+	duk_get_global_string(ctx, name.c_str());
+}
+
+/**
+ * Set a global variable.
+ *
+ * @param name the name of the global variable
+ * @param type the value to set
+ */
+template <typename Type>
+inline void putGlobal(ContextPtr ctx, const std::string &name, Type&& type)
+{
+	push(ctx, std::forward<Type>(type));
+	duk_put_global_string(ctx, name.c_str());
+}
+
+/**
+ * Put the value at the top of the stack as global property.
+ *
+ * @param name the property name
+ */
+inline void putGlobal(ContextPtr ctx, const std::string &name)
+{
+	duk_put_global_string(ctx, name.c_str());
+}
+
+/*
+ * Extra functions
+ * ----------------------------------------------------------
+ *
+ * The following functions are implemented for convenience and do not exists in the native Duktape API.
+ */
+
+/**
+ * Enumerate an object or an array at the specified index.
+ *
+ * @param index the object or array index
+ * @param flags the optional flags to pass to duk_enum
+ * @param getvalue set to true if you want to extract the value
+ * @param func the function to call for each properties
+ */
+template <typename Func>
+void enumerate(ContextPtr ctx, int index, duk_uint_t flags, duk_bool_t getvalue, Func &&func)
+{
+	duk_enum(ctx, index, flags);
+
+	while (duk_next(ctx, -1, getvalue)) {
+		func(ctx);
+		duk_pop_n(ctx, 1 + (getvalue ? 1 : 0));
+	}
+
+	duk_pop(ctx);
+}
+
+/**
+ * Return the this binding of the current function.
+ *
+ * @return the this binding as the template given
+ */
+template <typename T>
+inline auto self(ContextPtr ctx) -> decltype(TypeTraits<T>::get(ctx, 0))
+{
+	duk_push_this(ctx);
+	decltype(TypeTraits<T>::get(ctx, 0)) value = TypeTraits<T>::get(ctx, -1);
+	duk_pop(ctx);
+
+	return value;
+}
+
+/**
+ * Throw an ECMAScript exception.
+ *
+ * @param ex the exception
+ */
+template <typename Exception>
+void raise(ContextPtr ctx, const Exception &ex)
+{
+	ex.raise(ctx);
+}
+
+/**
+ * Wrapper for duk_throw.
+ *
+ * @param ctx the context
+ */
+inline void raise(ContextPtr ctx)
+{
+	duk_throw(ctx);
+}
+
+/**
+ * Wrapper for duk_error.
+ *
+ * @param ctx the context
+ * @param type the error type (e.g. DUK_ERR_REFERENCE_ERROR)
+ * @param fmt the format string
+ * @param args the arguments
+ */
+template <typename... Args>
+inline void raise(ContextPtr ctx, int type, const char *fmt, Args&&... args)
+{
+	duk_error(ctx, type, fmt, std::forward<Args>(args)...);
+}
+
+/**
+ * Wrapper for duk_new.
+ *
+ * @param ctx the context
+ * @param nargs the number of arguments
+ */
+inline void create(ContextPtr ctx, int nargs = 0)
+{
+	duk_new(ctx, nargs);
+}
+
+/**
+ * Construct the object in place, setting value as this binding.
+ *
+ * The TypeTraits<T> must have the following requirements:
+ *
+ * - static void construct(Context &, T): must update this with the value and keep the stack unchanged
+ *
+ * @param value the value to forward
+ * @see self
+ */
+template <typename T>
+inline void construct(ContextPtr ctx, T &&value)
+{
+	TypeTraits<std::decay_t<T>>::construct(ctx, std::forward<T>(value));
+}
+
+/**
+ * Sign the given object with the name from T.
+ *
+ * This is automatically done for when constructing/pushing object with Shared and Pointer helpers, however you need
+ * to manually add it when using inheritance.
+ */
+template <typename T>
+inline void sign(ContextPtr ctx, Index index)
+{
+	StackAssert sa(ctx, 0);
+
+	index = duk_normalize_index(ctx, index);
+
+	duk_push_string(ctx, TypeTraits<T>::name().c_str());
+	duk_push_boolean(ctx, true);
+	duk_def_prop(ctx, index < 0 ? index : index, DUK_DEFPROP_HAVE_VALUE);
+
+	/* Do for inherited classes */
+	for (const std::string &parent : TypeTraits<T>::inherits()) {
+		duk_push_string(ctx, parent.c_str());
+		duk_push_boolean(ctx, true);
+		duk_def_prop(ctx, index < 0 ? index : index, DUK_DEFPROP_HAVE_VALUE);
+	}
+}
+
+/**
+ * Check if the object at the given index is signed by T or raise TypeError if not.
+ *
+ * @param ctx the context
+ * @param index the index
+ * @see sign
+ */
+template <typename T>
+inline void checkSignature(ContextPtr ctx, Index index)
+{
+	StackAssert sa(ctx, 0);
+
+	if (!is<Object>(ctx, index) || !getProperty<bool>(ctx, index, TypeTraits<T>::name()))
+		raise(ctx, DUK_ERR_TYPE_ERROR, "invalid this binding");
+}
+
+/**
+ * Tells if the object at the specified index is of type T.
+ *
+ * @param ctx the context
+ * @param index the index
+ */
+template <typename T>
+inline bool isSigned(ContextPtr ctx, Index index)
+{
+	StackAssert sa(ctx, 0);
+
+	return is<Object>(ctx, index) && getProperty<bool>(ctx, index, TypeTraits<T>::name());
+}
+
+/* ------------------------------------------------------------------
+ * Exception handling
+ * ------------------------------------------------------------------ */
+
+/**
+ * @class Error
+ * @brief Base ECMAScript error class.
+ * @warning Override the function create for your own exceptions
+ */
+class Error {
+private:
+	int m_type{DUK_ERR_ERROR};
+	std::string m_message;
+
+protected:
+	/**
+	 * Constructor with a type of error specified, specially designed for derived errors.
+	 *
+	 * @param type of error (e.g. DUK_ERR_ERROR)
+	 * @param message the message
+	 */
+	inline Error(int type, std::string message) noexcept
+		: m_type(type)
+		, m_message(std::move(message))
+	{
+	}
+
+public:
+	/**
+	 * Constructor with a message.
+	 *
+	 * @param message the message
+	 */
+	inline Error(std::string message) noexcept
+		: m_message(std::move(message))
+	{
+	}
+
+	/**
+	 * Create the exception on the stack.
+	 *
+	 * @note the default implementation search for the global variables
+	 * @param ctx the context
+	 */
+	virtual void raise(ContextPtr ctx) const noexcept
+	{
+		duk_error(ctx, m_type, "%s", m_message.c_str());
+	}
+};
+
+/**
+ * @class EvalError
+ * @brief Error in eval() function.
+ */
+class EvalError : public Error {
+public:
+	/**
+	 * Construct an EvalError.
+	 *
+	 * @param message the message
+	 */
+	inline EvalError(std::string message) noexcept
+		: Error(DUK_ERR_EVAL_ERROR, std::move(message))
+	{
+	}
+};
+
+/**
+ * @class RangeError
+ * @brief Value is out of range.
+ */
+class RangeError : public Error {
+public:
+	/**
+	 * Construct an RangeError.
+	 *
+	 * @param message the message
+	 */
+	inline RangeError(std::string message) noexcept
+		: Error(DUK_ERR_RANGE_ERROR, std::move(message))
+	{
+	}
+};
+
+/**
+ * @class ReferenceError
+ * @brief Trying to use a variable that does not exist.
+ */
+class ReferenceError : public Error {
+public:
+	/**
+	 * Construct an ReferenceError.
+	 *
+	 * @param message the message
+	 */
+	inline ReferenceError(std::string message) noexcept
+		: Error(DUK_ERR_REFERENCE_ERROR, std::move(message))
+	{
+	}
+};
+
+/**
+ * @class SyntaxError
+ * @brief Syntax error in the script.
+ */
+class SyntaxError : public Error {
+public:
+	/**
+	 * Construct an SyntaxError.
+	 *
+	 * @param message the message
+	 */
+	inline SyntaxError(std::string message) noexcept
+		: Error(DUK_ERR_SYNTAX_ERROR, std::move(message))
+	{
+	}
+};
+
+/**
+ * @class TypeError
+ * @brief Invalid type given.
+ */
+class TypeError : public Error {
+public:
+	/**
+	 * Construct an TypeError.
+	 *
+	 * @param message the message
+	 */
+	inline TypeError(std::string message) noexcept
+		: Error(DUK_ERR_TYPE_ERROR, std::move(message))
+	{
+	}
+};
+
+/**
+ * @class URIError
+ * @brief URI manipulation failure.
+ */
+class URIError : public Error {
+public:
+	/**
+	 * Construct an URIError.
+	 *
+	 * @param message the message
+	 */
+	inline URIError(std::string message) noexcept
+		: Error(DUK_ERR_URI_ERROR, std::move(message))
+	{
+	}
+};
+
+/* ------------------------------------------------------------------
+ * Standard overloads for TypeTraits<T>
+ * ------------------------------------------------------------------ */
+
+/**
+ * @class TypeTraits<int>
+ * @brief Default implementation for int.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeTraits<int> {
+public:
+	/**
+	 * Get an integer, return 0 if not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the integer
+	 */
+	static inline int get(ContextPtr ctx, int index)
+	{
+		return duk_get_int(ctx, index);
+	}
+
+	/**
+	 * Check if value is an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if integer
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_number(ctx, index);
+	}
+
+	/**
+	 * Get an integer, return defaultValue if the value is not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the integer or defaultValue
+	 */
+	static inline int optional(ContextPtr ctx, int index, int defaultValue)
+	{
+		return is(ctx, index) ? get(ctx, index) : defaultValue;
+	}
+
+	/**
+	 * Push an integer.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(ContextPtr ctx, int value)
+	{
+		duk_push_int(ctx, value);
+	}
+
+	/**
+	 * Require an integer, throws a JavaScript exception if not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the integer
+	 */
+	static inline int require(ContextPtr ctx, int index)
+	{
+		return duk_require_int(ctx, index);
+	}
+};
+
+/**
+ * @class TypeTraits<bool>
+ * @brief Default implementation for bool.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeTraits<bool> {
+public:
+	/**
+	 * Get a boolean, return 0 if not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the boolean
+	 */
+	static inline bool get(ContextPtr ctx, int index)
+	{
+		return duk_get_boolean(ctx, index);
+	}
+
+	/**
+	 * Check if value is a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if boolean
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_boolean(ctx, index);
+	}
+
+	/**
+	 * Get a bool, return defaultValue if the value is not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the boolean or defaultValue
+	 */
+	static inline bool optional(ContextPtr ctx, int index, bool defaultValue)
+	{
+		return is(ctx, index) ? get(ctx, index) : defaultValue;
+	}
+
+	/**
+	 * Push a boolean.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(ContextPtr ctx, bool value)
+	{
+		duk_push_boolean(ctx, value);
+	}
+
+	/**
+	 * Require a boolean, throws a JavaScript exception if not a boolean.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the boolean
+	 */
+	static inline bool require(ContextPtr ctx, int index)
+	{
+		return duk_require_boolean(ctx, index);
+	}
+};
+
+/**
+ * @class TypeTraits<double>
+ * @brief Default implementation for double.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeTraits<double> {
+public:
+	/**
+	 * Get a double, return 0 if not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the double
+	 */
+	static inline double get(ContextPtr ctx, int index)
+	{
+		return duk_get_number(ctx, index);
+	}
+
+	/**
+	 * Check if value is a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if double
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_number(ctx, index);
+	}
+
+	/**
+	 * Get a double, return defaultValue if the value is not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the double or defaultValue
+	 */
+	static inline double optional(ContextPtr ctx, int index, double defaultValue)
+	{
+		return is(ctx, index) ? get(ctx, index) : defaultValue;
+	}
+
+	/**
+	 * Push a double.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(ContextPtr ctx, double value)
+	{
+		duk_push_number(ctx, value);
+	}
+
+	/**
+	 * Require a double, throws a JavaScript exception if not a double.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the double
+	 */
+	static inline double require(ContextPtr ctx, int index)
+	{
+		return duk_require_number(ctx, index);
+	}
+};
+
+/**
+ * @class TypeTraits<std::string>
+ * @brief Default implementation for std::string.
+ *
+ * Provides: get, is, optional, push, require.
+ *
+ * Note: the functions allows embedded '\0'.
+ */
+template <>
+class TypeTraits<std::string> {
+public:
+	/**
+	 * Get a string, return 0 if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline std::string get(ContextPtr ctx, int index)
+	{
+		duk_size_t size;
+		const char *text = duk_get_lstring(ctx, index, &size);
+
+		return std::string{text, size};
+	}
+
+	/**
+	 * Check if value is a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if string
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_string(ctx, index);
+	}
+
+	/**
+	 * Get a string, return defaultValue if the value is not an string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the string or defaultValue
+	 */
+	static inline std::string optional(ContextPtr ctx, int index, std::string defaultValue)
+	{
+		return is(ctx, index) ? get(ctx, index) : defaultValue;
+	}
+
+	/**
+	 * Push a string.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(ContextPtr ctx, const std::string &value)
+	{
+		duk_push_lstring(ctx, value.c_str(), value.length());
+	}
+
+	/**
+	 * Require a string, throws a JavaScript exception if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline std::string require(ContextPtr ctx, int index)
+	{
+		duk_size_t size;
+		const char *text = duk_require_lstring(ctx, index, &size);
+
+		return std::string{text, size};
+	}
+};
+
+/**
+ * @class TypeTraits<const char *>
+ * @brief Default implementation for const char literals.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <>
+class TypeTraits<const char *> {
+public:
+	/**
+	 * Get a string, return 0 if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline const char *get(ContextPtr ctx, int index)
+	{
+		return duk_get_string(ctx, index);
+	}
+
+	/**
+	 * Check if value is a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if string
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_string(ctx, index);
+	}
+
+	/**
+	 * Get an integer, return defaultValue if the value is not an integer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the integer or defaultValue
+	 */
+	static inline const char *optional(ContextPtr ctx, int index, const char *defaultValue)
+	{
+		return is(ctx, index) ? get(ctx, index) : defaultValue;
+	}
+
+	/**
+	 * Push a string.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(ContextPtr ctx, const char *value)
+	{
+		duk_push_string(ctx, value);
+	}
+
+	/**
+	 * Require a string, throws a JavaScript exception if not a string.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the string
+	 */
+	static inline const char *require(ContextPtr ctx, int index)
+	{
+		return duk_require_string(ctx, index);
+	}
+};
+
+/**
+ * @brief Implementation for non-managed pointers.
+ *
+ * Provides: get, is, optional, push, require.
+ */
+template <typename T>
+class TypeTraits<RawPointer<T>> {
+public:
+	/**
+	 * Get a pointer, return nullptr if not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the pointer
+	 */
+	static inline T *get(ContextPtr ctx, int index)
+	{
+		return static_cast<T *>(duk_to_pointer(ctx, index));
+	}
+
+	/**
+	 * Check if value is a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if pointer
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_pointer(ctx, index);
+	}
+
+	/**
+	 * Get a pointer, return defaultValue if the value is not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @param defaultValue the defaultValue
+	 * @return the pointer or defaultValue
+	 */
+	static inline T *optional(ContextPtr ctx, int index, RawPointer<T> defaultValue)
+	{
+		return is(ctx, index) ? get(ctx, index) : defaultValue.object;
+	}
+
+	/**
+	 * Push a pointer.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static inline void push(ContextPtr ctx, const RawPointer<T> &value)
+	{
+		duk_push_pointer(ctx, value.object);
+	}
+
+	/**
+	 * Require a pointer, throws a JavaScript exception if not a pointer.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return the pointer
+	 */
+	static inline T *require(ContextPtr ctx, int index)
+	{
+		return static_cast<T *>(duk_require_pointer(ctx, index));
+	}
+};
+
+/**
+ * @class TypeTraits<Function>
+ * @brief Push C++ function to the stack.
+ *
+ * Provides: push.
+ *
+ * This implementation push a Duktape/C function that is wrapped as C++ for convenience.
+ */
+template <>
+class TypeTraits<Function> {
+public:
+	/**
+	 * Check if the value at the given index is callable.
+	 *
+	 * @param ctx the context
+	 * @param index the value index
+	 * @return true if the value is callable
+	 */
+	static bool is(ContextPtr ctx, Index index)
+	{
+		return duk_is_callable(ctx, index);
+	}
+
+	/**
+	 * Push the C++ function, it is wrapped as Duktape/C function and allocated on the heap by moving the
+	 * std::function.
+	 *
+	 * @param ctx the context
+	 * @param fn the function
+	 */
+	static void push(ContextPtr ctx, Function fn)
+	{
+		duk_push_c_function(ctx, fn.function, fn.nargs);
+	}
+};
+
+/**
+ * @class TypeTraits<FunctionMap>
+ * @brief Put the functions to the object at the top of the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeTraits<FunctionMap> {
+public:
+	/**
+	 * Push all functions to the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param map the map of function
+	 */
+	static inline void push(ContextPtr ctx, const FunctionMap &map)
+	{
+		StackAssert sa(ctx, 0);
+
+		for (const auto &entry : map) {
+			duk_push_c_function(ctx, entry.second.function, entry.second.nargs);
+			duk_put_prop_string(ctx, -2, entry.first.c_str());
+		}
+	}
+};
+
+/**
+ * @class TypeTraits<Object>
+ * @brief Push empty object to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeTraits<Object> {
+public:
+	/**
+	 * Check if value is an object.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if object
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_object(ctx, index);
+	}
+
+	/**
+	 * Create an empty object on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(ContextPtr ctx, const Object &)
+	{
+		duk_push_object(ctx);
+	}
+};
+
+/**
+ * @class TypeTraits<Array>
+ * @brief Push empty array to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeTraits<Array> {
+public:
+	/**
+	 * Check if value is a array.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if array
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_array(ctx, index);
+	}
+
+	/**
+	 * Create an empty array on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(ContextPtr ctx, const Array &)
+	{
+		duk_push_array(ctx);
+	}
+};
+
+/**
+ * @class TypeTraits<Undefined>
+ * @brief Push undefined value to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeTraits<Undefined> {
+public:
+	/**
+	 * Check if value is undefined.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if undefined
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_undefined(ctx, index);
+	}
+
+	/**
+	 * Push undefined value on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(ContextPtr ctx, const Undefined &)
+	{
+		duk_push_undefined(ctx);
+	}
+};
+
+/**
+ * @class TypeTraits<Null>
+ * @brief Push null value to the stack.
+ *
+ * Provides: is, push.
+ */
+template <>
+class TypeTraits<Null> {
+public:
+	/**
+	 * Check if value is null.
+	 *
+	 * @param ctx the context
+	 * @param index the index
+	 * @return true if null
+	 */
+	static inline bool is(ContextPtr ctx, int index)
+	{
+		return duk_is_null(ctx, index);
+	}
+
+	/**
+	 * Push null value on the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(ContextPtr ctx, const Null &)
+	{
+		duk_push_null(ctx);
+	}
+};
+
+/**
+ * @brief Push this binding into the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeTraits<This> {
+public:
+	/**
+	 * Push this function into the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(ContextPtr ctx, const This &)
+	{
+		duk_push_this(ctx);
+	}
+};
+
+/**
+ * @class TypeTraits<Global>
+ * @brief Push the global object to the stack.
+ *
+ * Provides: push.
+ */
+template <>
+class TypeTraits<Global> {
+public:
+	/**
+	 * Push the global object into the stack.
+	 *
+	 * @param ctx the context
+	 */
+	static inline void push(ContextPtr ctx, const Global &)
+	{
+		duk_push_global_object(ctx);
+	}
+};
+
+/**
+ * @brief Push a map of key-value pair as objects.
+ *
+ * Provides: push.
+ *
+ * This class is convenient for settings constants such as enums, string and such.
+ */
+template <typename T>
+class TypeTraits<std::unordered_map<std::string, T>> {
+public:
+	/**
+	 * Put all values from the map as properties to the object at the top of the stack.
+	 *
+	 * @param ctx the context
+	 * @param map the values
+	 * @note You need an object at the top of the stack before calling this function
+	 */
+	static void push(ContextPtr ctx, const std::unordered_map<std::string, T> &map)
+	{
+		StackAssert sa(ctx, 0);
+
+		for (const auto &pair : map) {
+			TypeTraits<T>::push(ctx, pair.second);
+			duk_put_prop_string(ctx, -2, pair.first.c_str());
+		}
+	}
+};
+
+/**
+ * @brief Push or get vectors as JavaScript arrays.
+ *
+ * Provides: get, push.
+ */
+template <typename T>
+class TypeTraits<std::vector<T>> {
+public:
+	/**
+	 * Get an array from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the array index
+	 * @return the array or empty array if the value is not an array
+	 */
+	static std::vector<T> get(ContextPtr ctx, int index)
+	{
+		StackAssert sa(ctx, 0);
+
+		std::vector<T> result;
+
+		if (!duk_is_array(ctx, -1))
+			return result;
+
+		int total = duk_get_length(ctx, index);
+
+		for (int i = 0; i < total; ++i)
+			result.push_back(getProperty<T>(ctx, index, i));
+
+		return result;
+	}
+
+	/**
+	 * Create an array with the specified values.
+	 *
+	 * @param ctx the context
+	 * @param array the values
+	 */
+	static void push(ContextPtr ctx, const std::vector<T> &array)
+	{
+		StackAssert sa(ctx, 1);
+
+		duk_push_array(ctx);
+
+		unsigned i = 0;
+		for (const auto &v : array) {
+			TypeTraits<T>::push(ctx, v);
+			duk_put_prop_index(ctx, -2, i++);
+		}
+	}
+};
+
+/**
+ * @brief Implementation of managed shared_ptr
+ * @see Shared
+ */
+template <typename T>
+class TypeTraits<Shared<T>> {
+private:
+	static void apply(ContextPtr ctx, std::shared_ptr<T> value)
+	{
+		StackAssert sa(ctx, 0);
+
+		sign<T>(ctx, -1);
+
+		duk_push_pointer(ctx, new std::shared_ptr<T>(std::move(value)));
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-shared-ptr");
+		duk_push_c_function(ctx, [] (duk_context *ctx) -> Ret {
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-shared-ptr");
+			delete static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
+			duk_pop(ctx);
+			duk_push_null(ctx);
+			duk_put_prop_string(ctx, 0, "\xff""\xff""js-ptr");
+
+			return 0;
+		}, 1);
+		duk_set_finalizer(ctx, -2);
+	}
+
+public:
+	/**
+	 * Construct the shared_ptr as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void construct(ContextPtr ctx, Shared<T> value)
+	{
+		StackAssert sa(ctx, 0);
+
+		duk_push_this(ctx);
+		apply(ctx, std::move(value.object));
+		duk_pop(ctx);
+	}
+
+	/**
+	 * Push a managed shared_ptr as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void push(ContextPtr ctx, Shared<T> value)
+	{
+		StackAssert sa(ctx, 1);
+
+		duk_push_object(ctx);
+		apply(ctx, value.object);
+		TypeTraits<T>::prototype(ctx);
+		duk_set_prototype(ctx, -2);
+	}
+
+	/**
+	 * Get a managed shared_ptr from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the object index
+	 * @return the shared_ptr
+	 */
+	static std::shared_ptr<T> get(ContextPtr ctx, int index)
+	{
+		StackAssert sa(ctx, 0);
+
+		checkSignature<T>(ctx, index);
+
+		duk_get_prop_string(ctx, index, "\xff""\xff""js-shared-ptr");
+		std::shared_ptr<T> value = *static_cast<std::shared_ptr<T> *>(duk_to_pointer(ctx, -1));
+		duk_pop(ctx);
+
+		return value;
+	}
+};
+
+/**
+ * @brief Implementation of managed pointers
+ * @see Pointer
+ */
+template <typename T>
+class TypeTraits<Pointer<T>> {
+private:
+	static void apply(ContextPtr ctx, T *value)
+	{
+		StackAssert sa(ctx, 0);
+
+		sign<T>(ctx, -1);
+
+		duk_push_pointer(ctx, value);
+		duk_put_prop_string(ctx, -2, "\xff""\xff""js-ptr");
+		duk_push_c_function(ctx, [] (duk_context *ctx) -> Ret {
+			duk_get_prop_string(ctx, 0, "\xff""\xff""js-ptr");
+			delete static_cast<T *>(duk_to_pointer(ctx, -1));
+			duk_pop(ctx);
+			duk_push_null(ctx);
+			duk_put_prop_string(ctx, 0, "\xff""\xff""js-ptr");
+
+			return 0;
+		}, 1);
+		duk_set_finalizer(ctx, -2);
+	}
+
+public:
+	/**
+	 * Construct the pointer as this.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void construct(ContextPtr ctx, Pointer<T> value)
+	{
+		StackAssert sa(ctx, 0);
+
+		duk_push_this(ctx);
+		apply(ctx, value.object);
+		duk_pop(ctx);
+	}
+
+	/**
+	 * Push a managed pointer as object.
+	 *
+	 * @param ctx the context
+	 * @param value the value
+	 */
+	static void push(ContextPtr ctx, Pointer<T> value)
+	{
+		StackAssert sa(ctx, 1);
+
+		duk_push_object(ctx);
+		apply(ctx, value.object);
+		TypeTraits<T>::prototype(ctx);
+		duk_set_prototype(ctx, -2);
+	}
+
+	/**
+	 * Get a managed pointer from the stack.
+	 *
+	 * @param ctx the context
+	 * @param index the object index
+	 * @return the pointer
+	 * @warning Do not store the pointer into the C++ side, the object can be deleted at any time
+	 */
+	static T *get(ContextPtr ctx, int index)
+	{
+		StackAssert sa(ctx, 0);
+
+		checkSignature<T>(ctx, index);
+
+		duk_get_prop_string(ctx, index, "\xff""\xff""js-ptr");
+		T *value = static_cast<T *>(duk_to_pointer(ctx, -1));
+		duk_pop(ctx);
+
+		return value;
+	}
+};
+
+} // !duk
+
+} // !irccd
+
+#endif // !IRCCD_JS_HPP
--- a/lib/irccd/json.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/json.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -20,7 +20,7 @@
 
 #include <sstream>
 
-#include "json.h"
+#include "json.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/json.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1183 +0,0 @@
-/*
- * json.h -- C++14 JSON manipulation using jansson parser
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_JSON_H
-#define IRCCD_JSON_H
-
-/**
- * @file json.h
- * @brief Jansson C++14 wrapper
- *
- * These classes can be used to build or parse JSON documents using jansson library. It is designed to be safe
- * and explicit. It does not implement implicit sharing like jansson so when you access (e.g. Value::toObject) values
- * you get real copies, thus when you read big documents it can has a performance cost.
- */
-
-#include <cassert>
-#include <exception>
-#include <initializer_list>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace irccd {
-
-/**
- * Json namespace.
- */
-namespace json {
-
-/**
- * @enum Type
- * @brief Type of Value.
- */
-enum class Type {
-	Array,		//!< Value is an array []
-	Boolean,	//!< Value is boolean
-	Int,		//!< Value is integer
-	Null,		//!< Value is defined to null
-	Object,		//!< Value is object {}
-	Real,		//!< Value is float
-	String		//!< Value is unicode string
-};
-
-/**
- * @class Error
- * @brief Error description.
- */
-class Error : public std::exception {
-private:
-	std::string m_text;
-	std::string m_source;
-	int m_line;
-	int m_column;
-	int m_position;
-
-public:
-	/**
-	 * Create the error.
-	 *
-	 * @param text the text message
-	 * @param source the source (e.g. file name)
-	 * @param line the line number
-	 * @param column the column number
-	 * @param position the position
-	 */
-	inline Error(std::string text, std::string source, int line, int column, int position) noexcept
-		: m_text(std::move(text))
-		, m_source(std::move(source))
-		, m_line(line)
-		, m_column(column)
-		, m_position(position)
-	{
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the text
-	 */
-	inline const std::string &text() const noexcept
-	{
-		return m_text;
-	}
-
-	/**
-	 * Get the source (e.g. a file name).
-	 *
-	 * @return the source
-	 */
-	inline const std::string &source() const noexcept
-	{
-		return m_source;
-	}
-
-	/**
-	 * Get the line.
-	 *
-	 * @return the line
-	 */
-	inline int line() const noexcept
-	{
-		return m_line;
-	}
-
-	/**
-	 * Get the column.
-	 *
-	 * @return the column
-	 */
-	inline int column() const noexcept
-	{
-		return m_column;
-	}
-
-	/**
-	 * Get the position.
-	 *
-	 * @return the position
-	 */
-	inline int position() const noexcept
-	{
-		return m_position;
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the message
-	 */
-	const char *what() const noexcept override
-	{
-		return m_text.c_str();
-	}
-};
-
-/**
- * @class Buffer
- * @brief Open JSON document from text.
- */
-class Buffer {
-public:
-	std::string text;	//!< The JSON text
-};
-
-/**
- * @class File
- * @brief Open JSON document from a file.
- */
-class File {
-public:
-	std::string path;	//!< The path to the file
-};
-
-/**
- * @class Value
- * @brief Generic JSON value wrapper.
- */
-class Value {
-private:
-	Type m_type{Type::Null};
-
-	union {
-		double m_number;
-		bool m_boolean;
-		int m_integer;
-		std::string m_string;
-		std::vector<Value> m_array;
-		std::map<std::string, Value> m_object;
-	};
-
-	void copy(const Value &);
-	void move(Value &&);
-	std::string toJson(int indent, int current) const;
-
-	/**
-	 * @class BaseIterator
-	 * @brief This is the base class for iterator and const_iterator
-	 *
-	 * This iterator works for both arrays and objects. Because of that purpose, it is only available
-	 * as forward iterator.
-	 *
-	 * When iterator comes from an object, you can use key() otherwise you can use index().
-	 */
-	template <typename ValueType, typename ArrayIteratorType, typename ObjectIteratorType>
-	class BaseIterator : public std::iterator<std::forward_iterator_tag, ValueType> {
-	private:
-		friend class Value;
-
-		ValueType &m_value;
-		ArrayIteratorType m_ita;
-		ObjectIteratorType m_itm;
-
-		inline void increment()
-		{
-			if (m_value.isObject())
-				m_itm++;
-			else
-				m_ita++;
-		}
-
-		BaseIterator(ValueType &value, ObjectIteratorType it)
-			: m_value(value)
-			, m_itm(it)
-		{
-		}
-
-		BaseIterator(ValueType &value, ArrayIteratorType it)
-			: m_value(value)
-			, m_ita(it)
-		{
-		}
-
-	public:
-		/**
-		 * Get the iterator key (for objects).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @pre iterator must come from object
-		 * @return the key
-		 */
-		inline const std::string &key() const noexcept
-		{
-			assert(m_value.isObject());
-			assert(m_itm != m_value.m_object.end());
-
-			return m_itm->first;
-		}
-
-		/**
-		 * Get the iterator position (for arrays).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @pre iterator must come from arrays
-		 * @return the index
-		 */
-		inline unsigned index() const noexcept
-		{
-			assert(m_value.isArray());
-			assert(m_ita != m_value.m_array.end());
-
-			return std::distance(m_value.m_array.begin(), m_ita);
-		}
-
-		/**
-		 * Dereference the iterator.
-		 *
-		 * @pre iterator be dereferenceable
-		 * @return the value
-		 */
-		inline ValueType &operator*() noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			return (m_value.m_type == Type::Object) ? m_itm->second : *m_ita;
-		}
-
-		/**
-		 * Dereference the iterator as a pointer.
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @return the value
-		 */
-		inline ValueType *operator->() noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			return (m_value.m_type == Type::Object) ? &m_itm->second : &(*m_ita);
-		}
-
-		/**
-		 * Increment the iterator. (Prefix version).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @return *this;
-		 */
-		inline BaseIterator &operator++() noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			increment();
-
-			return *this;
-		}
-
-		/**
-		 * Increment the iterator. (Postfix version).
-		 *
-		 * @pre iterator must be dereferenceable
-		 * @return *this;
-		 */
-		inline BaseIterator &operator++(int) noexcept
-		{
-			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
-			       (m_value.isObject() && m_itm != m_value.m_object.end()));
-
-			increment();
-
-			return *this;
-		}
-
-		/**
-		 * Compare two iterators.
-		 *
-		 * @param it1 the first iterator
-		 * @param it2 the second iterator
-		 * @return true if they are same
-		 */
-		bool operator==(const BaseIterator &it) const noexcept
-		{
-			if (m_value.isObject() && it.m_value.isObject())
-				return m_itm == it.m_itm;
-			if (m_value.isArray() && it.m_value.isArray())
-				return m_ita == it.m_ita;
-
-			return false;
-		}
-
-		/**
-		 * Test if the iterator is different.
-		 *
-		 * @param it the iterator
-		 * @return true if they are different
-		 */
-		inline bool operator!=(const BaseIterator &it) const noexcept
-		{
-			return !(*this == it);
-		}
-	};
-
-public:
-	/**
-	 * Forward iterator.
-	 */
-	using iterator = BaseIterator<Value, typename std::vector<Value>::iterator, typename std::map<std::string, Value>::iterator>;
-
-	/**
-	 * Const forward iterator.
-	 */
-	using const_iterator = BaseIterator<const Value, typename std::vector<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>;
-
-	/**
-	 * Construct a null value.
-	 */
-	inline Value()
-	{
-	}
-
-	/**
-	 * Create a value with a specified type, this is usually only needed when you want to create an object or
-	 * an array.
-	 *
-	 * For any other types, initialize with sane default value.
-	 *
-	 * @param type the type
-	 */
-	Value(Type type);
-
-	/**
-	 * Construct a null value.
-	 */
-	inline Value(std::nullptr_t) noexcept
-		: m_type(Type::Null)
-	{
-	}
-
-	/**
-	 * Construct a boolean value.
-	 *
-	 * @param value the boolean value
-	 */
-	inline Value(bool value) noexcept
-		: m_type(Type::Boolean)
-		, m_boolean(value)
-	{
-	}
-
-	/**
-	 * Create value from integer.
-	 *
-	 * @param value the value
-	 */
-	inline Value(int value) noexcept
-		: m_type(Type::Int)
-		, m_integer(value)
-	{
-	}
-
-	/**
-	 * Construct a value from a C-string.
-	 *
-	 * @param value the C-string
-	 */
-	inline Value(const char *value)
-		: m_type(Type::String)
-	{
-		new (&m_string) std::string(value ? value : "");
-	}
-
-	/**
-	 * Construct a number value.
-	 *
-	 * @param value the real value
-	 */
-	inline Value(double value) noexcept
-		: m_type(Type::Real)
-		, m_number(value)
-	{
-	}
-
-	/**
-	 * Construct a string value.
-	 *
-	 * @param value the string
-	 */
-	inline Value(std::string value) noexcept
-		: m_type(Type::String)
-	{
-		new (&m_string) std::string(std::move(value));
-	}
-
-	/**
-	 * Create an object from a map.
-	 *
-	 * @param values the values
-	 * @see fromObject
-	 */
-	inline Value(std::map<std::string, Value> values)
-		: Value(Type::Object)
-	{
-		for (const auto &pair : values)
-			insert(pair.first, pair.second);
-	}
-
-	/**
-	 * Create an array from a vector.
-	 *
-	 * @param values the values
-	 * @see fromArray
-	 */
-	inline Value(std::vector<Value> values)
-		: Value(Type::Array)
-	{
-		for (Value value : values)
-			append(std::move(value));
-	}
-
-	/**
-	 * Construct a value from a buffer.
-	 *
-	 * @param buffer the text
-	 * @throw Error on errors
-	 */
-	Value(const Buffer &buffer);
-
-	/**
-	 * Construct a value from a file.
-	 *
-	 * @param file the file
-	 * @throw Error on errors
-	 */
-	Value(const File &file);
-
-	/**
-	 * Move constructor.
-	 *
-	 * @param other the value to move from
-	 */
-	inline Value(Value &&other)
-	{
-		move(std::move(other));
-	}
-
-	/**
-	 * Copy constructor.
-	 *
-	 * @param other the value to copy from
-	 */
-	inline Value(const Value &other)
-	{
-		copy(other);
-	}
-
-	/**
-	 * Copy operator.
-	 *
-	 * @param other the value to copy from
-	 * @return *this
-	 */
-	inline Value &operator=(const Value &other)
-	{
-		copy(other);
-
-		return *this;
-	}
-
-	/**
-	 * Move operator.
-	 *
-	 * @param other the value to move from
-	 */
-	inline Value &operator=(Value &&other)
-	{
-		move(std::move(other));
-
-		return *this;
-	}
-
-	/**
-	 * Destructor.
-	 */
-	~Value();
-
-	/**
-	 * Get an iterator to the beginning.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline iterator begin() noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? iterator(*this, m_object.begin()) : iterator(*this, m_array.begin());
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator begin() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.begin()) : const_iterator(*this, m_array.begin());
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator cbegin() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.cbegin()) : const_iterator(*this, m_array.cbegin());
-	}
-
-	/**
-	 * Get an iterator to the end.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline iterator end() noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? iterator(*this, m_object.end()) : iterator(*this, m_array.end());
-	}
-
-	/**
-	 * Get an iterator to the end.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator end() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.end()) : const_iterator(*this, m_array.end());
-	}
-
-	/**
-	 * Get an iterator to the end.
-	 *
-	 * @pre must be an array or object
-	 * @return the iterator
-	 */
-	inline const_iterator cend() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		return m_type == Type::Object ? const_iterator(*this, m_object.cend()) : const_iterator(*this, m_array.cend());
-	}
-
-	/**
-	 * Get the value type.
-	 *
-	 * @return the type
-	 */
-	inline Type typeOf() const noexcept
-	{
-		return m_type;
-	}
-
-	/**
-	 * Get the value as boolean.
-	 *
-	 * @return the value or false if not a boolean
-	 */
-	bool toBool() const noexcept;
-
-	/**
-	 * Get the value as integer.
-	 *
-	 * @return the value or 0 if not a integer
-	 */
-	int toInt() const noexcept;
-
-	/**
-	 * Get the value as real.
-	 *
-	 * @return the value or 0 if not a real
-	 */
-	double toReal() const noexcept;
-
-	/**
-	 * Get the value as string.
-	 *
-	 * @param coerce set to true to coerce the value if not a string
-	 * @return the value or empty string if not a string
-	 */
-	std::string toString(bool coerce = false) const noexcept;
-
-	/**
-	 * Check if the value is boolean type.
-	 *
-	 * @return true if boolean
-	 */
-	inline bool isBool() const noexcept
-	{
-		return m_type == Type::Boolean;
-	}
-
-	/**
-	 * Check if the value is integer type.
-	 *
-	 * @return true if integer
-	 */
-	inline bool isInt() const noexcept
-	{
-		return m_type == Type::Int;
-	}
-
-	/**
-	 * Check if the value is object type.
-	 *
-	 * @return true if object
-	 */
-	inline bool isObject() const noexcept
-	{
-		return m_type == Type::Object;
-	}
-
-	/**
-	 * Check if the value is array type.
-	 *
-	 * @return true if array
-	 */
-	inline bool isArray() const noexcept
-	{
-		return m_type == Type::Array;
-	}
-
-	/**
-	 * Check if the value is integer or real type.
-	 *
-	 * @return true if integer or real
-	 * @see toInt
-	 * @see toReal
-	 */
-	inline bool isNumber() const noexcept
-	{
-		return m_type == Type::Real || m_type == Type::Int;
-	}
-
-	/**
-	 * Check if the value is real type.
-	 *
-	 * @return true if real
-	 */
-	inline bool isReal() const noexcept
-	{
-		return m_type == Type::Real;
-	}
-
-	/**
-	 * Check if the value is null type.
-	 *
-	 * @return true if null
-	 */
-	inline bool isNull() const noexcept
-	{
-		return m_type == Type::Null;
-	}
-
-	/**
-	 * Check if the value is string type.
-	 *
-	 * @return true if string
-	 */
-	inline bool isString() const noexcept
-	{
-		return m_type == Type::String;
-	}
-
-	/**
-	 * Get the array or object size.
-	 *
-	 * @pre must be an array or object
-	 * @return the size
-	 */
-	inline unsigned size() const noexcept
-	{
-		assert(isArray() || isObject());
-
-		if (m_type == Type::Object)
-			return m_object.size();
-
-		return m_array.size();
-	}
-
-	/**
-	 * Remove all the values.
-	 *
-	 * @pre must be an array or an object
-	 */
-	inline void clear() noexcept
-	{
-		assert(isArray() || isObject());
-
-		if (m_type == Type::Array)
-			m_array.clear();
-		else
-			m_object.clear();
-	}
-
-	/*
-	 * Array functions
-	 * ----------------------------------------------------------
-	 */
-
-	/**
-	 * Get the value at the specified position or the defaultValue if position is out of bounds.
-	 *
-	 * @param position the position
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename DefaultValue>
-	inline Value valueOr(unsigned position, DefaultValue &&defaultValue) const
-	{
-		if (m_type != Type::Array || position >= m_array.size())
-			return defaultValue;
-
-		return m_array[position];
-	}
-
-	/**
-	 * Overloaded function with type check.
-	 *
-	 * @param position the position
-	 * @param type the requested type
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename DefaultValue>
-	inline Value valueOr(unsigned position, Type type, DefaultValue &&defaultValue) const
-	{
-		if (m_type != Type::Array || position >= m_array.size() || m_array[position].typeOf() != type)
-			return defaultValue;
-
-		return m_array[position];
-	}
-
-	/**
-	 * Get a value at the specified index.
-	 *
-	 * @pre must be an array
-	 * @param position the position
-	 * @return the value
-	 * @throw std::out_of_range if out of bounds
-	 */
-	inline const Value &at(unsigned position) const
-	{
-		assert(isArray());
-
-		return m_array.at(position);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @param position the position
-	 * @return the value
-	 * @throw std::out_of_range if out of bounds
-	 */
-	inline Value &at(unsigned position)
-	{
-		assert(isArray());
-
-		return m_array.at(position);
-	}
-
-	/**
-	 * Get a value at the specified index.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @return the value
-	 */
-	inline const Value &operator[](unsigned position) const
-	{
-		assert(isArray());
-		assert(position < m_array.size());
-
-		return m_array[position];
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @return the value
-	 */
-	inline Value &operator[](unsigned position)
-	{
-		assert(isArray());
-		assert(position < m_array.size());
-
-		return m_array[position];
-	}
-
-	/**
-	 * Push a value to the beginning of the array.
-	 *
-	 * @pre must be an array
-	 * @param value the value to push
-	 */
-	inline void push(const Value &value)
-	{
-		assert(isArray());
-
-		m_array.insert(m_array.begin(), value);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @param value the value to push
-	 */
-	inline void push(Value &&value)
-	{
-		assert(isArray());
-
-		m_array.insert(m_array.begin(), std::move(value));
-	}
-
-	/**
-	 * Insert a value at the specified position.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @param value the value to push
-	 */
-	inline void insert(unsigned position, const Value &value)
-	{
-		assert(isArray());
-		assert(position <= m_array.size());
-
-		m_array.insert(m_array.begin() + position, value);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 * @param value the value to push
-	 */
-	inline void insert(unsigned position, Value &&value)
-	{
-		assert(isArray());
-		assert(position <= m_array.size());
-
-		m_array.insert(m_array.begin() + position, std::move(value));
-	}
-
-	/**
-	 * Add a new value to the end.
-	 *
-	 * @pre must be an array
-	 * @param value the value to append
-	 */
-	inline void append(const Value &value)
-	{
-		assert(isArray());
-
-		m_array.push_back(value);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an array
-	 * @param value the value to append
-	 */
-	inline void append(Value &&value)
-	{
-		assert(isArray());
-
-		m_array.push_back(std::move(value));
-	}
-
-	/**
-	 * Remove a value at the specified position.
-	 *
-	 * @pre must be an array
-	 * @pre position must be valid
-	 * @param position the position
-	 */
-	inline void erase(unsigned position)
-	{
-		assert(isArray());
-		assert(position < m_array.size());
-
-		m_array.erase(m_array.begin() + position);
-	}
-
-	/*
-	 * Object functions
-	 * ----------------------------------------------------------
-	 */
-
-	/**
-	 * Get the value at the specified key or the defaultValue if key is absent.
-	 *
-	 * @param name the name
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename DefaultValue>
-	Value valueOr(const std::string &name, DefaultValue &&defaultValue) const
-	{
-		if (m_type != Type::Object)
-			return defaultValue;
-
-		auto it = m_object.find(name);
-
-		if (it == m_object.end())
-			return defaultValue;
-
-		return it->second;
-	}
-
-	/**
-	 * Overloaded function with type check.
-	 *
-	 * @param name the name
-	 * @param type the requested type
-	 * @param defaultValue the value replacement
-	 * @return the value or defaultValue
-	 */
-	template <typename DefaultValue>
-	Value valueOr(const std::string &name, Type type, DefaultValue &&defaultValue) const
-	{
-		if (m_type != Type::Object)
-			return defaultValue;
-
-		auto it = m_object.find(name);
-
-		if (it == m_object.end() || it->second.typeOf() != type)
-			return defaultValue;
-
-		return it->second;
-	}
-
-	/**
-	 * Get a value from the object.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 * @throw std::out_of_range if not found
-	 */
-	inline const Value &at(const std::string &name) const
-	{
-		assert(isObject());
-
-		return m_object.at(name);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 * @throw std::out_of_range if not found
-	 */
-	inline Value &at(const std::string &name)
-	{
-		assert(isObject());
-
-		return m_object.at(name);
-	}
-
-	/**
-	 * Get a value from the object.
-	 *
-	 * @pre must be an object
-	 * @param name the value key
-	 * @return the value
-	 */
-	inline Value &operator[](const std::string &name)
-	{
-		assert(isObject());
-
-		return m_object[name];
-	}
-
-	/**
-	 * Find a value by key.
-	 *
-	 * @pre must be an object
-	 * @param key the property key
-	 * @return the iterator or past the end if not found
-	 */
-	inline iterator find(const std::string &key)
-	{
-		assert(isObject());
-
-		return iterator(*this, m_object.find(key));
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an object
-	 * @param key the property key
-	 * @return the iterator or past the end if not found
-	 */
-	inline const_iterator find(const std::string &key) const
-	{
-		assert(isObject());
-
-		return const_iterator(*this, m_object.find(key));
-	}
-
-	/**
-	 * Insert a new value.
-	 *
-	 * @pre must be an object
-	 * @param name the key
-	 * @param value the value
-	 */
-	inline void insert(std::string name, const Value &value)
-	{
-		assert(isObject());
-
-		m_object.insert({std::move(name), value});
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @pre must be an object
-	 * @param name the key
-	 * @param value the value
-	 */
-	inline void insert(std::string name, Value &&value)
-	{
-		assert(isObject());
-
-		m_object.insert({std::move(name), std::move(value)});
-	}
-
-	/**
-	 * Check if a value exists.
-	 *
-	 * @pre must be an object
-	 * @param key the key value
-	 * @return true if exists
-	 */
-	inline bool contains(const std::string &key) const noexcept
-	{
-		assert(isObject());
-
-		return m_object.find(key) != m_object.end();
-	}
-
-	/**
-	 * Remove a value of the specified key.
-	 *
-	 * @pre must be an object
-	 * @param key the value key
-	 */
-	inline void erase(const std::string &key)
-	{
-		assert(isObject());
-
-		m_object.erase(key);
-	}
-
-	/**
-	 * Return this value as JSon representation.
-	 *
-	 * @param indent, the indentation to use (0 == compact, < 0 == tabs, > 0 == number of spaces)
-	 * @param tabs, use tabs or not
-	 * @return the string
-	 */
-	inline std::string toJson(int indent = 2) const
-	{
-		return toJson(indent, 0);
-	}
-};
-
-/**
- * Escape the input.
- *
- * @param input the input
- * @return the escaped string
- */
-std::string escape(const std::string &input);
-
-/**
- * Convenient function for creating array from initializer list.
- *
- * @param values the values
- * @return the array
- */
-inline Value array(std::initializer_list<Value> values)
-{
-	return Value(std::vector<Value>(values.begin(), values.end()));
-}
-
-/**
- * Convenient function for creating object from initializer list.
- *
- * @param values the values
- * @return the object
- */
-inline Value object(std::initializer_list<std::pair<std::string, Value>> values)
-{
-	return Value(std::map<std::string, Value>(values.begin(), values.end()));
-}
-
-} // !json
-
-} // !irccd
-
-#endif // !IRCCD_JSON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/json.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,1183 @@
+/*
+ * json.hpp -- C++14 JSON manipulation using jansson parser
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JSON_HPP
+#define IRCCD_JSON_HPP
+
+/**
+ * @file json.hpp
+ * @brief Jansson C++14 wrapper
+ *
+ * These classes can be used to build or parse JSON documents using jansson library. It is designed to be safe
+ * and explicit. It does not implement implicit sharing like jansson so when you access (e.g. Value::toObject) values
+ * you get real copies, thus when you read big documents it can has a performance cost.
+ */
+
+#include <cassert>
+#include <exception>
+#include <initializer_list>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace irccd {
+
+/**
+ * Json namespace.
+ */
+namespace json {
+
+/**
+ * @enum Type
+ * @brief Type of Value.
+ */
+enum class Type {
+	Array,		//!< Value is an array []
+	Boolean,	//!< Value is boolean
+	Int,		//!< Value is integer
+	Null,		//!< Value is defined to null
+	Object,		//!< Value is object {}
+	Real,		//!< Value is float
+	String		//!< Value is unicode string
+};
+
+/**
+ * @class Error
+ * @brief Error description.
+ */
+class Error : public std::exception {
+private:
+	std::string m_text;
+	std::string m_source;
+	int m_line;
+	int m_column;
+	int m_position;
+
+public:
+	/**
+	 * Create the error.
+	 *
+	 * @param text the text message
+	 * @param source the source (e.g. file name)
+	 * @param line the line number
+	 * @param column the column number
+	 * @param position the position
+	 */
+	inline Error(std::string text, std::string source, int line, int column, int position) noexcept
+		: m_text(std::move(text))
+		, m_source(std::move(source))
+		, m_line(line)
+		, m_column(column)
+		, m_position(position)
+	{
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the text
+	 */
+	inline const std::string &text() const noexcept
+	{
+		return m_text;
+	}
+
+	/**
+	 * Get the source (e.g. a file name).
+	 *
+	 * @return the source
+	 */
+	inline const std::string &source() const noexcept
+	{
+		return m_source;
+	}
+
+	/**
+	 * Get the line.
+	 *
+	 * @return the line
+	 */
+	inline int line() const noexcept
+	{
+		return m_line;
+	}
+
+	/**
+	 * Get the column.
+	 *
+	 * @return the column
+	 */
+	inline int column() const noexcept
+	{
+		return m_column;
+	}
+
+	/**
+	 * Get the position.
+	 *
+	 * @return the position
+	 */
+	inline int position() const noexcept
+	{
+		return m_position;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the message
+	 */
+	const char *what() const noexcept override
+	{
+		return m_text.c_str();
+	}
+};
+
+/**
+ * @class Buffer
+ * @brief Open JSON document from text.
+ */
+class Buffer {
+public:
+	std::string text;	//!< The JSON text
+};
+
+/**
+ * @class File
+ * @brief Open JSON document from a file.
+ */
+class File {
+public:
+	std::string path;	//!< The path to the file
+};
+
+/**
+ * @class Value
+ * @brief Generic JSON value wrapper.
+ */
+class Value {
+private:
+	Type m_type{Type::Null};
+
+	union {
+		double m_number;
+		bool m_boolean;
+		int m_integer;
+		std::string m_string;
+		std::vector<Value> m_array;
+		std::map<std::string, Value> m_object;
+	};
+
+	void copy(const Value &);
+	void move(Value &&);
+	std::string toJson(int indent, int current) const;
+
+	/**
+	 * @class BaseIterator
+	 * @brief This is the base class for iterator and const_iterator
+	 *
+	 * This iterator works for both arrays and objects. Because of that purpose, it is only available
+	 * as forward iterator.
+	 *
+	 * When iterator comes from an object, you can use key() otherwise you can use index().
+	 */
+	template <typename ValueType, typename ArrayIteratorType, typename ObjectIteratorType>
+	class BaseIterator : public std::iterator<std::forward_iterator_tag, ValueType> {
+	private:
+		friend class Value;
+
+		ValueType &m_value;
+		ArrayIteratorType m_ita;
+		ObjectIteratorType m_itm;
+
+		inline void increment()
+		{
+			if (m_value.isObject())
+				m_itm++;
+			else
+				m_ita++;
+		}
+
+		BaseIterator(ValueType &value, ObjectIteratorType it)
+			: m_value(value)
+			, m_itm(it)
+		{
+		}
+
+		BaseIterator(ValueType &value, ArrayIteratorType it)
+			: m_value(value)
+			, m_ita(it)
+		{
+		}
+
+	public:
+		/**
+		 * Get the iterator key (for objects).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @pre iterator must come from object
+		 * @return the key
+		 */
+		inline const std::string &key() const noexcept
+		{
+			assert(m_value.isObject());
+			assert(m_itm != m_value.m_object.end());
+
+			return m_itm->first;
+		}
+
+		/**
+		 * Get the iterator position (for arrays).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @pre iterator must come from arrays
+		 * @return the index
+		 */
+		inline unsigned index() const noexcept
+		{
+			assert(m_value.isArray());
+			assert(m_ita != m_value.m_array.end());
+
+			return std::distance(m_value.m_array.begin(), m_ita);
+		}
+
+		/**
+		 * Dereference the iterator.
+		 *
+		 * @pre iterator be dereferenceable
+		 * @return the value
+		 */
+		inline ValueType &operator*() noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			return (m_value.m_type == Type::Object) ? m_itm->second : *m_ita;
+		}
+
+		/**
+		 * Dereference the iterator as a pointer.
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @return the value
+		 */
+		inline ValueType *operator->() noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			return (m_value.m_type == Type::Object) ? &m_itm->second : &(*m_ita);
+		}
+
+		/**
+		 * Increment the iterator. (Prefix version).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @return *this;
+		 */
+		inline BaseIterator &operator++() noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			increment();
+
+			return *this;
+		}
+
+		/**
+		 * Increment the iterator. (Postfix version).
+		 *
+		 * @pre iterator must be dereferenceable
+		 * @return *this;
+		 */
+		inline BaseIterator &operator++(int) noexcept
+		{
+			assert((m_value.isArray()  && m_ita != m_value.m_array.end()) ||
+			       (m_value.isObject() && m_itm != m_value.m_object.end()));
+
+			increment();
+
+			return *this;
+		}
+
+		/**
+		 * Compare two iterators.
+		 *
+		 * @param it1 the first iterator
+		 * @param it2 the second iterator
+		 * @return true if they are same
+		 */
+		bool operator==(const BaseIterator &it) const noexcept
+		{
+			if (m_value.isObject() && it.m_value.isObject())
+				return m_itm == it.m_itm;
+			if (m_value.isArray() && it.m_value.isArray())
+				return m_ita == it.m_ita;
+
+			return false;
+		}
+
+		/**
+		 * Test if the iterator is different.
+		 *
+		 * @param it the iterator
+		 * @return true if they are different
+		 */
+		inline bool operator!=(const BaseIterator &it) const noexcept
+		{
+			return !(*this == it);
+		}
+	};
+
+public:
+	/**
+	 * Forward iterator.
+	 */
+	using iterator = BaseIterator<Value, typename std::vector<Value>::iterator, typename std::map<std::string, Value>::iterator>;
+
+	/**
+	 * Const forward iterator.
+	 */
+	using const_iterator = BaseIterator<const Value, typename std::vector<Value>::const_iterator, typename std::map<std::string, Value>::const_iterator>;
+
+	/**
+	 * Construct a null value.
+	 */
+	inline Value()
+	{
+	}
+
+	/**
+	 * Create a value with a specified type, this is usually only needed when you want to create an object or
+	 * an array.
+	 *
+	 * For any other types, initialize with sane default value.
+	 *
+	 * @param type the type
+	 */
+	Value(Type type);
+
+	/**
+	 * Construct a null value.
+	 */
+	inline Value(std::nullptr_t) noexcept
+		: m_type(Type::Null)
+	{
+	}
+
+	/**
+	 * Construct a boolean value.
+	 *
+	 * @param value the boolean value
+	 */
+	inline Value(bool value) noexcept
+		: m_type(Type::Boolean)
+		, m_boolean(value)
+	{
+	}
+
+	/**
+	 * Create value from integer.
+	 *
+	 * @param value the value
+	 */
+	inline Value(int value) noexcept
+		: m_type(Type::Int)
+		, m_integer(value)
+	{
+	}
+
+	/**
+	 * Construct a value from a C-string.
+	 *
+	 * @param value the C-string
+	 */
+	inline Value(const char *value)
+		: m_type(Type::String)
+	{
+		new (&m_string) std::string(value ? value : "");
+	}
+
+	/**
+	 * Construct a number value.
+	 *
+	 * @param value the real value
+	 */
+	inline Value(double value) noexcept
+		: m_type(Type::Real)
+		, m_number(value)
+	{
+	}
+
+	/**
+	 * Construct a string value.
+	 *
+	 * @param value the string
+	 */
+	inline Value(std::string value) noexcept
+		: m_type(Type::String)
+	{
+		new (&m_string) std::string(std::move(value));
+	}
+
+	/**
+	 * Create an object from a map.
+	 *
+	 * @param values the values
+	 * @see fromObject
+	 */
+	inline Value(std::map<std::string, Value> values)
+		: Value(Type::Object)
+	{
+		for (const auto &pair : values)
+			insert(pair.first, pair.second);
+	}
+
+	/**
+	 * Create an array from a vector.
+	 *
+	 * @param values the values
+	 * @see fromArray
+	 */
+	inline Value(std::vector<Value> values)
+		: Value(Type::Array)
+	{
+		for (Value value : values)
+			append(std::move(value));
+	}
+
+	/**
+	 * Construct a value from a buffer.
+	 *
+	 * @param buffer the text
+	 * @throw Error on errors
+	 */
+	Value(const Buffer &buffer);
+
+	/**
+	 * Construct a value from a file.
+	 *
+	 * @param file the file
+	 * @throw Error on errors
+	 */
+	Value(const File &file);
+
+	/**
+	 * Move constructor.
+	 *
+	 * @param other the value to move from
+	 */
+	inline Value(Value &&other)
+	{
+		move(std::move(other));
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the value to copy from
+	 */
+	inline Value(const Value &other)
+	{
+		copy(other);
+	}
+
+	/**
+	 * Copy operator.
+	 *
+	 * @param other the value to copy from
+	 * @return *this
+	 */
+	inline Value &operator=(const Value &other)
+	{
+		copy(other);
+
+		return *this;
+	}
+
+	/**
+	 * Move operator.
+	 *
+	 * @param other the value to move from
+	 */
+	inline Value &operator=(Value &&other)
+	{
+		move(std::move(other));
+
+		return *this;
+	}
+
+	/**
+	 * Destructor.
+	 */
+	~Value();
+
+	/**
+	 * Get an iterator to the beginning.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline iterator begin() noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? iterator(*this, m_object.begin()) : iterator(*this, m_array.begin());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator begin() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.begin()) : const_iterator(*this, m_array.begin());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator cbegin() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.cbegin()) : const_iterator(*this, m_array.cbegin());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline iterator end() noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? iterator(*this, m_object.end()) : iterator(*this, m_array.end());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator end() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.end()) : const_iterator(*this, m_array.end());
+	}
+
+	/**
+	 * Get an iterator to the end.
+	 *
+	 * @pre must be an array or object
+	 * @return the iterator
+	 */
+	inline const_iterator cend() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		return m_type == Type::Object ? const_iterator(*this, m_object.cend()) : const_iterator(*this, m_array.cend());
+	}
+
+	/**
+	 * Get the value type.
+	 *
+	 * @return the type
+	 */
+	inline Type typeOf() const noexcept
+	{
+		return m_type;
+	}
+
+	/**
+	 * Get the value as boolean.
+	 *
+	 * @return the value or false if not a boolean
+	 */
+	bool toBool() const noexcept;
+
+	/**
+	 * Get the value as integer.
+	 *
+	 * @return the value or 0 if not a integer
+	 */
+	int toInt() const noexcept;
+
+	/**
+	 * Get the value as real.
+	 *
+	 * @return the value or 0 if not a real
+	 */
+	double toReal() const noexcept;
+
+	/**
+	 * Get the value as string.
+	 *
+	 * @param coerce set to true to coerce the value if not a string
+	 * @return the value or empty string if not a string
+	 */
+	std::string toString(bool coerce = false) const noexcept;
+
+	/**
+	 * Check if the value is boolean type.
+	 *
+	 * @return true if boolean
+	 */
+	inline bool isBool() const noexcept
+	{
+		return m_type == Type::Boolean;
+	}
+
+	/**
+	 * Check if the value is integer type.
+	 *
+	 * @return true if integer
+	 */
+	inline bool isInt() const noexcept
+	{
+		return m_type == Type::Int;
+	}
+
+	/**
+	 * Check if the value is object type.
+	 *
+	 * @return true if object
+	 */
+	inline bool isObject() const noexcept
+	{
+		return m_type == Type::Object;
+	}
+
+	/**
+	 * Check if the value is array type.
+	 *
+	 * @return true if array
+	 */
+	inline bool isArray() const noexcept
+	{
+		return m_type == Type::Array;
+	}
+
+	/**
+	 * Check if the value is integer or real type.
+	 *
+	 * @return true if integer or real
+	 * @see toInt
+	 * @see toReal
+	 */
+	inline bool isNumber() const noexcept
+	{
+		return m_type == Type::Real || m_type == Type::Int;
+	}
+
+	/**
+	 * Check if the value is real type.
+	 *
+	 * @return true if real
+	 */
+	inline bool isReal() const noexcept
+	{
+		return m_type == Type::Real;
+	}
+
+	/**
+	 * Check if the value is null type.
+	 *
+	 * @return true if null
+	 */
+	inline bool isNull() const noexcept
+	{
+		return m_type == Type::Null;
+	}
+
+	/**
+	 * Check if the value is string type.
+	 *
+	 * @return true if string
+	 */
+	inline bool isString() const noexcept
+	{
+		return m_type == Type::String;
+	}
+
+	/**
+	 * Get the array or object size.
+	 *
+	 * @pre must be an array or object
+	 * @return the size
+	 */
+	inline unsigned size() const noexcept
+	{
+		assert(isArray() || isObject());
+
+		if (m_type == Type::Object)
+			return m_object.size();
+
+		return m_array.size();
+	}
+
+	/**
+	 * Remove all the values.
+	 *
+	 * @pre must be an array or an object
+	 */
+	inline void clear() noexcept
+	{
+		assert(isArray() || isObject());
+
+		if (m_type == Type::Array)
+			m_array.clear();
+		else
+			m_object.clear();
+	}
+
+	/*
+	 * Array functions
+	 * ----------------------------------------------------------
+	 */
+
+	/**
+	 * Get the value at the specified position or the defaultValue if position is out of bounds.
+	 *
+	 * @param position the position
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	inline Value valueOr(unsigned position, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Array || position >= m_array.size())
+			return defaultValue;
+
+		return m_array[position];
+	}
+
+	/**
+	 * Overloaded function with type check.
+	 *
+	 * @param position the position
+	 * @param type the requested type
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	inline Value valueOr(unsigned position, Type type, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Array || position >= m_array.size() || m_array[position].typeOf() != type)
+			return defaultValue;
+
+		return m_array[position];
+	}
+
+	/**
+	 * Get a value at the specified index.
+	 *
+	 * @pre must be an array
+	 * @param position the position
+	 * @return the value
+	 * @throw std::out_of_range if out of bounds
+	 */
+	inline const Value &at(unsigned position) const
+	{
+		assert(isArray());
+
+		return m_array.at(position);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param position the position
+	 * @return the value
+	 * @throw std::out_of_range if out of bounds
+	 */
+	inline Value &at(unsigned position)
+	{
+		assert(isArray());
+
+		return m_array.at(position);
+	}
+
+	/**
+	 * Get a value at the specified index.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @return the value
+	 */
+	inline const Value &operator[](unsigned position) const
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		return m_array[position];
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @return the value
+	 */
+	inline Value &operator[](unsigned position)
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		return m_array[position];
+	}
+
+	/**
+	 * Push a value to the beginning of the array.
+	 *
+	 * @pre must be an array
+	 * @param value the value to push
+	 */
+	inline void push(const Value &value)
+	{
+		assert(isArray());
+
+		m_array.insert(m_array.begin(), value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param value the value to push
+	 */
+	inline void push(Value &&value)
+	{
+		assert(isArray());
+
+		m_array.insert(m_array.begin(), std::move(value));
+	}
+
+	/**
+	 * Insert a value at the specified position.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @param value the value to push
+	 */
+	inline void insert(unsigned position, const Value &value)
+	{
+		assert(isArray());
+		assert(position <= m_array.size());
+
+		m_array.insert(m_array.begin() + position, value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 * @param value the value to push
+	 */
+	inline void insert(unsigned position, Value &&value)
+	{
+		assert(isArray());
+		assert(position <= m_array.size());
+
+		m_array.insert(m_array.begin() + position, std::move(value));
+	}
+
+	/**
+	 * Add a new value to the end.
+	 *
+	 * @pre must be an array
+	 * @param value the value to append
+	 */
+	inline void append(const Value &value)
+	{
+		assert(isArray());
+
+		m_array.push_back(value);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an array
+	 * @param value the value to append
+	 */
+	inline void append(Value &&value)
+	{
+		assert(isArray());
+
+		m_array.push_back(std::move(value));
+	}
+
+	/**
+	 * Remove a value at the specified position.
+	 *
+	 * @pre must be an array
+	 * @pre position must be valid
+	 * @param position the position
+	 */
+	inline void erase(unsigned position)
+	{
+		assert(isArray());
+		assert(position < m_array.size());
+
+		m_array.erase(m_array.begin() + position);
+	}
+
+	/*
+	 * Object functions
+	 * ----------------------------------------------------------
+	 */
+
+	/**
+	 * Get the value at the specified key or the defaultValue if key is absent.
+	 *
+	 * @param name the name
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	Value valueOr(const std::string &name, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Object)
+			return defaultValue;
+
+		auto it = m_object.find(name);
+
+		if (it == m_object.end())
+			return defaultValue;
+
+		return it->second;
+	}
+
+	/**
+	 * Overloaded function with type check.
+	 *
+	 * @param name the name
+	 * @param type the requested type
+	 * @param defaultValue the value replacement
+	 * @return the value or defaultValue
+	 */
+	template <typename DefaultValue>
+	Value valueOr(const std::string &name, Type type, DefaultValue &&defaultValue) const
+	{
+		if (m_type != Type::Object)
+			return defaultValue;
+
+		auto it = m_object.find(name);
+
+		if (it == m_object.end() || it->second.typeOf() != type)
+			return defaultValue;
+
+		return it->second;
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 * @throw std::out_of_range if not found
+	 */
+	inline const Value &at(const std::string &name) const
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 * @throw std::out_of_range if not found
+	 */
+	inline Value &at(const std::string &name)
+	{
+		assert(isObject());
+
+		return m_object.at(name);
+	}
+
+	/**
+	 * Get a value from the object.
+	 *
+	 * @pre must be an object
+	 * @param name the value key
+	 * @return the value
+	 */
+	inline Value &operator[](const std::string &name)
+	{
+		assert(isObject());
+
+		return m_object[name];
+	}
+
+	/**
+	 * Find a value by key.
+	 *
+	 * @pre must be an object
+	 * @param key the property key
+	 * @return the iterator or past the end if not found
+	 */
+	inline iterator find(const std::string &key)
+	{
+		assert(isObject());
+
+		return iterator(*this, m_object.find(key));
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param key the property key
+	 * @return the iterator or past the end if not found
+	 */
+	inline const_iterator find(const std::string &key) const
+	{
+		assert(isObject());
+
+		return const_iterator(*this, m_object.find(key));
+	}
+
+	/**
+	 * Insert a new value.
+	 *
+	 * @pre must be an object
+	 * @param name the key
+	 * @param value the value
+	 */
+	inline void insert(std::string name, const Value &value)
+	{
+		assert(isObject());
+
+		m_object.insert({std::move(name), value});
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @pre must be an object
+	 * @param name the key
+	 * @param value the value
+	 */
+	inline void insert(std::string name, Value &&value)
+	{
+		assert(isObject());
+
+		m_object.insert({std::move(name), std::move(value)});
+	}
+
+	/**
+	 * Check if a value exists.
+	 *
+	 * @pre must be an object
+	 * @param key the key value
+	 * @return true if exists
+	 */
+	inline bool contains(const std::string &key) const noexcept
+	{
+		assert(isObject());
+
+		return m_object.find(key) != m_object.end();
+	}
+
+	/**
+	 * Remove a value of the specified key.
+	 *
+	 * @pre must be an object
+	 * @param key the value key
+	 */
+	inline void erase(const std::string &key)
+	{
+		assert(isObject());
+
+		m_object.erase(key);
+	}
+
+	/**
+	 * Return this value as JSon representation.
+	 *
+	 * @param indent, the indentation to use (0 == compact, < 0 == tabs, > 0 == number of spaces)
+	 * @param tabs, use tabs or not
+	 * @return the string
+	 */
+	inline std::string toJson(int indent = 2) const
+	{
+		return toJson(indent, 0);
+	}
+};
+
+/**
+ * Escape the input.
+ *
+ * @param input the input
+ * @return the escaped string
+ */
+std::string escape(const std::string &input);
+
+/**
+ * Convenient function for creating array from initializer list.
+ *
+ * @param values the values
+ * @return the array
+ */
+inline Value array(std::initializer_list<Value> values)
+{
+	return Value(std::vector<Value>(values.begin(), values.end()));
+}
+
+/**
+ * Convenient function for creating object from initializer list.
+ *
+ * @param values the values
+ * @return the object
+ */
+inline Value object(std::initializer_list<std::pair<std::string, Value>> values)
+{
+	return Value(std::map<std::string, Value>(values.begin(), values.end()));
+}
+
+} // !json
+
+} // !irccd
+
+#endif // !IRCCD_JSON_HPP
--- a/lib/irccd/logger.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/logger.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -23,14 +23,14 @@
 #include <stdexcept>
 #include <streambuf>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if defined(HAVE_SYSLOG)
 #  include <syslog.h>
 #endif // !HAVE_SYSLOG
 
-#include "logger.h"
-#include "system.h"
+#include "logger.hpp"
+#include "system.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/logger.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * logger.h -- irccd logging
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_LOGGER_H
-#define IRCCD_LOGGER_H
-
-/**
- * @file logger.h
- * @brief Logging facilities.
- */
-
-#include <irccd/sysconfig.h>
-
-#include <memory>
-#include <sstream>
-#include <utility>
-
-namespace irccd {
-
-namespace log {
-
-/**
- * @enum Level
- * @brief Which level of warning
- */
-enum class Level {
-	Info,			//!< Standard information (disabled if verbose is false)
-	Warning,		//!< Warning (always shown)
-	Debug			//!< Debug message (only if compiled in debug mode)
-};
-
-/* --------------------------------------------------------
- * Interface -- abstract logging interface
- * -------------------------------------------------------- */
-
-/**
- * @class Interface
- * @brief Interface to implement new logger mechanisms
- *
- * Derive from this class and use Logger::setInterface() to change logging
- * system.
- *
- * @see File
- * @see Console
- * @see Syslog
- * @see Silent
- */
-class Interface {
-public:
-	/**
-	 * Write the line to the logs. The line to write will never contains
-	 * trailing new line character.
-	 *
-	 * @param level the level
-	 * @param line the line without trailing \n
-	 */	
-	virtual void write(Level level, const std::string &line) noexcept = 0;
-};
-
-/* --------------------------------------------------------
- * Console -- logs to console
- * -------------------------------------------------------- */
-
-/**
- * @class Console
- * @brief Logger implementation for console output
- */
-class Console : public Interface {
-public:
-	/**
-	 * @copydoc Interface::write
-	 */
-	void write(Level level, const std::string &line) noexcept override;
-};
-
-/* --------------------------------------------------------
- * File -- logs to a file
- * -------------------------------------------------------- */
-
-/**
- * @class File
- * @brief Output to a file
- */
-class File : public Interface {
-private:
-	std::string m_outputNormal;
-	std::string m_outputError;
-
-public:
-	/**
-	 * Outputs to files. Info and Debug are written in normal and Warnings
-	 * in errors.
-	 *
-	 * The same path can be used for all levels.
-	 *
-	 * @param normal the path to the normal logs
-	 * @param errors the path to the errors logs
-	 */
-	File(std::string normal, std::string errors);
-
-	/**
-	 * @copydoc Interface::write
-	 */
-	void write(Level level, const std::string &line) noexcept override;
-};
-
-/* --------------------------------------------------------
- * Silent -- disable all logs
- * -------------------------------------------------------- */
-
-/**
- * @class Silent
- * @brief Use to disable logs
- *
- * Useful for unit tests when some classes may emits log.
- */
-class Silent : public Interface {
-public:
-	/**
-	 * @copydoc Interface::write
-	 */
-	void write(Level level, const std::string &line) noexcept override;
-};
-
-/* --------------------------------------------------------
- * Syslog -- system logger
- * -------------------------------------------------------- */
-
-#if defined(HAVE_SYSLOG)
-
-/**
- * @class Syslog
- * @brief Implements logger into syslog
- */
-class Syslog : public Interface {
-public:
-	/**
-	 * Open the syslog.
-	 */
-	Syslog();
-
-	/**
-	 * Close the syslog.
-	 */
-	~Syslog();
-
-	/**
-	 * @copydoc Interface::write
-	 */
-	void write(Level level, const std::string &line) noexcept override;
-};
-
-#endif // !HAVE_SYSLOG
-
-/* --------------------------------------------------------
- * Functions
- * -------------------------------------------------------- */
-
-/**
- * Update the logger interface.
- *
- * @param iface the new interface
- */
-void setInterface(std::unique_ptr<Interface> iface) noexcept;
-
-/**
- * Get the stream for informational messages.
- *
- * @return the stream
- * @note Has no effect if verbose is set to false.
- */
-std::ostream &info() noexcept;
-
-/**
- * Get the stream for warnings.
- *
- * @return the stream
- */
-std::ostream &warning() noexcept;
-
-/**
- * Get the stream for debug messages.
- *
- * @return the stream
- * @note Has no effect if compiled in release mode.
- */
-std::ostream &debug() noexcept;
-
-/**
- * Tells if verbose is enabled.
- *
- * @return true if enabled
- */
-bool isVerbose() noexcept;
-
-/**
- * Set the verbosity mode.
- *
- * @param mode the new mode
- */
-void setVerbose(bool mode) noexcept;
-
-} // !log
-
-} // !irccd
-
-#endif // !IRCCD_LOGGER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/logger.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,222 @@
+/*
+ * logger.hpp -- irccd logging
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_LOGGER_HPP
+#define IRCCD_LOGGER_HPP
+
+/**
+ * @file logger.hpp
+ * @brief Logging facilities.
+ */
+
+#include <irccd/sysconfig.hpp>
+
+#include <memory>
+#include <sstream>
+#include <utility>
+
+namespace irccd {
+
+namespace log {
+
+/**
+ * @enum Level
+ * @brief Which level of warning
+ */
+enum class Level {
+	Info,			//!< Standard information (disabled if verbose is false)
+	Warning,		//!< Warning (always shown)
+	Debug			//!< Debug message (only if compiled in debug mode)
+};
+
+/* --------------------------------------------------------
+ * Interface -- abstract logging interface
+ * -------------------------------------------------------- */
+
+/**
+ * @class Interface
+ * @brief Interface to implement new logger mechanisms
+ *
+ * Derive from this class and use Logger::setInterface() to change logging
+ * system.
+ *
+ * @see File
+ * @see Console
+ * @see Syslog
+ * @see Silent
+ */
+class Interface {
+public:
+	/**
+	 * Write the line to the logs. The line to write will never contains
+	 * trailing new line character.
+	 *
+	 * @param level the level
+	 * @param line the line without trailing \n
+	 */	
+	virtual void write(Level level, const std::string &line) noexcept = 0;
+};
+
+/* --------------------------------------------------------
+ * Console -- logs to console
+ * -------------------------------------------------------- */
+
+/**
+ * @class Console
+ * @brief Logger implementation for console output
+ */
+class Console : public Interface {
+public:
+	/**
+	 * @copydoc Interface::write
+	 */
+	void write(Level level, const std::string &line) noexcept override;
+};
+
+/* --------------------------------------------------------
+ * File -- logs to a file
+ * -------------------------------------------------------- */
+
+/**
+ * @class File
+ * @brief Output to a file
+ */
+class File : public Interface {
+private:
+	std::string m_outputNormal;
+	std::string m_outputError;
+
+public:
+	/**
+	 * Outputs to files. Info and Debug are written in normal and Warnings
+	 * in errors.
+	 *
+	 * The same path can be used for all levels.
+	 *
+	 * @param normal the path to the normal logs
+	 * @param errors the path to the errors logs
+	 */
+	File(std::string normal, std::string errors);
+
+	/**
+	 * @copydoc Interface::write
+	 */
+	void write(Level level, const std::string &line) noexcept override;
+};
+
+/* --------------------------------------------------------
+ * Silent -- disable all logs
+ * -------------------------------------------------------- */
+
+/**
+ * @class Silent
+ * @brief Use to disable logs
+ *
+ * Useful for unit tests when some classes may emits log.
+ */
+class Silent : public Interface {
+public:
+	/**
+	 * @copydoc Interface::write
+	 */
+	void write(Level level, const std::string &line) noexcept override;
+};
+
+/* --------------------------------------------------------
+ * Syslog -- system logger
+ * -------------------------------------------------------- */
+
+#if defined(HAVE_SYSLOG)
+
+/**
+ * @class Syslog
+ * @brief Implements logger into syslog
+ */
+class Syslog : public Interface {
+public:
+	/**
+	 * Open the syslog.
+	 */
+	Syslog();
+
+	/**
+	 * Close the syslog.
+	 */
+	~Syslog();
+
+	/**
+	 * @copydoc Interface::write
+	 */
+	void write(Level level, const std::string &line) noexcept override;
+};
+
+#endif // !HAVE_SYSLOG
+
+/* --------------------------------------------------------
+ * Functions
+ * -------------------------------------------------------- */
+
+/**
+ * Update the logger interface.
+ *
+ * @param iface the new interface
+ */
+void setInterface(std::unique_ptr<Interface> iface) noexcept;
+
+/**
+ * Get the stream for informational messages.
+ *
+ * @return the stream
+ * @note Has no effect if verbose is set to false.
+ */
+std::ostream &info() noexcept;
+
+/**
+ * Get the stream for warnings.
+ *
+ * @return the stream
+ */
+std::ostream &warning() noexcept;
+
+/**
+ * Get the stream for debug messages.
+ *
+ * @return the stream
+ * @note Has no effect if compiled in release mode.
+ */
+std::ostream &debug() noexcept;
+
+/**
+ * Tells if verbose is enabled.
+ *
+ * @return true if enabled
+ */
+bool isVerbose() noexcept;
+
+/**
+ * Set the verbosity mode.
+ *
+ * @param mode the new mode
+ */
+void setVerbose(bool mode) noexcept;
+
+} // !log
+
+} // !irccd
+
+#endif // !IRCCD_LOGGER_HPP
--- a/lib/irccd/options.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/options.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,7 +18,7 @@
 
 #include <cassert>
 
-#include "options.h"
+#include "options.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/options.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * options.h -- parse Unix command line options
- *
- * Copyright (c) 2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_OPTION_PARSER_H
-#define IRCCD_OPTION_PARSER_H
-
-/**
- * @file options.h
- * @brief Basic options parsing.
- */
-
-#include <exception>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace irccd {
-
-/**
- * Namespace for options parsing.
- */
-namespace parser {
-
-/**
- * @class InvalidOption
- * @brief This exception is thrown when an invalid option has been found.
- */
-class InvalidOption : public std::exception {
-private:
-	std::string message;
-
-public:
-	/**
-	 * The invalid option given.
-	 */
-	std::string argument;
-
-	/**
-	 * Construct the exception.
-	 *
-	 * @param arg the argument missing
-	 */
-	inline InvalidOption(std::string arg)
-		: argument(std::move(arg))
-	{
-		message = std::string("invalid option: ") + argument;
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the error message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * @class MissingValue
- * @brief This exception is thrown when an option requires a value and no value has been given
- */
-class MissingValue : public std::exception {
-private:
-	std::string message;
-
-public:
-	/**
-	 * The argument that requires a value.
-	 */
-	std::string argument;
-
-	/**
-	 * Construct the exception.
-	 *
-	 * @param arg the argument that requires a value
-	 */
-	inline MissingValue(std::string arg)
-		: argument(std::move(arg))
-	{
-		message = std::string("missing argument for: ") + argument;
-	}
-
-	/**
-	 * Get the error message.
-	 *
-	 * @return the error message
-	 */
-	const char *what() const noexcept override
-	{
-		return message.c_str();
-	}
-};
-
-/**
- * Packed multimap of options.
- */
-using Result = std::multimap<std::string, std::string>;
-
-/**
- * Define the allowed options.
- */
-using Options = std::map<std::string, bool>;
-
-/**
- * Extract the command line options and return a result.
- *
- * @param args the arguments
- * @param definition
- * @warning the arguments vector is modified in place to remove parsed options
- * @throw MissingValue
- * @throw InvalidOption
- */
-Result read(std::vector<std::string> &args, const Options &definition);
-
-/**
- * Overloaded function for usage with main() arguments.
- *
- * @param argc the number of arguments
- * @param argv the argument vector
- * @param definition
- * @note don't forget to remove the first argv[0] argument
- * @warning the argc and argv are modified in place to remove parsed options
- * @throw MissingValue
- * @throw InvalidOption
- */
-Result read(int &argc, char **&argv, const Options &definition);
-
-} // !parser
-
-} // !irccd
-
-#endif // !IRCCD_OPTION_PARSER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/options.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,150 @@
+/*
+ * options.hpp -- parse Unix command line options
+ *
+ * Copyright (c) 2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_OPTION_PARSER_HPP
+#define IRCCD_OPTION_PARSER_HPP
+
+/**
+ * @file options.hpp
+ * @brief Basic options parsing.
+ */
+
+#include <exception>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace irccd {
+
+/**
+ * Namespace for options parsing.
+ */
+namespace parser {
+
+/**
+ * @class InvalidOption
+ * @brief This exception is thrown when an invalid option has been found.
+ */
+class InvalidOption : public std::exception {
+private:
+	std::string message;
+
+public:
+	/**
+	 * The invalid option given.
+	 */
+	std::string argument;
+
+	/**
+	 * Construct the exception.
+	 *
+	 * @param arg the argument missing
+	 */
+	inline InvalidOption(std::string arg)
+		: argument(std::move(arg))
+	{
+		message = std::string("invalid option: ") + argument;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the error message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * @class MissingValue
+ * @brief This exception is thrown when an option requires a value and no value has been given
+ */
+class MissingValue : public std::exception {
+private:
+	std::string message;
+
+public:
+	/**
+	 * The argument that requires a value.
+	 */
+	std::string argument;
+
+	/**
+	 * Construct the exception.
+	 *
+	 * @param arg the argument that requires a value
+	 */
+	inline MissingValue(std::string arg)
+		: argument(std::move(arg))
+	{
+		message = std::string("missing argument for: ") + argument;
+	}
+
+	/**
+	 * Get the error message.
+	 *
+	 * @return the error message
+	 */
+	const char *what() const noexcept override
+	{
+		return message.c_str();
+	}
+};
+
+/**
+ * Packed multimap of options.
+ */
+using Result = std::multimap<std::string, std::string>;
+
+/**
+ * Define the allowed options.
+ */
+using Options = std::map<std::string, bool>;
+
+/**
+ * Extract the command line options and return a result.
+ *
+ * @param args the arguments
+ * @param definition
+ * @warning the arguments vector is modified in place to remove parsed options
+ * @throw MissingValue
+ * @throw InvalidOption
+ */
+Result read(std::vector<std::string> &args, const Options &definition);
+
+/**
+ * Overloaded function for usage with main() arguments.
+ *
+ * @param argc the number of arguments
+ * @param argv the argument vector
+ * @param definition
+ * @note don't forget to remove the first argv[0] argument
+ * @warning the argc and argv are modified in place to remove parsed options
+ * @throw MissingValue
+ * @throw InvalidOption
+ */
+Result read(int &argc, char **&argv, const Options &definition);
+
+} // !parser
+
+} // !irccd
+
+#endif // !IRCCD_OPTION_PARSER_HPP
--- a/lib/irccd/path.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/path.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -21,7 +21,7 @@
 #include <sstream>
 #include <stdexcept>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if defined(IRCCD_SYSTEM_WINDOWS)
 #  include <Windows.h>
@@ -53,13 +53,13 @@
 #    include <libproc.h>
 #  endif
 
-#  include "xdg.h"
+#  include "xdg.hpp"
 #endif
 
-#include "fs.h"
-#include "path.h"
-#include "system.h"
-#include "util.h"
+#include "fs.hpp"
+#include "path.hpp"
+#include "system.hpp"
+#include "util.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/path.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * path.h -- special paths inside irccd
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_PATH_H
-#define IRCCD_PATH_H
-
-/**
- * @file path.h
- * @brief Path management.
- */
-
-#include <string>
-#include <vector>
-
-namespace irccd {
-
-namespace path {
-
-/**
- * PATH separator, either : or ;.
- */
-extern const char Separator;
-
-/**
- * @enum Path
- * @brief Which special path to get
- */
-enum Path {
-	PathConfig,			//!< Configuration files
-	PathData,			//!< Data directory
-	PathCache,			//!< Cache files
-	PathPlugins			//!< Path to the plugins
-};
-
-/**
- * @enum Owner
- * @brief For paths, get the installation path or the user ones
- */
-enum Owner {
-	OwnerSystem,			//!< System wide
-	OwnerUser			//!< User
-};
-
-/**
- * This function must be called before at the beginning of the main.
- *
- * It use system dependant program path lookup if available and fallbacks to the path given as argument if any failure
- * was encoutered.
- *
- * @param argv0 the path to the executable (argv[0])
- */
-void setApplicationPath(const std::string &argv0);
-
-/**
- * Clean a path by removing any extra / or \ and add a trailing one.
- *
- * @param path the path
- * @return the updated path
- */
-std::string clean(std::string path);
-
-/**
- * Generic function for path retrievement.
- *
- * The path is always terminated by a trailing / or \\.
- *
- * @pre setApplicationPath must have been called
- * @param path the type of path
- * @param owner system or user wide
- * @return the path
- */
-std::string get(Path path, Owner owner);
-
-/**
- * Generic function for multiple paths.
- *
- * This function will add more directories than pathSystem*() and pathUser*() functions, for example
- * it will add some path if irccd is relocatable.
- *
- * @pre setApplicationPath must have been called
- * @param path the type of path
- * @return the list of preferred directories in order
- */
-std::vector<std::string> list(Path path);
-
-} // !path
-
-} // !irccd
-
-#endif // !IRCCD_PATH_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/path.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,105 @@
+/*
+ * path.hpp -- special paths inside irccd
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_PATH_HPP
+#define IRCCD_PATH_HPP
+
+/**
+ * @file path.hpp
+ * @brief Path management.
+ */
+
+#include <string>
+#include <vector>
+
+namespace irccd {
+
+namespace path {
+
+/**
+ * PATH separator, either : or ;.
+ */
+extern const char Separator;
+
+/**
+ * @enum Path
+ * @brief Which special path to get
+ */
+enum Path {
+	PathConfig,			//!< Configuration files
+	PathData,			//!< Data directory
+	PathCache,			//!< Cache files
+	PathPlugins			//!< Path to the plugins
+};
+
+/**
+ * @enum Owner
+ * @brief For paths, get the installation path or the user ones
+ */
+enum Owner {
+	OwnerSystem,			//!< System wide
+	OwnerUser			//!< User
+};
+
+/**
+ * This function must be called before at the beginning of the main.
+ *
+ * It use system dependant program path lookup if available and fallbacks to the path given as argument if any failure
+ * was encoutered.
+ *
+ * @param argv0 the path to the executable (argv[0])
+ */
+void setApplicationPath(const std::string &argv0);
+
+/**
+ * Clean a path by removing any extra / or \ and add a trailing one.
+ *
+ * @param path the path
+ * @return the updated path
+ */
+std::string clean(std::string path);
+
+/**
+ * Generic function for path retrievement.
+ *
+ * The path is always terminated by a trailing / or \\.
+ *
+ * @pre setApplicationPath must have been called
+ * @param path the type of path
+ * @param owner system or user wide
+ * @return the path
+ */
+std::string get(Path path, Owner owner);
+
+/**
+ * Generic function for multiple paths.
+ *
+ * This function will add more directories than pathSystem*() and pathUser*() functions, for example
+ * it will add some path if irccd is relocatable.
+ *
+ * @pre setApplicationPath must have been called
+ * @param path the type of path
+ * @return the list of preferred directories in order
+ */
+std::vector<std::string> list(Path path);
+
+} // !path
+
+} // !irccd
+
+#endif // !IRCCD_PATH_HPP
--- a/lib/irccd/plugin.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/plugin.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,7 +18,7 @@
 
 #include <stdexcept>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if defined(HAVE_STAT)
 #  include <sys/stat.h>
@@ -26,22 +26,22 @@
 #  include <cstring>
 #endif
 
-#include "fs.h"
-#include "js-directory.h"
-#include "js-elapsed-timer.h"
-#include "js-file.h"
-#include "js-irccd.h"
-#include "js-logger.h"
-#include "js-plugin.h"
-#include "js-server.h"
-#include "js-system.h"
-#include "js-timer.h"
-#include "js-unicode.h"
-#include "js-util.h"
-#include "path.h"
-#include "plugin.h"
-#include "server.h"
-#include "util.h"
+#include "fs.hpp"
+#include "js-directory.hpp"
+#include "js-elapsed-timer.hpp"
+#include "js-file.hpp"
+#include "js-irccd.hpp"
+#include "js-logger.hpp"
+#include "js-plugin.hpp"
+#include "js-server.hpp"
+#include "js-system.hpp"
+#include "js-timer.hpp"
+#include "js-unicode.hpp"
+#include "js-util.hpp"
+#include "path.hpp"
+#include "plugin.hpp"
+#include "server.hpp"
+#include "util.hpp"
 
 using namespace std;
 
--- a/lib/irccd/plugin.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,369 +0,0 @@
-/*
- * plugin.h -- irccd JavaScript plugin interface
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_PLUGIN_H
-#define IRCCD_PLUGIN_H
-
-/**
- * @file plugin.h
- * @brief Irccd plugins
- */
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "js.h"
-#include "path.h"
-#include "signals.h"
-#include "timer.h"
-
-namespace irccd {
-
-class Server;
-class ServerWhois;
-
-/**
- * @class PluginInfo
- * @brief Plugin information
- */
-class PluginInfo {
-public:
-	std::string name;		//!< plugin name (from file on disk)
-	std::string parent;		//!< parent directory
-	std::string path;		//!< full path to the plugin file
-
-	/* Metadata */
-	std::string author{"unknown"};	//!< plugin author
-	std::string license{"unknown"};	//!< plugin license
-	std::string summary{"unknown"};	//!< short plugin description
-	std::string version{"unknown"};	//!< plugin version
-};
-
-/**
- * Configuration map extract from config file.
- */
-using PluginConfig = std::unordered_map<std::string, std::string>;
-
-/**
- * Timers that a plugin owns.
- */
-using PluginTimers = std::unordered_set<std::shared_ptr<Timer>>;
-
-/**
- * @class Plugin
- * @brief JavaScript plugin
- *
- * A plugin is identified by name and can be loaded and unloaded
- * at runtime.
- */
-class Plugin {
-public:
-	/**
-	 * Signal: onTimerSignal
-	 * ------------------------------------------------
-	 *
-	 * When a timer expires.
-	 *
-	 * Arguments:
-	 * - the timer object
-	 */
-	Signal<std::shared_ptr<Timer>> onTimerSignal;
-
-	/**
-	 * Signal: onTimerEnd
-	 * ------------------------------------------------
-	 *
-	 * When a timer is finished.
-	 *
-	 * Arguments:
-	 * - the timer object
-	 */
-	Signal<std::shared_ptr<Timer>> onTimerEnd;
-
-private:
-	/* JavaScript context */
-	duk::Context m_context;
-
-	/* Plugin info and its timers */
-	PluginInfo m_info;
-	PluginTimers m_timers;
-
-	/* Private helpers */
-	void call(const std::string &name, unsigned nargs = 0);
-	void putVars();
-	void putPath(const std::string &varname, const std::string &append, path::Path type);
-	void putPaths();
-	void putConfig(const PluginConfig &config);
-
-public:
-	/**
-	 * Correct constructor.
-	 *
-	 * @param name the plugin id
-	 * @param path the fully resolved path to the plugin
-	 * @param config the plugin configuration
-	 * @throws std::runtime_error on errors
-	 */
-	Plugin(std::string name, std::string path, const PluginConfig &config = PluginConfig());
-
-	/**
-	 * Temporary, close all timers.
-	 */
-	~Plugin();
-
-	/**
-	 * Get the plugin information.
-	 */
-	const PluginInfo &info() const;
-
-	/**
-	 * Add a timer to the plugin.
-	 *
-	 * @param timer the timer to add
-	 */
-	void addTimer(std::shared_ptr<Timer> timer) noexcept;
-
-	/**
-	 * Remove a timer from a plugin.
-	 *
-	 * @param timer
-	 */
-	void removeTimer(const std::shared_ptr<Timer> &timer) noexcept;
-
-	/**
-	 * Access the Duktape context.
-	 *
-	 * @return the context
-	 */
-	inline duk::Context &context() noexcept
-	{
-		return m_context;
-	}
-
-	/**
-	 * On channel message. This event will call onMessage or
-	 * onCommand if the messages starts with the command character
-	 * plus the plugin name.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the message
-	 * @param channel the channel
-	 * @param message the message or command
-	 */
-	void onCommand(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string message);
-
-	/**
-	 * On successful connection.
-	 *
-	 * @param server the server
-	 */
-	void onConnect(std::shared_ptr<Server> server);
-
-	/**
-	 * On channel mode.
-	 *
-	 * @param server the server
-	 * @param origin the ouser who has changed the mode
-	 * @param channel the channel
-	 * @param mode the mode
-	 * @param arg the optional mode argument
-	 */
-	void onChannelMode(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string mode, std::string arg);
-
-	/**
-	 * On a channel notice.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the notice
-	 * @param channel on which channel
-	 * @param notice the message
-	 */
-	void onChannelNotice(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string notice);
-
-	/**
-	 * On invitation.
-	 *
-	 * @param server the server
-	 * @param origin the user who invited you
-	 * @param channel the channel
-	 */
-	void onInvite(std::shared_ptr<Server> server, std::string origin, std::string channel);
-
-	/**
-	 * On join.
-	 *
-	 * @param server the server
-	 * @param origin the user who joined
-	 * @param channel the channel
-	 */
-	void onJoin(std::shared_ptr<Server> server, std::string origin, std::string channel);
-
-	/**
-	 * On kick.
-	 *
-	 * @param server the server
-	 * @param origin the user who kicked the target
-	 * @param channel the channel
-	 * @param target the kicked target
-	 * @param reason the optional reason
-	 */
-	void onKick(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string target, std::string reason);
-
-	/**
-	 * On load.
-	 */
-	void onLoad();
-
-	/**
-	 * On channel message.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the message
-	 * @param channel the channel
-	 * @param message the message or command
-	 */
-	void onMessage(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string message);
-
-	/**
-	 * On CTCP Action.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the message
-	 * @param channel the channel (may also be your nickname)
-	 * @param message the message
-	 */
-	void onMe(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string message);
-
-	/**
-	 * On user mode change.
-	 *
-	 * @param server the server
-	 * @param origin the person who changed the mode
-	 * @param mode the new mode
-	 */
-	void onMode(std::shared_ptr<Server> server, std::string origin, std::string mode);
-
-	/**
-	 * On names listing.
-	 *
-	 * @param server the server
-	 * @param channel the channel
-	 * @param list the list of nicknames
-	 */
-	void onNames(std::shared_ptr<Server> server, std::string channel, std::vector<std::string> list);
-
-	/**
-	 * On nick change.
-	 *
-	 * @param server the server
-	 * @param origin the user that changed its nickname
-	 * @param nick the new nickname
-	 */
-	void onNick(std::shared_ptr<Server> server, std::string origin, std::string nick);
-
-	/**
-	 * On user notice.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the notice
-	 * @param notice the notice
-	 */
-	void onNotice(std::shared_ptr<Server> server, std::string origin, std::string notice);
-
-	/**
-	 * On part.
-	 *
-	 * @param server the server
-	 * @param origin the user who left
-	 * @param channel the channel
-	 * @param reason the optional reason
-	 */
-	void onPart(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string reason);
-
-	/**
-	 * On user query.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the query
-	 * @param message the message
-	 */
-	void onQuery(std::shared_ptr<Server> server, std::string origin, std::string message);
-
-	/**
-	 * On user query command.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the query
-	 * @param message the message
-	 */
-	void onQueryCommand(std::shared_ptr<Server> server, std::string origin, std::string message);
-
-	/**
-	 * On reload.
-	 */
-	void onReload();
-
-	/**
-	 * On topic change.
-	 *
-	 * @param server the server
-	 * @param origin the user who sent the topic
-	 * @param channel the channel
-	 * @param topic the new topic
-	 */
-	void onTopic(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string topic);
-
-	/**
-	 * On unload.
-	 */
-	void onUnload();
-
-	/**
-	 * On whois information.
-	 *
-	 * @param server the server
-	 * @param info the info
-	 */
-	void onWhois(std::shared_ptr<Server> server, ServerWhois info);
-};
-
-namespace duk {
-
-/**
- * @brief Push plugin information.
- */
-template <>
-class TypeTraits<irccd::PluginInfo> {
-public:
-	/**
-	 * Push the plugin information as JavaScript object.
-	 *
-	 * @param ctx the context
-	 * @param info the plugin information
-	 */
-	static void push(ContextPtr ctx, const PluginInfo &info);
-};
-
-} // !duk
-
-} // !irccd
-
-#endif // !IRCCD_PLUGIN_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/plugin.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,369 @@
+/*
+ * plugin.hpp -- irccd JavaScript plugin interface
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_PLUGIN_HPP
+#define IRCCD_PLUGIN_HPP
+
+/**
+ * @file plugin.hpp
+ * @brief Irccd plugins
+ */
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "js.hpp"
+#include "path.hpp"
+#include "signals.hpp"
+#include "timer.hpp"
+
+namespace irccd {
+
+class Server;
+class ServerWhois;
+
+/**
+ * @class PluginInfo
+ * @brief Plugin information
+ */
+class PluginInfo {
+public:
+	std::string name;		//!< plugin name (from file on disk)
+	std::string parent;		//!< parent directory
+	std::string path;		//!< full path to the plugin file
+
+	/* Metadata */
+	std::string author{"unknown"};	//!< plugin author
+	std::string license{"unknown"};	//!< plugin license
+	std::string summary{"unknown"};	//!< short plugin description
+	std::string version{"unknown"};	//!< plugin version
+};
+
+/**
+ * Configuration map extract from config file.
+ */
+using PluginConfig = std::unordered_map<std::string, std::string>;
+
+/**
+ * Timers that a plugin owns.
+ */
+using PluginTimers = std::unordered_set<std::shared_ptr<Timer>>;
+
+/**
+ * @class Plugin
+ * @brief JavaScript plugin
+ *
+ * A plugin is identified by name and can be loaded and unloaded
+ * at runtime.
+ */
+class Plugin {
+public:
+	/**
+	 * Signal: onTimerSignal
+	 * ------------------------------------------------
+	 *
+	 * When a timer expires.
+	 *
+	 * Arguments:
+	 * - the timer object
+	 */
+	Signal<std::shared_ptr<Timer>> onTimerSignal;
+
+	/**
+	 * Signal: onTimerEnd
+	 * ------------------------------------------------
+	 *
+	 * When a timer is finished.
+	 *
+	 * Arguments:
+	 * - the timer object
+	 */
+	Signal<std::shared_ptr<Timer>> onTimerEnd;
+
+private:
+	/* JavaScript context */
+	duk::Context m_context;
+
+	/* Plugin info and its timers */
+	PluginInfo m_info;
+	PluginTimers m_timers;
+
+	/* Private helpers */
+	void call(const std::string &name, unsigned nargs = 0);
+	void putVars();
+	void putPath(const std::string &varname, const std::string &append, path::Path type);
+	void putPaths();
+	void putConfig(const PluginConfig &config);
+
+public:
+	/**
+	 * Correct constructor.
+	 *
+	 * @param name the plugin id
+	 * @param path the fully resolved path to the plugin
+	 * @param config the plugin configuration
+	 * @throws std::runtime_error on errors
+	 */
+	Plugin(std::string name, std::string path, const PluginConfig &config = PluginConfig());
+
+	/**
+	 * Temporary, close all timers.
+	 */
+	~Plugin();
+
+	/**
+	 * Get the plugin information.
+	 */
+	const PluginInfo &info() const;
+
+	/**
+	 * Add a timer to the plugin.
+	 *
+	 * @param timer the timer to add
+	 */
+	void addTimer(std::shared_ptr<Timer> timer) noexcept;
+
+	/**
+	 * Remove a timer from a plugin.
+	 *
+	 * @param timer
+	 */
+	void removeTimer(const std::shared_ptr<Timer> &timer) noexcept;
+
+	/**
+	 * Access the Duktape context.
+	 *
+	 * @return the context
+	 */
+	inline duk::Context &context() noexcept
+	{
+		return m_context;
+	}
+
+	/**
+	 * On channel message. This event will call onMessage or
+	 * onCommand if the messages starts with the command character
+	 * plus the plugin name.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the message
+	 * @param channel the channel
+	 * @param message the message or command
+	 */
+	void onCommand(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string message);
+
+	/**
+	 * On successful connection.
+	 *
+	 * @param server the server
+	 */
+	void onConnect(std::shared_ptr<Server> server);
+
+	/**
+	 * On channel mode.
+	 *
+	 * @param server the server
+	 * @param origin the ouser who has changed the mode
+	 * @param channel the channel
+	 * @param mode the mode
+	 * @param arg the optional mode argument
+	 */
+	void onChannelMode(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string mode, std::string arg);
+
+	/**
+	 * On a channel notice.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the notice
+	 * @param channel on which channel
+	 * @param notice the message
+	 */
+	void onChannelNotice(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string notice);
+
+	/**
+	 * On invitation.
+	 *
+	 * @param server the server
+	 * @param origin the user who invited you
+	 * @param channel the channel
+	 */
+	void onInvite(std::shared_ptr<Server> server, std::string origin, std::string channel);
+
+	/**
+	 * On join.
+	 *
+	 * @param server the server
+	 * @param origin the user who joined
+	 * @param channel the channel
+	 */
+	void onJoin(std::shared_ptr<Server> server, std::string origin, std::string channel);
+
+	/**
+	 * On kick.
+	 *
+	 * @param server the server
+	 * @param origin the user who kicked the target
+	 * @param channel the channel
+	 * @param target the kicked target
+	 * @param reason the optional reason
+	 */
+	void onKick(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string target, std::string reason);
+
+	/**
+	 * On load.
+	 */
+	void onLoad();
+
+	/**
+	 * On channel message.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the message
+	 * @param channel the channel
+	 * @param message the message or command
+	 */
+	void onMessage(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string message);
+
+	/**
+	 * On CTCP Action.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the message
+	 * @param channel the channel (may also be your nickname)
+	 * @param message the message
+	 */
+	void onMe(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string message);
+
+	/**
+	 * On user mode change.
+	 *
+	 * @param server the server
+	 * @param origin the person who changed the mode
+	 * @param mode the new mode
+	 */
+	void onMode(std::shared_ptr<Server> server, std::string origin, std::string mode);
+
+	/**
+	 * On names listing.
+	 *
+	 * @param server the server
+	 * @param channel the channel
+	 * @param list the list of nicknames
+	 */
+	void onNames(std::shared_ptr<Server> server, std::string channel, std::vector<std::string> list);
+
+	/**
+	 * On nick change.
+	 *
+	 * @param server the server
+	 * @param origin the user that changed its nickname
+	 * @param nick the new nickname
+	 */
+	void onNick(std::shared_ptr<Server> server, std::string origin, std::string nick);
+
+	/**
+	 * On user notice.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the notice
+	 * @param notice the notice
+	 */
+	void onNotice(std::shared_ptr<Server> server, std::string origin, std::string notice);
+
+	/**
+	 * On part.
+	 *
+	 * @param server the server
+	 * @param origin the user who left
+	 * @param channel the channel
+	 * @param reason the optional reason
+	 */
+	void onPart(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string reason);
+
+	/**
+	 * On user query.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the query
+	 * @param message the message
+	 */
+	void onQuery(std::shared_ptr<Server> server, std::string origin, std::string message);
+
+	/**
+	 * On user query command.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the query
+	 * @param message the message
+	 */
+	void onQueryCommand(std::shared_ptr<Server> server, std::string origin, std::string message);
+
+	/**
+	 * On reload.
+	 */
+	void onReload();
+
+	/**
+	 * On topic change.
+	 *
+	 * @param server the server
+	 * @param origin the user who sent the topic
+	 * @param channel the channel
+	 * @param topic the new topic
+	 */
+	void onTopic(std::shared_ptr<Server> server, std::string origin, std::string channel, std::string topic);
+
+	/**
+	 * On unload.
+	 */
+	void onUnload();
+
+	/**
+	 * On whois information.
+	 *
+	 * @param server the server
+	 * @param info the info
+	 */
+	void onWhois(std::shared_ptr<Server> server, ServerWhois info);
+};
+
+namespace duk {
+
+/**
+ * @brief Push plugin information.
+ */
+template <>
+class TypeTraits<irccd::PluginInfo> {
+public:
+	/**
+	 * Push the plugin information as JavaScript object.
+	 *
+	 * @param ctx the context
+	 * @param info the plugin information
+	 */
+	static void push(ContextPtr ctx, const PluginInfo &info);
+};
+
+} // !duk
+
+} // !irccd
+
+#endif // !IRCCD_PLUGIN_HPP
--- a/lib/irccd/rule.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/rule.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,9 +18,9 @@
 
 #include <stdexcept>
 
-#include "logger.h"
-#include "rule.h"
-#include "util.h"
+#include "logger.hpp"
+#include "rule.hpp"
+#include "util.hpp"
 
 using namespace std;
 
--- a/lib/irccd/rule.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * rule.h -- rule for server and channels
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_RULE_H
-#define IRCCD_RULE_H
-
-/**
- * @file rule.h
- * @brief Rule description
- */
-
-#include <sstream>
-#include <string>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-namespace irccd {
-
-/**
- * List of criterias.
- */
-using RuleSet = std::unordered_set<std::string>;
-
-/**
- * @enum RuleAction
- * @brief Rule action
- */
-enum class RuleAction {
-	Accept,			//!< The event is accepted (default)
-	Drop			//!< The event is dropped
-};
-
-/**
- * @class Rule
- * @brief Manage rule to activate or deactive events.
- */
-class Rule final {
-private:
-	RuleSet m_servers;
-	RuleSet m_channels;
-	RuleSet m_origins;
-	RuleSet m_plugins;
-	RuleSet m_events;
-	RuleAction m_action{RuleAction::Accept};
-
-	/*
-	 * Check if a map contains the value and return true if it is
-	 * or return true if value is empty (which means applicable).
-	 */
-	bool matchMap(const RuleSet &map, const std::string &value) const noexcept;
-
-public:
-	/**
-	 * Resolve the action to execute with the specified list of rules.
-	 *
-	 * @param rules the list of rules
-	 * @param server the server name
-	 * @param channel the channel name
-	 * @param origin the origin
-	 * @param plugin the plugin name
-	 * @param event the event name (e.g onKick)
-	 * @return true if the plugin must be called
-	 */
-	static bool solve(const std::vector<Rule> &rules,
-			  const std::string &server,
-			  const std::string &channel,
-			  const std::string &origin,
-			  const std::string &plugin,
-			  const std::string &event) noexcept;
-
-	/**
-	 * Rule constructor.
-	 *
-	 * @param servers the server list
-	 * @param channels the channels
-	 * @param nicknames the nicknames
-	 * @param plugins the plugins
-	 * @param events the events
-	 * @param action the rule action
-	 * @throw std::invalid_argument if events are invalid
-	 */
-	Rule(RuleSet servers = RuleSet{},
-	     RuleSet channels = RuleSet{},
-	     RuleSet nicknames = RuleSet{},
-	     RuleSet plugins = RuleSet{},
-	     RuleSet events = RuleSet{},
-	     RuleAction action = RuleAction::Accept);
-
-	/**
-	 * Check if that rule apply for the given criterias.
-	 *
-	 * @param server the server
-	 * @param channel the channel
-	 * @param nick the origin
-	 * @param plugin the plugin
-	 * @param event the event
-	 * @return true if match
-	 */
-	bool match(const std::string &server,
-		   const std::string &channel,
-		   const std::string &nick,
-		   const std::string &plugin,
-		   const std::string &event) const noexcept;
-
-	/**
-	 * Get the action.
-	 *
-	 * @return the action
-	 */
-	RuleAction action() const noexcept;
-
-	/**
-	 * Get the servers.
-	 *
-	 * @return the servers
-	 */
-	const RuleSet &servers() const noexcept;
-
-	/**
-	 * Get the channels.
-	 *
-	 * @return the channels
-	 */
-	const RuleSet &channels() const noexcept;
-
-	/**
-	 * Get the origins.
-	 *
-	 * @return the origins
-	 */
-	const RuleSet &origins() const noexcept;
-
-	/**
-	 * Get the plugins.
-	 *
-	 * @return the plugins
-	 */
-	const RuleSet &plugins() const noexcept;
-
-	/**
-	 * Get the events.
-	 *
-	 * @return the events
-	 */
-	const RuleSet &events() const noexcept;
-};
-
-} // !irccd
-
-#endif // !IRCCD_RULE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/rule.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,166 @@
+/*
+ * rule.hpp -- rule for server and channels
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_RULE_HPP
+#define IRCCD_RULE_HPP
+
+/**
+ * @file rule.hpp
+ * @brief Rule description
+ */
+
+#include <sstream>
+#include <string>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace irccd {
+
+/**
+ * List of criterias.
+ */
+using RuleSet = std::unordered_set<std::string>;
+
+/**
+ * @enum RuleAction
+ * @brief Rule action
+ */
+enum class RuleAction {
+	Accept,			//!< The event is accepted (default)
+	Drop			//!< The event is dropped
+};
+
+/**
+ * @class Rule
+ * @brief Manage rule to activate or deactive events.
+ */
+class Rule final {
+private:
+	RuleSet m_servers;
+	RuleSet m_channels;
+	RuleSet m_origins;
+	RuleSet m_plugins;
+	RuleSet m_events;
+	RuleAction m_action{RuleAction::Accept};
+
+	/*
+	 * Check if a map contains the value and return true if it is
+	 * or return true if value is empty (which means applicable).
+	 */
+	bool matchMap(const RuleSet &map, const std::string &value) const noexcept;
+
+public:
+	/**
+	 * Resolve the action to execute with the specified list of rules.
+	 *
+	 * @param rules the list of rules
+	 * @param server the server name
+	 * @param channel the channel name
+	 * @param origin the origin
+	 * @param plugin the plugin name
+	 * @param event the event name (e.g onKick)
+	 * @return true if the plugin must be called
+	 */
+	static bool solve(const std::vector<Rule> &rules,
+			  const std::string &server,
+			  const std::string &channel,
+			  const std::string &origin,
+			  const std::string &plugin,
+			  const std::string &event) noexcept;
+
+	/**
+	 * Rule constructor.
+	 *
+	 * @param servers the server list
+	 * @param channels the channels
+	 * @param nicknames the nicknames
+	 * @param plugins the plugins
+	 * @param events the events
+	 * @param action the rule action
+	 * @throw std::invalid_argument if events are invalid
+	 */
+	Rule(RuleSet servers = RuleSet{},
+	     RuleSet channels = RuleSet{},
+	     RuleSet nicknames = RuleSet{},
+	     RuleSet plugins = RuleSet{},
+	     RuleSet events = RuleSet{},
+	     RuleAction action = RuleAction::Accept);
+
+	/**
+	 * Check if that rule apply for the given criterias.
+	 *
+	 * @param server the server
+	 * @param channel the channel
+	 * @param nick the origin
+	 * @param plugin the plugin
+	 * @param event the event
+	 * @return true if match
+	 */
+	bool match(const std::string &server,
+		   const std::string &channel,
+		   const std::string &nick,
+		   const std::string &plugin,
+		   const std::string &event) const noexcept;
+
+	/**
+	 * Get the action.
+	 *
+	 * @return the action
+	 */
+	RuleAction action() const noexcept;
+
+	/**
+	 * Get the servers.
+	 *
+	 * @return the servers
+	 */
+	const RuleSet &servers() const noexcept;
+
+	/**
+	 * Get the channels.
+	 *
+	 * @return the channels
+	 */
+	const RuleSet &channels() const noexcept;
+
+	/**
+	 * Get the origins.
+	 *
+	 * @return the origins
+	 */
+	const RuleSet &origins() const noexcept;
+
+	/**
+	 * Get the plugins.
+	 *
+	 * @return the plugins
+	 */
+	const RuleSet &plugins() const noexcept;
+
+	/**
+	 * Get the events.
+	 *
+	 * @return the events
+	 */
+	const RuleSet &events() const noexcept;
+};
+
+} // !irccd
+
+#endif // !IRCCD_RULE_HPP
--- a/lib/irccd/server-private.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * server-private.h -- libircclient bridge
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SERVER_PRIVATE_H
-#define IRCCD_SERVER_PRIVATE_H
-
-#include <memory>
-
-#include <libircclient.h>
-
-#include "server.h"
-
-namespace irccd {
-
-/**
- * @brief Bridge for libircclient
- */
-class Server::Session {
-public:
-	/**
-	 * libircclient handle.
-	 */
-	using Handle = std::unique_ptr<irc_session_t, void (*)(irc_session_t *)>;
-
-private:
-	Handle m_handle;
-
-public:
-	/**
-	 * Create a null session.
-	 */
-	inline Session()
-		: m_handle(nullptr, nullptr)
-	{
-	}
-
-	/**
-	 * Convert the libircclient session.
-	 */
-	inline operator const irc_session_t *() const noexcept
-	{
-		return m_handle.get();
-	}
-
-	/**
-	 * Overloaded function.
-	 */
-	inline operator irc_session_t *() noexcept
-	{
-		return m_handle.get();
-	}
-
-	/**
-	 * Get the handle.
-	 *
-	 * @return the handle
-	 */
-	inline Handle &handle() noexcept
-	{
-		return m_handle;
-	}
-};
-
-} // !irccd
-
-#endif // !IRCCD_SERVER_PRIVATE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/server-private.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,81 @@
+/*
+ * server-private.hpp -- libircclient bridge
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SERVER_PRIVATE_HPP
+#define IRCCD_SERVER_PRIVATE_HPP
+
+#include <memory>
+
+#include <libircclient.h>
+
+#include "server.hpp"
+
+namespace irccd {
+
+/**
+ * @brief Bridge for libircclient
+ */
+class Server::Session {
+public:
+	/**
+	 * libircclient handle.
+	 */
+	using Handle = std::unique_ptr<irc_session_t, void (*)(irc_session_t *)>;
+
+private:
+	Handle m_handle;
+
+public:
+	/**
+	 * Create a null session.
+	 */
+	inline Session()
+		: m_handle(nullptr, nullptr)
+	{
+	}
+
+	/**
+	 * Convert the libircclient session.
+	 */
+	inline operator const irc_session_t *() const noexcept
+	{
+		return m_handle.get();
+	}
+
+	/**
+	 * Overloaded function.
+	 */
+	inline operator irc_session_t *() noexcept
+	{
+		return m_handle.get();
+	}
+
+	/**
+	 * Get the handle.
+	 *
+	 * @return the handle
+	 */
+	inline Handle &handle() noexcept
+	{
+		return m_handle;
+	}
+};
+
+} // !irccd
+
+#endif // !IRCCD_SERVER_PRIVATE_HPP
--- a/lib/irccd/server-state.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/server-state.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,7 +18,7 @@
 
 #include <cassert>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if !defined(_WIN32)
 #  include <sys/types.h>
@@ -27,8 +27,8 @@
 #  include <resolv.h>
 #endif
 
-#include "server-state.h"
-#include "server-private.h"
+#include "server-state.hpp"
+#include "server-private.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/server-state.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * server-state.h -- server current state
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SERVER_STATE_H
-#define IRCCD_SERVER_STATE_H
-
-/**
- * @file server-state.h
- * @brief Server state.
- */
-
-#include <irccd/sysconfig.h>
-
-#include "elapsed-timer.h"
-#include "sockets.h"
-
-namespace irccd {
-
-class Server;
-
-/**
- * @class ServerState
- * @brief Server current state.
- */
-class ServerState {
-public:
-	/**
-	 * @enum Type
-	 * @brief Server state
-	 */
-	enum Type {
-		Undefined,	//!< Not defined yet
-		Connecting,	//!< Connecting to the server
-		Connected,	//!< Connected and running
-		Disconnected,	//!< Disconnected and waiting before retrying
-	};
-
-private:
-	Type m_type;
-
-	/* For ServerState::Connecting */
-	bool m_started{false};
-	ElapsedTimer m_timer;
-
-	/* Private helpers */
-	bool connect(Server &server);
-
-	/* Different preparation */
-	void prepareConnected(Server &, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
-	void prepareConnecting(Server &, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
-	void prepareDisconnected(Server &, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
-
-public:
-	/**
-	 * Create the server state.
-	 *
-	 * @pre type must be valid
-	 * @param type the type
-	 */
-	ServerState(Type type);
-
-	/**
-	 * Prepare the state.
-	 *
-	 * @param server the server
-	 * @param setinput the read set
-	 * @param setoutput the write set
-	 * @param maxfd the maximum fd
-	 */
-	void prepare(Server &server, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
-
-	/**
-	 * Get the state type.
-	 *
-	 * @return the type
-	 */
-	inline Type type() const noexcept
-	{
-		return m_type;
-	}
-};
-
-} // !irccd
-
-#endif // !IRCCD_SERVER_STATE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/server-state.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,100 @@
+/*
+ * server-state.hpp -- server current state
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SERVER_STATE_HPP
+#define IRCCD_SERVER_STATE_HPP
+
+/**
+ * @file server-state.hpp
+ * @brief Server state.
+ */
+
+#include <irccd/sysconfig.hpp>
+
+#include "elapsed-timer.hpp"
+#include "sockets.hpp"
+
+namespace irccd {
+
+class Server;
+
+/**
+ * @class ServerState
+ * @brief Server current state.
+ */
+class ServerState {
+public:
+	/**
+	 * @enum Type
+	 * @brief Server state
+	 */
+	enum Type {
+		Undefined,	//!< Not defined yet
+		Connecting,	//!< Connecting to the server
+		Connected,	//!< Connected and running
+		Disconnected,	//!< Disconnected and waiting before retrying
+	};
+
+private:
+	Type m_type;
+
+	/* For ServerState::Connecting */
+	bool m_started{false};
+	ElapsedTimer m_timer;
+
+	/* Private helpers */
+	bool connect(Server &server);
+
+	/* Different preparation */
+	void prepareConnected(Server &, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
+	void prepareConnecting(Server &, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
+	void prepareDisconnected(Server &, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
+
+public:
+	/**
+	 * Create the server state.
+	 *
+	 * @pre type must be valid
+	 * @param type the type
+	 */
+	ServerState(Type type);
+
+	/**
+	 * Prepare the state.
+	 *
+	 * @param server the server
+	 * @param setinput the read set
+	 * @param setoutput the write set
+	 * @param maxfd the maximum fd
+	 */
+	void prepare(Server &server, fd_set &setinput, fd_set &setoutput, net::Handle &maxfd);
+
+	/**
+	 * Get the state type.
+	 *
+	 * @return the type
+	 */
+	inline Type type() const noexcept
+	{
+		return m_type;
+	}
+};
+
+} // !irccd
+
+#endif // !IRCCD_SERVER_STATE_HPP
--- a/lib/irccd/server.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/server.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -23,9 +23,9 @@
 
 #include <libirc_rfcnumeric.h>
 
-#include "logger.h"
-#include "server-private.h"
-#include "util.h"
+#include "logger.hpp"
+#include "server-private.hpp"
+#include "util.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/server.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
-/*
- * server.h -- an IRC server
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SERVER_H
-#define IRCCD_SERVER_H
-
-/**
- * @file server.h
- * @brief IRC Server.
- */
-
-#include <cstdint>
-#include <functional>
-#include <map>
-#include <memory>
-#include <queue>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include <irccd/sysconfig.h>
-
-#include "logger.h"
-#include "server-state.h"
-#include "signals.h"
-
-namespace irccd {
-
-/**
- * @class ServerIdentity
- * @brief Identity to use when connecting
- */
-class ServerIdentity {
-public:
-	std::string name{"irccd"};			//!< identity name
-	std::string nickname{"irccd"};			//!< nickname to show
-	std::string username{"irccd"};			//!< username to use for connection
-	std::string realname{"IRC Client Daemon"};	//!< the full real name
-	std::string ctcpversion{"IRC Client Daemon"};	//!< the CTCP version to define
-};
-
-/**
- * @class ServerChannel
- * @brief A channel to join with an optional password
- */
-class ServerChannel {
-public:
-	std::string name;				//!< the channel to join
-	std::string password;				//!< the optional password
-};
-
-/**
- * List of channels.
- */
-using ServerChannels = std::vector<ServerChannel>;
-
-/**
- * @enum ServerChanMode
- * @brief Prefixes for nicknames
- */
-enum class ServerChanMode {
-	Creator		= 'O',			//!< Channel creator
-	HalfOperator	= 'h',			//!< Half operator
-	Operator	= 'o',			//!< Channel operator
-	Protection	= 'a',			//!< Unkillable
-	Voiced		= 'v'			//!< Voice power
-};
-
-/**
- * @class ServerWhois
- * @brief Describe a whois information
- *
- * This is provided when whois command was requested.
- */
-class ServerWhois {
-public:
-	std::string nick;			//!< user's nickname
-	std::string user;			//!< user's user
-	std::string host;			//!< hostname
-	std::string realname;			//!< realname
-	std::vector<std::string> channels;	//!< the channels where the user is
-};
-
-/**
- * @class ServerInfo
- * @brief Server information
- *
- * This class contains everything needed to connect to a server.
- */
-class ServerInfo {
-public:
-	enum {
-		Ipv6		= (1 << 0),	//!< Connect using IPv6
-		Ssl		= (1 << 1),	//!< Use SSL
-		SslVerify	= (1 << 2)	//!< Verify SSL
-	};
-
-	std::string name;			//!< Server's name
-	std::string host;			//!< Hostname
-	std::string password;			//!< Optional server password
-	std::uint16_t port{6667};		//!< Server's port
-	std::uint8_t flags{0};			//!< Optional flags
-	std::map<ServerChanMode, char> modes;	//!< IRC modes (e.g. @~)
-};
-
-/**
- * @class ServerSettings
- * @brief Contains settings to tweak the server
- *
- * This class contains additional settings that tweaks the
- * server operations.
- */
-class ServerSettings {
-public:
-	enum {
-		AutoRejoin	= (1 << 0),	//!< Auto rejoin a channel after being kicked
-		JoinInvite	= (1 << 1)	//!< Join a channel on invitation
-	};
-
-	ServerChannels channels;		//!< List of channel to join
-	std::string command{"!"};		//!< The command character to trigger plugin command
-	std::int8_t recotries{-1};		//!< Number of tries to reconnect before giving up
-	std::uint16_t recotimeout{30};		//!< Number of seconds to wait before trying to connect
-	std::uint8_t flags{0};			//!< Optional flags
-
-	/* Private */
-	std::int8_t recocurrent{1};		//!< number of tries tested
-};
-
-/**
- * Deferred command to send to the server.
- *
- * If the command returns true, it has been correctly buffered for outgoing
- * and removed from the queue.
- */
-using ServerCommand = std::function<bool ()>;
-
-/**
- * @class Server
- * @brief The class that connect to a IRC server
- *
- * The server is a class that stores callbacks which will be called on IRC events. It is the lowest part of the
- * connection to a server, it can be used directly by the user to connect to a server.
- *
- * The server has several signals that will be emitted when data has arrived.
- *
- * When adding a server to the irccd instance using Irccd::addServer, these signals are connected to generate
- * events that will be dispatched to the plugins and to the transports.
- *
- * Note: the server is set in non blocking mode, commands are placed in a queue and sent when only when they are ready.
- */
-class Server {
-public:
-	/**
-	 * Bridge for libircclient.
-	 */
-	class Session;
-
-	/**
-	 * Signal: onChannelMode
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone changed the channel mode.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the channel
-	 * - the mode
-	 * - the optional mode argument
-	 */
-	Signal<std::string, std::string, std::string, std::string> onChannelMode;
-
-	/**
-	 * Signal: onChannelNotice
-	 * ------------------------------------------------
-	 *
-	 * Triggered when a notice has been sent on a channel.
-	 *
-	 * Arguments:
-	 * - the origin (the nickname who has sent the notice)
-	 * - the channel name
-	 * - the notice message
-	 */
-	Signal<std::string, std::string, std::string> onChannelNotice;
-
-	/**
-	 * Signal: onConnect
-	 * ------------------------------------------------
-	 *
-	 * Triggered when the server is successfully connected.
-	 */
-	Signal<> onConnect;
-
-	/**
-	 * Signal: onDie
-	 * ----------------------------------------------------------
-	 *
-	 * The server is dead.
-	 */
-	Signal<> onDie;
-
-	/**
-	 * Signal: onInvite
-	 * ------------------------------------------------
-	 *
-	 * Triggered when an invite has been sent to you (the bot).
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the channel
-	 * - your nickname
-	 */
-	Signal<std::string, std::string, std::string> onInvite;
-
-	/**
-	 * Signal: onJoin
-	 * ------------------------------------------------
-	 *
-	 * Triggered when a user has joined the channel, it also includes you.
-	 *
-	 * Arguments:
-	 * - the origin (may be you)
-	 * - the channel
-	 */
-	Signal<std::string, std::string> onJoin;
-
-	/**
-	 * Signal: onKick
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone has been kicked from a channel.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the channel
-	 * - the target who has been kicked
-	 * - the optional reason
-	 */
-	Signal<std::string, std::string, std::string, std::string> onKick;
-
-	/**
-	 * ServerEvent: onMessage
-	 * ------------------------------------------------
-	 *
-	 * Triggered when a message on a channel has been sent.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the channel
-	 * - the message
-	 */
-	Signal<std::string, std::string, std::string> onMessage;
-
-	/**
-	 * Signal: onMe
-	 * ------------------------------------------------
-	 *
-	 * Triggered on a CTCP Action.
-	 *
-	 * This is both used in a channel and in a private message so the target
-	 * may be a channel or your nickname.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the target
-	 * - the message
-	 */
-	Signal<std::string, std::string, std::string> onMe;
-
-	/**
-	 * Signal: onMode
-	 * ------------------------------------------------
-	 *
-	 * Triggered when the server changed your user mode.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the mode (e.g +i)
-	 */
-	Signal<std::string, std::string> onMode;
-
-	/**
-	 * Signal: onNames
-	 * ------------------------------------------------
-	 *
-	 * Triggered when names listing has finished on a channel.
-	 *
-	 * Arguments:
-	 * - the channel
-	 * - the ordered list of names
-	 */
-	Signal<std::string, std::set<std::string>> onNames;
-
-	/**
-	 * Signal: onNick
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone changed its nickname, it also includes you.
-	 *
-	 * Arguments:
-	 * - the old nickname (may be you)
-	 * - the new nickname
-	 */
-	Signal<std::string, std::string> onNick;
-
-	/**
-	 * Signal: onNotice
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone has sent a notice to you.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the notice message
-	 */
-	Signal<std::string, std::string> onNotice;
-
-	/**
-	 * Signal: onPart
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone has left the channel.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the channel that the nickname has left
-	 * - the optional reason
-	 */
-	Signal<std::string, std::string, std::string> onPart;
-
-	/**
-	 * Signal: onQuery
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone has sent you a private message.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the message
-	 */
-	Signal<std::string, std::string> onQuery;
-
-	/**
-	 * Signal: onTopic
-	 * ------------------------------------------------
-	 *
-	 * Triggered when someone changed the channel topic.
-	 *
-	 * Arguments:
-	 * - the origin
-	 * - the channel
-	 * - the new topic
-	 */
-	Signal<std::string, std::string, std::string> onTopic;
-
-	/**
-	 * Signal: onWhois
-	 * ------------------------------------------------
-	 *
-	 * Triggered when whois information has been received.
-	 *
-	 * Arguments:
-	 * - the whois object
-	 */
-	Signal<ServerWhois> onWhois;
-
-private:
-	using SessionPtr = std::unique_ptr<Session>;
-	using Queue = std::queue<ServerCommand>;
-
-	/**
-	 * List of NAMES being built.
-	 */
-	using NamesMap = std::unordered_map<std::string, std::set<std::string>>;
-
-	/**
-	 * List of WHOIS being built.
-	 */
-	using WhoisMap	= std::unordered_map<std::string, ServerWhois>;
-
-private:
-	ServerInfo m_info;
-	ServerSettings m_settings;
-	ServerIdentity m_identity;
-	SessionPtr m_session;
-	ServerState m_state;
-	ServerState m_next;
-	Queue m_queue;
-
-	/*
-	 * The names map is being built by a successive call to handleNumeric so we need to store a temporary
-	 * map by channels to list of names. Then, when we receive the end of names listing, we remove the
-	 * temporary set of names and calls the appropriate signal.
-	 */
-	NamesMap m_namesMap;
-	WhoisMap m_whoisMap;
-
-	bool isSelf(const std::string &nick) const noexcept;
-	void extractPrefixes(const std::string &line);
-	std::string cleanPrefix(std::string nickname) const noexcept;
-
-	inline std::string strify(const char *s)
-	{
-		return (s == nullptr) ? "" : std::string(s);
-	}
-
-	void handleChannel(const char *, const char **) noexcept;
-	void handleChannelMode(const char *, const char **) noexcept;
-	void handleChannelNotice(const char *, const char **) noexcept;
-	void handleConnect(const char *, const char **) noexcept;
-	void handleCtcpAction(const char *, const char **) noexcept;
-	void handleInvite(const char *, const char **) noexcept;
-	void handleJoin(const char *, const char **) noexcept;
-	void handleKick(const char *, const char **) noexcept;
-	void handleMode(const char *, const char **) noexcept;
-	void handleNick(const char *, const char **) noexcept;
-	void handleNotice(const char *, const char **) noexcept;
-	void handleNumeric(unsigned int, const char **, unsigned int) noexcept;
-	void handlePart(const char *, const char **) noexcept;
-	void handleQuery(const char *, const char **) noexcept;
-	void handleTopic(const char *, const char **) noexcept;
-
-public:
-	/**
-	 * Split a channel from the form channel:password into a ServerChannel object.
-	 *
-	 * @param value the value
-	 * @return a channel
-	 */
-	static ServerChannel splitChannel(const std::string &value);
-
-	/**
-	 * Construct a server.
-	 *
-	 * @param info the information
-	 * @param identity the identity
-	 * @param settings the settings
-	 */
-	Server(ServerInfo info, ServerIdentity identity = {}, ServerSettings settings = {});
-
-	/**
-	 * Destructor. Close the connection if needed.
-	 */
-	virtual ~Server();
-
-	/**
-	 * Set the next state to be used. This function is thread safe because
-	 * the server manager may set the next state to the current state.
-	 *
-	 * If the server is installed into the ServerManager, it is called
-	 * automatically.
-	 *
-	 * @param type the new state type
-	 * @warning Not thread-safe
-	 */
-	inline void next(ServerState::Type type)
-	{
-		m_next = ServerState(type);
-	}
-
-	/**
-	 * Switch to next state if it has.
-	 *
-	 * If the server is installed into irccd, it is called automatically.
-	 *
-	 * @warning Not thread-safe
-	 */
-	void update() noexcept;
-
-	/**
-	 * Request to disconnect. This function does not notify the
-	 * ServerService.
-	 *
-	 * @see Irccd::serverDisconnect
-	 * @note Thread-safe
-	 */
-	void disconnect() noexcept;
-
-	/**
-	 * Asks for a reconnection. This function does not notify the
-	 * ServerService.
-	 *
-	 * @see Irccd::serverReconnect
-	 * @note Thread-safe
-	 */
-	void reconnect() noexcept;
-
-	/**
-	 * Flush the pending commands if possible. This function will send
-	 * as much as possible commands.
-	 *
-	 * If the server is installed into the ServerManager, it is called
-	 * automatically.
-	 *
-	 * @note Thread-safe
-	 */
-	void flush() noexcept;
-
-	/**
-	 * Prepare the IRC Session to the socket.
-	 *
-	 * If the server is installed into the ServerManager, it is called
-	 * automatically.
-	 *
-	 * @warning Not thread-safe
-	 */
-	inline void prepare(fd_set &setinput, fd_set &setoutput, net::Handle &maxfd) noexcept
-	{
-		m_state.prepare(*this, setinput, setoutput, maxfd);
-	}
-
-	/**
-	 * Process incoming/outgoing data after selection.
-	 *
-	 * If the server is installed into the ServerManager, it is called
-	 * automatically.
-	 *
-	 * @param setinput
-	 * @param setoutput
-	 * @throw any exception that have been throw from user functions
-	 */
-	void sync(fd_set &setinput, fd_set &setoutput) noexcept;
-
-	/**
-	 * Get the server information.
-	 *
-	 * @warning This overload should not be used by the user, it is required to
-	 *          update the nickname.
-	 * @return the server information
-	 */
-	inline ServerInfo &info() noexcept
-	{
-		return m_info;
-	}
-
-	/**
-	 * Get the server information.
-	 *
-	 * @return the server information
-	 */
-	inline const ServerInfo &info() const noexcept
-	{
-		return m_info;
-	}
-
-	/**
-	 * Get the server settings.
-	 *
-	 * @warning This overload should not be used by the user, it is required to
-	 *          update the reconnection information.
-	 * @return the settings
-	 */
-	inline ServerSettings &settings() noexcept
-	{
-		return m_settings;
-	}
-
-	/**
-	 * Get the server settings.
-	 *
-	 * @return the settings
-	 */
-	inline const ServerSettings &settings() const noexcept
-	{
-		return m_settings;
-	}
-
-	/**
-	 * Get the identity.
-	 *
-	 * @return the identity
-	 */
-	inline ServerIdentity &identity() noexcept
-	{
-		return m_identity;
-	}
-
-	/**
-	 * Overloaded function
-	 *
-	 * @return the identity
-	 */
-	inline const ServerIdentity &identity() const noexcept
-	{
-		return m_identity;
-	}
-
-	/**
-	 * Get the current state identifier. Should not be used by user code.
-	 *
-	 * @note Thread-safe but the state may change just after the call
-	 */
-	inline ServerState::Type type() const noexcept
-	{
-		return m_state.type();
-	}
-
-	/**
-	 * Get the private session.
-	 *
-	 * @return the session
-	 */
-	inline Session &session() noexcept
-	{
-		return *m_session;
-	}
-
-	/**
-	 * Change the channel mode.
-	 *
-	 * @param channel the channel
-	 * @param mode the new mode
-	 * @note Thread-safe
-	 */
-	void cmode(std::string channel, std::string mode);
-
-	/**
-	 * Send a channel notice.
-	 *
-	 * @param channel the channel
-	 * @param message message notice
-	 * @note Thread-safe
-	 */
-	void cnotice(std::string channel, std::string message) noexcept;
-
-	/**
-	 * Invite a user to a channel.
-	 *
-	 * @param target the target nickname
-	 * @param channel the channel
-	 * @note Thread-safe
-	 */
-	void invite(std::string target, std::string channel) noexcept;
-
-	/**
-	 * Join a channel, the password is optional and can be kept empty.
-	 *
-	 * @param channel the channel to join
-	 * @param password the optional password
-	 * @note Thread-safe
-	 */
-	void join(std::string channel, std::string password = "") noexcept;
-
-	/**
-	 * Kick someone from the channel. Please be sure to have the rights
-	 * on that channel because errors won't be reported.
-	 *
-	 * @param target the target to kick
-	 * @param channel from which channel
-	 * @param reason the optional reason
-	 * @note Thread-safe
-	 */
-	void kick(std::string target, std::string channel, std::string reason = "") noexcept;
-
-	/**
-	 * Send a CTCP Action as known as /me. The target may be either a
-	 * channel or a nickname.
-	 *
-	 * @param target the nickname or the channel
-	 * @param message the message
-	 * @note Thread-safe
-	 */
-	void me(std::string target, std::string message);
-
-	/**
-	 * Send a message to the specified target or channel.
-	 *
-	 * @param target the target
-	 * @param message the message
-	 * @note Thread-safe
-	 */
-	void message(std::string target, std::string message);
-
-	/**
-	 * Change your user mode.
-	 *
-	 * @param mode the mode
-	 * @note Thread-safe
-	 */
-	void mode(std::string mode);
-
-	/**
-	 * Request the list of names.
-	 *
-	 * @param channel the channel
-	 * @note Thread-safe
-	 */
-	void names(std::string channel);
-
-	/**
-	 * Change your nickname.
-	 *
-	 * @param newnick the new nickname to use
-	 * @note Thread-safe
-	 */
-	void nick(std::string newnick);
-
-	/**
-	 * Send a private notice.
-	 *
-	 * @param target the target
-	 * @param message the notice message
-	 * @note Thread-safe
-	 */
-	void notice(std::string target, std::string message);
-
-	/**
-	 * Part from a channel.
-	 *
-	 * Please note that the reason is not supported on all servers so if you want portability, don't provide it.
-	 *
-	 * @param channel the channel to leave
-	 * @param reason the optional reason
-	 * @note Thread-safe
-	 */
-	void part(std::string channel, std::string reason = "");
-
-	/**
-	 * Send a raw message to the IRC server. You don't need to add
-	 * message terminators.
-	 *
-	 * @warning Use this function with care
-	 * @param raw the raw message (without `\r\n\r\n`)
-	 * @note Thread-safe
-	 */
-	void send(std::string raw);
-
-	/**
-	 * Change the channel topic.
-	 *
-	 * @param channel the channel
-	 * @param topic the desired topic
-	 * @note Thread-safe
-	 */
-	void topic(std::string channel, std::string topic);
-
-	/**
-	 * Request for whois information.
-	 *
-	 * @param target the target nickname
-	 * @note Thread-safe
-	 */
-	void whois(std::string target);
-};
-
-} // !irccd
-
-#endif // !IRCCD_SERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/server.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,765 @@
+/*
+ * server.hpp -- an IRC server
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SERVER_HPP
+#define IRCCD_SERVER_HPP
+
+/**
+ * @file server.hpp
+ * @brief IRC Server.
+ */
+
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <memory>
+#include <queue>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <irccd/sysconfig.hpp>
+
+#include "logger.hpp"
+#include "server-state.hpp"
+#include "signals.hpp"
+
+namespace irccd {
+
+/**
+ * @class ServerIdentity
+ * @brief Identity to use when connecting
+ */
+class ServerIdentity {
+public:
+	std::string name{"irccd"};			//!< identity name
+	std::string nickname{"irccd"};			//!< nickname to show
+	std::string username{"irccd"};			//!< username to use for connection
+	std::string realname{"IRC Client Daemon"};	//!< the full real name
+	std::string ctcpversion{"IRC Client Daemon"};	//!< the CTCP version to define
+};
+
+/**
+ * @class ServerChannel
+ * @brief A channel to join with an optional password
+ */
+class ServerChannel {
+public:
+	std::string name;				//!< the channel to join
+	std::string password;				//!< the optional password
+};
+
+/**
+ * List of channels.
+ */
+using ServerChannels = std::vector<ServerChannel>;
+
+/**
+ * @enum ServerChanMode
+ * @brief Prefixes for nicknames
+ */
+enum class ServerChanMode {
+	Creator		= 'O',			//!< Channel creator
+	HalfOperator	= 'h',			//!< Half operator
+	Operator	= 'o',			//!< Channel operator
+	Protection	= 'a',			//!< Unkillable
+	Voiced		= 'v'			//!< Voice power
+};
+
+/**
+ * @class ServerWhois
+ * @brief Describe a whois information
+ *
+ * This is provided when whois command was requested.
+ */
+class ServerWhois {
+public:
+	std::string nick;			//!< user's nickname
+	std::string user;			//!< user's user
+	std::string host;			//!< hostname
+	std::string realname;			//!< realname
+	std::vector<std::string> channels;	//!< the channels where the user is
+};
+
+/**
+ * @class ServerInfo
+ * @brief Server information
+ *
+ * This class contains everything needed to connect to a server.
+ */
+class ServerInfo {
+public:
+	enum {
+		Ipv6		= (1 << 0),	//!< Connect using IPv6
+		Ssl		= (1 << 1),	//!< Use SSL
+		SslVerify	= (1 << 2)	//!< Verify SSL
+	};
+
+	std::string name;			//!< Server's name
+	std::string host;			//!< Hostname
+	std::string password;			//!< Optional server password
+	std::uint16_t port{6667};		//!< Server's port
+	std::uint8_t flags{0};			//!< Optional flags
+	std::map<ServerChanMode, char> modes;	//!< IRC modes (e.g. @~)
+};
+
+/**
+ * @class ServerSettings
+ * @brief Contains settings to tweak the server
+ *
+ * This class contains additional settings that tweaks the
+ * server operations.
+ */
+class ServerSettings {
+public:
+	enum {
+		AutoRejoin	= (1 << 0),	//!< Auto rejoin a channel after being kicked
+		JoinInvite	= (1 << 1)	//!< Join a channel on invitation
+	};
+
+	ServerChannels channels;		//!< List of channel to join
+	std::string command{"!"};		//!< The command character to trigger plugin command
+	std::int8_t recotries{-1};		//!< Number of tries to reconnect before giving up
+	std::uint16_t recotimeout{30};		//!< Number of seconds to wait before trying to connect
+	std::uint8_t flags{0};			//!< Optional flags
+
+	/* Private */
+	std::int8_t recocurrent{1};		//!< number of tries tested
+};
+
+/**
+ * Deferred command to send to the server.
+ *
+ * If the command returns true, it has been correctly buffered for outgoing
+ * and removed from the queue.
+ */
+using ServerCommand = std::function<bool ()>;
+
+/**
+ * @class Server
+ * @brief The class that connect to a IRC server
+ *
+ * The server is a class that stores callbacks which will be called on IRC events. It is the lowest part of the
+ * connection to a server, it can be used directly by the user to connect to a server.
+ *
+ * The server has several signals that will be emitted when data has arrived.
+ *
+ * When adding a server to the irccd instance using Irccd::addServer, these signals are connected to generate
+ * events that will be dispatched to the plugins and to the transports.
+ *
+ * Note: the server is set in non blocking mode, commands are placed in a queue and sent when only when they are ready.
+ */
+class Server {
+public:
+	/**
+	 * Bridge for libircclient.
+	 */
+	class Session;
+
+	/**
+	 * Signal: onChannelMode
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone changed the channel mode.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the channel
+	 * - the mode
+	 * - the optional mode argument
+	 */
+	Signal<std::string, std::string, std::string, std::string> onChannelMode;
+
+	/**
+	 * Signal: onChannelNotice
+	 * ------------------------------------------------
+	 *
+	 * Triggered when a notice has been sent on a channel.
+	 *
+	 * Arguments:
+	 * - the origin (the nickname who has sent the notice)
+	 * - the channel name
+	 * - the notice message
+	 */
+	Signal<std::string, std::string, std::string> onChannelNotice;
+
+	/**
+	 * Signal: onConnect
+	 * ------------------------------------------------
+	 *
+	 * Triggered when the server is successfully connected.
+	 */
+	Signal<> onConnect;
+
+	/**
+	 * Signal: onDie
+	 * ----------------------------------------------------------
+	 *
+	 * The server is dead.
+	 */
+	Signal<> onDie;
+
+	/**
+	 * Signal: onInvite
+	 * ------------------------------------------------
+	 *
+	 * Triggered when an invite has been sent to you (the bot).
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the channel
+	 * - your nickname
+	 */
+	Signal<std::string, std::string, std::string> onInvite;
+
+	/**
+	 * Signal: onJoin
+	 * ------------------------------------------------
+	 *
+	 * Triggered when a user has joined the channel, it also includes you.
+	 *
+	 * Arguments:
+	 * - the origin (may be you)
+	 * - the channel
+	 */
+	Signal<std::string, std::string> onJoin;
+
+	/**
+	 * Signal: onKick
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone has been kicked from a channel.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the channel
+	 * - the target who has been kicked
+	 * - the optional reason
+	 */
+	Signal<std::string, std::string, std::string, std::string> onKick;
+
+	/**
+	 * ServerEvent: onMessage
+	 * ------------------------------------------------
+	 *
+	 * Triggered when a message on a channel has been sent.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the channel
+	 * - the message
+	 */
+	Signal<std::string, std::string, std::string> onMessage;
+
+	/**
+	 * Signal: onMe
+	 * ------------------------------------------------
+	 *
+	 * Triggered on a CTCP Action.
+	 *
+	 * This is both used in a channel and in a private message so the target
+	 * may be a channel or your nickname.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the target
+	 * - the message
+	 */
+	Signal<std::string, std::string, std::string> onMe;
+
+	/**
+	 * Signal: onMode
+	 * ------------------------------------------------
+	 *
+	 * Triggered when the server changed your user mode.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the mode (e.g +i)
+	 */
+	Signal<std::string, std::string> onMode;
+
+	/**
+	 * Signal: onNames
+	 * ------------------------------------------------
+	 *
+	 * Triggered when names listing has finished on a channel.
+	 *
+	 * Arguments:
+	 * - the channel
+	 * - the ordered list of names
+	 */
+	Signal<std::string, std::set<std::string>> onNames;
+
+	/**
+	 * Signal: onNick
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone changed its nickname, it also includes you.
+	 *
+	 * Arguments:
+	 * - the old nickname (may be you)
+	 * - the new nickname
+	 */
+	Signal<std::string, std::string> onNick;
+
+	/**
+	 * Signal: onNotice
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone has sent a notice to you.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the notice message
+	 */
+	Signal<std::string, std::string> onNotice;
+
+	/**
+	 * Signal: onPart
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone has left the channel.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the channel that the nickname has left
+	 * - the optional reason
+	 */
+	Signal<std::string, std::string, std::string> onPart;
+
+	/**
+	 * Signal: onQuery
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone has sent you a private message.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the message
+	 */
+	Signal<std::string, std::string> onQuery;
+
+	/**
+	 * Signal: onTopic
+	 * ------------------------------------------------
+	 *
+	 * Triggered when someone changed the channel topic.
+	 *
+	 * Arguments:
+	 * - the origin
+	 * - the channel
+	 * - the new topic
+	 */
+	Signal<std::string, std::string, std::string> onTopic;
+
+	/**
+	 * Signal: onWhois
+	 * ------------------------------------------------
+	 *
+	 * Triggered when whois information has been received.
+	 *
+	 * Arguments:
+	 * - the whois object
+	 */
+	Signal<ServerWhois> onWhois;
+
+private:
+	using SessionPtr = std::unique_ptr<Session>;
+	using Queue = std::queue<ServerCommand>;
+
+	/**
+	 * List of NAMES being built.
+	 */
+	using NamesMap = std::unordered_map<std::string, std::set<std::string>>;
+
+	/**
+	 * List of WHOIS being built.
+	 */
+	using WhoisMap	= std::unordered_map<std::string, ServerWhois>;
+
+private:
+	ServerInfo m_info;
+	ServerSettings m_settings;
+	ServerIdentity m_identity;
+	SessionPtr m_session;
+	ServerState m_state;
+	ServerState m_next;
+	Queue m_queue;
+
+	/*
+	 * The names map is being built by a successive call to handleNumeric so we need to store a temporary
+	 * map by channels to list of names. Then, when we receive the end of names listing, we remove the
+	 * temporary set of names and calls the appropriate signal.
+	 */
+	NamesMap m_namesMap;
+	WhoisMap m_whoisMap;
+
+	bool isSelf(const std::string &nick) const noexcept;
+	void extractPrefixes(const std::string &line);
+	std::string cleanPrefix(std::string nickname) const noexcept;
+
+	inline std::string strify(const char *s)
+	{
+		return (s == nullptr) ? "" : std::string(s);
+	}
+
+	void handleChannel(const char *, const char **) noexcept;
+	void handleChannelMode(const char *, const char **) noexcept;
+	void handleChannelNotice(const char *, const char **) noexcept;
+	void handleConnect(const char *, const char **) noexcept;
+	void handleCtcpAction(const char *, const char **) noexcept;
+	void handleInvite(const char *, const char **) noexcept;
+	void handleJoin(const char *, const char **) noexcept;
+	void handleKick(const char *, const char **) noexcept;
+	void handleMode(const char *, const char **) noexcept;
+	void handleNick(const char *, const char **) noexcept;
+	void handleNotice(const char *, const char **) noexcept;
+	void handleNumeric(unsigned int, const char **, unsigned int) noexcept;
+	void handlePart(const char *, const char **) noexcept;
+	void handleQuery(const char *, const char **) noexcept;
+	void handleTopic(const char *, const char **) noexcept;
+
+public:
+	/**
+	 * Split a channel from the form channel:password into a ServerChannel object.
+	 *
+	 * @param value the value
+	 * @return a channel
+	 */
+	static ServerChannel splitChannel(const std::string &value);
+
+	/**
+	 * Construct a server.
+	 *
+	 * @param info the information
+	 * @param identity the identity
+	 * @param settings the settings
+	 */
+	Server(ServerInfo info, ServerIdentity identity = {}, ServerSettings settings = {});
+
+	/**
+	 * Destructor. Close the connection if needed.
+	 */
+	virtual ~Server();
+
+	/**
+	 * Set the next state to be used. This function is thread safe because
+	 * the server manager may set the next state to the current state.
+	 *
+	 * If the server is installed into the ServerManager, it is called
+	 * automatically.
+	 *
+	 * @param type the new state type
+	 * @warning Not thread-safe
+	 */
+	inline void next(ServerState::Type type)
+	{
+		m_next = ServerState(type);
+	}
+
+	/**
+	 * Switch to next state if it has.
+	 *
+	 * If the server is installed into irccd, it is called automatically.
+	 *
+	 * @warning Not thread-safe
+	 */
+	void update() noexcept;
+
+	/**
+	 * Request to disconnect. This function does not notify the
+	 * ServerService.
+	 *
+	 * @see Irccd::serverDisconnect
+	 * @note Thread-safe
+	 */
+	void disconnect() noexcept;
+
+	/**
+	 * Asks for a reconnection. This function does not notify the
+	 * ServerService.
+	 *
+	 * @see Irccd::serverReconnect
+	 * @note Thread-safe
+	 */
+	void reconnect() noexcept;
+
+	/**
+	 * Flush the pending commands if possible. This function will send
+	 * as much as possible commands.
+	 *
+	 * If the server is installed into the ServerManager, it is called
+	 * automatically.
+	 *
+	 * @note Thread-safe
+	 */
+	void flush() noexcept;
+
+	/**
+	 * Prepare the IRC Session to the socket.
+	 *
+	 * If the server is installed into the ServerManager, it is called
+	 * automatically.
+	 *
+	 * @warning Not thread-safe
+	 */
+	inline void prepare(fd_set &setinput, fd_set &setoutput, net::Handle &maxfd) noexcept
+	{
+		m_state.prepare(*this, setinput, setoutput, maxfd);
+	}
+
+	/**
+	 * Process incoming/outgoing data after selection.
+	 *
+	 * If the server is installed into the ServerManager, it is called
+	 * automatically.
+	 *
+	 * @param setinput
+	 * @param setoutput
+	 * @throw any exception that have been throw from user functions
+	 */
+	void sync(fd_set &setinput, fd_set &setoutput) noexcept;
+
+	/**
+	 * Get the server information.
+	 *
+	 * @warning This overload should not be used by the user, it is required to
+	 *          update the nickname.
+	 * @return the server information
+	 */
+	inline ServerInfo &info() noexcept
+	{
+		return m_info;
+	}
+
+	/**
+	 * Get the server information.
+	 *
+	 * @return the server information
+	 */
+	inline const ServerInfo &info() const noexcept
+	{
+		return m_info;
+	}
+
+	/**
+	 * Get the server settings.
+	 *
+	 * @warning This overload should not be used by the user, it is required to
+	 *          update the reconnection information.
+	 * @return the settings
+	 */
+	inline ServerSettings &settings() noexcept
+	{
+		return m_settings;
+	}
+
+	/**
+	 * Get the server settings.
+	 *
+	 * @return the settings
+	 */
+	inline const ServerSettings &settings() const noexcept
+	{
+		return m_settings;
+	}
+
+	/**
+	 * Get the identity.
+	 *
+	 * @return the identity
+	 */
+	inline ServerIdentity &identity() noexcept
+	{
+		return m_identity;
+	}
+
+	/**
+	 * Overloaded function
+	 *
+	 * @return the identity
+	 */
+	inline const ServerIdentity &identity() const noexcept
+	{
+		return m_identity;
+	}
+
+	/**
+	 * Get the current state identifier. Should not be used by user code.
+	 *
+	 * @note Thread-safe but the state may change just after the call
+	 */
+	inline ServerState::Type type() const noexcept
+	{
+		return m_state.type();
+	}
+
+	/**
+	 * Get the private session.
+	 *
+	 * @return the session
+	 */
+	inline Session &session() noexcept
+	{
+		return *m_session;
+	}
+
+	/**
+	 * Change the channel mode.
+	 *
+	 * @param channel the channel
+	 * @param mode the new mode
+	 * @note Thread-safe
+	 */
+	void cmode(std::string channel, std::string mode);
+
+	/**
+	 * Send a channel notice.
+	 *
+	 * @param channel the channel
+	 * @param message message notice
+	 * @note Thread-safe
+	 */
+	void cnotice(std::string channel, std::string message) noexcept;
+
+	/**
+	 * Invite a user to a channel.
+	 *
+	 * @param target the target nickname
+	 * @param channel the channel
+	 * @note Thread-safe
+	 */
+	void invite(std::string target, std::string channel) noexcept;
+
+	/**
+	 * Join a channel, the password is optional and can be kept empty.
+	 *
+	 * @param channel the channel to join
+	 * @param password the optional password
+	 * @note Thread-safe
+	 */
+	void join(std::string channel, std::string password = "") noexcept;
+
+	/**
+	 * Kick someone from the channel. Please be sure to have the rights
+	 * on that channel because errors won't be reported.
+	 *
+	 * @param target the target to kick
+	 * @param channel from which channel
+	 * @param reason the optional reason
+	 * @note Thread-safe
+	 */
+	void kick(std::string target, std::string channel, std::string reason = "") noexcept;
+
+	/**
+	 * Send a CTCP Action as known as /me. The target may be either a
+	 * channel or a nickname.
+	 *
+	 * @param target the nickname or the channel
+	 * @param message the message
+	 * @note Thread-safe
+	 */
+	void me(std::string target, std::string message);
+
+	/**
+	 * Send a message to the specified target or channel.
+	 *
+	 * @param target the target
+	 * @param message the message
+	 * @note Thread-safe
+	 */
+	void message(std::string target, std::string message);
+
+	/**
+	 * Change your user mode.
+	 *
+	 * @param mode the mode
+	 * @note Thread-safe
+	 */
+	void mode(std::string mode);
+
+	/**
+	 * Request the list of names.
+	 *
+	 * @param channel the channel
+	 * @note Thread-safe
+	 */
+	void names(std::string channel);
+
+	/**
+	 * Change your nickname.
+	 *
+	 * @param newnick the new nickname to use
+	 * @note Thread-safe
+	 */
+	void nick(std::string newnick);
+
+	/**
+	 * Send a private notice.
+	 *
+	 * @param target the target
+	 * @param message the notice message
+	 * @note Thread-safe
+	 */
+	void notice(std::string target, std::string message);
+
+	/**
+	 * Part from a channel.
+	 *
+	 * Please note that the reason is not supported on all servers so if you want portability, don't provide it.
+	 *
+	 * @param channel the channel to leave
+	 * @param reason the optional reason
+	 * @note Thread-safe
+	 */
+	void part(std::string channel, std::string reason = "");
+
+	/**
+	 * Send a raw message to the IRC server. You don't need to add
+	 * message terminators.
+	 *
+	 * @warning Use this function with care
+	 * @param raw the raw message (without `\r\n\r\n`)
+	 * @note Thread-safe
+	 */
+	void send(std::string raw);
+
+	/**
+	 * Change the channel topic.
+	 *
+	 * @param channel the channel
+	 * @param topic the desired topic
+	 * @note Thread-safe
+	 */
+	void topic(std::string channel, std::string topic);
+
+	/**
+	 * Request for whois information.
+	 *
+	 * @param target the target nickname
+	 * @note Thread-safe
+	 */
+	void whois(std::string target);
+};
+
+} // !irccd
+
+#endif // !IRCCD_SERVER_HPP
--- a/lib/irccd/signals.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * signals.h -- synchronous observer mechanism
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SIGNALS_H
-#define IRCCD_SIGNALS_H
-
-#include <functional>
-#include <stack>
-#include <unordered_map>
-#include <vector>
-
-/**
- * @file signals.h
- * @brief Similar Qt signal subsystem for irccd
- */
-
-namespace irccd {
-
-/**
- * @class SignalConnection
- * @brief Stores the reference to the callable
- *
- * This class can be stored to remove a registered function from a Signal, be
- * careful to not mix connections between different signals as they are just
- * referenced by ids.
- */
-class SignalConnection {
-private:
-	unsigned m_id;
-
-public:
-	/**
-	 * Create a signal connection.
-	 *
-	 * @param id the id
-	 */
-	inline SignalConnection(unsigned id) noexcept
-		: m_id(id)
-	{
-	}
-
-	/**
-	 * Get the reference object.
-	 *
-	 * @return the id
-	 */
-	inline unsigned id() const noexcept
-	{
-		return m_id;
-	}
-};
-
-/**
- * @class Signal
- * @brief Stores and call registered functions
- *
- * This class is intended to be use as a public field in the desired object.
- *
- * The user just have to call one of connect(), disconnect() or the call
- * operator to use this class.
- *
- * It stores the callable as std::function so type-erasure is complete.
- *
- * The user is responsible of taking care that the object is still alive
- * in case that the function takes a reference to the object.
- */
-template <typename... Args>
-class Signal {
-private:
-	using Function = std::function<void (Args...)>;
-	using FunctionMap = std::unordered_map<unsigned, Function>;
-	using Stack = std::stack<unsigned>;
-
-	FunctionMap m_functions;
-	Stack m_stack;
-	unsigned m_max{0};
-
-public:
-	/**
-	 * Register a new function to the signal.
-	 *
-	 * @param function the function
-	 * @return the connection in case you want to remove it
-	 */
-	inline SignalConnection connect(Function function) noexcept
-	{
-		unsigned id;
-
-		if (!m_stack.empty()) {
-			id = m_stack.top();
-			m_stack.pop();
-		} else {
-			id = m_max ++;
-		}
-
-		m_functions.emplace(id, std::move(function));
-
-		return SignalConnection{id};
-	}
-
-	/**
-	 * Disconnect a connection.
-	 *
-	 * @param connection the connection
-	 * @warning Be sure that the connection belongs to that signal
-	 */
-	inline void disconnect(const SignalConnection &connection) noexcept
-	{
-		auto value = m_functions.find(connection.id());
-
-		if (value != m_functions.end()) {
-			m_functions.erase(connection.id());
-			m_stack.push(connection.id());
-		}
-	}
-
-	/**
-	 * Remove all registered functions.
-	 */
-	inline void clear()
-	{
-		m_functions.clear();
-		m_max = 0;
-
-		while (!m_stack.empty())
-			m_stack.pop();
-	}
-
-	/**
-	 * Call every functions.
-	 *
-	 * @param args the arguments to pass to the signal
-	 */
-	void operator()(Args... args) const
-	{
-		/*
-		 * Make a copy of the ids before iterating because the callbacks may eventually remove or modify
-		 * the list.
-		 */
-		std::vector<unsigned> ids;
-
-		for (auto &pair : m_functions)
-			ids.push_back(pair.first);
-
-		/*
-		 * Now iterate while checking if the next id is still available, however if any new signals were
-		 * added while iterating, they will not be called immediately.
-		 */
-		for (unsigned i : ids) {
-			auto it = m_functions.find(i);
-
-			if (it != m_functions.end())
-				it->second(args...);
-		}
-	}
-};
-
-} // !irccd
-
-#endif // !IRCCD_SIGNALS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/signals.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,175 @@
+/*
+ * signals.h -- synchronous observer mechanism
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SIGNALS_H
+#define IRCCD_SIGNALS_H
+
+#include <functional>
+#include <stack>
+#include <unordered_map>
+#include <vector>
+
+/**
+ * @file signals.h
+ * @brief Similar Qt signal subsystem for irccd
+ */
+
+namespace irccd {
+
+/**
+ * @class SignalConnection
+ * @brief Stores the reference to the callable
+ *
+ * This class can be stored to remove a registered function from a Signal, be
+ * careful to not mix connections between different signals as they are just
+ * referenced by ids.
+ */
+class SignalConnection {
+private:
+	unsigned m_id;
+
+public:
+	/**
+	 * Create a signal connection.
+	 *
+	 * @param id the id
+	 */
+	inline SignalConnection(unsigned id) noexcept
+		: m_id(id)
+	{
+	}
+
+	/**
+	 * Get the reference object.
+	 *
+	 * @return the id
+	 */
+	inline unsigned id() const noexcept
+	{
+		return m_id;
+	}
+};
+
+/**
+ * @class Signal
+ * @brief Stores and call registered functions
+ *
+ * This class is intended to be use as a public field in the desired object.
+ *
+ * The user just have to call one of connect(), disconnect() or the call
+ * operator to use this class.
+ *
+ * It stores the callable as std::function so type-erasure is complete.
+ *
+ * The user is responsible of taking care that the object is still alive
+ * in case that the function takes a reference to the object.
+ */
+template <typename... Args>
+class Signal {
+private:
+	using Function = std::function<void (Args...)>;
+	using FunctionMap = std::unordered_map<unsigned, Function>;
+	using Stack = std::stack<unsigned>;
+
+	FunctionMap m_functions;
+	Stack m_stack;
+	unsigned m_max{0};
+
+public:
+	/**
+	 * Register a new function to the signal.
+	 *
+	 * @param function the function
+	 * @return the connection in case you want to remove it
+	 */
+	inline SignalConnection connect(Function function) noexcept
+	{
+		unsigned id;
+
+		if (!m_stack.empty()) {
+			id = m_stack.top();
+			m_stack.pop();
+		} else {
+			id = m_max ++;
+		}
+
+		m_functions.emplace(id, std::move(function));
+
+		return SignalConnection{id};
+	}
+
+	/**
+	 * Disconnect a connection.
+	 *
+	 * @param connection the connection
+	 * @warning Be sure that the connection belongs to that signal
+	 */
+	inline void disconnect(const SignalConnection &connection) noexcept
+	{
+		auto value = m_functions.find(connection.id());
+
+		if (value != m_functions.end()) {
+			m_functions.erase(connection.id());
+			m_stack.push(connection.id());
+		}
+	}
+
+	/**
+	 * Remove all registered functions.
+	 */
+	inline void clear()
+	{
+		m_functions.clear();
+		m_max = 0;
+
+		while (!m_stack.empty())
+			m_stack.pop();
+	}
+
+	/**
+	 * Call every functions.
+	 *
+	 * @param args the arguments to pass to the signal
+	 */
+	void operator()(Args... args) const
+	{
+		/*
+		 * Make a copy of the ids before iterating because the callbacks may eventually remove or modify
+		 * the list.
+		 */
+		std::vector<unsigned> ids;
+
+		for (auto &pair : m_functions)
+			ids.push_back(pair.first);
+
+		/*
+		 * Now iterate while checking if the next id is still available, however if any new signals were
+		 * added while iterating, they will not be called immediately.
+		 */
+		for (unsigned i : ids) {
+			auto it = m_functions.find(i);
+
+			if (it != m_functions.end())
+				it->second(args...);
+		}
+	}
+};
+
+} // !irccd
+
+#endif // !IRCCD_SIGNALS_H
--- a/lib/irccd/sockets.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/sockets.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -23,7 +23,7 @@
 #include <cstring>
 #include <mutex>
 
-#include "sockets.h"
+#include "sockets.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/sockets.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4078 +0,0 @@
-/*
- * sockets.h -- portable C++ socket wrappers
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SOCKETS_H
-#define IRCCD_SOCKETS_H
-
-/**
- * @file sockets.h
- * @brief Portable socket abstraction
- *
- * # Introduction
- *
- * This file is a portable networking library.
- *
- * ## Options
- *
- * The user may set the following variables before compiling these files:
- *
- * ### General options
- *
- * - **SOCKET_NO_AUTO_INIT**: (bool) Set to 0 if you don't want Socket class to
- * automatically calls net::init function and net::finish functions.
- * - **SOCKET_NO_SSL**: (bool) Set to 0 if you don't have access to OpenSSL library.
- * - **SOCKET_NO_AUTO_SSL_INIT**: (bool) Set to 0 if you don't want Socket class with Tls to automatically init
- * the OpenSSL library. You will need to call net::ssl::init and net::ssl::finish.
- *
- * ### Options for Listener class
- *
- * Feature detection, multiple implementations may be avaible, for example, Linux has poll, select and epoll.
- *
- * We assume that `select(2)` is always available.
- *
- * Of course, you can set the variables yourself if you test it with your build system.
- *
- * - **SOCKET_HAVE_POLL**: Defined on all BSD, Linux. Also defined on Windows
- *   if _WIN32_WINNT is set to 0x0600 or greater.
- * - **SOCKET_HAVE_KQUEUE**: Defined on all BSD and Apple.
- * - **SOCKET_HAVE_EPOLL**: Defined on Linux only.
- * - **SOCKET_DEFAULT_BACKEND**: Which backend to use (e.g. `Select`).
- *
- * The preference priority is ordered from left to right.
- *
- * | System        | Backend                 | Class name   |
- * |---------------|-------------------------|--------------|
- * | Linux         | epoll(7)                | Epoll        |
- * | *BSD          | kqueue(2)               | Kqueue       |
- * | Windows       | poll(2), select(2)      | Poll, Select |
- * | Mac OS X      | kqueue(2)               | Kqueue       |
- */
-
-#if defined(_WIN32)
-#  if _WIN32_WINNT >= 0x0600 && !defined(SOCKET_HAVE_POLL)
-#    define SOCKET_HAVE_POLL
-#  endif
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
-#  if !defined(SOCKET_HAVE_KQUEUE)
-#    define SOCKET_HAVE_KQUEUE
-#  endif
-#  if !defined(SOCKET_HAVE_POLL)
-#    define SOCKET_HAVE_POLL
-#  endif
-#elif defined(__linux__)
-#  if !defined(SOCKET_HAVE_EPOLL)
-#    define SOCKET_HAVE_EPOLL
-#  endif
-#  if !defined(SOCKET_HAVE_POLL)
-#    define SOCKET_HAVE_POLL
-#  endif
-#endif
-
-/*
- * Define SOCKET_DEFAULT_BACKEND
- * ------------------------------------------------------------------
- */
-
-/**
- * Defines the default Listener backend to use.
- *
- * @note Do not rely on the value shown in doxygen.
- */
-#if defined(_WIN32)
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    if defined(SOCKET_HAVE_POLL)
-#      define SOCKET_DEFAULT_BACKEND Poll
-#    else
-#      define SOCKET_DEFAULT_BACKEND Select
-#    endif
-#  endif
-#elif defined(__linux__)
-#  include <sys/epoll.h>
-
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    define SOCKET_DEFAULT_BACKEND Epoll
-#  endif
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
-#  include <sys/types.h>
-#  include <sys/event.h>
-#  include <sys/time.h>
-
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    define SOCKET_DEFAULT_BACKEND Kqueue
-#  endif
-#else
-#  if !defined(SOCKET_DEFAULT_BACKEND)
-#    define SOCKET_DEFAULT_BACKEND Select
-#  endif
-#endif
-
-#if defined(SOCKET_HAVE_POLL) && !defined(_WIN32)
-#  include <poll.h>
-#endif
-
-/*
- * Headers to include
- * ------------------------------------------------------------------
- */
-
-#if defined(_WIN32)
-#  include <cstdlib>
-
-#  include <WinSock2.h>
-#  include <WS2tcpip.h>
-#else
-#  include <cerrno>
-
-#  include <sys/ioctl.h>
-#  include <sys/types.h>
-#  include <sys/socket.h>
-#  include <sys/un.h>
-
-#  include <arpa/inet.h>
-
-#  include <netinet/in.h>
-#  include <netinet/tcp.h>
-
-#  include <fcntl.h>
-#  include <netdb.h>
-#  include <unistd.h>
-#endif
-
-#if !defined(SOCKET_NO_SSL)
-#  include <openssl/err.h>
-#  include <openssl/evp.h>
-#  include <openssl/ssl.h>
-#endif
-
-#include <cassert>
-#include <chrono>
-#include <cstdlib>
-#include <cstring>
-#include <exception>
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace irccd {
-
-/**
- * General network namespace.
- */
-namespace net {
-
-/*
- * Portables types
- * ------------------------------------------------------------------
- *
- * The following types are defined differently between Unix and Windows.
- */
-
-/* {{{ Protocols */
-
-#if defined(_WIN32)
-
-/**
- * Socket type, SOCKET.
- */
-using Handle	= SOCKET;
-
-/**
- * Argument to pass to set.
- */
-using ConstArg	= const char *;
-
-/**
- * Argument to pass to get.
- */
-using Arg	= char *;
-
-#else
-
-/**
- * Socket type, int.
- */
-using Handle	= int;
-
-/**
- * Argument to pass to set.
- */
-using ConstArg	= const void *;
-
-/**
- * Argument to pass to get.
- */
-using Arg	= void *;
-
-#endif
-
-/* }}} */
-
-/*
- * Portable constants
- * ------------------------------------------------------------------
- *
- * These constants are needed to check functions return codes, they are rarely needed in end user code.
- */
-
-/* {{{ Constants */
-
-/*
- * The following constants are defined differently from Unix
- * to Windows.
- */
-#if defined(_WIN32)
-
-/**
- * Socket creation failure or invalidation.
- */
-extern const Handle Invalid;
-
-/**
- * Socket operation failure.
- */
-extern const int Failure;
-
-#else
-
-/**
- * Socket creation failure or invalidation.
- */
-extern const int Invalid;
-
-/**
- * Socket operation failure.
- */
-extern const int Failure;
-
-#endif
-
-#if !defined(SOCKET_NO_SSL)
-
-namespace ssl {
-
-/**
- * @enum Method
- * @brief Which OpenSSL method to use.
- */
-enum Method {
-	Tlsv1,		//!< TLS v1.2 (recommended)
-	Sslv3		//!< SSLv3
-};
-
-} // !ssl
-
-#endif
-
-/* }}} */
-
-/*
- * Portable functions
- * ------------------------------------------------------------------
- *
- * The following free functions can be used to initialize the library or to get the last system error.
- */
-
-/* {{{ Functions */
-
-/**
- * Initialize the socket library. Except if you defined SOCKET_NO_AUTO_INIT, you don't need to call this
- * function manually.
- */
-void init() noexcept;
-
-/**
- * Close the socket library.
- */
-void finish() noexcept;
-
-#if !defined(SOCKET_NO_SSL)
-
-/**
- * OpenSSL namespace.
- */
-namespace ssl {
-
-/**
- * Initialize the OpenSSL library. Except if you defined SOCKET_NO_AUTO_SSL_INIT, you don't need to call this function
- * manually.
- */
-void init() noexcept;
-
-/**
- * Close the OpenSSL library.
- */
-void finish() noexcept;
-
-} // !ssl
-
-#endif // SOCKET_NO_SSL
-
-/**
- * Get the last socket system error. The error is set from errno or from
- * WSAGetLastError on Windows.
- *
- * @return a string message
- */
-std::string error();
-
-/**
- * Get the last system error.
- *
- * @param errn the error number (errno or WSAGetLastError)
- * @return the error
- */
-std::string error(int errn);
-
-/* }}} */
-
-/*
- * Error class
- * ------------------------------------------------------------------
- *
- * This is the main exception thrown on socket operations.
- */
-
-/* {{{ Error */
-
-/**
- * @class Error
- * @brief Base class for sockets error
- */
-class Error : public std::exception {
-public:
-	/**
-	 * @enum Code
-	 * @brief Which kind of error
-	 */
-	enum Code {
-		Timeout,		///!< The action did timeout
-		System,			///!< There is a system error
-		Other			///!< Other custom error
-	};
-
-private:
-	Code m_code;
-	std::string m_function;
-	std::string m_error;
-
-public:
-	/**
-	 * Constructor that use the last system error.
-	 *
-	 * @param code which kind of error
-	 * @param function the function name
-	 */
-	Error(Code code, std::string function);
-
-	/**
-	 * Constructor that use the system error set by the user.
-	 *
-	 * @param code which kind of error
-	 * @param function the function name
-	 * @param error the error
-	 */
-	Error(Code code, std::string function, int error);
-
-	/**
-	 * Constructor that set the error specified by the user.
-	 *
-	 * @param code which kind of error
-	 * @param function the function name
-	 * @param error the error
-	 */
-	Error(Code code, std::string function, std::string error);
-
-	/**
-	 * Get which function has triggered the error.
-	 *
-	 * @return the function name (e.g connect)
-	 */
-	inline const std::string &function() const noexcept
-	{
-		return m_function;
-	}
-
-	/**
-	 * The error code.
-	 *
-	 * @return the code
-	 */
-	inline Code code() const noexcept
-	{
-		return m_code;
-	}
-
-	/**
-	 * Get the error (only the error content).
-	 *
-	 * @return the error
-	 */
-	const char *what() const noexcept
-	{
-		return m_error.c_str();
-	}
-};
-
-/* }}} */
-
-/*
- * State class
- * ------------------------------------------------------------------
- *
- * To facilitate higher-level stuff, the socket has a state.
- */
-
-/* {{{ State */
-
-/**
- * @enum State
- * @brief Current socket state.
- */
-enum class State {
-	Open,			//!< Socket is open
-	Bound,			//!< Socket is bound to an address
-	Connecting,		//!< The connection is in progress
-	Connected,		//!< Connection is complete
-	Accepted,		//!< Socket has been accepted (client)
-	Accepting,		//!< The client acceptation is in progress
-	Closed,			//!< The socket has been closed
-	Disconnected,		//!< The connection was lost
-};
-
-/* }}} */
-
-/*
- * Action enum
- * ------------------------------------------------------------------
- *
- * Defines the pending operation.
- */
-
-/* {{{ Action */
-
-/**
- * @enum Action
- * @brief Define the current operation that must complete.
- *
- * Some operations like accept, connect, recv or send must sometimes do several round-trips to complete and the socket
- * action is set with that enumeration. The user is responsible of calling accept, connect send or recv until the
- * operation is complete.
- *
- * Note: the user must wait for the appropriate condition in Socket::condition to check if the required condition is
- * met.
- *
- * It is important to complete the operation in the correct order because protocols like Tls may require to continue
- * re-negociating when calling Socket::send or Socket::Recv.
- */
-enum class Action {
-	None,		//!< No action is required, socket is ready
-	Accept,		//!< The socket is not yet accepted, caller must call accept() again
-	Connect,	//!< The socket is not yet connected, caller must call connect() again
-	Receive,	//!< The received operation has not succeeded yet, caller must call recv() or recvfrom() again
-	Send		//!< The send operation has not succeded yet, caller must call send() or sendto() again
-};
-
-/* }}} */
-
-/*
- * Condition enum
- * ------------------------------------------------------------------
- *
- * Defines if we must wait for reading or writing.
- */
-
-/* {{{ Condition */
-
-/**
- * @enum Condition
- * @brief Define the required condition for the socket.
- *
- * As explained in Action enumeration, some operations required to be called several times, before calling these
- * operations, the user must wait the socket to be readable or writable. This can be checked with Socket::condition.
- */
-enum class Condition {
-	None,			//!< No condition is required
-	Readable = (1 << 0),	//!< The socket must be readable
-	Writable = (1 << 1)	//!< The socket must be writable
-};
-
-/**
- * Apply bitwise XOR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-constexpr Condition operator^(Condition v1, Condition v2) noexcept
-{
-	return static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
-}
-
-/**
- * Apply bitwise AND.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-constexpr Condition operator&(Condition v1, Condition v2) noexcept
-{
-	return static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
-}
-
-/**
- * Apply bitwise OR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-constexpr Condition operator|(Condition v1, Condition v2) noexcept
-{
-	return static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
-}
-
-/**
- * Apply bitwise NOT.
- *
- * @param v the value
- * @return the complement
- */
-constexpr Condition operator~(Condition v) noexcept
-{
-	return static_cast<Condition>(~static_cast<int>(v));
-}
-
-/**
- * Assign bitwise OR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-inline Condition &operator|=(Condition &v1, Condition v2) noexcept
-{
-	v1 = static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
-
-	return v1;
-}
-
-/**
- * Assign bitwise AND.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-inline Condition &operator&=(Condition &v1, Condition v2) noexcept
-{
-	v1 = static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
-
-	return v1;
-}
-
-/**
- * Assign bitwise XOR.
- *
- * @param v1 the first value
- * @param v2 the second value
- * @return the new value
- */
-inline Condition &operator^=(Condition &v1, Condition v2) noexcept
-{
-	v1 = static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
-
-	return v1;
-}
-
-/* }}} */
-
-/*
- * Base Socket class
- * ------------------------------------------------------------------
- *
- * This base class has operations that are common to all types of sockets but you usually instanciate
- * a SocketTcp or SocketUdp
- */
-
-/* {{{ Socket */
-
-/**
- * @class Socket
- * @brief Base socket class for socket operations.
- *
- * **Important:** When using non-blocking sockets, some considerations must be taken. See the implementation of the
- * underlying protocol for more details.
- *
- * @see protocol::Tls
- * @see protocol::Tcp
- * @see protocol::Udp
- */
-template <typename Address, typename Protocol>
-class Socket {
-private:
-	Protocol m_proto;
-	State m_state{State::Closed};
-	Action m_action{Action::None};
-	Condition m_condition{Condition::None};
-
-protected:
-	/**
-	 * The native handle.
-	 */
-	Handle m_handle{Invalid};
-
-public:
-	/**
-	 * Create a socket handle.
-	 *
-	 * This is the primary function and the only one that creates the socket handle, all other constructors
-	 * are just overloaded functions.
-	 *
-	 * @param domain the domain AF_*
-	 * @param type the type SOCK_*
-	 * @param protocol the protocol
-	 * @param iface the implementation
-	 * @throw net::Error on errors
-	 * @post state is set to Open
-	 * @post handle is not set to Invalid
-	 */
-	Socket(int domain, int type, int protocol, Protocol iface = {})
-		: m_proto(std::move(iface))
-	{
-#if !defined(SOCKET_NO_AUTO_INIT)
-		init();
-#endif
-		m_handle = ::socket(domain, type, protocol);
-
-		if (m_handle == Invalid) {
-			throw Error{Error::System, "socket"};
-		}
-
-		m_proto.create(*this);
-		m_state = State::Open;
-
-		assert(m_handle != Invalid);
-	}
-
-	/**
-	 * This tries to create a socket.
-	 *
-	 * Domain and type are determined by the Address and Protocol object.
-	 *
-	 * @param protocol the protocol
-	 * @param address which type of address
-	 * @throw net::Error on errors
-	 */
-	explicit inline Socket(Protocol protocol = {}, const Address &address = {})
-		: Socket{address.domain(), protocol.type(), 0, std::move(protocol)}
-	{
-	}
-
-	/**
-	 * Construct a socket with an already created descriptor.
-	 *
-	 * @param handle the native descriptor
-	 * @param state specify the socket state
-	 * @param protocol the type of socket implementation
-	 * @post action is set to None
-	 * @post condition is set to None
-	 */
-	explicit inline Socket(Handle handle, State state = State::Closed, Protocol protocol = {}) noexcept
-		: m_proto(std::move(protocol))
-		, m_state{state}
-		, m_handle{handle}
-	{
-		assert(m_action == Action::None);
-		assert(m_condition == Condition::None);
-	}
-
-	/**
-	 * Create an invalid socket. Can be used when you cannot instanciate the socket immediately.
-	 */
-	explicit inline Socket(std::nullptr_t) noexcept
-		: m_handle{Invalid}
-	{
-	}
-
-	/**
-	 * Copy constructor deleted.
-	 */
-	Socket(const Socket &) = delete;
-
-	/**
-	 * Transfer ownership from other to this.
-	 *
-	 * @param other the other socket
-	 */
-	inline Socket(Socket &&other) noexcept
-		: m_proto(std::move(other.m_proto))
-		, m_state{other.m_state}
-		, m_action{other.m_action}
-		, m_condition{other.m_condition}
-		, m_handle{other.m_handle}
-	{
-		/* Invalidate other */
-		other.m_handle = Invalid;
-		other.m_state = State::Closed;
-		other.m_action = Action::None;
-		other.m_condition = Condition::None;
-	}
-
-	/**
-	 * Default destructor.
-	 */
-	virtual ~Socket()
-	{
-		close();
-	}
-
-	/**
-	 * Access the implementation.
-	 *
-	 * @return the implementation
-	 * @warning use this function with care
-	 */
-	inline const Protocol &protocol() const noexcept
-	{
-		return m_proto;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the implementation
-	 */
-	inline Protocol &protocol() noexcept
-	{
-		return m_proto;
-	}
-
-	/**
-	 * Get the current socket state.
-	 *
-	 * @return the state
-	 */
-	inline State state() const noexcept
-	{
-		return m_state;
-	}
-
-	/**
-	 * Change the current socket state.
-	 *
-	 * @param state the new state
-	 * @warning only implementations should call this function
-	 */
-	inline void setState(State state) noexcept
-	{
-		m_state = state;
-	}
-
-	/**
-	 * Get the pending operation.
-	 *
-	 * @return the action to complete before continuing
-	 * @note usually only needed in non-blocking sockets
-	 */
-	inline Action action() const noexcept
-	{
-		return m_action;
-	}
-
-	/**
-	 * Change the pending operation.
-	 *
-	 * @param action the action
-	 * @warning you should not call this function yourself
-	 */
-	inline void setAction(Action action) noexcept
-	{
-		m_action = action;
-	}
-
-	/**
-	 * Get the condition to wait for.
-	 *
-	 * @return the condition
-	 */
-	inline Condition condition() const noexcept
-	{
-		return m_condition;
-	}
-
-	/**
-	 * Change the condition required.
-	 *
-	 * @param condition the condition
-	 * @warning you should not call this function yourself
-	 */
-	inline void setCondition(Condition condition) noexcept
-	{
-		m_condition = condition;
-	}
-
-	/**
-	 * Set an option for the socket. Wrapper of setsockopt(2).
-	 *
-	 * @param level the setting level
-	 * @param name the name
-	 * @param arg the value
-	 * @throw net::Error on errors
-	 */
-	template <typename Argument>
-	void set(int level, int name, const Argument &arg)
-	{
-		if (setsockopt(m_handle, level, name, (ConstArg)&arg, sizeof (arg)) == Failure) {
-			throw Error{Error::System, "set"};
-		}
-	}
-
-	/**
-	 * Object-oriented option setter.
-	 *
-	 * The object must have `set(Socket<Address, Protocol> &) const`.
-	 *
-	 * @param option the option
-	 * @throw net::Error on errors
-	 */
-	template <typename Option>
-	inline void set(const Option &option)
-	{
-		option.set(*this);
-	}
-
-	/**
-	 * Get an option for the socket. Wrapper of getsockopt(2).
-	 *
-	 * @param level the setting level
-	 * @param name the name
-	 * @throw net::Error on errors
-	 */
-	template <typename Argument>
-	Argument get(int level, int name)
-	{
-		Argument desired, result{};
-		socklen_t size = sizeof (result);
-
-		if (getsockopt(m_handle, level, name, (Arg)&desired, &size) == Failure) {
-			throw Error{Error::System, "get"};
-		}
-
-		std::memcpy(&result, &desired, size);
-
-		return result;
-	}
-
-	/**
-	 * Object-oriented option getter.
-	 *
-	 * The object must have `T get(Socket<Address, Protocol> &) const`, T can be any type and it is the value
-	 * returned from this function.
-	 *
-	 * @return the same value as get() in the option
-	 * @throw net::Error on errors
-	 */
-	template <typename Option>
-	inline auto get() -> decltype(std::declval<Option>().get(*this))
-	{
-		return Option{}.get(*this);
-	}
-
-	/**
-	 * Get the native handle.
-	 *
-	 * @return the handle
-	 * @warning Not portable
-	 */
-	inline Handle handle() const noexcept
-	{
-		return m_handle;
-	}
-
-	/**
-	 * Bind using a native address.
-	 *
-	 * @param address the address
-	 * @param length the size
-	 * @pre state must not be Bound
-	 * @throw net::Error on errors
-	 */
-	void bind(const sockaddr *address, socklen_t length)
-	{
-		assert(m_state != State::Bound);
-
-		if (::bind(m_handle, address, length) == Failure) {
-			throw Error{Error::System, "bind"};
-		}
-
-		m_state = State::Bound;
-	}
-
-	/**
-	 * Overload that takes an address.
-	 *
-	 * @param address the address
-	 * @throw net::Error on errors
-	 */
-	inline void bind(const Address &address)
-	{
-		bind(address.address(), address.length());
-	}
-
-	/**
-	 * Listen for pending connection.
-	 *
-	 * @param max the maximum number
-	 * @pre state must be Bound
-	 * @throw net::Error on errors
-	 */
-	inline void listen(int max = 128)
-	{
-		assert(m_state == State::Bound);
-
-		if (::listen(this->m_handle, max) == Failure) {
-			throw Error{Error::System, "listen"};
-		}
-	}
-
-	/**
-	 * Connect to the address.
-	 *
-	 * If connection cannot be established immediately, connect with no argument must be called again. See
-	 * the underlying protocol for more information.
-	 *
-	 * @pre state must be State::Open
-	 * @param address the address
-	 * @param length the the address length
-	 * @throw net::Error on errors
-	 * @post state is set to State::Connecting or State::Connected
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	void connect(const sockaddr *address, socklen_t length)
-	{
-		assert(m_state == State::Open);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		m_proto.connect(*this, address, length);
-
-		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
-		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * Effectively call connect(address.address(), address.length());
-	 *
-	 * @param address the address
-	 */
-	inline void connect(const Address &address)
-	{
-		connect(address.address(), address.length());
-	}
-
-	/**
-	 * Continue the connection, only required with non-blocking sockets.
-	 *
-	 * @pre state must be State::Connecting
-	 * @throw net::Error on errors
-	 */
-	void connect()
-	{
-		assert(m_state == State::Connecting);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		m_proto.connect(*this);
-
-		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
-		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
-	}
-
-	/**
-	 * Accept a new client. If there are no pending connection, throws an error.
-	 *
-	 * If the client cannot be accepted immediately, the client is returned and accept with no arguments
-	 * must be called on it. See the underlying protocol for more information.
-	 *
-	 * @pre state must be State::Bound
-	 * @param info the address where to store client's information (optional)
-	 * @return the new socket
-	 * @throw Error on errors
-	 * @post returned client's state is set to State::Accepting or State::Accepted
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	Socket<Address, Protocol> accept(Address *info)
-	{
-		assert(m_state == State::Bound);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		sockaddr_storage storage;
-		socklen_t length = sizeof (storage);
-
-		Socket<Address, Protocol> sc = m_proto.accept(*this, reinterpret_cast<sockaddr *>(&storage), &length);
-
-		if (info) {
-			*info = Address{&storage, length};
-		}
-
-		/* Master do not change */
-		assert(m_state == State::Bound);
-		assert(m_action == Action::None);
-		assert(m_condition == Condition::None);
-
-		/* Client */
-		assert(
-			(sc.state() == State::Accepting && sc.action() == Action::Accept && sc.condition() != Condition::None) ||
-			(sc.state() == State::Accepted  && sc.action() == Action::None   && sc.condition() == Condition::None)
-		);
-
-		return sc;
-	}
-
-	/**
-	 * Continue the accept process on this client. This function must be called only when the socket is
-	 * ready to be readable or writable! (see condition).
-	 *
-	 * @pre state must be State::Accepting
-	 * @throw Error on errors
-	 * @post if connection is complete, state is changed to State::Accepted, action and condition are unset
-	 * @post if connection is still in progress, condition is set
-	 */
-	void accept()
-	{
-		assert(m_state == State::Accepting);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		m_proto.accept(*this);
-
-		assert(
-			(m_state == State::Accepting && m_action == Action::Accept && m_condition != Condition::None) ||
-			(m_state == State::Accepted  && m_action == Action::None   && m_condition == Condition::None)
-		);
-	}
-
-	/**
-	 * Get the local name. This is a wrapper of getsockname().
-	 *
-	 * @return the address
-	 * @throw Error on failures
-	 * @pre state() must not be State::Closed
-	 */
-	Address address() const
-	{
-		assert(m_state != State::Closed);
-
-		sockaddr_storage ss;
-		socklen_t length = sizeof (sockaddr_storage);
-
-		if (::getsockname(m_handle, (sockaddr *)&ss, &length) == Failure) {
-			throw Error{Error::System, "getsockname"};
-		}
-
-		return Address(&ss, length);
-	}
-
-	/**
-	 * Receive some data.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * If action is set to Action::None and result is set to 0, disconnection occured.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @pre action must not be Action::Send
-	 * @return the number of bytes received or 0
-	 * @throw Error on error
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	unsigned recv(void *data, unsigned length)
-	{
-		assert(m_action != Action::Send);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		unsigned nbread = m_proto.recv(*this, data, length);
-
-		return nbread;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param count the number of bytes to receive
-	 * @return the string
-	 * @throw Error on error
-	 */
-	inline std::string recv(unsigned count)
-	{
-		std::string result;
-
-		result.resize(count);
-		auto n = recv(const_cast<char *>(result.data()), count);
-		result.resize(n);
-
-		return result;
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * @param data the data buffer
-	 * @param length the buffer length
-	 * @return the number of bytes sent or 0
-	 * @pre action() must not be Flag::Receive
-	 * @throw Error on error
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	unsigned send(const void *data, unsigned length)
-	{
-		assert(m_action != Action::Receive);
-
-		m_action = Action::None;
-		m_condition = Condition::None;
-
-		unsigned nbsent = m_proto.send(*this, data, length);
-
-		assert((m_action == Action::None && m_condition == Condition::None) ||
-		       (m_action == Action::Send && m_condition != Condition::None));
-
-		return nbsent;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the string to send
-	 * @return the number of bytes sent
-	 * @throw Error on error
-	 */
-	inline unsigned send(const std::string &data)
-	{
-		return send(data.c_str(), data.size());
-	}
-
-	/**
-	 * Send data to an end point.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the client address
-	 * @param addrlen the address length
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	inline unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
-	{
-		return m_proto.sendto(*this, data, length, address, addrlen);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the destination
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 */
-	inline unsigned sendto(const void *data, unsigned length, const Address &address)
-	{
-		return sendto(data, length, address.address(), address.length());
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the data
-	 * @param address the address
-	 * @return the number of bytes sent
-	 * @throw net:;Error on errors
-	 */
-	inline unsigned sendto(const std::string &data, const Address &address)
-	{
-		return sendto(data.c_str(), data.length(), address);
-	}
-
-	/**
-	 * Receive data from an end point.
-	 *
-	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
-	 * again when ready. See the underlying protocol for more information.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param address the address destination
-	 * @param addrlen the address length (in/out)
-	 * @return the number of bytes received
-	 * @throw net::Error on errors
-	 * @note For non-blocking sockets, see the underlying protocol function for more details
-	 */
-	inline unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
-	{
-		return m_proto.recvfrom(*this, data, length, address, addrlen);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param info the address destination
-	 * @return the number of bytes received
-	 * @throw net::Error on errors
-	 */
-	inline unsigned recvfrom(void *data, unsigned length, Address *info = nullptr)
-	{
-		sockaddr_storage storage;
-		socklen_t addrlen = sizeof (sockaddr_storage);
-
-		auto n = recvfrom(data, length, reinterpret_cast<sockaddr *>(&storage), &addrlen);
-
-		if (info && n != 0) {
-			*info = Address{&storage, addrlen};
-		}
-
-		return n;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param count the maximum number of bytes to receive
-	 * @param info the client information
-	 * @return the string
-	 * @throw net::Error on errors
-	 */
-	std::string recvfrom(unsigned count, Address *info = nullptr)
-	{
-		std::string result;
-
-		result.resize(count);
-		auto n = recvfrom(const_cast<char *>(result.data()), count, info);
-		result.resize(n);
-
-		return result;
-	}
-
-	/**
-	 * Close the socket.
-	 *
-	 * Automatically called from the destructor.
-	 */
-	void close()
-	{
-		if (m_handle != Invalid) {
-#if defined(_WIN32)
-			::closesocket(m_handle);
-#else
-			::close(m_handle);
-#endif
-			m_handle = Invalid;
-		}
-
-		m_state = State::Closed;
-		m_action = Action::None;
-		m_condition = Condition::None;
-	}
-
-	/**
-	 * Assignment operator forbidden.
-	 *
-	 * @return *this
-	 */
-	Socket &operator=(const Socket &) = delete;
-
-	/**
-	 * Transfer ownership from other to this. The other socket is left
-	 * invalid and will not be closed.
-	 *
-	 * @param other the other socket
-	 * @return this
-	 */
-	Socket &operator=(Socket &&other) noexcept
-	{
-		m_handle = other.m_handle;
-		m_proto = std::move(other.m_proto);
-		m_state = other.m_state;
-		m_action = other.m_action;
-		m_condition = other.m_condition;
-
-		/* Invalidate other */
-		other.m_handle = Invalid;
-		other.m_state = State::Closed;
-		other.m_action = Action::None;
-		other.m_condition = Condition::None;
-
-		return *this;
-	}
-};
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if they equals
- */
-template <typename Address, typename Protocol>
-bool operator==(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() == s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if they are different
- */
-template <typename Address, typename Protocol>
-bool operator!=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() != s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 < s2
- */
-template <typename Address, typename Protocol>
-bool operator<(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() < s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 > s2
- */
-template <typename Address, typename Protocol>
-bool operator>(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() > s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 <= s2
- */
-template <typename Address, typename Protocol>
-bool operator<=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() <= s2.handle();
-}
-
-/**
- * Compare two sockets.
- *
- * @param s1 the first socket
- * @param s2 the second socket
- * @return true if s1 >= s2
- */
-template <typename Address, typename Protocol>
-bool operator>=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
-{
-	return s1.handle() >= s2.handle();
-}
-
-/* }}} */
-
-/*
- * Predefined options
- * ------------------------------------------------------------------
- */
-
-/* {{{ Options */
-
-/**
- * Namespace of predefined options.
- */
-namespace option {
-
-/*
- * Options for socket
- * ------------------------------------------------------------------
- */
-
-/* {{{ Options for socket */
-
-/**
- * @class SockBlockMode
- * @brief Set or get the blocking-mode for a socket.
- * @warning On Windows, it's not possible to check if the socket is blocking or not.
- */
-class SockBlockMode {
-public:
-	/**
-	 * Set to false if you want non-blocking socket.
-	 */
-	bool value{false};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void set(Socket<Address, Protocol> &sc) const
-	{
-#if defined(O_NONBLOCK) && !defined(_WIN32)
-		int flags;
-
-		if ((flags = fcntl(sc.handle(), F_GETFL, 0)) < 0) {
-			flags = 0;
-		}
-
-		if (value) {
-			flags &= ~(O_NONBLOCK);
-		} else {
-			flags |= O_NONBLOCK;
-		}
-
-		if (fcntl(sc.handle(), F_SETFL, flags) < 0) {
-			throw Error{Error::System, "fcntl"};
-		}
-#else
-		unsigned long flags = (value) ? 0 : 1;
-
-		if (ioctlsocket(sc.handle(), FIONBIO, &flags) == Failure) {
-			throw Error{Error::System, "fcntl"};
-		}
-#endif
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	bool get(Socket<Address, Protocol> &sc) const
-	{
-#if defined(O_NONBLOCK) && !defined(_WIN32)
-		int flags = fcntl(sc.handle(), F_GETFL, 0);
-
-		if (flags < 0) {
-			throw Error{Error::System, "fcntl"};
-		}
-
-		return !(flags & O_NONBLOCK);
-#else
-		throw Error{Error::Other, "get", "Windows API cannot let you get the blocking status of a socket"};
-#endif
-	}
-};
-
-/**
- * @class SockReuseAddress
- * @brief Reuse address, must be used before calling Socket::bind
- */
-class SockReuseAddress {
-public:
-	/**
-	 * Set to true if you want to set the SOL_SOCKET/SO_REUSEADDR option.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_REUSEADDR, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.template get<int>(SOL_SOCKET, SO_REUSEADDR));
-	}
-};
-
-/**
- * @class SockSendBuffer
- * @brief Set or get the output buffer.
- */
-class SockSendBuffer {
-public:
-	/**
-	 * Set to the buffer size.
-	 */
-	int value{2048};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_SNDBUF, value);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline int get(Socket<Address, Protocol> &sc) const
-	{
-		return sc.template get<int>(SOL_SOCKET, SO_SNDBUF);
-	}
-};
-
-/**
- * @class SockReceiveBuffer
- * @brief Set or get the input buffer.
- */
-class SockReceiveBuffer {
-public:
-	/**
-	 * Set to the buffer size.
-	 */
-	int value{2048};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_RCVBUF, value);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline int get(Socket<Address, Protocol> &sc) const
-	{
-		return sc.template get<int>(SOL_SOCKET, SO_RCVBUF);
-	}
-};
-
-/* }}} */
-
-/**
- * @class TcpNoDelay
- * @brief Set this option if you want to disable nagle's algorithm.
- */
-class TcpNoDelay {
-public:
-	/**
-	 * Set to true to set TCP_NODELAY option.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(IPPROTO_TCP, TCP_NODELAY, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.template get<int>(IPPROTO_TCP, TCP_NODELAY));
-	}
-};
-
-/**
- * @class Ipv6Only
- * @brief Control IPPROTO_IPV6/IPV6_V6ONLY
- *
- * Note: some systems may or not set this option by default so it's a good idea to set it in any case to either
- * false or true if portability is a concern.
- */
-class Ipv6Only {
-public:
-	/**
-	 * Set this to use only IPv6.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(IPPROTO_IPV6, IPV6_V6ONLY, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.template get<int>(IPPROTO_IPV6, IPV6_V6ONLY));
-	}
-};
-
-} // !option
-
-/* }}} */
-
-/*
- * Predefined addressed to be used
- * ------------------------------------------------------------------
- *
- * - Ip,
- * - Local.
- */
-
-/* {{{ Addresses */
-
-/**
- * Set of predefined addresses.
- */
-namespace address {
-
-/**
- * @class Ip
- * @brief Base class for IPv6 and IPv4, you can use it if you don't know in advance if you'll use IPv6 or IPv4.
- */
-class Ip {
-public:
-	/**
-	 * @enum Type
-	 * @brief Type of ip address.
-	 */
-	enum Type {
-		v4 = AF_INET,		//!< AF_INET
-		v6 = AF_INET6		//!< AF_INET6
-	};
-
-private:
-	/*
-	 * Default domain when using default constructors.
-	 *
-	 * Note: AF_INET or AF_INET6, not
-	 */
-	static int m_default;
-
-	union {
-		sockaddr_in m_sin;
-		sockaddr_in6 m_sin6;
-	};
-
-	socklen_t m_length{0};
-	int m_domain{AF_INET};
-
-public:
-	/**
-	 * Set the default domain to use when using default Ip constructor. By default, AF_INET is used.
-	 *
-	 * @pre domain must be Type::v4 or Type::v6
-	 */
-	static inline void setDefault(Type domain) noexcept
-	{
-		assert(domain == Type::v4 || domain == Type::v6);
-
-		m_default = static_cast<int>(domain);
-	}
-
-	/**
-	 * Construct using the default domain.
-	 */
-	inline Ip() noexcept
-		: Ip(static_cast<Type>(m_default))
-	{
-	}
-
-	/**
-	 * Default initialize the Ip domain.
-	 *
-	 * @pre domain must be AF_INET or AF_INET6 only
-	 * @param domain the domain (AF_INET or AF_INET6)
-	 */
-	Ip(Type domain) noexcept;
-
-	/**
-	 * Construct an address suitable for bind() or connect().
-	 *
-	 * @pre domain must be Type::v4 or Type::v6
-	 * @param domain the domain (AF_INET or AF_INET6)
-	 * @param host the host (* for any)
-	 * @param port the port number
-	 * @throw Error on errors
-	 */
-	Ip(const std::string &host, int port, Type domain = v4);
-
-	/**
-	 * Construct an address from a storage.
-	 *
-	 * @pre storage's domain must be AF_INET or AF_INET6 only
-	 * @param ss the storage
-	 * @param length the length
-	 */
-	Ip(const sockaddr_storage *ss, socklen_t length) noexcept;
-
-	/**
-	 * Get the domain (AF_INET or AF_INET6).
-	 *
-	 * @return the domain
-	 */
-	inline int domain() const noexcept
-	{
-		return m_domain;
-	}
-
-	/**
-	 * Return the underlying address, either sockaddr_in6 or sockaddr_in.
-	 *
-	 * @return the address
-	 */
-	inline const sockaddr *address() const noexcept
-	{
-		if (m_domain == AF_INET6) {
-			return reinterpret_cast<const sockaddr *>(&m_sin6);
-		}
-
-		return reinterpret_cast<const sockaddr *>(&m_sin);
-	}
-
-	/**
-	 * Return the underlying address length.
-	 *
-	 * @return the length
-	 */
-	inline socklen_t length() const noexcept
-	{
-		return m_length;
-	}
-
-	/**
-	 * Get the port.
-	 *
-	 * @return the port
-	 */
-	inline int port() const noexcept
-	{
-		if (m_domain == AF_INET6) {
-			return ntohs(m_sin6.sin6_port);
-		}
-
-		return ntohs(m_sin.sin_port);
-	}
-};
-
-#if !defined(_WIN32)
-
-/**
- * @class Local
- * @brief unix family sockets
- *
- * Create an address to a specific path. Only available on Unix.
- */
-class Local {
-private:
-	sockaddr_un m_sun;
-	std::string m_path;
-
-public:
-	/**
-	 * Get the domain AF_LOCAL.
-	 *
-	 * @return AF_LOCAL
-	 */
-	inline int domain() const noexcept
-	{
-		return AF_LOCAL;
-	}
-
-	/**
-	 * Default constructor.
-	 */
-	Local() noexcept;
-
-	/**
-	 * Construct an address to a path.
-	 *
-	 * @param path the path
-	 * @param rm remove the file before (default: false)
-	 */
-	Local(std::string path, bool rm = false) noexcept;
-
-	/**
-	 * Construct an unix address from a storage address.
-	 *
-	 * @pre storage's domain must be AF_LOCAL
-	 * @param ss the storage
-	 * @param length the length
-	 */
-	Local(const sockaddr_storage *ss, socklen_t length) noexcept;
-
-	/**
-	 * Get the sockaddr_un.
-	 *
-	 * @return the address
-	 */
-	inline const sockaddr *address() const noexcept
-	{
-		return reinterpret_cast<const sockaddr *>(&m_sun);
-	}
-
-	/**
-	 * Get the address length.
-	 *
-	 * @return the length
-	 */
-	inline socklen_t length() const noexcept
-	{
-#if defined(SOCKET_HAVE_SUN_LEN)
-		return SUN_LEN(&m_sun);
-#else
-		return sizeof (m_sun);
-#endif
-	}
-};
-
-#endif // !_WIN32
-
-} // !address
-
-/* }}} */
-
-/*
- * Predefined protocols
- * ------------------------------------------------------------------
- *
- * - Tcp, for standard stream connections,
- * - Udp, for standard datagram connections,
- * - Tls, for secure stream connections.
- */
-
-/* {{{ Protocols */
-
-/**
- * Set of predefined protocols.
- */
-namespace protocol {
-
-/* {{{ Tcp */
-
-/**
- * @class Tcp
- * @brief Clear TCP implementation.
- *
- * This is the basic TCP protocol that implements recv, send, connect and accept as wrappers of the usual
- * C functions.
- */
-class Tcp {
-public:
-	/**
-	 * Socket type.
-	 *
-	 * @return SOCK_STREAM
-	 */
-	inline int type() const noexcept
-	{
-		return SOCK_STREAM;
-	}
-
-	/**
-	 * Do nothing.
-	 *
-	 * This function is just present for compatibility, it should never be called.
-	 */
-	template <typename Address>
-	inline void create(Socket<Address, Tcp> &) const noexcept
-	{
-		/* No-op */
-	}
-
-	/**
-	 * Standard connect.
-	 *
-	 * If the socket is marked non-blocking and the connection cannot be established immediately, then the
-	 * following is true:
-	 *
-	 * - state is set to State::Connecting,
-	 * - action is set to Action::Connect,
-	 * - condition is set to Condition::Writable.
-	 *
-	 * Then the user must wait until the socket is writable and call connect() with 0 arguments.
-	 *
-	 * If the socket is blocking, this function blocks until the connection is complete or an error occurs, in
-	 * that case state is either set to State::Connected or State::Disconnected but action and condition are
-	 * not set.
-	 *
-	 * @param sc the socket
-	 * @param address the address
-	 * @param length the length
-	 * @throw net::Error on errors
-	 * @note Wrapper of connect(2)
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
-	{
-		if (::connect(sc.handle(), address, length) == Failure) {
-			/*
-			 * Determine if the error comes from a non-blocking connect that cannot be
-			 * accomplished yet.
-			 */
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				sc.setState(State::Connecting);
-				sc.setAction(Action::Connect);
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "connect", error};
-			}
-#else
-			if (errno == EINPROGRESS) {
-				sc.setState(State::Connecting);
-				sc.setAction(Action::Connect);
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "connect"};
-			}
-#endif
-		} else {
-			sc.setState(State::Connected);
-		}
-	}
-
-	/**
-	 * Continue the connection. This function must only be called when the socket is ready for writing,
-	 * the user is responsible of waiting for that condition.
-	 *
-	 * This function check for SOL_SOCKET/SO_ERROR status.
-	 *
-	 * If the connection is complete, status is set to State::Connected, otherwise it is set to
-	 * State::Disconnected. In both cases, action and condition are not set.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc)
-	{
-		int error = sc.template get<int>(SOL_SOCKET, SO_ERROR);
-
-		if (error == Failure) {
-			sc.setState(State::Disconnected);
-			throw Error{Error::System, "connect", error};
-		}
-
-		sc.setState(State::Connected);
-	}
-
-	/**
-	 * Accept a clear client.
-	 *
-	 * If the socket is marked non-blocking and there are no pending connection, this function throws an
-	 * error. The user must wait that the socket is readable before calling this function.
-	 *
-	 * If the socket is blocking, this function blocks until a new client is connected or throws an error on
-	 * errors.
-	 *
-	 * If the socket is correctly returned, its state is set to State::Accepted and its action and condition
-	 * are not set.
-	 *
-	 * In any case, action and condition of this socket are not set.
-	 *
-	 * @param sc the socket
-	 * @param address the address destination
-	 * @param length the address length
-	 * @return the socket
-	 * @throw net::Error on errors
-	 * @note Wrapper of accept(2)
-	 */
-	template <typename Address, typename Protocol>
-	Socket<Address, Protocol> accept(Socket<Address, Protocol> &sc, sockaddr *address, socklen_t *length)
-	{
-		Handle handle = ::accept(sc.handle(), address, length);
-
-		if (handle == Invalid) {
-			throw Error{Error::System, "accept"};
-		}
-
-		return Socket<Address, Protocol>{handle, State::Accepted};
-	}
-
-	/**
-	 * Continue accept.
-	 *
-	 * This function is just present for compatibility, it should never be called.
-	 */
-	template <typename Address, typename Protocol>
-	inline void accept(Socket<Address, Protocol> &) const noexcept
-	{
-		/* no-op */
-	}
-
-	/**
-	 * Receive data.
-	 *
-	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
-	 * Condition::Readable. If 0 is returned and condition is not set, then the state is set to
-	 * State::Disconnected.
-	 *
-	 * If the socket is blocking, this function blocks until some data is available or if an error occurs.
-	 *
-	 * In any case, action is never set.
-	 *
-	 * @param sc the socket
-	 * @param data the destination
-	 * @param length the destination length
-	 * @return the number of bytes read
-	 * @throw Error on errors
-	 * @note Wrapper of recv(2)
-	 */
-	template <typename Address>
-	unsigned recv(Socket<Address, Tcp> &sc, void *data, unsigned length)
-	{
-		int nbread = ::recv(sc.handle(), (Arg)data, length, 0);
-
-		if (nbread == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbread = 0;
-				sc.setCondition(Condition::Readable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "recv", error};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				sc.setCondition(Condition::Readable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "recv"};
-			}
-#endif
-		} else if (nbread == 0) {
-			sc.setState(State::Disconnected);
-		}
-
-		return static_cast<unsigned>(nbread);
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
-	 * Condition::Writable.
-	 *
-	 * If the socket is blocking, this function blocks until the data has been sent.
-	 *
-	 * On any other errors, this function throw net::Error.
-	 *
-	 * @param sc the socket
-	 * @param data the buffer to send
-	 * @param length the buffer length
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 * @note Wrapper of send(2)
-	 */
-	template <typename Address>
-	unsigned send(Socket<Address, Tcp> &sc, const void *data, unsigned length)
-	{
-		int nbsent = ::send(sc.handle(), (ConstArg)data, length, 0);
-
-		if (nbsent == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "send", error};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "send"};
-			}
-#endif
-		}
-
-		return static_cast<unsigned>(nbsent);
-	}
-};
-
-/* }}} */
-
-/* {{{ Udp */
-
-/**
- * @class Udp
- * @brief Clear UDP type.
- *
- * This class is the basic implementation of UDP sockets.
- */
-class Udp {
-public:
-	/**
-	 * Socket type.
-	 *
-	 * @return SOCK_DGRAM
-	 */
-	inline int type() const noexcept
-	{
-		return SOCK_DGRAM;
-	}
-
-	/**
-	 * Do nothing.
-	 */
-	template <typename Address>
-	inline void create(Socket<Address, Udp> &) noexcept
-	{
-		/* No-op */
-	}
-
-	/**
-	 * Receive data from an end point.
-	 *
-	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
-	 * Condition::Readable.
-	 *
-	 * If the socket is blocking, this functions blocks until some data is available or if an error occurs.
-	 *
-	 * @param sc the socket
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param address the address
-	 * @param addrlen the initial address length
-	 * @return the number of bytes received
-	 * @throw Error on error
-	 */
-	template <typename Address>
-	unsigned recvfrom(Socket<Address, Udp> &sc, void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
-	{
-		int nbread;
-
-		nbread = ::recvfrom(sc.handle(), (Arg)data, length, 0, address, addrlen);
-
-		if (nbread == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbread = 0;
-				sc.setCondition(Condition::Readable);
-			} else {
-				throw Error{Error::System, "recvfrom"};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				nbread = 0;
-				sc.setCondition(Condition::Readable);
-			} else {
-				throw Error{Error::System, "recvfrom"};
-			}
-#endif
-		}
-
-		return static_cast<unsigned>(nbread);
-	}
-
-	/**
-	 * Send data to an end point.
-	 *
-	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
-	 * Condition::Writable.
-	 *
-	 * If the socket is blocking, this functions blocks until the data has been sent.
-	 *
-	 * @param sc the socket
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the client address
-	 * @param addrlen the adderss length
-	 * @return the number of bytes sent
-	 * @throw Error on error
-	 */
-	template <typename Address>
-	unsigned sendto(Socket<Address, Udp> &sc, const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
-	{
-		int nbsent;
-
-		nbsent = ::sendto(sc.handle(), (ConstArg)data, length, 0, address, addrlen);
-		if (nbsent == Failure) {
-#if defined(_WIN32)
-			int error = WSAGetLastError();
-
-			if (error == WSAEWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				throw Error{Error::System, "sendto", error};
-			}
-#else
-			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				nbsent = 0;
-				sc.setCondition(Condition::Writable);
-			} else {
-				throw Error{Error::System, "sendto"};
-			}
-#endif
-		}
-
-		return static_cast<unsigned>(nbsent);
-	}
-};
-
-/* }}} */
-
-/* {{{ Tls */
-
-#if !defined(SOCKET_NO_SSL)
-
-/**
- * @class Tls
- * @brief OpenSSL secure layer for TCP.
- *
- * **Note:** This protocol is much more difficult to use with non-blocking sockets, if some operations would block, the
- * user is responsible of calling the function again by waiting for the appropriate condition. See the functions for
- * more details.
- *
- * @see Tls::accept
- * @see Tls::connect
- * @see Tls::recv
- * @see Tls::send
- */
-class Tls : private Tcp {
-private:
-	using Context = std::shared_ptr<SSL_CTX>;
-	using Ssl = std::unique_ptr<SSL, void (*)(SSL *)>;
-
-	/* OpenSSL objects */
-	Context m_context;
-	Ssl m_ssl{nullptr, nullptr};
-
-	/* Status */
-	bool m_tcpconnected{false};
-
-	/*
-	 * User definable parameters
-	 */
-	ssl::Method m_method{ssl::Tlsv1};
-	std::string m_key;
-	std::string m_certificate;
-	bool m_verify{false};
-
-	/*
-	 * Construct with a context and ssl, for Tls::accept.
-	 */
-	Tls(Context context, Ssl ssl)
-		: m_context{std::move(context)}
-		, m_ssl{std::move(ssl)}
-	{
-	}
-
-	/*
-	 * Get the OpenSSL error message.
-	 */
-	inline std::string error(int error)
-	{
-		auto msg = ERR_reason_error_string(error);
-
-		return msg == nullptr ? "" : msg;
-	}
-
-	/*
-	 * Update the states after an uncompleted operation.
-	 */
-	template <typename Address, typename Protocol>
-	inline void updateStates(Socket<Address, Protocol> &sc, State state, Action action, int code)
-	{
-		assert(code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE);
-
-		sc.setState(state);
-		sc.setAction(action);
-
-		if (code == SSL_ERROR_WANT_READ) {
-			sc.setCondition(Condition::Readable);
-		} else {
-			sc.setCondition(Condition::Writable);
-		}
-	}
-
-	/*
-	 * Continue the connect operation.
-	 */
-	template <typename Address, typename Protocol>
-	void processConnect(Socket<Address, Protocol> &sc)
-	{
-		int ret = SSL_connect(m_ssl.get());
-
-		if (ret <= 0) {
-			int no = SSL_get_error(m_ssl.get(), ret);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				updateStates(sc, State::Connecting, Action::Connect, no);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error{Error::System, "connect", error(no)};
-			}
-		} else {
-			sc.setState(State::Connected);
-		}
-	}
-
-	/*
-	 * Continue accept.
-	 */
-	template <typename Address, typename Protocol>
-	void processAccept(Socket<Address, Protocol> &sc)
-	{
-		int ret = SSL_accept(m_ssl.get());
-
-		if (ret <= 0) {
-			int no = SSL_get_error(m_ssl.get(), ret);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				updateStates(sc, State::Accepting, Action::Accept, no);
-			} else {
-				sc.setState(State::Disconnected);
-				throw Error(Error::System, "accept", error(no));
-			}
-		} else {
-			sc.setState(State::Accepted);
-		}
-	}
-
-public:
-	/**
-	 * @copydoc Tcp::type
-	 */
-	inline int type() const noexcept
-	{
-		return SOCK_STREAM;
-	}
-
-	/**
-	 * Empty TLS constructor.
-	 */
-	Tls()
-	{
-#if !defined(SOCKET_NO_SSL_AUTO_INIT)
-		net::ssl::init();
-#endif
-	}
-
-	/**
-	 * Set the method.
-	 *
-	 * @param method the method
-	 * @pre the socket must not be already created
-	 */
-	inline void setMethod(ssl::Method method) noexcept
-	{
-		assert(!m_context);
-		assert(!m_ssl);
-
-		m_method = method;
-	}
-
-	/**
-	 * Use the specified private key file.
-	 *
-	 * @param file the path to the private key
-	 */
-	inline void setPrivateKey(std::string file) noexcept
-	{
-		m_key = std::move(file);
-	}
-
-	/**
-	 * Use the specified certificate file.
-	 *
-	 * @param file the path to the file
-	 */
-	inline void setCertificate(std::string file) noexcept
-	{
-		m_certificate = std::move(file);
-	}
-
-	/**
-	 * Set to true if we must verify the certificate and private key.
-	 *
-	 * @param verify the mode
-	 */
-	inline void setVerify(bool verify = true) noexcept
-	{
-		m_verify = verify;
-	}
-
-	/**
-	 * Initialize the SSL objects after have created.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	inline void create(Socket<Address, Tls> &sc)
-	{
-		auto method = (m_method == ssl::Tlsv1) ? TLSv1_method() : SSLv23_method();
-
-		m_context = {SSL_CTX_new(method), SSL_CTX_free};
-		m_ssl = {SSL_new(m_context.get()), SSL_free};
-
-		SSL_set_fd(m_ssl.get(), sc.handle());
-
-		/* Load certificates */
-		if (m_certificate.size() > 0) {
-			SSL_CTX_use_certificate_file(m_context.get(), m_certificate.c_str(), SSL_FILETYPE_PEM);
-		}
-		if (m_key.size() > 0) {
-			SSL_CTX_use_PrivateKey_file(m_context.get(), m_key.c_str(), SSL_FILETYPE_PEM);
-		}
-		if (m_verify && !SSL_CTX_check_private_key(m_context.get())) {
-			throw Error{Error::System, "(openssl)", "unable to verify key"};
-		}
-	}
-
-	/**
-	 * Connect to a secure host.
-	 *
-	 * If the socket is marked non-blocking and the connection cannot be established yet, then the state is set
-	 * to State::Connecting, the condition is set to Condition::Readable or Condition::Writable, the user must
-	 * wait for the appropriate condition before calling the overload connect which takes 0 argument.
-	 *
-	 * If the socket is blocking, this functions blocks until the connection is complete.
-	 *
-	 * If the connection was completed correctly the state is set to State::Connected.
-	 *
-	 * @param sc the socket
-	 * @param address the address
-	 * @param length the address length
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
-	{
-		/* 1. Connect using raw TCP */
-		Tcp::connect(sc, address, length);
-
-		/* 2. If the connection is complete (e.g. non-blocking), try handshake */
-		if (sc.state() == State::Connected) {
-			m_tcpconnected = true;
-			processConnect(sc);
-		}
-	}
-
-	/**
-	 * Continue the connection.
-	 *
-	 * This function must be called when the socket is ready for reading or writing (check with Socket::condition),
-	 * the state may change exactly like the initial connect call.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	void connect(Socket<Address, Protocol> &sc)
-	{
-		/* 1. Be sure to complete standard connect before */
-		if (!m_tcpconnected) {
-			Tcp::connect(sc);
-			m_tcpconnected = sc.state() == State::Connected;
-		}
-
-		if (m_tcpconnected) {
-			processConnect(sc);
-		}
-	}
-
-	/**
-	 * Accept a secure client.
-	 *
-	 * Because SSL needs several round-trips, if the socket is marked non-blocking and the connection is not
-	 * completed yet, a new socket is returned but with the State::Accepting state. Its condition is set to
-	 * Condition::Readable or Condition::Writable, the user is responsible of calling accept overload which takes
-	 * 0 arguments on the returned socket when the condition is met.
-	 *
-	 * If the socket is blocking, this function blocks until the client is accepted and returned.
-	 *
-	 * If the client is accepted correctly, its state is set to State::Accepted. This instance does not change.
-	 *
-	 * @param sc the socket
-	 * @param address the address destination
-	 * @param length the address length
-	 * @return the client
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	Socket<Address, Tls> accept(Socket<Address, Tls> &sc, sockaddr *address, socklen_t *length)
-	{
-		Socket<Address, Tls> client = Tcp::accept(sc, address, length);
-		Tls &proto = client.protocol();
-
-		/* 1. Share the context */
-		proto.m_context = m_context;
-
-		/* 2. Create new SSL instance */
-		proto.m_ssl = Ssl{SSL_new(m_context.get()), SSL_free};
-		SSL_set_fd(proto.m_ssl.get(), client.handle());
-
-		/* 3. Try accept process on the **new** client */
-		proto.processAccept(client);
-
-		return client;
-	}
-
-	/**
-	 * Continue accept.
-	 *
-	 * This function must be called on the client that is being accepted.
-	 *
-	 * Like accept or connect, user is responsible of calling this function until the connection is complete.
-	 *
-	 * @param sc the socket
-	 * @throw net::Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void accept(Socket<Address, Protocol> &sc)
-	{
-		processAccept(sc);
-	}
-
-	/**
-	 * Receive some secure data.
-	 *
-	 * If the socket is marked non-blocking, 0 is returned if no data is available yet or if the connection
-	 * needs renegociation. If renegociation is required case, the action is set to Action::Receive and condition
-	 * is set to Condition::Readable or Condition::Writable. The user must wait that the condition is met and
-	 * call this function again.
-	 *
-	 * @param sc the socket
-	 * @param data the destination
-	 * @param len the buffer length
-	 * @return the number of bytes read
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	unsigned recv(Socket<Address, Tls> &sc, void *data, unsigned len)
-	{
-		auto nbread = SSL_read(m_ssl.get(), data, len);
-
-		if (nbread <= 0) {
-			auto no = SSL_get_error(m_ssl.get(), nbread);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				nbread = 0;
-				updateStates(sc, sc.state(), Action::Receive, no);
-			} else {
-				throw Error{Error::System, "recv", error(no)};
-			}
-		}
-
-		return nbread;
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * Like recv, if the socket is marked non-blocking and no data can be sent or a negociation is required,
-	 * condition and action are set. See receive for more details
-	 *
-	 * @param sc the socket
-	 * @param data the data to send
-	 * @param len the buffer length
-	 * @return the number of bytes sent
-	 * @throw net::Error on errors
-	 */
-	template <typename Address>
-	unsigned send(Socket<Address, Tls> &sc, const void *data, unsigned len)
-	{
-		auto nbsent = SSL_write(m_ssl.get(), data, len);
-
-		if (nbsent <= 0) {
-			auto no = SSL_get_error(m_ssl.get(), nbsent);
-
-			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				nbsent = 0;
-				updateStates(sc, sc.state(), Action::Send, no);
-			} else {
-				throw Error{Error::System, "send", error(no)};
-			}
-		}
-
-		return nbsent;
-	}
-};
-
-#endif // !SOCKET_NO_SSL
-
-/* }}} */
-
-} // !protocol
-
-/* }}} */
-
-/*
- * Convenient helpers
- * ------------------------------------------------------------------
- *
- * - SocketTcp<Address>, for TCP sockets,
- * - SocketUdp<Address>, for UDP sockets,
- * - SocketTls<Address>, for secure TCP sockets.
- */
-
-/* {{{ Helpers */
-
-/**
- * Helper to create TCP sockets.
- */
-template <typename Address>
-using SocketTcp = Socket<Address, protocol::Tcp>;
-
-/**
- * Helper to create TCP/IP sockets.
- */
-using SocketTcpIp = Socket<address::Ip, protocol::Tcp>;
-
-#if !defined(_WIN32)
-
-/**
- * Helper to create TCP/Local sockets.
- */
-using SocketTcpLocal = Socket<address::Local, protocol::Tcp>;
-
-#endif
-
-/**
- * Helper to create UDP sockets.
- */
-template <typename Address>
-using SocketUdp = Socket<Address, protocol::Udp>;
-
-/**
- * Helper to create UDP/IP sockets.
- */
-using SocketUdpIp = Socket<address::Ip, protocol::Udp>;
-
-#if !defined(SOCKET_NO_SSL)
-
-/**
- * Helper to create OpenSSL TCP sockets.
- */
-template <typename Address>
-using SocketTls = Socket<Address, protocol::Tls>;
-
-/**
- * Helper to create OpenSSL TCP/Ip sockets.
- */
-using SocketTlsIp = Socket<address::Ip, protocol::Tls>;
-
-#endif // !SOCKET_NO_SSL
-
-/* }}} */
-
-/*
- * Select wrapper
- * ------------------------------------------------------------------
- *
- * Wrapper for select(2) and other various implementations.
- */
-
-/* {{{ Listener */
-
-/**
- * @class ListenerStatus
- * @brief Result of polling
- *
- * Result of a select call, returns the first ready socket found with its
- * flags.
- */
-class ListenerStatus {
-public:
-	Handle socket;		//!< which socket is ready
-	Condition flags;	//!< the flags
-};
-
-/**
- * Table used in the socket listener to store which sockets have been
- * set in which directions.
- */
-using ListenerTable = std::map<Handle, Condition>;
-
-/**
- * @class Select
- * @brief Implements select(2)
- *
- * This class is the fallback of any other method, it is not preferred at all for many reasons.
- */
-class Select {
-public:
-	/**
-	 * No-op, uses the ListenerTable directly.
-	 */
-	inline void set(const ListenerTable &, Handle, Condition, bool) noexcept {}
-
-	/**
-	 * No-op, uses the ListenerTable directly.
-	 */
-	inline void unset(const ListenerTable &, Handle, Condition, bool) noexcept {}
-
-	/**
-	 * Return the sockets
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &table, int ms);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "select";
-	}
-};
-
-#if defined(SOCKET_HAVE_POLL)
-
-/**
- * @class Poll
- * @brief Implements poll(2).
- *
- * Poll is widely supported and is better than select(2). It is still not the
- * best option as selecting the sockets is O(n).
- */
-class Poll {
-private:
-	std::vector<pollfd> m_fds;
-
-	short toPoll(Condition flags) const noexcept;
-	Condition toCondition(short &event) const noexcept;
-
-public:
-	/**
-	 * Set the handle.
-	 */
-	void set(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Unset the handle.
-	 */
-	void unset(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Wait for events.
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "poll";
-	}
-};
-
-#endif
-
-#if defined(SOCKET_HAVE_EPOLL)
-
-/**
- * @class Epoll
- * @brief Linux's epoll.
- */
-class Epoll {
-private:
-	int m_handle;
-	std::vector<epoll_event> m_events;
-
-	Epoll(const Epoll &) = delete;
-	Epoll &operator=(const Epoll &) = delete;
-	Epoll(const Epoll &&) = delete;
-	Epoll &operator=(const Epoll &&) = delete;
-
-	uint32_t toEpoll(Condition flags) const noexcept;
-	Condition toCondition(uint32_t events) const noexcept;
-	void update(Handle sc, int op, int eflags);
-
-public:
-	/**
-	 * Construct the epoll instance.
-	 */
-	Epoll();
-
-	/**
-	 * Close the epoll instance.
-	 */
-	~Epoll();
-
-	/**
-	 * Set the handle.
-	 */
-	void set(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Unset the handle.
-	 */
-	void unset(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Wait for events.
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &, int);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "epoll";
-	}
-};
-
-#endif
-
-#if defined(SOCKET_HAVE_KQUEUE)
-
-/**
- * @class Kqueue
- * @brief Implements kqueue(2).
- *
- * This implementation is available on all BSD and Mac OS X. It is better than
- * poll(2) because it's O(1), however it's a bit more memory consuming.
- */
-class Kqueue {
-private:
-	std::vector<struct kevent> m_result;
-	int m_handle;
-
-	Kqueue(const Kqueue &) = delete;
-	Kqueue &operator=(const Kqueue &) = delete;
-	Kqueue(Kqueue &&) = delete;
-	Kqueue &operator=(Kqueue &&) = delete;
-
-	void update(Handle sc, int filter, int kflags);
-
-public:
-	/**
-	 * Construct the kqueue instance.
-	 */
-	Kqueue();
-
-	/**
-	 * Destroy the kqueue instance.
-	 */
-	~Kqueue();
-
-	/**
-	 * Set the handle.
-	 */
-	void set(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Unset the handle.
-	 */
-	void unset(const ListenerTable &, Handle, Condition, bool);
-
-	/**
-	 * Wait for events.
-	 */
-	std::vector<ListenerStatus> wait(const ListenerTable &, int);
-
-	/**
-	 * Backend identifier
-	 */
-	inline const char *name() const noexcept
-	{
-		return "kqueue";
-	}
-};
-
-#endif
-
-/**
- * @class Listener
- * @brief Synchronous multiplexing
- *
- * Convenient wrapper around the select() system call.
- *
- * This class is implemented using a bridge pattern to allow different uses
- * of listener implementation.
- *
- * You should not reinstanciate a new Listener at each iteartion of your
- * main loop as it can be extremely costly. Instead use the same listener that
- * you can safely modify on the fly.
- *
- * Currently, poll, epoll, select and kqueue are available.
- *
- * To implement the backend, the following functions must be available:
- *
- * ### Set
- *
- * @code
- * void set(const ListenerTable &, Handle sc, Condition condition, bool add);
- * @endcode
- *
- * This function, takes the socket to be added and the flags. The condition is
- * always guaranteed to be correct and the function will never be called twice
- * even if the user tries to set the same flag again.
- *
- * An optional add argument is added for backends which needs to do different
- * operation depending if the socket was already set before or if it is the
- * first time (e.g EPOLL_CTL_ADD vs EPOLL_CTL_MOD for epoll(7).
- *
- * ### Unset
- *
- * @code
- * void unset(const ListenerTable &, Handle sc, Condition condition, bool remove);
- * @endcode
- *
- * Like set, this function is only called if the condition is actually set and will
- * not be called multiple times.
- *
- * Also like set, an optional remove argument is set if the socket is being
- * completely removed (e.g no more flags are set for this socket).
- *
- * ### Wait
- *
- * @code
- * std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
- * @endcode
- *
- * Wait for the sockets to be ready with the specified milliseconds. Must return a list of ListenerStatus,
- * may throw any exceptions.
- *
- * ### Name
- *
- * @code
- * inline const char *name() const noexcept
- * @endcode
- *
- * Returns the backend name. Usually the class in lower case.
- */
-template <typename Backend = SOCKET_DEFAULT_BACKEND>
-class Listener {
-private:
-	Backend m_backend;
-	ListenerTable m_table;
-
-public:
-	/**
-	 * Construct an empty listener.
-	 */
-	Listener() = default;
-
-	/**
-	 * Get the backend.
-	 *
-	 * @return the backend
-	 */
-	inline const Backend &backend() const noexcept
-	{
-		return m_backend;
-	}
-
-	/**
-	 * Get the non-modifiable table.
-	 *
-	 * @return the table
-	 */
-	inline const ListenerTable &table() const noexcept
-	{
-		return m_table;
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator begin() const noexcept
-	{
-		return m_table.begin();
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator cbegin() const noexcept
-	{
-		return m_table.cbegin();
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator end() const noexcept
-	{
-		return m_table.end();
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @return the iterator
-	 */
-	inline ListenerTable::const_iterator cend() const noexcept
-	{
-		return m_table.cend();
-	}
-
-	/**
-	 * Add or update a socket to the listener.
-	 *
-	 * If the socket is already placed with the appropriate flags, the
-	 * function is a no-op.
-	 *
-	 * If incorrect flags are passed, the function does nothing.
-	 *
-	 * @param sc the socket
-	 * @param condition the condition (may be OR'ed)
-	 * @throw Error if the backend failed to set
-	 */
-	void set(Handle sc, Condition condition)
-	{
-		/* Invalid or useless flags */
-		if (condition == Condition::None || static_cast<int>(condition) > 0x3)
-			return;
-
-		auto it = m_table.find(sc);
-
-		/*
-		 * Do not update the table if the backend failed to add
-		 * or update.
-		 */
-		if (it == m_table.end()) {
-			m_backend.set(m_table, sc, condition, true);
-			m_table.emplace(sc, condition);
-		} else {
-			/* Remove flag if already present */
-			if ((condition & Condition::Readable) == Condition::Readable &&
-			    (it->second & Condition::Readable) == Condition::Readable) {
-				condition &= ~(Condition::Readable);
-			}
-			if ((condition & Condition::Writable) == Condition::Writable &&
-			    (it->second & Condition::Writable) == Condition::Writable) {
-				condition &= ~(Condition::Writable);
-			}
-
-			/* Still need a call? */
-			if (condition != Condition::None) {
-				m_backend.set(m_table, sc, condition, false);
-				it->second |= condition;
-			}
-		}
-	}
-
-	/**
-	 * Unset a socket from the listener, only the flags is removed
-	 * unless the two flagss are requested.
-	 *
-	 * For example, if you added a socket for both reading and writing,
-	 * unsetting the write flags will keep the socket for reading.
-	 *
-	 * @param sc the socket
-	 * @param condition the condition (may be OR'ed)
-	 * @see remove
-	 */
-	void unset(Handle sc, Condition condition)
-	{
-		auto it = m_table.find(sc);
-
-		/* Invalid or useless flags */
-		if (condition == Condition::None || static_cast<int>(condition) > 0x3 || it == m_table.end())
-			return;
-
-		/*
-		 * Like set, do not update if the socket is already at the appropriate
-		 * state.
-		 */
-		if ((condition & Condition::Readable) == Condition::Readable &&
-		    (it->second & Condition::Readable) != Condition::Readable) {
-			condition &= ~(Condition::Readable);
-		}
-		if ((condition & Condition::Writable) == Condition::Writable &&
-		    (it->second & Condition::Writable) != Condition::Writable) {
-			condition &= ~(Condition::Writable);
-		}
-
-		if (condition != Condition::None) {
-			/* Determine if it's a complete removal */
-			bool removal = ((it->second) & ~(condition)) == Condition::None;
-
-			m_backend.unset(m_table, sc, condition, removal);
-
-			if (removal) {
-				m_table.erase(it);
-			} else {
-				it->second &= ~(condition);
-			}
-		}
-	}
-
-	/**
-	 * Remove completely the socket from the listener.
-	 *
-	 * It is a shorthand for unset(sc, Condition::Readable | Condition::Writable);
-	 *
-	 * @param sc the socket
-	 */
-	inline void remove(Handle sc)
-	{
-		unset(sc, Condition::Readable | Condition::Writable);
-	}
-
-	/**
-	 * Remove all sockets.
-	 */
-	inline void clear()
-	{
-		while (!m_table.empty()) {
-			remove(m_table.begin()->first);
-		}
-	}
-
-	/**
-	 * Get the number of sockets in the listener.
-	 */
-	inline ListenerTable::size_type size() const noexcept
-	{
-		return m_table.size();
-	}
-
-	/**
-	 * Select a socket. Waits for a specific amount of time specified as the duration.
-	 *
-	 * @param duration the duration
-	 * @return the socket ready
-	 */
-	template <typename Rep, typename Ratio>
-	inline ListenerStatus wait(const std::chrono::duration<Rep, Ratio> &duration)
-	{
-		assert(!m_table.empty());
-
-		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
-
-		return m_backend.wait(m_table, cvt.count())[0];
-	}
-
-	/**
-	 * Overload with milliseconds.
-	 *
-	 * @param timeout the optional timeout in milliseconds
-	 * @return the socket ready
-	 */
-	inline ListenerStatus wait(int timeout = -1)
-	{
-		return wait(std::chrono::milliseconds(timeout));
-	}
-
-	/**
-	 * Select multiple sockets.
-	 *
-	 * @param duration the duration
-	 * @return the socket ready
-	 */
-	template <typename Rep, typename Ratio>
-	inline std::vector<ListenerStatus> waitMultiple(const std::chrono::duration<Rep, Ratio> &duration)
-	{
-		assert(!m_table.empty());
-
-		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
-
-		return m_backend.wait(m_table, cvt.count());
-	}
-
-	/**
-	 * Overload with milliseconds.
-	 *
-	 * @return the socket ready
-	 */
-	inline std::vector<ListenerStatus> waitMultiple(int timeout = -1)
-	{
-		return waitMultiple(std::chrono::milliseconds(timeout));
-	}
-};
-
-/* }}} */
-
-/*
- * Callback
- * ------------------------------------------------------------------
- *
- * Function owner with tests.
- */
-
-/* {{{ Callback */
-
-/**
- * @class Callback
- * @brief Convenient signal owner that checks if the target is valid.
- *
- * This class also catch all errors thrown from signals to avoid interfering with our process.
- */
-template <typename... Args>
-class Callback : public std::function<void (Args...)> {
-public:
-	/**
-	 * Inherited constructors.
-	 */
-	using std::function<void (Args...)>::function;
-
-	/**
-	 * Execute the callback only if a target is set.
-	 */
-	void operator()(Args... args) const
-	{
-		if (*this) {
-			try {
-				std::function<void (Args...)>::operator()(args...);
-			} catch (...) {
-			}
-		}
-	}
-};
-
-/* }}} */
-
-/*
- * StreamConnection
- * ------------------------------------------------------------------
- *
- * Client connected on the server side.
- */
-
-/* {{{ StreamConnection */
-
-/**
- * @class StreamConnection
- * @brief Connected client on the server side.
- *
- * This object is created from StreamServer when a new client is connected, it is the higher
- * level object of sockets and completely asynchronous.
- */
-template <typename Address, typename Protocol>
-class StreamConnection {
-public:
-	/**
-	 * Called when the output has changed.
-	 */
-	using WriteHandler = Callback<>;
-
-private:
-	/* Signals */
-	WriteHandler m_onWrite;
-
-	/* Sockets and output buffer */
-	Socket<Address, Protocol> m_socket;
-	std::string m_output;
-
-public:
-	/**
-	 * Create the connection.
-	 *
-	 * @param s the socket
-	 */
-	StreamConnection(Socket<Address, Protocol> s)
-		: m_socket{std::move(s)}
-	{
-		m_socket.set(net::option::SockBlockMode{false});
-	}
-
-	/**
-	 * Access the underlying socket.
-	 *
-	 * @return the socket
-	 * @warning use with care
-	 */
-	inline Socket<Address, Protocol> &socket() noexcept
-	{
-		return m_socket;
-	}
-
-	/**
-	 * Access the current output.
-	 *
-	 * @return the output
-	 */
-	inline const std::string &output() const noexcept
-	{
-		return m_output;
-	}
-
-	/**
-	 * Overloaded function
-	 *
-	 * @return the output
-	 * @warning use with care, avoid modifying the output if you don't know what you're doing
-	 */
-	inline std::string &output() noexcept
-	{
-		return m_output;
-	}
-
-	/**
-	 * Post some data to be sent asynchronously.
-	 *
-	 * @param str the data to append
-	 */
-	inline void send(std::string str)
-	{
-		m_output += str;
-		m_onWrite();
-	}
-
-	/**
-	 * Kill the client.
-	 */
-	inline void close()
-	{
-		m_socket.close();
-	}
-
-	/**
-	 * Set the write handler, the signal is emitted when the output has changed so that the StreamServer owner
-	 * knows that there are some data to send.
-	 *
-	 * @param handler the handler
-	 * @warning you usually never need to set this yourself
-	 */
-	inline void setWriteHandler(WriteHandler handler)
-	{
-		m_onWrite = std::move(handler);
-	}
-};
-
-/* }}} */
-
-/*
- * StreamServer
- * ------------------------------------------------------------------
- *
- * Convenient stream oriented server.
- */
-
-/* {{{ StreamServer */
-
-/**
- * @class StreamServer
- * @brief Convenient stream server for TCP and TLS.
- *
- * This class does all the things for you as accepting new clients, listening for it and sending data. It works
- * asynchronously without blocking to let you control your process workflow.
- *
- * This class is not thread safe and you must not call any of the functions from different threads.
- */
-template <typename Address, typename Protocol>
-class StreamServer {
-public:
-	/**
-	 * Handler when a new client is connected.
-	 */
-	using ConnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
-
-	/**
-	 * Handler when a client is disconnected.
-	 */
-	using DisconnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
-
-	/**
-	 * Handler when data has been received from a client.
-	 */
-	using ReadHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
-
-	/**
-	 * Handler when data has been correctly sent to a client.
-	 */
-	using WriteHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
-
-	/**
-	 * Handler when an error occured.
-	 */
-	using ErrorHandler = Callback<const Error &>;
-
-	/**
-	 * Handler when there was a timeout.
-	 */
-	using TimeoutHandler = Callback<>;
-
-private:
-	using ClientMap = std::map<Handle, std::shared_ptr<StreamConnection<Address, Protocol>>>;
-
-	/* Signals */
-	ConnectionHandler m_onConnection;
-	DisconnectionHandler m_onDisconnection;
-	ReadHandler m_onRead;
-	WriteHandler m_onWrite;
-	ErrorHandler m_onError;
-	TimeoutHandler m_onTimeout;
-
-	/* Sockets */
-	Socket<Address, Protocol> m_master;
-	Listener<> m_listener;
-	ClientMap m_clients;
-
-	/*
-	 * Update flags depending on the required condition.
-	 */
-	void updateFlags(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
-	{
-		assert(client->socket().action() != Action::None);
-
-		m_listener.remove(client->socket().handle());
-		m_listener.set(client->socket().handle(), client->socket().condition());
-	}
-
-	/*
-	 * Continue accept process.
-	 */
-	template <typename AcceptCall>
-	void processAccept(std::shared_ptr<StreamConnection<Address, Protocol>> &client, const AcceptCall &acceptFunc)
-	{
-		try {
-			/* Do the accept */
-			acceptFunc();
-
-			/* 1. First remove completely the client */
-			m_listener.remove(client->socket().handle());
-
-			/* 2. If accept is not finished, wait for the appropriate condition */
-			if (client->socket().state() == State::Accepted) {
-				/* 3. Client is accepted, notify the user */
-				m_listener.set(client->socket().handle(), Condition::Readable);
-				m_onConnection(client);
-			} else {
-				/* Operation still in progress */
-				updateFlags(client);
-			}
-		} catch (const Error &error) {
-			m_clients.erase(client->socket().handle());
-			m_listener.remove(client->socket().handle());
-			m_onError(error);
-		}
-	}
-
-	/*
-	 * Process initial accept of master socket, this is the initial accepting process. Except on errors, the
-	 * socket is stored but the user will be notified only once the socket is completely accepted.
-	 */
-	void processInitialAccept()
-	{
-		// TODO: store address too.
-		std::shared_ptr<StreamConnection<Address, Protocol>> client = std::make_shared<StreamConnection<Address, Protocol>>(m_master.accept(nullptr));
-		std::weak_ptr<StreamConnection<Address, Protocol>> ptr{client};
-
-		/* 1. Register output changed to update listener */
-		client->setWriteHandler([this, ptr] () {
-			auto client = ptr.lock();
-
-			/* Do not update the listener immediately if an action is pending */
-			if (client && client->socket().action() == Action::None && !client->output().empty()) {
-				m_listener.set(client->socket().handle(), Condition::Writable);
-			}
-		});
-
-		/* 2. Add the client */
-		m_clients.insert(std::make_pair(client->socket().handle(), client));
-
-		/*
-		 * 2. Do an initial check to set the listener flags, at this moment the socket may or not be
-		 *    completely accepted.
-		 */
-		processAccept(client, [&] () {});
-	}
-
-	/*
-	 * Read or complete the read operation.
-	 */
-	void processRead(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
-	{
-		/*
-		 * Read because there is something to read or because the pending operation is
-		 * read and must complete.
-		 */
-		auto buffer = client->socket().recv(512);
-
-		/*
-		 * Now the receive operation may be completed, in that case, two possibilities:
-		 *
-		 * 1. The action is set to None (completed)
-		 * 2. The action is still not complete, update the flags
-		 */
-		if (client->socket().action() == Action::None) {
-			/* Empty mean normal disconnection */
-			if (buffer.empty()) {
-				m_listener.remove(client->socket().handle());
-				m_clients.erase(client->socket().handle());
-				m_onDisconnection(client);
-			} else {
-				/*
-				 * At this step, it is possible that we were completing a receive operation, in this
-				 * case the write flag may be removed, add it if required.
-				 */
-				if (!client->output().empty()) {
-					m_listener.set(client->socket().handle(), Condition::Writable);
-				}
-
-				m_onRead(client, buffer);
-			}
-		} else {
-			/* Operation in progress */
-			updateFlags(client);
-		}
-	}
-
-	/*
-	 * Flush the output buffer.
-	 */
-	void processWrite(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
-	{
-		auto &output = client->output();
-		auto nsent = client->socket().send(output);
-
-		if (client->socket().action() == Action::None) {
-			/* 1. Create a copy of content that has been sent */
-			auto sent = output.substr(0, nsent);
-
-			/* 2. Erase the content sent */
-			output.erase(0, nsent);
-
-			/* 3. Update listener */
-			if (output.empty()) {
-				m_listener.unset(client->socket().handle(), Condition::Writable);
-			}
-
-			/* 4. Notify user */
-			m_onWrite(client, sent);
-		} else {
-			updateFlags(client);
-		}
-	}
-
-	void processSync(std::shared_ptr<StreamConnection<Address, Protocol>> &client, Condition flags)
-	{
-		try {
-			auto action = client->socket().action();
-
-			if (action == Action::Receive ||
-			    (action == Action::None && (flags & Condition::Readable) == Condition::Readable)) {
-				processRead(client);
-			} else if ((flags & Condition::Writable) == Condition::Writable) {
-				processWrite(client);
-			}
-		} catch (const Error &error) {
-			m_onDisconnection(client);
-			m_listener.remove(client->socket().handle());
-			m_clients.erase(client->socket().handle());
-		}
-	}
-
-public:
-	/**
-	 * Create a stream server with the specified address to bind.
-	 *
-	 * @param protocol the protocol (Tcp or Tls)
-	 * @param address the address to bind
-	 * @param max the max number to listen
-	 * @throw Error on errors
-	 */
-	StreamServer(Protocol protocol, const Address &address, int max = 128)
-		: m_master{std::move(protocol), address}
-	{
-		// TODO: m_onError
-		m_master.set(SOL_SOCKET, SO_REUSEADDR, 1);
-		m_master.bind(address);
-		m_master.listen(max);
-		m_listener.set(m_master.handle(), Condition::Readable);
-	}
-
-	/**
-	 * Set the connection handler, called when a new client is connected.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setConnectionHandler(ConnectionHandler handler)
-	{
-		m_onConnection = std::move(handler);
-	}
-
-	/**
-	 * Set the disconnection handler, called when a client died.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setDisconnectionHandler(DisconnectionHandler handler)
-	{
-		m_onDisconnection = std::move(handler);
-	}
-
-	/**
-	 * Set the receive handler, called when a client has sent something.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setReadHandler(ReadHandler handler)
-	{
-		m_onRead = std::move(handler);
-	}
-
-	/**
-	 * Set the writing handler, called when some data has been sent to a client.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setWriteHandler(WriteHandler handler)
-	{
-		m_onWrite = std::move(handler);
-	}
-
-	/**
-	 * Set the error handler, called when unrecoverable error has occured.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setErrorHandler(ErrorHandler handler)
-	{
-		m_onError = std::move(handler);
-	}
-
-	/**
-	 * Set the timeout handler, called when the selection has timeout.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setTimeoutHandler(TimeoutHandler handler)
-	{
-		m_onTimeout = std::move(handler);
-	}
-
-	/**
-	 * Poll for the next event.
-	 *
-	 * @param timeout the timeout (-1 for indefinitely)
-	 * @throw Error on errors
-	 */
-	void poll(int timeout = -1)
-	{
-		try {
-			auto st = m_listener.wait(timeout);
-
-			if (st.socket == m_master.handle()) {
-				/* New client */
-				processInitialAccept();
-			} else {
-				/* Recv / Send / Accept on a client */
-				auto client = m_clients[st.socket];
-
-				if (client->socket().state() == State::Accepted) {
-					processSync(client, st.flags);
-				} else {
-					processAccept(client, [&] () { client->socket().accept(); });
-				}
-			}
-		} catch (const Error &error) {
-			if (error.code() == Error::Timeout) {
-				m_onTimeout();
-			} else {
-				m_onError(error);
-			}
-		}
-	}
-};
-
-/* }}} */
-
-/*
- * StreamClient
- * ------------------------------------------------------------------
- */
-
-/* {{{ StreamClient */
-
-/**
- * @class StreamClient
- * @brief Client side connection to a server.
- *
- * This class is not thread safe and you must not call any of the functions from different threads.
- */
-template <typename Address, typename Protocol>
-class StreamClient {
-public:
-	/**
-	 * Handler when connection is complete.
-	 */
-	using ConnectionHandler = Callback<>;
-
-	/**
-	 * Handler when data has been received.
-	 */
-	using ReadHandler = Callback<const std::string &>;
-
-	/**
-	 * Handler when data has been sent correctly.
-	 */
-	using WriteHandler = Callback<const std::string &>;
-
-	/**
-	 * Handler when disconnected.
-	 */
-	using DisconnectionHandler = Callback<>;
-
-	/**
-	 * Handler on unrecoverable error.
-	 */
-	using ErrorHandler = Callback<const Error &>;
-
-	/**
-	 * Handler when timeout occured.
-	 */
-	using TimeoutHandler = Callback<>;
-
-private:
-	/* Signals */
-	ConnectionHandler m_onConnection;
-	ReadHandler m_onRead;
-	WriteHandler m_onWrite;
-	DisconnectionHandler m_onDisconnection;
-	ErrorHandler m_onError;
-	TimeoutHandler m_onTimeout;
-
-	/* Socket */
-	Socket<Address, Protocol> m_socket;
-	Listener<> m_listener;
-
-	/* Output buffer */
-	std::string m_output;
-
-	/*
-	 * Update the flags after an uncompleted operation. This function must only be called when the operation
-	 * has not complete (e.g. connect, recv, send).
-	 */
-	void updateFlags()
-	{
-		assert(m_socket.action() != Action::None);
-
-		m_listener.remove(m_socket.handle());
-		m_listener.set(m_socket.handle(), m_socket.condition());
-	}
-
-	/*
-	 * This is the generic connect helper, it will be used to both initiate the connection or to continue the
-	 * connection process if needed.
-	 *
-	 * Thus the template parameter is the appropriate function to call either, m_socket.connect(address) or
-	 * m_socket.connect().
-	 *
-	 * See poll() and connect() to understand.
-	 */
-	template <typename ConnectCall>
-	void processConnect(const ConnectCall &connectFunc)
-	{
-		/* Call m_socket.connect() or m_socket.connect(address) */
-		connectFunc();
-
-		/* Remove entirely */
-		m_listener.remove(m_socket.handle());
-
-		if (m_socket.state() == State::Connected) {
-			m_onConnection();
-			m_listener.set(m_socket.handle(), Condition::Readable);
-		} else {
-			/* Connection still in progress */
-			updateFlags();
-		}
-	}
-
-	/*
-	 * Receive or complete the receive command, if the command is not complete, the listener is updated
-	 * accordingly.
-	 */
-	void processRead()
-	{
-		auto received = m_socket.recv(512);
-
-		if (m_socket.action() == Action::None) {
-			/* 0 means disconnection */
-			if (received.empty()) {
-				m_onDisconnection();
-			} else {
-				/*
-				 * At this step, it is possible that we were completing a receive operation, in this
-				 * case the write flag may be removed, add it if required.
-				 */
-				if (m_output.empty()) {
-					m_listener.unset(m_socket.handle(), Condition::Writable);
-				}
-
-				m_onRead(received);
-			}
-		} else {
-			/* Receive operation in progress */
-			updateFlags();
-		}
-	}
-
-	/*
-	 * Send or complete the send command, if the command is not complete, the listener is updated
-	 * accordingly.
-	 */
-	void processWrite()
-	{
-		auto nsent = m_socket.send(m_output);
-
-		if (m_socket.action() == Action::None) {
-			/* 1. Make a copy of what has been sent */
-			auto sent = m_output.substr(0, nsent);
-
-			/* 2. Erase sent content */
-			m_output.erase(0, nsent);
-
-			/* 3. Update flags if needed */
-			if (m_output.empty()) {
-				m_listener.unset(m_socket.handle(), Condition::Writable);
-			}
-
-			/* 4. Notify user */
-			m_onWrite(sent);
-		} else {
-			/* Send operation in progress */
-			updateFlags();
-		}
-	}
-
-	/*
-	 * Receive or send.
-	 */
-	void processSync(Condition condition)
-	{
-		if ((m_socket.action() == Action::Receive) ||
-		    (m_socket.action() == Action::None && (condition & Condition::Readable) == Condition::Readable)) {
-			processRead();
-		} else {
-			processWrite();
-		}
-	}
-
-public:
-	/**
-	 * Create a client. The client is automatically marked as non-blocking.
-	 *
-	 * @param protocol the protocol (Tcp or Tls)
-	 * @param address the optional address
-	 * @throw net::Error on failures
-	 */
-	StreamClient(Protocol protocol = {}, const Address &address = {})
-		: m_socket{std::move(protocol), address}
-	{
-		m_socket.set(net::option::SockBlockMode{false});
-		m_listener.set(m_socket.handle(), Condition::Readable);
-	}
-
-	/**
-	 * Set the connection handler, called when the connection succeed.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setConnectionHandler(ConnectionHandler handler)
-	{
-		m_onConnection = std::move(handler);
-	}
-
-	/**
-	 * Set the disconnection handler, called when the server closed the connection.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setDisconnectionHandler(DisconnectionHandler handler)
-	{
-		m_onDisconnection = std::move(handler);
-	}
-
-	/**
-	 * Set the read handler, called when we received something.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setReadHandler(ReadHandler handler)
-	{
-		m_onRead = std::move(handler);
-	}
-
-	/**
-	 * Set the write handler, called when we successfully sent data.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setWriteHandler(WriteHandler handler)
-	{
-		m_onWrite = std::move(handler);
-	}
-
-	/**
-	 * Set the error handler, called when unexpected error occurs.
-	 *
-	 * @param handler the handler
-	 */
-	inline void setErrorHandler(ErrorHandler handler)
-	{
-		m_onError = std::move(handler);
-	}
-
-	/**
-	 * Connect to a server, this function may connect immediately or not in any case the connection handler
-	 * will be called when the connection completed.
-	 *
-	 * @param address the address to connect to
-	 */
-	void connect(const Address &address) noexcept
-	{
-		assert(m_socket.state() == State::Open);
-
-		processConnect([&] () { m_socket.connect(address); });
-	}
-
-	/**
-	 * Asynchronously send data to the server.
-	 *
-	 * @param str the data to append
-	 */
-	void send(std::string str)
-	{
-		m_output += str;
-
-		/* Don't update the listener if there is a pending operation */
-		if (m_socket.state() == State::Connected && m_socket.action() == Action::None && !m_output.empty()) {
-			m_listener.set(m_socket.handle(), Condition::Writable);
-		}
-	}
-
-	/**
-	 * Wait for the next event.
-	 *
-	 * @param timeout the time to wait in milliseconds
-	 * @throw Error on errors
-	 */
-	void poll(int timeout = -1) noexcept
-	{
-		try {
-			auto st = m_listener.wait(timeout);
-
-			if (m_socket.state() != State::Connected) {
-				/* Continue the connection */
-				processConnect([&] () { m_socket.connect(); });
-			} else {
-				/* Read / Write */
-				processSync(st.flags);
-			}
-		} catch (const Error &error) {
-			if (error.code() == Error::Timeout) {
-				m_onTimeout();
-			} else {
-				m_listener.remove(m_socket.handle());
-				m_onError(error);
-			}
-		}
-	}
-};
-
-/* }}} */
-
-} // !net
-
-} // !irccd
-
-#endif // !IRCCD_SOCKETS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/sockets.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,4078 @@
+/*
+ * sockets.hpp -- portable C++ socket wrappers
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SOCKETS_HPP
+#define IRCCD_SOCKETS_HPP
+
+/**
+ * @file sockets.hpp
+ * @brief Portable socket abstraction
+ *
+ * # Introduction
+ *
+ * This file is a portable networking library.
+ *
+ * ## Options
+ *
+ * The user may set the following variables before compiling these files:
+ *
+ * ### General options
+ *
+ * - **SOCKET_NO_AUTO_INIT**: (bool) Set to 0 if you don't want Socket class to
+ * automatically calls net::init function and net::finish functions.
+ * - **SOCKET_NO_SSL**: (bool) Set to 0 if you don't have access to OpenSSL library.
+ * - **SOCKET_NO_AUTO_SSL_INIT**: (bool) Set to 0 if you don't want Socket class with Tls to automatically init
+ * the OpenSSL library. You will need to call net::ssl::init and net::ssl::finish.
+ *
+ * ### Options for Listener class
+ *
+ * Feature detection, multiple implementations may be avaible, for example, Linux has poll, select and epoll.
+ *
+ * We assume that `select(2)` is always available.
+ *
+ * Of course, you can set the variables yourself if you test it with your build system.
+ *
+ * - **SOCKET_HAVE_POLL**: Defined on all BSD, Linux. Also defined on Windows
+ *   if _WIN32_WINNT is set to 0x0600 or greater.
+ * - **SOCKET_HAVE_KQUEUE**: Defined on all BSD and Apple.
+ * - **SOCKET_HAVE_EPOLL**: Defined on Linux only.
+ * - **SOCKET_DEFAULT_BACKEND**: Which backend to use (e.g. `Select`).
+ *
+ * The preference priority is ordered from left to right.
+ *
+ * | System        | Backend                 | Class name   |
+ * |---------------|-------------------------|--------------|
+ * | Linux         | epoll(7)                | Epoll        |
+ * | *BSD          | kqueue(2)               | Kqueue       |
+ * | Windows       | poll(2), select(2)      | Poll, Select |
+ * | Mac OS X      | kqueue(2)               | Kqueue       |
+ */
+
+#if defined(_WIN32)
+#  if _WIN32_WINNT >= 0x0600 && !defined(SOCKET_HAVE_POLL)
+#    define SOCKET_HAVE_POLL
+#  endif
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+#  if !defined(SOCKET_HAVE_KQUEUE)
+#    define SOCKET_HAVE_KQUEUE
+#  endif
+#  if !defined(SOCKET_HAVE_POLL)
+#    define SOCKET_HAVE_POLL
+#  endif
+#elif defined(__linux__)
+#  if !defined(SOCKET_HAVE_EPOLL)
+#    define SOCKET_HAVE_EPOLL
+#  endif
+#  if !defined(SOCKET_HAVE_POLL)
+#    define SOCKET_HAVE_POLL
+#  endif
+#endif
+
+/*
+ * Define SOCKET_DEFAULT_BACKEND
+ * ------------------------------------------------------------------
+ */
+
+/**
+ * Defines the default Listener backend to use.
+ *
+ * @note Do not rely on the value shown in doxygen.
+ */
+#if defined(_WIN32)
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    if defined(SOCKET_HAVE_POLL)
+#      define SOCKET_DEFAULT_BACKEND Poll
+#    else
+#      define SOCKET_DEFAULT_BACKEND Select
+#    endif
+#  endif
+#elif defined(__linux__)
+#  include <sys/epoll.h>
+
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    define SOCKET_DEFAULT_BACKEND Epoll
+#  endif
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#  include <sys/types.h>
+#  include <sys/event.h>
+#  include <sys/time.h>
+
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    define SOCKET_DEFAULT_BACKEND Kqueue
+#  endif
+#else
+#  if !defined(SOCKET_DEFAULT_BACKEND)
+#    define SOCKET_DEFAULT_BACKEND Select
+#  endif
+#endif
+
+#if defined(SOCKET_HAVE_POLL) && !defined(_WIN32)
+#  include <poll.h>
+#endif
+
+/*
+ * Headers to include
+ * ------------------------------------------------------------------
+ */
+
+#if defined(_WIN32)
+#  include <cstdlib>
+
+#  include <WinSock2.h>
+#  include <WS2tcpip.h>
+#else
+#  include <cerrno>
+
+#  include <sys/ioctl.h>
+#  include <sys/types.h>
+#  include <sys/socket.h>
+#  include <sys/un.h>
+
+#  include <arpa/inet.h>
+
+#  include <netinet/in.h>
+#  include <netinet/tcp.h>
+
+#  include <fcntl.h>
+#  include <netdb.h>
+#  include <unistd.h>
+#endif
+
+#if !defined(SOCKET_NO_SSL)
+#  include <openssl/err.h>
+#  include <openssl/evp.h>
+#  include <openssl/ssl.h>
+#endif
+
+#include <cassert>
+#include <chrono>
+#include <cstdlib>
+#include <cstring>
+#include <exception>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace irccd {
+
+/**
+ * General network namespace.
+ */
+namespace net {
+
+/*
+ * Portables types
+ * ------------------------------------------------------------------
+ *
+ * The following types are defined differently between Unix and Windows.
+ */
+
+/* {{{ Protocols */
+
+#if defined(_WIN32)
+
+/**
+ * Socket type, SOCKET.
+ */
+using Handle	= SOCKET;
+
+/**
+ * Argument to pass to set.
+ */
+using ConstArg	= const char *;
+
+/**
+ * Argument to pass to get.
+ */
+using Arg	= char *;
+
+#else
+
+/**
+ * Socket type, int.
+ */
+using Handle	= int;
+
+/**
+ * Argument to pass to set.
+ */
+using ConstArg	= const void *;
+
+/**
+ * Argument to pass to get.
+ */
+using Arg	= void *;
+
+#endif
+
+/* }}} */
+
+/*
+ * Portable constants
+ * ------------------------------------------------------------------
+ *
+ * These constants are needed to check functions return codes, they are rarely needed in end user code.
+ */
+
+/* {{{ Constants */
+
+/*
+ * The following constants are defined differently from Unix
+ * to Windows.
+ */
+#if defined(_WIN32)
+
+/**
+ * Socket creation failure or invalidation.
+ */
+extern const Handle Invalid;
+
+/**
+ * Socket operation failure.
+ */
+extern const int Failure;
+
+#else
+
+/**
+ * Socket creation failure or invalidation.
+ */
+extern const int Invalid;
+
+/**
+ * Socket operation failure.
+ */
+extern const int Failure;
+
+#endif
+
+#if !defined(SOCKET_NO_SSL)
+
+namespace ssl {
+
+/**
+ * @enum Method
+ * @brief Which OpenSSL method to use.
+ */
+enum Method {
+	Tlsv1,		//!< TLS v1.2 (recommended)
+	Sslv3		//!< SSLv3
+};
+
+} // !ssl
+
+#endif
+
+/* }}} */
+
+/*
+ * Portable functions
+ * ------------------------------------------------------------------
+ *
+ * The following free functions can be used to initialize the library or to get the last system error.
+ */
+
+/* {{{ Functions */
+
+/**
+ * Initialize the socket library. Except if you defined SOCKET_NO_AUTO_INIT, you don't need to call this
+ * function manually.
+ */
+void init() noexcept;
+
+/**
+ * Close the socket library.
+ */
+void finish() noexcept;
+
+#if !defined(SOCKET_NO_SSL)
+
+/**
+ * OpenSSL namespace.
+ */
+namespace ssl {
+
+/**
+ * Initialize the OpenSSL library. Except if you defined SOCKET_NO_AUTO_SSL_INIT, you don't need to call this function
+ * manually.
+ */
+void init() noexcept;
+
+/**
+ * Close the OpenSSL library.
+ */
+void finish() noexcept;
+
+} // !ssl
+
+#endif // SOCKET_NO_SSL
+
+/**
+ * Get the last socket system error. The error is set from errno or from
+ * WSAGetLastError on Windows.
+ *
+ * @return a string message
+ */
+std::string error();
+
+/**
+ * Get the last system error.
+ *
+ * @param errn the error number (errno or WSAGetLastError)
+ * @return the error
+ */
+std::string error(int errn);
+
+/* }}} */
+
+/*
+ * Error class
+ * ------------------------------------------------------------------
+ *
+ * This is the main exception thrown on socket operations.
+ */
+
+/* {{{ Error */
+
+/**
+ * @class Error
+ * @brief Base class for sockets error
+ */
+class Error : public std::exception {
+public:
+	/**
+	 * @enum Code
+	 * @brief Which kind of error
+	 */
+	enum Code {
+		Timeout,		///!< The action did timeout
+		System,			///!< There is a system error
+		Other			///!< Other custom error
+	};
+
+private:
+	Code m_code;
+	std::string m_function;
+	std::string m_error;
+
+public:
+	/**
+	 * Constructor that use the last system error.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 */
+	Error(Code code, std::string function);
+
+	/**
+	 * Constructor that use the system error set by the user.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 * @param error the error
+	 */
+	Error(Code code, std::string function, int error);
+
+	/**
+	 * Constructor that set the error specified by the user.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 * @param error the error
+	 */
+	Error(Code code, std::string function, std::string error);
+
+	/**
+	 * Get which function has triggered the error.
+	 *
+	 * @return the function name (e.g connect)
+	 */
+	inline const std::string &function() const noexcept
+	{
+		return m_function;
+	}
+
+	/**
+	 * The error code.
+	 *
+	 * @return the code
+	 */
+	inline Code code() const noexcept
+	{
+		return m_code;
+	}
+
+	/**
+	 * Get the error (only the error content).
+	 *
+	 * @return the error
+	 */
+	const char *what() const noexcept
+	{
+		return m_error.c_str();
+	}
+};
+
+/* }}} */
+
+/*
+ * State class
+ * ------------------------------------------------------------------
+ *
+ * To facilitate higher-level stuff, the socket has a state.
+ */
+
+/* {{{ State */
+
+/**
+ * @enum State
+ * @brief Current socket state.
+ */
+enum class State {
+	Open,			//!< Socket is open
+	Bound,			//!< Socket is bound to an address
+	Connecting,		//!< The connection is in progress
+	Connected,		//!< Connection is complete
+	Accepted,		//!< Socket has been accepted (client)
+	Accepting,		//!< The client acceptation is in progress
+	Closed,			//!< The socket has been closed
+	Disconnected,		//!< The connection was lost
+};
+
+/* }}} */
+
+/*
+ * Action enum
+ * ------------------------------------------------------------------
+ *
+ * Defines the pending operation.
+ */
+
+/* {{{ Action */
+
+/**
+ * @enum Action
+ * @brief Define the current operation that must complete.
+ *
+ * Some operations like accept, connect, recv or send must sometimes do several round-trips to complete and the socket
+ * action is set with that enumeration. The user is responsible of calling accept, connect send or recv until the
+ * operation is complete.
+ *
+ * Note: the user must wait for the appropriate condition in Socket::condition to check if the required condition is
+ * met.
+ *
+ * It is important to complete the operation in the correct order because protocols like Tls may require to continue
+ * re-negociating when calling Socket::send or Socket::Recv.
+ */
+enum class Action {
+	None,		//!< No action is required, socket is ready
+	Accept,		//!< The socket is not yet accepted, caller must call accept() again
+	Connect,	//!< The socket is not yet connected, caller must call connect() again
+	Receive,	//!< The received operation has not succeeded yet, caller must call recv() or recvfrom() again
+	Send		//!< The send operation has not succeded yet, caller must call send() or sendto() again
+};
+
+/* }}} */
+
+/*
+ * Condition enum
+ * ------------------------------------------------------------------
+ *
+ * Defines if we must wait for reading or writing.
+ */
+
+/* {{{ Condition */
+
+/**
+ * @enum Condition
+ * @brief Define the required condition for the socket.
+ *
+ * As explained in Action enumeration, some operations required to be called several times, before calling these
+ * operations, the user must wait the socket to be readable or writable. This can be checked with Socket::condition.
+ */
+enum class Condition {
+	None,			//!< No condition is required
+	Readable = (1 << 0),	//!< The socket must be readable
+	Writable = (1 << 1)	//!< The socket must be writable
+};
+
+/**
+ * Apply bitwise XOR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+constexpr Condition operator^(Condition v1, Condition v2) noexcept
+{
+	return static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
+}
+
+/**
+ * Apply bitwise AND.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+constexpr Condition operator&(Condition v1, Condition v2) noexcept
+{
+	return static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
+}
+
+/**
+ * Apply bitwise OR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+constexpr Condition operator|(Condition v1, Condition v2) noexcept
+{
+	return static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
+}
+
+/**
+ * Apply bitwise NOT.
+ *
+ * @param v the value
+ * @return the complement
+ */
+constexpr Condition operator~(Condition v) noexcept
+{
+	return static_cast<Condition>(~static_cast<int>(v));
+}
+
+/**
+ * Assign bitwise OR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+inline Condition &operator|=(Condition &v1, Condition v2) noexcept
+{
+	v1 = static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
+
+	return v1;
+}
+
+/**
+ * Assign bitwise AND.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+inline Condition &operator&=(Condition &v1, Condition v2) noexcept
+{
+	v1 = static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
+
+	return v1;
+}
+
+/**
+ * Assign bitwise XOR.
+ *
+ * @param v1 the first value
+ * @param v2 the second value
+ * @return the new value
+ */
+inline Condition &operator^=(Condition &v1, Condition v2) noexcept
+{
+	v1 = static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
+
+	return v1;
+}
+
+/* }}} */
+
+/*
+ * Base Socket class
+ * ------------------------------------------------------------------
+ *
+ * This base class has operations that are common to all types of sockets but you usually instanciate
+ * a SocketTcp or SocketUdp
+ */
+
+/* {{{ Socket */
+
+/**
+ * @class Socket
+ * @brief Base socket class for socket operations.
+ *
+ * **Important:** When using non-blocking sockets, some considerations must be taken. See the implementation of the
+ * underlying protocol for more details.
+ *
+ * @see protocol::Tls
+ * @see protocol::Tcp
+ * @see protocol::Udp
+ */
+template <typename Address, typename Protocol>
+class Socket {
+private:
+	Protocol m_proto;
+	State m_state{State::Closed};
+	Action m_action{Action::None};
+	Condition m_condition{Condition::None};
+
+protected:
+	/**
+	 * The native handle.
+	 */
+	Handle m_handle{Invalid};
+
+public:
+	/**
+	 * Create a socket handle.
+	 *
+	 * This is the primary function and the only one that creates the socket handle, all other constructors
+	 * are just overloaded functions.
+	 *
+	 * @param domain the domain AF_*
+	 * @param type the type SOCK_*
+	 * @param protocol the protocol
+	 * @param iface the implementation
+	 * @throw net::Error on errors
+	 * @post state is set to Open
+	 * @post handle is not set to Invalid
+	 */
+	Socket(int domain, int type, int protocol, Protocol iface = {})
+		: m_proto(std::move(iface))
+	{
+#if !defined(SOCKET_NO_AUTO_INIT)
+		init();
+#endif
+		m_handle = ::socket(domain, type, protocol);
+
+		if (m_handle == Invalid) {
+			throw Error{Error::System, "socket"};
+		}
+
+		m_proto.create(*this);
+		m_state = State::Open;
+
+		assert(m_handle != Invalid);
+	}
+
+	/**
+	 * This tries to create a socket.
+	 *
+	 * Domain and type are determined by the Address and Protocol object.
+	 *
+	 * @param protocol the protocol
+	 * @param address which type of address
+	 * @throw net::Error on errors
+	 */
+	explicit inline Socket(Protocol protocol = {}, const Address &address = {})
+		: Socket{address.domain(), protocol.type(), 0, std::move(protocol)}
+	{
+	}
+
+	/**
+	 * Construct a socket with an already created descriptor.
+	 *
+	 * @param handle the native descriptor
+	 * @param state specify the socket state
+	 * @param protocol the type of socket implementation
+	 * @post action is set to None
+	 * @post condition is set to None
+	 */
+	explicit inline Socket(Handle handle, State state = State::Closed, Protocol protocol = {}) noexcept
+		: m_proto(std::move(protocol))
+		, m_state{state}
+		, m_handle{handle}
+	{
+		assert(m_action == Action::None);
+		assert(m_condition == Condition::None);
+	}
+
+	/**
+	 * Create an invalid socket. Can be used when you cannot instanciate the socket immediately.
+	 */
+	explicit inline Socket(std::nullptr_t) noexcept
+		: m_handle{Invalid}
+	{
+	}
+
+	/**
+	 * Copy constructor deleted.
+	 */
+	Socket(const Socket &) = delete;
+
+	/**
+	 * Transfer ownership from other to this.
+	 *
+	 * @param other the other socket
+	 */
+	inline Socket(Socket &&other) noexcept
+		: m_proto(std::move(other.m_proto))
+		, m_state{other.m_state}
+		, m_action{other.m_action}
+		, m_condition{other.m_condition}
+		, m_handle{other.m_handle}
+	{
+		/* Invalidate other */
+		other.m_handle = Invalid;
+		other.m_state = State::Closed;
+		other.m_action = Action::None;
+		other.m_condition = Condition::None;
+	}
+
+	/**
+	 * Default destructor.
+	 */
+	virtual ~Socket()
+	{
+		close();
+	}
+
+	/**
+	 * Access the implementation.
+	 *
+	 * @return the implementation
+	 * @warning use this function with care
+	 */
+	inline const Protocol &protocol() const noexcept
+	{
+		return m_proto;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the implementation
+	 */
+	inline Protocol &protocol() noexcept
+	{
+		return m_proto;
+	}
+
+	/**
+	 * Get the current socket state.
+	 *
+	 * @return the state
+	 */
+	inline State state() const noexcept
+	{
+		return m_state;
+	}
+
+	/**
+	 * Change the current socket state.
+	 *
+	 * @param state the new state
+	 * @warning only implementations should call this function
+	 */
+	inline void setState(State state) noexcept
+	{
+		m_state = state;
+	}
+
+	/**
+	 * Get the pending operation.
+	 *
+	 * @return the action to complete before continuing
+	 * @note usually only needed in non-blocking sockets
+	 */
+	inline Action action() const noexcept
+	{
+		return m_action;
+	}
+
+	/**
+	 * Change the pending operation.
+	 *
+	 * @param action the action
+	 * @warning you should not call this function yourself
+	 */
+	inline void setAction(Action action) noexcept
+	{
+		m_action = action;
+	}
+
+	/**
+	 * Get the condition to wait for.
+	 *
+	 * @return the condition
+	 */
+	inline Condition condition() const noexcept
+	{
+		return m_condition;
+	}
+
+	/**
+	 * Change the condition required.
+	 *
+	 * @param condition the condition
+	 * @warning you should not call this function yourself
+	 */
+	inline void setCondition(Condition condition) noexcept
+	{
+		m_condition = condition;
+	}
+
+	/**
+	 * Set an option for the socket. Wrapper of setsockopt(2).
+	 *
+	 * @param level the setting level
+	 * @param name the name
+	 * @param arg the value
+	 * @throw net::Error on errors
+	 */
+	template <typename Argument>
+	void set(int level, int name, const Argument &arg)
+	{
+		if (setsockopt(m_handle, level, name, (ConstArg)&arg, sizeof (arg)) == Failure) {
+			throw Error{Error::System, "set"};
+		}
+	}
+
+	/**
+	 * Object-oriented option setter.
+	 *
+	 * The object must have `set(Socket<Address, Protocol> &) const`.
+	 *
+	 * @param option the option
+	 * @throw net::Error on errors
+	 */
+	template <typename Option>
+	inline void set(const Option &option)
+	{
+		option.set(*this);
+	}
+
+	/**
+	 * Get an option for the socket. Wrapper of getsockopt(2).
+	 *
+	 * @param level the setting level
+	 * @param name the name
+	 * @throw net::Error on errors
+	 */
+	template <typename Argument>
+	Argument get(int level, int name)
+	{
+		Argument desired, result{};
+		socklen_t size = sizeof (result);
+
+		if (getsockopt(m_handle, level, name, (Arg)&desired, &size) == Failure) {
+			throw Error{Error::System, "get"};
+		}
+
+		std::memcpy(&result, &desired, size);
+
+		return result;
+	}
+
+	/**
+	 * Object-oriented option getter.
+	 *
+	 * The object must have `T get(Socket<Address, Protocol> &) const`, T can be any type and it is the value
+	 * returned from this function.
+	 *
+	 * @return the same value as get() in the option
+	 * @throw net::Error on errors
+	 */
+	template <typename Option>
+	inline auto get() -> decltype(std::declval<Option>().get(*this))
+	{
+		return Option{}.get(*this);
+	}
+
+	/**
+	 * Get the native handle.
+	 *
+	 * @return the handle
+	 * @warning Not portable
+	 */
+	inline Handle handle() const noexcept
+	{
+		return m_handle;
+	}
+
+	/**
+	 * Bind using a native address.
+	 *
+	 * @param address the address
+	 * @param length the size
+	 * @pre state must not be Bound
+	 * @throw net::Error on errors
+	 */
+	void bind(const sockaddr *address, socklen_t length)
+	{
+		assert(m_state != State::Bound);
+
+		if (::bind(m_handle, address, length) == Failure) {
+			throw Error{Error::System, "bind"};
+		}
+
+		m_state = State::Bound;
+	}
+
+	/**
+	 * Overload that takes an address.
+	 *
+	 * @param address the address
+	 * @throw net::Error on errors
+	 */
+	inline void bind(const Address &address)
+	{
+		bind(address.address(), address.length());
+	}
+
+	/**
+	 * Listen for pending connection.
+	 *
+	 * @param max the maximum number
+	 * @pre state must be Bound
+	 * @throw net::Error on errors
+	 */
+	inline void listen(int max = 128)
+	{
+		assert(m_state == State::Bound);
+
+		if (::listen(this->m_handle, max) == Failure) {
+			throw Error{Error::System, "listen"};
+		}
+	}
+
+	/**
+	 * Connect to the address.
+	 *
+	 * If connection cannot be established immediately, connect with no argument must be called again. See
+	 * the underlying protocol for more information.
+	 *
+	 * @pre state must be State::Open
+	 * @param address the address
+	 * @param length the the address length
+	 * @throw net::Error on errors
+	 * @post state is set to State::Connecting or State::Connected
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	void connect(const sockaddr *address, socklen_t length)
+	{
+		assert(m_state == State::Open);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		m_proto.connect(*this, address, length);
+
+		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
+		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * Effectively call connect(address.address(), address.length());
+	 *
+	 * @param address the address
+	 */
+	inline void connect(const Address &address)
+	{
+		connect(address.address(), address.length());
+	}
+
+	/**
+	 * Continue the connection, only required with non-blocking sockets.
+	 *
+	 * @pre state must be State::Connecting
+	 * @throw net::Error on errors
+	 */
+	void connect()
+	{
+		assert(m_state == State::Connecting);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		m_proto.connect(*this);
+
+		assert((m_state == State::Connected  && m_action == Action::None    && m_condition == Condition::None) ||
+		       (m_state == State::Connecting && m_action == Action::Connect && m_condition != Condition::None));
+	}
+
+	/**
+	 * Accept a new client. If there are no pending connection, throws an error.
+	 *
+	 * If the client cannot be accepted immediately, the client is returned and accept with no arguments
+	 * must be called on it. See the underlying protocol for more information.
+	 *
+	 * @pre state must be State::Bound
+	 * @param info the address where to store client's information (optional)
+	 * @return the new socket
+	 * @throw Error on errors
+	 * @post returned client's state is set to State::Accepting or State::Accepted
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	Socket<Address, Protocol> accept(Address *info)
+	{
+		assert(m_state == State::Bound);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		sockaddr_storage storage;
+		socklen_t length = sizeof (storage);
+
+		Socket<Address, Protocol> sc = m_proto.accept(*this, reinterpret_cast<sockaddr *>(&storage), &length);
+
+		if (info) {
+			*info = Address{&storage, length};
+		}
+
+		/* Master do not change */
+		assert(m_state == State::Bound);
+		assert(m_action == Action::None);
+		assert(m_condition == Condition::None);
+
+		/* Client */
+		assert(
+			(sc.state() == State::Accepting && sc.action() == Action::Accept && sc.condition() != Condition::None) ||
+			(sc.state() == State::Accepted  && sc.action() == Action::None   && sc.condition() == Condition::None)
+		);
+
+		return sc;
+	}
+
+	/**
+	 * Continue the accept process on this client. This function must be called only when the socket is
+	 * ready to be readable or writable! (see condition).
+	 *
+	 * @pre state must be State::Accepting
+	 * @throw Error on errors
+	 * @post if connection is complete, state is changed to State::Accepted, action and condition are unset
+	 * @post if connection is still in progress, condition is set
+	 */
+	void accept()
+	{
+		assert(m_state == State::Accepting);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		m_proto.accept(*this);
+
+		assert(
+			(m_state == State::Accepting && m_action == Action::Accept && m_condition != Condition::None) ||
+			(m_state == State::Accepted  && m_action == Action::None   && m_condition == Condition::None)
+		);
+	}
+
+	/**
+	 * Get the local name. This is a wrapper of getsockname().
+	 *
+	 * @return the address
+	 * @throw Error on failures
+	 * @pre state() must not be State::Closed
+	 */
+	Address address() const
+	{
+		assert(m_state != State::Closed);
+
+		sockaddr_storage ss;
+		socklen_t length = sizeof (sockaddr_storage);
+
+		if (::getsockname(m_handle, (sockaddr *)&ss, &length) == Failure) {
+			throw Error{Error::System, "getsockname"};
+		}
+
+		return Address(&ss, length);
+	}
+
+	/**
+	 * Receive some data.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * If action is set to Action::None and result is set to 0, disconnection occured.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @pre action must not be Action::Send
+	 * @return the number of bytes received or 0
+	 * @throw Error on error
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	unsigned recv(void *data, unsigned length)
+	{
+		assert(m_action != Action::Send);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		unsigned nbread = m_proto.recv(*this, data, length);
+
+		return nbread;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param count the number of bytes to receive
+	 * @return the string
+	 * @throw Error on error
+	 */
+	inline std::string recv(unsigned count)
+	{
+		std::string result;
+
+		result.resize(count);
+		auto n = recv(const_cast<char *>(result.data()), count);
+		result.resize(n);
+
+		return result;
+	}
+
+	/**
+	 * Send some data.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * @param data the data buffer
+	 * @param length the buffer length
+	 * @return the number of bytes sent or 0
+	 * @pre action() must not be Flag::Receive
+	 * @throw Error on error
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	unsigned send(const void *data, unsigned length)
+	{
+		assert(m_action != Action::Receive);
+
+		m_action = Action::None;
+		m_condition = Condition::None;
+
+		unsigned nbsent = m_proto.send(*this, data, length);
+
+		assert((m_action == Action::None && m_condition == Condition::None) ||
+		       (m_action == Action::Send && m_condition != Condition::None));
+
+		return nbsent;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the string to send
+	 * @return the number of bytes sent
+	 * @throw Error on error
+	 */
+	inline unsigned send(const std::string &data)
+	{
+		return send(data.c_str(), data.size());
+	}
+
+	/**
+	 * Send data to an end point.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the client address
+	 * @param addrlen the address length
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	inline unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
+	{
+		return m_proto.sendto(*this, data, length, address, addrlen);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the destination
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 */
+	inline unsigned sendto(const void *data, unsigned length, const Address &address)
+	{
+		return sendto(data, length, address.address(), address.length());
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the data
+	 * @param address the address
+	 * @return the number of bytes sent
+	 * @throw net:;Error on errors
+	 */
+	inline unsigned sendto(const std::string &data, const Address &address)
+	{
+		return sendto(data.c_str(), data.length(), address);
+	}
+
+	/**
+	 * Receive data from an end point.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param address the address destination
+	 * @param addrlen the address length (in/out)
+	 * @return the number of bytes received
+	 * @throw net::Error on errors
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	inline unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
+	{
+		return m_proto.recvfrom(*this, data, length, address, addrlen);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param info the address destination
+	 * @return the number of bytes received
+	 * @throw net::Error on errors
+	 */
+	inline unsigned recvfrom(void *data, unsigned length, Address *info = nullptr)
+	{
+		sockaddr_storage storage;
+		socklen_t addrlen = sizeof (sockaddr_storage);
+
+		auto n = recvfrom(data, length, reinterpret_cast<sockaddr *>(&storage), &addrlen);
+
+		if (info && n != 0) {
+			*info = Address{&storage, addrlen};
+		}
+
+		return n;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param count the maximum number of bytes to receive
+	 * @param info the client information
+	 * @return the string
+	 * @throw net::Error on errors
+	 */
+	std::string recvfrom(unsigned count, Address *info = nullptr)
+	{
+		std::string result;
+
+		result.resize(count);
+		auto n = recvfrom(const_cast<char *>(result.data()), count, info);
+		result.resize(n);
+
+		return result;
+	}
+
+	/**
+	 * Close the socket.
+	 *
+	 * Automatically called from the destructor.
+	 */
+	void close()
+	{
+		if (m_handle != Invalid) {
+#if defined(_WIN32)
+			::closesocket(m_handle);
+#else
+			::close(m_handle);
+#endif
+			m_handle = Invalid;
+		}
+
+		m_state = State::Closed;
+		m_action = Action::None;
+		m_condition = Condition::None;
+	}
+
+	/**
+	 * Assignment operator forbidden.
+	 *
+	 * @return *this
+	 */
+	Socket &operator=(const Socket &) = delete;
+
+	/**
+	 * Transfer ownership from other to this. The other socket is left
+	 * invalid and will not be closed.
+	 *
+	 * @param other the other socket
+	 * @return this
+	 */
+	Socket &operator=(Socket &&other) noexcept
+	{
+		m_handle = other.m_handle;
+		m_proto = std::move(other.m_proto);
+		m_state = other.m_state;
+		m_action = other.m_action;
+		m_condition = other.m_condition;
+
+		/* Invalidate other */
+		other.m_handle = Invalid;
+		other.m_state = State::Closed;
+		other.m_action = Action::None;
+		other.m_condition = Condition::None;
+
+		return *this;
+	}
+};
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if they equals
+ */
+template <typename Address, typename Protocol>
+bool operator==(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() == s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if they are different
+ */
+template <typename Address, typename Protocol>
+bool operator!=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() != s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 < s2
+ */
+template <typename Address, typename Protocol>
+bool operator<(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() < s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 > s2
+ */
+template <typename Address, typename Protocol>
+bool operator>(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() > s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 <= s2
+ */
+template <typename Address, typename Protocol>
+bool operator<=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() <= s2.handle();
+}
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 >= s2
+ */
+template <typename Address, typename Protocol>
+bool operator>=(const Socket<Address, Protocol> &s1, const Socket<Address, Protocol> &s2)
+{
+	return s1.handle() >= s2.handle();
+}
+
+/* }}} */
+
+/*
+ * Predefined options
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Options */
+
+/**
+ * Namespace of predefined options.
+ */
+namespace option {
+
+/*
+ * Options for socket
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Options for socket */
+
+/**
+ * @class SockBlockMode
+ * @brief Set or get the blocking-mode for a socket.
+ * @warning On Windows, it's not possible to check if the socket is blocking or not.
+ */
+class SockBlockMode {
+public:
+	/**
+	 * Set to false if you want non-blocking socket.
+	 */
+	bool value{false};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void set(Socket<Address, Protocol> &sc) const
+	{
+#if defined(O_NONBLOCK) && !defined(_WIN32)
+		int flags;
+
+		if ((flags = fcntl(sc.handle(), F_GETFL, 0)) < 0) {
+			flags = 0;
+		}
+
+		if (value) {
+			flags &= ~(O_NONBLOCK);
+		} else {
+			flags |= O_NONBLOCK;
+		}
+
+		if (fcntl(sc.handle(), F_SETFL, flags) < 0) {
+			throw Error{Error::System, "fcntl"};
+		}
+#else
+		unsigned long flags = (value) ? 0 : 1;
+
+		if (ioctlsocket(sc.handle(), FIONBIO, &flags) == Failure) {
+			throw Error{Error::System, "fcntl"};
+		}
+#endif
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	bool get(Socket<Address, Protocol> &sc) const
+	{
+#if defined(O_NONBLOCK) && !defined(_WIN32)
+		int flags = fcntl(sc.handle(), F_GETFL, 0);
+
+		if (flags < 0) {
+			throw Error{Error::System, "fcntl"};
+		}
+
+		return !(flags & O_NONBLOCK);
+#else
+		throw Error{Error::Other, "get", "Windows API cannot let you get the blocking status of a socket"};
+#endif
+	}
+};
+
+/**
+ * @class SockReuseAddress
+ * @brief Reuse address, must be used before calling Socket::bind
+ */
+class SockReuseAddress {
+public:
+	/**
+	 * Set to true if you want to set the SOL_SOCKET/SO_REUSEADDR option.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_REUSEADDR, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(SOL_SOCKET, SO_REUSEADDR));
+	}
+};
+
+/**
+ * @class SockSendBuffer
+ * @brief Set or get the output buffer.
+ */
+class SockSendBuffer {
+public:
+	/**
+	 * Set to the buffer size.
+	 */
+	int value{2048};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_SNDBUF, value);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline int get(Socket<Address, Protocol> &sc) const
+	{
+		return sc.template get<int>(SOL_SOCKET, SO_SNDBUF);
+	}
+};
+
+/**
+ * @class SockReceiveBuffer
+ * @brief Set or get the input buffer.
+ */
+class SockReceiveBuffer {
+public:
+	/**
+	 * Set to the buffer size.
+	 */
+	int value{2048};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_RCVBUF, value);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline int get(Socket<Address, Protocol> &sc) const
+	{
+		return sc.template get<int>(SOL_SOCKET, SO_RCVBUF);
+	}
+};
+
+/* }}} */
+
+/**
+ * @class TcpNoDelay
+ * @brief Set this option if you want to disable nagle's algorithm.
+ */
+class TcpNoDelay {
+public:
+	/**
+	 * Set to true to set TCP_NODELAY option.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(IPPROTO_TCP, TCP_NODELAY, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(IPPROTO_TCP, TCP_NODELAY));
+	}
+};
+
+/**
+ * @class Ipv6Only
+ * @brief Control IPPROTO_IPV6/IPV6_V6ONLY
+ *
+ * Note: some systems may or not set this option by default so it's a good idea to set it in any case to either
+ * false or true if portability is a concern.
+ */
+class Ipv6Only {
+public:
+	/**
+	 * Set this to use only IPv6.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(IPPROTO_IPV6, IPV6_V6ONLY, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(IPPROTO_IPV6, IPV6_V6ONLY));
+	}
+};
+
+} // !option
+
+/* }}} */
+
+/*
+ * Predefined addressed to be used
+ * ------------------------------------------------------------------
+ *
+ * - Ip,
+ * - Local.
+ */
+
+/* {{{ Addresses */
+
+/**
+ * Set of predefined addresses.
+ */
+namespace address {
+
+/**
+ * @class Ip
+ * @brief Base class for IPv6 and IPv4, you can use it if you don't know in advance if you'll use IPv6 or IPv4.
+ */
+class Ip {
+public:
+	/**
+	 * @enum Type
+	 * @brief Type of ip address.
+	 */
+	enum Type {
+		v4 = AF_INET,		//!< AF_INET
+		v6 = AF_INET6		//!< AF_INET6
+	};
+
+private:
+	/*
+	 * Default domain when using default constructors.
+	 *
+	 * Note: AF_INET or AF_INET6, not
+	 */
+	static int m_default;
+
+	union {
+		sockaddr_in m_sin;
+		sockaddr_in6 m_sin6;
+	};
+
+	socklen_t m_length{0};
+	int m_domain{AF_INET};
+
+public:
+	/**
+	 * Set the default domain to use when using default Ip constructor. By default, AF_INET is used.
+	 *
+	 * @pre domain must be Type::v4 or Type::v6
+	 */
+	static inline void setDefault(Type domain) noexcept
+	{
+		assert(domain == Type::v4 || domain == Type::v6);
+
+		m_default = static_cast<int>(domain);
+	}
+
+	/**
+	 * Construct using the default domain.
+	 */
+	inline Ip() noexcept
+		: Ip(static_cast<Type>(m_default))
+	{
+	}
+
+	/**
+	 * Default initialize the Ip domain.
+	 *
+	 * @pre domain must be AF_INET or AF_INET6 only
+	 * @param domain the domain (AF_INET or AF_INET6)
+	 */
+	Ip(Type domain) noexcept;
+
+	/**
+	 * Construct an address suitable for bind() or connect().
+	 *
+	 * @pre domain must be Type::v4 or Type::v6
+	 * @param domain the domain (AF_INET or AF_INET6)
+	 * @param host the host (* for any)
+	 * @param port the port number
+	 * @throw Error on errors
+	 */
+	Ip(const std::string &host, int port, Type domain = v4);
+
+	/**
+	 * Construct an address from a storage.
+	 *
+	 * @pre storage's domain must be AF_INET or AF_INET6 only
+	 * @param ss the storage
+	 * @param length the length
+	 */
+	Ip(const sockaddr_storage *ss, socklen_t length) noexcept;
+
+	/**
+	 * Get the domain (AF_INET or AF_INET6).
+	 *
+	 * @return the domain
+	 */
+	inline int domain() const noexcept
+	{
+		return m_domain;
+	}
+
+	/**
+	 * Return the underlying address, either sockaddr_in6 or sockaddr_in.
+	 *
+	 * @return the address
+	 */
+	inline const sockaddr *address() const noexcept
+	{
+		if (m_domain == AF_INET6) {
+			return reinterpret_cast<const sockaddr *>(&m_sin6);
+		}
+
+		return reinterpret_cast<const sockaddr *>(&m_sin);
+	}
+
+	/**
+	 * Return the underlying address length.
+	 *
+	 * @return the length
+	 */
+	inline socklen_t length() const noexcept
+	{
+		return m_length;
+	}
+
+	/**
+	 * Get the port.
+	 *
+	 * @return the port
+	 */
+	inline int port() const noexcept
+	{
+		if (m_domain == AF_INET6) {
+			return ntohs(m_sin6.sin6_port);
+		}
+
+		return ntohs(m_sin.sin_port);
+	}
+};
+
+#if !defined(_WIN32)
+
+/**
+ * @class Local
+ * @brief unix family sockets
+ *
+ * Create an address to a specific path. Only available on Unix.
+ */
+class Local {
+private:
+	sockaddr_un m_sun;
+	std::string m_path;
+
+public:
+	/**
+	 * Get the domain AF_LOCAL.
+	 *
+	 * @return AF_LOCAL
+	 */
+	inline int domain() const noexcept
+	{
+		return AF_LOCAL;
+	}
+
+	/**
+	 * Default constructor.
+	 */
+	Local() noexcept;
+
+	/**
+	 * Construct an address to a path.
+	 *
+	 * @param path the path
+	 * @param rm remove the file before (default: false)
+	 */
+	Local(std::string path, bool rm = false) noexcept;
+
+	/**
+	 * Construct an unix address from a storage address.
+	 *
+	 * @pre storage's domain must be AF_LOCAL
+	 * @param ss the storage
+	 * @param length the length
+	 */
+	Local(const sockaddr_storage *ss, socklen_t length) noexcept;
+
+	/**
+	 * Get the sockaddr_un.
+	 *
+	 * @return the address
+	 */
+	inline const sockaddr *address() const noexcept
+	{
+		return reinterpret_cast<const sockaddr *>(&m_sun);
+	}
+
+	/**
+	 * Get the address length.
+	 *
+	 * @return the length
+	 */
+	inline socklen_t length() const noexcept
+	{
+#if defined(SOCKET_HAVE_SUN_LEN)
+		return SUN_LEN(&m_sun);
+#else
+		return sizeof (m_sun);
+#endif
+	}
+};
+
+#endif // !_WIN32
+
+} // !address
+
+/* }}} */
+
+/*
+ * Predefined protocols
+ * ------------------------------------------------------------------
+ *
+ * - Tcp, for standard stream connections,
+ * - Udp, for standard datagram connections,
+ * - Tls, for secure stream connections.
+ */
+
+/* {{{ Protocols */
+
+/**
+ * Set of predefined protocols.
+ */
+namespace protocol {
+
+/* {{{ Tcp */
+
+/**
+ * @class Tcp
+ * @brief Clear TCP implementation.
+ *
+ * This is the basic TCP protocol that implements recv, send, connect and accept as wrappers of the usual
+ * C functions.
+ */
+class Tcp {
+public:
+	/**
+	 * Socket type.
+	 *
+	 * @return SOCK_STREAM
+	 */
+	inline int type() const noexcept
+	{
+		return SOCK_STREAM;
+	}
+
+	/**
+	 * Do nothing.
+	 *
+	 * This function is just present for compatibility, it should never be called.
+	 */
+	template <typename Address>
+	inline void create(Socket<Address, Tcp> &) const noexcept
+	{
+		/* No-op */
+	}
+
+	/**
+	 * Standard connect.
+	 *
+	 * If the socket is marked non-blocking and the connection cannot be established immediately, then the
+	 * following is true:
+	 *
+	 * - state is set to State::Connecting,
+	 * - action is set to Action::Connect,
+	 * - condition is set to Condition::Writable.
+	 *
+	 * Then the user must wait until the socket is writable and call connect() with 0 arguments.
+	 *
+	 * If the socket is blocking, this function blocks until the connection is complete or an error occurs, in
+	 * that case state is either set to State::Connected or State::Disconnected but action and condition are
+	 * not set.
+	 *
+	 * @param sc the socket
+	 * @param address the address
+	 * @param length the length
+	 * @throw net::Error on errors
+	 * @note Wrapper of connect(2)
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
+	{
+		if (::connect(sc.handle(), address, length) == Failure) {
+			/*
+			 * Determine if the error comes from a non-blocking connect that cannot be
+			 * accomplished yet.
+			 */
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				sc.setState(State::Connecting);
+				sc.setAction(Action::Connect);
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "connect", error};
+			}
+#else
+			if (errno == EINPROGRESS) {
+				sc.setState(State::Connecting);
+				sc.setAction(Action::Connect);
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "connect"};
+			}
+#endif
+		} else {
+			sc.setState(State::Connected);
+		}
+	}
+
+	/**
+	 * Continue the connection. This function must only be called when the socket is ready for writing,
+	 * the user is responsible of waiting for that condition.
+	 *
+	 * This function check for SOL_SOCKET/SO_ERROR status.
+	 *
+	 * If the connection is complete, status is set to State::Connected, otherwise it is set to
+	 * State::Disconnected. In both cases, action and condition are not set.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc)
+	{
+		int error = sc.template get<int>(SOL_SOCKET, SO_ERROR);
+
+		if (error == Failure) {
+			sc.setState(State::Disconnected);
+			throw Error{Error::System, "connect", error};
+		}
+
+		sc.setState(State::Connected);
+	}
+
+	/**
+	 * Accept a clear client.
+	 *
+	 * If the socket is marked non-blocking and there are no pending connection, this function throws an
+	 * error. The user must wait that the socket is readable before calling this function.
+	 *
+	 * If the socket is blocking, this function blocks until a new client is connected or throws an error on
+	 * errors.
+	 *
+	 * If the socket is correctly returned, its state is set to State::Accepted and its action and condition
+	 * are not set.
+	 *
+	 * In any case, action and condition of this socket are not set.
+	 *
+	 * @param sc the socket
+	 * @param address the address destination
+	 * @param length the address length
+	 * @return the socket
+	 * @throw net::Error on errors
+	 * @note Wrapper of accept(2)
+	 */
+	template <typename Address, typename Protocol>
+	Socket<Address, Protocol> accept(Socket<Address, Protocol> &sc, sockaddr *address, socklen_t *length)
+	{
+		Handle handle = ::accept(sc.handle(), address, length);
+
+		if (handle == Invalid) {
+			throw Error{Error::System, "accept"};
+		}
+
+		return Socket<Address, Protocol>{handle, State::Accepted};
+	}
+
+	/**
+	 * Continue accept.
+	 *
+	 * This function is just present for compatibility, it should never be called.
+	 */
+	template <typename Address, typename Protocol>
+	inline void accept(Socket<Address, Protocol> &) const noexcept
+	{
+		/* no-op */
+	}
+
+	/**
+	 * Receive data.
+	 *
+	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
+	 * Condition::Readable. If 0 is returned and condition is not set, then the state is set to
+	 * State::Disconnected.
+	 *
+	 * If the socket is blocking, this function blocks until some data is available or if an error occurs.
+	 *
+	 * In any case, action is never set.
+	 *
+	 * @param sc the socket
+	 * @param data the destination
+	 * @param length the destination length
+	 * @return the number of bytes read
+	 * @throw Error on errors
+	 * @note Wrapper of recv(2)
+	 */
+	template <typename Address>
+	unsigned recv(Socket<Address, Tcp> &sc, void *data, unsigned length)
+	{
+		int nbread = ::recv(sc.handle(), (Arg)data, length, 0);
+
+		if (nbread == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "recv", error};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				sc.setCondition(Condition::Readable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "recv"};
+			}
+#endif
+		} else if (nbread == 0) {
+			sc.setState(State::Disconnected);
+		}
+
+		return static_cast<unsigned>(nbread);
+	}
+
+	/**
+	 * Send some data.
+	 *
+	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
+	 * Condition::Writable.
+	 *
+	 * If the socket is blocking, this function blocks until the data has been sent.
+	 *
+	 * On any other errors, this function throw net::Error.
+	 *
+	 * @param sc the socket
+	 * @param data the buffer to send
+	 * @param length the buffer length
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 * @note Wrapper of send(2)
+	 */
+	template <typename Address>
+	unsigned send(Socket<Address, Tcp> &sc, const void *data, unsigned length)
+	{
+		int nbsent = ::send(sc.handle(), (ConstArg)data, length, 0);
+
+		if (nbsent == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "send", error};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "send"};
+			}
+#endif
+		}
+
+		return static_cast<unsigned>(nbsent);
+	}
+};
+
+/* }}} */
+
+/* {{{ Udp */
+
+/**
+ * @class Udp
+ * @brief Clear UDP type.
+ *
+ * This class is the basic implementation of UDP sockets.
+ */
+class Udp {
+public:
+	/**
+	 * Socket type.
+	 *
+	 * @return SOCK_DGRAM
+	 */
+	inline int type() const noexcept
+	{
+		return SOCK_DGRAM;
+	}
+
+	/**
+	 * Do nothing.
+	 */
+	template <typename Address>
+	inline void create(Socket<Address, Udp> &) noexcept
+	{
+		/* No-op */
+	}
+
+	/**
+	 * Receive data from an end point.
+	 *
+	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
+	 * Condition::Readable.
+	 *
+	 * If the socket is blocking, this functions blocks until some data is available or if an error occurs.
+	 *
+	 * @param sc the socket
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param address the address
+	 * @param addrlen the initial address length
+	 * @return the number of bytes received
+	 * @throw Error on error
+	 */
+	template <typename Address>
+	unsigned recvfrom(Socket<Address, Udp> &sc, void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
+	{
+		int nbread;
+
+		nbread = ::recvfrom(sc.handle(), (Arg)data, length, 0, address, addrlen);
+
+		if (nbread == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				throw Error{Error::System, "recvfrom"};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				throw Error{Error::System, "recvfrom"};
+			}
+#endif
+		}
+
+		return static_cast<unsigned>(nbread);
+	}
+
+	/**
+	 * Send data to an end point.
+	 *
+	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
+	 * Condition::Writable.
+	 *
+	 * If the socket is blocking, this functions blocks until the data has been sent.
+	 *
+	 * @param sc the socket
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the client address
+	 * @param addrlen the adderss length
+	 * @return the number of bytes sent
+	 * @throw Error on error
+	 */
+	template <typename Address>
+	unsigned sendto(Socket<Address, Udp> &sc, const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
+	{
+		int nbsent;
+
+		nbsent = ::sendto(sc.handle(), (ConstArg)data, length, 0, address, addrlen);
+		if (nbsent == Failure) {
+#if defined(_WIN32)
+			int error = WSAGetLastError();
+
+			if (error == WSAEWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				throw Error{Error::System, "sendto", error};
+			}
+#else
+			if (errno == EAGAIN || errno == EWOULDBLOCK) {
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				throw Error{Error::System, "sendto"};
+			}
+#endif
+		}
+
+		return static_cast<unsigned>(nbsent);
+	}
+};
+
+/* }}} */
+
+/* {{{ Tls */
+
+#if !defined(SOCKET_NO_SSL)
+
+/**
+ * @class Tls
+ * @brief OpenSSL secure layer for TCP.
+ *
+ * **Note:** This protocol is much more difficult to use with non-blocking sockets, if some operations would block, the
+ * user is responsible of calling the function again by waiting for the appropriate condition. See the functions for
+ * more details.
+ *
+ * @see Tls::accept
+ * @see Tls::connect
+ * @see Tls::recv
+ * @see Tls::send
+ */
+class Tls : private Tcp {
+private:
+	using Context = std::shared_ptr<SSL_CTX>;
+	using Ssl = std::unique_ptr<SSL, void (*)(SSL *)>;
+
+	/* OpenSSL objects */
+	Context m_context;
+	Ssl m_ssl{nullptr, nullptr};
+
+	/* Status */
+	bool m_tcpconnected{false};
+
+	/*
+	 * User definable parameters
+	 */
+	ssl::Method m_method{ssl::Tlsv1};
+	std::string m_key;
+	std::string m_certificate;
+	bool m_verify{false};
+
+	/*
+	 * Construct with a context and ssl, for Tls::accept.
+	 */
+	Tls(Context context, Ssl ssl)
+		: m_context{std::move(context)}
+		, m_ssl{std::move(ssl)}
+	{
+	}
+
+	/*
+	 * Get the OpenSSL error message.
+	 */
+	inline std::string error(int error)
+	{
+		auto msg = ERR_reason_error_string(error);
+
+		return msg == nullptr ? "" : msg;
+	}
+
+	/*
+	 * Update the states after an uncompleted operation.
+	 */
+	template <typename Address, typename Protocol>
+	inline void updateStates(Socket<Address, Protocol> &sc, State state, Action action, int code)
+	{
+		assert(code == SSL_ERROR_WANT_READ || code == SSL_ERROR_WANT_WRITE);
+
+		sc.setState(state);
+		sc.setAction(action);
+
+		if (code == SSL_ERROR_WANT_READ) {
+			sc.setCondition(Condition::Readable);
+		} else {
+			sc.setCondition(Condition::Writable);
+		}
+	}
+
+	/*
+	 * Continue the connect operation.
+	 */
+	template <typename Address, typename Protocol>
+	void processConnect(Socket<Address, Protocol> &sc)
+	{
+		int ret = SSL_connect(m_ssl.get());
+
+		if (ret <= 0) {
+			int no = SSL_get_error(m_ssl.get(), ret);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				updateStates(sc, State::Connecting, Action::Connect, no);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error{Error::System, "connect", error(no)};
+			}
+		} else {
+			sc.setState(State::Connected);
+		}
+	}
+
+	/*
+	 * Continue accept.
+	 */
+	template <typename Address, typename Protocol>
+	void processAccept(Socket<Address, Protocol> &sc)
+	{
+		int ret = SSL_accept(m_ssl.get());
+
+		if (ret <= 0) {
+			int no = SSL_get_error(m_ssl.get(), ret);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				updateStates(sc, State::Accepting, Action::Accept, no);
+			} else {
+				sc.setState(State::Disconnected);
+				throw Error(Error::System, "accept", error(no));
+			}
+		} else {
+			sc.setState(State::Accepted);
+		}
+	}
+
+public:
+	/**
+	 * @copydoc Tcp::type
+	 */
+	inline int type() const noexcept
+	{
+		return SOCK_STREAM;
+	}
+
+	/**
+	 * Empty TLS constructor.
+	 */
+	Tls()
+	{
+#if !defined(SOCKET_NO_SSL_AUTO_INIT)
+		net::ssl::init();
+#endif
+	}
+
+	/**
+	 * Set the method.
+	 *
+	 * @param method the method
+	 * @pre the socket must not be already created
+	 */
+	inline void setMethod(ssl::Method method) noexcept
+	{
+		assert(!m_context);
+		assert(!m_ssl);
+
+		m_method = method;
+	}
+
+	/**
+	 * Use the specified private key file.
+	 *
+	 * @param file the path to the private key
+	 */
+	inline void setPrivateKey(std::string file) noexcept
+	{
+		m_key = std::move(file);
+	}
+
+	/**
+	 * Use the specified certificate file.
+	 *
+	 * @param file the path to the file
+	 */
+	inline void setCertificate(std::string file) noexcept
+	{
+		m_certificate = std::move(file);
+	}
+
+	/**
+	 * Set to true if we must verify the certificate and private key.
+	 *
+	 * @param verify the mode
+	 */
+	inline void setVerify(bool verify = true) noexcept
+	{
+		m_verify = verify;
+	}
+
+	/**
+	 * Initialize the SSL objects after have created.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	inline void create(Socket<Address, Tls> &sc)
+	{
+		auto method = (m_method == ssl::Tlsv1) ? TLSv1_method() : SSLv23_method();
+
+		m_context = {SSL_CTX_new(method), SSL_CTX_free};
+		m_ssl = {SSL_new(m_context.get()), SSL_free};
+
+		SSL_set_fd(m_ssl.get(), sc.handle());
+
+		/* Load certificates */
+		if (m_certificate.size() > 0) {
+			SSL_CTX_use_certificate_file(m_context.get(), m_certificate.c_str(), SSL_FILETYPE_PEM);
+		}
+		if (m_key.size() > 0) {
+			SSL_CTX_use_PrivateKey_file(m_context.get(), m_key.c_str(), SSL_FILETYPE_PEM);
+		}
+		if (m_verify && !SSL_CTX_check_private_key(m_context.get())) {
+			throw Error{Error::System, "(openssl)", "unable to verify key"};
+		}
+	}
+
+	/**
+	 * Connect to a secure host.
+	 *
+	 * If the socket is marked non-blocking and the connection cannot be established yet, then the state is set
+	 * to State::Connecting, the condition is set to Condition::Readable or Condition::Writable, the user must
+	 * wait for the appropriate condition before calling the overload connect which takes 0 argument.
+	 *
+	 * If the socket is blocking, this functions blocks until the connection is complete.
+	 *
+	 * If the connection was completed correctly the state is set to State::Connected.
+	 *
+	 * @param sc the socket
+	 * @param address the address
+	 * @param length the address length
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc, const sockaddr *address, socklen_t length)
+	{
+		/* 1. Connect using raw TCP */
+		Tcp::connect(sc, address, length);
+
+		/* 2. If the connection is complete (e.g. non-blocking), try handshake */
+		if (sc.state() == State::Connected) {
+			m_tcpconnected = true;
+			processConnect(sc);
+		}
+	}
+
+	/**
+	 * Continue the connection.
+	 *
+	 * This function must be called when the socket is ready for reading or writing (check with Socket::condition),
+	 * the state may change exactly like the initial connect call.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	void connect(Socket<Address, Protocol> &sc)
+	{
+		/* 1. Be sure to complete standard connect before */
+		if (!m_tcpconnected) {
+			Tcp::connect(sc);
+			m_tcpconnected = sc.state() == State::Connected;
+		}
+
+		if (m_tcpconnected) {
+			processConnect(sc);
+		}
+	}
+
+	/**
+	 * Accept a secure client.
+	 *
+	 * Because SSL needs several round-trips, if the socket is marked non-blocking and the connection is not
+	 * completed yet, a new socket is returned but with the State::Accepting state. Its condition is set to
+	 * Condition::Readable or Condition::Writable, the user is responsible of calling accept overload which takes
+	 * 0 arguments on the returned socket when the condition is met.
+	 *
+	 * If the socket is blocking, this function blocks until the client is accepted and returned.
+	 *
+	 * If the client is accepted correctly, its state is set to State::Accepted. This instance does not change.
+	 *
+	 * @param sc the socket
+	 * @param address the address destination
+	 * @param length the address length
+	 * @return the client
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	Socket<Address, Tls> accept(Socket<Address, Tls> &sc, sockaddr *address, socklen_t *length)
+	{
+		Socket<Address, Tls> client = Tcp::accept(sc, address, length);
+		Tls &proto = client.protocol();
+
+		/* 1. Share the context */
+		proto.m_context = m_context;
+
+		/* 2. Create new SSL instance */
+		proto.m_ssl = Ssl{SSL_new(m_context.get()), SSL_free};
+		SSL_set_fd(proto.m_ssl.get(), client.handle());
+
+		/* 3. Try accept process on the **new** client */
+		proto.processAccept(client);
+
+		return client;
+	}
+
+	/**
+	 * Continue accept.
+	 *
+	 * This function must be called on the client that is being accepted.
+	 *
+	 * Like accept or connect, user is responsible of calling this function until the connection is complete.
+	 *
+	 * @param sc the socket
+	 * @throw net::Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void accept(Socket<Address, Protocol> &sc)
+	{
+		processAccept(sc);
+	}
+
+	/**
+	 * Receive some secure data.
+	 *
+	 * If the socket is marked non-blocking, 0 is returned if no data is available yet or if the connection
+	 * needs renegociation. If renegociation is required case, the action is set to Action::Receive and condition
+	 * is set to Condition::Readable or Condition::Writable. The user must wait that the condition is met and
+	 * call this function again.
+	 *
+	 * @param sc the socket
+	 * @param data the destination
+	 * @param len the buffer length
+	 * @return the number of bytes read
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	unsigned recv(Socket<Address, Tls> &sc, void *data, unsigned len)
+	{
+		auto nbread = SSL_read(m_ssl.get(), data, len);
+
+		if (nbread <= 0) {
+			auto no = SSL_get_error(m_ssl.get(), nbread);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				nbread = 0;
+				updateStates(sc, sc.state(), Action::Receive, no);
+			} else {
+				throw Error{Error::System, "recv", error(no)};
+			}
+		}
+
+		return nbread;
+	}
+
+	/**
+	 * Send some data.
+	 *
+	 * Like recv, if the socket is marked non-blocking and no data can be sent or a negociation is required,
+	 * condition and action are set. See receive for more details
+	 *
+	 * @param sc the socket
+	 * @param data the data to send
+	 * @param len the buffer length
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
+	 */
+	template <typename Address>
+	unsigned send(Socket<Address, Tls> &sc, const void *data, unsigned len)
+	{
+		auto nbsent = SSL_write(m_ssl.get(), data, len);
+
+		if (nbsent <= 0) {
+			auto no = SSL_get_error(m_ssl.get(), nbsent);
+
+			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
+				nbsent = 0;
+				updateStates(sc, sc.state(), Action::Send, no);
+			} else {
+				throw Error{Error::System, "send", error(no)};
+			}
+		}
+
+		return nbsent;
+	}
+};
+
+#endif // !SOCKET_NO_SSL
+
+/* }}} */
+
+} // !protocol
+
+/* }}} */
+
+/*
+ * Convenient helpers
+ * ------------------------------------------------------------------
+ *
+ * - SocketTcp<Address>, for TCP sockets,
+ * - SocketUdp<Address>, for UDP sockets,
+ * - SocketTls<Address>, for secure TCP sockets.
+ */
+
+/* {{{ Helpers */
+
+/**
+ * Helper to create TCP sockets.
+ */
+template <typename Address>
+using SocketTcp = Socket<Address, protocol::Tcp>;
+
+/**
+ * Helper to create TCP/IP sockets.
+ */
+using SocketTcpIp = Socket<address::Ip, protocol::Tcp>;
+
+#if !defined(_WIN32)
+
+/**
+ * Helper to create TCP/Local sockets.
+ */
+using SocketTcpLocal = Socket<address::Local, protocol::Tcp>;
+
+#endif
+
+/**
+ * Helper to create UDP sockets.
+ */
+template <typename Address>
+using SocketUdp = Socket<Address, protocol::Udp>;
+
+/**
+ * Helper to create UDP/IP sockets.
+ */
+using SocketUdpIp = Socket<address::Ip, protocol::Udp>;
+
+#if !defined(SOCKET_NO_SSL)
+
+/**
+ * Helper to create OpenSSL TCP sockets.
+ */
+template <typename Address>
+using SocketTls = Socket<Address, protocol::Tls>;
+
+/**
+ * Helper to create OpenSSL TCP/Ip sockets.
+ */
+using SocketTlsIp = Socket<address::Ip, protocol::Tls>;
+
+#endif // !SOCKET_NO_SSL
+
+/* }}} */
+
+/*
+ * Select wrapper
+ * ------------------------------------------------------------------
+ *
+ * Wrapper for select(2) and other various implementations.
+ */
+
+/* {{{ Listener */
+
+/**
+ * @class ListenerStatus
+ * @brief Result of polling
+ *
+ * Result of a select call, returns the first ready socket found with its
+ * flags.
+ */
+class ListenerStatus {
+public:
+	Handle socket;		//!< which socket is ready
+	Condition flags;	//!< the flags
+};
+
+/**
+ * Table used in the socket listener to store which sockets have been
+ * set in which directions.
+ */
+using ListenerTable = std::map<Handle, Condition>;
+
+/**
+ * @class Select
+ * @brief Implements select(2)
+ *
+ * This class is the fallback of any other method, it is not preferred at all for many reasons.
+ */
+class Select {
+public:
+	/**
+	 * No-op, uses the ListenerTable directly.
+	 */
+	inline void set(const ListenerTable &, Handle, Condition, bool) noexcept {}
+
+	/**
+	 * No-op, uses the ListenerTable directly.
+	 */
+	inline void unset(const ListenerTable &, Handle, Condition, bool) noexcept {}
+
+	/**
+	 * Return the sockets
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &table, int ms);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "select";
+	}
+};
+
+#if defined(SOCKET_HAVE_POLL)
+
+/**
+ * @class Poll
+ * @brief Implements poll(2).
+ *
+ * Poll is widely supported and is better than select(2). It is still not the
+ * best option as selecting the sockets is O(n).
+ */
+class Poll {
+private:
+	std::vector<pollfd> m_fds;
+
+	short toPoll(Condition flags) const noexcept;
+	Condition toCondition(short &event) const noexcept;
+
+public:
+	/**
+	 * Set the handle.
+	 */
+	void set(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Unset the handle.
+	 */
+	void unset(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Wait for events.
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "poll";
+	}
+};
+
+#endif
+
+#if defined(SOCKET_HAVE_EPOLL)
+
+/**
+ * @class Epoll
+ * @brief Linux's epoll.
+ */
+class Epoll {
+private:
+	int m_handle;
+	std::vector<epoll_event> m_events;
+
+	Epoll(const Epoll &) = delete;
+	Epoll &operator=(const Epoll &) = delete;
+	Epoll(const Epoll &&) = delete;
+	Epoll &operator=(const Epoll &&) = delete;
+
+	uint32_t toEpoll(Condition flags) const noexcept;
+	Condition toCondition(uint32_t events) const noexcept;
+	void update(Handle sc, int op, int eflags);
+
+public:
+	/**
+	 * Construct the epoll instance.
+	 */
+	Epoll();
+
+	/**
+	 * Close the epoll instance.
+	 */
+	~Epoll();
+
+	/**
+	 * Set the handle.
+	 */
+	void set(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Unset the handle.
+	 */
+	void unset(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Wait for events.
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &, int);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "epoll";
+	}
+};
+
+#endif
+
+#if defined(SOCKET_HAVE_KQUEUE)
+
+/**
+ * @class Kqueue
+ * @brief Implements kqueue(2).
+ *
+ * This implementation is available on all BSD and Mac OS X. It is better than
+ * poll(2) because it's O(1), however it's a bit more memory consuming.
+ */
+class Kqueue {
+private:
+	std::vector<struct kevent> m_result;
+	int m_handle;
+
+	Kqueue(const Kqueue &) = delete;
+	Kqueue &operator=(const Kqueue &) = delete;
+	Kqueue(Kqueue &&) = delete;
+	Kqueue &operator=(Kqueue &&) = delete;
+
+	void update(Handle sc, int filter, int kflags);
+
+public:
+	/**
+	 * Construct the kqueue instance.
+	 */
+	Kqueue();
+
+	/**
+	 * Destroy the kqueue instance.
+	 */
+	~Kqueue();
+
+	/**
+	 * Set the handle.
+	 */
+	void set(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Unset the handle.
+	 */
+	void unset(const ListenerTable &, Handle, Condition, bool);
+
+	/**
+	 * Wait for events.
+	 */
+	std::vector<ListenerStatus> wait(const ListenerTable &, int);
+
+	/**
+	 * Backend identifier
+	 */
+	inline const char *name() const noexcept
+	{
+		return "kqueue";
+	}
+};
+
+#endif
+
+/**
+ * @class Listener
+ * @brief Synchronous multiplexing
+ *
+ * Convenient wrapper around the select() system call.
+ *
+ * This class is implemented using a bridge pattern to allow different uses
+ * of listener implementation.
+ *
+ * You should not reinstanciate a new Listener at each iteartion of your
+ * main loop as it can be extremely costly. Instead use the same listener that
+ * you can safely modify on the fly.
+ *
+ * Currently, poll, epoll, select and kqueue are available.
+ *
+ * To implement the backend, the following functions must be available:
+ *
+ * ### Set
+ *
+ * @code
+ * void set(const ListenerTable &, Handle sc, Condition condition, bool add);
+ * @endcode
+ *
+ * This function, takes the socket to be added and the flags. The condition is
+ * always guaranteed to be correct and the function will never be called twice
+ * even if the user tries to set the same flag again.
+ *
+ * An optional add argument is added for backends which needs to do different
+ * operation depending if the socket was already set before or if it is the
+ * first time (e.g EPOLL_CTL_ADD vs EPOLL_CTL_MOD for epoll(7).
+ *
+ * ### Unset
+ *
+ * @code
+ * void unset(const ListenerTable &, Handle sc, Condition condition, bool remove);
+ * @endcode
+ *
+ * Like set, this function is only called if the condition is actually set and will
+ * not be called multiple times.
+ *
+ * Also like set, an optional remove argument is set if the socket is being
+ * completely removed (e.g no more flags are set for this socket).
+ *
+ * ### Wait
+ *
+ * @code
+ * std::vector<ListenerStatus> wait(const ListenerTable &, int ms);
+ * @endcode
+ *
+ * Wait for the sockets to be ready with the specified milliseconds. Must return a list of ListenerStatus,
+ * may throw any exceptions.
+ *
+ * ### Name
+ *
+ * @code
+ * inline const char *name() const noexcept
+ * @endcode
+ *
+ * Returns the backend name. Usually the class in lower case.
+ */
+template <typename Backend = SOCKET_DEFAULT_BACKEND>
+class Listener {
+private:
+	Backend m_backend;
+	ListenerTable m_table;
+
+public:
+	/**
+	 * Construct an empty listener.
+	 */
+	Listener() = default;
+
+	/**
+	 * Get the backend.
+	 *
+	 * @return the backend
+	 */
+	inline const Backend &backend() const noexcept
+	{
+		return m_backend;
+	}
+
+	/**
+	 * Get the non-modifiable table.
+	 *
+	 * @return the table
+	 */
+	inline const ListenerTable &table() const noexcept
+	{
+		return m_table;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator begin() const noexcept
+	{
+		return m_table.begin();
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator cbegin() const noexcept
+	{
+		return m_table.cbegin();
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator end() const noexcept
+	{
+		return m_table.end();
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @return the iterator
+	 */
+	inline ListenerTable::const_iterator cend() const noexcept
+	{
+		return m_table.cend();
+	}
+
+	/**
+	 * Add or update a socket to the listener.
+	 *
+	 * If the socket is already placed with the appropriate flags, the
+	 * function is a no-op.
+	 *
+	 * If incorrect flags are passed, the function does nothing.
+	 *
+	 * @param sc the socket
+	 * @param condition the condition (may be OR'ed)
+	 * @throw Error if the backend failed to set
+	 */
+	void set(Handle sc, Condition condition)
+	{
+		/* Invalid or useless flags */
+		if (condition == Condition::None || static_cast<int>(condition) > 0x3)
+			return;
+
+		auto it = m_table.find(sc);
+
+		/*
+		 * Do not update the table if the backend failed to add
+		 * or update.
+		 */
+		if (it == m_table.end()) {
+			m_backend.set(m_table, sc, condition, true);
+			m_table.emplace(sc, condition);
+		} else {
+			/* Remove flag if already present */
+			if ((condition & Condition::Readable) == Condition::Readable &&
+			    (it->second & Condition::Readable) == Condition::Readable) {
+				condition &= ~(Condition::Readable);
+			}
+			if ((condition & Condition::Writable) == Condition::Writable &&
+			    (it->second & Condition::Writable) == Condition::Writable) {
+				condition &= ~(Condition::Writable);
+			}
+
+			/* Still need a call? */
+			if (condition != Condition::None) {
+				m_backend.set(m_table, sc, condition, false);
+				it->second |= condition;
+			}
+		}
+	}
+
+	/**
+	 * Unset a socket from the listener, only the flags is removed
+	 * unless the two flagss are requested.
+	 *
+	 * For example, if you added a socket for both reading and writing,
+	 * unsetting the write flags will keep the socket for reading.
+	 *
+	 * @param sc the socket
+	 * @param condition the condition (may be OR'ed)
+	 * @see remove
+	 */
+	void unset(Handle sc, Condition condition)
+	{
+		auto it = m_table.find(sc);
+
+		/* Invalid or useless flags */
+		if (condition == Condition::None || static_cast<int>(condition) > 0x3 || it == m_table.end())
+			return;
+
+		/*
+		 * Like set, do not update if the socket is already at the appropriate
+		 * state.
+		 */
+		if ((condition & Condition::Readable) == Condition::Readable &&
+		    (it->second & Condition::Readable) != Condition::Readable) {
+			condition &= ~(Condition::Readable);
+		}
+		if ((condition & Condition::Writable) == Condition::Writable &&
+		    (it->second & Condition::Writable) != Condition::Writable) {
+			condition &= ~(Condition::Writable);
+		}
+
+		if (condition != Condition::None) {
+			/* Determine if it's a complete removal */
+			bool removal = ((it->second) & ~(condition)) == Condition::None;
+
+			m_backend.unset(m_table, sc, condition, removal);
+
+			if (removal) {
+				m_table.erase(it);
+			} else {
+				it->second &= ~(condition);
+			}
+		}
+	}
+
+	/**
+	 * Remove completely the socket from the listener.
+	 *
+	 * It is a shorthand for unset(sc, Condition::Readable | Condition::Writable);
+	 *
+	 * @param sc the socket
+	 */
+	inline void remove(Handle sc)
+	{
+		unset(sc, Condition::Readable | Condition::Writable);
+	}
+
+	/**
+	 * Remove all sockets.
+	 */
+	inline void clear()
+	{
+		while (!m_table.empty()) {
+			remove(m_table.begin()->first);
+		}
+	}
+
+	/**
+	 * Get the number of sockets in the listener.
+	 */
+	inline ListenerTable::size_type size() const noexcept
+	{
+		return m_table.size();
+	}
+
+	/**
+	 * Select a socket. Waits for a specific amount of time specified as the duration.
+	 *
+	 * @param duration the duration
+	 * @return the socket ready
+	 */
+	template <typename Rep, typename Ratio>
+	inline ListenerStatus wait(const std::chrono::duration<Rep, Ratio> &duration)
+	{
+		assert(!m_table.empty());
+
+		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+
+		return m_backend.wait(m_table, cvt.count())[0];
+	}
+
+	/**
+	 * Overload with milliseconds.
+	 *
+	 * @param timeout the optional timeout in milliseconds
+	 * @return the socket ready
+	 */
+	inline ListenerStatus wait(int timeout = -1)
+	{
+		return wait(std::chrono::milliseconds(timeout));
+	}
+
+	/**
+	 * Select multiple sockets.
+	 *
+	 * @param duration the duration
+	 * @return the socket ready
+	 */
+	template <typename Rep, typename Ratio>
+	inline std::vector<ListenerStatus> waitMultiple(const std::chrono::duration<Rep, Ratio> &duration)
+	{
+		assert(!m_table.empty());
+
+		auto cvt = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
+
+		return m_backend.wait(m_table, cvt.count());
+	}
+
+	/**
+	 * Overload with milliseconds.
+	 *
+	 * @return the socket ready
+	 */
+	inline std::vector<ListenerStatus> waitMultiple(int timeout = -1)
+	{
+		return waitMultiple(std::chrono::milliseconds(timeout));
+	}
+};
+
+/* }}} */
+
+/*
+ * Callback
+ * ------------------------------------------------------------------
+ *
+ * Function owner with tests.
+ */
+
+/* {{{ Callback */
+
+/**
+ * @class Callback
+ * @brief Convenient signal owner that checks if the target is valid.
+ *
+ * This class also catch all errors thrown from signals to avoid interfering with our process.
+ */
+template <typename... Args>
+class Callback : public std::function<void (Args...)> {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using std::function<void (Args...)>::function;
+
+	/**
+	 * Execute the callback only if a target is set.
+	 */
+	void operator()(Args... args) const
+	{
+		if (*this) {
+			try {
+				std::function<void (Args...)>::operator()(args...);
+			} catch (...) {
+			}
+		}
+	}
+};
+
+/* }}} */
+
+/*
+ * StreamConnection
+ * ------------------------------------------------------------------
+ *
+ * Client connected on the server side.
+ */
+
+/* {{{ StreamConnection */
+
+/**
+ * @class StreamConnection
+ * @brief Connected client on the server side.
+ *
+ * This object is created from StreamServer when a new client is connected, it is the higher
+ * level object of sockets and completely asynchronous.
+ */
+template <typename Address, typename Protocol>
+class StreamConnection {
+public:
+	/**
+	 * Called when the output has changed.
+	 */
+	using WriteHandler = Callback<>;
+
+private:
+	/* Signals */
+	WriteHandler m_onWrite;
+
+	/* Sockets and output buffer */
+	Socket<Address, Protocol> m_socket;
+	std::string m_output;
+
+public:
+	/**
+	 * Create the connection.
+	 *
+	 * @param s the socket
+	 */
+	StreamConnection(Socket<Address, Protocol> s)
+		: m_socket{std::move(s)}
+	{
+		m_socket.set(net::option::SockBlockMode{false});
+	}
+
+	/**
+	 * Access the underlying socket.
+	 *
+	 * @return the socket
+	 * @warning use with care
+	 */
+	inline Socket<Address, Protocol> &socket() noexcept
+	{
+		return m_socket;
+	}
+
+	/**
+	 * Access the current output.
+	 *
+	 * @return the output
+	 */
+	inline const std::string &output() const noexcept
+	{
+		return m_output;
+	}
+
+	/**
+	 * Overloaded function
+	 *
+	 * @return the output
+	 * @warning use with care, avoid modifying the output if you don't know what you're doing
+	 */
+	inline std::string &output() noexcept
+	{
+		return m_output;
+	}
+
+	/**
+	 * Post some data to be sent asynchronously.
+	 *
+	 * @param str the data to append
+	 */
+	inline void send(std::string str)
+	{
+		m_output += str;
+		m_onWrite();
+	}
+
+	/**
+	 * Kill the client.
+	 */
+	inline void close()
+	{
+		m_socket.close();
+	}
+
+	/**
+	 * Set the write handler, the signal is emitted when the output has changed so that the StreamServer owner
+	 * knows that there are some data to send.
+	 *
+	 * @param handler the handler
+	 * @warning you usually never need to set this yourself
+	 */
+	inline void setWriteHandler(WriteHandler handler)
+	{
+		m_onWrite = std::move(handler);
+	}
+};
+
+/* }}} */
+
+/*
+ * StreamServer
+ * ------------------------------------------------------------------
+ *
+ * Convenient stream oriented server.
+ */
+
+/* {{{ StreamServer */
+
+/**
+ * @class StreamServer
+ * @brief Convenient stream server for TCP and TLS.
+ *
+ * This class does all the things for you as accepting new clients, listening for it and sending data. It works
+ * asynchronously without blocking to let you control your process workflow.
+ *
+ * This class is not thread safe and you must not call any of the functions from different threads.
+ */
+template <typename Address, typename Protocol>
+class StreamServer {
+public:
+	/**
+	 * Handler when a new client is connected.
+	 */
+	using ConnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
+
+	/**
+	 * Handler when a client is disconnected.
+	 */
+	using DisconnectionHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &>;
+
+	/**
+	 * Handler when data has been received from a client.
+	 */
+	using ReadHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
+
+	/**
+	 * Handler when data has been correctly sent to a client.
+	 */
+	using WriteHandler = Callback<const std::shared_ptr<StreamConnection<Address, Protocol>> &, const std::string &>;
+
+	/**
+	 * Handler when an error occured.
+	 */
+	using ErrorHandler = Callback<const Error &>;
+
+	/**
+	 * Handler when there was a timeout.
+	 */
+	using TimeoutHandler = Callback<>;
+
+private:
+	using ClientMap = std::map<Handle, std::shared_ptr<StreamConnection<Address, Protocol>>>;
+
+	/* Signals */
+	ConnectionHandler m_onConnection;
+	DisconnectionHandler m_onDisconnection;
+	ReadHandler m_onRead;
+	WriteHandler m_onWrite;
+	ErrorHandler m_onError;
+	TimeoutHandler m_onTimeout;
+
+	/* Sockets */
+	Socket<Address, Protocol> m_master;
+	Listener<> m_listener;
+	ClientMap m_clients;
+
+	/*
+	 * Update flags depending on the required condition.
+	 */
+	void updateFlags(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
+	{
+		assert(client->socket().action() != Action::None);
+
+		m_listener.remove(client->socket().handle());
+		m_listener.set(client->socket().handle(), client->socket().condition());
+	}
+
+	/*
+	 * Continue accept process.
+	 */
+	template <typename AcceptCall>
+	void processAccept(std::shared_ptr<StreamConnection<Address, Protocol>> &client, const AcceptCall &acceptFunc)
+	{
+		try {
+			/* Do the accept */
+			acceptFunc();
+
+			/* 1. First remove completely the client */
+			m_listener.remove(client->socket().handle());
+
+			/* 2. If accept is not finished, wait for the appropriate condition */
+			if (client->socket().state() == State::Accepted) {
+				/* 3. Client is accepted, notify the user */
+				m_listener.set(client->socket().handle(), Condition::Readable);
+				m_onConnection(client);
+			} else {
+				/* Operation still in progress */
+				updateFlags(client);
+			}
+		} catch (const Error &error) {
+			m_clients.erase(client->socket().handle());
+			m_listener.remove(client->socket().handle());
+			m_onError(error);
+		}
+	}
+
+	/*
+	 * Process initial accept of master socket, this is the initial accepting process. Except on errors, the
+	 * socket is stored but the user will be notified only once the socket is completely accepted.
+	 */
+	void processInitialAccept()
+	{
+		// TODO: store address too.
+		std::shared_ptr<StreamConnection<Address, Protocol>> client = std::make_shared<StreamConnection<Address, Protocol>>(m_master.accept(nullptr));
+		std::weak_ptr<StreamConnection<Address, Protocol>> ptr{client};
+
+		/* 1. Register output changed to update listener */
+		client->setWriteHandler([this, ptr] () {
+			auto client = ptr.lock();
+
+			/* Do not update the listener immediately if an action is pending */
+			if (client && client->socket().action() == Action::None && !client->output().empty()) {
+				m_listener.set(client->socket().handle(), Condition::Writable);
+			}
+		});
+
+		/* 2. Add the client */
+		m_clients.insert(std::make_pair(client->socket().handle(), client));
+
+		/*
+		 * 2. Do an initial check to set the listener flags, at this moment the socket may or not be
+		 *    completely accepted.
+		 */
+		processAccept(client, [&] () {});
+	}
+
+	/*
+	 * Read or complete the read operation.
+	 */
+	void processRead(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
+	{
+		/*
+		 * Read because there is something to read or because the pending operation is
+		 * read and must complete.
+		 */
+		auto buffer = client->socket().recv(512);
+
+		/*
+		 * Now the receive operation may be completed, in that case, two possibilities:
+		 *
+		 * 1. The action is set to None (completed)
+		 * 2. The action is still not complete, update the flags
+		 */
+		if (client->socket().action() == Action::None) {
+			/* Empty mean normal disconnection */
+			if (buffer.empty()) {
+				m_listener.remove(client->socket().handle());
+				m_clients.erase(client->socket().handle());
+				m_onDisconnection(client);
+			} else {
+				/*
+				 * At this step, it is possible that we were completing a receive operation, in this
+				 * case the write flag may be removed, add it if required.
+				 */
+				if (!client->output().empty()) {
+					m_listener.set(client->socket().handle(), Condition::Writable);
+				}
+
+				m_onRead(client, buffer);
+			}
+		} else {
+			/* Operation in progress */
+			updateFlags(client);
+		}
+	}
+
+	/*
+	 * Flush the output buffer.
+	 */
+	void processWrite(std::shared_ptr<StreamConnection<Address, Protocol>> &client)
+	{
+		auto &output = client->output();
+		auto nsent = client->socket().send(output);
+
+		if (client->socket().action() == Action::None) {
+			/* 1. Create a copy of content that has been sent */
+			auto sent = output.substr(0, nsent);
+
+			/* 2. Erase the content sent */
+			output.erase(0, nsent);
+
+			/* 3. Update listener */
+			if (output.empty()) {
+				m_listener.unset(client->socket().handle(), Condition::Writable);
+			}
+
+			/* 4. Notify user */
+			m_onWrite(client, sent);
+		} else {
+			updateFlags(client);
+		}
+	}
+
+	void processSync(std::shared_ptr<StreamConnection<Address, Protocol>> &client, Condition flags)
+	{
+		try {
+			auto action = client->socket().action();
+
+			if (action == Action::Receive ||
+			    (action == Action::None && (flags & Condition::Readable) == Condition::Readable)) {
+				processRead(client);
+			} else if ((flags & Condition::Writable) == Condition::Writable) {
+				processWrite(client);
+			}
+		} catch (const Error &error) {
+			m_onDisconnection(client);
+			m_listener.remove(client->socket().handle());
+			m_clients.erase(client->socket().handle());
+		}
+	}
+
+public:
+	/**
+	 * Create a stream server with the specified address to bind.
+	 *
+	 * @param protocol the protocol (Tcp or Tls)
+	 * @param address the address to bind
+	 * @param max the max number to listen
+	 * @throw Error on errors
+	 */
+	StreamServer(Protocol protocol, const Address &address, int max = 128)
+		: m_master{std::move(protocol), address}
+	{
+		// TODO: m_onError
+		m_master.set(SOL_SOCKET, SO_REUSEADDR, 1);
+		m_master.bind(address);
+		m_master.listen(max);
+		m_listener.set(m_master.handle(), Condition::Readable);
+	}
+
+	/**
+	 * Set the connection handler, called when a new client is connected.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setConnectionHandler(ConnectionHandler handler)
+	{
+		m_onConnection = std::move(handler);
+	}
+
+	/**
+	 * Set the disconnection handler, called when a client died.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setDisconnectionHandler(DisconnectionHandler handler)
+	{
+		m_onDisconnection = std::move(handler);
+	}
+
+	/**
+	 * Set the receive handler, called when a client has sent something.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setReadHandler(ReadHandler handler)
+	{
+		m_onRead = std::move(handler);
+	}
+
+	/**
+	 * Set the writing handler, called when some data has been sent to a client.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setWriteHandler(WriteHandler handler)
+	{
+		m_onWrite = std::move(handler);
+	}
+
+	/**
+	 * Set the error handler, called when unrecoverable error has occured.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setErrorHandler(ErrorHandler handler)
+	{
+		m_onError = std::move(handler);
+	}
+
+	/**
+	 * Set the timeout handler, called when the selection has timeout.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setTimeoutHandler(TimeoutHandler handler)
+	{
+		m_onTimeout = std::move(handler);
+	}
+
+	/**
+	 * Poll for the next event.
+	 *
+	 * @param timeout the timeout (-1 for indefinitely)
+	 * @throw Error on errors
+	 */
+	void poll(int timeout = -1)
+	{
+		try {
+			auto st = m_listener.wait(timeout);
+
+			if (st.socket == m_master.handle()) {
+				/* New client */
+				processInitialAccept();
+			} else {
+				/* Recv / Send / Accept on a client */
+				auto client = m_clients[st.socket];
+
+				if (client->socket().state() == State::Accepted) {
+					processSync(client, st.flags);
+				} else {
+					processAccept(client, [&] () { client->socket().accept(); });
+				}
+			}
+		} catch (const Error &error) {
+			if (error.code() == Error::Timeout) {
+				m_onTimeout();
+			} else {
+				m_onError(error);
+			}
+		}
+	}
+};
+
+/* }}} */
+
+/*
+ * StreamClient
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ StreamClient */
+
+/**
+ * @class StreamClient
+ * @brief Client side connection to a server.
+ *
+ * This class is not thread safe and you must not call any of the functions from different threads.
+ */
+template <typename Address, typename Protocol>
+class StreamClient {
+public:
+	/**
+	 * Handler when connection is complete.
+	 */
+	using ConnectionHandler = Callback<>;
+
+	/**
+	 * Handler when data has been received.
+	 */
+	using ReadHandler = Callback<const std::string &>;
+
+	/**
+	 * Handler when data has been sent correctly.
+	 */
+	using WriteHandler = Callback<const std::string &>;
+
+	/**
+	 * Handler when disconnected.
+	 */
+	using DisconnectionHandler = Callback<>;
+
+	/**
+	 * Handler on unrecoverable error.
+	 */
+	using ErrorHandler = Callback<const Error &>;
+
+	/**
+	 * Handler when timeout occured.
+	 */
+	using TimeoutHandler = Callback<>;
+
+private:
+	/* Signals */
+	ConnectionHandler m_onConnection;
+	ReadHandler m_onRead;
+	WriteHandler m_onWrite;
+	DisconnectionHandler m_onDisconnection;
+	ErrorHandler m_onError;
+	TimeoutHandler m_onTimeout;
+
+	/* Socket */
+	Socket<Address, Protocol> m_socket;
+	Listener<> m_listener;
+
+	/* Output buffer */
+	std::string m_output;
+
+	/*
+	 * Update the flags after an uncompleted operation. This function must only be called when the operation
+	 * has not complete (e.g. connect, recv, send).
+	 */
+	void updateFlags()
+	{
+		assert(m_socket.action() != Action::None);
+
+		m_listener.remove(m_socket.handle());
+		m_listener.set(m_socket.handle(), m_socket.condition());
+	}
+
+	/*
+	 * This is the generic connect helper, it will be used to both initiate the connection or to continue the
+	 * connection process if needed.
+	 *
+	 * Thus the template parameter is the appropriate function to call either, m_socket.connect(address) or
+	 * m_socket.connect().
+	 *
+	 * See poll() and connect() to understand.
+	 */
+	template <typename ConnectCall>
+	void processConnect(const ConnectCall &connectFunc)
+	{
+		/* Call m_socket.connect() or m_socket.connect(address) */
+		connectFunc();
+
+		/* Remove entirely */
+		m_listener.remove(m_socket.handle());
+
+		if (m_socket.state() == State::Connected) {
+			m_onConnection();
+			m_listener.set(m_socket.handle(), Condition::Readable);
+		} else {
+			/* Connection still in progress */
+			updateFlags();
+		}
+	}
+
+	/*
+	 * Receive or complete the receive command, if the command is not complete, the listener is updated
+	 * accordingly.
+	 */
+	void processRead()
+	{
+		auto received = m_socket.recv(512);
+
+		if (m_socket.action() == Action::None) {
+			/* 0 means disconnection */
+			if (received.empty()) {
+				m_onDisconnection();
+			} else {
+				/*
+				 * At this step, it is possible that we were completing a receive operation, in this
+				 * case the write flag may be removed, add it if required.
+				 */
+				if (m_output.empty()) {
+					m_listener.unset(m_socket.handle(), Condition::Writable);
+				}
+
+				m_onRead(received);
+			}
+		} else {
+			/* Receive operation in progress */
+			updateFlags();
+		}
+	}
+
+	/*
+	 * Send or complete the send command, if the command is not complete, the listener is updated
+	 * accordingly.
+	 */
+	void processWrite()
+	{
+		auto nsent = m_socket.send(m_output);
+
+		if (m_socket.action() == Action::None) {
+			/* 1. Make a copy of what has been sent */
+			auto sent = m_output.substr(0, nsent);
+
+			/* 2. Erase sent content */
+			m_output.erase(0, nsent);
+
+			/* 3. Update flags if needed */
+			if (m_output.empty()) {
+				m_listener.unset(m_socket.handle(), Condition::Writable);
+			}
+
+			/* 4. Notify user */
+			m_onWrite(sent);
+		} else {
+			/* Send operation in progress */
+			updateFlags();
+		}
+	}
+
+	/*
+	 * Receive or send.
+	 */
+	void processSync(Condition condition)
+	{
+		if ((m_socket.action() == Action::Receive) ||
+		    (m_socket.action() == Action::None && (condition & Condition::Readable) == Condition::Readable)) {
+			processRead();
+		} else {
+			processWrite();
+		}
+	}
+
+public:
+	/**
+	 * Create a client. The client is automatically marked as non-blocking.
+	 *
+	 * @param protocol the protocol (Tcp or Tls)
+	 * @param address the optional address
+	 * @throw net::Error on failures
+	 */
+	StreamClient(Protocol protocol = {}, const Address &address = {})
+		: m_socket{std::move(protocol), address}
+	{
+		m_socket.set(net::option::SockBlockMode{false});
+		m_listener.set(m_socket.handle(), Condition::Readable);
+	}
+
+	/**
+	 * Set the connection handler, called when the connection succeed.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setConnectionHandler(ConnectionHandler handler)
+	{
+		m_onConnection = std::move(handler);
+	}
+
+	/**
+	 * Set the disconnection handler, called when the server closed the connection.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setDisconnectionHandler(DisconnectionHandler handler)
+	{
+		m_onDisconnection = std::move(handler);
+	}
+
+	/**
+	 * Set the read handler, called when we received something.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setReadHandler(ReadHandler handler)
+	{
+		m_onRead = std::move(handler);
+	}
+
+	/**
+	 * Set the write handler, called when we successfully sent data.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setWriteHandler(WriteHandler handler)
+	{
+		m_onWrite = std::move(handler);
+	}
+
+	/**
+	 * Set the error handler, called when unexpected error occurs.
+	 *
+	 * @param handler the handler
+	 */
+	inline void setErrorHandler(ErrorHandler handler)
+	{
+		m_onError = std::move(handler);
+	}
+
+	/**
+	 * Connect to a server, this function may connect immediately or not in any case the connection handler
+	 * will be called when the connection completed.
+	 *
+	 * @param address the address to connect to
+	 */
+	void connect(const Address &address) noexcept
+	{
+		assert(m_socket.state() == State::Open);
+
+		processConnect([&] () { m_socket.connect(address); });
+	}
+
+	/**
+	 * Asynchronously send data to the server.
+	 *
+	 * @param str the data to append
+	 */
+	void send(std::string str)
+	{
+		m_output += str;
+
+		/* Don't update the listener if there is a pending operation */
+		if (m_socket.state() == State::Connected && m_socket.action() == Action::None && !m_output.empty()) {
+			m_listener.set(m_socket.handle(), Condition::Writable);
+		}
+	}
+
+	/**
+	 * Wait for the next event.
+	 *
+	 * @param timeout the time to wait in milliseconds
+	 * @throw Error on errors
+	 */
+	void poll(int timeout = -1) noexcept
+	{
+		try {
+			auto st = m_listener.wait(timeout);
+
+			if (m_socket.state() != State::Connected) {
+				/* Continue the connection */
+				processConnect([&] () { m_socket.connect(); });
+			} else {
+				/* Read / Write */
+				processSync(st.flags);
+			}
+		} catch (const Error &error) {
+			if (error.code() == Error::Timeout) {
+				m_onTimeout();
+			} else {
+				m_listener.remove(m_socket.handle());
+				m_onError(error);
+			}
+		}
+	}
+};
+
+/* }}} */
+
+} // !net
+
+} // !irccd
+
+#endif // !IRCCD_SOCKETS_HPP
--- a/lib/irccd/system.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/system.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -20,7 +20,7 @@
 #include <ctime>
 #include <stdexcept>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
 #if defined(HAVE_SETPROGNAME)
 #  include <cstdlib>
@@ -43,7 +43,6 @@
 #  include <sys/utsname.h>
 #  include <sys/time.h>
 #  include <sys/types.h>
-
 #  include <unistd.h>
 
 #  include <cerrno>
@@ -67,10 +66,10 @@
 #  include <pwd.h>
 #endif
 
-#include "fs.h"
-#include "logger.h"
-#include "system.h"
-#include "util.h"
+#include "fs.hpp"
+#include "logger.hpp"
+#include "system.hpp"
+#include "util.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/system.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * system.h -- platform dependent functions for system inspection
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_SYSTEM_H
-#define IRCCD_SYSTEM_H
-
-/**
- * @file system.h
- * @brief System dependant functions
- */
-
-#include <irccd/sysconfig.h>
-
-#include <cstdint>
-#include <string>
-
-namespace irccd {
-
-namespace sys {
-
-/**
- * Set the program name, needed for some functions or some systems.
- *
- * @param name the program name
- */
-void setProgramName(std::string name) noexcept;
-
-/**
- * Get the program name.
- *
- * @return the program name
- */
-const std::string &programName() noexcept;
-
-/**
- * Get the system name.
- *
- * @return the name
- */
-std::string name();
-
-/**
- * Get the system version.
- *
- * @return the version
- */
-std::string version();
-
-/**
- * Get the number of seconds elapsed since the boottime.
- *
- * @return the number of seconds
- */
-uint64_t uptime();
-
-/**
- * Get the milliseconds elapsed since the application
- * startup.
- *
- * @return the milliseconds
- */
-uint64_t ticks();
-
-/**
- * Get an environment variable.
- *
- * @return the value or empty string
- */
-std::string env(const std::string &var);
-
-/**
- * Get home directory usually /home/foo
- *
- * @return the home directory
- */
-std::string home();
-
-#if defined(HAVE_SETUID)
-
-/**
- * Set the effective uid by name or numeric value.
- *
- * @param value the value
- */
-void setUid(const std::string &value);
-
-#endif
-
-#if defined(HAVE_SETGID)
-
-/**
- * Set the effective gid by name or numeric value.
- *
- * @param value the value
- */
-void setGid(const std::string &value);
-
-#endif
-
-} // !sys
-
-} // !irccd
-
-#endif // !IRCCD_SYSTEM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/system.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,119 @@
+/*
+ * system.hpp -- platform dependent functions for system inspection
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_SYSTEM_HPP
+#define IRCCD_SYSTEM_HPP
+
+/**
+ * @file system.hpp
+ * @brief System dependant functions
+ */
+
+#include <irccd/sysconfig.hpp>
+
+#include <cstdint>
+#include <string>
+
+namespace irccd {
+
+namespace sys {
+
+/**
+ * Set the program name, needed for some functions or some systems.
+ *
+ * @param name the program name
+ */
+void setProgramName(std::string name) noexcept;
+
+/**
+ * Get the program name.
+ *
+ * @return the program name
+ */
+const std::string &programName() noexcept;
+
+/**
+ * Get the system name.
+ *
+ * @return the name
+ */
+std::string name();
+
+/**
+ * Get the system version.
+ *
+ * @return the version
+ */
+std::string version();
+
+/**
+ * Get the number of seconds elapsed since the boottime.
+ *
+ * @return the number of seconds
+ */
+uint64_t uptime();
+
+/**
+ * Get the milliseconds elapsed since the application
+ * startup.
+ *
+ * @return the milliseconds
+ */
+uint64_t ticks();
+
+/**
+ * Get an environment variable.
+ *
+ * @return the value or empty string
+ */
+std::string env(const std::string &var);
+
+/**
+ * Get home directory usually /home/foo
+ *
+ * @return the home directory
+ */
+std::string home();
+
+#if defined(HAVE_SETUID)
+
+/**
+ * Set the effective uid by name or numeric value.
+ *
+ * @param value the value
+ */
+void setUid(const std::string &value);
+
+#endif
+
+#if defined(HAVE_SETGID)
+
+/**
+ * Set the effective gid by name or numeric value.
+ *
+ * @param value the value
+ */
+void setGid(const std::string &value);
+
+#endif
+
+} // !sys
+
+} // !irccd
+
+#endif // !IRCCD_SYSTEM_HPP
--- a/lib/irccd/timer.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/timer.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -19,7 +19,7 @@
 #include <cassert>
 #include <chrono>
 
-#include "timer.h"
+#include "timer.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/timer.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-/*
- * timer.h -- threaded timers
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_TIMER_H
-#define IRCCD_TIMER_H
-
-/**
- * @file timer.h
- * @brief Provides interval based timers for JavaScript
- */
-
-#include <atomic>
-#include <condition_variable>
-#include <functional>
-#include <mutex>
-#include <thread>
-
-#include "signals.h"
-
-namespace irccd {
-
-/**
- * @enum TimerType
- * @brief Type of timer
- */
-enum class TimerType {
-	Single,			//!< The timer ends after execution
-	Repeat			//!< The timer loops
-};
-
-/**
- * @class Timer
- * @brief Timer class
- *
- * A timer is a thread object that emits a signal periodically or just one time. It is perfectly pausable and resumable
- * to reuse the same object.
- *
- * The delay is configured in milliseconds and the user has choice to use any
- * delay needed.
- *
- * We use a condition variable to wait for the specified delay unless the timer
- * must be stopped.
- */
-class Timer {
-public:
-	/**
-	 * Signal: onSignal
-	 * ----------------------------------------------------------
-	 *
-	 * Called when the timeout expires.
-	 */
-	Signal<> onSignal;
-
-	/**
-	 * Signal: onEnd
-	 * ----------------------------------------------------------
-	 *
-	 * Called when the timeout ends.
-	 */
-	Signal<> onEnd;
-
-private:
-	enum {
-		Paused,
-		Running,
-		Stopped
-	};
-
-	TimerType m_type;
-	unsigned m_delay;
-
-	/* Thread management */
-	std::atomic<int> m_state{Paused};
-	std::mutex m_mutex;
-	std::condition_variable m_condition;
-	std::thread m_thread;
-
-	void run();
-
-public:
-	/**
-	 * Timer constructor.
-	 *
-	 * The timer is not started, use start().
-	 *
-	 * @param type the timer type
-	 * @param delay the delay in milliseconds
-	 * @post isRunning() returns false
-	 */
-	Timer(TimerType type, unsigned delay) noexcept;
-
-	/**
-	 * Destructor, closes the thread.
-	 *
-	 * @pre stop() must have been called.
-	 */
-	virtual ~Timer();
-
-	/**
-	 * Start the thread.
-	 *
-	 * @pre isRunning() must return false
-	 * @pre onSignal() must have been called
-	 * @pre onEnd() must have been called
-	 * @note Thread-safe
-	 */
-	void start();
-
-	/**
-	 * Stop the timer, may be used by the user to stop it.
-	 *
-	 * @note Thread-safe
-	 */
-	void stop();
-
-	/**
-	 * Get the type of timer.
-	 *
-	 * @return the type.
-	 */
-	inline TimerType type() const noexcept
-	{
-		return m_type;
-	}
-
-	/**
-	 * Tells if the timer has still a running thread.
-	 *
-	 * @return true if still alive
-	 * @note Thread-safe
-	 */
-	inline bool isRunning() const noexcept
-	{
-		return m_state == Running;
-	}
-};
-
-} // !irccd
-
-#endif // !IRCCD_TIMER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/timer.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,155 @@
+/*
+ * timer.hpp -- threaded timers
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_TIMER_HPP
+#define IRCCD_TIMER_HPP
+
+/**
+ * @file timer.hpp
+ * @brief Provides interval based timers for JavaScript
+ */
+
+#include <atomic>
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <thread>
+
+#include "signals.hpp"
+
+namespace irccd {
+
+/**
+ * @enum TimerType
+ * @brief Type of timer
+ */
+enum class TimerType {
+	Single,			//!< The timer ends after execution
+	Repeat			//!< The timer loops
+};
+
+/**
+ * @class Timer
+ * @brief Timer class
+ *
+ * A timer is a thread object that emits a signal periodically or just one time. It is perfectly pausable and resumable
+ * to reuse the same object.
+ *
+ * The delay is configured in milliseconds and the user has choice to use any
+ * delay needed.
+ *
+ * We use a condition variable to wait for the specified delay unless the timer
+ * must be stopped.
+ */
+class Timer {
+public:
+	/**
+	 * Signal: onSignal
+	 * ----------------------------------------------------------
+	 *
+	 * Called when the timeout expires.
+	 */
+	Signal<> onSignal;
+
+	/**
+	 * Signal: onEnd
+	 * ----------------------------------------------------------
+	 *
+	 * Called when the timeout ends.
+	 */
+	Signal<> onEnd;
+
+private:
+	enum {
+		Paused,
+		Running,
+		Stopped
+	};
+
+	TimerType m_type;
+	unsigned m_delay;
+
+	/* Thread management */
+	std::atomic<int> m_state{Paused};
+	std::mutex m_mutex;
+	std::condition_variable m_condition;
+	std::thread m_thread;
+
+	void run();
+
+public:
+	/**
+	 * Timer constructor.
+	 *
+	 * The timer is not started, use start().
+	 *
+	 * @param type the timer type
+	 * @param delay the delay in milliseconds
+	 * @post isRunning() returns false
+	 */
+	Timer(TimerType type, unsigned delay) noexcept;
+
+	/**
+	 * Destructor, closes the thread.
+	 *
+	 * @pre stop() must have been called.
+	 */
+	virtual ~Timer();
+
+	/**
+	 * Start the thread.
+	 *
+	 * @pre isRunning() must return false
+	 * @pre onSignal() must have been called
+	 * @pre onEnd() must have been called
+	 * @note Thread-safe
+	 */
+	void start();
+
+	/**
+	 * Stop the timer, may be used by the user to stop it.
+	 *
+	 * @note Thread-safe
+	 */
+	void stop();
+
+	/**
+	 * Get the type of timer.
+	 *
+	 * @return the type.
+	 */
+	inline TimerType type() const noexcept
+	{
+		return m_type;
+	}
+
+	/**
+	 * Tells if the timer has still a running thread.
+	 *
+	 * @return true if still alive
+	 * @note Thread-safe
+	 */
+	inline bool isRunning() const noexcept
+	{
+		return m_state == Running;
+	}
+};
+
+} // !irccd
+
+#endif // !IRCCD_TIMER_HPP
--- a/lib/irccd/transport-client.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/transport-client.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,9 +16,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "json.h"
-#include "logger.h"
-#include "transport-client.h"
+#include "json.hpp"
+#include "logger.hpp"
+#include "transport-client.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/transport-client.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/*
- * transport-client.h -- client connected to irccd
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_TRANSPORT_CLIENT_H
-#define IRCCD_TRANSPORT_CLIENT_H
-
-/**
- * @file transport-client.h
- * @brief Client connected to irccd
- */
-
-#include <functional>
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-#include "server.h"
-#include "signals.h"
-#include "sockets.h"
-
-namespace irccd {
-
-namespace json {
-
-class Value;
-
-} // !json
-
-/**
- * @class TransportClient
- * @brief Client connected to irccd.
- *
- * This class emits a warning upon clients request through onCommand signal.
- */
-class TransportClient {
-public:
-	/**
-	 * Signal: onCommand
-	 * ----------------------------------------------------------
-	 *
-	 * Arguments:
-	 *   - the command
-	 */
-	Signal<const json::Value &> onCommand;
-
-	/**
-	 * Signal: onDie
-	 * ----------------------------------------------------------
-	 *
-	 * The client has disconnected.
-	 */
-	Signal<> onDie;
-
-protected:
-	std::string m_input;
-	std::string m_output;
-
-	/* Parse input buffer */
-	void parse(const std::string &);
-
-	/* Do I/O */
-	virtual void receive() = 0;
-	virtual void send() = 0;
-
-public:
-	/**
-	 * Virtual destructor defaulted.
-	 */
-	virtual ~TransportClient() = default;
-
-	/**
-	 * Send or receive data, called after a select.
-	 *
-	 * @param setinput the input fd_set
-	 * @param setoutput the output fd_set
-	 */
-	void sync(fd_set &setinput, fd_set &setoutput);
-
-#if 0
-	/**
-	 * Notify the client that the command succeeded.
-	 *
-	 * @param command the command name
-	 */
-	void ok(const std::string &command);
-
-	/**
-	 * Send an error message to the client.
-	 *
-	 * @param command the command name
-	 * @param message the error message
-	 */
-	void error(const std::string &command, std::string message);
-#endif
-
-	/**
-	 * Send some data, it will be pushed to the outgoing buffer.
-	 *
-	 * This function appends "\r\n\r\n" after the message so you don't have
-	 * to do it manually.
-	 *
-	 * @param message the message
-	 */
-	void send(std::string message);
-
-	/**
-	 * Tell if the client has data pending for output.
-	 *
-	 * @return true if has pending data to write
-	 */
-	inline bool hasOutput() const noexcept
-	{
-		return !m_output.empty();
-	}
-
-	/**
-	 * Get the underlying socket handle.
-	 *
-	 * @return the socket
-	 */
-	virtual net::Handle handle() noexcept = 0;
-};
-
-/**
- * @brief Template class for Tcp and Ssl sockets
- */
-template <typename Address>
-class TransportClientBase : public TransportClient {
-private:
-	net::SocketTcp<Address> m_socket;
-
-protected:
-	void send() override;
-	void receive() override;
-
-public:
-	/**
-	 * Create a client.
-	 *
-	 * @param socket the socket
-	 */
-	inline TransportClientBase(net::SocketTcp<Address> socket)
-		: m_socket(std::move(socket))
-	{
-	}
-
-	/**
-	 * @copydoc TransportClient::handle
-	 */
-	net::Handle handle() noexcept override
-	{
-		return m_socket.handle();
-	}
-};
-
-template <typename Address>
-void TransportClientBase<Address>::receive()
-{
-	try {
-		auto message = m_socket.recv(512);
-
-		if (message.empty())
-			onDie();
-
-		m_input += message;
-	} catch (const std::exception &) {
-		onDie();
-	}
-
-	std::string::size_type pos;
-	while ((pos = m_input.find("\r\n\r\n")) != std::string::npos) {
-		/*
-		 * Make a copy and erase it in case that onComplete function
-		 * throws.
-		 */
-		auto message = m_input.substr(0, pos);
-
-		m_input.erase(m_input.begin(), m_input.begin() + pos + 4);
-
-		parse(message);
-	}
-}
-
-template <typename Address>
-void TransportClientBase<Address>::send()
-{
-	m_output.erase(0, m_socket.send(m_output));
-}
-
-} // !irccd
-
-#endif // !IRCCD_TRANSPORT_CLIENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/transport-client.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,207 @@
+/*
+ * transport-client.hpp -- client connected to irccd
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_TRANSPORT_CLIENT_HPP
+#define IRCCD_TRANSPORT_CLIENT_HPP
+
+/**
+ * @file transport-client.hpp
+ * @brief Client connected to irccd
+ */
+
+#include <functional>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include "server.hpp"
+#include "signals.hpp"
+#include "sockets.hpp"
+
+namespace irccd {
+
+namespace json {
+
+class Value;
+
+} // !json
+
+/**
+ * @class TransportClient
+ * @brief Client connected to irccd.
+ *
+ * This class emits a warning upon clients request through onCommand signal.
+ */
+class TransportClient {
+public:
+	/**
+	 * Signal: onCommand
+	 * ----------------------------------------------------------
+	 *
+	 * Arguments:
+	 *   - the command
+	 */
+	Signal<const json::Value &> onCommand;
+
+	/**
+	 * Signal: onDie
+	 * ----------------------------------------------------------
+	 *
+	 * The client has disconnected.
+	 */
+	Signal<> onDie;
+
+protected:
+	std::string m_input;
+	std::string m_output;
+
+	/* Parse input buffer */
+	void parse(const std::string &);
+
+	/* Do I/O */
+	virtual void receive() = 0;
+	virtual void send() = 0;
+
+public:
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~TransportClient() = default;
+
+	/**
+	 * Send or receive data, called after a select.
+	 *
+	 * @param setinput the input fd_set
+	 * @param setoutput the output fd_set
+	 */
+	void sync(fd_set &setinput, fd_set &setoutput);
+
+#if 0
+	/**
+	 * Notify the client that the command succeeded.
+	 *
+	 * @param command the command name
+	 */
+	void ok(const std::string &command);
+
+	/**
+	 * Send an error message to the client.
+	 *
+	 * @param command the command name
+	 * @param message the error message
+	 */
+	void error(const std::string &command, std::string message);
+#endif
+
+	/**
+	 * Send some data, it will be pushed to the outgoing buffer.
+	 *
+	 * This function appends "\r\n\r\n" after the message so you don't have
+	 * to do it manually.
+	 *
+	 * @param message the message
+	 */
+	void send(std::string message);
+
+	/**
+	 * Tell if the client has data pending for output.
+	 *
+	 * @return true if has pending data to write
+	 */
+	inline bool hasOutput() const noexcept
+	{
+		return !m_output.empty();
+	}
+
+	/**
+	 * Get the underlying socket handle.
+	 *
+	 * @return the socket
+	 */
+	virtual net::Handle handle() noexcept = 0;
+};
+
+/**
+ * @brief Template class for Tcp and Ssl sockets
+ */
+template <typename Address>
+class TransportClientBase : public TransportClient {
+private:
+	net::SocketTcp<Address> m_socket;
+
+protected:
+	void send() override;
+	void receive() override;
+
+public:
+	/**
+	 * Create a client.
+	 *
+	 * @param socket the socket
+	 */
+	inline TransportClientBase(net::SocketTcp<Address> socket)
+		: m_socket(std::move(socket))
+	{
+	}
+
+	/**
+	 * @copydoc TransportClient::handle
+	 */
+	net::Handle handle() noexcept override
+	{
+		return m_socket.handle();
+	}
+};
+
+template <typename Address>
+void TransportClientBase<Address>::receive()
+{
+	try {
+		auto message = m_socket.recv(512);
+
+		if (message.empty())
+			onDie();
+
+		m_input += message;
+	} catch (const std::exception &) {
+		onDie();
+	}
+
+	std::string::size_type pos;
+	while ((pos = m_input.find("\r\n\r\n")) != std::string::npos) {
+		/*
+		 * Make a copy and erase it in case that onComplete function
+		 * throws.
+		 */
+		auto message = m_input.substr(0, pos);
+
+		m_input.erase(m_input.begin(), m_input.begin() + pos + 4);
+
+		parse(message);
+	}
+}
+
+template <typename Address>
+void TransportClientBase<Address>::send()
+{
+	m_output.erase(0, m_socket.send(m_output));
+}
+
+} // !irccd
+
+#endif // !IRCCD_TRANSPORT_CLIENT_HPP
--- a/lib/irccd/transport-server.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/transport-server.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -22,7 +22,7 @@
 
 #include <sstream>
 
-#include "transport-server.h"
+#include "transport-server.hpp"
 
 namespace irccd {
 
--- a/lib/irccd/transport-server.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * transport-server.h -- I/O for irccd clients (acceptors)
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_TRANSPORT_SERVER_H
-#define IRCCD_TRANSPORT_SERVER_H
-
-/**
- * @file transport-server.h
- * @brief Transports for irccd
- */
-
-#include <memory>
-#include <string>
-
-#include <irccd/sysconfig.h>
-
-#include "sockets.h"
-#include "transport-client.h"
-
-namespace irccd {
-
-/**
- * @class TransportServer
- * @brief Bring networking between irccd and irccdctl
- *
- * This class contains a master sockets for listening to TCP connections, it is then processed by irccd.
- *
- * The transport class supports the following domains:
- *
- * | Domain                | Class                 |
- * |-----------------------|-----------------------|
- * | IPv4, IPv6            | TransportServerIp     |
- * | Unix (not on Windows) | TransportServerUnix   |
- *
- * Note: IPv4 and IPv6 can be combined, using TransportServer::IPv6 and its option.
- */
-class TransportServer {
-private:
-	TransportServer(const TransportServer &) = delete;
-	TransportServer(TransportServer &&) = delete;
-
-	TransportServer &operator=(const TransportServer &) = delete;
-	TransportServer &operator=(TransportServer &&) = delete;
-
-public:
-	/**
-	 * Default constructor.
-	 */
-	TransportServer() = default;
-
-	/**
-	 * Destructor defaulted.
-	 */
-	virtual ~TransportServer() = default;
-
-	/**
-	 * Retrieve the underlying socket handle.
-	 *
-	 * @return the socket
-	 */
-	virtual net::Handle handle() noexcept = 0;
-
-	/**
-	 * Accept a new client depending on the domain.
-	 *
-	 * @return the new client
-	 */
-	virtual std::shared_ptr<TransportClient> accept() = 0;
-};
-
-/**
- * @class TransportServerIp
- * @brief Base class for both IPv4 and IPv6 servers.
- */
-class TransportServerIp : public TransportServer {
-protected:
-	net::SocketTcp<net::address::Ip> m_socket;
-
-public:
-	/**
-	 * Create a IP transport, use IPv6 or IPv4 address.
-	 *
-	 * @param domain AF_INET or AF_INET6
-	 * @param address the address or "*" for any
-	 * @param port the port number
-	 * @param ipv6only set to true to disable IPv4
-	 * @throw net::Error on failures
-	 */
-	TransportServerIp(int domain, const std::string &address, int port, bool ipv6only = true);
-
-	/**
-	 * @copydoc TransportServer::socket
-	 */
-	net::Handle handle() noexcept override;
-
-	/**
-	 * @copydoc TransportServer::accept
-	 */
-	std::shared_ptr<TransportClient> accept() override;
-};
-
-#if !defined(IRCCD_SYSTEM_WINDOWS)
-
-/**
- * @class TransportServerUnix
- * @brief Implementation of transports for Unix sockets.
- */
-class TransportServerUnix : public TransportServer {
-private:
-	net::SocketTcp<net::address::Local> m_socket;
-	std::string m_path;
-
-public:
-	/**
-	 * Create a Unix transport.
-	 *
-	 * @param path the path
-	 */
-	TransportServerUnix(std::string path);
-
-	/**
-	 * Destroy the transport and remove the file.
-	 */
-	~TransportServerUnix();
-
-	/**
-	 * @copydoc TransportServer::socket
-	 */
-	net::Handle handle() noexcept override;
-
-	/**
-	 * @copydoc TransportServer::accept
-	 */
-	std::shared_ptr<TransportClient> accept() override;
-};
-
-#endif // !_WIN32
-
-} // !irccd
-
-#endif // !IRCCD_TRANSPORT_SERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/transport-server.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,156 @@
+/*
+ * transport-server.hpp -- I/O for irccd clients (acceptors)
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_TRANSPORT_SERVER_HPP
+#define IRCCD_TRANSPORT_SERVER_HPP
+
+/**
+ * @file transport-server.hpp
+ * @brief Transports for irccd
+ */
+
+#include <memory>
+#include <string>
+
+#include <irccd/sysconfig.hpp>
+
+#include "sockets.hpp"
+#include "transport-client.hpp"
+
+namespace irccd {
+
+/**
+ * @class TransportServer
+ * @brief Bring networking between irccd and irccdctl
+ *
+ * This class contains a master sockets for listening to TCP connections, it is then processed by irccd.
+ *
+ * The transport class supports the following domains:
+ *
+ * | Domain                | Class                 |
+ * |-----------------------|-----------------------|
+ * | IPv4, IPv6            | TransportServerIp     |
+ * | Unix (not on Windows) | TransportServerUnix   |
+ *
+ * Note: IPv4 and IPv6 can be combined, using TransportServer::IPv6 and its option.
+ */
+class TransportServer {
+private:
+	TransportServer(const TransportServer &) = delete;
+	TransportServer(TransportServer &&) = delete;
+
+	TransportServer &operator=(const TransportServer &) = delete;
+	TransportServer &operator=(TransportServer &&) = delete;
+
+public:
+	/**
+	 * Default constructor.
+	 */
+	TransportServer() = default;
+
+	/**
+	 * Destructor defaulted.
+	 */
+	virtual ~TransportServer() = default;
+
+	/**
+	 * Retrieve the underlying socket handle.
+	 *
+	 * @return the socket
+	 */
+	virtual net::Handle handle() noexcept = 0;
+
+	/**
+	 * Accept a new client depending on the domain.
+	 *
+	 * @return the new client
+	 */
+	virtual std::shared_ptr<TransportClient> accept() = 0;
+};
+
+/**
+ * @class TransportServerIp
+ * @brief Base class for both IPv4 and IPv6 servers.
+ */
+class TransportServerIp : public TransportServer {
+protected:
+	net::SocketTcp<net::address::Ip> m_socket;
+
+public:
+	/**
+	 * Create a IP transport, use IPv6 or IPv4 address.
+	 *
+	 * @param domain AF_INET or AF_INET6
+	 * @param address the address or "*" for any
+	 * @param port the port number
+	 * @param ipv6only set to true to disable IPv4
+	 * @throw net::Error on failures
+	 */
+	TransportServerIp(int domain, const std::string &address, int port, bool ipv6only = true);
+
+	/**
+	 * @copydoc TransportServer::socket
+	 */
+	net::Handle handle() noexcept override;
+
+	/**
+	 * @copydoc TransportServer::accept
+	 */
+	std::shared_ptr<TransportClient> accept() override;
+};
+
+#if !defined(IRCCD_SYSTEM_WINDOWS)
+
+/**
+ * @class TransportServerUnix
+ * @brief Implementation of transports for Unix sockets.
+ */
+class TransportServerUnix : public TransportServer {
+private:
+	net::SocketTcp<net::address::Local> m_socket;
+	std::string m_path;
+
+public:
+	/**
+	 * Create a Unix transport.
+	 *
+	 * @param path the path
+	 */
+	TransportServerUnix(std::string path);
+
+	/**
+	 * Destroy the transport and remove the file.
+	 */
+	~TransportServerUnix();
+
+	/**
+	 * @copydoc TransportServer::socket
+	 */
+	net::Handle handle() noexcept override;
+
+	/**
+	 * @copydoc TransportServer::accept
+	 */
+	std::shared_ptr<TransportClient> accept() override;
+};
+
+#endif // !_WIN32
+
+} // !irccd
+
+#endif // !IRCCD_TRANSPORT_SERVER_HPP
--- a/lib/irccd/unicode.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/unicode.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -16,7 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "unicode.h"
+#include "unicode.hpp"
 
 /*
  * The following code has been generated from Go mkrunetype adapted to our
--- a/lib/irccd/unicode.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * unicode.h -- UTF-8 to UTF-32 conversions and various operations
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_UNICODE_H
-#define IRCCD_UNICODE_H
-
-/**
- * @file unicode.h
- * @brief UTF-8 to UTF-32 conversions
- */
-
-#include <stdexcept>
-#include <string>
-
-namespace irccd {
-
-namespace unicode {
-
-void encode(char32_t point, char res[5]) noexcept;
-void decode(char32_t &c, const char *res) noexcept;
-
-/**
- * Get the number of bytes for the first multi byte character from a
- * utf-8 string.
- *
- * This can be used to iterate a valid UTF-8 string to jump to the next
- * real character.
- *
- * @param c the first multi byte character
- * @return the number of bytes [1-4]
- */
-int nbytesUtf8(char c) noexcept;
-
-/**
- * Get the number of bytes for the unicode point.
- *
- * @param point the unicode point
- * @return the number of bytes [1-4] or -1 on invalid
- */
-int nbytesPoint(char32_t point) noexcept;
-
-/**
- * Get real number of character in a string.
- *
- * @param str the string
- * @return the length
- * @throw std::invalid_argument on invalid sequence
- */
-int length(const std::string &str);
-
-/**
- * Iterate over all real characters in the UTF-8 string.
- *
- * The function must have the following signature:
- *	void f(char ch)
- *
- * @param str the UTF-8 string
- * @throw std::invalid_argument on invalid sequence
- */
-template <typename Func>
-void forEach(const std::string &str, Func function)
-{
-	for (size_t i = 0; i < str.size(); ) {
-		char32_t point = 0;
-		int size = nbytesUtf8(str[i]);
-
-		if (size < 0) {
-			throw std::invalid_argument("invalid sequence");
-		}
-
-		decode(point, str.data() + i);
-		function(point);
-
-		i += size;
-	}
-}
-
-/**
- * Convert a UTF-32 string to UTF-8 string.
- *
- * @param array the UTF-32 string
- * @return the UTF-8 string
- * @throw std::invalid_argument on invalid sequence
- */
-std::string toUtf8(const std::u32string &array);
-
-/**
- * Convert a UTF-8 string to UTF-32 string.
- *
- * @param str the UTF-8 string
- * @return the UTF-32 string
- * @throw std::invalid_argument on invalid sequence
- */
-std::u32string toUtf32(const std::string &str);
-
-/**
- * Check if the unicode character is space.
- *
- * @param c the character
- * @return true if space
- */
-bool isspace(char32_t c) noexcept;
-
-/**
- * Check if the unicode character is digit.
- *
- * @param c the character
- * @return true if digit
- */
-bool isdigit(char32_t c) noexcept;
-
-/**
- * Check if the unicode character is alpha category.
- *
- * @param c the character
- * @return true if alpha
- */
-bool isalpha(char32_t c) noexcept;
-
-/**
- * Check if the unicode character is upper case.
- *
- * @param c the character
- * @return true if upper case
- */
-bool isupper(char32_t c) noexcept;
-
-/**
- * Check if the unicode character is lower case.
- *
- * @param c the character
- * @return true if lower case
- */
-bool islower(char32_t c) noexcept;
-
-/**
- * Check if the unicode character is title case.
- *
- * @param c the character
- * @return true if title case
- */
-bool istitle(char32_t c) noexcept;
-
-/**
- * Convert to upper case.
- *
- * @param c the character
- * @return the upper case character
- */
-char32_t toupper(char32_t c) noexcept;
-
-/**
- * Convert to lower case.
- *
- * @param c the character
- * @return the lower case character
- */
-char32_t tolower(char32_t c) noexcept;
-
-/**
- * Convert to title case.
- *
- * @param c the character
- * @return the title case character
- */
-char32_t totitle(char32_t c) noexcept;
-
-/**
- * Convert the UTF-32 string to upper case.
- *
- * @param str the str
- * @return the upper case string
- */
-inline std::u32string toupper(std::u32string str)
-{
-	for (size_t i = 0; i < str.size(); ++i) {
-		str[i] = toupper(str[i]);
-	}
-
-	return str;
-}
-
-/**
- * Convert the UTF-8 string to upper case.
- *
- * @param str the str
- * @return the upper case string
- * @warning very slow at the moment
- */
-inline std::string toupper(const std::string &str)
-{
-	return toUtf8(toupper(toUtf32(str)));
-}
-
-/**
- * Convert the UTF-32 string to lower case.
- *
- * @param str the str
- * @return the lower case string
- */
-inline std::u32string tolower(std::u32string str)
-{
-	for (size_t i = 0; i < str.size(); ++i) {
-		str[i] = tolower(str[i]);
-	}
-
-	return str;
-}
-
-/**
- * Convert the UTF-8 string to lower case.
- *
- * @param str the str
- * @return the lower case string
- * @warning very slow at the moment
- */
-inline std::string tolower(const std::string &str)
-{
-	return toUtf8(tolower(toUtf32(str)));
-}
-
-} // !unicode
-
-} // !irccd
-
-#endif // !IRCCD_UNICODE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/unicode.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,241 @@
+/*
+ * unicode.hpp -- UTF-8 to UTF-32 conversions and various operations
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_UNICODE_HPP
+#define IRCCD_UNICODE_HPP
+
+/**
+ * @file unicode.hpp
+ * @brief UTF-8 to UTF-32 conversions
+ */
+
+#include <stdexcept>
+#include <string>
+
+namespace irccd {
+
+namespace unicode {
+
+void encode(char32_t point, char res[5]) noexcept;
+void decode(char32_t &c, const char *res) noexcept;
+
+/**
+ * Get the number of bytes for the first multi byte character from a
+ * utf-8 string.
+ *
+ * This can be used to iterate a valid UTF-8 string to jump to the next
+ * real character.
+ *
+ * @param c the first multi byte character
+ * @return the number of bytes [1-4]
+ */
+int nbytesUtf8(char c) noexcept;
+
+/**
+ * Get the number of bytes for the unicode point.
+ *
+ * @param point the unicode point
+ * @return the number of bytes [1-4] or -1 on invalid
+ */
+int nbytesPoint(char32_t point) noexcept;
+
+/**
+ * Get real number of character in a string.
+ *
+ * @param str the string
+ * @return the length
+ * @throw std::invalid_argument on invalid sequence
+ */
+int length(const std::string &str);
+
+/**
+ * Iterate over all real characters in the UTF-8 string.
+ *
+ * The function must have the following signature:
+ *	void f(char ch)
+ *
+ * @param str the UTF-8 string
+ * @throw std::invalid_argument on invalid sequence
+ */
+template <typename Func>
+void forEach(const std::string &str, Func function)
+{
+	for (size_t i = 0; i < str.size(); ) {
+		char32_t point = 0;
+		int size = nbytesUtf8(str[i]);
+
+		if (size < 0) {
+			throw std::invalid_argument("invalid sequence");
+		}
+
+		decode(point, str.data() + i);
+		function(point);
+
+		i += size;
+	}
+}
+
+/**
+ * Convert a UTF-32 string to UTF-8 string.
+ *
+ * @param array the UTF-32 string
+ * @return the UTF-8 string
+ * @throw std::invalid_argument on invalid sequence
+ */
+std::string toUtf8(const std::u32string &array);
+
+/**
+ * Convert a UTF-8 string to UTF-32 string.
+ *
+ * @param str the UTF-8 string
+ * @return the UTF-32 string
+ * @throw std::invalid_argument on invalid sequence
+ */
+std::u32string toUtf32(const std::string &str);
+
+/**
+ * Check if the unicode character is space.
+ *
+ * @param c the character
+ * @return true if space
+ */
+bool isspace(char32_t c) noexcept;
+
+/**
+ * Check if the unicode character is digit.
+ *
+ * @param c the character
+ * @return true if digit
+ */
+bool isdigit(char32_t c) noexcept;
+
+/**
+ * Check if the unicode character is alpha category.
+ *
+ * @param c the character
+ * @return true if alpha
+ */
+bool isalpha(char32_t c) noexcept;
+
+/**
+ * Check if the unicode character is upper case.
+ *
+ * @param c the character
+ * @return true if upper case
+ */
+bool isupper(char32_t c) noexcept;
+
+/**
+ * Check if the unicode character is lower case.
+ *
+ * @param c the character
+ * @return true if lower case
+ */
+bool islower(char32_t c) noexcept;
+
+/**
+ * Check if the unicode character is title case.
+ *
+ * @param c the character
+ * @return true if title case
+ */
+bool istitle(char32_t c) noexcept;
+
+/**
+ * Convert to upper case.
+ *
+ * @param c the character
+ * @return the upper case character
+ */
+char32_t toupper(char32_t c) noexcept;
+
+/**
+ * Convert to lower case.
+ *
+ * @param c the character
+ * @return the lower case character
+ */
+char32_t tolower(char32_t c) noexcept;
+
+/**
+ * Convert to title case.
+ *
+ * @param c the character
+ * @return the title case character
+ */
+char32_t totitle(char32_t c) noexcept;
+
+/**
+ * Convert the UTF-32 string to upper case.
+ *
+ * @param str the str
+ * @return the upper case string
+ */
+inline std::u32string toupper(std::u32string str)
+{
+	for (size_t i = 0; i < str.size(); ++i) {
+		str[i] = toupper(str[i]);
+	}
+
+	return str;
+}
+
+/**
+ * Convert the UTF-8 string to upper case.
+ *
+ * @param str the str
+ * @return the upper case string
+ * @warning very slow at the moment
+ */
+inline std::string toupper(const std::string &str)
+{
+	return toUtf8(toupper(toUtf32(str)));
+}
+
+/**
+ * Convert the UTF-32 string to lower case.
+ *
+ * @param str the str
+ * @return the lower case string
+ */
+inline std::u32string tolower(std::u32string str)
+{
+	for (size_t i = 0; i < str.size(); ++i) {
+		str[i] = tolower(str[i]);
+	}
+
+	return str;
+}
+
+/**
+ * Convert the UTF-8 string to lower case.
+ *
+ * @param str the str
+ * @return the lower case string
+ * @warning very slow at the moment
+ */
+inline std::string tolower(const std::string &str)
+{
+	return toUtf8(tolower(toUtf32(str)));
+}
+
+} // !unicode
+
+} // !irccd
+
+#endif // !IRCCD_UNICODE_HPP
--- a/lib/irccd/util.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/lib/irccd/util.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -24,10 +24,10 @@
 #include <sstream>
 #include <stdexcept>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include "util.h"
-#include "unicode.h"
+#include "util.hpp"
+#include "unicode.hpp"
 
 using namespace std::string_literals;
 
--- a/lib/irccd/util.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * util.h -- some utilities
- *
- * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_UTIL_H
-#define IRCCD_UTIL_H
-
-/**
- * @file util.h
- * @brief Utilities.
- */
-
-#include <ctime>
-#include <initializer_list>
-#include <regex>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-namespace irccd {
-
-namespace util {
-
-/**
- * @enum MessageType
- * @brief Describe which type of message has been received
- *
- * On channels and queries, you may have a special command or a standard message depending on the
- * beginning of the message.
- *
- * Example: `!reminder help' may invoke the command event if a plugin reminder exists.
- */
-enum class MessageType {
-	Command,		//!< special command
-	Message			//!< standard message
-};
-
-/**
- * @brief Combine the type of message and its content.
- */
-using MessagePair = std::pair<std::string, MessageType>;
-
-/**
- * @class Substitution
- * @brief Used for format() function.
- */
-class Substitution {
-public:
-	/**
-	 * Fill that field if you want a date.
-	 */
-	std::time_t time{std::time(nullptr)};
-
-	/**
-	 * Fill that map if you want to replace keywords.
-	 */
-	std::unordered_map<std::string, std::string> keywords;
-};
-
-/**
- * Format a string and update all templates.
- *
- * ## Syntax
- *
- * The syntax is <strong>?{}</strong> where <strong>?</strong> is replaced by one of the token defined below. Braces
- * are mandatory and cannot be ommited.
- *
- * To write a literal template construct, prepend the token twice.
- *
- * ## Availables templates
- *
- * The following templates are available:
- *
- * - <strong>\#{name}</strong>: name will be substituted from the keywords in params,
- * - <strong>\${name}</strong>: name will be substituted from the environment variable,
- * - <strong>\@{attributes}</strong>: the attributes will be substituted to IRC colors (see below),
- * - <strong>%</strong>, any format accepted by strftime(3).
- *
- * ## Attributes
- *
- * The attribute format is composed of three parts, foreground, background and modifiers, each separated by a comma.
- *
- * **Note:** you cannot omit parameters, to specify the background, you must specify the foreground.
- *
- * ## Examples
- *
- * ### Valid constructs
- *
- *   - <strong>\#{target}, welcome</strong>: if target is set to "irccd", becomes "irccd, welcome",
- *   - <strong>\@{red}\#{target}</strong>: if target is specified, it is written in red,
- *
- * ### Invalid or literals constructs
- *
- *   - <strong>\#\#{target}</strong>: will output "\#{target}",
- *   - <strong>\#\#</strong>: will output "\#\#",
- *   - <strong>\#target</strong>: will output "\#target",
- *   - <strong>\#{target</strong>: will throw std::invalid_argument.
- *
- * ### Colors & attributes
- *
- *   - <strong>\@{red,blue}</strong>: will write text red on blue background,
- *   - <strong>\@{default,yellow}</strong>: will write default color text on yellow background,
- *   - <strong>\@{white,black,bold,underline}</strong>: will write white text on black in both bold and underline.
- */
-std::string format(std::string text, const Substitution &params = {});
-
-/**
- * Remove leading and trailing spaces.
- *
- * @param str the string
- * @return the removed white spaces
- */
-std::string strip(std::string str);
-
-/**
- * Split a string by delimiters.
- *
- * @param list the string to split
- * @param delimiters a list of delimiters
- * @param max max number of split
- * @return a list of string splitted
- */
-std::vector<std::string> split(const std::string &list, const std::string &delimiters, int max = -1);
-
-/**
- * Join values by a separator and return a string.
- *
- * @param first the first iterator
- * @param last the last iterator
- * @param delim the optional delimiter
- */
-template <typename InputIt, typename DelimType = char>
-std::string join(InputIt first, InputIt last, DelimType delim = ':')
-{
-	std::ostringstream oss;
-
-	if (first != last) {
-		oss << *first;
-
-		while (++first != last)
-			oss << delim << *first;
-	}
-
-	return oss.str();
-}
-
-/**
- * Convenient overload.
- *
- * @param list the initializer list
- * @param delim the delimiter
- * @return the string
- */
-template <typename T, typename DelimType = char>
-inline std::string join(std::initializer_list<T> list, DelimType delim = ':')
-{
-	return join(list.begin(), list.end(), delim);
-}
-
-/**
- * Parse IRC message and determine if it's a command or a simple message.
- *
- * @param message the message line
- * @param commandChar the command char (e.g '!')
- * @param plugin the plugin name
- * @return the pair
- */
-MessagePair parseMessage(std::string message, const std::string &commandChar, const std::string &plugin);
-
-/**
- * Server and identities must have strict names. This function can
- * be used to ensure that they are valid.
- *
- * @param name the identifier name
- * @return true if is valid
- */
-inline bool isIdentifierValid(const std::string &name)
-{
-	return std::regex_match(name, std::regex("[A-Za-z0-9-_]+"));
-}
-
-/**
- * Check if the value is a boolean, 1, yes and true are accepted.
- *
- * @param value the value
- * @return true if is boolean
- * @note this function is case-insensitive
- */
-bool isBoolean(std::string value) noexcept;
-
-/**
- * Check if the string is an integer.
- *
- * @param value the input
- * @param base the optional base
- * @return true if integer
- */
-bool isInt(const std::string &value, int base = 10) noexcept;
-
-/**
- * Check if the string is real.
- *
- * @param value the value
- * @return true if real
- */
-bool isReal(const std::string &value) noexcept;
-
-/**
- * Check if the string is a number.
- *
- * @param value the value
- * @return true if it is a number
- */
-inline bool isNumber(const std::string &value) noexcept
-{
-	return isInt(value) || isReal(value);
-}
-
-/**
- * Parse a network message from an input buffer and remove it from it.
- *
- * @param input the buffer, will be updated
- * @return the message or empty string if there is nothing
- */
-std::string nextNetwork(std::string &input);
-
-} // !util
-
-} // !irccd
-
-#endif // !IRCCD_UTIL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/util.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,246 @@
+/*
+ * util.hpp -- some utilities
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_UTIL_HPP
+#define IRCCD_UTIL_HPP
+
+/**
+ * @file util.hpp
+ * @brief Utilities.
+ */
+
+#include <ctime>
+#include <initializer_list>
+#include <regex>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace irccd {
+
+namespace util {
+
+/**
+ * @enum MessageType
+ * @brief Describe which type of message has been received
+ *
+ * On channels and queries, you may have a special command or a standard message depending on the
+ * beginning of the message.
+ *
+ * Example: `!reminder help' may invoke the command event if a plugin reminder exists.
+ */
+enum class MessageType {
+	Command,		//!< special command
+	Message			//!< standard message
+};
+
+/**
+ * @brief Combine the type of message and its content.
+ */
+using MessagePair = std::pair<std::string, MessageType>;
+
+/**
+ * @class Substitution
+ * @brief Used for format() function.
+ */
+class Substitution {
+public:
+	/**
+	 * Fill that field if you want a date.
+	 */
+	std::time_t time{std::time(nullptr)};
+
+	/**
+	 * Fill that map if you want to replace keywords.
+	 */
+	std::unordered_map<std::string, std::string> keywords;
+};
+
+/**
+ * Format a string and update all templates.
+ *
+ * ## Syntax
+ *
+ * The syntax is <strong>?{}</strong> where <strong>?</strong> is replaced by one of the token defined below. Braces
+ * are mandatory and cannot be ommited.
+ *
+ * To write a literal template construct, prepend the token twice.
+ *
+ * ## Availables templates
+ *
+ * The following templates are available:
+ *
+ * - <strong>\#{name}</strong>: name will be substituted from the keywords in params,
+ * - <strong>\${name}</strong>: name will be substituted from the environment variable,
+ * - <strong>\@{attributes}</strong>: the attributes will be substituted to IRC colors (see below),
+ * - <strong>%</strong>, any format accepted by strftime(3).
+ *
+ * ## Attributes
+ *
+ * The attribute format is composed of three parts, foreground, background and modifiers, each separated by a comma.
+ *
+ * **Note:** you cannot omit parameters, to specify the background, you must specify the foreground.
+ *
+ * ## Examples
+ *
+ * ### Valid constructs
+ *
+ *   - <strong>\#{target}, welcome</strong>: if target is set to "irccd", becomes "irccd, welcome",
+ *   - <strong>\@{red}\#{target}</strong>: if target is specified, it is written in red,
+ *
+ * ### Invalid or literals constructs
+ *
+ *   - <strong>\#\#{target}</strong>: will output "\#{target}",
+ *   - <strong>\#\#</strong>: will output "\#\#",
+ *   - <strong>\#target</strong>: will output "\#target",
+ *   - <strong>\#{target</strong>: will throw std::invalid_argument.
+ *
+ * ### Colors & attributes
+ *
+ *   - <strong>\@{red,blue}</strong>: will write text red on blue background,
+ *   - <strong>\@{default,yellow}</strong>: will write default color text on yellow background,
+ *   - <strong>\@{white,black,bold,underline}</strong>: will write white text on black in both bold and underline.
+ */
+std::string format(std::string text, const Substitution &params = {});
+
+/**
+ * Remove leading and trailing spaces.
+ *
+ * @param str the string
+ * @return the removed white spaces
+ */
+std::string strip(std::string str);
+
+/**
+ * Split a string by delimiters.
+ *
+ * @param list the string to split
+ * @param delimiters a list of delimiters
+ * @param max max number of split
+ * @return a list of string splitted
+ */
+std::vector<std::string> split(const std::string &list, const std::string &delimiters, int max = -1);
+
+/**
+ * Join values by a separator and return a string.
+ *
+ * @param first the first iterator
+ * @param last the last iterator
+ * @param delim the optional delimiter
+ */
+template <typename InputIt, typename DelimType = char>
+std::string join(InputIt first, InputIt last, DelimType delim = ':')
+{
+	std::ostringstream oss;
+
+	if (first != last) {
+		oss << *first;
+
+		while (++first != last)
+			oss << delim << *first;
+	}
+
+	return oss.str();
+}
+
+/**
+ * Convenient overload.
+ *
+ * @param list the initializer list
+ * @param delim the delimiter
+ * @return the string
+ */
+template <typename T, typename DelimType = char>
+inline std::string join(std::initializer_list<T> list, DelimType delim = ':')
+{
+	return join(list.begin(), list.end(), delim);
+}
+
+/**
+ * Parse IRC message and determine if it's a command or a simple message.
+ *
+ * @param message the message line
+ * @param commandChar the command char (e.g '!')
+ * @param plugin the plugin name
+ * @return the pair
+ */
+MessagePair parseMessage(std::string message, const std::string &commandChar, const std::string &plugin);
+
+/**
+ * Server and identities must have strict names. This function can
+ * be used to ensure that they are valid.
+ *
+ * @param name the identifier name
+ * @return true if is valid
+ */
+inline bool isIdentifierValid(const std::string &name)
+{
+	return std::regex_match(name, std::regex("[A-Za-z0-9-_]+"));
+}
+
+/**
+ * Check if the value is a boolean, 1, yes and true are accepted.
+ *
+ * @param value the value
+ * @return true if is boolean
+ * @note this function is case-insensitive
+ */
+bool isBoolean(std::string value) noexcept;
+
+/**
+ * Check if the string is an integer.
+ *
+ * @param value the input
+ * @param base the optional base
+ * @return true if integer
+ */
+bool isInt(const std::string &value, int base = 10) noexcept;
+
+/**
+ * Check if the string is real.
+ *
+ * @param value the value
+ * @return true if real
+ */
+bool isReal(const std::string &value) noexcept;
+
+/**
+ * Check if the string is a number.
+ *
+ * @param value the value
+ * @return true if it is a number
+ */
+inline bool isNumber(const std::string &value) noexcept
+{
+	return isInt(value) || isReal(value);
+}
+
+/**
+ * Parse a network message from an input buffer and remove it from it.
+ *
+ * @param input the buffer, will be updated
+ * @return the message or empty string if there is nothing
+ */
+std::string nextNetwork(std::string &input);
+
+} // !util
+
+} // !irccd
+
+#endif // !IRCCD_UTIL_HPP
--- a/lib/irccd/xdg.h	Tue Apr 19 10:17:52 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * xdg.h -- XDG directory specifications
- *
- * Copyright (c) 2013, 2014, 2015 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_XDG_H
-#define IRCCD_XDG_H
-
-/**
- * @file xdg.h
- * @brief Read XDG standard specifications
- */
-
-#include <vector>
-#include <string>
-
-namespace irccd {
-
-/**
- * @class Xdg
- * @brief XDG specifications
- *
- * Read and get XDG directories. This file contains exports thingies so it can
- * compiles successfully on Windows but its usage is discouraged.
- */
-class Xdg {
-public:
-	/**
-	 * list of directories.
-	 */
-	using List	= std::vector<std::string>;
-
-private:
-	std::string	m_configHome;
-	std::string	m_dataHome;
-	std::string	m_cacheHome;
-	std::string	m_runtimeDir;
-	List		m_configDirs;
-	List		m_dataDirs;
-
-public:
-	/**
-	 * Open an xdg instance and load directories.
-	 *
-	 * @throw std::runtime_error on failures
-	 */
-	Xdg();
-
-	/**
-	 * Get the config directory. ${XDG_CONFIG_HOME} or ${HOME}/.config
-	 *
-	 * @return the config directory
-	 */
-	const std::string &configHome() const noexcept;
-
-	/**
-	 * Get the data directory. ${XDG_DATA_HOME} or ${HOME}/.local/share
-	 *
-	 * @return the data directory
-	 */
-	const std::string &dataHome() const noexcept;
-
-	/**
-	 * Get the cache directory. ${XDG_CACHE_HOME} or ${HOME}/.cache
-	 *
-	 * @return the cache directory
-	 */
-	const std::string &cacheHome() const noexcept;
-
-	/**
-	 * Get the runtime directory. ${XDG_RUNTIME_DIR} must be set,
-	 * if not, it throws an exception.
-	 *
-	 * The XDG standard says that application should handle XDG_RUNTIME_DIR by
-	 * themselves.
-	 *
-	 * @return the runtime directory
-	 * @throw std::runtime_error on error
-	 */
-	const std::string &runtimeDir() const;
-
-	/**
-	 * Get the standard config directories. ${XDG_CONFIG_DIRS} or { "/etc/xdg" }
-	 *
-	 * @return the list of config directories
-	 */
-	const List &configDirs() const noexcept;
-
-	/**
-	 * Get the data directories. ${XDG_DATA_DIRS} or { "/usr/local/share", "/usr/share" }
-	 *
-	 * @return the list of data directories
-	 */
-	const List &dataDirs() const noexcept;
-};
-
-} // !irccd
-
-#endif // !IRCCD_XDG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/irccd/xdg.hpp	Wed Apr 20 19:45:00 2016 +0200
@@ -0,0 +1,112 @@
+/*
+ * xdg.h -- XDG directory specifications
+ *
+ * Copyright (c) 2013, 2014, 2015 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_XDG_H
+#define IRCCD_XDG_H
+
+/**
+ * @file xdg.h
+ * @brief Read XDG standard specifications
+ */
+
+#include <vector>
+#include <string>
+
+namespace irccd {
+
+/**
+ * @class Xdg
+ * @brief XDG specifications
+ *
+ * Read and get XDG directories. This file contains exports thingies so it can
+ * compiles successfully on Windows but its usage is discouraged.
+ */
+class Xdg {
+public:
+	/**
+	 * list of directories.
+	 */
+	using List	= std::vector<std::string>;
+
+private:
+	std::string	m_configHome;
+	std::string	m_dataHome;
+	std::string	m_cacheHome;
+	std::string	m_runtimeDir;
+	List		m_configDirs;
+	List		m_dataDirs;
+
+public:
+	/**
+	 * Open an xdg instance and load directories.
+	 *
+	 * @throw std::runtime_error on failures
+	 */
+	Xdg();
+
+	/**
+	 * Get the config directory. ${XDG_CONFIG_HOME} or ${HOME}/.config
+	 *
+	 * @return the config directory
+	 */
+	const std::string &configHome() const noexcept;
+
+	/**
+	 * Get the data directory. ${XDG_DATA_HOME} or ${HOME}/.local/share
+	 *
+	 * @return the data directory
+	 */
+	const std::string &dataHome() const noexcept;
+
+	/**
+	 * Get the cache directory. ${XDG_CACHE_HOME} or ${HOME}/.cache
+	 *
+	 * @return the cache directory
+	 */
+	const std::string &cacheHome() const noexcept;
+
+	/**
+	 * Get the runtime directory. ${XDG_RUNTIME_DIR} must be set,
+	 * if not, it throws an exception.
+	 *
+	 * The XDG standard says that application should handle XDG_RUNTIME_DIR by
+	 * themselves.
+	 *
+	 * @return the runtime directory
+	 * @throw std::runtime_error on error
+	 */
+	const std::string &runtimeDir() const;
+
+	/**
+	 * Get the standard config directories. ${XDG_CONFIG_DIRS} or { "/etc/xdg" }
+	 *
+	 * @return the list of config directories
+	 */
+	const List &configDirs() const noexcept;
+
+	/**
+	 * Get the data directories. ${XDG_DATA_DIRS} or { "/usr/local/share", "/usr/share" }
+	 *
+	 * @return the list of data directories
+	 */
+	const List &dataDirs() const noexcept;
+};
+
+} // !irccd
+
+#endif // !IRCCD_XDG_H
--- a/tests/elapsedtimer/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/elapsedtimer/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -20,7 +20,7 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/elapsed-timer.h>
+#include <irccd/elapsed-timer.hpp>
 
 using namespace irccd;
 using namespace std::chrono_literals;
--- a/tests/js-elapsedtimer/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-elapsedtimer/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -20,8 +20,8 @@
 
 #include <thread>
 
-#include <irccd/js-irccd.h>
-#include <irccd/js-elapsed-timer.h>
+#include <irccd/js-irccd.hpp>
+#include <irccd/js-elapsed-timer.hpp>
 
 using namespace irccd;
 using namespace std::chrono_literals;
--- a/tests/js-file/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-file/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -20,8 +20,8 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/js-file.h>
-#include <irccd/js-irccd.h>
+#include <irccd/js-file.hpp>
+#include <irccd/js-irccd.hpp>
 
 using namespace irccd;
 
--- a/tests/js-irccd/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-irccd/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,10 +18,10 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include <irccd/js-irccd.h>
-#include <irccd/logger.h>
+#include <irccd/js-irccd.hpp>
+#include <irccd/logger.hpp>
 
 using namespace irccd;
 
--- a/tests/js-logger/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-logger/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,11 +18,11 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include <irccd/js-irccd.h>
-#include <irccd/js-logger.h>
-#include <irccd/logger.h>
+#include <irccd/js-irccd.hpp>
+#include <irccd/js-logger.hpp>
+#include <irccd/logger.hpp>
 
 using namespace irccd;
 
--- a/tests/js-system/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-system/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,9 +18,9 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/js-irccd.h>
-#include <irccd/js-system.h>
-#include <irccd/system.h>
+#include <irccd/js-irccd.hpp>
+#include <irccd/js-system.hpp>
+#include <irccd/system.hpp>
 
 using namespace irccd;
 
--- a/tests/js-timer/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-timer/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,9 +18,9 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/elapsed-timer.h>
-#include <irccd/irccd.h>
-#include <irccd/system.h>
+#include <irccd/elapsed-timer.hpp>
+#include <irccd/irccd.hpp>
+#include <irccd/system.hpp>
 
 using namespace irccd;
 
--- a/tests/js-unicode/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-unicode/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -22,8 +22,8 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/js-irccd.h>
-#include <irccd/js-unicode.h>
+#include <irccd/js-irccd.hpp>
+#include <irccd/js-unicode.hpp>
 
 using namespace irccd;
 
--- a/tests/js-util/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/js-util/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,8 +18,8 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/js-irccd.h>
-#include <irccd/js-util.h>
+#include <irccd/js-irccd.hpp>
+#include <irccd/js-util.hpp>
 
 using namespace irccd;
 
--- a/tests/path/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/path/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,10 +18,10 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/sysconfig.h>
+#include <irccd/sysconfig.hpp>
 
-#include <irccd/logger.h>
-#include <irccd/path.h>
+#include <irccd/logger.hpp>
+#include <irccd/path.hpp>
 
 namespace irccd {
 
--- a/tests/rules/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/rules/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,7 +18,7 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/rule.h>
+#include <irccd/rule.hpp>
 
 namespace irccd {
 
--- a/tests/timer/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/timer/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,8 +18,8 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/elapsed-timer.h>
-#include <irccd/timer.h>
+#include <irccd/elapsed-timer.hpp>
+#include <irccd/timer.hpp>
 
 using namespace irccd;
 using namespace std::chrono_literals;
--- a/tests/util/main.cpp	Tue Apr 19 10:17:52 2016 +0200
+++ b/tests/util/main.cpp	Wed Apr 20 19:45:00 2016 +0200
@@ -18,8 +18,8 @@
 
 #include <gtest/gtest.h>
 
-#include <irccd/util.h>
-#include <irccd/system.h>
+#include <irccd/util.hpp>
+#include <irccd/system.hpp>
 
 namespace irccd {