webgui: mod_netconf: --with-notifications

using libwebsockets
diff --git a/src/Makefile.in b/src/Makefile.in
index 3c43b0a..bbc80db 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -24,7 +24,8 @@
 APXS=/usr/sbin/apxs
 
 CFLAGS=-I/usr/include/json
-LIBS=-lnetconf -ljson
+CPPFLAGS=@CPPFLAGS@
+LIBS=@LIBS@
 
 SRCS=mod_netconf.c \
      test-client.c
@@ -34,11 +35,14 @@
 all: module client
 
 module: mod_netconf.c
-	$(APXS) $(LIBS) $(ARCSID) -c mod_netconf.c
+	$(APXS) $(LIBS) $(ARCSID) $(CPPFLAGS) -c mod_netconf.c notification-server.c
 
 client: test-client.c
 	gcc $(RCSID) -std=gnu99 -Wall -g -ljson -I/usr/include/json test-client.c -o test-client
 
+notification-test: notification-server.c
+	gcc $(RCSID) -std=gnu99 -Wall -g -lwebsockets -DTEST_NOTIFICATION_SERVER notification-server.c -o notification-test
+
 #install: $(NAME).la
 #	$(APXS) -i $(NAME).la
 
diff --git a/src/configure b/src/configure
index 5229695..5bce59a 100755
--- a/src/configure
+++ b/src/configure
@@ -696,6 +696,7 @@
 ac_subst_files=''
 ac_user_opts='
 enable_option_checking
+with_notifications
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1323,6 +1324,11 @@
    esac
   cat <<\_ACEOF
 
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-notifications    Enable notifications
+
 Some influential environment variables:
   CC          C compiler command
   CFLAGS      C compiler flags
@@ -1950,6 +1956,7 @@
 
 RELEASE=1
 
+LIBS="-lnetconf -ljson"
 
 if test "`git show > /dev/null 2>&1;echo $?`" = "0"; then
 	RCSID="-DRCSID=\\\"\$(IDGIT)\\\""
@@ -2990,6 +2997,7 @@
 
 REQS="$REQS libnetconf"
 BUILDREQS="$BUILDREQS libnetconf-devel"
+CPPFLAGS=""
 
 # Checks for header files.
 ac_ext=c
@@ -3763,6 +3771,21 @@
 
 
 
+# Check whether --with-notifications was given.
+if test "${with_notifications+set}" = set; then
+  withval=$with_notifications;
+		CPPFLAGS=" -DWITH_NOTIFICATIONS "
+		LIBS="-lwebsockets $LIBS"
+
+else
+  CPPFLAGS="$CPPFLAGS"
+
+fi
+
+
+
+
+
 
 
 
diff --git a/src/configure.in b/src/configure.in
index 2d122af..43e7ca2 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -14,6 +14,7 @@
 
 RELEASE=1
 AC_SUBST(RELEASE)
+LIBS="-lnetconf -ljson"
 
 if test "`git show > /dev/null 2>&1;echo $?`" = "0"; then
 	RCSID="-DRCSID=\\\"\$(IDGIT)\\\""
@@ -30,6 +31,7 @@
 AC_SEARCH_LIBS([ncds_apply_rpc],[netconf], ,AC_MSG_ERROR([libnetconf not found!]))
 REQS="$REQS libnetconf"
 BUILDREQS="$BUILDREQS libnetconf-devel"
+CPPFLAGS=""
 
 # Checks for header files.
 AC_CHECK_HEADER([libnetconf.h], ,AC_MSG_ERROR([libnetconf.h not found!]))
@@ -43,11 +45,22 @@
 	AC_MSG_WARN([Due to missing rpmbuild you will not able to generate RPM package.])
 fi
 
+
+AC_ARG_WITH([notifications],
+	[AC_HELP_STRING([--with-notifications], [Enable notifications])],
+	[
+		CPPFLAGS=" -DWITH_NOTIFICATIONS "
+		LIBS="-lwebsockets $LIBS"
+	],
+	[CPPFLAGS="$CPPFLAGS"]
+)
+
 AC_SUBST(REQS)
 AC_SUBST(BUILDREQS)
 AC_SUBST(CPPFLAGS)
 AC_SUBST(RCSID)
 AC_SUBST(ARCSID)
+AC_SUBST(LIBS)
 
 AC_CONFIG_FILES([Makefile])
 AC_CONFIG_FILES([mod_netconf.spec])
