changeset 4:c12262a01559

Docs: remove specifications from main repository Task: #436
author David Demelier <markand@malikania.fr>
date Tue, 22 Mar 2016 23:02:56 +0100
parents 67edc8b3e5e9
children 83db85eb4de9
files CMakeLists.txt cmake/MalikaniaFunctions.cmake cmake/MalikaniaOptions.cmake docs/CMakeLists.txt docs/Colors.txt docs/UML/CMakeLists.txt docs/UML/client/CMakeLists.txt docs/UML/client/Rendering.txt docs/UML/client/States.txt docs/UML/database/Accounts.txt docs/UML/database/Builds.txt docs/UML/database/CMakeLists.txt docs/UML/database/Inventory.txt docs/books/CMakeLists.txt docs/books/conventions/CMakeLists.txt docs/books/conventions/Conventions.txt docs/books/developer/CMakeLists.txt docs/books/developer/Developer.txt docs/books/mercurial/CMakeLists.txt docs/books/mercurial/Mercurial.txt docs/books/mercurial/images/Add-context.png docs/books/mercurial/images/Add-window.png docs/books/mercurial/images/Clone.png docs/books/mercurial/images/Commit-context.png docs/books/mercurial/images/Commit-window.png docs/books/mercurial/images/Diff-context.png docs/books/mercurial/images/Diff-window.png docs/books/mercurial/images/Merge-context.png docs/books/mercurial/images/Pull-context.png docs/books/mercurial/images/Pull-window.png docs/books/mercurial/images/Push-context.png docs/books/mercurial/images/Push-window.png docs/books/mercurial/images/Remove-context.png docs/books/mercurial/images/Remove-window.png docs/books/mercurial/images/Update-context.png docs/books/mercurial/images/Update-window.png docs/books/specifications/Architecture/Intro.txt docs/books/specifications/Architecture/Technologies.txt docs/books/specifications/Bundle/Format.txt docs/books/specifications/Bundle/Intro.txt docs/books/specifications/Bundle/Usage.txt docs/books/specifications/CMakeLists.txt docs/books/specifications/GameData/Animations.txt docs/books/specifications/GameData/Game.txt docs/books/specifications/GameData/Intro.txt docs/books/specifications/GameData/Manifest.txt docs/books/specifications/GameData/Sprites.txt docs/books/specifications/GameData/images/format.png docs/books/specifications/Gameplay/Intro.txt docs/books/specifications/Gameplay/Stats.txt docs/books/specifications/Intro.txt docs/books/specifications/Network/Commands.txt docs/books/specifications/Network/Commands/account-create.txt docs/books/specifications/Network/Commands/account-identify.txt docs/books/specifications/Network/Commands/character-create.txt docs/books/specifications/Network/Commands/character-delete.txt docs/books/specifications/Network/Commands/character-list.txt docs/books/specifications/Network/Commands/character-select.txt docs/books/specifications/Network/Commands/exchange-add.txt docs/books/specifications/Network/Commands/exchange-start.txt docs/books/specifications/Network/Intro.txt docs/books/specifications/Network/Messages.txt docs/books/specifications/Network/Messages/server-info.txt docs/books/specifications/Network/Messages/server-message.txt docs/books/specifications/Overview/Intro.txt docs/books/specifications/Tools/Intro.txt docs/books/specifications/Tools/Malikania-bundle.txt docs/books/specifications/Tools/Malikania-vm.txt libcommon/malikania/Socket.cpp libcommon/malikania/SocketAddress.cpp libcommon/malikania/SocketListener.cpp libcommon/malikania/SocketSsl.cpp libcommon/malikania/SocketTcp.cpp libcommon/malikania/Sockets.cpp libcommon/malikania/Sockets.h libserver/CMakeLists.txt libserver/malikania/Server.cpp libserver/malikania/Server.h libserver/malikania/ServerApp.cpp libserver/malikania/ServerApp.h
diffstat 80 files changed, 31 insertions(+), 8669 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ b/CMakeLists.txt	Tue Mar 22 23:02:56 2016 +0100
@@ -59,6 +59,4 @@
 message("      Release flags:   ${CMAKE_CXX_FLAGS_RELEASE}")
 message("")
 message("Documentation:")
-message("      UML diagrams:    ${WITH_DOCS_UML_MSG}")
 message("      Doxygen:         ${WITH_DOCS_DOXYGEN_MSG}")
-message("      Books:           ${WITH_DOCS_BOOKS_MSG}")
--- a/cmake/MalikaniaFunctions.cmake	Tue Mar 22 22:50:35 2016 +0100
+++ b/cmake/MalikaniaFunctions.cmake	Tue Mar 22 23:02:56 2016 +0100
@@ -21,28 +21,6 @@
 # ---------------------------------------------------------
 # The following macros are available:
 #
-# malikania_generate_book
-# -----------------------
-#
-# malikania_generate_book(
-#	name			The target name (book-${name})
-#	output			The output file name
-#	sources			The sources files, kept in order
-# )
-#
-# Generate a book using pandoc.
-#
-# malikania_generate_uml
-# ----------------------
-#
-# malikania_generate_uml(
-#	NAME			The target name
-#	DIRECTORY		Output directory (relative to docs_BINARY_DIR)
-#	SOURCES			The sources files
-# )
-#
-# Generate a target uml-${NAME} with all ${SOURCES} specified to be processed by plantuml.
-#
 # malikania_define_executable
 # ---------------------------
 #
@@ -183,38 +161,6 @@
 	apply_flags(${LIB_TARGET} LIB_FLAGS)
 endfunction()
 
