mod_netconf: notification testing version
- refs #655
diff --git a/src/Makefile.in b/src/Makefile.in
index bbc80db..e899de3 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -28,9 +28,12 @@
LIBS=@LIBS@
SRCS=mod_netconf.c \
+ notification-server.c \
test-client.c
-HDRS=message_type.h
+HDRS=message_type.h \
+ notification_module.h \
+ mod_netconf.h
all: module client
diff --git a/src/VERSION b/src/VERSION
index 78bc1ab..d9df1bb 100644
--- a/src/VERSION
+++ b/src/VERSION
@@ -1 +1 @@
-0.10.0
+0.11.0
diff --git a/src/configure b/src/configure
index 5bce59a..d64ca9b 100755
--- a/src/configure
+++ b/src/configure
@@ -2995,8 +2995,8 @@
{ (exit 1); exit 1; }; }
fi
-REQS="$REQS libnetconf"
-BUILDREQS="$BUILDREQS libnetconf-devel"
+REQS="$REQS libnetconf >= 0.4.0 libwebsockets"
+BUILDREQS="$BUILDREQS libnetconf-devel libwebsockets-devel"
CPPFLAGS=""
# Checks for header files.
diff --git a/src/configure.in b/src/configure.in
index 43e7ca2..26715ae 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -29,8 +29,8 @@
# Checks for libraries.
AC_SEARCH_LIBS([ncds_apply_rpc],[netconf], ,AC_MSG_ERROR([libnetconf not found!]))
-REQS="$REQS libnetconf"
-BUILDREQS="$BUILDREQS libnetconf-devel"
+REQS="$REQS libnetconf >= 0.4.0 libwebsockets"
+BUILDREQS="$BUILDREQS libnetconf-devel libwebsockets-devel"
CPPFLAGS=""
# Checks for header files.
diff --git a/src/libwebsockets.h b/src/libwebsockets.h
deleted file mode 100644
index b7eaa41..0000000
--- a/src/libwebsockets.h
+++ /dev/null
@@ -1,982 +0,0 @@
-/*
- * 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 b2e11de..24aa4d8 100644
--- a/src/mod_netconf.c
+++ b/src/mod_netconf.c
@@ -223,6 +223,7 @@
(port==NULL) ? "830" : port,
nc_session_get_id(session));
+ /** \todo allocate from apr_pool */
if ((locked_session = malloc (sizeof (struct session_with_mutex))) == NULL || pthread_mutex_init (&locked_session->lock, NULL) != 0) {
nc_session_free(session);
free (locked_session);
@@ -240,6 +241,7 @@
ap_log_error (APLOG_MARK, APLOG_ERR, 0, server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
return NULL;
}
+ locked_session->notifications = apr_array_make(pool, NOTIFICATION_QUEUE_SIZE, sizeof(notification_t));
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "Add connection to the list");
apr_hash_set(conns, apr_pstrdup(pool, session_key), APR_HASH_KEY_STRING, (void *) locked_session);
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, server, "Before session_unlock");
@@ -270,6 +272,8 @@
}
locked_session = (struct session_with_mutex *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
if (locked_session != NULL) {
+ /** \todo free all notifications from queue */
+ apr_array_clear(locked_session->notifications);
pthread_mutex_destroy(&locked_session->lock);
ns = locked_session->session;
free (locked_session);
@@ -1446,8 +1450,11 @@
return;
}
+ /* prepare internal lists */
+ netconf_sessions_list = apr_hash_make(pool);
+
#ifdef WITH_NOTIFICATIONS
- if (notification_init(pool, server) == -1) {
+ if (notification_init(pool, server, netconf_sessions_list) == -1) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "libwebsockets initialization failed");
use_notifications = 0;
} else {
@@ -1455,9 +1462,6 @@
}
#endif
- /* prepare internal lists */
- netconf_sessions_list = apr_hash_make(pool);
-
/* setup libnetconf's callbacks */
nc_verbosity(NC_VERB_DEBUG);
clb_print_server = server;
diff --git a/src/mod_netconf.spec.in b/src/mod_netconf.spec.in
index af04b73..88bc5cf 100644
--- a/src/mod_netconf.spec.in
+++ b/src/mod_netconf.spec.in
@@ -20,7 +20,7 @@
%setup
%build
-%configure --with-distro=@DISTRO@ @LIBNETCONF_WITH@;
+%configure --with-distro=@DISTRO@ @LIBNETCONF_WITH@ --with-notifications;
make
%install
@@ -29,7 +29,7 @@
%post
#add device module to configuration only when installing, not on update or reinstall.
#https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging/Guidelines#Running_scriptlets_only_in_certain_situations
-[ -d /var/run/httpd ] || {mkdir -p /var/run/httpd && chown apache:apache /var/run/httpd}
+[ -d /var/run/httpd ] || { mkdir -p /var/run/httpd && chown apache:apache /var/run/httpd; }
service httpd restart
%postun
diff --git a/src/notification-server.c b/src/notification-server.c
index 382629b..0fdbba4 100644
--- a/src/notification-server.c
+++ b/src/notification-server.c
@@ -25,14 +25,23 @@
#include <string.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <sys/queue.h>
#include <fcntl.h>
#include <assert.h>
-#include "libwebsockets.h"
+#include <pthread.h>
+#include <libnetconf.h>
+#include <libwebsockets.h>
#include "notification_module.h"
+#include "mod_netconf.h"
#ifndef TEST_NOTIFICATION_SERVER
#include <httpd.h>
#include <http_log.h>
+#include <apr_hash.h>
+#include <apr_tables.h>
+
+#else
+static int force_exit = 0;
#endif
#if defined(TEST_NOTIFICATION_SERVER) || defined(WITH_NOTIFICATIONS)
@@ -42,10 +51,19 @@
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;
+extern pthread_rwlock_t session_lock; /**< mutex protecting netconf_session_list from multiple access errors */
+
+struct ntf_thread_config {
+ struct nc_session *session;
+ char *session_hash;
+};
+
+static apr_hash_t *netconf_locked_sessions = NULL;
+static pthread_key_t thread_key;
+
/*
* This demo server shows how to use libwebsockets for one or more
* websocket protocols in the same server
@@ -236,8 +254,7 @@
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);
+ //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;
@@ -283,53 +300,51 @@
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);
- }
-}
+//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 */
@@ -341,102 +356,320 @@
* connection.
*/
-struct per_session_data__dumb_increment {
+struct per_session_data__notif_client {
int number;
+ char *session_key;
+ struct nc_session *session;
};
-//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);
-// }
-//}
+struct session_with_mutex *get_ncsession_from_key(const char *session_key)
+{
+ struct session_with_mutex *locked_session = NULL;
+ if (session_key == NULL) {
+ return (NULL);
+ }
+ if (pthread_rwlock_wrlock(&session_lock) != 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+ #endif
+ return (NULL);
+ }
+ locked_session = (struct session_with_mutex *)apr_hash_get(netconf_locked_sessions, session_key, APR_HASH_KEY_STRING);
+ if (pthread_rwlock_unlock (&session_lock) != 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+ #endif
+ return (NULL);
+ }
+ return locked_session;
+}
+
+/* rpc parameter is freed after the function call */
+static int send_recv_process(struct nc_session *session, const char* operation, nc_rpc* rpc)
+{
+ nc_reply *reply = NULL;
+ char *data = NULL;
+ int ret = EXIT_SUCCESS;
+
+ /* send the request and get the reply */
+ switch (nc_session_send_recv(session, rpc, &reply)) {
+ case NC_MSG_UNKNOWN:
+ if (nc_session_get_status(session) != NC_SESSION_STATUS_WORKING) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: receiving rpc-reply failed.");
+ }
+ #endif
+ //cmd_disconnect(NULL);
+ ret = EXIT_FAILURE;
+ break;
+ }
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Unknown error occurred.");
+ }
+ #endif
+ ret = EXIT_FAILURE;
+ break;
+ case NC_MSG_NONE:
+ /* error occurred, but processed by callback */
+ break;
+ case NC_MSG_REPLY:
+ switch (nc_reply_get_type(reply)) {
+ case NC_REPLY_OK:
+ break;
+ case NC_REPLY_DATA:
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notifications: recv: %s.", data = nc_reply_get_data (reply));
+ free(data);
+ }
+ #endif
+ break;
+ case NC_REPLY_ERROR:
+ /* wtf, you shouldn't be here !?!? */
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: operation failed, but rpc-error was not processed.");
+ }
+ #endif
+ ret = EXIT_FAILURE;
+ break;
+ default:
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: unexpected operation result.");
+ }
+ #endif
+ ret = EXIT_FAILURE;
+ break;
+ }
+ break;
+ default:
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Unknown error occurred.");
+ }
+ #endif
+ ret = EXIT_FAILURE;
+ break;
+ }
+ nc_rpc_free(rpc);
+ nc_reply_free(reply);
+
+ return (ret);
+}
+
+/**
+ * \brief Callback to store incoming notification
+ * \param [in] eventtime - time when notification occured
+ * \param [in] content - content of notification
+ */
+static void notification_fileprint (time_t eventtime, const char* content)
+{
+ char t[128];
+ struct session_with_mutex *target_session = NULL;
+ notification_t *ntf = NULL;
+ char *session_hash = NULL;
+
+ t[0] = 0;
+ strftime(t, sizeof(t), "%c", localtime(&eventtime));
+
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: eventTime: %s\n%s\n", t, content);
+ }
+
+ /* \todo replace last_session_key with client identification */
+ session_hash = pthread_getspecific(thread_key);
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: fileprint getspecific (%s)", session_hash);
+ }
+ target_session = get_ncsession_from_key(session_hash);
+ if (target_session == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "no session found last_session_key (%s)", session_hash);
+ return;
+ }
+ if (pthread_mutex_lock(&target_session->lock) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "Error while locking rwlock: %d (%s)", errno, strerror(errno));
+ return;
+ }
+ if (target_session->notifications == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "target_session->notifications is NULL");
+ if (pthread_mutex_unlock(&target_session->lock) != 0) {
+ ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+ return;
+ }
+ return;
+ }
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: ready to push to notifications queue");
+ }
+ ntf = (notification_t *) apr_array_push(target_session->notifications);
+ if (ntf == NULL) {
+ ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Failed to allocate element ");
+ if (pthread_mutex_unlock(&target_session->lock) != 0) {
+ ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+ return;
+ }
+ return;
+ }
+ ntf->eventtime = time(NULL);
+ //ntf->content = strdup("notifikace");
+ //ntf->eventtime = eventtime;
+ ntf->content = strdup(content);
+
+ if (http_server != NULL) {
+ ap_log_error (APLOG_MARK, APLOG_NOTICE, 0, http_server, "added notif to queue %u (%s)", (unsigned int) ntf->eventtime, "notifikace");
+ }
+
+ if (pthread_mutex_unlock(&target_session->lock) != 0) {
+ ap_log_error (APLOG_MARK, APLOG_ERR, 0, http_server, "Error while unlocking rwlock: %d (%s)", errno, strerror(errno));
+ return;
+ }
+}
+
+/**
+ * \brief Thread for libnetconf notifications dispatch
+ * \param [in] arg - struct ntf_thread_config * with nc_session
+ */
+void* notification_thread(void* arg)
+{
+ struct ntf_thread_config *config = (struct ntf_thread_config*)arg;
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notifications: in thread for libnetconf notifications");
+ }
+ #endif
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notifications: pthread_key_create");
+ }
+ if (pthread_key_create(&thread_key, NULL) != 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: pthread_key_create failed");
+ }
+ #endif
+ }
+ pthread_setspecific(thread_key, config->session_hash);
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notifications: dispatching");
+ }
+ ncntf_dispatch_receive(config->session, notification_fileprint);
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notifications: ended thread for libnetconf notifications");
+ }
+ #endif
+ free(config);
+ return (NULL);
+}
+
+
+int notif_subscribe(struct session_with_mutex *locked_session, const char *session_hash, time_t start_time, time_t stop_time)
+{
+ time_t start = -1;
+ time_t stop = -1;
+ struct nc_filter *filter = NULL;
+ char *stream = NULL;
+ nc_rpc *rpc = NULL;
+ pthread_t thread;
+ struct ntf_thread_config *tconfig;
+ struct nc_session *session;
+
+ if (locked_session == NULL) {
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: no locked_session was given.");
+ }
+ return (EXIT_FAILURE);
+ }
+
+ session = locked_session->session;
+
+ start = time(NULL) + start_time;
+ stop = time(NULL) + stop_time;
+ if (http_server != NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: history: %u %u", (unsigned int) start, (unsigned int) stop);
+ }
+
+ if (session == NULL) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: NETCONF session not established.");
+ }
+ #endif
+ return (EXIT_FAILURE);
+ }
+
+ /* check if notifications are allowed on this session */
+ if (nc_session_notif_allowed(session) == 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Notification subscription is not allowed on this session.");
+ }
+ #endif
+ return (EXIT_FAILURE);
+ }
+ /* check times */
+ if (start != -1 && stop != -1 && start > stop) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: Subscription start time must be lower than the end time.");
+ }
+ #endif
+ return (EXIT_FAILURE);
+ }
+
+ /* create requests */
+ rpc = nc_rpc_subscribe(stream, filter, (start_time == 0)?NULL:&start, (stop_time == 0)?NULL:&stop);
+ nc_filter_free(filter);
+ if (rpc == NULL) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating an rpc request failed.");
+ }
+ #endif
+ return (EXIT_FAILURE);
+ }
+
+ if (send_recv_process(session, "subscribe", rpc) != 0) {
+ return (EXIT_FAILURE);
+ }
+ rpc = NULL; /* just note that rpc is already freed by send_recv_process() */
+
+ tconfig = malloc(sizeof(struct ntf_thread_config));
+ tconfig->session = session;
+ tconfig->session_hash = strdup(session_hash);
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating libnetconf notification thread (%s).",
+ tconfig->session_hash);
+ }
+ if (pthread_create(&thread, NULL, notification_thread, tconfig) != 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notifications: creating a thread for receiving notifications failed");
+ }
+ #endif
+ return (EXIT_FAILURE);
+ }
+ pthread_detach(thread);
+ return (EXIT_SUCCESS);
+}
static int callback_notification(struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
- void *user, void *in, size_t len)
+ 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];
+ int n = 0;
+ int m = 0;
+ unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 + 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
+ struct per_session_data__notif_client *pss = (struct per_session_data__notif_client *)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) {
@@ -447,8 +680,70 @@
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 (pss->session_key == NULL) {
+ return 0;
+ }
+ /*
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: prepare to SENDING");
+ }
+ */
+
+ struct session_with_mutex *ls = get_ncsession_from_key(pss->session_key);
+ if (ls == NULL) {
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: session not found");
+ }
+ return -1;
+ }
+ if (pthread_mutex_lock(&ls->lock) != 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: cannot lock session");
+ }
+ #endif
+ }
+ notification_t *notif = NULL;
+ if (ls->notifications == NULL) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: no notifications array");
+ }
+ #endif
+ pthread_mutex_unlock(&ls->lock);
+ return -1;
+ }
+
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: POP notifications for session");
+ }
+
+ while ((notif = (notification_t *) apr_array_pop(ls->notifications)) != NULL) {
+ char t[128];
+ t[0] = 0;
+ strftime(t, sizeof(t), "%c", localtime(¬if->eventtime));
+ n = 0;
+ n = sprintf((char *)p, "%s\n", notif->content);
+ m = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
+ //free(notif->content);
+ //free(notif);
+ }
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: POP notifications done");
+ }
+
+ if (pthread_mutex_unlock(&ls->lock) != 0) {
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, http_server, "notification: cannot unlock session");
+ }
+ #endif
+ }
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: unlocked session lock");
+ }
+
+
if (m < n) {
lwsl_err("ERROR %d writing to di socket\n", n);
return -1;
@@ -461,6 +756,37 @@
case LWS_CALLBACK_RECEIVE:
// fprintf(stderr, "rx %d\n", (int)len);
+ #ifndef TEST_NOTIFICATION_SERVER
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "received: (%s)", (char *)in);
+ }
+ #endif
+ if (pss->session_key == NULL) {
+ char session_key_buf[41];
+ int start = -1;
+ time_t stop = time(NULL) + 30;
+
+ strncpy((char *) session_key_buf, (const char *) in, 40);
+ session_key_buf[40] = '\0';
+ pss->session_key = strdup(session_key_buf);
+ sscanf(in+40, "%d %d", (int *) &start, (int *) &stop);
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: get key (%s) from (%s) (%i,%i)", pss->session_key, (char *) in, (int) start, (int) stop);
+ }
+
+ /* TODO subscribe, map with ncnotif print callback */
+ struct session_with_mutex *ls = get_ncsession_from_key(pss->session_key);
+ if (ls == NULL) {
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, http_server, "notification: session_key not found (%s)", pss->session_key);
+ }
+ return 0;
+ }
+ if (http_server != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, http_server, "notification: prepare to subscribe stream");
+ }
+ notif_subscribe(ls, pss->session_key, (time_t) start, (time_t) stop);
+ }
if (len < 6)
break;
if (strcmp((const char *)in, "reset\n") == 0)
@@ -498,24 +824,29 @@
{
"notification-protocol",
callback_notification,
- sizeof(struct per_session_data__dumb_increment),
- 10,
+ sizeof(struct per_session_data__notif_client),
+ 80,
},
{ NULL, NULL, 0, 0 } /* terminator */
};
-int notification_init(apr_pool_t * pool, server_rec * server)
+/**
+ * initialization of notification module
+ */
+int notification_init(apr_pool_t * pool, server_rec * server, apr_hash_t *conns)
{
- char cert_path[1024];
- char key_path[1024];
- int use_ssl = 0;
+ //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] = "";
+ //char interface_name[128] = "";
const char *iface = NULL;
int debug_level = 7;
+ netconf_locked_sessions = conns;
+
memset(&info, 0, sizeof info);
info.port = NOTIFICATION_SERVER_PORT;
@@ -558,6 +889,7 @@
lwsl_err("libwebsocket init failed\n");
return -1;
}
+ return 0;
}
void notification_close()
@@ -567,6 +899,7 @@
lwsl_notice("libwebsockets-test-server exited cleanly\n");
}
+
/**
* \brief send notification if any
* \return < 0 on error
@@ -625,106 +958,6 @@
#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;
diff --git a/src/notification_module.h b/src/notification_module.h
index 8166af3..8861e12 100644
--- a/src/notification_module.h
+++ b/src/notification_module.h
@@ -42,11 +42,12 @@
*/
#ifndef __NOTIFICATION_MODULE_H
#define __NOTIFICATION_MODULE_H
-#include "libwebsockets.h"
+#include <libwebsockets.h>
#ifndef TEST_NOTIFICATION_SERVER
#include <httpd.h>
#include <http_log.h>
+#include <apr_hash.h>
#else
typedef struct p {} apr_pool_t;
typedef struct s {} server_rec;
@@ -54,10 +55,24 @@
#define NOTIFICATION_SERVER_PORT 8080
-int notification_init(apr_pool_t * pool, server_rec * server);
+/**
+ * \brief Notification module initialization
+ * \param pool - apr_pool_t for memory allocation
+ * \param server - server_rec for Apache logging
+ * \param conns - apr_hash_t representing the list of netconf connections
+ * \return 0 on success
+ */
+int notification_init(apr_pool_t * pool, server_rec * server, apr_hash_t *conns);
+/**
+ * \brief Handle method - passes execution into the libwebsocket library
+ * \return 0 on success
+ */
int notification_handle();
+/**
+ * \brief Notification module finalization
+ */
void notification_close();
#endif