diff --git a/src/libwebsockets.h b/src/libwebsockets.h
new file mode 100644
index 0000000..b7eaa41
--- /dev/null
+++ b/src/libwebsockets.h
@@ -0,0 +1,982 @@
+/*
+ * libwebsockets - small server side websockets and web server implementation
+ *
+ * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation:
+ *  version 2.1 of the License.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+
+#ifndef __LIBWEBSOCKET_H__
+#define __LIBWEBSOCKET_H__
+
+#ifdef __cplusplus
+extern "C" {
+#include <cstddef>
+#endif
+
+#ifdef WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stddef.h>
+#include "../win32port/win32helpers/websock-w32.h"
+
+#include "../win32port/win32helpers/gettimeofday.h"
+
+#define strcasecmp stricmp
+#define getdtablesize() 30000
+
+typedef int ssize_t;
+
+#ifdef LWS_DLL
+#ifdef LWS_INTERNAL
+#define LWS_EXTERN extern __declspec(dllexport)
+#else
+#define LWS_EXTERN extern __declspec(dllimport)
+#endif
+#endif
+
+#else // NOT WIN32
+#include <poll.h>
+#include <unistd.h>
+#endif
+
+#include <assert.h>
+
+#ifndef LWS_EXTERN
+#define LWS_EXTERN extern
+#endif
+
+#define CONTEXT_PORT_NO_LISTEN 0
+#define MAX_MUX_RECURSION 2
+
+enum lws_log_levels {
+	LLL_ERR = 1 << 0,
+	LLL_WARN = 1 << 1,
+	LLL_NOTICE = 1 << 2,
+	LLL_INFO = 1 << 3,
+	LLL_DEBUG = 1 << 4,
+	LLL_PARSER = 1 << 5,
+	LLL_HEADER = 1 << 6,
+	LLL_EXT = 1 << 7,
+	LLL_CLIENT = 1 << 8,
+	LLL_LATENCY = 1 << 9,
+
+	LLL_COUNT = 10 /* set to count of valid flags */
+};
+
+LWS_EXTERN void _lws_log(int filter, const char *format, ...);
+
+/* notice, warn and log are always compiled in */
+#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
+#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
+#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
+/*
+ *  weaker logging can be deselected at configure time using --disable-debug
+ *  that gets rid of the overhead of checking while keeping _warn and _err
+ *  active
+ */
+#ifdef _DEBUG
+
+#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
+#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
+#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
+#define lwsl_header(...)  _lws_log(LLL_HEADER, __VA_ARGS__)
+#define lwsl_ext(...)  _lws_log(LLL_EXT, __VA_ARGS__)
+#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
+#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
+LWS_EXTERN void lwsl_hexdump(void *buf, size_t len);
+
+#else /* no debug */
+
+#define lwsl_info(...)
+#define lwsl_debug(...)
+#define lwsl_parser(...)
+#define lwsl_header(...)
+#define lwsl_ext(...)
+#define lwsl_client(...)
+#define lwsl_latency(...)
+#define lwsl_hexdump(a, b)
+
+#endif
+
+enum libwebsocket_context_options {
+	LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2,
+	LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME = 4,
+};
+
+enum libwebsocket_callback_reasons {
+	LWS_CALLBACK_ESTABLISHED,
+	LWS_CALLBACK_CLIENT_CONNECTION_ERROR,
+	LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH,
+	LWS_CALLBACK_CLIENT_ESTABLISHED,
+	LWS_CALLBACK_CLOSED,
+	LWS_CALLBACK_RECEIVE,
+	LWS_CALLBACK_CLIENT_RECEIVE,
+	LWS_CALLBACK_CLIENT_RECEIVE_PONG,
+	LWS_CALLBACK_CLIENT_WRITEABLE,
+	LWS_CALLBACK_SERVER_WRITEABLE,
+	LWS_CALLBACK_HTTP,
+	LWS_CALLBACK_HTTP_FILE_COMPLETION,
+	LWS_CALLBACK_HTTP_WRITEABLE,
+	LWS_CALLBACK_FILTER_NETWORK_CONNECTION,
+	LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION,
+	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
+	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
+	LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
+	LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER,
+	LWS_CALLBACK_CONFIRM_EXTENSION_OKAY,
+	LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
+	LWS_CALLBACK_PROTOCOL_INIT,
+	LWS_CALLBACK_PROTOCOL_DESTROY,
+	/* external poll() management support */
+	LWS_CALLBACK_ADD_POLL_FD,
+	LWS_CALLBACK_DEL_POLL_FD,
+	LWS_CALLBACK_SET_MODE_POLL_FD,
+	LWS_CALLBACK_CLEAR_MODE_POLL_FD,
+};
+
+#ifndef LWS_NO_EXTENSIONS
+enum libwebsocket_extension_callback_reasons {
+	LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT,
+	LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT,
+	LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT,
+	LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT,
+	LWS_EXT_CALLBACK_CONSTRUCT,
+	LWS_EXT_CALLBACK_CLIENT_CONSTRUCT,
+	LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE,
+	LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION,
+	LWS_EXT_CALLBACK_DESTROY,
+	LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING,
+	LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED,
+	LWS_EXT_CALLBACK_PACKET_RX_PREPARSE,
+	LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
+	LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
+	LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX,
+	LWS_EXT_CALLBACK_FLUSH_PENDING_TX,
+	LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX,
+	LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION,
+	LWS_EXT_CALLBACK_1HZ,
+	LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE,
+	LWS_EXT_CALLBACK_IS_WRITEABLE,
+	LWS_EXT_CALLBACK_PAYLOAD_TX,
+	LWS_EXT_CALLBACK_PAYLOAD_RX,
+};
+#endif
+
+enum libwebsocket_write_protocol {
+	LWS_WRITE_TEXT,
+	LWS_WRITE_BINARY,
+	LWS_WRITE_CONTINUATION,
+	LWS_WRITE_HTTP,
+
+	/* special 04+ opcodes */
+
+	LWS_WRITE_CLOSE,
+	LWS_WRITE_PING,
+	LWS_WRITE_PONG,
+
+	/* flags */
+
+	LWS_WRITE_NO_FIN = 0x40,
+	/*
+	 * client packet payload goes out on wire unmunged
+	 * only useful for security tests since normal servers cannot
+	 * decode the content if used
+	 */
+	LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80
+};
+
+/*
+ * you need these to look at headers that have been parsed if using the
+ * LWS_CALLBACK_FILTER_CONNECTION callback.  If a header from the enum
+ * list below is absent, .token = NULL and token_len = 0.  Otherwise .token
+ * points to .token_len chars containing that header content.
+ */
+
+struct lws_tokens {
+	char *token;
+	int token_len;
+};
+
+enum lws_token_indexes {
+	WSI_TOKEN_GET_URI,
+	WSI_TOKEN_HOST,
+	WSI_TOKEN_CONNECTION,
+	WSI_TOKEN_KEY1,
+	WSI_TOKEN_KEY2,
+	WSI_TOKEN_PROTOCOL,
+	WSI_TOKEN_UPGRADE,
+	WSI_TOKEN_ORIGIN,
+	WSI_TOKEN_DRAFT,
+	WSI_TOKEN_CHALLENGE,
+
+	/* new for 04 */
+	WSI_TOKEN_KEY,
+	WSI_TOKEN_VERSION,
+	WSI_TOKEN_SWORIGIN,
+
+	/* new for 05 */
+	WSI_TOKEN_EXTENSIONS,
+
+	/* client receives these */
+	WSI_TOKEN_ACCEPT,
+	WSI_TOKEN_NONCE,
+	WSI_TOKEN_HTTP,
+	WSI_TOKEN_MUXURL,
+
+	/* use token storage to stash these */
+
+	_WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
+	_WSI_TOKEN_CLIENT_PEER_ADDRESS,
+	_WSI_TOKEN_CLIENT_URI,
+	_WSI_TOKEN_CLIENT_HOST,
+	_WSI_TOKEN_CLIENT_ORIGIN,
+
+	/* always last real token index*/
+	WSI_TOKEN_COUNT,
+	/* parser state additions */
+	WSI_TOKEN_NAME_PART,
+	WSI_TOKEN_SKIPPING,
+	WSI_TOKEN_SKIPPING_SAW_CR,
+	WSI_PARSING_COMPLETE,
+	WSI_INIT_TOKEN_MUXURL,
+};
+
+/*
+ * From RFC 6455
+   1000
+
+      1000 indicates a normal closure, meaning that the purpose for
+      which the connection was established has been fulfilled.
+
+   1001
+
+      1001 indicates that an endpoint is "going away", such as a server
+      going down or a browser having navigated away from a page.
+
+   1002
+
+      1002 indicates that an endpoint is terminating the connection due
+      to a protocol error.
+
+   1003
+
+      1003 indicates that an endpoint is terminating the connection
+      because it has received a type of data it cannot accept (e.g., an
+      endpoint that understands only text data MAY send this if it
+      receives a binary message).
+
+   1004
+
+      Reserved.  The specific meaning might be defined in the future.
+
+   1005
+
+      1005 is a reserved value and MUST NOT be set as a status code in a
+      Close control frame by an endpoint.  It is designated for use in
+      applications expecting a status code to indicate that no status
+      code was actually present.
+
+   1006
+
+      1006 is a reserved value and MUST NOT be set as a status code in a
+      Close control frame by an endpoint.  It is designated for use in
+      applications expecting a status code to indicate that the
+      connection was closed abnormally, e.g., without sending or
+      receiving a Close control frame.
+
+   1007
+
+      1007 indicates that an endpoint is terminating the connection
+      because it has received data within a message that was not
+      consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
+      data within a text message).
+
+   1008
+
+      1008 indicates that an endpoint is terminating the connection
+      because it has received a message that violates its policy.  This
+      is a generic status code that can be returned when there is no
+      other more suitable status code (e.g., 1003 or 1009) or if there
+      is a need to hide specific details about the policy.
+
+   1009
+
+      1009 indicates that an endpoint is terminating the connection
+      because it has received a message that is too big for it to
+      process.
+
+   1010
+
+      1010 indicates that an endpoint (client) is terminating the
+      connection because it has expected the server to negotiate one or
+      more extension, but the server didn't return them in the response
+      message of the WebSocket handshake.  The list of extensions that
+      are needed SHOULD appear in the /reason/ part of the Close frame.
+      Note that this status code is not used by the server, because it
+      can fail the WebSocket handshake instead.
+
+   1011
+
+      1011 indicates that a server is terminating the connection because
+      it encountered an unexpected condition that prevented it from
+      fulfilling the request.
+
+   1015
+
+      1015 is a reserved value and MUST NOT be set as a status code in a
+      Close control frame by an endpoint.  It is designated for use in
+      applications expecting a status code to indicate that the
+      connection was closed due to a failure to perform a TLS handshake
+      (e.g., the server certificate can't be verified).
+*/
+
+enum lws_close_status {
+	LWS_CLOSE_STATUS_NOSTATUS = 0,
+	LWS_CLOSE_STATUS_NORMAL = 1000,
+	LWS_CLOSE_STATUS_GOINGAWAY = 1001,
+	LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002,
+	LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003,
+	LWS_CLOSE_STATUS_RESERVED = 1004,
+	LWS_CLOSE_STATUS_NO_STATUS = 1005,
+	LWS_CLOSE_STATUS_ABNORMAL_CLOSE = 1006,
+	LWS_CLOSE_STATUS_INVALID_PAYLOAD = 1007,
+	LWS_CLOSE_STATUS_POLICY_VIOLATION = 1008,
+	LWS_CLOSE_STATUS_MESSAGE_TOO_LARGE = 1009,
+	LWS_CLOSE_STATUS_EXTENSION_REQUIRED = 1010,
+	LWS_CLOSE_STATUS_UNEXPECTED_CONDITION = 1011,
+	LWS_CLOSE_STATUS_TLS_FAILURE = 1015,
+};
+
+struct libwebsocket;
+struct libwebsocket_context;
+/* needed even with extensions disabled for create context */
+struct libwebsocket_extension;
+
+/**
+ * callback_function() - User server actions
+ * @context:	Websockets context
+ * @wsi:	Opaque websocket instance pointer
+ * @reason:	The reason for the call
+ * @user:	Pointer to per-session user data allocated by library
+ * @in:		Pointer used for some callback reasons
+ * @len:	Length set for some callback reasons
+ *
+ *	This callback is the way the user controls what is served.  All the
+ *	protocol detail is hidden and handled by the library.
+ *
+ *	For each connection / session there is user data allocated that is
+ *	pointed to by "user".  You set the size of this user data area when
+ *	the library is initialized with libwebsocket_create_server.
+ *
+ *	You get an opportunity to initialize user data when called back with
+ *	LWS_CALLBACK_ESTABLISHED reason.
+ *
+ *  LWS_CALLBACK_ESTABLISHED:  after the server completes a handshake with
+ *				an incoming client
+ *
+ *  LWS_CALLBACK_CLIENT_CONNECTION_ERROR: the request client connection has
+ *        been unable to complete a handshake with the remote server
+ *
+ *  LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: this is the last chance for the
+ *				client user code to examine the http headers
+ *				and decide to reject the connection.  If the
+ *				content in the headers is interesting to the
+ *				client (url, etc) it needs to copy it out at
+ *				this point since it will be destroyed before
+ *				the CLIENT_ESTABLISHED call
+ *
+ *  LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed
+ *				a handshake with the remote server
+ *
+ *	LWS_CALLBACK_CLOSED: when the websocket session ends
+ *
+ *	LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a
+ *				remote client, it can be found at *in and is
+ *				len bytes long
+ *
+ *	LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets,
+ *				they appear with this callback reason.  PONG
+ *				packets only exist in 04+ protocol
+ *
+ *	LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the
+ *				client connection, it can be found at *in and
+ *				is len bytes long
+ *
+ *	LWS_CALLBACK_HTTP: an http request has come from a client that is not
+ *				asking to upgrade the connection to a websocket
+ *				one.  This is a chance to serve http content,
+ *				for example, to send a script to the client
+ *				which will then open the websockets connection.
+ *				@in points to the URI path requested and
+ *				libwebsockets_serve_http_file() makes it very
+ *				simple to send back a file to the client.
+ *				Normally after sending the file you are done
+ *				with the http connection, since the rest of the
+ *				activity will come by websockets from the script
+ *				that was delivered by http, so you will want to
+ *				return 1; to close and free up the connection.
+ *				That's important because it uses a slot in the
+ *				total number of client connections allowed set
+ *				by MAX_CLIENTS.
+ *
+ *	LWS_CALLBACK_HTTP_WRITEABLE: you can write more down the http protocol
+ *		link now.
+ *
+ *	LWS_CALLBACK_HTTP_FILE_COMPLETION: a file requested to be send down
+ *				http link has completed.
+ *
+ *	LWS_CALLBACK_CLIENT_WRITEABLE:
+ *      LWS_CALLBACK_SERVER_WRITEABLE:   If you call
+ *		libwebsocket_callback_on_writable() on a connection, you will
+ *		get one of these callbacks coming when the connection socket
+ *		is able to accept another write packet without blocking.
+ *		If it already was able to take another packet without blocking,
+ *		you'll get this callback at the next call to the service loop
+ *		function.  Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE
+ *		and servers get LWS_CALLBACK_SERVER_WRITEABLE.
+ *
+ *	LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to
+ *		the server at network level; the connection is accepted but then
+ *		passed to this callback to decide whether to hang up immediately
+ *		or not, based on the client IP.  @in contains the connection
+ *		socket's descriptor.  Return non-zero to terminate
+ *		the connection before sending or receiving anything.
+ *		Because this happens immediately after the network connection
+ *		from the client, there's no websocket protocol selected yet so
+ *		this callback is issued only to protocol 0.
+ *
+ *	LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has
+ *		been received and parsed from the client, but the response is
+ *		not sent yet.  Return non-zero to disallow the connection.
+ *		@user is a pointer to an array of struct lws_tokens, you can
+ *		use the header enums lws_token_indexes from libwebsockets.h
+ *		to check for and read the supported header presence and
+ *		content before deciding to allow the handshake to proceed or
+ *		to kill the connection.
+ *
+ *	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for
+ *		including OpenSSL support, this callback allows your user code
+ *		to perform extra SSL_CTX_load_verify_locations() or similar
+ *		calls to direct OpenSSL where to find certificates the client
+ *		can use to confirm the remote server identity.  @user is the
+ *		OpenSSL SSL_CTX*
+ *
+ *	LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for
+ *		including OpenSSL support, this callback allows your user code
+ *		to load extra certifcates into the server which allow it to
+ *		verify the validity of certificates returned by clients.  @user
+ *		is the server's OpenSSL SSL_CTX*
+ *
+ *	LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the
+ *		libwebsockets context was created with the option
+ *		LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this
+ *		callback is generated during OpenSSL verification of the cert
+ *		sent from the client.  It is sent to protocol[0] callback as
+ *		no protocol has been negotiated on the connection yet.
+ *		Notice that the libwebsockets context and wsi are both NULL
+ *		during this callback.  See
+ *		 http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html
+ *		to understand more detail about the OpenSSL callback that
+ *		generates this libwebsockets callback and the meanings of the
+ *		arguments passed.  In this callback, @user is the x509_ctx,
+ *		@in is the ssl pointer and @len is preverify_ok
+ *		Notice that this callback maintains libwebsocket return
+ *		conventions, return 0 to mean the cert is OK or 1 to fail it.
+ *		This also means that if you don't handle this callback then
+ *		the default callback action of returning 0 allows the client
+ *		certificates.
+ *
+ *	LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: this callback happens
+ *		when a client handshake is being compiled.  @user is NULL,
+ *		@in is a char **, it's pointing to a char * which holds the
+ *		next location in the header buffer where you can add
+ *		headers, and @len is the remaining space in the header buffer,
+ *		which is typically some hundreds of bytes.  So, to add a canned
+ *		cookie, your handler code might look similar to:
+ *
+ *		char **p = (char **)in;
+ *
+ *		if (len < 100)
+ *			return 1;
+ *
+ *		*p += sprintf(*p, "Cookie: a=b\x0d\x0a");
+ *
+ *		return 0;
+ *
+ *		Notice if you add anything, you just have to take care about
+ *		the CRLF on the line you added.  Obviously this callback is
+ *		optional, if you don't handle it everything is fine.
+ *
+ *		Notice the callback is coming to protocols[0] all the time,
+ *		because there is no specific protocol handshook yet.
+ *
+ *	LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code
+ *		sees that it does support a requested extension, before
+ *		accepting the extension by additing to the list sent back to
+ *		the client it gives this callback just to check that it's okay
+ *		to use that extension.  It calls back to the requested protocol
+ *		and with @in being the extension name, @len is 0 and @user is
+ *		valid.  Note though at this time the ESTABLISHED callback hasn't
+ *		happened yet so if you initialize @user content there, @user
+ *		content during this callback might not be useful for anything.
+ *		Notice this callback comes to protocols[0].
+ *
+ *	LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:	When a client
+ *		connection is being prepared to start a handshake to a server,
+ *		each supported extension is checked with protocols[0] callback
+ *		with this reason, giving the user code a chance to suppress the
+ *		claim to support that extension by returning non-zero.  If
+ *		unhandled, by default 0 will be returned and the extension
+ *		support included in the header to the server.  Notice this
+ *		callback comes to protocols[0].
+ *
+ *	LWS_CALLBACK_PROTOCOL_INIT:	One-time call per protocol so it can
+ *		do initial setup / allocations etc
+ *
+ *	LWS_CALLBACK_PROTOCOL_DESTROY:	One-time call per protocol indicating
+ *		this protocol won't get used at all after this callback, the
+ *		context is getting destroyed.  Take the opportunity to
+ *		deallocate everything that was allocated by the protocol.
+ *
+ *	The next four reasons are optional and only need taking care of if you
+ *	will be integrating libwebsockets sockets into an external polling
+ *	array.
+ *
+ *	LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop
+ *		internally, but in the case you are integrating with another
+ *		server you will need to have libwebsocket sockets share a
+ *		polling array with the other server.  This and the other
+ *		POLL_FD related callbacks let you put your specialized
+ *		poll array interface code in the callback for protocol 0, the
+ *		first protocol you support, usually the HTTP protocol in the
+ *		serving case.  This callback happens when a socket needs to be
+ *		added to the polling loop: @in contains the fd, and
+ *		@len is the events bitmap (like, POLLIN).  If you are using the
+ *		internal polling loop (the "service" callback), you can just
+ *		ignore these callbacks.
+ *
+ *	LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor
+ *		needs to be removed from an external polling array.  @in is
+ *		the socket desricptor.  If you are using the internal polling
+ *		loop, you can just ignore it.
+ *
+ *	LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets
+ *		wants to modify the events for the socket descriptor in @in.
+ *		The handler should OR @len on to the events member of the pollfd
+ *		struct for this socket descriptor.  If you are using the
+ *		internal polling loop, you can just ignore it.
+ *
+ *	LWS_CALLBACK_CLEAR_MODE_POLL_FD: This callback occurs when libwebsockets
+ *		wants to modify the events for the socket descriptor in @in.
+ *		The handler should AND ~@len on to the events member of the
+ *		pollfd struct for this socket descriptor.  If you are using the
+ *		internal polling loop, you can just ignore it.
+ */
+LWS_EXTERN int callback(struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
+							  void *in, size_t len);
+
+typedef int (callback_function)(struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
+							  void *in, size_t len);
+
+#ifndef LWS_NO_EXTENSIONS
+/**
+ * extension_callback_function() - Hooks to allow extensions to operate
+ * @context:	Websockets context
+ * @ext:	This extension
+ * @wsi:	Opaque websocket instance pointer
+ * @reason:	The reason for the call
+ * @user:	Pointer to per-session user data allocated by library
+ * @in:		Pointer used for some callback reasons
+ * @len:	Length set for some callback reasons
+ *
+ *	Each extension that is active on a particular connection receives
+ *	callbacks during the connection lifetime to allow the extension to
+ *	operate on websocket data and manage itself.
+ *
+ *	Libwebsockets takes care of allocating and freeing "user" memory for
+ *	each active extension on each connection.  That is what is pointed to
+ *	by the @user parameter.
+ *
+ *	LWS_EXT_CALLBACK_CONSTRUCT:  called when the server has decided to
+ *		select this extension from the list provided by the client,
+ *		just before the server will send back the handshake accepting
+ *		the connection with this extension active.  This gives the
+ *		extension a chance to initialize its connection context found
+ *		in @user.
+ *
+ *	LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT
+ *		but called when client is instantiating this extension.  Some
+ *		extensions will work the same on client and server side and then
+ *		you can just merge handlers for both CONSTRUCTS.
+ *
+ *	LWS_EXT_CALLBACK_DESTROY:  called when the connection the extension was
+ *		being used on is about to be closed and deallocated.  It's the
+ *		last chance for the extension to deallocate anything it has
+ *		allocated in the user data (pointed to by @user) before the
+ *		user data is deleted.  This same callback is used whether you
+ *		are in client or server instantiation context.
+ *
+ *	LWS_EXT_CALLBACK_PACKET_RX_PREPARSE: when this extension was active on
+ *		a connection, and a packet of data arrived at the connection,
+ *		it is passed to this callback to give the extension a chance to
+ *		change the data, eg, decompress it.  @user is pointing to the
+ *		extension's private connection context data, @in is pointing
+ *		to an lws_tokens struct, it consists of a char * pointer called
+ *		token, and an int called token_len.  At entry, these are
+ *		set to point to the received buffer and set to the content
+ *		length.  If the extension will grow the content, it should use
+ *		a new buffer allocated in its private user context data and
+ *		set the pointed-to lws_tokens members to point to its buffer.
+ *
+ *	LWS_EXT_CALLBACK_PACKET_TX_PRESEND: this works the same way as
+ *		LWS_EXT_CALLBACK_PACKET_RX_PREPARSE above, except it gives the
+ *		extension a chance to change websocket data just before it will
+ *		be sent out.  Using the same lws_token pointer scheme in @in,
+ *		the extension can change the buffer and the length to be
+ *		transmitted how it likes.  Again if it wants to grow the
+ *		buffer safely, it should copy the data into its own buffer and
+ *		set the lws_tokens token pointer to it.
+ */
+LWS_EXTERN int extension_callback(struct libwebsocket_context *context,
+			struct libwebsocket_extension *ext,
+			struct libwebsocket *wsi,
+			enum libwebsocket_extension_callback_reasons reason,
+			void *user, void *in, size_t len);
+
+typedef int (extension_callback_function)(struct libwebsocket_context *context,
+			struct libwebsocket_extension *ext,
+			struct libwebsocket *wsi,
+			enum libwebsocket_extension_callback_reasons reason,
+			void *user, void *in, size_t len);
+#endif
+
+/**
+ * struct libwebsocket_protocols -	List of protocols and handlers server
+ *					supports.
+ * @name:	Protocol name that must match the one given in the client
+ *		Javascript new WebSocket(url, 'protocol') name
+ * @callback:	The service callback used for this protocol.  It allows the
+ *		service action for an entire protocol to be encapsulated in
+ *		the protocol-specific callback
+ * @per_session_data_size:	Each new connection using this protocol gets
+ *		this much memory allocated on connection establishment and
+ *		freed on connection takedown.  A pointer to this per-connection
+ *		allocation is passed into the callback in the 'user' parameter
+ * @rx_buffer_size: if you want atomic frames delivered to the callback, you
+ *		should set this to the size of the biggest legal frame that
+ *		you support.  If the frame size is exceeded, there is no
+ *		error, but the buffer will spill to the user callback when
+ *		full, which you can detect by using
+ *		libwebsockets_remaining_packet_payload().  Notice that you
+ *		just talk about frame size here, the LWS_SEND_BUFFER_PRE_PADDING
+ *		and post-padding are automatically also allocated on top.
+ * @owning_server:	the server init call fills in this opaque pointer when
+ *		registering this protocol with the server.
+ * @protocol_index: which protocol we are starting from zero
+ *
+ *	This structure represents one protocol supported by the server.  An
+ *	array of these structures is passed to libwebsocket_create_server()
+ *	allows as many protocols as you like to be handled by one server.
+ */
+
+struct libwebsocket_protocols {
+	const char *name;
+	callback_function *callback;
+	size_t per_session_data_size;
+	size_t rx_buffer_size;
+
+	/*
+	 * below are filled in on server init and can be left uninitialized,
+	 * no need for user to use them directly either
+	 */
+
+	struct libwebsocket_context *owning_server;
+	int protocol_index;
+};
+
+#ifndef LWS_NO_EXTENSIONS
+/**
+ * struct libwebsocket_extension -	An extension we know how to cope with
+ *
+ * @name:			Formal extension name, eg, "deflate-stream"
+ * @callback:			Service callback
+ * @per_session_data_size:	Libwebsockets will auto-malloc this much
+ *				memory for the use of the extension, a pointer
+ *				to it comes in the @user callback parameter
+ * @per_context_private_data:   Optional storage for this extension that
+ *				is per-context, so it can track stuff across
+ *				all sessions, etc, if it wants
+ */
+
+struct libwebsocket_extension {
+	const char *name;
+	extension_callback_function *callback;
+	size_t per_session_data_size;
+	void *per_context_private_data;
+};
+#endif
+
+/**
+ * struct lws_context_creation_info: parameters to create context with
+ *
+ * @port:	Port to listen on... you can use 0 to suppress listening on
+ *		any port, that's what you want if you are not running a
+ *		websocket server at all but just using it as a client
+ * @iface:	NULL to bind the listen socket to all interfaces, or the
+ *		interface name, eg, "eth2"
+ * @protocols:	Array of structures listing supported protocols and a protocol-
+ *		specific callback for each one.  The list is ended with an
+ *		entry that has a NULL callback pointer.
+ *		It's not const because we write the owning_server member
+ * @extensions: NULL or array of libwebsocket_extension structs listing the
+ *		extensions this context supports.  If you configured with
+ *		--without-extensions, you should give NULL here.
+ * @ssl_cert_filepath:	If libwebsockets was compiled to use ssl, and you want
+ *			to listen using SSL, set to the filepath to fetch the
+ *			server cert from, otherwise NULL for unencrypted
+ * @ssl_private_key_filepath: filepath to private key if wanting SSL mode,
+ *			else ignored
+ * @ssl_ca_filepath: CA certificate filepath or NULL
+ * @ssl_cipher_list:	List of valid ciphers to use (eg,
+ * 			"RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL"
+ * 			or you can leave it as NULL to get "DEFAULT"
+ * @gid:	group id to change to after setting listen socket, or -1.
+ * @uid:	user id to change to after setting listen socket, or -1.
+ * @options:	0, or LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK
+ * @user:	optional user pointer that can be recovered via the context
+ *		pointer using libwebsocket_context_user
+ * @ka_time:	0 for no keepalive, otherwise apply this keepalive timeout to
+ *		all libwebsocket sockets, client or server
+ * @ka_probes:	if ka_time was nonzero, after the timeout expires how many
+ *		times to try to get a response from the peer before giving up
+ *		and killing the connection
+ * @ka_interval: if ka_time was nonzero, how long to wait before each ka_probes
+ *		attempt
+ */
+
+struct lws_context_creation_info {
+	int port;
+	const char *iface;
+	struct libwebsocket_protocols *protocols;
+	struct libwebsocket_extension *extensions;
+	const char *ssl_cert_filepath;
+	const char *ssl_private_key_filepath;
+	const char *ssl_ca_filepath;
+	const char *ssl_cipher_list;
+	int gid;
+	int uid;
+	unsigned int options;
+	void *user;
+	int ka_time;
+	int ka_probes;
+	int ka_interval;
+
+};
+
+LWS_EXTERN
+void lws_set_log_level(int level,
+			void (*log_emit_function)(int level, const char *line));
+
+LWS_EXTERN void
+lwsl_emit_syslog(int level, const char *line);
+
+LWS_EXTERN struct libwebsocket_context *
+libwebsocket_create_context(struct lws_context_creation_info *info);
+
+LWS_EXTERN void
+libwebsocket_context_destroy(struct libwebsocket_context *context);
+
+LWS_EXTERN int
+libwebsocket_service(struct libwebsocket_context *context, int timeout_ms);
+
+LWS_EXTERN int
+libwebsocket_service_fd(struct libwebsocket_context *context,
+							 struct pollfd *pollfd);
+
+LWS_EXTERN void *
+libwebsocket_context_user(struct libwebsocket_context *context);
+
+/*
+ * IMPORTANT NOTICE!
+ *
+ * When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY)
+ * the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE
+ * buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len).
+ *
+ * This allows us to add protocol info before and after the data, and send as
+ * one packet on the network without payload copying, for maximum efficiency.
+ *
+ * So for example you need this kind of code to use libwebsocket_write with a
+ * 128-byte payload
+ *
+ *   char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING];
+ *
+ *   // fill your part of the buffer... for example here it's all zeros
+ *   memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128);
+ *
+ *   libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128,
+ *   								LWS_WRITE_TEXT);
+ *
+ * When sending LWS_WRITE_HTTP, there is no protocol addition and you can just
+ * use the whole buffer without taking care of the above.
+ */
+
+/*
+ * this is the frame nonce plus two header plus 8 length
+ *   there's an additional two for mux extension per mux nesting level
+ * 2 byte prepend on close will already fit because control frames cannot use
+ * the big length style
+ */
+
+#define LWS_SEND_BUFFER_PRE_PADDING (4 + 10 + (2 * MAX_MUX_RECURSION))
+#define LWS_SEND_BUFFER_POST_PADDING 4
+
+LWS_EXTERN int
+libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len,
+				     enum libwebsocket_write_protocol protocol);
+
+LWS_EXTERN int
+libwebsockets_serve_http_file(struct libwebsocket_context *context,
+			struct libwebsocket *wsi, const char *file,
+						     const char *content_type);
+LWS_EXTERN int
+libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
+			struct libwebsocket *wsi);
+
+LWS_EXTERN const struct libwebsocket_protocols *
+libwebsockets_get_protocol(struct libwebsocket *wsi);
+
+LWS_EXTERN int
+libwebsocket_callback_on_writable(struct libwebsocket_context *context,
+						      struct libwebsocket *wsi);
+
+LWS_EXTERN int
+libwebsocket_callback_on_writable_all_protocol(
+				 const struct libwebsocket_protocols *protocol);
+
+LWS_EXTERN int
+libwebsocket_get_socket_fd(struct libwebsocket *wsi);
+
+LWS_EXTERN int
+libwebsocket_is_final_fragment(struct libwebsocket *wsi);
+
+LWS_EXTERN unsigned char
+libwebsocket_get_reserved_bits(struct libwebsocket *wsi);
+
+LWS_EXTERN int
+libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable);
+
+LWS_EXTERN void
+libwebsocket_rx_flow_allow_all_protocol(
+				const struct libwebsocket_protocols *protocol);
+
+LWS_EXTERN size_t
+libwebsockets_remaining_packet_payload(struct libwebsocket *wsi);
+
+LWS_EXTERN struct libwebsocket *
+libwebsocket_client_connect(struct libwebsocket_context *clients,
+			      const char *address,
+			      int port,
+			      int ssl_connection,
+			      const char *path,
+			      const char *host,
+			      const char *origin,
+			      const char *protocol,
+			      int ietf_version_or_minus_one);
+
+LWS_EXTERN struct libwebsocket *
+libwebsocket_client_connect_extended(struct libwebsocket_context *clients,
+			      const char *address,
+			      int port,
+			      int ssl_connection,
+			      const char *path,
+			      const char *host,
+			      const char *origin,
+			      const char *protocol,
+			      int ietf_version_or_minus_one,
+			      void *userdata);
+
+LWS_EXTERN const char *
+libwebsocket_canonical_hostname(struct libwebsocket_context *context);
+
+
+LWS_EXTERN void
+libwebsockets_get_peer_addresses(struct libwebsocket_context *context,
+		struct libwebsocket *wsi, int fd, char *name, int name_len,
+					char *rip, int rip_len);
+
+LWS_EXTERN int
+libwebsockets_get_random(struct libwebsocket_context *context,
+							    void *buf, int len);
+
+LWS_EXTERN int
+lws_daemonize(const char *_lock_path);
+
+LWS_EXTERN int
+lws_send_pipe_choked(struct libwebsocket *wsi);
+
+LWS_EXTERN int
+lws_frame_is_binary(struct libwebsocket *wsi);
+
+LWS_EXTERN unsigned char *
+libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md);
+
+LWS_EXTERN int
+lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
+
+LWS_EXTERN int
+lws_b64_decode_string(const char *in, char *out, int out_size);
+
+LWS_EXTERN const char *
+lws_get_library_version(void);
+
+/* access to headers... only valid while headers valid */
+
+LWS_EXTERN int
+lws_hdr_total_length(struct libwebsocket *wsi, enum lws_token_indexes h);
+
+LWS_EXTERN int
+lws_hdr_copy(struct libwebsocket *wsi, char *dest, int len,
+						enum lws_token_indexes h);
+
+/*
+ * Note: this is not normally needed as a user api.  It's provided in case it is
+ * useful when integrating with other app poll loop service code.
+ */
+
+LWS_EXTERN int
+libwebsocket_read(struct libwebsocket_context *context,
+				struct libwebsocket *wsi,
+					       unsigned char *buf, size_t len);
+
+#ifndef LWS_NO_EXTENSIONS
+LWS_EXTERN struct libwebsocket_extension *libwebsocket_get_internal_extensions();
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mod_netconf.c b/src/mod_netconf.c
index ccd6c05..3142225 100644
--- a/src/mod_netconf.c
+++ b/src/mod_netconf.c
@@ -8,7 +8,7 @@
  * \date 2013
  */
 /*
- * Copyright (C) 2011-2012 CESNET
+ * Copyright (C) 2011-2013 CESNET
  *
  * LICENSE TERMS
  *
@@ -50,6 +50,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <sys/fcntl.h>
 #include <pthread.h>
 #include <ctype.h>
 
@@ -67,6 +68,10 @@
 
 #include <libnetconf.h>
 
+#ifdef WITH_NOTIFICATIONS
+#include "notification_module.h"
+#endif
+
 #include "message_type.h"
 
 
@@ -1320,8 +1325,11 @@
  */
 static void forked_proc(apr_pool_t * pool, server_rec * server)
 {
+	struct timeval tv;
 	struct sockaddr_un local, remote;
 	int lsock, client, ret, i, pthread_count = 0;
+	char use_notifications = 0;
+	unsigned int olds = 0;
 	socklen_t len;
 	mod_netconf_cfg *cfg;
 	apr_hash_t *netconf_sessions_list;
@@ -1371,6 +1379,15 @@
 		return;
 	}
 