-function(malikania_generate_uml)
-	set(options "")
-	set(oneValueArgs NAME DIRECTORY)
-	set(multiValueArgs SOURCES)
-
-	cmake_parse_arguments(UML "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
-	foreach (f ${UML_SOURCES})
-		get_filename_component(filename ${f} NAME_WE)
-
-		list(APPEND outputs ${docs_BINARY_DIR}/uml/${filename}.png)
-
-		add_custom_command(
-			OUTPUT ${docs_BINARY_DIR}/uml/${filename}.png
-			DEPENDS ${f}
-			COMMAND
-				${CMAKE_COMMAND} -E make_directory ${docs_BINARY_DIR}/uml
-			COMMAND
-				${Java_JAVA_EXECUTABLE} -jar ${PLANTUML_JAR} ${f} -o ${docs_BINARY_DIR}/uml
-			VERBATIM
-		)
-	endforeach ()
-
-	add_custom_target(
-		docs-uml-${UML_NAME}
-		DEPENDS ${outputs}
-		SOURCES ${UML_SOURCES}
-	)
-
-	add_dependencies(docs-uml docs-uml-${UML_NAME})
-endfunction()
-
 function(malikania_create_test)
 	set(singleArgs NAME)
 	set(multiArgs LIBRARIES SOURCES RESOURCES)
@@ -273,22 +219,6 @@
 	add_dependencies(tests test-${TEST_NAME})
 endfunction()
 
-function(malikania_generate_book name output sources)
-	pandoc(
-		TARGET docs-book-${name}
-		SOURCES ${sources}
-		OUTPUT ${docs_BINARY_DIR}/books/${output}
-		FROM markdown
-		TO latex
-		TOC
-		STANDALONE
-		MAKE_DIRECTORY
-		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-	)
-
-	add_dependencies(docs-books docs-book-${name})
-endfunction()
-
 macro(setg var value)
 	set(${var} ${value} CACHE INTERNAL "" FORCE)
 endmacro()
--- a/cmake/MalikaniaOptions.cmake	Tue Mar 22 22:50:35 2016 +0100
+++ b/cmake/MalikaniaOptions.cmake	Tue Mar 22 23:02:56 2016 +0100
@@ -33,20 +33,14 @@
 #
 # The following options are available:
 #    WITH_DOCS			- Disable or enable all docs, if set to Off, disable all documentation.
-#    WITH_DOCS_UML		- Enable UML diagram generation.
-#    WITH_DOCS_DOXYGEN		- Enable doxygen
-#    WITH_DOCS_BOOKS		- Enable build of books
+#    WITH_DOXYGEN		- Enable doxygen
 #
 
 option(WITH_DOCS "Build all documentation" On)
-option(WITH_DOCS_UML "Enable UML diagrams generation" On)
-option(WITH_DOCS_DOXYGEN "Enable doxygen generation" On)
-option(WITH_DOCS_BOOKS "Enable build of books" On)
+option(WITH_DOXYGEN "Enable doxygen generation" On)
 
 if (NOT WITH_DOCS)
-	set(WITH_DOCS_UML Off)
-	set(WITH_DOCS_DOXYGEN Off)
-	set(WITH_DOCS_BOOKS Off)
+	set(WITH_DOXYGEN Off)
 endif ()
 
 #
--- a/docs/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ b/docs/CMakeLists.txt	Tue Mar 22 23:02:56 2016 +0100
@@ -32,67 +32,16 @@
 find_package(Doxygen)
 
 if (DOXYGEN_FOUND)
-	if (WITH_DOCS_DOXYGEN)
-		setg(WITH_DOCS_DOXYGEN_MSG "Yes")
+	if (WITH_DOXYGEN)
+		setg(WITH_DOXYGEN_MSG "Yes")
 	else ()
-		setg(WITH_DOCS_DOXYGEN_MSG "No (disabled by user)")
+		setg(WITH_DOXYGEN_MSG "No (disabled by user)")
 	endif ()
 else ()
-	setg(WITH_DOCS_DOXYGEN_MSG "No (doxygen not found)")
-	setg(WITH_DOCS_DOXYGEN Off)
-endif ()
-
-if (WITH_DOCS_DOXYGEN)
-	add_subdirectory(doxygen)
+	setg(WITH_DOXYGEN_MSG "No (doxygen not found)")
+	setg(WITH_DOXYGEN Off)
 endif ()
 
-#
-# UML generation with plantuml.
-# -------------------------------------------------------------------
-#
-
-find_package(Java COMPONENTS Runtime)
-
-if (Java_JAVA_EXECUTABLE AND DOXYGEN_DOT_EXECUTABLE)
-	if (WITH_DOCS_UML)
-		setg(WITH_DOCS_UML_MSG "Yes")
-	else ()
-		setg(WITH_DOCS_UML_MSG "No (disabled by user)")
-	endif ()
-elseif (NOT Java_JAVA_EXECUTABLE)
-	setg(WITH_DOCS_UML_MSG "No (Java not found)")
-	setg(WITH_DOCS_UML Off)
-elseif (NOT DOXYGEN_DOT_EXECUTABLE)
-	setg(WITH_DOCS_UML_MSG "No (dot not found)")
-	setg(WITH_DOCS_UML Off)
-endif ()
-
-if (WITH_DOCS_UML)
-	add_subdirectory(UML)
+if (WITH_DOXYGEN)
+	add_subdirectory(doxygen)
 endif ()
-
-#
-# Books, specifications, docs generation.
-# -------------------------------------------------------------------
-#
-
-find_package(Pandoc)
-find_package(LATEX)
-
-if (Pandoc_FOUND AND (PDFLATEX_COMPILER OR LATEX_COMPILER OR BIBTEX_COMPILER OR MAKEINDEX_COMPILER))
-	if (WITH_DOCS_BOOKS)
-		setg(WITH_DOCS_BOOKS_MSG "Yes")
-	else ()
-		setg(WITH_DOCS_BOOKS_MSG "No (disabled by user)")
-	endif ()
-elseif (NOT Pandoc_FOUND)
-	setg(WITH_DOCS_BOOKS_MSG "No (pandoc not found)")
-	setg(WITH_DOCS_BOOKS Off)
-elseif (NOT PDFLATEX_COMPILER)
-	setg(WITH_DOCS_BOOKS_MSG "No (pdflatex not found)")
-	setg(WITH_DOCS_BOOKS Off)
-endif ()
-
-if (WITH_DOCS_BOOKS)
-	add_subdirectory(books)
-endif ()
--- a/docs/Colors.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-Official colors scheme for any Malikania art.
-
-#####  Color Palette by Paletton.com
-#####  Palette URL: http://paletton.com/#uid=7030u0kiZsx93KzekyUn2oOqMk4
-
-*** Primary color:
-
-   shade 0 = #E3665C = rgb(227,102, 92) = rgba(227,102, 92,1) = rgb0(0.89,0.4,0.361)
-   shade 1 = #FFBCB7 = rgb(255,188,183) = rgba(255,188,183,1) = rgb0(1,0.737,0.718)
-   shade 2 = #FF958D = rgb(255,149,141) = rgba(255,149,141,1) = rgb0(1,0.584,0.553)
-   shade 3 = #C64237 = rgb(198, 66, 55) = rgba(198, 66, 55,1) = rgb0(0.776,0.259,0.216)
-   shade 4 = #A0241A = rgb(160, 36, 26) = rgba(160, 36, 26,1) = rgb0(0.627,0.141,0.102)
-
-*** Secondary color (1):
-
-   shade 0 = #E39D5C = rgb(227,157, 92) = rgba(227,157, 92,1) = rgb0(0.89,0.616,0.361)
-   shade 1 = #FFD9B7 = rgb(255,217,183) = rgba(255,217,183,1) = rgb0(1,0.851,0.718)
-   shade 2 = #FFC48D = rgb(255,196,141) = rgba(255,196,141,1) = rgb0(1,0.769,0.553)
-   shade 3 = #C67C37 = rgb(198,124, 55) = rgba(198,124, 55,1) = rgb0(0.776,0.486,0.216)
-   shade 4 = #A05A1A = rgb(160, 90, 26) = rgba(160, 90, 26,1) = rgb0(0.627,0.353,0.102)
-
-*** Secondary color (2):
-
-   shade 0 = #3A818B = rgb( 58,129,139) = rgba( 58,129,139,1) = rgb0(0.227,0.506,0.545)
-   shade 1 = #94C5CC = rgb(148,197,204) = rgba(148,197,204,1) = rgb0(0.58,0.773,0.8)
-   shade 2 = #5D9CA5 = rgb( 93,156,165) = rgba( 93,156,165,1) = rgb0(0.365,0.612,0.647)
-   shade 3 = #236F79 = rgb( 35,111,121) = rgba( 35,111,121,1) = rgb0(0.137,0.435,0.475)
-   shade 4 = #115862 = rgb( 17, 88, 98) = rgba( 17, 88, 98,1) = rgb0(0.067,0.345,0.384)
-
-*** Complement color:
-
-   shade 0 = #47AE59 = rgb( 71,174, 89) = rgba( 71,174, 89,1) = rgb0(0.278,0.682,0.349)
-   shade 1 = #A1E0AC = rgb(161,224,172) = rgba(161,224,172,1) = rgb0(0.631,0.878,0.675)
-   shade 2 = #6FC97E = rgb(111,201,126) = rgba(111,201,126,1) = rgb0(0.435,0.788,0.494)
-   shade 3 = #2A973D = rgb( 42,151, 61) = rgba( 42,151, 61,1) = rgb0(0.165,0.592,0.239)
-   shade 4 = #147A26 = rgb( 20,122, 38) = rgba( 20,122, 38,1) = rgb0(0.078,0.478,0.149)
-
-
-#####  Generated by Paletton.com (c) 2002-2014
--- a/docs/UML/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-project(UML)
-
-add_custom_target(docs-uml COMMENT "UML diagram generation")
-
-add_dependencies(docs docs-uml)
-
-add_subdirectory(database)
-add_subdirectory(client)
--- a/docs/UML/client/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-project(client)
-
-set(
-	FILES
-	${client_SOURCE_DIR}/States.txt
-	${client_SOURCE_DIR}/Rendering.txt
-)
-
-malikania_generate_uml(
-	NAME client
-	DIRECTORY client
-	SOURCES ${FILES}
-)
-
--- a/docs/UML/client/Rendering.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-'
-' Rendering.txt -- rendering
-'
-' Copyright (c) 2013, 2014 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.
-'
-
-@startuml
-
-class Screen {
-	+Screen(width, height, title)
-	+setFullscreen(mode: bool)
-	+width() const: int
-	+height() const: int
-	+isOpen() const: bool
-}
-
-class Renderer {
-	+drawPoint(point, color)
-	+drawPoints(points, color)
-	+drawLine(line, color)
-	+drawLines(lines, color)
-	+drawCircle(circle, color)
-	+drawCircles(circles, color)
-	+clear()
-	+present()
-}
-
-class Image {
-	+Image(path)
-	+width() const
-	+height() const
-	+draw(x: int, y: int)
-}
-
-class Sprite {
-	+Sprite(path)
-	+width() const: int
-	+height() const: int
-	+spacingX() const: int
-	+spacingY() const: int
-	+marginX() const: int
-	+marginY() const: int
-	+cellWidth() const: int
-	+cellHeight() const: int
-	+cellCount() const: int
-	+draw(index: int)
-}
-
-class Animation {
-	+Animation(path)
-	+sprite(): const Sprite &
-}
-
-class Animator {
-	+Animator(sprite: const Sprite &)
-	+update()
-	+draw(x: int, y: int)
-}
-
-Animation -- "1" Sprite: m_sprite
-Animator -- "1" Animation: m_animation
-Sprite -- "1" Image: m_image
-
-note right of Image : Each implementation has its appropriate source file, for example Image.h and Image_android.cpp, Image_sdl.cpp.
-
-skinparam defaultFontName DejaVu Sans Mono
-skinparam defaultFontSize 10
-
-skinparam classBorderColor #236F79
-skinparam classBackgroundColor #5D9CA5
-skinparam classArrowColor #236F79
-
-@enduml
--- a/docs/UML/client/States.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-'
-' States.txt -- different default client states
-'
-' Copyright (c) 2013, 2014 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.
-'
-
-@startuml
-
-[*] --> Loading
-Loading --> Login
-Login --> Connecting
-Connecting --> Downloading
-Connecting --> LoadingMap
-LoadingMap --> Running
-Downloading --> Running
-Running --> LoadingBattle
-LoadingBattle --> Battle
-Battle --> EndBattle
-
-Loading : Loading game resources
-Login : Waiting for user input for connecting
-Connecting : Waiting for connection to the server
-LoadingMap : Loading the map
-Downloading : Downloading updates locally
-Running : In game map
-LoadingBattle : State before a battle starts (useful for animations)
-Battle : In game battle
-EndBattle : When a battle has finished
-
-skinparam defaultFontName DejaVu Sans Mono
-skinparam defaultFontSize 10
-
-skinparam stateBorderColor #236F79
-skinparam stateBackgroundColor #5D9CA5
-skinparam stateArrowColor #236F79
-
-@enduml
--- a/docs/UML/database/Accounts.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-'
-' Accounts.txt -- database diagram for accounts
-'
-' Copyright (c) 2013, 2014 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.
-'
-
-@startuml
-
-class account {
-	ac_id: int
-	ac_name: varchar [32]
-	ac_email: varchar [128]
-	ac_firstname: varchar [32]
-	ac_lastname: varchar [32]
-	ac_salt: varchar [8]
-	ac_password: varchar [256]
-	ac_joindate: date
-}
-
-class log_history {
-	log_id : int
-	log_ac_id : int #
-}
-
-class log_history_item {
-	lhi_id : int
-	lhi_log_id : int #
-	lhi_status : enum
-	lhi_date : time
-}
-
-class character {
-	ch_id : int
-	ch_ac_id : int #
-	ch_class : varchar [32]
-	ch_createdate : date
-}
-
-class status {
-	st_id : int
-	st_status : enum
-	st_hp : int
-	st_mp : int	
-}
-
-class points {
-	pt_id : int
-	pt_st_id : int #
-	pt_avail : int16_t
-	pt_force : int16_t
-	pt_defense : int16_t
-	pt_agility : int16_t
-}
-
-hide account methods
-hide log_history methods
-hide log_history_item methods
-hide character methods
-hide status methods
-hide points methods
-
-account "1" -- "1" log_history
-account "1" -- "0..8" character
-character "1" -- "1" status
-log_history "1" -- "0..*" log_history_item
-status "1" -- "1" points
-
-skinparam defaultFontName DejaVu Sans Mono
-skinparam defaultFontSize 10
-
-skinparam classBorderColor #C67C37
-skinparam classBackgroundColor FFC48D
-skinparam classArrowColor #C67C37
-
-@enduml
--- a/docs/UML/database/Builds.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-'
-' Buildings.txt -- database diagram for in game buildings
-'
-' Copyright (c) 2013, 2014 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.
-'
-
-@startuml
-
-class build {
-	bd_id : int
-	bd_ac_id : int #
-	bd_position : int [2]
-	bd_title : varchar [32]
-	bd_password : varchar [25]
-	bd_kind : varchar [32]
-}
-
-class chest {
-	ch_id : int
-	ch_bd_id : int #
-	ch_name : varchar [32]
-}
-
-class chest_object {
-	cho_id : int
-	cho_ch_id : int #
-	cho_name : varchar [32]
-	cho_count : int16_t
-}
-
-hide build methods
-hide chest methods
-hide chest_object methods
-
-build "1" -- "1" chest
-chest "1" -- "0..*" chest_object
-
-skinparam defaultFontName DejaVu Sans Mono
-skinparam defaultFontSize 10
-
-skinparam classBorderColor #C67C37
-skinparam classBackgroundColor FFC48D
-skinparam classArrowColor #C67C37
-
-@enduml
--- a/docs/UML/database/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-project(database)
-
-set(
-	FILES
-	${database_SOURCE_DIR}/Accounts.txt
-	${database_SOURCE_DIR}/Builds.txt
-	${database_SOURCE_DIR}/Inventory.txt
-)
-
-malikania_generate_uml(
-	NAME database
-	DIRECTORY database
-	SOURCES ${FILES}
-)
--- a/docs/UML/database/Inventory.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-'
-' Inventory.txt -- database diagram for inventory
-'
-' Copyright (c) 2013, 2014 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.
-'
-
-@startuml
-
-class inventory {
-	inv_id : int
-	inv_ch_id : int #
-}
-
-class inventory_object {
-	invo_id : int
-	invo_inv_id : int #
-	invo_name : varchar [32]
-	invo_count : int16_t
-}
-
-class character {
-}
-
-class artefact {
-	atf_id : int
-	atf_ch_id : int #
-	atf_name : varchar [32]
-}
-
-class quest {
-	qs_id : int
-	qs_ch_id : int
-	qs_name : varchar [32]
-	qs_status : enum
-}
-
-class quest_property {
-	qp_id : int
-	qp_name : varchar [32]
-	qp_value : varchar [64]
-}
-
-hide inventory methods
-hide inventory_object methods
-hide character attributes
-hide character methods
-hide artefact methods
-hide quest methods
-hide quest_property methods
-
-character "1" -- "0..3" artefact
-character "1" -- "0..*" quest
-character "1" -- "1" inventory
-inventory "1" -- "0..*" inventory_object
-quest "1" -- "0..*" quest_property
-
-skinparam defaultFontName DejaVu Sans Mono
-skinparam defaultFontSize 10
-
-skinparam classBorderColor #C67C37
-skinparam classBackgroundColor FFC48D
-skinparam classArrowColor #C67C37
-
-@enduml
--- a/docs/books/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-project(books)
-
-add_custom_target(docs-books COMMENT "Generated books")
-
-add_dependencies(docs docs-books)
-
-add_subdirectory(conventions)
-add_subdirectory(developer)
-add_subdirectory(specifications)
-add_subdirectory(mercurial)
--- a/docs/books/conventions/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-malikania_generate_book(
-	conventions
-	Conventions.pdf
-	Conventions.txt
-)
--- a/docs/books/conventions/Conventions.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,649 +0,0 @@
----
-title: Coding conventions
-author:
-  - David Demelier <markand@malikania.fr>
-  - Renaud Jenny <renox0@malikania.fr>
-  - Alexis Dörr <nanahara@malikania.fr>
-date: April 13, 2015
-abstract: Official coding conventions for Malikania related developments.
----
-
-Please read this page with care, we are **very** strict about coding guidelines. Code which does not honour this is rejected.
-
-# C++
-
-## Style
-
-### General rules
-
-- Never write two consecutives blank lines,
-- Always use 8 tabs indent (no spaces),
-- No jokes,
-- No easter eggs,
-- Don’t use raw pointers,
-- A function should do one thing but well [KISS](http://en.wikipedia.org/wiki/KISS_principle)
-
-### Header in the source file
-
-Each file (except examples) must have the license header like this:
-
-````cpp
-/*
- * filename.ext -- short description here
- *
- * Copyright (c) 2013, 2014, 2015 Malikania Authors
- *
- * 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.
- */
-````
-
-**Note**: For other file than C++, be sure to adapt the comment tokens, see the `CMakeLists.txt` for examples.
-
-### Statement separation
-
-Always separate blocks by contexts.
-
-````cpp
-void Object::destroy()
-{
-	if (m_motor.isStarted()) {
-		m_motor.brake();
-	}
-	if (m_motor.hasOil()) {
-		m_motor.control();
-	}
-
-	if (m_driver.isDead()) {
-		sendLetter();
-	}
-
-	for (auto r : m_wheels) {
-		r.checkInflation();
-	}
-}
-````
-
-### Long lines
-
-We usually like to keep code in less that 100 characters, we admit up to
-120 characters but that should be rare. If possible use local variables
-if it’s too long.
-
-To avoid:
-
-````cpp
-if (myObject.getParameter("foo").getValue().substr(0, 7) == "test") {
-	...
-}
-````
-
-Prefer:
-
-````cpp
-auto &value = myObject.getParameter("foo").getValue();
-
-if (value.substr(0, 7) == "test") {
-	...
-}
-````
-
-When long lines appear in a conditional, indent the next line to 4 characters. In this situation, you must add braces on the next line
-
-````cpp
-if (onecondition && twocondition &&
-    three && four)
-{
-	somestuff();
-}
-````
-
-### Braces
-
-Braces comes on the same line they are needed.
-
-````cpp
-if (condition) {
-	apply();
-	add();
-} else {
-	something();
-	ok();
-}
-````
-
-Braces are mandatory everywhere, even if there is only one statement.
-
-````cpp
-// Correct
-if (condition) {
-	validate();
-}
-
-// Also correct
-if (condition1) {
-	validate();
-} else {
-	clear();
-	restart();
-}
-````
-
-And a lambda has its brace on the same line too:
-
-````cpp
-sort([&] (object &) -> bool {
-	return true;
-});
-````
-
-Only functions have their braces on a new line:
-
-````cpp
-void f()
-{
-}
-````
-
-### Symbols placement and qualifiers
-
-The symbols `&` and `*` must be place just next to the variable name. The qualifiers must always be placed **before** the type.
-
-Bad:
-
-````cpp
-Entity const& entity = find();
-````
-
-Correct:
-
-````cpp
-const Entity &entity = find();
-````
-
-### Naming
-
-All functions, variables, class names are always camelCase. Only
-namespaces must be all lowercase, short and concise.
-
-*Note:* you **must** not create a new namespace except malikania and
-anonymous ones.
-
-More rules:
-
-- English names
-- Member variables start with m\_
-- No hungarian notation
-
-````cpp
-int variable;
-
-void myFunction()
-{
-}
-````
-
-## Programming
-
-### Make elegant code
-
-This is useless:
-
-````cpp
-if (m_valid) {
-	return true;
-}
-
-return false;
-````
-
-Just try to be as concise as possible:
-
-````cpp
-return m_valid;
-````
-
-### Useless else
-
-When you use `continue`, `break` or `return` you **don't** need else.
-
-````cpp
-for (auto &f : values) {
-	if (f.isValid()) {
-		continue;
-	}
-
-	code();
-}
-````
-
-````cpp
-if (notValid) {
-	return;
-}
-
-statement();
-````
-
-### Note about continue
-
-The `continue` keyword is very welcome, but don't make heavy usage of it if the
-loop is simple.
-
-Bad:
-
-````cpp
-for (auto &f : values) {
-	if (!f.isValid()) {
-		continue;
-	}
-	if (!f.advance(100)) {
-		continue;
-	}
-
-	f.trap();
-}
-````
-
-Better:
-
-````cpp
-for (auto &f : values) {
-	if (f.isValid() && f.advance(100)) {
-		f.trap();
-	}
-}
-````
-
-### Comments
-
-Avoid useless comments in source files. Comment complex things or why it
-is done like this. However any public method / function in the .h
-**must** be documented as doxygen without exception.
-
-````cpp
-/*
- * Multi line comments look like
- * this.
- */
-
-// Short comment
-````
-
-Example of class with doxygen:
-
-````cpp
-// header.h
-
-/**
- * @class A
- * @brief The A class
- */
-class A {
-public:
-	/**
-	 * Destory the object and all its ancestors.
-	 *
-	 * @return true
-	 */
-	bool destroy();
-};
-````
-
-### Getters / setters
-
-This concept applies the most to Java programmers. If possible, setters must be
-avoided, it is not a good programming practices. However, getters are
-welcome if they are needed and must return:
-
-- If object:
-	- Const reference to the object (and the function is marked const)
-	- Overload non const
-- If primitive:
-	- A copy of the value
-
-If you really need getters and setters, follow the Qt convention:
-
-- The getter must be the variable name (e.g `title()`)
-- The setter is prefixed by set (e.g `setTitle()`)
-
-Bad:
-
-````cpp
-Window w;
-
-w.setTitle("Fabulous window title here");
-w.setIcon("path/to/the/icon/file.png");
-w.setSize(100, 200);
-````
-
-Better :
-
-````cpp
-WindowParams params {
-	"Fabulous window title here",
-	"path/to/the/icon/file.png",
-	100, 200
-};
-
-Window w(params);
-````
-
-If you need a bunch of parameters, don't hesitate to use small packages classes with public members (with no m\_ prefixe).
-
-### Header guards
-
-- Header guards must be named `MALIKANIA_FILENAME_H`
-- The `#endif` must have a comment
-
-Example if the file is `Foo.h`:
-
-````cpp
-#ifndef MALIKANIA_FOO_H
-#define MALIKANIA_FOO_H
-
-#endif // !MALIKANIA_FOO_H
-````
-
-## Constructs
-
-### Arguments passing
-
-The following rules of thumb must be used when passing arguments:
-
-- The type is an object **non-polymorphic**
-	- The argument will not be copied nor modified in the receiver: **const reference**
-	- The argument is an in/out parameter: **non-const reference**
-	- The argument is a sink-argument (receiver needs its own copy): **value**
-- The type is an object **polymorphic**
-	- You must store the object (e.g a vector, a member variable)
-		- Use smart pointer and pass by value
-	- The object will just be read or forwarded
-		- Pass by template with same rules as non-polymorphic
-		- Pass by universal reference if the type must be forwarded to another function
-- The type is primitive
-	- Pass always by value
-
-Example of sink arguments:
-
-````cpp
-class Person {
-private:
-	std::string m_firstName;
-	std::string m_lastName;
-
-public:
-	Person(std::string firstName, std::string lastName)
-		: m_firstName(std::move(firstName))
-		, m_lastName(std::move(lastName))
-	{
-	}
-};
-````
-
-Example of **polymorphic** read-only
-
-````cpp
-template <typename Drawable>
-void draw(Drawable &drawable)
-{
-	drawable.draw();
-}
-
-Rectangle r{1, 2};
-
-draw(r);
-````
-
-Example of **polymorphic** sink-argument
-
-````cpp
-void addEffect(std::unique_ptr<Effect> effect)
-{
-	m_effets.push_back(std::move(effect));
-}
-
-addEffect(std::make_unique<Fire>());
-````
-
-### Exceptions
-
-Exceptions must be used instead of returns code to indicate errors. However be sure that:
-
-1. You don't throw exceptions in most used functions (e.g main loop)
-2. Try to limit exceptions at loading, on user input
-3. You always catch by const reference
-
-### Class declaration
-
-A class must have the following order:
-
-1. Public, private types (with using, not typedef),
-2. Private fields,
-3. Protected fields,
-4. Private functions
-5. Protected functions
-6. Public functions
-7. Virtual and overrided functions
-8. Operators
-
-````cpp
-class Foo {
-public:
-	using List = std::vector;
-
-private:
-	List m_list;
-	int m_count;
-
-public:
-	Foo();
-
-	int &operator[](int);
-};
-````
-
-**Note**: always add a space after a scope block (public, private, protected).
-
-### Commented code
-
-Commented code must be surrounded by `#if 0` and `#endif`. It easier to manipulate and allows nested comments. Avoid commenting too much code, if the code is useless, just delete it.
-
-````cpp
-#if 0
-	// This is currently buggy
-	memcpy(NULL, "don't use C routines", BUFSIZ);
-#endif
-````
-
-### Comment labels
-
-Lot of IDEs support some labels in comments such as:
-
-- **FIXME**, a label to mark the code as unoptimized / perfectible
-- **TODO**, missing feature or stuff
-- **XXX**, something wrong
-
-Please note that using them indicates that you're probably doing something wrong.
-
-### Includes order
-
-The includes should always come in the following order.
-
-1. C++ headers
-2. C header
-3. Third party libraries
-4. Application headers in ""
-
-````cpp
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <iostream>
-
-#include <Converter.h>
-
-#include "Foo.h"
-````
-
-**Note**: always use C++ headers for C equivalent, stdio.h -\> cstdio, etc.
-
-### RTTI
-
-- Usage of dynamic_cast is strictly forbidden
-- Same for anything requiring RTTI (typeid)
-
-### Singleton
-
-Do not use singletons.
-
-### C language
-
-Don't use anything from C such as `#define`, `memcpy`, `fopen` or even `malloc`.
-
-# CMake
-
-## Style
-
-CMake files guidelines are quite close to the C++ one.
-
-- Use only tabs
-- Put spaces before keywords (if, foreach)
-
-## Argument indent
-
-When there is a function which takes named arguments, indent all of them if the
-function is too long.
-
-You must also indent if there are more than one argument to parameters.
-
-````cmake
-long_command(
-	NAME foo
-	TARGET foo
-	ARGS
-		-j6
-		-c'a'
-	SOURCES
-		a.txt
-		b.txt
-)
-````
-
-# JavaScript
-
-JavaScript coding conventions are close to the C++ guidelines.
-
-## Semicolons
-
-JavaScript can omit semicolons, but you must use them for each statement.
-
-## Conditionals
-
-If possible always use strict comparisons using `===` and `!==`.
-
-## Object oriented naming
-
-To mimic object oriented JavaScript, just name function constructors in
-CamelCase.
-
-````
-function Vehicle()
-{
-}
-
-Vehicle.prototype.drive = function ()
-{
-}
-````
-
-## Lexical this issue
-
-When you have to capture the real `this` pointer into a function callback, add
-a local variable named `self`.
-
-````javascript
-function Foo()
-{
-	this.entries = [];
-
-	var self = this;
-
-	something(function (x) {
-		self.entries.push(x);
-	});
-}
-````
-
-# Json
-
-JSON files are close to the C++ guidelines.
-
-## Indent
-
-Only use 2 spaces indentation.
-
-````json
-{
-  "property": "value"
-}
-````
-
-## Braces
-
-Braces follow same conventions as C++ except for arrays where you must place
-object braces on their own line.
-
-````json
-{
-  "property": "value",
-  "verbose": false,
-  "network": {
-    "port": 19000
-  },
-  "array": [
-    {
-      "has-indent": true
-    }
-  ]
-}
-````
-
-# Markdown
-
-Markdown is used for the documentation process.
-
-## Bullet lists
-
-Markdown offers different bullet list symbols, you must only use `-`.
-
-## Headers
-
-Do not use underlined headers (`====` and `----`), only use `#`.
-
-Bad:
-
-````markdown
-Level 1
-=======
-
-Level 2
--------
-````
-
-Correct:
-
-````markdown
-# Level 1
-
-## Level 2
-````
--- a/docs/books/developer/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-malikania_generate_book(
-	developer
-	Developer.pdf
-	Developer.txt
-)
\ No newline at end of file
--- a/docs/books/developer/Developer.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
----
-title: Malikania Engine developer guide
-author:
-  - David Demelier <markand@malikania.fr>
-  - Renaud Jenny <renox0@malikania.fr>
-  - Alexis Dörr <nanahara@malikania.fr>
-date: February 26, 2015
-abstract: Document related to Malikania's model of development and developer procedures.
----
-
-# Introduction
-
-This paper describes the model of development used in Malikania Engine. You must
-read it if you're a Malikania Developer.
-
-You may also read that paper if you want to use a development version for your
-own use.
-
-# Branching model
-
-The Malikania developments use [Mercurial](http://mercurial.selenic.com)
-bookmarks and branches for different purposes.
-
-The branches are used to separate the current development and the stables
-versions.
-
-Malikania Engine offers security fixes from N to N-3 major versions. For example
-if version 5.0 is released and a bug is found in 2.4.5, it is fixed.
-
-However, when a new major version is released (N), the last major version (N-1)
-does not get any new feature anymore.
-
-## Branch: default
-
-This is the most active branch. It can either contains the most recent code
-for the next major release or the next minor release depending on the
-roadmap.
-
-The default branch has active developers who add new features and then merge
-them to stable branches (see below).
-
-## Branch: x-stable
-
-The branch `x-stable` contains the last minor versions for major version
-numbered **x**.
-
-For example, if the last stable branch is `3-stable`, then this branch will
-produces 3.1.z, 3.2.z and such.
-
-The default branch MUST always merge to the **latest** stable branch.
-
-There are no general rules when a new major version is planned, it highly depends
-on the needs and features planned.
-
-This branch is useful if you want to test new features without having to update
-your game since it completely honours semantic versioning, thus having complete
-backward compatibility since version x.0.0.
-
-## Branch: x.y-release
-
-This is the most inactive branch, it is also called as a maintainance branch.
-Only fixes are commited to that branch. It's also the only branch were tags
-are created.
-
-It is the **recommended** branch for any user who wants to use Malikania Engine
-Mercurial repository.
-
-This branch produces the next patch version, for example, with a branch numbered
-`4.1-release`, this branch will produces 4.1.1, 4.1.2, etc.
-
-# Usage of bookmarks
-
-Bookmarks are distinct from branches and are used for different purposes. If you
-don't know Mercurial bookmarks, have a look at this
-[explanation](http://mercurial.selenic.com/wiki/Bookmarks).
-
-Bookmarks are slightly different than Git branches as they do not create heads
-automatically. This is quite confusing at first but it's not a real problem
-since there is a special bookmark named @ (see below).
-
-Bookmarks are created by developers to mark specific works, see below for the
-list of bookmarks.
-
-**Note:** When you push the bookmark for the first time, you must pass it to the
-arguments (e.g `hg push -B feature-hello`).
-
-## Bookmark: @
-
-This is the "default" bookmark. It has a special meaning in Mercurial, it is the
-automatically update bookmark on **new clones**.
-
-It's also the bookmark where all development takes place. When you start
-a **new** work, you MUST always update to that bookmark.
-
-## Bookmark: feature-xyz
-
-When starting a new feature, you MUST create a new bookmark named `feature-xyz`
-where xyz is a shortname for the feature.
-
-## Bookmark: change-xyz
-
-This bookmark is created when a change has to been done. It does not add any new
-features.
-
-## Bookmark: fix-xyz
-
-The `fix-xyz` bookmark is used to fix a bug. These bookmarks usually take places
-only in `x.y-release` branches.
-
-# Finishing a feature
-
-When you have finished a feature, change or any work. There are several steps to
-do correctly.
-
-## Redmine fields
-
-If your task has been created for Redmine, you must do the following
-
-1. Set the amount of time done
-2. Set the percentage
-3. Set the revision number in the description (e.g `r123`)
-
-**Note:** Redmine does not fetch automatically new revisions, you may need to
-visualize the repository from redmine to check the revision number.
-
-## Commit message
-
-You must also use an appropriate commit message. Every commit message starts at
-least with a capital letter and ends with period.
-
-Then, if the task is complete, you may set the following fields after a blank
-line:
-
-- **Task:** the task number (with a #)
-- **Requested by:** requested by a specific person (if no task)
-- **Submitted by:** if the user has provided a patch
-
-For the person identity, use the following convention:
-
-- FirstName LastName \<email\> (if user allow all)
-- FirstName LastName (if user does not want its email to be shown)
-
-Otherwise, don't set the identity if the person does not want to be represented.
-
-You MUST indent the fields in two tabs (8-size indent, no spaces).
-
-Example of a commit message for a standard Redmine task:
-
-````
-Add support for animation files.
-
-Task:		#127
-````
-
-Example of a commit message for a contribution:
-
-````
-Add support for Mac OS X.
-
-Submitted by:	Jean-François Aloué
-````
-
-# Contributing
-
-This section targets users who wants to contribute to Malikania Engine and are
-not developers.
-
-## You found a bug
-
-1. Make sure you indeed found a bug.
-2. Double check if there are no pending issues about the same bug.
-3. Check one more time for the same bug
-
-Then please provide if possible, a reproducable example so we can test easily.
-If you already made a fix for the bug then please add `[PATCH]` prefix to the
-Redmine task and attach it as files.
-
-## You want a new feature
-
-Adding new features makes the Malikania Engine more and more powerful, it also
-makes it more and more big and maybe more and more slow.
-
-Always consider twice for the feature, if it can be done from ECMAScript, then
-keep it into your project.
-
-Then follow these steps:
-
-1. Check if there is an issue about your feature
-	- There is a closed feature
-		- There are no plans to add this feature
-	- There are no issue
-		- Provide a correct description about the feature
-
-Please take in account that we love adding contributions to our project but if
-it is a very big feature always ask us in the forums, IRC or mails to be sure
-if we will accept the feature to avoid you wasting your time.
\ No newline at end of file
--- a/docs/books/mercurial/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-malikania_generate_book(
-	mercurial
-	Mercurial.pdf
-	Mercurial.txt
-)
--- a/docs/books/mercurial/Mercurial.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
----
-title: Mercurial
-author:
-  - David Demelier <markand@malikania.fr>
-  - Renaud Jenny <renox0@malikania.fr>
-  - Alexis Dörr <nanahara@malikania.fr>
-date: February 11, 2015
-abstract: Beginner guide to Mercurial SCM
----
-
-# Introduction
-
-This document targets those who are unfamiliar with Mercurial or with DVCS
-tools.
-
-If you are familiar with Git, you will understand Mercurial easily.
-
-## What is a DVCS
-
-A Distributed Revision Control System (DRCS) is a tool used to develop and
-control the version of a project. In contrast to a RCS, the distributed one
-can work offline.
-
-Note: DVCS is a synonym.
-
-# Mercurial
-
-[Mercurial](http://mercurial.selenic.com/) is a popular cross-platform SCM.
-
-## Why Mercurial
-
-Why mercurial and not other?
-
-The Mercurial choise is almost an historical reason, it was first chosen for
-various reasons where other SCM were not options.
-
-On the other hand, Mercurial has several benefits:
-
-- Portable, this feature is mandatory in the project goal
-- Easy, creating and starting using a Mercurial repository is very easy
-- Beautiful, TortoiseHg and its dedicated workbench is a very convenient tool
-
-# Mercurial commands
-
-## clone
-
-Used to copy an existing repository locally.
-
-**Syntax**
-
-	hg clone <scheme><path> [destination]
-
-**Example**
-
-	hg clone http://hg.foo.org/repository
-
-![Clone.png](images/Clone.png)
-
-## pull
-
-Pull updates (without applying) from a repository.
-
-**Syntax**
-
-	hg pull [source]
-
-**Example**
-
-	hg pull
-	hg pull http://hg.foo.org/repo
-
-![Pull](images/Pull-context.png)
-
-![Pull](images/Pull-window.png)
-
-## update
-
-Update the content of a repository. This command let you update the repository to any revision (older or newer). It is commonly used after a pull.
-
-**Syntax**
-
-	hg update [args...]
-
-**Example**
-
-	hg up
-	hg up -r 234        # update to revision 234
-
-![Update](images/Update-context.png)
-
-![Update](images/Update-window.png)
-
-## merge
-
-This action allows you to merge different branches / revisions / bookmarks. It will try to resolve conflict by itself and may ask you to resolve them if not possible.
-
-**Syntax**
-
-	hg merge [args...]
-
-**Example**
-
-	hg merge                   # merge with the default next head
-	hg merge -r 123            # merge with revision 123
-
-![Merge](images/Merge-context.png)
-
-## add
-
-Add files or directories.
-
-**Syntax**
-
-	hg add files...
-
-**Example**
-
-	hg add myfile.cpp
-	hg add myfile1.cpp myfile2.cpp
-	hg add mydirectory
-
-![Add](images/Add-context.png)
-
-![Add](images/Add-window.png)
-
-## remove
-
-Remove tracked files.
-
-**Syntax**
-
-	hg remove files...
-
-**Example**
-
-	hg remove myfile.cpp
-	hg remove myfile1.cpp myfile2.cpp
-	hg remove mydirectory
-
-![Remove](images/Remove-context.png)
-
-![Remove](images/Remove-window.png)
-
-## commit
-
-Commit validates and create a new changeset locally. Thanks to the DRCS nature of Mercurial, it is completely possible to rollback. You may commit multiple times before pushing.
-
-**Syntax**
-
-	hg commit [args...] [files]
-
-**Example**
-
-	hg ci -m "test"
-	hg ci a.cpp
-
-![Commit](images/Commit-context.png)
-
-![Commit](images/Commit-window.png)
-
-## push
-
-Push every local changesets to the destination.
-
-**Syntax**
-
-	hg push [args...] [destination]
-
-**Example**
-
-	hg push
-
-![Push](images/Push-context.png)
-
-![Push](images/Push-window.png)
-
-## diff
-
-Shows the difference between revisions.
-
-**Syntax**
-
-	hg diff [-r r1 [-r r2]]
-	hg diff [-c r]
-
-**Example**
-
-	hg diff
-	hg diff -r 124
-	hg diff -r 1 -r 2
-
-![Diff](images/Diff-context.png)
-
-![Diff](images/Diff-window.png)
-
-## heads
-
-Show the different heads available.
-
-**Syntax**
-
-	hg heads [args...]
-
-**Example**
-
-	hg heads
-
-**Possible output**
-
-changeset:   237:370dccb35ac9
-tag:         tip
-user:        David Demelier <markand@malikania.fr>
-date:        Sat Jul 05 09:06:39 2014 +0200
-summary:     OptionParser: add more tests
Binary file docs/books/mercurial/images/Add-context.png has changed
Binary file docs/books/mercurial/images/Add-window.png has changed
Binary file docs/books/mercurial/images/Clone.png has changed
Binary file docs/books/mercurial/images/Commit-context.png has changed
Binary file docs/books/mercurial/images/Commit-window.png has changed
Binary file docs/books/mercurial/images/Diff-context.png has changed
Binary file docs/books/mercurial/images/Diff-window.png has changed
Binary file docs/books/mercurial/images/Merge-context.png has changed
Binary file docs/books/mercurial/images/Pull-context.png has changed
Binary file docs/books/mercurial/images/Pull-window.png has changed
Binary file docs/books/mercurial/images/Push-context.png has changed
Binary file docs/books/mercurial/images/Push-window.png has changed
Binary file docs/books/mercurial/images/Remove-context.png has changed
Binary file docs/books/mercurial/images/Remove-window.png has changed
Binary file docs/books/mercurial/images/Update-context.png has changed
Binary file docs/books/mercurial/images/Update-window.png has changed
--- a/docs/books/specifications/Architecture/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-# Architecture
-
-Malikania Engine is exclusively client-server based. While it is strictly a
-client-server architecture, it is still possible to write one player games
-by running a local server on the user's machine with some effort.
-
-## Server
-
-Everything is computed on the server side to avoid any cheat. That includes:
-
-- Handling authentication,
-- Handling players,
-- Handling battles,
-- Handling moves on maps.
-
-## Client
-
-The client is only responsible of:
-
-- Graphics,
-- Sounds,
-- Input,
-- Connection with server.
-
--- a/docs/books/specifications/Architecture/Technologies.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-## Technologies
-
-The Malikania Engine is written in C++11.
-
-### Runtime libraries
-
-The following libraries are *required* as the base Malikania Engine core:
-
-- C++14,
-- [OpenSSL](http://www.openssl.org), for the secure part of network protocol,
-- [libjansson](http://www.digip.org/jansson), JSON library for game data,
-- [libzip](http://www.nih.at/libzip/), ZIP library for archive bundles,
-- [libcurl](http://curl.haxx.se/libcurl), library for downloading updates.
-
-#### On desktop
-
-- [SDL 2.0](http://libsdl.org), for the client part only
-
-### Development libraries and tools
-
-The following libraries may be needed when building and developing a game:
-
-- [CMake](http://www.cmake.org), for building the toolchain
-- [Pandoc](http://http://johnmacfarlane.net/pandoc), used for generating documentation
-- [Java](https://www.java.com/en), for UML diagrams
--- a/docs/books/specifications/Bundle/Format.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-## Format
-
-The format is a compressed ZIP archive file with no password.
-
--- a/docs/books/specifications/Bundle/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-# Bundles
-
-Bundles are archives containing the required files to be played in the engine.
-
--- a/docs/books/specifications/Bundle/Usage.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-## Usage
-
-A bundle archive is just an archive that contains all the game data.
-
-It is close to what a cardrige is to a game console, the game is simply loaded
-in the Malikania Engine and the engine knows how to run it.
-
-This offers the following benefits:
-
-- Easy to download, provide,
-- Compression,
-- Associate the file type to the engine in the operating system.
-
--- a/docs/books/specifications/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for malikania
-#
-# Copyright (c) 2013, 2014, 2015 Malikania Authors
-#
-# 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.
-#
-
-#
-# This order makes the book order, don't change it
-#
-set(
-	FILES
-	"${CMAKE_CURRENT_SOURCE_DIR}/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Overview/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Architecture/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Architecture/Technologies.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Gameplay/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Gameplay/Stats.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Bundle/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Bundle/Usage.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Bundle/Format.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/GameData/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/GameData/Game.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/GameData/Manifest.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/GameData/Sprites.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/GameData/Animations.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Tools/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Tools/Malikania-vm.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Tools/Malikania-bundle.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Intro.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Messages.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Messages/server-info.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Messages/server-message.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/account-create.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/account-identify.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/character-create.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/character-delete.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/character-list.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/character-select.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/exchange-start.txt"
-	"${CMAKE_CURRENT_SOURCE_DIR}/Network/Commands/exchange-add.txt"
-)
-
-malikania_generate_book(
-	specifications
-	Specifications.pdf
-	"${FILES}"
-)
--- a/docs/books/specifications/GameData/Animations.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-## Animations
-
-The animations are animated sprites. They provide a convenient way of drawing
-animations onto the screen because they update themselves automatically.
-
-Animations use [Sprites][] to be shown.
-
-### JSON description
-
-A JSON file is always associated with an animation. If you have ten animations, you have ten JSON files for them.
-
-````json
-{
-  "alias": "Fire",
-  "sprite": "Fire-sprite",
-  "frames": [
-    { "delay": 100, "cell": 1 },
-    { "delay": 105, "cell": 0 }
-  ]
-}
-````
-
-- **alias**: the name required to register the animation
-- **sprite**: the sprite name (the sprite's alias)
-- **frames**: for each frame the following:
-	- **delay**: the delay in milliseconds
-	- **cell**: (Optional) the cell index
-
-With that following code, a file will be generated with the following images:
-
-1. delay of 100 ms before switching to the second frame
-2. delay of 105 ms before switching finishing the animation
--- a/docs/books/specifications/GameData/Game.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-## Game
-
-The game definition is mandatory and MUST be present in the both server and
-client bundle.
-
-It is defined in the file **game.json**
-
-### JSON description
-
-````json
-{
-  "name": "Short game name",
-  "authors": [ "Name LastName <email>" ],
-  "version": "Game version",
-  "requires": "Engine version format",
-  "license": "License acronym"
-}
-````
-
-- **name**: the game name,
-- **authors**: the game authors (at least one),
-- **version**: the game version as string, can be arbitrary,
-- **requires**: the required version of Malikania Engine, see below
-- **license**: (Optional) the license,
-
-**About the version**
-
-There is no specific format for the **requires** field, you just specify a
-version (at least major).
-
-Because Malikania Engine is backward compatible only with minor versions (as
-specified in the semver specification) the game is automatically disabled
-if tried to be ran from an incompatible Malikania Engine version.
-
-**Example**
-
-1. You have developed your game using Malikania Engine 1.3.2, then set **requires**
-to "1.3.2", It will be compatible with any version greater or equal to 1.3.2 but
-not with version greater or equal to 2.0.0.
-
-2. You have developed your game using Malikania Engine 1.0, you can just set
-**requires** to "1".
--- a/docs/books/specifications/GameData/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-# Game data definition
-
-This section details how game objects are defined.
-
-Usually games are defined in JSON if applicable, other scriptable parts
-are written in ECMAScript.
-
--- a/docs/books/specifications/GameData/Manifest.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-## Manifest
-
-The manifest file tells the engine how many files for each component are
-available.
-
-It is mandatory to list all of the game data.
-
-### JSON description
-
-The file is named `manifest.json` and is installed in the root game directory.
-
-````json
-{
-  "images": [
-    "images/wood.png",
-    "images/cat.png"
-  ],
-  "spells": [
-    "spells/fire.js"
-  ]
-}
-````
-
-You can use the [malikania-bundle][] tool to create manifest files
-automatically.
--- a/docs/books/specifications/GameData/Sprites.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-## Sprites
-
-The sprites are definitions of graphical libraries.
-
-An image can store multiple frames of a sprite and then the game can select one
-of this frame. It is useful to store the different images sprites of characters,
-object for example.
-
-Each sprite requires one JSON file.
-
-### JSON description
-
-````json
-{
-  "image": "jack.png",
-  "alias": "Jack",
-  "cell": [ 16, 16 ],
-  "size": [ 100, 100 ],
-  "space": [ 0, 0 ],
-  "margin": [ 0, 0 ]
-}
-````
-
-- **alias**: the sprite alias that will be used to retrieve in the registry
-- **image**: the relative path to the image
-- **cell**: each cell size
-- **size**: Optional, the full size of the image, if not set determined at compilation
-- **space**: Optional, space between cells
-- **margin**: Optional, space before the first cell horizontally and vertically
-
-### Margin and padding
-
-Padding and margin are allowed before and between cells.
-
-![Optional padding, margin and space](GameData/images/format.png)\
-
-
-On that image, you can see:
-
-* a margin of 8x8 pixels (in blue)
-* a padding of 4x4 pixels between cells (in red)
-* the cell size of 32x32 pixels (in green)
Binary file docs/books/specifications/GameData/images/format.png has changed
--- a/docs/books/specifications/Gameplay/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-# Gameplay
-
-This section details the characteristics of a game created with Malikania
-Engine.
--- a/docs/books/specifications/Gameplay/Stats.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-## Character statistics
-
-Each character has the following statistics.
-
-### Levels
-
-A character level starts at level 1 and goes to 100 included. This is not
-configurable by the game.
-
-### Spells
-
-The number of spells is defined by the specifications and cannot be configured
-by the game.
-
-The following table shows how the spells are gained during the player
-lifetime.
-
-| Level | Number of spells available |
-|-------|----------------------------|
-| 2 | 3 |
-| 3 | 4 |
-| 8 | 5 |
-| 12 | 6 |
-| 15 | 7 |
-| 20 | 8 |
-| 28 | 9 |
-| 40 | 10 |
-| 56 | 11 |
-| 68 | 12 |
-| 85 | 13 |
-| 100 | 14 |
-
-### Statistics
-
-Each character has:
-
-| Name         | Range   | Description             |
-|--------------|---------|-------------------------|
-| Heal points  | 0-32767 | The player heal points  |
-| Magic points | 0-127   | The player magic points |
-| Move points  | 0-20    | The player move points  |
--- a/docs/books/specifications/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
----
-title: Malikania Engine
-author:
-  - David Demelier <markand@malikania.fr>
-  - Renaud Jenny <renox0@malikania.fr>
-  - Alexis Dörr <nanahara@malikania.fr>
-date: February 26, 2015
-abstract: Official Malikania Engine specifications
----
-
-# Synopsis
-
-This paper details the official Malikania Engine specifications and its
-reference implementation.
-
-# Terms
-
-The keywords MUST, SHOULD, MAY are to be interpreted as described in
-[RFC 2119](http://tools.ietf.org/html/rfc2119).
--- a/docs/books/specifications/Network/Commands.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-## Commands
-
-The commands are sent from the client to the server.
--- a/docs/books/specifications/Network/Commands/account-create.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-### account-create (secure)
-
-Create an account on the server. Registration must be enabled, otherwise
-an error is raised to the client.
-
-#### Synopsis
-
-````json
-{
-  "command": "account-create",
-  "login": "login name",
-  "first-name": "first name",
-  "last-name": "last name",
-  "password": "password",
-  "email": "email address"
-}
-````
-
-#### Fields
-
-- **login**: the login, following the login naming rules
-- **first-name**: the user first name
-- **last-name**: the user last name
-- **password**: clear password
-- **email**: the email address
--- a/docs/books/specifications/Network/Commands/account-identify.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-### account-identify (secure)
-
-Identify a player.
-
-#### Synopsis
-
-````json
-{
-  "command": "account-identify",
-  "login": "jean",
-  "password": "password"
-}
-````
-
-#### Fields
-
-- **login**, the account name
-- **password**, the password
--- a/docs/books/specifications/Network/Commands/character-create.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-### character-create
-
-Create a character.
-
-#### Synopsis
-
-````json
-{
-  "command": "character-create",
-  "nickname": "character nickname",
-  "class": "class alias",
-  "gender": "male or female"
-}
-````
-
-#### Fields
-
-- **nickname**: the character nickname
-- **class**: the class alias
-- **gender**: the character gender
--- a/docs/books/specifications/Network/Commands/character-delete.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-### character-delete
-
-Deletes a character, there are no confirmation possible, the client must do it.
-
-#### Synopsis
-
-````json
-{
-  "command": "character-delete",
-  "id": 123
-}
-````
-
-#### Fields
-
-- **id**: the character id
--- a/docs/books/specifications/Network/Commands/character-list.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-### character-list
-
-List all characters available for the connected player.
-
-#### Synopsis
-
-````json
-{
-  "command": "character-list"
-}
-````
--- a/docs/books/specifications/Network/Commands/character-select.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-### character-select
-
-Select a character.
-
-#### Synopsis
-
-````json
-{
-  "command": "character-select",
-  "id": "character id"
-}
-````
-
-#### Fields
-
-- **id**: the character id
--- a/docs/books/specifications/Network/Commands/exchange-add.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-### exchange-add
-
-Add an object to the exchange session, this automatically disable acceptation
-in the other side.
-
-#### Synopsis
-
-````json
-{
-  "command": "exchange-add",
-  "id": 123
-}
-````
-
-#### Fields
-
-- **id**: the object id in the player inventory
--- a/docs/books/specifications/Network/Commands/exchange-start.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-### exchange-start (secure)
-
-Start an exchange session with a player.
-
-#### Synopsis
-
-````json
-{
-  "command": "exchange-start",
-  "id": 123
-}
-````
-
-#### Fields
-
-- **id**: the player id
--- a/docs/books/specifications/Network/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-# Network
-
-Networking in Malikania Engine.
-
-In that part, we will describe messages and requests. The messages come
-from the server while the requests come from the clients.
-
-## Syntax
-
-The network protocol use JSON in multiline format.
-
-You can use both Unix or Windows line endings. However, to terminate
-a message, an empty line must be added and terminated by '\\r\\n'.
-
-**Example:**
-
-1. This is a simple single-line message
-
-````json
-{ "command": "reload" }
-````
-
-2. This is a multi-lines message
-
-````json
-{
-  "command": "identify",
-  "nickname": "foo",
-}
-````
--- a/docs/books/specifications/Network/Messages.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-## Messages
-
-The message are emitted from the server and goes either to a specific
-client or to all connected players
--- a/docs/books/specifications/Network/Messages/server-info.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-### server-info
-
-Get the server information.
-
-#### Synopsis
-
-````json
-{
-  "command": "server-info",
-  "version": 1.0,
-  "engine": 3.2,
-  "admins": [ "player1", "player2" ],
-  "motd": "Message of the day",
-  "download": {
-    "enabled": true,
-    "sites": [
-      "http://pub.mygame.org/files",
-      "http://pub2.mygame.org/files"
-    ]
-  }
-}
-````
-
-#### Fields
-
-- **version**, the game version
-- **engine**, the engine version running
-- **admins**, (Optional) the list of administrators
-- **motd**, (Optional) a message of the day
-- **download**, (Optional) the download properties
-	- **enabled**: (Optional) enable download from the server. Default: false.
-	- **sites**: (Optional) list of mirrors where to download data, required if **enabled** is set.
-
--- a/docs/books/specifications/Network/Messages/server-message.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-### server-message
-
-The server has sent a global message which is sent to all connected users.
-
-#### Synopsis
-
-````json
-{
-  "command": "server-message",
-  "origin": "nickname",
-  "message": "Content of the message"
-}
-````
-
-#### Fields
-
-- **origin**: the user who has sent the global message
-- **message**: the content of the message, never sent empty
--- a/docs/books/specifications/Overview/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# Overview
-
-## What is Malikania Engine?
-
-Malikania Engine is a powerful free, opensource 2D MMORPG engine written in
-C++14 and use ECMAScript for the games.
-
-It is designed in mind to be as easy as possible to use. It is also very
-flexible to let you create games quickly with no difficulties.
-
-It is specialized in MMORPG only, while you can create your game how you want,
-it is not designed to be a general game engine.
-
-## How does it work?
-
-Malikania Engine is a set of multiple executables which will execute games
-written in ECMAScript.
--- a/docs/books/specifications/Tools/Intro.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-# Tools
-
-The following list of tools come with the reference implementation of the
-Malikania Engine:
-
-- malikania-vm [^malikania-vm-except]
-- malikania-bundle
-- malikania-animation
-- malikania-sprite
-- malikania-map
-- malikania-translate
-- malikania-manifest
-
-[^malikania-vm-except]: the the `malikania-vm` tool is an external package as it
-helps managing the Malikania Engine VMs.
--- a/docs/books/specifications/Tools/Malikania-bundle.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-## malikania-bundle
-
-The `malikania-bundle` tool manages the games cartridges.
-
-### Command line usage
-
-(@) `malikania-bundle create *archive* *game-directory*`
-(@) `malikania-bundle install [-d directory] *archive*`
-(@) `malikania-bundle info *field* *name*`
-(@) `malikania-bundle list`
-
-**Signature (1)**
-
-Creates the file *archive* from the game directory specified by
-*game-directory*.
-
-**Signature (2)**
-
-Install the game archive specified by *archive* to the optional directory
-specified by *-d directory*, otherwise, install it to the user Malikania Engine
-folder.
-
-**Note**: the *directory* is the prefix, invoking
-`malikania-bundle install -d /tmp/ game-1.mcg` will install */tmp/game-1*.
-
-**Signature (3)**
-
-Extract a field information from the game which may be an already installed game
-or an game archive specified by path. This usage MUST search for the filesystem path
-before seeking installed games.
-
-The *field* must be one of the following:
-
-- *version*, the game version
-- *engine*, the Malikania Engine version
-- *author*, the game author
--- a/docs/books/specifications/Tools/Malikania-vm.txt	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-## malikania-vm
-
-The `malikania-vm` tool is the most important tool within the Malikania Engine
-framework.
-
-Because Malikania Engine is backward compatible only with minor versions (as
-specified by semver), it is sometimes necessary to install multiple major
-versions of the Malikania Engine.
-
-To facilitate the launch of the games, the malikania-vm tool will use the
-appropriate version of the engine according to the game requirements.
-
-Because of that, this tool is built as a completely separate project and MUST
-be present before installation of any engine.
-
-The malikania-vm provides all the wrappers for every other Malikania Engine
-tools.
-
-### Installing new Malikania Engine version
-
-When a Malikania Engine version is installed, it also register itself to a small
-file kept by malikania-vm.
-
-This can be done from the Malikania Engine install target or by hand with the
-malikania-vm utility directly.
-
-**Note**: because Malikania Engine is backward compatible with minor versions,
-it does not make sense to install two versions from the same major version.
-
-Bad example:
-
-- 1.0.6
-- 1.2.4
-
-Correct example:
-
-- 1.4.0
-- 2.7
-
-### The Malikania-VM JSON description file
-
-The malikania-vm stores all engines installed into a JSON file. It is installed
-by default in:
-
-- **PREFIX/etc/malikania/vm.json**
-
-````json
-[
-  {
-    "version": "1.0.6",
-    "prefix": "/usr/local",
-    "execdir": "libexec/malikania/1.0.6",
-    "libdir": "lib",
-    "dbdir": "lib/malikania/1.0.6",
-    "datadir": "share/malikania/1.0.6",
-    "docdir": "doc/malikania/1.0.6",
-    "etcdir": "etc/malikania/1.0.6"
-  }
-]
-````
-
-- **version**: the engine version
-- **prefix**: Optional, the prefix where installed (if set, MUST be absolute)
-- **execdir**: Optional, the directory where to store Malikania Engine binaries
-- **libdir**: Optional, the directory where Malikania Engine public libraries are stored
-- **dbdir**: Optional, the directory where database backends are stored
-- **datadir**: Optional, the directory where Malikania Engine data are stored
-- **docdir**: Optional, the directory where Malikania Engine documentation are stored
-- **etcdir**: Optional, the directory where Malikania Engine configuration are stored
-
-**Note**: If any of **execdir**, **libdir**, **dbdir**, **datadir**, **docdir**,
-**etcdir** is not absolute, then it is relative to the prefix (recommended).
-
-### Command line usage
-
-(@) `malikania-vm list`
-(@) `malikania-vm unregister version`
-(@) `malikania-vm register version [-p prefix] [-e execdir] [-l libdir] [-d dbdir]
-[-s datadir] [-D docdir] [-c etcdir]`
-
-**Signature (1)**
-
-List all Malikania Engine installations.
-
-**Signature (2)**
-
-Remove the specified Malikania Engine version from the registry (not from the
-disk).
-
-**Signature (3)**
-
-Add a new Malikania Engine version to the Malikania VM registry.
-
-### CMake module
-
-The malikania-vm tool installs **MalikaniaVMConfig.cmake**, the Malikania Engine
-can set `MALIKANIA_VM_NO_REGISTER` before including the file so that the install
-target does not register itself to the malikania-vm (not recommended).
--- a/libcommon/malikania/Socket.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- * Socket.cpp -- portable C++ socket wrappers
- *
- * Copyright (c) 2013, 2014 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.
- */
-
-#include <cstring>
-
-#include "Socket.h"
-#include "SocketAddress.h"
-
-/* --------------------------------------------------------
- * System dependent code
- * -------------------------------------------------------- */
-
-#if defined(_WIN32)
-
-std::string Socket::syserror(int errn)
-{
-	LPSTR str = nullptr;
-	std::string errmsg = "Unknown error";
-
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		NULL,
-		errn,
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&str, 0, NULL);
-
-
-	if (str) {
-		errmsg = std::string(str);
-		LocalFree(str);
-	}
-
-	return errmsg;
-}
-
-#else
-
-#include <cerrno>
-
-std::string Socket::syserror(int errn)
-{
-	return strerror(errn);
-}
-
-#endif
-
-std::string Socket::syserror()
-{
-#if defined(_WIN32)
-	return syserror(WSAGetLastError());
-#else
-	return syserror(errno);
-#endif
-}
-
-/* --------------------------------------------------------
- * SocketError class
- * -------------------------------------------------------- */
-
-SocketError::SocketError(Code code, std::string function)
-	: m_code(code)
-	, m_function(std::move(function))
-	, m_error(Socket::syserror())
-{
-}
-
-SocketError::SocketError(Code code, std::string function, int error)
-	: m_code(code)
-	, m_function(std::move(function))
-	, m_error(Socket::syserror(error))
-{
-}
-
-SocketError::SocketError(Code code, std::string function, std::string error)
-	: m_code(code)
-	, m_function(std::move(function))
-	, m_error(std::move(error))
-{
-}
-
-/* --------------------------------------------------------
- * Socket class
- * -------------------------------------------------------- */
-
-#if defined(_WIN32)
-std::mutex Socket::s_mutex;
-std::atomic<bool> Socket::s_initialized{false};
-#endif
-
-Socket::Socket(int domain, int type, int protocol)
-{
-#if defined(_WIN32) && !defined(SOCKET_NO_WSA_INIT)
-	if (!s_initialized) {
-		initialize();
-	}
-#endif
-
-	m_handle = ::socket(domain, type, protocol);
-
-	if (m_handle == Invalid) {
-		throw SocketError(SocketError::System, "socket");
-	}
-
-	m_state = SocketState::Opened;
-}
-
-SocketAddress Socket::address() const
-{
-#if defined(_WIN32)
-	int length;
-#else
-	socklen_t length;
-#endif
-
-	sockaddr_storage ss;
-
-	if (getsockname(m_handle, (sockaddr *)&ss, &length) == Error)
-		throw SocketError(SocketError::System, "getsockname");
-
-	return SocketAddress(ss, length);
-}
-
-void Socket::bind(const SocketAddress &address)
-{
-	const auto &sa = address.address();
-	const auto addrlen = address.length();
-
-	if (::bind(m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == Error) {
-		throw SocketError(SocketError::System, "bind");
-	}
-
-	m_state = SocketState::Bound;
-}
-
-void Socket::close()
-{
-#if defined(_WIN32)
-	::closesocket(m_handle);
-#else
-	::close(m_handle);
-#endif
-
-	m_state = SocketState::Closed;
-}
-
-void Socket::setBlockMode(bool block)
-{
-#if defined(O_NONBLOCK) && !defined(_WIN32)
-	int flags;
-
-	if ((flags = fcntl(m_handle, F_GETFL, 0)) == -1) {
-		flags = 0;
-	}
-
-	if (block) {
-		flags &= ~(O_NONBLOCK);
-	} else {
-		flags |= O_NONBLOCK;
-	}
-
-	if (fcntl(m_handle, F_SETFL, flags) == Error) {
-		throw SocketError(SocketError::System, "setBlockMode");
-	}
-#else
-	unsigned long flags = (block) ? 0 : 1;
-
-	if (ioctlsocket(m_handle, FIONBIO, &flags) == Error) {
-		throw SocketError(SocketError::System, "setBlockMode");
-	}
-#endif
-}
-
-bool operator==(const Socket &s1, const Socket &s2)
-{
-	return s1.handle() == s2.handle();
-}
-
-bool operator<(const Socket &s1, const Socket &s2)
-{
-	return s1.handle() < s2.handle();
-}
--- a/libcommon/malikania/SocketAddress.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * SocketAddress.cpp -- socket addresses management
- *
- * Copyright (c) 2013, 2014 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.
- */
-
-#include <algorithm>
-#include <cstring>
-
-#include "Socket.h"
-#include "SocketAddress.h"
-
-namespace address {
-
-/* --------------------------------------------------------
- * Internet implementation
- * -------------------------------------------------------- */
-
-Internet::Internet(const std::string &host, unsigned port, int domain)
-{
-	if (host == "*") {
-		if (domain == AF_INET6) {
-			sockaddr_in6 *ptr = (sockaddr_in6 *)&m_addr;
-
-			ptr->sin6_addr = in6addr_any;
-			ptr->sin6_family = AF_INET6;
-			ptr->sin6_port = htons(port);
-
-			m_addrlen = sizeof (sockaddr_in6);
-		} else {
-			sockaddr_in *ptr = (sockaddr_in *)&m_addr;
-
-			ptr->sin_addr.s_addr = INADDR_ANY;
-			ptr->sin_family = AF_INET;
-			ptr->sin_port = htons(port);
-
-			m_addrlen = sizeof (sockaddr_in);
-		}
-	} else {
-		addrinfo hints, *res;
-
-		std::memset(&hints, 0, sizeof (addrinfo));
-		hints.ai_family = domain;
-
-		auto error = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
-		if (error != 0) {
-			throw SocketError(SocketError::System, "getaddrinfo", gai_strerror(error));
-		}
-
-		std::memcpy(&m_addr, res->ai_addr, res->ai_addrlen);
-		m_addrlen = res->ai_addrlen;
-		freeaddrinfo(res);
-	}
-}
-
-/* --------------------------------------------------------
- * Unix implementation
- * -------------------------------------------------------- */
-
-#if !defined(_WIN32)
-
-#include <sys/un.h>
-
-Unix::Unix(const std::string &path, bool rm)
-{
-	sockaddr_un *sun = (sockaddr_un *)&m_addr;
-
-	// Silently remove the file even if it fails
-	if (rm) {
-		::remove(path.c_str());
-	}
-
-	// Copy the path
-	memset(sun->sun_path, 0, sizeof (sun->sun_path));
-	strncpy(sun->sun_path, path.c_str(), sizeof (sun->sun_path) - 1);
-
-	// Set the parameters
-	sun->sun_family = AF_UNIX;
-	m_addrlen = SUN_LEN(sun);
-}
-
-#endif // _WIN32
-
-} // !address
-
-/* --------------------------------------------------------
- * SocketAddress implementation
- * -------------------------------------------------------- */
-
-SocketAddress::SocketAddress()
-	: m_addrlen(0)
-{
-	memset(&m_addr, 0, sizeof (m_addr));
-}
-
-SocketAddress::SocketAddress(const sockaddr_storage &addr, socklen_t length)
-	: m_addr(addr)
-	, m_addrlen(length)
-{
-}
-
-const sockaddr_storage &SocketAddress::address() const
-{
-	return m_addr;
-}
-
-socklen_t SocketAddress::length() const
-{
-	return m_addrlen;
-}
-
-bool operator<(const SocketAddress &s1, const SocketAddress &s2)
-{
-	const auto &array1 = reinterpret_cast<const unsigned char *>(&s1.address());
-	const auto &array2 = reinterpret_cast<const unsigned char *>(&s2.address());
-
-	return std::lexicographical_compare(array1, array1 + s1.length(), array2, array2 + s2.length());
-}
-
-bool operator==(const SocketAddress &s1, const SocketAddress &s2)
-{
-	const auto &array1 = reinterpret_cast<const unsigned char *>(&s1.address());
-	const auto &array2 = reinterpret_cast<const unsigned char *>(&s2.address());
-
-	return std::equal(array1, array1 + s1.length(), array2, array2 + s2.length());
-}
--- a/libcommon/malikania/SocketListener.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,380 +0,0 @@
-/*
- * SocketListener.cpp -- portable select() wrapper
- *
- * Copyright (c) 2013, 2014 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.
- */
-
-#include <algorithm>
-#include <set>
-
-#include "SocketListener.h"
-
-/* --------------------------------------------------------
- * Select implementation
- * -------------------------------------------------------- */
-
-namespace backend {
-
-std::vector<SocketStatus> Select::wait(const SocketTable &table, int ms)
-{
-	timeval maxwait, *towait;
-	fd_set readset;
-	fd_set writeset;
-
-	FD_ZERO(&readset);
-	FD_ZERO(&writeset);
-
-	Socket::Handle max = 0;
-
-	for (const auto &s : table) {
-		if (s.second.second & SocketListener::Read) {
-			FD_SET(s.first, &readset);
-		}
-		if (s.second.second & SocketListener::Write) {
-			FD_SET(s.first, &writeset);
-		}
-
-		if (s.first > max) {
-			max = s.first;
-		}
-	}
-
-	maxwait.tv_sec = 0;
-	maxwait.tv_usec = ms * 1000;
-
-	// Set to nullptr for infinite timeout.
-	towait = (ms < 0) ? nullptr : &maxwait;
-
-	auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
-	if (error == Socket::Error) {
-		throw SocketError(SocketError::System, "select");
-	}
-	if (error == 0) {
-		throw SocketError(SocketError::Timeout, "select", "Timeout while listening");
-	}
-
-	std::vector<SocketStatus> sockets;
-
-	for (auto &c : table) {
-		if (FD_ISSET(c.first, &readset)) {
-			sockets.push_back(SocketStatus{c.second.first, SocketListener::Read});
-		}
-		if (FD_ISSET(c.first, &writeset)) {
-			sockets.push_back(SocketStatus{c.second.first, SocketListener::Write});
-		}
-	}
-
-	return sockets;
-}
-
-/* --------------------------------------------------------
- * Poll implementation
- * -------------------------------------------------------- */
-
-#if defined(SOCKET_HAVE_POLL)
-
-#if defined(_WIN32)
-#  define poll WSAPoll
-#endif
-
-short Poll::topoll(int flags) const noexcept
-{
-	short result(0);
-
-	if (flags & SocketListener::Read) {
-		result |= POLLIN;
-	}
-	if (flags & SocketListener::Write) {
-		result |= POLLOUT;
-	}
-
-	return result;
-}
-
-int Poll::toflags(short &event) const noexcept
-{
-	int flags = 0;
-
-	/*
-	 * Poll implementations mark the socket differently regarding
-	 * the disconnection of a socket.
-	 *
-	 * At least, even if POLLHUP or POLLIN is set, recv() always
-	 * return 0 so we mark the socket as readable.
-	 */
-	if ((event & POLLIN) || (event & POLLHUP)) {
-		flags |= SocketListener::Read;
-	}
-	if (event & POLLOUT) {
-		flags |= SocketListener::Write;
-	}
-
-	// Reset event for safety
-	event = 0;
-
-	return flags;
-}
-
-void Poll::set(const SocketTable &, Socket s, int flags, bool add)
-{
-	if (add) {
-		m_lookup.emplace(s.handle(), s);
-		m_fds.push_back(pollfd{s.handle(), topoll(flags), 0});
-	} else {
-		auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const struct pollfd &pfd) {
-			return pfd.fd == s.handle();
-		});
-
-		it->events |= topoll(flags);
-	}
-}
-
-void Poll::unset(const SocketTable &, Socket s, int flags, bool remove)
-{
-	auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const struct pollfd &pfd) {
-		return pfd.fd == s.handle();
-	});
-
-	if (remove) {
-		m_lookup.erase(it->fd);
-		m_fds.erase(it);
-	} else {
-		it->events &= ~(topoll(flags));
-	}
-}
-
-std::vector<SocketStatus> Poll::wait(const SocketTable &, int ms)
-{
-	auto result = poll(m_fds.data(), m_fds.size(), ms);
-	if (result == 0) {
-		throw SocketError(SocketError::Timeout, "select", "Timeout while listening");
-	}
-	if (result < 0) {
-		throw SocketError(SocketError::System, "poll");
-	}
-
-	std::vector<SocketStatus> sockets;
-	for (auto &fd : m_fds) {
-		if (fd.revents != 0) {
-			sockets.push_back(SocketStatus{m_lookup.at(fd.fd), toflags(fd.revents)});
-		}
-	}
-
-	return sockets;
-}
-
-#endif // !SOCKET_HAVE_POLL
-
-/* --------------------------------------------------------
- * Epoll implementation
- * -------------------------------------------------------- */
-
-#if defined(SOCKET_HAVE_EPOLL)
-
-uint32_t Epoll::toepoll(int flags) const noexcept
-{
-	uint32_t events = 0;
-
-	if (flags & SocketListener::Read) {
-		events |= EPOLLIN;
-	}
-	if (flags & SocketListener::Write) {
-		events |= EPOLLOUT;
-	}
-
-	return events;
-}
-
-int Epoll::toflags(uint32_t events) const noexcept
-{
-	int flags = 0;
-
-	if ((events & EPOLLIN) || (events & EPOLLHUP)) {
-		flags |= SocketListener::Read;
-	}
-	if (events & EPOLLOUT) {
-		flags |= SocketListener::Write;
-	}
-
-	return flags;
-}
-
-void Epoll::update(Socket &sc, int op, int flags)
-{
-	struct epoll_event ev;
-
-	std::memset(&ev, 0, sizeof (struct epoll_event));
-
-	ev.events = flags;
-	ev.data.fd = sc.handle();
-
-	if (epoll_ctl(m_handle, op, sc.handle(), &ev) < 0) {
-		throw SocketError(SocketError::System, "epoll_ctl");
-	}
-}
-
-Epoll::Epoll()
-	: m_handle(epoll_create1(0))
-{
-	if (m_handle < 0) {
-		throw SocketError(SocketError::System, "epoll_create");
-	}
-}
-
-Epoll::~Epoll()
-{
-	close(m_handle);
-}
-
-/*
- * Add a new epoll_event or just update it.
- */
-void Epoll::set(const SocketTable &, Socket &sc, int flags, bool add)
-{
-	update(sc, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, toepoll(flags));
-
-	if (add) {
-		m_events.resize(m_events.size() + 1);
-	}
-}
-
-/*
- * Unset is a bit complicated case because SocketListener tells us which
- * flag to remove but to update epoll descriptor we need to pass
- * the effective flags that we want to be applied.
- *
- * So we put the same flags that are currently effective and remove the
- * requested one.
- */
-void Epoll::unset(const SocketTable &table, Socket &sc, int flags, bool remove)
-{
-	if (remove) {
-		update(sc, EPOLL_CTL_DEL, 0);
-		m_events.resize(m_events.size() - 1);
-	} else {
-		update(sc, EPOLL_CTL_MOD, table.at(sc.handle()).second & ~(toepoll(flags)));
-	}
-}
-
-std::vector<SocketStatus> Epoll::wait(const SocketTable &table, int ms)
-{
-	int ret = epoll_wait(m_handle, m_events.data(), m_events.size(), ms);
-	std::vector<SocketStatus> result;
-
-	if (ret == 0) {
-		throw SocketError(SocketError::Timeout, "epoll_wait");
-	}
-	if (ret < 0) {
-		throw SocketError(SocketError::System, "epoll_wait");
-	}
-
-	for (int i = 0; i < ret; ++i) {
-		result.push_back(SocketStatus{table.at(m_events[i].data.fd).first, toflags(m_events[i].events)});
-	}
-
-	return result;
-}
-
-#endif // !SOCKET_HAVE_EPOLL
-
-/* --------------------------------------------------------
- * Kqueue implementation
- * -------------------------------------------------------- */
-
-#if defined(SOCKET_HAVE_KQUEUE)
-
-Kqueue::Kqueue()
-	: m_handle(kqueue())
-{
-	if (m_handle < 0) {
-		throw SocketError(SocketError::System, "kqueue");
-	}
-}
-
-Kqueue::~Kqueue()
-{
-	close(m_handle);
-}
-
-void Kqueue::update(const Socket &sc, int filter, int flags)
-{
-	struct kevent ev;
-
-	EV_SET(&ev, sc.handle(), filter, flags, 0, 0, nullptr);
-
-	if (kevent(m_handle, &ev, 1, nullptr, 0, nullptr) < 0) {
-		throw SocketError(SocketError::System, "kevent");
-	}
-}
-
-void Kqueue::set(const SocketTable &, const Socket &sc, int flags, bool add)
-{
-	if (flags & SocketListener::Read) {
-		update(sc, EVFILT_READ, EV_ADD | EV_ENABLE);
-	}
-	if (flags & SocketListener::Write) {
-		update(sc, EVFILT_WRITE, EV_ADD | EV_ENABLE);
-	}
-
-	if (add) {
-		m_result.resize(m_result.size() + 1);
-	}
-}
-
-void Kqueue::unset(const SocketTable &, const Socket &sc, int flags, bool remove)
-{
-	if (flags & SocketListener::Read) {
-		update(sc, EVFILT_READ, EV_DELETE);
-	}
-	if (flags & SocketListener::Write) {
-		update(sc, EVFILT_WRITE, EV_DELETE);
-	}
-
-	if (remove) {
-		m_result.resize(m_result.size() - 1);
-	}
-}
-
-std::vector<SocketStatus> Kqueue::wait(const SocketTable &table, int ms)
-{
-	std::vector<SocketStatus> sockets;
-	timespec ts = { 0, 0 };
-	timespec *pts = (ms <= 0) ? nullptr : &ts;
-
-	ts.tv_sec = ms / 1000;
-	ts.tv_nsec = (ms % 1000) * 1000000;
-
-	int nevents = kevent(m_handle, nullptr, 0, &m_result[0], m_result.capacity(), pts);
-
-	if (nevents == 0) {
-		throw SocketError(SocketError::Timeout, "kevent");
-	}
-	if (nevents < 0) {
-		throw SocketError(SocketError::System, "kevent");
-	}
-
-	for (int i = 0; i < nevents; ++i) {
-		Socket sc = table.at(m_result[i].ident).first;
-		int flags = m_result[i].filter == EVFILT_READ ? SocketListener::Read : SocketListener::Write;
-
-		sockets.push_back(SocketStatus{sc, flags});
-	}
-
-	return sockets;
-}
-
-#endif // !SOCKET_HAVE_KQUEUE
-
-} // !backend
--- a/libcommon/malikania/SocketSsl.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,230 +0,0 @@
-/*
- * SocketSsl.cpp -- OpenSSL extension for sockets
- *
- * Copyright (c) 2013, 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.
- */
-
-#include "SocketAddress.h"
-#include "SocketListener.h"
-#include "SocketSsl.h"
-
-namespace {
-
-auto sslMethod(int mflags)
-{
-	if (mflags & SocketSslOptions::All)
-		return SSLv23_method();
-	if (mflags & SocketSslOptions::SSLv3)
-		return SSLv3_method();
-	if (mflags & SocketSslOptions::TLSv1)
-		return TLSv1_method();
-
-	return SSLv23_method();
-}
-
-inline std::string sslError(int error)
-{
-	return ERR_reason_error_string(error);
-}
-
-inline int toDirection(int error)
-{
-	if (error == SocketError::WouldBlockRead)
-		return SocketListener::Read;
-	if (error ==  SocketError::WouldBlockWrite)
-		return SocketListener::Write;
-
-	return 0;
-}
-
-} // !namespace
-
-std::mutex SocketSsl::s_sslMutex;
-std::atomic<bool> SocketSsl::s_sslInitialized{false};
-
-SocketSsl::SocketSsl(Socket::Handle handle, SSL_CTX *context, SSL *ssl)
-	: SocketAbstractTcp(handle)
-	, m_context(context, SSL_CTX_free)
-	, m_ssl(ssl, SSL_free)
-{
-#if !defined(SOCKET_NO_SSL_INIT)
-	if (!s_sslInitialized) {
-		sslInitialize();
-	}
-#endif
-}
-
-SocketSsl::SocketSsl(int family, int protocol, SocketSslOptions options)
-	: SocketAbstractTcp(family, protocol)
-	, m_options(std::move(options))
-{
-#if !defined(SOCKET_NO_SSL_INIT)
-	if (!s_sslInitialized) {
-		sslInitialize();
-	}
-#endif
-}
-
-void SocketSsl::connect(const SocketAddress &address)
-{
-	standardConnect(address);
-
-	// Context first
-	auto context = SSL_CTX_new(sslMethod(m_options.method));
-
-	m_context = ContextHandle(context, SSL_CTX_free);
-
-	// SSL object then
-	auto ssl = SSL_new(context);
-
-	m_ssl = SslHandle(ssl, SSL_free);
-
-	SSL_set_fd(ssl, m_handle);
-
-	auto ret = SSL_connect(ssl);
-
-	if (ret <= 0) {
-		auto error = SSL_get_error(ssl, ret);
-
-		if (error == SSL_ERROR_WANT_READ) {
-			throw SocketError(SocketError::WouldBlockRead, "connect", "Operation in progress");
-		} else if (error == SSL_ERROR_WANT_WRITE) {
-			throw SocketError(SocketError::WouldBlockWrite, "connect", "Operation in progress");
-		} else {
-			throw SocketError(SocketError::System, "connect", sslError(error));
-		}
-	}
-
-	m_state = SocketState::Connected;
-}
-
-void SocketSsl::waitConnect(const SocketAddress &address, int timeout)
-{
-	try {
-		// Initial try
-		connect(address);
-	} catch (const SocketError &ex) {
-		if (ex.code() == SocketError::WouldBlockRead || ex.code() == SocketError::WouldBlockWrite) {
-			SocketListener listener{{*this, toDirection(ex.code())}};
-
-			listener.wait(timeout);
-
-			// Second try
-			connect(address);
-		} else {
-			throw;
-		}
-	}
-}
-
-SocketSsl SocketSsl::accept()
-{
-	SocketAddress dummy;
-
-	return accept(dummy);
-}
-
-SocketSsl SocketSsl::accept(SocketAddress &info)
-{
-	auto client = standardAccept(info);
-	auto context = SSL_CTX_new(sslMethod(m_options.method));
-
-	if (m_options.certificate.size() > 0)
-		SSL_CTX_use_certificate_file(context, m_options.certificate.c_str(), SSL_FILETYPE_PEM);
-	if (m_options.privateKey.size() > 0)
-		SSL_CTX_use_PrivateKey_file(context, m_options.privateKey.c_str(), SSL_FILETYPE_PEM);
-	if (m_options.verify && !SSL_CTX_check_private_key(context)) {
-		client.close();
-		throw SocketError(SocketError::System, "accept", "certificate failure");
-	}
-
-	// SSL object
-	auto ssl = SSL_new(context);
-
-	SSL_set_fd(ssl, client.handle());
-
-	auto ret = SSL_accept(ssl);
-
-	if (ret <= 0) {
-		auto error = SSL_get_error(ssl, ret);
-
-		if (error == SSL_ERROR_WANT_READ) {
-			throw SocketError(SocketError::WouldBlockRead, "accept", "Operation would block");
-		} else if (error == SSL_ERROR_WANT_WRITE) {
-			throw SocketError(SocketError::WouldBlockWrite, "accept", "Operation would block");
-		} else {
-			throw SocketError(SocketError::System, "accept", sslError(error));
-		}
-	}
-
-	return SocketSsl(client.handle(), context, ssl);
-}
-
-unsigned SocketSsl::recv(void *data, unsigned len)
-{
-	auto nbread = SSL_read(m_ssl.get(), data, len);
-
-	if (nbread <= 0) {
-		auto error = SSL_get_error(m_ssl.get(), nbread);
-
-		if (error == SSL_ERROR_WANT_READ) {
-			throw SocketError(SocketError::WouldBlockRead, "recv", "Operation would block");
-		} else if (error == SSL_ERROR_WANT_WRITE) {
-			throw SocketError(SocketError::WouldBlockWrite, "recv", "Operation would block");
-		} else {
-			throw SocketError(SocketError::System, "recv", sslError(error));
-		}
-	}
-
-	return nbread;
-}
-
-unsigned SocketSsl::waitRecv(void *data, unsigned len, int timeout)
-{
-	SocketListener listener{{*this, SocketListener::Read}};
-
-	listener.wait(timeout);
-
-	return recv(data, len);
-}
-
-unsigned SocketSsl::send(const void *data, unsigned len)
-{
-	auto nbread = SSL_write(m_ssl.get(), data, len);
-
-	if (nbread <= 0) {
-		auto error = SSL_get_error(m_ssl.get(), nbread);
-
-		if (error == SSL_ERROR_WANT_READ) {
-			throw SocketError(SocketError::WouldBlockRead, "send", "Operation would block");
-		} else if (error == SSL_ERROR_WANT_WRITE) {
-			throw SocketError(SocketError::WouldBlockWrite, "send", "Operation would block");
-		} else {
-			throw SocketError(SocketError::System, "send", sslError(error));
-		}
-	}
-
-	return nbread;
-}
-
-unsigned SocketSsl::waitSend(const void *data, unsigned len, int timeout)
-{
-	SocketListener listener{{*this, SocketListener::Write}};
-
-	listener.wait(timeout);
-
-	return send(data, len);
-}
-
--- a/libcommon/malikania/SocketTcp.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * SocketTcp.cpp -- portable C++ socket wrappers
- *
- * Copyright (c) 2013, 2014 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.
- */
-
-#include "SocketAddress.h"
-#include "SocketListener.h"
-#include "SocketTcp.h"
-
-/* --------------------------------------------------------
- * SocketAbstractTcp
- * -------------------------------------------------------- */
-
-void SocketAbstractTcp::listen(int max)
-{
-	if (::listen(m_handle, max) == Error) {
-		throw SocketError(SocketError::System, "listen");
-	}
-}
-
-Socket SocketAbstractTcp::standardAccept(SocketAddress &info)
-{
-	Socket::Handle handle;
-
-	// Store the information
-	sockaddr_storage address;
-	socklen_t addrlen;
-
-	addrlen = sizeof (sockaddr_storage);
-	handle = ::accept(m_handle, reinterpret_cast<sockaddr *>(&address), &addrlen);
-
-	if (handle == Invalid) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "accept", error);
-		}
-
-		throw SocketError(SocketError::System, "accept", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "accept");
-		}
-
-		throw SocketError(SocketError::System, "accept");
-#endif
-	}
-
-	info = SocketAddress(address, addrlen);
-
-	return Socket(handle);
-}
-
-void SocketAbstractTcp::standardConnect(const SocketAddress &address)
-{
-	if (m_state == SocketState::Connected) {
-		return;
-	}
-
-	auto &sa = address.address();
-	auto addrlen = address.length();
-
-	if (::connect(m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == Error) {
-		/*
-		 * Determine if the error comes from a non-blocking connect that cannot be
-		 * accomplished yet.
-		 */
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "connect", error);
-		}
-
-		throw SocketError(SocketError::System, "connect", error);
-#else
-		if (errno == EINPROGRESS) {
-			throw SocketError(SocketError::WouldBlockWrite, "connect");
-		}
-
-		throw SocketError(SocketError::System, "connect");
-#endif
-	}
-
-	m_state = SocketState::Connected;
-}
-
-/* --------------------------------------------------------
- * SocketTcp
- * -------------------------------------------------------- */
-
-SocketTcp SocketTcp::accept()
-{
-	SocketAddress dummy;
-
-	return accept(dummy);
-}
-
-SocketTcp SocketTcp::accept(SocketAddress &info)
-{
-	return standardAccept(info);
-}
-
-void SocketTcp::connect(const SocketAddress &address)
-{
-	return standardConnect(address);
-}
-
-void SocketTcp::waitConnect(const SocketAddress &address, int timeout)
-{
-	if (m_state == SocketState::Connected) {
-		return;
-	}
-
-	// Initial try
-	try {
-		connect(address);
-	} catch (const SocketError &ex) {
-		if (ex.code() == SocketError::WouldBlockWrite) {
-			SocketListener listener{{*this, SocketListener::Write}};
-
-			listener.wait(timeout);
-
-			// Socket is writable? Check if there is an error
-			int error = get<int>(SOL_SOCKET, SO_ERROR);
-
-			if (error) {
-				throw SocketError(SocketError::System, "connect", error);
-			}
-		} else {
-			throw;
-		}
-	}
-
-	m_state = SocketState::Connected;
-}
-
-SocketTcp SocketTcp::waitAccept(int timeout)
-{
-	SocketAddress dummy;
-
-	return waitAccept(dummy, timeout);
-}
-
-SocketTcp SocketTcp::waitAccept(SocketAddress &info, int timeout)
-{
-	SocketListener listener{{*this, SocketListener::Read}};
-
-	listener.wait(timeout);
-
-	return accept(info);
-}
-
-unsigned SocketTcp::recv(void *data, unsigned dataLen)
-{
-	int nbread;
-
-	nbread = ::recv(m_handle, (Socket::Arg)data, dataLen, 0);
-	if (nbread == Error) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "recv", error);
-		}
-
-		throw SocketError(SocketError::System, "recv", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "recv");
-		}
-
-		throw SocketError(SocketError::System, "recv");
-#endif
-	} else if (nbread == 0) {
-		m_state = SocketState::Closed;
-	}
-
-	return (unsigned)nbread;
-}
-
-unsigned SocketTcp::waitRecv(void *data, unsigned length, int timeout)
-{
-	SocketListener listener{{*this, SocketListener::Read}};
-
-	listener.wait(timeout);
-
-	return recv(data, length);
-}
-
-unsigned SocketTcp::send(const void *data, unsigned length)
-{
-	int nbsent;
-
-	nbsent = ::send(m_handle, (Socket::ConstArg)data, length, 0);
-	if (nbsent == Error) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "send", error);
-		}
-
-		throw SocketError(SocketError::System, "send", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "send");
-		}
-
-		throw SocketError(SocketError::System, "send");
-#endif
-	}
-
-	return (unsigned)nbsent;
-}
-
-unsigned SocketTcp::waitSend(const void *data, unsigned length, int timeout)
-{
-	SocketListener listener{{*this, SocketListener::Write}};
-
-	listener.wait(timeout);
-
-	return send(data, length);
-}
--- a/libcommon/malikania/Sockets.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,713 +0,0 @@
-/*
- * Sockets.cpp -- portable C++ socket wrappers
- *
- * Copyright (c) 2013-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.
- */
-
-#define TIMEOUT_MSG "operation timeout"
-
-#include <algorithm>
-#include <atomic>
-#include <cstring>
-#include <mutex>
-
-#include "Sockets.h"
-
-namespace malikania {
-
-namespace net {
-
-/*
- * Portable constants
- * ------------------------------------------------------------------
- */
-
-/* {{{ Constants */
-
-#if defined(_WIN32)
-
-const Handle Invalid{INVALID_SOCKET};
-const int Failure{SOCKET_ERROR};
-
-#else
-
-const Handle Invalid{-1};
-const int Failure{-1};
-
-#endif
-
-/* }}} */
-
-/*
- * Portable functions
- * ------------------------------------------------------------------
- */
-
-/* {{{ Functions */
-
-#if defined(_WIN32)
-
-namespace {
-
-static std::mutex s_mutex;
-static std::atomic<bool> s_initialized{false};
-
-} // !namespace
-
-#endif // !_WIN32
-
-void init() noexcept
-{
-#if defined(_WIN32)
-	std::lock_guard<std::mutex> lock(s_mutex);
-
-	if (!s_initialized) {
-		s_initialized = true;
-
-		WSADATA wsa;
-		WSAStartup(MAKEWORD(2, 2), &wsa);
-
-		/*
-		 * If SOCKET_WSA_NO_INIT is not set then the user
-		 * must also call finish himself.
-		 */
-#if !defined(SOCKET_NO_AUTO_INIT)
-		atexit(finish);
-#endif
-	}
-#endif
-}
-
-void finish() noexcept
-{
-#if defined(_WIN32)
-	WSACleanup();
-#endif
-}
-
-std::string error(int errn)
-{
-#if defined(_WIN32)
-	LPSTR str = nullptr;
-	std::string errmsg = "Unknown error";
-
-	FormatMessageA(
-		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-		NULL,
-		errn,
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		(LPSTR)&str, 0, NULL);
-
-
-	if (str) {
-		errmsg = std::string(str);
-		LocalFree(str);
-	}
-
-	return errmsg;
-#else
-	return strerror(errn);
-#endif
-}
-
-std::string error()
-{
-#if defined(_WIN32)
-	return error(WSAGetLastError());
-#else
-	return error(errno);
-#endif
-}
-
-/* }}} */
-
-/*
- * SSL stuff
- * ------------------------------------------------------------------
- */
-
-/* {{{ SSL initialization */
-
-#if !defined(SOCKET_NO_SSL)
-
-namespace ssl {
-
-namespace {
-
-std::mutex mutex;
-std::atomic<bool> initialized{false};
-
-} // !namespace
-
-void finish() noexcept
-{
-	ERR_free_strings();
-}
-
-void init() noexcept
-{
-	std::lock_guard<std::mutex> lock{mutex};
-
-	if (!initialized) {
-		initialized = true;
-
-		SSL_library_init();
-		SSL_load_error_strings();
-		OpenSSL_add_all_algorithms();
-
-#if !defined(SOCKET_NO_AUTO_SSL_INIT)
-		atexit(finish);
-#endif // SOCKET_NO_AUTO_SSL_INIT
-	}
-}
-
-} // !ssl
-
-#endif // SOCKET_NO_SSL
-
-/* }}} */
-
-/*
- * Error class
- * ------------------------------------------------------------------
- */
-
-/* {{{ Error */
-
-Error::Error(Code code, std::string function)
-	: m_code{code}
-	, m_function{std::move(function)}
-	, m_error{error()}
-{
-}
-
-Error::Error(Code code, std::string function, int n)
-	: m_code{code}
-	, m_function{std::move(function)}
-	, m_error{error(n)}
-{
-}
-
-Error::Error(Code code, std::string function, std::string error)
-	: m_code{code}
-	, m_function{std::move(function)}
-	, m_error{std::move(error)}
-{
-}
-
-/* }}} */
-
-/*
- * Predefine addressed to be used
- * ------------------------------------------------------------------
- */
-
-/* {{{ Addresses */
-
-namespace address {
-
-/* Default domain */
-int Ip::m_default{AF_INET};
-
-Ip::Ip(Type domain) noexcept
-	: m_domain(static_cast<int>(domain))
-{
-	assert(m_domain == AF_INET6 || m_domain == AF_INET);
-
-	if (m_domain == AF_INET6) {
-		std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
-	} else {
-		std::memset(&m_sin, 0, sizeof (sockaddr_in));
-	}
-}
-
-Ip::Ip(const std::string &host, int port, Type domain)
-	: m_domain(static_cast<int>(domain))
-{
-	assert(m_domain == AF_INET6 || m_domain == AF_INET);
-
-	if (host == "*") {
-		if (m_domain == AF_INET6) {
-			std::memset(&m_sin6, 0, sizeof (sockaddr_in6));
-
-			m_length = sizeof (sockaddr_in6);
-			m_sin6.sin6_addr = in6addr_any;
-			m_sin6.sin6_family = AF_INET6;
-			m_sin6.sin6_port = htons(port);
-		} else {
-			std::memset(&m_sin, 0, sizeof (sockaddr_in));
-
-			m_length = sizeof (sockaddr_in);
-			m_sin.sin_addr.s_addr = INADDR_ANY;
-			m_sin.sin_family = AF_INET;
-			m_sin.sin_port = htons(port);
-		}
-	} else {
-		addrinfo hints, *res;
-
-		std::memset(&hints, 0, sizeof (addrinfo));
-		hints.ai_family = domain;
-
-		auto error = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
-		if (error != 0) {
-			throw Error{Error::System, "getaddrinfo", gai_strerror(error)};
-		}
-
-		if (m_domain == AF_INET6) {
-			std::memcpy(&m_sin6, res->ai_addr, res->ai_addrlen);
-		} else {
-			std::memcpy(&m_sin, res->ai_addr, res->ai_addrlen);
-		}
-
-		m_length = res->ai_addrlen;
-		freeaddrinfo(res);
-	}
-}
-
-Ip::Ip(const sockaddr_storage *ss, socklen_t length) noexcept
-	: m_length{length}
-	, m_domain{ss->ss_family}
-{
-	assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET);
-
-	if (ss->ss_family == AF_INET6) {
-		std::memcpy(&m_sin6, ss, length);
-	} else if (ss->ss_family == AF_INET) {
-		std::memcpy(&m_sin, ss, length);
-	}
-}
-
-#if !defined(_WIN32)
-
-Local::Local() noexcept
-{
-	std::memset(&m_sun, 0, sizeof (sockaddr_un));
-}
-
-Local::Local(std::string path, bool rm) noexcept
-	: m_path{std::move(path)}
-{
-	/* Silently remove the file even if it fails */
-	if (rm) {
-		::remove(m_path.c_str());
-	}
-
-	/* Copy the path */
-	std::memset(m_sun.sun_path, 0, sizeof (m_sun.sun_path));
-	std::strncpy(m_sun.sun_path, m_path.c_str(), sizeof (m_sun.sun_path) - 1);
-
-	/* Set the parameters */
-	m_sun.sun_family = AF_LOCAL;
-}
-
-Local::Local(const sockaddr_storage *ss, socklen_t length) noexcept
-{
-	assert(ss->ss_family == AF_LOCAL);
-
-	if (ss->ss_family == AF_LOCAL) {
-		std::memcpy(&m_sun, ss, length);
-		m_path = reinterpret_cast<const sockaddr_un &>(m_sun).sun_path;
-	}
-}
-
-#endif // !_WIN32
-
-} // !address
-
-/* }}} */
-
-/*
- * Select
- * ------------------------------------------------------------------
- */
-
-/* {{{ Select */
-
-std::vector<ListenerStatus> Select::wait(const ListenerTable &table, int ms)
-{
-	timeval maxwait, *towait;
-	fd_set readset;
-	fd_set writeset;
-
-	FD_ZERO(&readset);
-	FD_ZERO(&writeset);
-
-	Handle max = 0;
-
-	for (const auto &pair : table) {
-		if ((pair.second & Condition::Readable) == Condition::Readable) {
-			FD_SET(pair.first, &readset);
-		}
-		if ((pair.second & Condition::Writable) == Condition::Writable) {
-			FD_SET(pair.first, &writeset);
-		}
-
-		if (pair.first > max) {
-			max = pair.first;
-		}
-	}
-
-	maxwait.tv_sec = 0;
-	maxwait.tv_usec = ms * 1000;
-
-	// Set to nullptr for infinite timeout.
-	towait = (ms < 0) ? nullptr : &maxwait;
-
-	auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
-	if (error == Failure) {
-		throw Error{Error::System, "select"};
-	}
-	if (error == 0) {
-		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
-	}
-
-	std::vector<ListenerStatus> sockets;
-
-	for (const auto &pair : table) {
-		if (FD_ISSET(pair.first, &readset)) {
-			sockets.push_back(ListenerStatus{pair.first, Condition::Readable});
-		}
-		if (FD_ISSET(pair.first, &writeset)) {
-			sockets.push_back(ListenerStatus{pair.first, Condition::Writable});
-		}
-	}
-
-	return sockets;
-}
-
-/* }}} */
-
-/*
- * Poll
- * ------------------------------------------------------------------
- */
-
-/* {{{ Poll */
-
-/*
- * Poll implementation
- * ------------------------------------------------------------------
- */
-
-#if defined(SOCKET_HAVE_POLL)
-
-#if defined(_WIN32)
-#  define poll WSAPoll
-#endif
-
-short Poll::toPoll(Condition condition) const noexcept
-{
-	short result(0);
-
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		result |= POLLIN;
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		result |= POLLOUT;
-	}
-
-	return result;
-}
-
-Condition Poll::toCondition(short &event) const noexcept
-{
-	Condition condition{Condition::None};
-
-	/*
-	 * Poll implementations mark the socket differently regarding
-	 * the disconnection of a socket.
-	 *
-	 * At least, even if POLLHUP or POLLIN is set, recv() always
-	 * return 0 so we mark the socket as readable.
-	 */
-	if ((event & POLLIN) || (event & POLLHUP)) {
-		condition |= Condition::Readable;
-	}
-	if (event & POLLOUT) {
-		condition |= Condition::Writable;
-	}
-
-	/* Reset event for safety */
-	event = 0;
-
-	return condition;
-}
-
-void Poll::set(const ListenerTable &, Handle h, Condition condition, bool add)
-{
-	if (add) {
-		m_fds.push_back(pollfd{h, toPoll(condition), 0});
-	} else {
-		auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
-			return pfd.fd == h;
-		});
-
-		it->events |= toPoll(condition);
-	}
-}
-
-void Poll::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
-{
-	auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const pollfd &pfd) {
-		return pfd.fd == h;
-	});
-
-	if (remove) {
-		m_fds.erase(it);
-	} else {
-		it->events &= ~(toPoll(condition));
-	}
-}
-
-std::vector<ListenerStatus> Poll::wait(const ListenerTable &, int ms)
-{
-	auto result = poll(m_fds.data(), m_fds.size(), ms);
-	if (result == 0) {
-		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
-	}
-	if (result < 0) {
-		throw Error{Error::System, "poll"};
-	}
-
-	std::vector<ListenerStatus> sockets;
-	for (auto &fd : m_fds) {
-		if (fd.revents != 0) {
-			sockets.push_back(ListenerStatus{fd.fd, toCondition(fd.revents)});
-		}
-	}
-
-	return sockets;
-}
-
-#endif // !SOCKET_HAVE_POLL
-
-/* }}} */
-
-/*
- * Epoll implementation
- * ------------------------------------------------------------------
- */
-
-/* {{{ Epoll */
-
-#if defined(SOCKET_HAVE_EPOLL)
-
-uint32_t Epoll::toEpoll(Condition condition) const noexcept
-{
-	uint32_t events = 0;
-
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		events |= EPOLLIN;
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		events |= EPOLLOUT;
-	}
-
-	return events;
-}
-
-Condition Epoll::toCondition(uint32_t events) const noexcept
-{
-	Condition condition{Condition::None};
-
-	if ((events & EPOLLIN) || (events & EPOLLHUP)) {
-		condition |= Condition::Readable;
-	}
-	if (events & EPOLLOUT) {
-		condition |= Condition::Writable;
-	}
-
-	return condition;
-}
-
-void Epoll::update(Handle h, int op, int eflags)
-{
-	epoll_event ev;
-
-	std::memset(&ev, 0, sizeof (epoll_event));
-
-	ev.events = eflags;
-	ev.data.fd = h;
-
-	if (epoll_ctl(m_handle, op, h, &ev) < 0) {
-		throw Error{Error::System, "epoll_ctl"};
-	}
-}
-
-Epoll::Epoll()
-	: m_handle{epoll_create1(0)}
-{
-	if (m_handle < 0) {
-		throw Error{Error::System, "epoll_create"};
-	}
-}
-
-Epoll::~Epoll()
-{
-	close(m_handle);
-}
-
-/*
- * For set and unset, we need to apply the whole flags required, so if the socket
- * was set to Connection::Readable and user add Connection::Writable, we must
- * place both.
- */
-void Epoll::set(const ListenerTable &table, Handle sc, Condition condition, bool add)
-{
-	if (add) {
-		update(sc, EPOLL_CTL_ADD, toEpoll(condition));
-		m_events.resize(m_events.size() + 1);
-	} else {
-		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) | condition));
-	}
-}
-
-/*
- * Unset is a bit complicated case because Listener tells us which
- * flag to remove but to update epoll descriptor we need to pass
- * the effective flags that we want to be applied.
- *
- * So we put the same flags that are currently effective and remove the
- * requested one.
- */
-void Epoll::unset(const ListenerTable &table, Handle sc, Condition condition, bool remove)
-{
-	if (remove) {
-		update(sc, EPOLL_CTL_DEL, 0);
-		m_events.resize(m_events.size() - 1);
-	} else {
-		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) & ~(condition)));
-	}
-}
-
-std::vector<ListenerStatus> Epoll::wait(const ListenerTable &, int ms)
-{
-	int ret = epoll_wait(m_handle, m_events.data(), m_events.size(), ms);
-	std::vector<ListenerStatus> result;
-
-	if (ret == 0) {
-		throw Error{Error::Timeout, "epoll_wait", TIMEOUT_MSG};
-	}
-	if (ret < 0) {
-		throw Error{Error::System, "epoll_wait"};
-	}
-
-	for (int i = 0; i < ret; ++i) {
-		result.push_back(ListenerStatus{m_events[i].data.fd, toCondition(m_events[i].events)});
-	}
-
-	return result;
-}
-
-#endif // !SOCKET_HAVE_EPOLL
-
-/* }}} */
-
-/*
- * Kqueue implementation
- * ------------------------------------------------------------------
- */
-
-/* {{{ Kqueue */
-
-#if defined(SOCKET_HAVE_KQUEUE)
-
-Kqueue::Kqueue()
-	: m_handle(kqueue())
-{
-	if (m_handle < 0) {
-		throw Error{Error::System, "kqueue"};
-	}
-}
-
-Kqueue::~Kqueue()
-{
-	close(m_handle);
-}
-
-void Kqueue::update(Handle h, int filter, int kflags)
-{
-	struct kevent ev;
-
-	EV_SET(&ev, h, filter, kflags, 0, 0, nullptr);
-
-	if (kevent(m_handle, &ev, 1, nullptr, 0, nullptr) < 0) {
-		throw Error{Error::System, "kevent"};
-	}
-}
-
-void Kqueue::set(const ListenerTable &, Handle h, Condition condition, bool add)
-{
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		update(h, EVFILT_READ, EV_ADD | EV_ENABLE);
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		update(h, EVFILT_WRITE, EV_ADD | EV_ENABLE);
-	}
-
-	if (add) {
-		m_result.resize(m_result.size() + 1);
-	}
-}
-
-void Kqueue::unset(const ListenerTable &, Handle h, Condition condition, bool remove)
-{
-	if ((condition & Condition::Readable) == Condition::Readable) {
-		update(h, EVFILT_READ, EV_DELETE);
-	}
-	if ((condition & Condition::Writable) == Condition::Writable) {
-		update(h, EVFILT_WRITE, EV_DELETE);
-	}
-
-	if (remove) {
-		m_result.resize(m_result.size() - 1);
-	}
-}
-
-std::vector<ListenerStatus> Kqueue::wait(const ListenerTable &, int ms)
-{
-	std::vector<ListenerStatus> sockets;
-	timespec ts = { 0, 0 };
-	timespec *pts = (ms <= 0) ? nullptr : &ts;
-
-	ts.tv_sec = ms / 1000;
-	ts.tv_nsec = (ms % 1000) * 1000000;
-
-	int nevents = kevent(m_handle, nullptr, 0, &m_result[0], m_result.capacity(), pts);
-
-	if (nevents == 0) {
-		throw Error{Error::Timeout, "kevent", TIMEOUT_MSG};
-	}
-	if (nevents < 0) {
-		throw Error{Error::System, "kevent"};
-	}
-
-	for (int i = 0; i < nevents; ++i) {
-		sockets.push_back(ListenerStatus{
-			static_cast<Handle>(m_result[i].ident),
-			m_result[i].filter == EVFILT_READ ? Condition::Readable : Condition::Writable
-		});
-	}
-
-	return sockets;
-}
-
-#endif // !SOCKET_HAVE_KQUEUE
-
-/* }}} */
-
-} // !net
-
-} // !malikania
--- a/libcommon/malikania/Sockets.h	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4092 +0,0 @@
-/*
- * Sockets.h -- portable C++ socket wrappers
- *
- * Copyright (c) 2013-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 _SOCKETS_H_
-#define _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 malikania {
-
-/**
- * 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;
-
-		return m_proto.recv(*this, data, length);
-	}
-
-	/**
-	 * 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;
-
-		return m_proto.send(*this, data, length);
-	}
-
-	/**
-	 * 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 {
-		mutable sockaddr_in m_sin;
-		mutable 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);
-	}
-
-	/**
-	 * Get the IP address in textual form.
-	 *
-	 * @return the address
-	 * @throw Error on errors
-	 */
-	std::string ip() const
-	{
-		char result[128];
-
-		std::memset(result, 0, sizeof (result));
-
-		if (m_domain == AF_INET6) {
-			if (!inet_ntop(AF_INET6, &m_sin6.sin6_addr, result, sizeof (result))) {
-				throw Error{Error::System, "inet_ntop"};
-			}
-		} else {
-			if (!inet_ntop(AF_INET, &m_sin.sin_addr, result, sizeof (result))) {
-				throw Error{Error::System, "inet_ntop"};
-			}
-		}
-
-		return result;
-	}
-};
-
-#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)
-	{
-		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)
-	{
-		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
-
-} // !malikania
-
-#endif // !_SOCKETS_H_
--- a/libserver/CMakeLists.txt	Tue Mar 22 22:50:35 2016 +0100
+++ b/libserver/CMakeLists.txt	Tue Mar 22 23:02:56 2016 +0100
@@ -16,24 +16,24 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #
 
-set(
-	HEADERS
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Server.h
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ServerApp.h
-)
-
-set(
-	SOURCES
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Server.cpp
-	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ServerApp.cpp
-)
-
-malikania_create_library(
-	PROJECT libserver
-	TARGET libserver
-	SOURCES ${HEADERS} ${SOURCES}
-	PUBLIC_INCLUDES
-		${CMAKE_CURRENT_SOURCE_DIR}
-	LIBRARIES
-		libcommon
-)
+# set(
+# 	HEADERS
+# 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Server.h
+# 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ServerApp.h
+# )
+#
+# set(
+# 	SOURCES
+# 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/Server.cpp
+# 	${CMAKE_CURRENT_SOURCE_DIR}/malikania/ServerApp.cpp
+# )
+#
+# malikania_create_library(
+# 	PROJECT libserver
+# 	TARGET libserver
+# 	SOURCES ${HEADERS} ${SOURCES}
+# 	PUBLIC_INCLUDES
+# 		${CMAKE_CURRENT_SOURCE_DIR}
+# 	LIBRARIES
+# 		libcommon
+# )
--- a/libserver/malikania/Server.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#include "Server.h"
-
-namespace malikania {
-
-#if 0
-
-net::address::Ip Server::buildIp(const ServerSettings &st) const noexcept
-{
-	return net::address::Ip(st.address, st.port);
-}
-
-net::protocol::Tls Server::buildTls(const ServerSettings &st) const noexcept
-{
-	net::protocol::Tls tls;
-
-
-	return tls;
-}
-
-Server::Server(const ServerSettings &st)
-	: m_server(net::address::Ip)
-{
-}
-
-#endif
-
-} // !malikania
--- a/libserver/malikania/Server.h	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-#ifndef MALIKANIA_SERVER_H
-#define MALIKANIA_SERVER_H
-
-#include <cstdint>
-
-#include <malikania/Sockets.h>
-
-namespace malikania {
-
-class ServerSettings {
-public:
-	std::string address{"*"};
-	std::uint16_t port{3320};
-};
-
-class Server {
-private:
-	using StreamServer = net::StreamServer<net::address::Ip, net::protocol::Tls>;
-
-	StreamServer m_server;
-
-#if 0
-
-	net::address::Ip buildIp() const noexcept;
-	net::protocol::Tls buildTls() const noexcept;
-
-#endif
-
-public:
-	/**
-	 * Construct a server.
-	 *
-	 * @param st the settings
-	 */
-	//Server(const ServerSettings &st);
-
-	/**
-	 * Poll the next events.
-	 *
-	 * @param timeeout
-	 */
-	void poll(unsigned timeout = -1);
-};
-
-} // !malikania
-
-#endif // !MALIKANIA_SERVER_H
--- a/libserver/malikania/ServerApp.cpp	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * ServerApp.cpp -- main class for creating a server application
- *
- * Copyright (c) 2013-2015 Malikania Authors
- *
- * 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.
- */
-
-#include <malikania/Game.h>
-#include <malikania/Json.h>
-
-#include "ServerApp.h"
-
-namespace malikania {
-
-ServerApp::ServerApp(const ResourcesLoader &)
-	//: Game{directory.metadata()}
-{
-}
-
-} // !malikania
--- a/libserver/malikania/ServerApp.h	Tue Mar 22 22:50:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * ServerApp.h -- main class for creating a server application
- *
- * Copyright (c) 2013-2015 Malikania Authors
- *
- * 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 SERVER_APP_H
-#define SERVER_APP_H
-
-#include <malikania/Game.h>
-#include <malikania/ResourcesLoader.h>
-
-namespace malikania {
-
-/**
- * @class ServerApp
- * @brief Create a server application
- */
-class ServerApp {
-public:
-	/**
-	 * Create a server application.
-	 *
-	 * @param directory the directory
-	 */
-	ServerApp(const ResourcesLoader &directory);
-};
-
-} // !malikania
-
-#endif // !SERVER_APP_H