+	#ifdef WITH_NOTIFICATIONS
+	if (notification_init(pool, server) == -1) {
+		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "libwebsockets initialization failed");
+		use_notifications = 0;
+	} else {
+		use_notifications = 1;
+	}
+	#endif
+
 	/* prepare internal lists */
 	netconf_sessions_list = apr_hash_make(pool);
 
@@ -1396,12 +1413,25 @@
 		close (lsock);
 		return;
 	}
-
+	
+	fcntl(lsock, F_SETFL, fcntl(lsock, F_GETFL, 0) | O_NONBLOCK);
 	while (isterminated == 0) {
-		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "waiting for another client's request");
+		gettimeofday(&tv, NULL);
+		#ifdef WITH_NOTIFICATIONS
+		if (((unsigned int)tv.tv_sec - olds) > 60) {
+			ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "handling notifications");
+		}
+		if (use_notifications == 1) {
+			notification_handle();
+		}
+		#endif
 
 		/* open incoming connection if any */
 		len = sizeof(remote);
+		if (((unsigned int)tv.tv_sec - olds) > 60) {
+			ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "accepting another client");
+			olds = tv.tv_sec;
+		}
 		client = accept(lsock, (struct sockaddr *) &remote, &len);
 		if (client == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
 			apr_sleep(SLEEP_TIME);
@@ -1454,6 +1484,10 @@
 
 	close(lsock);
 
+	#ifdef WITH_NOTIFICATIONS
+	notification_close();
+	#endif
+
 	/* destroy rwlock */
 	pthread_rwlock_destroy(&session_lock);
 	pthread_rwlockattr_destroy(&lock_attrs);
diff --git a/src/notification-server.c b/src/notification-server.c
new file mode 100644
index 0000000..382629b
--- /dev/null
+++ b/src/notification-server.c
@@ -0,0 +1,738 @@
+/*
+ * libwebsockets-test-server - libwebsockets test implementation
+ *
+ * Copyright (C) 2010-2011 Andy Green <andy@warmcat.com>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation:
+ *  version 2.1 of the License.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ *  MA  02110-1301  USA
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include "libwebsockets.h"
+#include "notification_module.h"
+
+#ifndef TEST_NOTIFICATION_SERVER
+#include <httpd.h>
+#include <http_log.h>
+#endif
+
+#if defined(TEST_NOTIFICATION_SERVER) || defined(WITH_NOTIFICATIONS)
+static int close_testing;
+static int max_poll_elements;
+
+static struct pollfd *pollfds;
+static int *fd_lookup;
+static int count_pollfds;
+static int force_exit = 0;
+static struct libwebsocket_context *context = NULL;
+static server_rec *http_server = NULL;
+
+/*
+ * This demo server shows how to use libwebsockets for one or more
+ * websocket protocols in the same server
+ *
+ * It defines the following websocket protocols:
+ *
+ *  dumb-increment-protocol:  once the socket is opened, an incrementing
+ *				ascii string is sent down it every 50ms.
+ *				If you send "reset\n" on the websocket, then
+ *				the incrementing number is reset to 0.
+ *
+ *  lws-mirror-protocol: copies any received packet to every connection also
+ *				using this protocol, including the sender
+ */
+
+enum demo_protocols {
+	/* always first */
+	PROTOCOL_HTTP = 0,
+
+	PROTOCOL_NOTIFICATION,
+
+	/* always last */
+	DEMO_PROTOCOL_COUNT
+};
+
+
+#define LOCAL_RESOURCE_PATH "."
+char *resource_path = LOCAL_RESOURCE_PATH;
+
+/*
+ * We take a strict whitelist approach to stop ../ attacks
+ */
+
+struct serveable {
+	const char *urlpath;
+	const char *mimetype;
+}; 
+
+static const struct serveable whitelist[] = {
+	{ "/favicon.ico", "image/x-icon" },
+	{ "/libwebsockets.org-logo.png", "image/png" },
+
+	/* last one is the default served if no match */
+	{ "/test.html", "text/html" },
+};
+
+struct per_session_data__http {
+	int fd;
+};
+
+/* this protocol server (always the first one) just knows how to do HTTP */
+
+static int callback_http(struct libwebsocket_context *context,
+		struct libwebsocket *wsi,
+		enum libwebsocket_callback_reasons reason, void *user,
+							   void *in, size_t len)
+{
+	char client_name[128];
+	char client_ip[128];
+	char buf[256];
+	int n, m;
+	unsigned char *p;
+	static unsigned char buffer[4096];
+	struct stat stat_buf;
+	struct per_session_data__http *pss = (struct per_session_data__http *)user;
+	int fd = (int)(long)in;
+
+	switch (reason) {
+	case LWS_CALLBACK_HTTP:
+
+		/* check for the "send a big file by hand" example case */
+
+		if (!strcmp((const char *)in, "/leaf.jpg")) {
+			char leaf_path[1024];
+			snprintf(leaf_path, sizeof(leaf_path), "%s/leaf.jpg", resource_path);
+
+			/* well, let's demonstrate how to send the hard way */
+
+			p = buffer;
+
+			pss->fd = open(leaf_path, O_RDONLY);
+
+			if (pss->fd < 0)
+				return -1;
+
+			fstat(pss->fd, &stat_buf);
+
+			/*
+			 * we will send a big jpeg file, but it could be
+			 * anything.  Set the Content-Type: appropriately
+			 * so the browser knows what to do with it.
+			 */
+
+			p += sprintf((char *)p,
+				"HTTP/1.0 200 OK\x0d\x0a"
+				"Server: libwebsockets\x0d\x0a"
+				"Content-Type: image/jpeg\x0d\x0a"
+					"Content-Length: %u\x0d\x0a\x0d\x0a",
+					(unsigned int)stat_buf.st_size);
+
+			/*
+			 * send the http headers...
+			 * this won't block since it's the first payload sent
+			 * on the connection since it was established
+			 * (too small for partial)
+			 */
+
+			n = libwebsocket_write(wsi, buffer,
+				   p - buffer, LWS_WRITE_HTTP);
+
+			if (n < 0) {
+				close(pss->fd);
+				return -1;
+			}
+			/*
+			 * book us a LWS_CALLBACK_HTTP_WRITEABLE callback
+			 */
+			libwebsocket_callback_on_writable(context, wsi);
+			break;
+		}
+
+		/* if not, send a file the easy way */
+
+		for (n = 0; n < (sizeof(whitelist) / sizeof(whitelist[0]) - 1); n++)
+			if (in && strcmp((const char *)in, whitelist[n].urlpath) == 0)
+				break;
+
+		sprintf(buf, "%s%s", resource_path, whitelist[n].urlpath);
+
+		if (libwebsockets_serve_http_file(context, wsi, buf, whitelist[n].mimetype))
+			return -1; /* through completion or error, close the socket */
+
+		/*
+		 * notice that the sending of the file completes asynchronously,
+		 * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
+		 * it's done
+		 */
+
+		break;
+
+	case LWS_CALLBACK_HTTP_FILE_COMPLETION:
+//		lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n");
+		/* kill the connection after we sent one file */
+		return -1;
+
+	case LWS_CALLBACK_HTTP_WRITEABLE:
+		/*
+		 * we can send more of whatever it is we were sending
+		 */
+
+		do {
+			n = read(pss->fd, buffer, sizeof buffer);
+			/* problem reading, close conn */
+			if (n < 0)
+				goto bail;
+			/* sent it all, close conn */
+			if (n == 0)
+				goto bail;
+			/*
+			 * because it's HTTP and not websocket, don't need to take
+			 * care about pre and postamble
+			 */
+			m = libwebsocket_write(wsi, buffer, n, LWS_WRITE_HTTP);
+			if (m < 0)
+				/* write failed, close conn */
+				goto bail;
+			if (m != n)
+				/* partial write, adjust */
+				lseek(pss->fd, m - n, SEEK_CUR);
+
+		} while (!lws_send_pipe_choked(wsi));
+		libwebsocket_callback_on_writable(context, wsi);
+		break;
+
+bail:
+		close(pss->fd);
+		return -1;
+
+	/*
+	 * callback for confirming to continue with client IP appear in
+	 * protocol 0 callback since no websocket protocol has been agreed
+	 * yet.  You can just ignore this if you won't filter on client IP
+	 * since the default uhandled callback return is 0 meaning let the
+	 * connection continue.
+	 */
+
+	case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
+		libwebsockets_get_peer_addresses(context, wsi, (int)(long)in, client_name,
+			     sizeof(client_name), client_ip, sizeof(client_ip));
+
+		fprintf(stderr, "Received network connect from %s (%s)\n",
+							client_name, client_ip);
+		/* if we returned non-zero from here, we kill the connection */
+		break;
+
+	/*
+	 * callbacks for managing the external poll() array appear in
+	 * protocol 0 callback
+	 */
+
+	case LWS_CALLBACK_ADD_POLL_FD:
+
+		if (count_pollfds >= max_poll_elements) {
+			lwsl_err("LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
+			return 1;
+		}
+
+		fd_lookup[fd] = count_pollfds;
+		pollfds[count_pollfds].fd = fd;
+		pollfds[count_pollfds].events = (int)(long)len;
+		pollfds[count_pollfds++].revents = 0;
+		break;
+
+	case LWS_CALLBACK_DEL_POLL_FD:
+		if (!--count_pollfds)
+			break;
+		m = fd_lookup[fd];
+		/* have the last guy take up the vacant slot */
+		pollfds[m] = pollfds[count_pollfds];
+		fd_lookup[pollfds[count_pollfds].fd] = m;
+		break;
+
+	case LWS_CALLBACK_SET_MODE_POLL_FD:
+		pollfds[fd_lookup[fd]].events |= (int)(long)len;
+		break;
+
+	case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
+		pollfds[fd_lookup[fd]].events &= ~(int)(long)len;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * this is just an example of parsing handshake headers, you don't need this
+ * in your code unless you will filter allowing connections by the header
+ * content
+ */
+
+static void
+dump_handshake_info(struct libwebsocket *wsi)
+{
+	int n;
+	static const char *token_names[WSI_TOKEN_COUNT] = {
+		/*[WSI_TOKEN_GET_URI]		=*/ "GET URI",
+		/*[WSI_TOKEN_HOST]		=*/ "Host",
+		/*[WSI_TOKEN_CONNECTION]	=*/ "Connection",
+		/*[WSI_TOKEN_KEY1]		=*/ "key 1",
+		/*[WSI_TOKEN_KEY2]		=*/ "key 2",
+		/*[WSI_TOKEN_PROTOCOL]		=*/ "Protocol",
+		/*[WSI_TOKEN_UPGRADE]		=*/ "Upgrade",
+		/*[WSI_TOKEN_ORIGIN]		=*/ "Origin",
+		/*[WSI_TOKEN_DRAFT]		=*/ "Draft",
+		/*[WSI_TOKEN_CHALLENGE]		=*/ "Challenge",
+
+		/* new for 04 */
+		/*[WSI_TOKEN_KEY]		=*/ "Key",
+		/*[WSI_TOKEN_VERSION]		=*/ "Version",
+		/*[WSI_TOKEN_SWORIGIN]		=*/ "Sworigin",
+
+		/* new for 05 */
+		/*[WSI_TOKEN_EXTENSIONS]	=*/ "Extensions",
+
+		/* client receives these */
+		/*[WSI_TOKEN_ACCEPT]		=*/ "Accept",
+		/*[WSI_TOKEN_NONCE]		=*/ "Nonce",
+		/*[WSI_TOKEN_HTTP]		=*/ "Http",
+		/*[WSI_TOKEN_MUXURL]	=*/ "MuxURL",
+	};
+	char buf[256];
+
+	for (n = 0; n < WSI_TOKEN_COUNT; n++) {
+		if (!lws_hdr_total_length(wsi, n))
+			continue;
+
+		lws_hdr_copy(wsi, buf, sizeof buf, n);
+
+		fprintf(stderr, "    %s = %s\n", token_names[n], buf);
+	}
+}
+
+/* dumb_increment protocol */
+
+/*
+ * one of these is auto-created for each connection and a pointer to the
+ * appropriate instance is passed to the callback in the user parameter
+ *
+ * for this example protocol we use it to individualize the count for each
+ * connection.
+ */
+
+struct per_session_data__dumb_increment {
+	int number;
+};
+
+//static void get_client_notification()
+//{
+//	/* get non-exclusive (read) access to sessions_list (conns) */
+//	if (pthread_rwlock_rdlock (&session_lock) != 0) {
+//		ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+//		return NULL;
+//	}
+//	/* get session where send the RPC */
+//	locked_session = (struct session_with_mutex *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
+//	if (locked_session != NULL) {
+//		session = locked_session->session;
+//	}
+//	if (session != NULL) {
+//		/* get exclusive access to session */
+//		if (pthread_mutex_lock(&locked_session->lock) != 0) {
+//			/* unlock before returning error */
+//			if (pthread_rwlock_unlock (&session_lock) != 0) {
+//				ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+//				return NULL;
+//			}
+//			return NULL;
+//		}
+//		/* send the request and get the reply */
+//		msgt = nc_session_send_recv(session, rpc, &reply);
+//
+//		/* first release exclusive lock for this session */
+//		pthread_mutex_unlock(&locked_session->lock);
+//		/* end of critical section */
+//		if (pthread_rwlock_unlock (&session_lock) != 0) {
+//			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+//			return (NULL);
+//		}
+//
+//		/* process the result of the operation */
+//		switch (msgt) {
+//		case NC_MSG_UNKNOWN:
+//			if (nc_session_get_status(session) != NC_SESSION_STATUS_WORKING) {
+//				ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: receiving rpc-reply failed");
+//				netconf_close(server, conns, session_key);
+//				return (NULL);
+//			}
+//			/* no break */
+//		case NC_MSG_NONE:
+//			/* there is error handled by callback */
+//			return (NULL);
+//			break;
+//		case NC_MSG_REPLY:
+//			switch (replyt = nc_reply_get_type(reply)) {
+//			case NC_REPLY_DATA:
+//				if ((data = nc_reply_get_data (reply)) == NULL) {
+//					ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: no data from reply");
+//					data = NULL;
+//				}
+//				break;
+//			default:
+//				ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: unexpected rpc-reply (%d)", replyt);
+//				data = NULL;
+//				break;
+//			}
+//			break;
+//		default:
+//			ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: unexpected reply message received (%d)", msgt);
+//			data = NULL;
+//			break;
+//		}
+//		nc_reply_free(reply);
+//		return (data);
+//	} else {
+//		/* release lock on failure */
+//		if (pthread_rwlock_unlock (&session_lock) != 0) {
+//			ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+//		}
+//		ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to process.");
+//		return (NULL);
+//	}
+//}
+
+static int callback_notification(struct libwebsocket_context *context,
+			struct libwebsocket *wsi,
+			enum libwebsocket_callback_reasons reason,
+					       void *user, void *in, size_t len)
+{
+	int isnotif = 0;
+	int n, m;
+	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + LWS_SEND_BUFFER_POST_PADDING];
+	unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
+	struct per_session_data__dumb_increment *pss = (struct per_session_data__dumb_increment *)user;
+	#ifndef TEST_NOTIFICATION_SERVER
+	if (http_server != NULL) {
+		ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "libwebsockets callback_notification");
+	}
+	#endif
+
+	switch (reason) {
+
+	case LWS_CALLBACK_ESTABLISHED:
+		lwsl_info("callback_notification: LWS_CALLBACK_ESTABLISHED\n");
+		pss->number = 0;
+		break;
+
+	case LWS_CALLBACK_SERVER_WRITEABLE:
+//		get_client_notification();
+		n = sprintf((char *)p, "not%d\n", pss->number++);
+		m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
+		if (m < n) {
+			lwsl_err("ERROR %d writing to di socket\n", n);
+			return -1;
+		}
+		if (close_testing && pss->number == 50) {
+			lwsl_info("close tesing limit, closing\n");
+			return -1;
+		}
+		break;
+
+	case LWS_CALLBACK_RECEIVE:
+//		fprintf(stderr, "rx %d\n", (int)len);
+		if (len < 6)
+			break;
+		if (strcmp((const char *)in, "reset\n") == 0)
+			pss->number = 0;
+		break;
+	/*
+	 * this just demonstrates how to use the protocol filter. If you won't
+	 * study and reject connections based on header content, you don't need
+	 * to handle this callback
+	 */
+
+	case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
+		//dump_handshake_info(wsi);
+		/* you could return non-zero here and kill the connection */
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* list of supported protocols and callbacks */
+
+static struct libwebsocket_protocols protocols[] = {
+	/* first protocol must always be HTTP handler */
+
+	{
+		"http-only",		/* name */
+		callback_http,		/* callback */
+		sizeof (struct per_session_data__http),	/* per_session_data_size */
+		0,			/* max frame size / rx buffer */
+	},
+	{
+		"notification-protocol",
+		callback_notification,
+		sizeof(struct per_session_data__dumb_increment),
+		10,
+	},
+	{ NULL, NULL, 0, 0 } /* terminator */
+};
+
+
+int notification_init(apr_pool_t * pool, server_rec * server)
+{
+	char cert_path[1024];
+	char key_path[1024];
+	int use_ssl = 0;
+	struct lws_context_creation_info info;
+	int opts = 0;
+	char interface_name[128] = "";
+	const char *iface = NULL;
+	int debug_level = 7;
+
+	memset(&info, 0, sizeof info);
+	info.port = NOTIFICATION_SERVER_PORT;
+
+	/* tell the library what debug level to emit and to send it to syslog */
+	lws_set_log_level(debug_level, lwsl_emit_syslog);
+
+	#ifndef TEST_NOTIFICATION_SERVER
+	if (server != NULL) {
+		http_server = server;
+		ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "Initialization of libwebsocket");
+	}
+	#endif
+	lwsl_notice("libwebsockets test server - "
+			"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - "
+						    "licensed under LGPL2.1\n");
+	max_poll_elements = getdtablesize();
+	pollfds = malloc(max_poll_elements * sizeof (struct pollfd));
+	fd_lookup = malloc(max_poll_elements * sizeof (int));
+	if (pollfds == NULL || fd_lookup == NULL) {
+		lwsl_err("Out of memory pollfds=%d\n", max_poll_elements);
+		return -1;
+	}
+
+	info.iface = iface;
+	info.protocols = protocols;
+
+	//snprintf(cert_path, sizeof(cert_path), "%s/libwebsockets-test-server.pem", resource_path);
+	//snprintf(key_path, sizeof(cert_path), "%s/libwebsockets-test-server.key.pem", resource_path);
+
+	//info.ssl_cert_filepath = cert_path;
+	//info.ssl_private_key_filepath = key_path;
+
+	info.gid = -1;
+	info.uid = -1;
+	info.options = opts;
+
+	/* create server */
+	context = libwebsocket_create_context(&info);
+	if (context == NULL) {
+		lwsl_err("libwebsocket init failed\n");
+		return -1;
+	}
+}
+
+void notification_close()
+{
+	libwebsocket_context_destroy(context);
+
+	lwsl_notice("libwebsockets-test-server exited cleanly\n");
+}
+
+/**
+ * \brief send notification if any
+ * \return < 0 on error
+ */
+int notification_handle()
+{
+	static struct timeval tv;
+	static unsigned int olds = 0;
+	int n = 0;
+
+	gettimeofday(&tv, NULL);
+
+	/*
+	 * This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every
+	 * live websocket connection using the DUMB_INCREMENT protocol,
+	 * as soon as it can take more packets (usually immediately)
+	 */
+
+	if (((unsigned int)tv.tv_sec - olds) > 0) {
+		libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_NOTIFICATION]);
+		olds = tv.tv_sec;
+	}
+
+
+	/*
+	 * this represents an existing server's single poll action
+	 * which also includes libwebsocket sockets
+	 */
+
+	n = poll(pollfds, count_pollfds, 50);
+	if (n < 0)
+		return n;
+
+
+	if (n) {
+		for (n = 0; n < count_pollfds; n++) {
+			if (pollfds[n].revents) {
+				/*
+				 * returns immediately if the fd does not
+				 * match anything under libwebsockets
+				 * control
+				 */
+				if (libwebsocket_service_fd(context, &pollfds[n]) < 0) {
+					return 1;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+#endif
+
+
+#ifndef WITH_NOTIFICATIONS
+#ifdef TEST_NOTIFICATION_SERVER
+int main(int argc, char **argv)
+{
+//	char cert_path[1024];
+//	char key_path[1024];
+//	int n = 0;
+//	int use_ssl = 0;
+//	struct libwebsocket_context *context;
+//	int opts = 0;
+//	char interface_name[128] = "";
+//	const char *iface = NULL;
+//	unsigned int oldus = 0;
+//	unsigned int olds = 0;
+//	struct lws_context_creation_info info;
+//
+//	int debug_level = 7;
+//
+//	memset(&info, 0, sizeof info);
+//	info.port = 8081;
+//
+//	/* tell the library what debug level to emit and to send it to syslog */
+//	lws_set_log_level(debug_level, lwsl_emit_syslog);
+//
+//	lwsl_notice("libwebsockets test server - "
+//			"(C) Copyright 2010-2013 Andy Green <andy@warmcat.com> - "
+//						    "licensed under LGPL2.1\n");
+//	max_poll_elements = getdtablesize();
+//	pollfds = malloc(max_poll_elements * sizeof (struct pollfd));
+//	fd_lookup = malloc(max_poll_elements * sizeof (int));
+//	if (pollfds == NULL || fd_lookup == NULL) {
+//		lwsl_err("Out of memory pollfds=%d\n", max_poll_elements);
+//		return -1;
+//	}
+//
+//	info.iface = iface;
+//	info.protocols = protocols;
+//
+//	//snprintf(cert_path, sizeof(cert_path), "%s/libwebsockets-test-server.pem", resource_path);
+//	//snprintf(key_path, sizeof(cert_path), "%s/libwebsockets-test-server.key.pem", resource_path);
+//
+//	//info.ssl_cert_filepath = cert_path;
+//	//info.ssl_private_key_filepath = key_path;
+//	//
+//	info.gid = -1;
+//	info.uid = -1;
+//	info.options = opts;
+//
+//	/* create server */
+//	context = libwebsocket_create_context(&info);
+//	if (context == NULL) {
+//		lwsl_err("libwebsocket init failed\n");
+//		return -1;
+//	}
+//
+//	n = 0;
+//	while (n >= 0 && !force_exit) {
+//		struct timeval tv;
+//
+//		gettimeofday(&tv, NULL);
+//
+//		/*
+//		 * This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every
+//		 * live websocket connection using the DUMB_INCREMENT protocol,
+//		 * as soon as it can take more packets (usually immediately)
+//		 */
+//
+//		if (((unsigned int)tv.tv_sec - olds) > 0) {
+//			libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_NOTIFICATION]);
+//			olds = tv.tv_sec;
+//		}
+//
+//
+//		/*
+//		 * this represents an existing server's single poll action
+//		 * which also includes libwebsocket sockets
+//		 */
+//
+//		n = poll(pollfds, count_pollfds, 50);
+//		if (n < 0)
+//			continue;
+//
+//
+//		if (n) {
+//			for (n = 0; n < count_pollfds; n++) {
+//				if (pollfds[n].revents) {
+//					/*
+//					* returns immediately if the fd does not
+//					* match anything under libwebsockets
+//					* control
+//					*/
+//					if (libwebsocket_service_fd(context, &pollfds[n]) < 0) {
+//						break;
+//					}
+//				}
+//			}
+//		}
+//	}
+//
+//	libwebsocket_context_destroy(context);
+//
+//	lwsl_notice("libwebsockets-test-server exited cleanly\n");
+//
+//	return 0;
+	if (notification_init(NULL, NULL) == -1) {
+		fprintf(stderr, "Error during initialization\n");
+		return 1;
+	}
+	while (!force_exit) {
+		notification_handle();
+	}
+	notification_close();
+}
+#endif
+#endif
diff --git a/src/notification_module.h b/src/notification_module.h
new file mode 100644
index 0000000..8166af3
--- /dev/null
+++ b/src/notification_module.h
@@ -0,0 +1,64 @@
+/*!
+ * \file notification_module.h
+ * \brief 
+ * \author Tomas Cejka <cejkat@cesnet.cz>
+ * \date 2013
+ */
+/*
+ * Copyright (C) 2013 CESNET
+ *
+ * LICENSE TERMS
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of the Company nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this
+ * product may be distributed under the terms of the GNU General Public
+ * License (GPL) version 2 or later, in which case the provisions
+ * of the GPL apply INSTEAD OF those given above.
+ *
+ * This software is provided ``as is'', and any express or implied
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose are disclaimed.
+ * In no event shall the company or contributors be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential
+ * damages (including, but not limited to, procurement of substitute
+ * goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether
+ * in contract, strict liability, or tort (including negligence or
+ * otherwise) arising in any way out of the use of this software, even
+ * if advised of the possibility of such damage.
+ *
+ */
+#ifndef __NOTIFICATION_MODULE_H
+#define __NOTIFICATION_MODULE_H
+#include "libwebsockets.h"
+
+#ifndef TEST_NOTIFICATION_SERVER
+#include <httpd.h>
+#include <http_log.h>
+#else
+typedef struct p {} apr_pool_t;
+typedef struct s {} server_rec;
+#endif
+
+#define NOTIFICATION_SERVER_PORT	8080
+
+int notification_init(apr_pool_t * pool, server_rec * server);
+
+int notification_handle();
+
+void notification_close();
+
+#endif
+