intégration des logiciels tier comme NanoMQ ainsi que les fichiers json de score

This commit is contained in:
2024-11-18 22:44:28 +01:00
parent 8f2ed89e05
commit a04c4c1f59
138 changed files with 27816 additions and 0 deletions

View File

@ -0,0 +1,539 @@
//
// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
// Copyright 2020 Dirac Research <robert.bielik@dirac.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef NNG_SUPPLEMENTAL_HTTP_HTTP_H
#define NNG_SUPPLEMENTAL_HTTP_HTTP_H
// HTTP API. Only present if HTTP support compiled into the library.
// Functions will return NNG_ENOTSUP (or NULL or 0 as appropriate)
// if the library lacks support for HTTP.
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
struct nng_tls_config;
// HTTP status codes. This list is not exhaustive.
enum nng_http_status {
NNG_HTTP_STATUS_CONTINUE = 100,
NNG_HTTP_STATUS_SWITCHING = 101,
NNG_HTTP_STATUS_PROCESSING = 102,
NNG_HTTP_STATUS_OK = 200,
NNG_HTTP_STATUS_CREATED = 201,
NNG_HTTP_STATUS_ACCEPTED = 202,
NNG_HTTP_STATUS_NOT_AUTHORITATIVE = 203,
NNG_HTTP_STATUS_NO_CONTENT = 204,
NNG_HTTP_STATUS_RESET_CONTENT = 205,
NNG_HTTP_STATUS_PARTIAL_CONTENT = 206,
NNG_HTTP_STATUS_MULTI_STATUS = 207,
NNG_HTTP_STATUS_ALREADY_REPORTED = 208,
NNG_HTTP_STATUS_IM_USED = 226,
NNG_HTTP_STATUS_MULTIPLE_CHOICES = 300,
NNG_HTTP_STATUS_STATUS_MOVED_PERMANENTLY = 301,
NNG_HTTP_STATUS_FOUND = 302,
NNG_HTTP_STATUS_SEE_OTHER = 303,
NNG_HTTP_STATUS_NOT_MODIFIED = 304,
NNG_HTTP_STATUS_USE_PROXY = 305,
NNG_HTTP_STATUS_TEMPORARY_REDIRECT = 307,
NNG_HTTP_STATUS_PERMANENT_REDIRECT = 308,
NNG_HTTP_STATUS_BAD_REQUEST = 400,
NNG_HTTP_STATUS_UNAUTHORIZED = 401,
NNG_HTTP_STATUS_PAYMENT_REQUIRED = 402,
NNG_HTTP_STATUS_FORBIDDEN = 403,
NNG_HTTP_STATUS_NOT_FOUND = 404,
NNG_HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
NNG_HTTP_STATUS_NOT_ACCEPTABLE = 406,
NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED = 407,
NNG_HTTP_STATUS_REQUEST_TIMEOUT = 408,
NNG_HTTP_STATUS_CONFLICT = 409,
NNG_HTTP_STATUS_GONE = 410,
NNG_HTTP_STATUS_LENGTH_REQUIRED = 411,
NNG_HTTP_STATUS_PRECONDITION_FAILED = 412,
NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE = 413,
NNG_HTTP_STATUS_ENTITY_TOO_LONG = 414,
NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416,
NNG_HTTP_STATUS_EXPECTATION_FAILED = 417,
NNG_HTTP_STATUS_TEAPOT = 418,
NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY = 422,
NNG_HTTP_STATUS_LOCKED = 423,
NNG_HTTP_STATUS_FAILED_DEPENDENCY = 424,
NNG_HTTP_STATUS_UPGRADE_REQUIRED = 426,
NNG_HTTP_STATUS_PRECONDITION_REQUIRED = 428,
NNG_HTTP_STATUS_TOO_MANY_REQUESTS = 429,
NNG_HTTP_STATUS_HEADERS_TOO_LARGE = 431,
NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS = 451,
NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
NNG_HTTP_STATUS_NOT_IMPLEMENTED = 501,
NNG_HTTP_STATUS_BAD_GATEWAY = 502,
NNG_HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
NNG_HTTP_STATUS_GATEWAY_TIMEOUT = 504,
NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP = 505,
NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = 506,
NNG_HTTP_STATUS_INSUFFICIENT_STORAGE = 507,
NNG_HTTP_STATUS_LOOP_DETECTED = 508,
NNG_HTTP_STATUS_NOT_EXTENDED = 510,
NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED = 511,
};
// nng_http_req represents an HTTP request.
typedef struct nng_http_req nng_http_req;
// nng_http_req_alloc creates a vanilla HTTP request object. The object is
// initialized with the given URL object for an HTTP/1.1 GET request by
// default. It also adds the Host: header required for HTTP/1.1. If the
// url is NULL, then the uri and Host: header are uninitialized, and will
// need to be set explicitly.
NNG_DECL int nng_http_req_alloc(nng_http_req **, const nng_url *);
// nng_http_req_free frees an HTTP request object.
NNG_DECL void nng_http_req_free(nng_http_req *);
// nng_http_req_get_method returns the method.
NNG_DECL const char *nng_http_req_get_method(nng_http_req *);
// nng_http_req_get_version returns the version, usually HTTP/1.1.
NNG_DECL const char *nng_http_req_get_version(nng_http_req *);
// nng_http_req_get_uri returns the "abs-uri", which is URL without
// the scheme, host, or port.
NNG_DECL const char *nng_http_req_get_uri(nng_http_req *);
// nng_http_req_set_header sets an HTTP header, replacing any previous value
// that might have been present.
NNG_DECL int nng_http_req_set_header(
nng_http_req *, const char *, const char *);
// nng_http_req_add_header adds an HTTP header, without disrupting any other
// with the same name that might have been present.
NNG_DECL int nng_http_req_add_header(
nng_http_req *, const char *, const char *);
// nng_http_req_del_header deletes all occurrences of a named header.
NNG_DECL int nng_http_req_del_header(nng_http_req *, const char *);
// nng_http_req_get_header looks up a header with the named, returns NULL
// if not found.
NNG_DECL const char *nng_http_req_get_header(nng_http_req *, const char *);
// nng_http_req_set_method is used to change the method of a request.
// The method should be an upper case HTTP method, like POST, or DELETE.
// Null sets the default ("GET").
NNG_DECL int nng_http_req_set_method(nng_http_req *, const char *);
// nng_http_req_set_version is used to change the version of a request.
// Normally the version is "HTTP/1.1". Note that the framework does
// not support HTTP/2 at all. Null sets the default ("HTTP/1.1").
NNG_DECL int nng_http_req_set_version(nng_http_req *, const char *);
// nng_http_req_set_uri is used to change the URI of a request. This
// should be an "abs-uri", that is a path, plus query and fragment if
// needed. The scheme, host, and port don't belong here. The URI should
// start with a leading '/' per HTTP.
NNG_DECL int nng_http_req_set_uri(nng_http_req *, const char *);
// nng_http_req_set_data adds entity data to the request. The
// data object must persist (so only really useful for static data).
// The content-length header is updated as well, but the caller should
// probably set the content-type header.
NNG_DECL int nng_http_req_set_data(nng_http_req *, const void *, size_t);
// nng_http_req_copy_data adds entity data to the response. A private
// copy of the data is made (will be freed with the request).
// The content-length header is updated as well, but the caller should
// probably set the content-type header.
NNG_DECL int nng_http_req_copy_data(nng_http_req *, const void *, size_t);
// nng_http_req_get_data gets the data for the response.
NNG_DECL void nng_http_req_get_data(nng_http_req *, void **, size_t *);
// nng_http_res represents an HTTP response.
typedef struct nng_http_res nng_http_res;
// nng_http_res_alloc creates a vanilla HTTP response object. The object is
// initialized for an HTTP/1.1 200 OK response by default.
NNG_DECL int nng_http_res_alloc(nng_http_res **);
// nng_http_res_alloc_error creates an error HTTP response object. The object
// is initialized for an HTTP/1.1 response, and contains an associated
// generic HTML error page.
NNG_DECL int nng_http_res_alloc_error(nng_http_res **, uint16_t);
// nng_http_res_free frees an HTTP response object.
NNG_DECL void nng_http_res_free(nng_http_res *);
// nng_http_res_get_status returns the HTTP status code from the server.
NNG_DECL uint16_t nng_http_res_get_status(nng_http_res *);
// nng_http_res_set_status sets the HTTP status code.
NNG_DECL int nng_http_res_set_status(nng_http_res *, uint16_t);
// nng_http_res_get_reason returns the human readable status message
// that the server responds (or responded) with.
NNG_DECL const char *nng_http_res_get_reason(nng_http_res *);
// nng_http_res_set_reason sets the human readable status message.
// NULL means that a default reason is used based on the status code.
NNG_DECL int nng_http_res_set_reason(nng_http_res *, const char *);
// nng_http_res_set_header sets an HTTP header, replacing any previous value
// that might have been present.
NNG_DECL int nng_http_res_set_header(
nng_http_res *, const char *, const char *);
// nng_http_res_add_header adds an HTTP header, without disrupting any other
// with the same name that might have been present.
NNG_DECL int nng_http_res_add_header(
nng_http_res *, const char *, const char *);
// nng_http_res_del_header deletes all occurrences of a named header.
NNG_DECL int nng_http_res_del_header(nng_http_res *, const char *);
// nng_http_res_get_header looks up a header with the named, returns NULL
// if not found.
NNG_DECL const char *nng_http_res_get_header(nng_http_res *, const char *);
// nng_http_res_set_version is used to change the version of a response.
// Normally the version is "HTTP/1.1". Note that the framework does
// not support HTTP/2 at all. NULL sets the default ("HTTP/1.1").
NNG_DECL int nng_http_res_set_version(nng_http_res *, const char *);
// nng_http_res_get_version returns the version, usually HTTP/1.1.
NNG_DECL const char *nng_http_res_get_version(nng_http_res *);
// nng_http_res_get_data gets the data for the response.
NNG_DECL void nng_http_res_get_data(nng_http_res *, void **, size_t *);
// nng_http_res_set_data adds entity data to the response. The
// data object must persist (so only really useful for static data).
// The content-length header is updated as well, but the caller should
// probably set the content-type header.
NNG_DECL int nng_http_res_set_data(nng_http_res *, const void *, size_t);
// nng_http_res_copy_data adds entity data to the response. A private
// copy of the data is made (will be freed with the request).
// The content-length header is updated as well, but the caller should
// probably set the content-type header.
NNG_DECL int nng_http_res_copy_data(nng_http_res *, const void *, size_t);
// An nng_http_conn represents an underlying "connection". It may be
// a TCP channel, or a TLS channel, but the main thing is that this is
// normally only used for exchanging HTTP requests and responses.
typedef struct nng_http_conn nng_http_conn;
// nng_http_conn_close closes the underlying channel. Applications should
// not use this channel after this operation is performed.
NNG_DECL void nng_http_conn_close(nng_http_conn *);
// nng_http_conn_read attempts to read data from the connection. This
// completes as soon as at least one byte is read; it does not wait
// for the entire aio to be filled.
NNG_DECL void nng_http_conn_read(nng_http_conn *, nng_aio *);
// nng_http_conn_read_all is like nng_http_conn_read, but it does not
// finish until either all the requested data is read, or an error occurs.
NNG_DECL void nng_http_conn_read_all(nng_http_conn *, nng_aio *);
// nng_http_conn_write attempts to write data, but it can write less
// than the amount requested. (It completes as soon as at least one
// byte is written.)
NNG_DECL void nng_http_conn_write(nng_http_conn *, nng_aio *);
// nng_http_conn_write_all is like nng_http_conn_write, but it does not
// finish until either all the requested data is written, or an error occurs.
NNG_DECL void nng_http_conn_write_all(nng_http_conn *, nng_aio *);
// nng_http_conn_write_req writes the entire request. It will also write any
// data that has been attached.
NNG_DECL void nng_http_conn_write_req(
nng_http_conn *, nng_http_req *, nng_aio *);
// nng_http_conn_write_res writes the entire response. It will also write any
// data that has been attached.
NNG_DECL void nng_http_conn_write_res(
nng_http_conn *, nng_http_res *, nng_aio *);
// nng_http_conn_read_req reads an entire request, EXCEPT for any entity
// data. The caller is responsible for processing the headers in the request
// and reading any submitted entity data itself.
NNG_DECL void nng_http_conn_read_req(
nng_http_conn *, nng_http_req *, nng_aio *);
// nng_http_conn_read_res reads an entire response, EXCEPT for any entity
// data. The caller is responsible for processing the headers in the response
// and reading any submitted entity data itself.
NNG_DECL void nng_http_conn_read_res(
nng_http_conn *, nng_http_res *, nng_aio *);
// nng_http_req_reset resets the request to an initially allocated state.
NNG_DECL void nng_http_req_reset(nng_http_req *);
// nng_http_res_reset resets the response to an initially allocated state.
NNG_DECL void nng_http_res_reset(nng_http_res *);
// nng_http_handler is a handler used on the server side to handle HTTP
// requests coming into a specific URL.
typedef struct nng_http_handler nng_http_handler;
// nng_http_handler_alloc creates a server handler object, for the supplied
// absolute URI (path only) with the callback. By default the handler
// is assumed to handle only GET requests (and implictly HEAD requests
// as well.)
//
// Note that methods which modify a handler cannot be called while the handler
// is registered with the server, and that a handler can only be registered
// once per server.
//
// The callback function will receive the following arguments (via
// nng_aio_get_input(): nng_http_request *, nng_http_handler *, and
// nng_http_conn *. The first is a request object, for convenience.
// The second is the handler, from which the callback can obtain any other
// data it has set. The final is the http connection, which can be used
// to hijack the session.
//
// Upon completion, the handler should store an nng_http_res * as the
// first output using nng_aio_set_output. If it does not do so, or supplies
// NULL, then it must send a response itself.
//
// The callback should complete with a result of 0 in most circumstances.
// If it completes with an error, then the connection is terminated, after
// possibly sending a 500 error response to the client.
NNG_DECL int nng_http_handler_alloc(
nng_http_handler **, const char *, void (*)(nng_aio *));
// nng_http_handler_free frees the handler. This actually just drops a
// reference count on the handler, as it may be in use by an existing
// server. The server will also call this when it is destroyed.
NNG_DECL void nng_http_handler_free(nng_http_handler *);
// nng_http_handler_alloc_file creates a "file" based handler, that
// serves up static content from the given file path. The content-type
// supplied is determined from the file name using a simple built-in map.
NNG_DECL int nng_http_handler_alloc_file(
nng_http_handler **, const char *, const char *);
// nng_http_handler_alloc_static creates a static-content handler.
// The last argument is the content-type, which may be NULL (in which case
// "application/octet-stream" is assumed.)
NNG_DECL int nng_http_handler_alloc_static(
nng_http_handler **, const char *, const void *, size_t, const char *);
// nng_http_handler_alloc_redirect creates an HTTP redirect handler.
// The status is given, along with the new URL. If the status is 0,
// then 301 will be used instead.
NNG_DECL int nng_http_handler_alloc_redirect(
nng_http_handler **, const char *, uint16_t, const char *);
// nng_http_handler_alloc_file creates a "directory" based handler, that
// serves up static content from the given directory tree. Directories
// that contain an index.html or index.htm file use that file for the
// directory content, otherwise a suitable error page is returned (the server
// does not generate index pages automatically.) The content-type for
// files is determined from the file name using a simple built-in map.
NNG_DECL int nng_http_handler_alloc_directory(
nng_http_handler **, const char *, const char *);
// nng_http_handler_set_method sets the method that the handler will be
// called for. By default this is GET. If NULL is supplied for the
// method, then the handler is executed regardless of method, and must
// inspect the method itself.
NNG_DECL int nng_http_handler_set_method(nng_http_handler *, const char *);
// nng_http_handler_set_host sets the Host: that the handler will be
// called for (to allow for virtual hosts). If the value is NULL (the
// default, then the Host: header is not considered when matching the
// handler.) Note that the Host: header must match *exactly* (except
// that case is not considered.)
NNG_DECL int nng_http_handler_set_host(nng_http_handler *, const char *);
// nng_http_handler_collect_body is used to indicate the server should
// check for, and process, data sent by the client, which will be attached
// to the request. If this is false, then the handler will need to check
// for and process any content data. By default the server will accept
// up to 1MB. If the client attempts to send more data than requested,
// then a 400 Bad Request will be sent back to the client. To set an
// unlimited value, use (size_t)-1. To preclude the client from sending
// *any* data, use 0. (The static and file handlers use 0 by default.)
NNG_DECL int nng_http_handler_collect_body(nng_http_handler *, bool, size_t);
// nng_http_handler_set_tree indicates that the handler is being registered
// for a hierarchical tree, rather than just a single path, so it will be
// called for all child paths supplied. By default the handler is only
// called for an exact path match.
NNG_DECL int nng_http_handler_set_tree(nng_http_handler *);
// nng_http_handler_set_tree_exclusive indicates that the handler is being
// registered for a heirarchical tree *exclusively*, rather than just a single
// path, so it will be called for all child paths supplied. By default the
// handler is only called for an exact path match. Exclusive means that any
// other handler on a conflicting path will induce an address conflict error
// when added to a server.
NNG_DECL int nng_http_handler_set_tree_exclusive(nng_http_handler *);
// nng_http_handler_set_data is used to store additional data, along with
// a possible clean up routine. (The clean up is a custom de-allocator and
// will be called with the supplied data as an argument, when the handler
// is being de-allocated.)
NNG_DECL int nng_http_handler_set_data(
nng_http_handler *, void *, void (*)(void *));
// nng_http_handler_get_data returns the data that was previously stored.
NNG_DECL void *nng_http_handler_get_data(nng_http_handler *);
// nng_http_server is a handle to an HTTP server instance. Servers
// only serve a single port / address at this time.
typedef struct nng_http_server nng_http_server;
// nng_http_server_hold gets a server structure, using the address determined
// from the URL. If a server already exists, then a hold is placed on it, and
// that instance is returned. If no such server exists, then a new instance
// is created.
NNG_DECL int nng_http_server_hold(nng_http_server **, const nng_url *);
// nng_http_server_release releases the hold on the server. If this is the
// last instance of the server, then it is shutdown and resources are freed.
NNG_DECL void nng_http_server_release(nng_http_server *);
// nng_http_server_start starts the server handling HTTP. Once this is
// called, it will not be possible to change certain parameters (such as
// any TLS configuration).
NNG_DECL int nng_http_server_start(nng_http_server *);
// nng_http_server_stop stops the server. No new client connections are
// accepted after this returns. Once a server is stopped fully, the
// instance will no longer be returned by nng_http_server_hold, as the
// server may not be reused.
NNG_DECL void nng_http_server_stop(nng_http_server *);
// nng_http_server_add_handler registers a handler on the server.
// This function will return NNG_EADDRINUSE if a conflicting handler
// is already registered (i.e. a handler with the same value for Host,
// Method, and URL.)
NNG_DECL int nng_http_server_add_handler(
nng_http_server *, nng_http_handler *);
// nni_http_del_handler removes the given handler. The caller is
// responsible for finalizing it afterwards. If the handler was not found
// (not registered), NNG_ENOENT is returned. In this case it is unsafe
// to make assumptions about the validity of the handler.
NNG_DECL int nng_http_server_del_handler(
nng_http_server *, nng_http_handler *);
// nng_http_server_set_tls adds a TLS configuration to the server,
// and enables the use of it. This returns NNG_EBUSY if the server is
// already started. This wipes out the entire TLS configuration on the
// server client, so the caller must have configured it reasonably.
// This API is not recommended unless the caller needs complete control
// over the TLS configuration.
NNG_DECL int nng_http_server_set_tls(
nng_http_server *, struct nng_tls_config *);
// nng_http_server_get_tls obtains the TLS configuration if one is present,
// or returns NNG_EINVAL. The TLS configuration is invalidated if the
// nng_http_server_set_tls function is called, so be careful.
NNG_DECL int nng_http_server_get_tls(
nng_http_server *, struct nng_tls_config **);
// nng_http_server_get_addr obtains the address with which the server was
// initialized or returns NNG_EINVAL. Useful for instance when the port has
// been automatically assigned.
NNG_DECL int nng_http_server_get_addr(nng_http_server *, nng_sockaddr *);
// nng_http_server_set_error_page sets a custom error page (HTML) content
// to be sent for the given error code. This is used when the error is
// generated internally by the framework, or when the application returns
// the response back to the server via the handler's aio, and the response
// was allocated with nng_http_res_alloc_error. If the response was not
// allocated this way, or the application writes the response itself instead
// of letting the server do so, then this setting will be ignored.
NNG_DECL int nng_http_server_set_error_page(
nng_http_server *, uint16_t, const char *);
// nng_http_server_set_error_file works like nng_http_server_error_page,
// except that the content is loaded from the named file path. The contents
// are loaded at the time this function is called, so this function should be
// called anytime the contents of the named file have changed.
NNG_DECL int nng_http_server_set_error_file(
nng_http_server *, uint16_t, const char *);
// nng_http_server_res_error takes replaces the body of the response with
// a custom error page previously set for the server, using the status
// of the response. The response must have the status set first using
// nng_http_res_set_status or implicitly via nng_http_res_alloc_error.
NNG_DECL int nng_http_server_res_error(nng_http_server *, nng_http_res *);
// nng_http_hijack is intended to be called by a handler that wishes to
// take over the processing of the HTTP session -- usually to change protocols
// (such as in the case of websocket). The caller is responsible for the
// final disposal of the associated nng_http_conn. Also, this completely
// disassociates the http session from the server, so the server may be
// stopped or destroyed without affecting the hijacked session. Note also
// that the hijacker will need to issue any HTTP reply itself. Finally,
// when a session is hijacked, the caller is also responsible for disposing
// of the request structure. (Some hijackers may keep the request for
// further processing.)
NNG_DECL int nng_http_hijack(nng_http_conn *);
// nng_http_client represents a "client" object. Clients can be used
// to create HTTP connections. At present, connections are not cached
// or reused, but that could change in the future.
typedef struct nng_http_client nng_http_client;
// nng_http_client_alloc allocates a client object, associated with
// the given URL.
NNG_DECL int nng_http_client_alloc(nng_http_client **, const nng_url *);
// nng_http_client_free frees the client. Connections created by the
// the client are not necessarily closed.
NNG_DECL void nng_http_client_free(nng_http_client *);
// nng_http_client_set_tls sets the TLS configuration. This wipes out
// the entire TLS configuration on the client, so the caller must have
// configured it reasonably. This API is not recommended unless the
// caller needs complete control over the TLS configuration.
NNG_DECL int nng_http_client_set_tls(
nng_http_client *, struct nng_tls_config *);
// nng_http_client_get_tls obtains the TLS configuration if one is present,
// or returns NNG_EINVAL. The supplied TLS configuration object may
// be invalidated by any future calls to nni_http_client_set_tls.
NNG_DECL int nng_http_client_get_tls(
nng_http_client *, struct nng_tls_config **);
// nng_http_client_connect establishes a new connection with the server
// named in the URL used when the client was created. Once the connection
// is established, the associated nng_http_conn object pointer is returned
// in the first (index 0) output for the aio.
NNG_DECL void nng_http_client_connect(nng_http_client *, nng_aio *);
// nng_http_conn_transact is used to perform a round-trip exchange (i.e. a
// single HTTP transaction). It will not automatically close the connection,
// unless some kind of significant error occurs. The caller should close
// the connection if the aio does not complete successfully.
NNG_DECL void nng_http_conn_transact(
nng_http_conn *, nng_http_req *, nng_http_res *, nng_aio *);
// nng_http_client_transact is used to execute a single transaction to a
// server. The connection is opened, and will be closed when the transaction is
// complete.
NNG_DECL void nng_http_client_transact(
nng_http_client *, nng_http_req *, nng_http_res *, nng_aio *);
#ifdef __cplusplus
}
#endif
#endif // NNG_H

View File

@ -0,0 +1,80 @@
#ifndef NANOLIB_ACL_CONF_H
#define NANOLIB_ACL_CONF_H
#include <string.h>
#include "nng/nng.h"
#include "nng/supplemental/nanolib/cJSON.h"
typedef enum {
ACL_ALLOW,
ACL_DENY,
} acl_permit;
typedef enum {
ACL_USERNAME,
ACL_CLIENTID,
ACL_IPADDR,
ACL_AND,
ACL_OR,
ACL_NONE,
} acl_rule_type;
typedef enum {
ACL_PUB,
ACL_SUB,
ACL_ALL,
} acl_action_type;
typedef enum {
ACL_RULE_SINGLE_STRING,
ACL_RULE_STRING_ARRAY,
ACL_RULE_INT_ARRAY,
ACL_RULE_ALL,
} acl_value_type;
typedef struct acl_rule_ct {
acl_value_type type;
size_t count;
union {
char * str;
char **str_array;
int * int_array;
} value;
} acl_rule_ct;
typedef struct {
acl_rule_type rule_type;
acl_rule_ct rule_ct;
} acl_sub_rule;
typedef struct {
size_t count;
acl_sub_rule **rules;
} acl_sub_rules_array;
typedef struct acl_rule {
size_t id;
acl_permit permit;
acl_rule_type rule_type;
union {
acl_rule_ct ct;
acl_sub_rules_array array;
} rule_ct;
acl_action_type action;
size_t topic_count;
char ** topics;
} acl_rule;
typedef struct {
bool enable;
size_t rule_count;
acl_rule **rules;
} conf_acl;
extern void conf_acl_parse(conf_acl *acl, const char *path);
extern void conf_acl_init(conf_acl *acl);
extern void conf_acl_destroy(conf_acl *acl);
extern bool acl_parse_json_rule(cJSON *obj, size_t id, acl_rule **rule);
extern void print_acl_conf(conf_acl *acl);
#endif /* NANOLIB_ACL_CONF_H */

View File

@ -0,0 +1,21 @@
#ifndef BASE64_H
#define BASE64_H
#include "nng/nng.h"
#define BASE64_ENCODE_OUT_SIZE(s) ((unsigned int)((((s) + 2) / 3) * 4 + 1))
#define BASE64_DECODE_OUT_SIZE(s) ((unsigned int)(((s) / 4) * 3))
/*
* out is null-terminated encode string.
* return values is out length, exclusive terminating `\0'
*/
NNG_DECL unsigned int
base64_encode(const unsigned char *in, unsigned int inlen, char *out);
/*
* return values is out length
*/
NNG_DECL unsigned int
base64_decode(const char *in, unsigned int inlen, unsigned char *out);
#endif /* BASE64_H */

View File

@ -0,0 +1,116 @@
# ifndef BINARY_SEARCH_H
# define BINARY_SEARCH_H
#include "cvector.h"
#include <stdint.h>
#include <stdbool.h>
/**
* @brief binary_search - vec is an dynamic array
* @param l - it is the left boundry of the vec
* @param index - index is the result we search
* @param e - e contain message we want to search
* @param cmp - cmp is a compare method
* @return true or false, if we find or not
*/
static inline bool
_binary_search(
void **vec, int l, size_t *index, void *e, int (*cmp)(void *x, void *y))
{
int r = cvector_size(vec) - 1;
int m = 0;
// if we do not find the element
// vec = [0, 1, 3, 4], e = 2 ,
// m will be 2, index = 2 ok
// vec = [0, 1, 2, 4], e = 3 ,
// m will be 2, index = 2 error,
// index = 2 + add(1) ok
int add = 0;
// log_info("l: %d", l);
// log_info("r: %d", r);
while ( l <= r) {
m = l + (r - l) / 2;
// Check if x is present at mid
if (cmp(vec[m], e) == 0) {
*index = m;
return true;
}
// log_info("m: %d", m);
// If x greater, ignore left half
if (cmp(vec[m], e) < 0) {
l = m + 1;
add = 1;
// If x is smaller, ignore right half
} else {
r = m - 1;
add = 0;
}
}
// log_info("m: %d", m);
// if we reach here, then element was
// not present
*index = m + add;
return false;
}
static inline bool
_binary_search_uint32(uint32_t *vec, int l, size_t *index, uint32_t e,
int (*cmp)(uint32_t x, uint32_t y))
{
int r = cvector_size(vec) - 1;
int m = 0;
// if we do not find the element
// vec = [0, 1, 3, 4], e = 2 ,
// m will be 2, index = 2 ok
// vec = [0, 1, 2, 4], e = 3 ,
// m will be 2, index = 2 error,
// index = 2 + add(1) ok
int add = 0;
// log_info("l: %d", l);
// log_info("r: %d", r);
while ( l <= r) {
m = l + (r - l) / 2;
// Check if x is present at mid
if (cmp(vec[m], e) == 0) {
*index = m;
return true;
}
// log_info("m: %d", m);
// If x greater, ignore left half
if (cmp(vec[m], e) < 0) {
l = m + 1;
add = 1;
// If x is smaller, ignore right half
} else {
r = m - 1;
add = 0;
}
}
// log_info("m: %d", m);
// if we reach here, then element was
// not present
*index = m + add;
return false;
}
#define binary_search(vec, l, index, e, cmp) \
_binary_search(vec, l, index, e, cmp)
#define binary_search_uint32(vec, l, index, e, cmp) \
_binary_search_uint32(vec, l, index, e, cmp)
#endif

View File

@ -0,0 +1,62 @@
#ifndef BLF_H
#define BLF_H
#include "nng/nng.h"
#include "nng/supplemental/nanolib/conf.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct blf_object blf_object;
typedef void (*blf_cb)(blf_object *arg);
typedef enum {
WRITE_TO_NORMAL1,
WRITE_TO_TEMP1,
} blf_write_type;
typedef struct {
uint32_t start_idx;
uint32_t end_idx;
char *filename;
} blf_file_range;
typedef struct {
blf_file_range **range;
int size;
int start; // file range start index
} blf_file_ranges;
typedef struct {
uint8_t *data;
uint32_t size;
} blf_data_packet;
struct blf_object {
uint64_t *keys;
uint8_t **darray;
uint32_t *dsize;
uint32_t size;
nng_aio *aio;
void *arg;
blf_file_ranges *ranges;
blf_write_type type;
};
blf_object *blf_object_alloc(uint64_t *keys, uint8_t **darray, uint32_t *dsize,
uint32_t size, nng_aio *aio, void *arg);
void blf_object_free(blf_object *elem);
int blf_write_batch_async(blf_object *elem);
int blf_write_launcher(conf_blf *conf);
const char *blf_find(uint64_t key);
const char **blf_find_span(
uint64_t start_key, uint64_t end_key, uint32_t *size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,294 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 15
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,37 @@
//
// Copyright 2020 NanoMQ Team, Inc. <jaylin@emqx.io>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#include <sys/types.h>
#define CMD_BUFF_LEN 1024
extern char *cmd_output_buff;
extern int cmd_output_len;
#ifndef NNG_PLATFORM_WINDOWS
#define CMD_RUN(cmd) \
do { \
ret = cmd_run(cmd); \
if (ret < 0) \
goto err; \
} while (0)
#define CMD_FRUN(fcmd, ...) \
do { \
ret = nano_cmd_frun(fcmd, __VA_ARGS__); \
if (ret < 0) \
goto err; \
} while (0)
extern int nano_cmd_run(const char *cmd);
extern int nano_cmd_run_status(const char *cmd);
extern int nano_cmd_frun(const char *format, ...);
#endif
extern void nano_cmd_cleanup(void);

View File

@ -0,0 +1,691 @@
#ifndef CONF_H
#define CONF_H
#include <ctype.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nng/nng.h"
#include "rule.h"
#include "acl_conf.h"
#include "log.h"
#include "ringbuffer.h"
#include "nng/supplemental/util/platform.h"
#define PID_PATH_NAME "/tmp/nanomq/nanomq.pid"
#define CONF_PATH_NAME "/etc/nanomq.conf"
#define CONF_ZMQ_GATEWAY_PATH_NAME "/etc/nanomq_zmq_gateway.conf"
#define CONF_VSOMEIP_GATEWAY_PATH_NAME "/etc/nanomq_vsomeip_gateway.conf"
#define CONF_DDS_GATEWAY_PATH_NAME "/etc/nanomq_dds_gateway.conf"
#define CONF_TCP_URL_DEFAULT "nmq-tcp://0.0.0.0:1883"
#define CONF_TLS_URL_DEFAULT "tls+nmq-tcp://0.0.0.0:8883"
#define CONF_WS_URL_DEFAULT "nmq-ws://0.0.0.0:8083/mqtt"
#define CONF_WSS_URL_DEFAULT "nmq-wss://0.0.0.0:8086/mqtt"
#define BROKER_NMQ_TCP_URL_PREFIX "nmq-tcp"
#define BROKER_NMQ_TCP_TLS_URL_PREFIX "tls+nmq-tcp"
#define BROKER_NMQ_WS_URL_PREFIX "nmq-ws"
#define BROKER_NMQ_WSS_URL_PREFIX "nmq-wss"
#define BROKER_TCP_URL_PREFIX "broker+tcp"
#define BROKER_WS_URL_PREFIX "nmq+ws"
#define BROKER_WSS_URL_PREFIX "nmq+wss"
#define RULE_ENG_OFF 0
#define RULE_ENG_SDB 1
#define RULE_ENG_FDB (1 << 1)
#define RULE_ENG_MDB (1 << 2)
#define RULE_ENG_RPB (1 << 3)
#define FREE_NONULL(p) \
if (p) { \
free(p); \
p = NULL; \
}
struct conf_auth {
bool enable;
size_t count;
char **usernames;
char **passwords;
};
typedef struct conf_auth conf_auth;
struct conf_tls {
bool enable;
char *url; // "tls+nmq-tcp://addr:port"
char *cafile;
char *certfile;
char *keyfile;
char *ca;
char *cert;
char *key;
char *key_password;
bool verify_peer;
bool set_fail; // fail_if_no_peer_cert
};
typedef struct conf_tls conf_tls;
// TODO: params for one single tcp node should be in here.
typedef struct {
bool enable;
char *url;
uint8_t nodelay;
uint8_t keepalive;
uint8_t quickack;
uint16_t keepidle;
uint16_t keepintvl;
uint16_t keepcnt;
uint16_t sendtimeo;
uint16_t recvtimeo;
} conf_tcp;
typedef struct {
size_t count;
conf_tls **nodes;
} conf_tls_list;
typedef struct {
size_t count;
conf_tcp **nodes;
} conf_tcp_list;
struct conf_sqlite {
bool enable;
size_t disk_cache_size; // specify the max rows of sqlite table
char * mounted_file_path; // specify the db file path
size_t
flush_mem_threshold; // flush to sqlite table when count of message
// is equal or greater than this value
uint64_t resend_interval; // resend caching message interval (ms)
};
typedef struct conf_sqlite conf_sqlite;
struct conf_http_header {
char *key;
char *value;
};
typedef struct conf_http_header conf_http_header;
typedef enum {
ACCESS,
USERNAME,
CLIENTID,
IPADDRESS,
PROTOCOL,
PASSWORD,
SOCKPORT, // sockport of server accepted
COMMON_NAME, // common name of client TLS cert
SUBJECT, // subject of client TLS cert
TOPIC,
MOUNTPOINT,
} http_param_type;
struct conf_http_param {
char * name;
http_param_type type;
};
typedef struct conf_http_param conf_http_param;
struct conf_auth_http_req {
char *url;
char *method;
size_t header_count;
conf_http_header **headers;
size_t param_count;
conf_http_param **params;
// TODO not support yet
conf_tls tls;
};
typedef struct conf_auth_http_req conf_auth_http_req;
struct conf_auth_http {
bool enable;
conf_auth_http_req auth_req;
conf_auth_http_req super_req;
conf_auth_http_req acl_req;
uint64_t timeout; // seconds
uint64_t connect_timeout; // seconds
size_t pool_size;
};
typedef struct conf_auth_http conf_auth_http;
struct conf_jwt {
char *iss;
char *public_keyfile;
char *private_keyfile;
char *public_key;
char *private_key;
size_t public_key_len;
size_t private_key_len;
};
typedef struct conf_jwt conf_jwt;
typedef enum {
BASIC,
JWT,
NONE_AUTH,
} auth_type_t;
struct conf_http_server {
bool enable;
uint16_t port;
char *username;
char *password;
size_t parallel;
auth_type_t auth_type;
conf_jwt jwt;
nng_socket *broker_sock;
};
typedef struct conf_http_server conf_http_server;
struct conf_websocket {
bool enable;
char *url; // "nmq-ws://addr:port/path"
char *tls_url; // "nmq-wss://addr:port/path"
};
typedef struct conf_websocket conf_websocket;
#define NO_RETAIN 2 // default retain flag value, none 0, 1
#define NO_QOS 3 // default QoS level value for forwarding bridge msg, 3 = keep old qos
typedef struct {
char *remote_topic;
uint32_t remote_topic_len;
char *local_topic;
uint32_t local_topic_len;
char *prefix;
uint32_t prefix_len;
char *suffix;
uint32_t suffix_len;
uint8_t nolocal;
uint8_t retain; // override for retain
uint8_t qos; // override for QoS
uint8_t retain_as_published;
uint8_t retain_handling;
uint32_t stream_id; // only effective when multi_stream is enabled
} topics;
typedef struct {
char *key;
char *value;
}conf_user_property;
typedef struct {
uint32_t session_expiry_interval;
uint8_t request_problem_info;
uint8_t request_response_info;
uint16_t receive_maximum;
uint16_t topic_alias_maximum;
uint32_t maximum_packet_size;
size_t user_property_size;
conf_user_property **user_property;
} conf_bridge_conn_properties;
typedef struct {
uint8_t payload_format_indicator;
uint32_t message_expiry_interval;
char * content_type;
char * response_topic;
char * correlation_data;
uint32_t will_delay_interval;
size_t user_property_size;
conf_user_property **user_property;
} conf_bridge_conn_will_properties;
typedef struct {
uint32_t identifier;
size_t user_property_size;
conf_user_property **user_property;
} conf_bridge_sub_properties;
struct conf_bridge_node {
bool enable;
bool dynamic;
bool clean_start;
bool transparent;
bool will_flag;
bool will_retain;
void *sock;
void *bridge_arg; // for reloading bridge case
char *name;
char *address;
char *host;
char *clientid;
char *username;
char *password;
char *will_payload;
char *will_topic;
uint8_t proto_ver;
uint8_t will_qos;
uint16_t port;
uint16_t keepalive;
uint16_t backoff_max;
uint64_t cancel_timeout;
uint64_t resend_interval; // resend caching message interval (ms)
uint64_t resend_wait;
size_t sub_count;
size_t forwards_count;
size_t max_recv_queue_len;
size_t max_send_queue_len;
topics **forwards_list;
uint64_t parallel;
topics **sub_list;
conf_tls tls;
conf_tcp tcp;
conf_sqlite *sqlite;
nng_aio **bridge_aio;
nng_mtx *mtx;
bool hybrid; // enable/disable hybrid bridging
char **hybrid_servers;
// MQTT v5 property
conf_bridge_conn_properties * conn_properties;
conf_bridge_conn_will_properties *will_properties;
conf_bridge_sub_properties * sub_properties;
#if defined(SUPP_QUIC)
// config params for QUIC only
bool multi_stream;
bool stream_auto_genid; // generate stream id automatically for each stream
bool qos_first; // send QoS msg in high priority
uint64_t qkeepalive; //keepalive timeout interval of QUIC transport
uint64_t qconnect_timeout; // HandshakeIdleTimeoutMs of QUIC
uint32_t qdiscon_timeout; // DisconnectTimeoutMs
uint32_t qidle_timeout; // Disconnect after idle
uint32_t qsend_idle_timeout; // SendIdleTimeoutMs
uint32_t qinitial_rtt_ms; // Initial RTT estimate.
uint32_t qmax_ack_delay_ms; // MaxAckDelayMs How long to wait after receiving data before sending an ACK.
uint8_t qcongestion_control; // congestion control algorithm 1: bbr 0: cubic
bool quic_0rtt; // 0RTT.
#endif
};
typedef struct conf_bridge_node conf_bridge_node;
typedef struct ringBuffer_node ringBuffer_node;
struct ringBuffer_node {
char *name;
uint32_t fullOp;
uint64_t cap;
};
typedef struct conf_exchange_node conf_exchange_node;
struct conf_exchange_node {
char *name;
char *topic;
ringBuffer_node **rbufs;
size_t rbufs_sz;
nng_socket *sock;
nng_mtx *mtx;
char *exchange_url;
};
typedef struct conf_exchange_encryption conf_exchange_encryption;
struct conf_exchange_encryption {
bool enable;
char *key;
};
typedef struct conf_exchange conf_exchange;
struct conf_exchange {
size_t count;
conf_exchange_node **nodes;
conf_exchange_encryption *encryption;
};
#if defined(SUPP_PLUGIN)
typedef struct conf_plugin_lib conf_plugin_lib;
struct conf_plugin_lib {
char *path;
};
typedef struct conf_plugin conf_plugin;
struct conf_plugin {
struct conf_plugin_lib **libs;
size_t path_sz;
};
#endif
typedef enum {
UNCOMPRESSED,
SNAPPY,
GZIP,
BROTLI,
ZSTD,
LZ4
} compression_type;
typedef enum { AES_GCM_V1 = 0, AES_GCM_CTR_V1 = 1 } cipher_type;
struct conf_parquet_encryption {
bool enable;
char *key_id;
char *key;
cipher_type type;
};
typedef struct conf_parquet_encryption conf_parquet_encryption;
struct conf_parquet {
bool enable;
char *dir;
char *file_name_prefix;
uint8_t file_count;
uint32_t limit_frequency;
uint8_t file_index;
int32_t file_size;
compression_type comp_type;
conf_parquet_encryption encryption;
};
typedef struct conf_parquet conf_parquet;
struct conf_blf {
bool enable;
char *dir;
char *file_name_prefix;
uint8_t file_count;
uint8_t file_index;
int32_t file_size;
compression_type comp_type;
};
typedef struct conf_blf conf_blf;
struct conf_bridge {
size_t count;
conf_bridge_node **nodes;
conf_sqlite sqlite;
};
typedef struct conf_bridge conf_bridge;
typedef struct {
char *zmq_sub_url;
char *zmq_pub_url;
char *mqtt_url;
char *sub_topic;
char *pub_topic;
char *zmq_sub_pre;
char *zmq_pub_pre;
char *path;
char *username;
char *password;
void *zmq_sender;
int proto_ver;
int keepalive;
bool clean_start;
int parallel;
enum { PUB_SUB, REQ_REP } type;
conf_http_server http_server;
} zmq_gateway_conf;
typedef struct {
nng_socket *sock;
char *mqtt_url;
char *sub_topic;
char *pub_topic;
char *username;
char *password;
char *clientid;
char *path;
int proto_ver;
int keepalive;
bool clean_start;
uint8_t sub_qos;
int parallel;
conf_http_server http_server;
// vsomeip parameter
uint16_t service_id;
uint16_t service_instance_id;
uint16_t service_method_id;
uint16_t service_event_id;
uint16_t service_eventgroup_id;
char *conf_path;
} vsomeip_gateway_conf;
typedef struct {
char *from;
char *to;
char *struct_name;
} dds_gateway_topic;
typedef struct {
dds_gateway_topic **dds2mqtt;
size_t dds2mqtt_sz;
dds_gateway_topic **mqtt2dds;
size_t mqtt2dds_sz;
} dds_gateway_forward;
typedef struct {
nng_socket *sock;
bool clean_start;
uint8_t proto_ver;
uint16_t port;
uint16_t keepalive;
char * address;
char * clientid;
char * username;
char * password;
conf_tls tls;
} dds_gateway_mqtt;
typedef struct {
char * idl_type;
size_t domain_id;
char * subscriber_partition;
char * publisher_partition;
bool shm_mode;
char * shm_log_level;
} dds_gateway_dds;
typedef struct {
char * path;
dds_gateway_mqtt mqtt;
dds_gateway_dds dds;
dds_gateway_forward forward;
conf_http_server http_server;
} dds_gateway_conf;
typedef enum {
CLIENT_CONNECT,
CLIENT_CONNACK,
CLIENT_CONNECTED,
CLIENT_DISCONNECTED,
CLIENT_SUBSCRIBE,
CLIENT_UNSUBSCRIBE,
SESSION_SUBSCRIBED,
SESSION_UNSUBSCRIBED,
SESSION_TERMINATED,
MESSAGE_PUBLISH,
MESSAGE_DELIVERED,
MESSAGE_ACKED,
UNKNOWN_EVENT,
} webhook_event;
typedef enum {
plain,
base64,
base62
} hook_payload_type;
struct conf_web_hook_rule {
uint16_t rule_num;
webhook_event event;
char * action;
char * topic;
};
typedef struct conf_web_hook_rule conf_web_hook_rule;
struct conf_web_hook {
bool enable;
char * url;
size_t pool_size;
hook_payload_type encode_payload;
size_t header_count;
conf_http_header **headers;
uint16_t rule_count;
conf_web_hook_rule **rules;
nng_mtx *ex_mtx; // mutex for saios
nng_aio *ex_aio; // Await flush
nng_aio **saios; // Aios for sending message
// TODO not support yet
conf_tls tls;
};
typedef struct conf_web_hook conf_web_hook;
typedef enum {
memory,
sqlite,
} persistence_type;
struct conf {
char *vin;
char *cmd_ipc_url;
char *hook_ipc_url;
char *conf_file;
char *url;
bool enable;
int property_size;
int msq_len;
uint32_t num_taskq_thread;
uint32_t max_taskq_thread;
uint32_t parallel; // broker ctx
uint64_t total_ctx; // Total ctx of work (bridge + AWS + broker + HTTP)
uint64_t max_packet_size; // byte
uint32_t client_max_packet_size; // byte
uint32_t max_inflight_window;
uint32_t max_awaiting_rel;
uint32_t await_rel_timeout;
uint32_t qos_duration;
float backoff;
void *db_root;
bool allow_anonymous;
bool daemon;
bool ipc_internal;
bool bridge_mode;
conf_tcp_list tcp_list;
conf_tls_list tls_list;
conf_sqlite sqlite;
conf_tls tls;
conf_http_server http_server;
conf_websocket websocket;
conf_bridge bridge; //standard MQTT
conf_bridge aws_bridge; // AWS IoT Core
conf_exchange exchange;
conf_parquet parquet;
conf_blf blf;
#if defined(SUPP_PLUGIN)
conf_plugin plugin;
#endif
conf_web_hook web_hook;
#if defined(ENABLE_LOG)
conf_log log;
#endif
#if defined(SUPP_RULE_ENGINE)
conf_rule rule_eng;
#endif
#ifdef ACL_SUPP
conf_acl acl;
acl_permit acl_nomatch;
bool enable_acl_cache;
size_t acl_cache_max_size;
size_t acl_cache_ttl;
enum { ACL_IGNORE, ACL_DISCONNECT } acl_deny_action;
#endif
conf_auth auths;
conf_auth_http auth_http;
struct hashmap_s *cid_table;
};
typedef struct conf conf;
webhook_event get_webhook_event(const char *hook_type, const char *hook_name);
NNG_DECL int get_size(const char *str, uint64_t *size);
NNG_DECL int get_time(const char *str, uint64_t *second);
NNG_DECL void conf_parse(conf *nanomq_conf);
NNG_DECL void conf_parse_ver2(conf *nanomq_conf);
NNG_DECL void conf_gateway_parse_ver2(zmq_gateway_conf *gateway);
NNG_DECL void conf_vsomeip_gateway_parse_ver2(vsomeip_gateway_conf *config);
NNG_DECL void conf_dds_gateway_init(dds_gateway_conf *config);
NNG_DECL void conf_dds_gateway_parse_ver2(dds_gateway_conf *config);
NNG_DECL void conf_dds_gateway_destory(dds_gateway_conf *config);
NNG_DECL void conf_init(conf *nanomq_conf);
NNG_DECL void print_conf(conf *nanomq_conf);
NNG_DECL void conf_set_threads(conf *nanomq_conf);
NNG_DECL void conf_fini(conf *nanomq_conf);
NNG_DECL void conf_update(const char *fpath, const char *key, char *value);
NNG_DECL void conf_update2(const char *fpath, const char *key1,
const char *key2, const char *key3, char *value);
NNG_DECL void
conf_bridge_node_parse(
conf_bridge_node *node, conf_sqlite *bridge_sqlite, cJSON *obj);
NNG_DECL void conf_bridge_node_destroy(conf_bridge_node *node);
NNG_DECL void conf_update_var(
const char *fpath, const char *key, uint8_t type, void *var);
NNG_DECL void conf_update_var2(const char *fpath, const char *key1,
const char *key2, const char *key3, uint8_t type, void *var);
NNG_DECL const char* conf_get_vin(void);
NNG_DECL void conf_free_vin();
#define conf_update_int(path, key, var) \
conf_update_var(path, key, 0, (void *) &(var))
#define conf_update_u8(path, key, var) \
conf_update_var(path, key, 1, (void *) &(var))
#define conf_update_u16(path, key, var) \
conf_update_var(path, key, 2, (void *) &(var))
#define conf_update_u32(path, key, var) \
conf_update_var(path, key, 3, (void *) &(var))
#define conf_update_u64(path, key, var) \
conf_update_var(path, key, 4, (void *) &(var))
#define conf_update_long(path, key, var) \
conf_update_var(path, key, 5, (void *) &(var))
#define conf_update_double(path, key, var) \
conf_update_var(path, key, 6, (void *) &(var))
#define conf_update_bool(path, key, var) \
conf_update_var(path, key, 7, (void *) &(var))
#define conf_update2_int(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 0, (void *) &(var))
#define conf_update2_u8(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 1, (void *) &(var))
#define conf_update2_u16(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 2, (void *) &(var))
#define conf_update2_u32(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 3, (void *) &(var))
#define conf_update2_u64(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 4, (void *) &(var))
#define conf_update2_long(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 5, (void *) &(var))
#define conf_update2_double(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 6, (void *) &(var))
#define conf_update2_bool(path, key1, key2, key3, var) \
conf_update_var2(path, key1, key2, key3, 7, (void *) &(var))
#endif

View File

@ -0,0 +1,228 @@
#ifndef CVECTOR_H_
#define CVECTOR_H_
#include <assert.h> /* for assert */
#include <stdlib.h> /* for malloc/realloc/free */
/**
* @brief cvector_vector_type - The vector type used in this library
*/
#define cvector(type) type *
/**
* @brief cvector_set_capacity - For internal use, sets the capacity variable
* of the vector
* @param vec - the vector
* @param size - the new capacity to set
* @return void
*/
#define cvector_set_capacity(vec, size) \
do { \
if (vec) { \
((size_t *) (vec))[-1] = (size); \
} \
} while (0)
/**
* @brief cvector_set_size - For internal use, sets the size variable of the
* vector
* @param vec - the vector
* @param size - the new capacity to set
* @return void
*/
#define cvector_set_size(vec, size) \
do { \
if (vec) { \
((size_t *) (vec))[-2] = (size); \
} \
} while (0)
/**
* @brief cvector_capacity - gets the current capacity of the vector
* @param vec - the vector
* @return the capacity as a size_t
*/
#define cvector_capacity(vec) ((vec) ? ((size_t *) (vec))[-1] : (size_t) 0)
/**
* @brief cvector_size - gets the current size of the vector
* @param vec - the vector
* @return the size as a size_t
*/
#define cvector_size(vec) ((vec) ? ((size_t *) (vec))[-2] : (size_t) 0)
/**
* @brief cvector_empty - returns non-zero if the vector is empty
* @param vec - the vector
* @return non-zero if empty, zero if non-empty
*/
#define cvector_empty(vec) (cvector_size(vec) == 0)
/**
* @brief cvector_grow - For internal use, ensures that the vector is at least
* <count> elements big
* @param vec - the vector
* @param count - the new capacity to set
* @return void
*/
#define cvector_grow(vec, count) \
do { \
const size_t cv_sz = \
(count) * sizeof(*(vec)) + (sizeof(size_t) * 2); \
if (!(vec)) { \
size_t *cv_p = malloc(cv_sz); \
assert(cv_p); \
(vec) = (void *) (&cv_p[2]); \
cvector_set_capacity((vec), (count)); \
cvector_set_size((vec), 0); \
} else { \
size_t *cv_p1 = &((size_t *) (vec))[-2]; \
size_t *cv_p2 = realloc(cv_p1, (cv_sz)); \
assert(cv_p2); \
(vec) = (void *) (&cv_p2[2]); \
cvector_set_capacity((vec), (count)); \
} \
} while (0)
/**
* @brief cvector_pop_back - removes the last element from the vector
* @param vec - the vector
* @return void
*/
#define cvector_pop_back(vec) \
do { \
cvector_set_size((vec), cvector_size(vec) - 1); \
} while (0)
/**
* @brief cvector_erase - removes the element at index i from the vector
* @param vec - the vector
* @param i - index of element to remove
* @return void
*/
#define cvector_erase(vec, i) \
do { \
if (vec) { \
const size_t cv_sz = cvector_size(vec); \
if ((i) < cv_sz) { \
cvector_set_size((vec), cv_sz - 1); \
size_t cv_x; \
for (cv_x = (i); cv_x < (cv_sz - 1); \
++cv_x) { \
(vec)[cv_x] = (vec)[cv_x + 1]; \
} \
} \
} \
} while (0)
/**
* @brief cvector_free - frees all memory associated with the vector
* @param vec - the vector
* @return void
*/
#define cvector_free(vec) \
do { \
if (vec) { \
size_t *p1 = &((size_t *) (vec))[-2]; \
free(p1); \
} \
} while (0)
/**
* @brief cvector_begin - returns an iterator to first element of the vector
* @param vec - the vector
* @return a pointer to the first element (or NULL)
*/
#define cvector_begin(vec) (vec)
/**
* @brief cvector_end - returns an iterator to one past the last element of the
* vector
* @param vec - the vector
* @return a pointer to one past the last element (or NULL)
*/
#define cvector_end(vec) ((vec) ? &((vec)[cvector_size(vec)]) : NULL)
/* user request to use logarithmic growth algorithm */
#ifdef CVECTOR_LOGARITHMIC_GROWTH
/**
* @brief cvector_push_back - adds an element to the end of the vector
* @param vec - the vector
* @param value - the value to add
* @return void
*/
#define cvector_push_back(vec, value) \
do { \
size_t cv_cap = cvector_capacity(vec); \
if (cv_cap <= cvector_size(vec)) { \
cvector_grow( \
(vec), !cv_cap ? cv_cap + 1 : cv_cap * 2); \
} \
vec[cvector_size(vec)] = (value); \
cvector_set_size((vec), cvector_size(vec) + 1); \
} while (0)
#else
/**
* @brief cvector_push_back - adds an element to the end of the vector
* @param vec - the vector
* @param value - the value to add
* @return void
*/
#define cvector_push_back(vec, value) \
do { \
size_t cv_cap = cvector_capacity(vec); \
if (cv_cap <= cvector_size(vec)) { \
cvector_grow((vec), cv_cap + 1); \
} \
vec[cvector_size(vec)] = (value); \
cvector_set_size((vec), cvector_size(vec) + 1); \
} while (0)
#endif /* CVECTOR_LOGARITHMIC_GROWTH */
/**
* @brief cvector_copy - copy a vector
* @param from - the original vector
* @param to - destination to which the function copy to
* @return void
*/
#define cvector_copy(from, to) \
do { \
for (size_t i = 0; i < cvector_size(from); i++) { \
cvector_push_back(to, from[i]); \
} \
} while (0)
#endif /* CVECTOR_H_ */
/**
* @brief cvector_insert - insert the element at index i to the vector
* @param vec - the vector
* @param i - index of element to insert
* @param value - value to insert
* @return void
*/
#define cvector_insert(vec, i, value) \
do { \
if (cvector_empty(vec)) { \
cvector_push_back(vec, value); \
} else { \
size_t cv_cap = cvector_capacity(vec); \
if (cv_cap <= cvector_size(vec)) { \
cvector_grow((vec), \
!cv_cap ? cv_cap + 1 : cv_cap * 2); \
} \
const size_t cv_sz = cvector_size(vec); \
if ((i) < cv_sz) { \
cvector_set_size((vec), cv_sz + 1); \
size_t cv_x; \
for (cv_x = (cv_sz); cv_x > (i); cv_x--) { \
(vec)[cv_x] = (vec)[cv_x - 1]; \
} \
vec[i] = (value); \
} \
} \
} while (0)

View File

@ -0,0 +1,63 @@
#ifndef NANOLIB_ENV_H
#define NANOLIB_ENV_H
#include "conf.h"
#include "nng/nng.h"
#define NANOMQ_BROKER_URL "NANOMQ_BROKER_URL"
#define NANOMQ_EXCHANGER_URL "NANOMQ_EXCHANGER_URL"
#define NANOMQ_DAEMON "NANOMQ_DAEMON"
#define NANOMQ_TCP_ENABLE "NANOMQ_TCP_ENABLE"
#define NANOMQ_NUM_TASKQ_THREAD "NANOMQ_MAX_TASKQ_THREAD"
#define NANOMQ_MAX_TASKQ_THREAD "NANOMQ_MAX_TASKQ_THREAD"
#define NANOMQ_PARALLEL "NANOMQ_PARALLEL"
#define NANOMQ_PROPERTY_SIZE "NANOMQ_PROPERTY_SIZE"
#define NANOMQ_MAX_PACKET_SIZE "NANOMQ_MAX_PACKET_SIZE"
#define NANOMQ_CLIENT_MAX_PACKET_SIZE "NANOMQ_CLIENT_MAX_PACKET_SIZE"
#define NANOMQ_MSQ_LEN "NANOMQ_MSQ_LEN"
#define NANOMQ_QOS_DURATION "NANOMQ_QOS_DURATION"
#define NANOMQ_ALLOW_ANONYMOUS "NANOMQ_ALLOW_ANONYMOUS"
#define NANOMQ_MSG_PERSISTENCE "NANOMQ_MSG_PERSISTENCE"
#define NANOMQ_WEBSOCKET_ENABLE "NANOMQ_WEBSOCKET_ENABLE"
#define NANOMQ_WEBSOCKET_URL "NANOMQ_WEBSOCKET_URL"
#define NANOMQ_WEBSOCKET_TLS_URL "NANOMQ_WEBSOCKET_TLS_URL"
#define NANOMQ_HTTP_SERVER_ENABLE "NANOMQ_HTTP_SERVER_ENABLE"
#define NANOMQ_HTTP_SERVER_PORT "NANOMQ_HTTP_SERVER_PORT"
#define NANOMQ_HTTP_SERVER_PARALLEL "NANOMQ_HTTP_SERVER_PARALLEL"
#define NANOMQ_HTTP_SERVER_USERNAME "NANOMQ_HTTP_SERVER_USERNAME"
#define NANOMQ_HTTP_SERVER_PASSWORD "NANOMQ_HTTP_SERVER_PASSWORD"
#define NANOMQ_HTTP_SERVER_AUTH_TYPE "NANOMQ_HTTP_SERVER_AUTH_TYPE"
#define NANOMQ_HTTP_SERVER_JWT_PUBLIC_KEYFILE \
"NANOMQ_HTTP_SERVER_JWT_PUBLIC_KEYFILE"
#define NANOMQ_HTTP_SERVER_JWT_PRIVATE_KEYFILE \
"NANOMQ_HTTP_SERVER_JWT_PRIVATE_KEYFILE"
#define NANOMQ_TLS_ENABLE "NANOMQ_TLS_ENABLE"
#define NANOMQ_TLS_URL "NANOMQ_TLS_URL"
#define NANOMQ_TLS_CA_CERT_PATH "NANOMQ_TLS_CA_CERT_PATH"
#define NANOMQ_TLS_CERT_PATH "NANOMQ_TLS_CERT_PATH"
#define NANOMQ_TLS_KEY_PATH "NANOMQ_TLS_KEY_PATH"
#define NANOMQ_TLS_KEY_PASSWORD "NANOMQ_TLS_KEY_PASSWORD"
#define NANOMQ_TLS_VERIFY_PEER "NANOMQ_TLS_VERIFY_PEER"
#define NANOMQ_TLS_FAIL_IF_NO_PEER_CERT "NANOMQ_TLS_FAIL_IF_NO_PEER_CERT"
#define NANOMQ_LOG_LEVEL "NANOMQ_LOG_LEVEL"
#define NANOMQ_LOG_TO "NANOMQ_LOG_TO"
#define NANOMQ_LOG_UDS_ADDR "NANOMQ_LOG_UDS_ADDR"
#define NANOMQ_LOG_DIR "NANOMQ_LOG_DIR"
#define NANOMQ_LOG_FILE "NANOMQ_LOG_FILE"
#define NANOMQ_LOG_ROTATION_SIZE "NANOMQ_LOG_ROTATION_SIZE"
#define NANOMQ_LOG_ROTATION_COUNT "NANOMQ_LOG_ROTATION_COUNT"
#define NANOMQ_CONF_PATH "NANOMQ_CONF_PATH"
#define NANOMQ_VIN "NANOMQ_VIN"
#define NANOMQ_PID_FILE "NANOMQ_PID_FILE"
NNG_DECL void read_env_conf(conf *config);
NNG_DECL char *read_env_vin();
NNG_DECL char *read_env_pid_file();
#endif

View File

@ -0,0 +1,18 @@
#ifndef NANO_FILE_H
#define NANO_FILE_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "nng/nng.h"
NNG_DECL bool nano_file_exists(const char *fpath);
NNG_DECL char * nano_getcwd(char *buf, size_t size);
NNG_DECL int64_t nano_getline(
char **restrict line, size_t *restrict len, FILE *restrict fp);
NNG_DECL char * nano_concat_path(const char *dir, const char *file_name);
NNG_DECL int file_write_string(const char *fpath, const char *string);
NNG_DECL int file_create_dir(const char *fpath);
NNG_DECL size_t file_load_data(const char *filepath, void **data);
#endif

View File

@ -0,0 +1,121 @@
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#include "cvector.h"
#include <stdbool.h>
#include <stdint.h>
#include "nng/nng.h"
#include "nng/mqtt/packet.h"
struct topic_queue {
uint8_t qos;
char *topic;
struct topic_queue *next;
};
typedef struct topic_queue topic_queue;
struct msg_queue {
char * msg;
struct msg_queue *next;
};
typedef struct msg_queue msg_queue;
// atpair is alias topic pair
typedef struct dbhash_atpair_s dbhash_atpair_t;
struct dbhash_atpair_s {
uint32_t alias;
char * topic;
};
typedef struct dbhash_ptpair_s dbhash_ptpair_t;
// ptpair is pipe topic pair
struct dbhash_ptpair_s {
uint32_t pipe;
char * topic;
};
/**
* @brief alias_cmp - A callback to compare different alias
* @param x - normally x is pointer of dbhash_atpair_t
* @param y - normally y is pointer of alias
* @return 0, minus or plus
*/
static inline int
alias_cmp(void *x_, void *y_)
{
uint32_t * alias = (uint32_t *) y_;
dbhash_atpair_t *ele_x = (dbhash_atpair_t *) x_;
return *alias - ele_x->alias;
}
NNG_DECL void dbhash_init_alias_table(void);
NNG_DECL void dbhash_destroy_alias_table(void);
// This function do not verify value of alias and topic,
// therefore you should make sure alias and topic is
// not illegal.
NNG_DECL void dbhash_insert_atpair(uint32_t pipe_id, uint32_t alias, const char *topic);
NNG_DECL const char *dbhash_find_atpair(uint32_t pipe_id, uint32_t alias);
NNG_DECL void dbhash_del_atpair_queue(uint32_t pipe_id);
NNG_DECL void dbhash_init_pipe_table(void);
NNG_DECL void dbhash_destroy_pipe_table(void);
NNG_DECL void dbhash_insert_topic(uint32_t id, char *val, uint8_t qos);
NNG_DECL bool dbhash_check_topic(uint32_t id, char *val);
NNG_DECL char *dbhash_get_first_topic(uint32_t id);
NNG_DECL topic_queue *topic_queue_init(char *topic, int topic_len);
NNG_DECL void topic_queue_release(topic_queue *tq);
NNG_DECL topic_queue *init_topic_queue_with_topic_node(topic_node *tn);
NNG_DECL struct topic_queue *dbhash_get_topic_queue(uint32_t id);
NNG_DECL struct topic_queue *dbhash_copy_topic_queue(uint32_t id);
NNG_DECL void dbhash_del_topic(uint32_t id, char *topic);
NNG_DECL void *dbhash_del_topic_queue(
uint32_t id, void *(*cb)(void *, char *), void *args);
NNG_DECL bool dbhash_check_id(uint32_t id);
NNG_DECL void *dbhash_check_id_and_do(uint32_t id, void *(*cb)(void *), void *arg);
NNG_DECL void dbhash_print_topic_queue(uint32_t id);
NNG_DECL topic_queue **dbhash_get_topic_queue_all(size_t *sz);
NNG_DECL dbhash_ptpair_t *dbhash_ptpair_alloc(uint32_t p, char *t);
NNG_DECL void dbhash_ptpair_free(dbhash_ptpair_t *pt);
NNG_DECL dbhash_ptpair_t **dbhash_get_ptpair_all(void);
NNG_DECL size_t dbhash_get_pipe_cnt(void);
NNG_DECL void dbhash_init_cached_table(void);
NNG_DECL void dbhash_destroy_cached_table(void);
NNG_DECL void dbhash_cache_topic_all(uint32_t pid, uint32_t cid);
NNG_DECL void dbhash_restore_topic_all(uint32_t cid, uint32_t pid);
NNG_DECL struct topic_queue *dbhash_get_cached_topic(uint32_t cid);
NNG_DECL void dbhash_del_cached_topic_all(uint32_t key);
NNG_DECL bool dbhash_cached_check_id(uint32_t key);
#endif

View File

@ -0,0 +1,9 @@
#ifndef HOCON_H
#define HOCON_H
#include "cJSON.h"
cJSON *hocon_parse_file(const char *file);
cJSON *hocon_parse_str(char *str, size_t len);
#endif

View File

@ -0,0 +1,627 @@
/* The MIT License
Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
An example:
#include "khash.h"
KHASH_MAP_INIT_INT(32, char)
int main() {
int ret, is_missing;
khiter_t k;
khash_t(32) *h = kh_init(32);
k = kh_put(32, h, 5, &ret);
kh_value(h, k) = 10;
k = kh_get(32, h, 10);
is_missing = (k == kh_end(h));
k = kh_get(32, h, 5);
kh_del(32, h, k);
for (k = kh_begin(h); k != kh_end(h); ++k)
if (kh_exist(h, k)) kh_value(h, k) = 1;
kh_destroy(32, h);
return 0;
}
*/
/*
2013-05-02 (0.2.8):
* Use quadratic probing. When the capacity is power of 2, stepping function
i*(i+1)/2 guarantees to traverse each bucket. It is better than double
hashing on cache performance and is more robust than linear probing.
In theory, double hashing should be more robust than quadratic probing.
However, my implementation is probably not for large hash tables, because
the second hash function is closely tied to the first hash function,
which reduce the effectiveness of double hashing.
Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
2011-12-29 (0.2.7):
* Minor code clean up; no actual effect.
2011-09-16 (0.2.6):
* The capacity is a power of 2. This seems to dramatically improve the
speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
- http://code.google.com/p/ulib/
- http://nothings.org/computer/judy/
* Allow to optionally use linear probing which usually has better
performance for random input. Double hashing is still the default as it
is more robust to certain non-random input.
* Added Wang's integer hash function (not used by default). This hash
function is more robust to certain non-random input.
2011-02-14 (0.2.5):
* Allow to declare global functions.
2009-09-26 (0.2.4):
* Improve portability
2008-09-19 (0.2.3):
* Corrected the example
* Improved interfaces
2008-09-11 (0.2.2):
* Improved speed a little in kh_put()
2008-09-10 (0.2.1):
* Added kh_clear()
* Fixed a compiling error
2008-09-02 (0.2.0):
* Changed to token concatenation which increases flexibility.
2008-08-31 (0.1.2):
* Fixed a bug in kh_get(), which has not been tested previously.
2008-08-31 (0.1.1):
* Added destructor
*/
#ifndef __AC_KHASH_H
#define __AC_KHASH_H
/*!
@header
Generic hash table library.
*/
#define AC_VERSION_KHASH_H "0.2.8"
#include <stdlib.h>
#include <string.h>
#include <limits.h>
/* compiler specific configuration */
#if UINT_MAX == 0xffffffffu
typedef unsigned int khint32_t;
#elif ULONG_MAX == 0xffffffffu
typedef unsigned long khint32_t;
#endif
#if ULONG_MAX == ULLONG_MAX
typedef unsigned long khint64_t;
#else
typedef unsigned long long khint64_t;
#endif
#ifndef kh_inline
#ifdef _MSC_VER
#define kh_inline __inline
#else
#define kh_inline inline
#endif
#endif /* kh_inline */
#ifndef klib_unused
#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
#define klib_unused __attribute__ ((__unused__))
#else
#define klib_unused
#endif
#endif /* klib_unused */
typedef khint32_t khint_t;
typedef khint_t khiter_t;
#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
#endif
#ifndef kcalloc
#define kcalloc(N,Z) calloc(N,Z)
#endif
#ifndef kmalloc
#define kmalloc(Z) malloc(Z)
#endif
#ifndef krealloc
#define krealloc(P,Z) realloc(P,Z)
#endif
#ifndef kfree
#define kfree(P) free(P)
#endif
static const double __ac_HASH_UPPER = 0.77;
#define __KHASH_TYPE(name, khkey_t, khval_t) \
typedef struct kh_##name##_s { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t;
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
extern kh_##name##_t *kh_init_##name(void); \
extern void kh_destroy_##name(kh_##name##_t *h); \
extern void kh_clear_##name(kh_##name##_t *h); \
extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
extern void kh_del_##name(kh_##name##_t *h, khint_t x);
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
SCOPE kh_##name##_t *kh_init_##name(void) { \
return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t)); \
} \
SCOPE void kh_destroy_##name(kh_##name##_t *h) \
{ \
if (h) { \
kfree((void *)h->keys); kfree(h->flags); \
kfree((void *)h->vals); \
kfree(h); \
} \
} \
SCOPE void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->flags) { \
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
h->size = h->n_occupied = 0; \
} \
} \
SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
{ \
if (h->n_buckets) { \
khint_t k, i, last, mask, step = 0; \
mask = h->n_buckets - 1; \
k = __hash_func(key); i = k & mask; \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
i = (i + (++step)) & mask; \
if (i == last) return h->n_buckets; \
} \
return __ac_iseither(h->flags, i)? h->n_buckets : i; \
} else return 0; \
} \
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
khint_t j = 1; \
{ \
kroundup32(new_n_buckets); \
if (new_n_buckets < 4) new_n_buckets = 4; \
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
else { /* hash table size to be changed (shrink or expand); rehash */ \
new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (!new_flags) return -1; \
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (!new_keys) { kfree(new_flags); return -1; } \
h->keys = new_keys; \
if (kh_is_map) { \
khval_t *new_vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
if (!new_vals) { kfree(new_flags); return -1; } \
h->vals = new_vals; \
} \
} /* otherwise shrink */ \
} \
} \
if (j) { /* rehashing is needed */ \
for (j = 0; j != h->n_buckets; ++j) { \
if (__ac_iseither(h->flags, j) == 0) { \
khkey_t key = h->keys[j]; \
khval_t val; \
khint_t new_mask; \
new_mask = new_n_buckets - 1; \
if (kh_is_map) val = h->vals[j]; \
__ac_set_isdel_true(h->flags, j); \
while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
khint_t k, i, step = 0; \
k = __hash_func(key); \
i = k & new_mask; \
while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
__ac_set_isempty_false(new_flags, i); \
if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
} else { /* write the element and jump out of the loop */ \
h->keys[i] = key; \
if (kh_is_map) h->vals[i] = val; \
break; \
} \
} \
} \
} \
if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (kh_is_map) h->vals = (khval_t*)krealloc((void *)h->vals, new_n_buckets * sizeof(khval_t)); \
} \
kfree(h->flags); /* free the working space */ \
h->flags = new_flags; \
h->n_buckets = new_n_buckets; \
h->n_occupied = h->size; \
h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
} \
return 0; \
} \
SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t x; \
if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
if (h->n_buckets > (h->size<<1)) { \
if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
*ret = -1; return h->n_buckets; \
} \
} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
*ret = -1; return h->n_buckets; \
} \
} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
{ \
khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
else { \
last = i; \
while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
if (__ac_isdel(h->flags, i)) site = i; \
i = (i + (++step)) & mask; \
if (i == last) { x = site; break; } \
} \
if (x == h->n_buckets) { \
if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
else x = i; \
} \
} \
} \
if (__ac_isempty(h->flags, x)) { /* not present at all */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; ++h->n_occupied; \
*ret = 1; \
} else if (__ac_isdel(h->flags, x)) { /* deleted */ \
h->keys[x] = key; \
__ac_set_isboth_false(h->flags, x); \
++h->size; \
*ret = 2; \
} else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
return x; \
} \
SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
{ \
if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
__ac_set_isdel_true(h->flags, x); \
--h->size; \
} \
}
#define KHASH_DECLARE(name, khkey_t, khval_t) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_PROTOTYPES(name, khkey_t, khval_t)
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
__KHASH_TYPE(name, khkey_t, khval_t) \
__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
/* --- BEGIN OF HASH FUNCTIONS --- */
/*! @function
@abstract Integer hash function
@param key The integer [khint32_t]
@return The hash value [khint_t]
*/
#define kh_int_hash_func(key) (khint32_t)(key)
/*! @function
@abstract Integer comparison function
*/
#define kh_int_hash_equal(a, b) ((a) == (b))
/*! @function
@abstract 64-bit integer hash function
@param key The integer [khint64_t]
@return The hash value [khint_t]
*/
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
/*! @function
@abstract 64-bit integer comparison function
*/
#define kh_int64_hash_equal(a, b) ((a) == (b))
/*! @function
@abstract const char* hash function
@param s Pointer to a null terminated string
@return The hash value
*/
static kh_inline khint_t __ac_X31_hash_string(const char *s)
{
khint_t h = (khint_t)*s;
if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
return h;
}
/*! @function
@abstract Another interface to const char* hash function
@param key Pointer to a null terminated string [const char*]
@return The hash value [khint_t]
*/
#define kh_str_hash_func(key) __ac_X31_hash_string(key)
/*! @function
@abstract Const char* comparison function
*/
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
static kh_inline khint_t __ac_Wang_hash(khint_t key)
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return key;
}
#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key)
/* --- END OF HASH FUNCTIONS --- */
/* Other convenient macros... */
/*!
@abstract Type of the hash table.
@param name Name of the hash table [symbol]
*/
#define khash_t(name) kh_##name##_t
/*! @function
@abstract Initiate a hash table.
@param name Name of the hash table [symbol]
@return Pointer to the hash table [khash_t(name)*]
*/
#define kh_init(name) kh_init_##name()
/*! @function
@abstract Destroy a hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
*/
#define kh_destroy(name, h) kh_destroy_##name(h)
/*! @function
@abstract Reset a hash table without deallocating memory.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
*/
#define kh_clear(name, h) kh_clear_##name(h)
/*! @function
@abstract Resize a hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param s New size [khint_t]
*/
#define kh_resize(name, h, s) kh_resize_##name(h, s)
/*! @function
@abstract Insert a key to the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Key [type of keys]
@param r Extra return code: -1 if the operation failed;
0 if the key is present in the hash table;
1 if the bucket is empty (never used); 2 if the element in
the bucket has been deleted [int*]
@return Iterator to the inserted element [khint_t]
*/
#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
/*! @function
@abstract Retrieve a key from the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Key [type of keys]
@return Iterator to the found element, or kh_end(h) if the element is absent [khint_t]
*/
#define kh_get(name, h, k) kh_get_##name(h, k)
/*! @function
@abstract Remove a key from the hash table.
@param name Name of the hash table [symbol]
@param h Pointer to the hash table [khash_t(name)*]
@param k Iterator to the element to be deleted [khint_t]
*/
#define kh_del(name, h, k) kh_del_##name(h, k)
/*! @function
@abstract Test whether a bucket contains data.
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return 1 if containing data; 0 otherwise [int]
*/
#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
/*! @function
@abstract Get key given an iterator
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return Key [type of keys]
*/
#define kh_key(h, x) ((h)->keys[x])
/*! @function
@abstract Get value given an iterator
@param h Pointer to the hash table [khash_t(name)*]
@param x Iterator to the bucket [khint_t]
@return Value [type of values]
@discussion For hash sets, calling this results in segfault.
*/
#define kh_val(h, x) ((h)->vals[x])
/*! @function
@abstract Alias of kh_val()
*/
#define kh_value(h, x) ((h)->vals[x])
/*! @function
@abstract Get the start iterator
@param h Pointer to the hash table [khash_t(name)*]
@return The start iterator [khint_t]
*/
#define kh_begin(h) (khint_t)(0)
/*! @function
@abstract Get the end iterator
@param h Pointer to the hash table [khash_t(name)*]
@return The end iterator [khint_t]
*/
#define kh_end(h) ((h)->n_buckets)
/*! @function
@abstract Get the number of elements in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@return Number of elements in the hash table [khint_t]
*/
#define kh_size(h) ((h)->size)
/*! @function
@abstract Get the number of buckets in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@return Number of buckets in the hash table [khint_t]
*/
#define kh_n_buckets(h) ((h)->n_buckets)
/*! @function
@abstract Iterate over the entries in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@param kvar Variable to which key will be assigned
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(kvar) = kh_key(h,__i); \
(vvar) = kh_val(h,__i); \
code; \
} }
/*! @function
@abstract Iterate over the values in the hash table
@param h Pointer to the hash table [khash_t(name)*]
@param vvar Variable to which value will be assigned
@param code Block of code to execute
*/
#define kh_foreach_value(h, vvar, code) { khint_t __i; \
for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
if (!kh_exist(h,__i)) continue; \
(vvar) = kh_val(h,__i); \
code; \
} }
/* More convenient interfaces */
/*! @function
@abstract Instantiate a hash set containing integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT(name) \
KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash map containing integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT(name, khval_t) \
KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
/*! @function
@abstract Instantiate a hash set containing 64-bit integer keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_INT64(name) \
KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
/*! @function
@abstract Instantiate a hash map containing 64-bit integer keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_INT64(name, khval_t) \
KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
typedef const char *kh_cstr_t;
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
*/
#define KHASH_SET_INIT_STR(name) \
KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
/*! @function
@abstract Instantiate a hash map containing const char* keys
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
#define KHASH_MAP_INIT_STR(name, khval_t) \
KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
#endif /* __AC_KHASH_H */

View File

@ -0,0 +1,33 @@
#include <stdio.h>
#include <stdlib.h>
struct linkedListNode {
void *data;
unsigned long long expiredAt;
struct linkedListNode *next;
struct linkedListNode *prev;
};
struct linkedList {
unsigned int cap;
unsigned int size;
unsigned int overWrite;
unsigned long long expiredAt;
struct linkedListNode *head;
struct linkedListNode *tail;
};
int linkedList_replace_head(struct linkedList *list,
void *data,
unsigned long long expiredAt);
int linkedList_init(struct linkedList **list,
unsigned int cap,
unsigned int overWrite,
unsigned long long expiredAt);
int linkedList_enqueue(struct linkedList *list,
void *data,
unsigned long long expiredAt);
int linkedList_dequeue(struct linkedList *list,
void **data);
int linkedList_release(struct linkedList *list);

View File

@ -0,0 +1,111 @@
#ifndef NNG_NANOLIB_LOG_H
#define NNG_NANOLIB_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "nng/nng.h"
#define LOG_VERSION "0.2.1"
/**
* 2023-12-08 move conf_log to log.h
*/
// log type
#define LOG_TO_FILE (1 << 0)
#define LOG_TO_CONSOLE (1 << 1)
#define LOG_TO_SYSLOG (1 << 2)
#define LOG_TO_UDS (1 << 3)
typedef struct conf_log conf_log;
struct conf_log {
uint8_t type;
int level;
char *dir;
char *file;
char *uds_addr;
FILE *fp;
char *abs_path; // absolut path of log file
char *rotation_sz_str; // 1000KB, 100MB, 10GB
uint64_t rotation_sz; // unit: byte
size_t rotation_count; // rotation count
};
typedef struct {
va_list ap;
const char *fmt;
const char *file;
const char *func;
struct tm time;
void * udata;
int line;
int level;
conf_log * config;
} log_event;
typedef void (*log_func)(log_event *ev);
enum {
NNG_LOG_FATAL = 0,
NNG_LOG_ERROR,
NNG_LOG_WARN,
NNG_LOG_INFO,
NNG_LOG_DEBUG,
NNG_LOG_TRACE,
};
NNG_DECL const char *log_level_string(int level);
NNG_DECL int log_level_num(const char *level);
NNG_DECL void log_set_level(int level);
NNG_DECL int log_add_callback(
log_func fn, void *udata, int level, void *mtx, conf_log *config);
NNG_DECL void log_add_console(int level, void *mtx);
NNG_DECL int log_add_fp(FILE *fp, int level, void *mtx, conf_log *config);
NNG_DECL void log_add_syslog(const char *log_name, uint8_t level, void *mtx);
NNG_DECL void log_add_uds(const char *uds_path, const char *log_name, uint8_t level, void *mtx);
NNG_DECL void uds_closelog(void);
NNG_DECL void log_log(int level, const char *file, int line, const char *func,
const char *fmt, ...);
NNG_DECL void log_clear_callback();
#ifdef ENABLE_LOG
#define log_trace(...) \
log_log(NNG_LOG_TRACE, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define log_debug(...) \
log_log(NNG_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define log_info(...) \
log_log(NNG_LOG_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define log_warn(...) \
log_log(NNG_LOG_WARN, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define log_error(...) \
log_log(NNG_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define log_fatal(...) \
log_log(NNG_LOG_FATAL, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#else
static inline void dummy_log_function(const char *fmt, ...) { (void)fmt; }
#define log_trace(...) dummy_log_function(__VA_ARGS__)
#define log_debug(...) dummy_log_function(__VA_ARGS__)
#define log_info(...) dummy_log_function(__VA_ARGS__)
#define log_warn(...) dummy_log_function(__VA_ARGS__)
#define log_error(...) dummy_log_function(__VA_ARGS__)
#define log_fatal(...) dummy_log_function(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,77 @@
#ifndef NANOLIB_MD5_H
#define NANOLIB_MD5_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__WINDOWS__) || defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)
#else
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define READ_DATA_SIZE 1024
#define MD5_SIZE 16
#define MD5_STR_LEN (MD5_SIZE * 2)
#define MD5_LEN 32
typedef struct
{
unsigned int count[2];
unsigned int state[4];
unsigned char buffer[64];
} MD5_CTX;
#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
{ \
a += F(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define GG(a,b,c,d,x,s,ac) \
{ \
a += G(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define HH(a,b,c,d,x,s,ac) \
{ \
a += H(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) \
{ \
a += I(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
int ComputeStringMD5(unsigned char *dest_str, unsigned int dest_len, char *md5_str);
int ComputeFileMD5(const char *file_path, char *md5_str);
void MD5Init(MD5_CTX *context);
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen);
void MD5Final(MD5_CTX *context, unsigned char digest[16]);
void MD5Transform(unsigned int state[4], unsigned char block[64]);
void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len);
void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,138 @@
#ifndef MQTT_DB_H
#define MQTT_DB_H
#include "cvector.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "nng/nng.h"
typedef enum {
MQTT_VERSION_V311 = 4,
MQTT_VERSION_V5 = 5,
} mqtt_version_t;
typedef struct dbtree dbtree;
typedef struct {
char * topic;
char **clients;
int cld_cnt;
} dbtree_info;
/**
* @brief dbtree_create - Create a dbtree.
* @param dbtree - dbtree
* @return void
*/
NNG_DECL void dbtree_create(dbtree **db);
/**
* @brief dbtree_destory - Destory dbtree tree
* @param dbtree - dbtree
* @return void
*/
NNG_DECL void dbtree_destory(dbtree *db);
/**
* @brief dbtree_print - Print dbtree for debug.
* @param dbtree - dbtree
* @return void
*/
NNG_DECL void dbtree_print(dbtree *db);
/**
* @brief dbtree_insert_client - check if this
* topic and pipe id is exist on the tree, if
* there is not exist, this func will insert node
* recursively until find all topic then insert
* client on the node.
* @param dbtree - dbtree_node
* @param topic - topic
* @param pipe_id - pipe id
* @return
*/
NNG_DECL void *dbtree_insert_client(
dbtree *db, char *topic, uint32_t pipe_id);
/**
* @brief dbtree_find_client - check if this
* topic and pipe id is exist on the tree, if
* there is not exist, return it.
* @param dbtree - dbtree_node
* @param topic - topic
* @param ctxt - data related with pipe_id
* @param pipe_id - pipe id
* @return
*/
// void *dbtree_find_client(dbtree *db, char *topic, uint32_t pipe_id);
/**
* @brief dbtree_delete_client - This function will
* be called when disconnection and cleansession = 1.
* check if this topic and client id is exist on the
* tree, if there is exist, this func will delete
* related node and client on the tree
* @param dbtree - dbtree
* @param topic - topic
* @param pipe_id - pipe id
* @return
*/
NNG_DECL void *dbtree_delete_client(
dbtree *db, char *topic, uint32_t pipe_id);
/**
* @brief dbtree_find_clients_and_cache_msg - Get all
* subscribers online to this topic
* @param dbtree - dbtree
* @param topic - topic
* @return pipe id array
*/
NNG_DECL uint32_t *dbtree_find_clients(dbtree *db, char *topic);
/**
* @brief dbtree_insert_retain - Insert retain message to this topic.
* @param db - dbtree
* @param topic - topic
* @param ret_msg - dbtree_retain_msg
* @return
*/
NNG_DECL nng_msg *dbtree_insert_retain(
dbtree *db, char *topic, nng_msg *ret_msg);
/**
* @brief dbtree_delete_retain - Delete all retain message to this topic.
* @param db - dbtree
* @param topic - topic
* @return ctxt or NULL, if client can be delete or not
*/
NNG_DECL nng_msg *dbtree_delete_retain(dbtree *db, char *topic);
/**
* @brief dbtree_find_retain - Get all retain message to this topic.
* @param db - dbtree
* @param topic - topic
* @return dbtree_retain_msg pointer vector
*/
NNG_DECL nng_msg **dbtree_find_retain(dbtree *db, char *topic);
/**
* @brief dbtree_find_shared_clients - This function
* will Find shared subscribe client.
* @param dbtree - dbtree
* @param topic - topic
* @return pipe id array
*/
NNG_DECL uint32_t *dbtree_find_shared_clients(dbtree *db, char *topic);
/**
* @brief dbtree_get_tree - This function will
* get all info about this tree.
* @param dbtree - dbtree
* @param cb - a callback function
* @return all info about this tree
*/
NNG_DECL void ***dbtree_get_tree(dbtree *db, void *(*cb)(uint32_t pipe_id));
#endif

View File

@ -0,0 +1,10 @@
#ifndef NANOLIB_H
#define NANOLIB_H
#include "hash_table.h"
#include "mqtt_db.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#endif

View File

@ -0,0 +1,76 @@
#ifndef PARQUET_H
#define PARQUET_H
#include "nng/nng.h"
#include "nng/supplemental/nanolib/conf.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct parquet_object parquet_object;
typedef void (*parquet_cb)(parquet_object *arg);
typedef enum {
WRITE_TO_NORMAL,
WRITE_TO_TEMP,
} parquet_write_type;
typedef struct {
uint32_t start_idx;
uint32_t end_idx;
char *filename;
} parquet_file_range;
typedef struct {
parquet_file_range **range;
int size;
int start; // file range start index
} parquet_file_ranges;
typedef struct {
uint8_t *data;
uint32_t size;
} parquet_data_packet;
struct parquet_object {
uint64_t *keys;
uint8_t **darray;
uint32_t *dsize;
uint32_t size;
nng_aio *aio;
void *arg;
parquet_file_ranges *ranges;
parquet_write_type type;
char *topic;
};
parquet_object *parquet_object_alloc(uint64_t *keys, uint8_t **darray,
uint32_t *dsize, uint32_t size, nng_aio *aio, void *arg);
void parquet_object_free(parquet_object *elem);
parquet_file_range *parquet_file_range_alloc(uint32_t start_idx, uint32_t end_idx, char *filename);
void parquet_file_range_free(parquet_file_range *range);
void parquet_object_set_cb(parquet_object *obj, parquet_cb cb);
int parquet_write_batch_async(parquet_object *elem);
// Write a batch to a temporary Parquet file, utilize it in scenarios where a single
// file is sufficient for writing, sending, and subsequent deletion.
int parquet_write_batch_tmp_async(parquet_object *elem);
int parquet_write_launcher(conf_parquet *conf);
const char *parquet_find(uint64_t key);
const char **parquet_find_span(
uint64_t start_key, uint64_t end_key, uint32_t *size);
parquet_data_packet *parquet_find_data_packet(conf_parquet *conf, char *filename, uint64_t key);
parquet_data_packet **parquet_find_data_packets(conf_parquet *conf, char **filenames, uint64_t *keys, uint32_t len);
parquet_data_packet **parquet_find_data_span_packets(conf_parquet *conf, uint64_t start_key, uint64_t end_key, uint32_t *size, char *topic);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,105 @@
/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual,
especially those whose name start with YY_ or yy_. They are
private implementation details that can be changed or removed. */
#ifndef YY_YY_NANOMQ_NNG_SRC_SUPPLEMENTAL_NANOLIB_PARSER_H_INCLUDED
# define YY_YY_NANOMQ_NNG_SRC_SUPPLEMENTAL_NANOLIB_PARSER_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int yydebug;
#endif
/* Token kinds. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
YYEMPTY = -2,
YYEOF = 0, /* "end of file" */
YYerror = 256, /* error */
YYUNDEF = 257, /* "invalid token" */
LCURLY = 258, /* LCURLY */
RCURLY = 259, /* RCURLY */
LBRAC = 260, /* LBRAC */
RBRAC = 261, /* RBRAC */
COMMA = 262, /* COMMA */
PUNCT = 263, /* PUNCT */
VTRUE = 264, /* VTRUE */
VFALSE = 265, /* VFALSE */
VNULL = 266, /* VNULL */
STRING = 267, /* STRING */
USTRING = 268, /* USTRING */
RSTRING = 269, /* RSTRING */
BYTESIZE = 270, /* BYTESIZE */
PERCENT = 271, /* PERCENT */
DURATION = 272, /* DURATION */
DECIMAL = 273, /* DECIMAL */
INTEGER = 274 /* INTEGER */
};
typedef enum yytokentype yytoken_kind_t;
#endif
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
#line 25 "parser.y"
double intval;
double floatval;
char *strval;
struct cJSON *jsonval;
struct jso_kv *jkval;
#line 91 "nng/src/supplemental/nanolib/parser.h"
};
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;
int yyparse (struct cJSON **jso);
#endif /* !YY_YY_NANOMQ_NNG_SRC_SUPPLEMENTAL_NANOLIB_PARSER_H_INCLUDED */

View File

@ -0,0 +1,87 @@
#ifndef QUEUE_H
#define QUEUE_H
#include <stdio.h>
#include <stdlib.h>
#define INITIAL_SIZE 5
typedef struct {
void** array;
int front;
int rear;
int size;
int capacity;
} CircularQueue;
#define INIT_QUEUE(queue) \
do { \
(queue).array = (void**)malloc(INITIAL_SIZE * sizeof(void*)); \
(queue).front = -1; \
(queue).rear = -1; \
(queue).size = 0; \
(queue).capacity = INITIAL_SIZE; \
} while(0)
#define NEXT_INDEX(index, size) (((index) + 1) % (size))
#define IS_EMPTY(queue) ((queue).size == 0)
#define QUEUE_SIZE(queue) ((queue).size)
#define ENQUEUE(queue, element) \
do { \
if ((queue).size == (queue).capacity) { \
int new_capacity = (queue).capacity * 2; \
void** new_array = (void**)malloc(new_capacity * sizeof(void*)); \
int i = 0; \
int j = (queue).front; \
while (i < (queue).size) { \
new_array[i] = (queue).array[j]; \
i++; \
j = NEXT_INDEX(j, (queue).capacity); \
} \
free((queue).array); \
(queue).array = new_array; \
(queue).front = 0; \
(queue).rear = (queue).size - 1; \
(queue).capacity = new_capacity; \
} \
if (IS_EMPTY(queue)) { \
(queue).front = 0; \
} \
(queue).rear = NEXT_INDEX((queue).rear, (queue).capacity); \
(queue).array[(queue).rear] = (element); \
(queue).size++; \
} while(0)
#define DEQUEUE(queue) \
({ \
void* dequeued_element = NULL; \
if (IS_EMPTY(queue)) { \
printf("Queue is empty. Cannot dequeue.\n"); \
} else { \
dequeued_element = (queue).array[(queue).front]; \
(queue).front = NEXT_INDEX((queue).front, (queue).capacity); \
(queue).size--; \
if (IS_EMPTY(queue)) { \
(queue).front = -1; \
(queue).rear = -1; \
} \
} \
dequeued_element; \
})
#define FOREACH_QUEUE(queue, elem) \
for (int i = (queue).front, _count = 0; \
(queue).size != 0 && _count < (queue).size; \
i = NEXT_INDEX(i, (queue).capacity), _count++) \
\
for (elem = (queue).array[i]; \
elem != NULL; \
elem = NULL)
#define DESTROY_QUEUE(queue) free((queue).array)
#endif

View File

@ -0,0 +1,138 @@
//
// Copyright 2023 NanoMQ Team, Inc. <jaylin@emqx.io>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#include <stdio.h>
#include <stdlib.h>
#include "nng/nng.h"
#include "nng/supplemental/util/platform.h"
#include "nng/supplemental/nanolib/cvector.h"
#define RBNAME_LEN 100
#define RINGBUFFER_MAX_SIZE 0xffffffff
#define RBRULELIST_MAX_SIZE 0xff
#define ENQUEUE_IN_HOOK 0x0001
#define ENQUEUE_OUT_HOOK 0x0010
#define DEQUEUE_IN_HOOK 0x0100
#define DEQUEUE_OUT_HOOK 0x1000
#define HOOK_MASK ((ENQUEUE_IN_HOOK) | (ENQUEUE_OUT_HOOK) | (DEQUEUE_IN_HOOK) | (DEQUEUE_OUT_HOOK))
typedef struct ringBuffer_s ringBuffer_t;
typedef struct ringBufferMsg_s ringBufferMsg_t;
typedef struct ringBufferRule_s ringBufferRule_t;
/* For RB_FULL_FILE */
typedef struct ringBufferFile_s ringBufferFile_t;
typedef struct ringBufferFileRange_s ringBufferFileRange_t;
struct ringBufferMsg_s {
uint64_t key;
void *data;
/* TTL of each message */
unsigned long long expiredAt;
};
enum fullOption {
RB_FULL_NONE,
RB_FULL_DROP,
RB_FULL_RETURN,
RB_FULL_FILE,
RB_FULL_MAX
};
struct ringBufferFileRange_s {
uint64_t startidx;
uint64_t endidx;
char *filename;
};
struct ringBufferFile_s {
uint64_t *keys;
nng_aio *aio;
ringBufferFileRange_t **ranges;
};
struct ringBuffer_s {
char name[RBNAME_LEN];
unsigned int head;
unsigned int tail;
unsigned int size;
unsigned int cap;
/* TTL of all messages in ringbuffer */
unsigned long long expiredAt;
unsigned int enqinRuleListLen;
unsigned int enqoutRuleListLen;
unsigned int deqinRuleListLen;
unsigned int deqoutRuleListLen;
ringBufferRule_t *enqinRuleList[RBRULELIST_MAX_SIZE];
ringBufferRule_t *enqoutRuleList[RBRULELIST_MAX_SIZE];
ringBufferRule_t *deqinRuleList[RBRULELIST_MAX_SIZE];
ringBufferRule_t *deqoutRuleList[RBRULELIST_MAX_SIZE];
enum fullOption fullOp;
/* FOR RB_FULL_FILE */
ringBufferFile_t **files;
nng_mtx *ring_lock;
ringBufferMsg_t *msgs;
};
struct ringBufferRule_s {
/*
* flag: ENQUEUE_IN_HOOK/ENQUEUE_OUT_HOOK/DEQUEUE_IN_HOOK/DEQUEUE_OUT_HOOK
* return: 0: success, -1: failed
*/
int (*match)(ringBuffer_t *rb, void *data, int flag);
/*
* return: 0: continue, -1: stop and return
*/
int (*target)(ringBuffer_t *rb, void *data, int flag);
};
int ringBuffer_add_rule(ringBuffer_t *rb,
int (*match)(ringBuffer_t *rb, void *data, int flag),
int (*target)(ringBuffer_t *rb, void *data, int flag),
int flag);
int ringBuffer_init(ringBuffer_t **rb,
unsigned int cap,
enum fullOption fullOp,
unsigned long long expiredAt);
int ringBuffer_enqueue(ringBuffer_t *rb,
uint64_t key,
void *data,
unsigned long long expiredAt,
nng_aio *aio);
int ringBuffer_dequeue(ringBuffer_t *rb, void **data);
int ringBuffer_release(ringBuffer_t *rb);
int ringBuffer_search_msg_by_key(ringBuffer_t *rb, uint64_t key, nng_msg **msg);
int ringBuffer_search_msgs_by_key(ringBuffer_t *rb, uint64_t key, uint32_t count, nng_msg ***list);
int ringBuffer_search_msgs_fuzz(ringBuffer_t *rb,
uint64_t start,
uint64_t end,
uint32_t *count,
nng_msg ***list);
int ringBuffer_get_and_clean_msgs(ringBuffer_t *rb,
unsigned int *count, nng_msg ***list);
int ringBuffer_set_fullOp(ringBuffer_t *rb, enum fullOption fullOp);
#ifdef SUPP_PARQUET
int ringBuffer_get_msgs_from_file(ringBuffer_t *rb, void ***msgs, int **msgLen);
int ringBuffer_get_msgs_from_file_by_keys(ringBuffer_t *rb, uint64_t *keys, uint32_t count,
void ***msgs, int **msgLen);
#endif
#endif

View File

@ -0,0 +1,138 @@
#ifndef RULE_H
#define RULE_H
#include <stdint.h>
#include "nng/nng.h"
#include "nng/supplemental/util/platform.h"
typedef enum {
RULE_QOS,
RULE_ID,
RULE_TOPIC,
RULE_CLIENTID,
RULE_USERNAME,
RULE_PASSWORD,
RULE_TIMESTAMP,
RULE_PAYLOAD_ALL,
RULE_PAYLOAD_FIELD,
} rule_type;
typedef enum {
RULE_CMP_NONE, // compare type init value
RULE_CMP_EQUAL, // compare symbol '='
RULE_CMP_UNEQUAL, // compare symbol '!=' or '<>'
RULE_CMP_GREATER, // compare symbol '>'
RULE_CMP_LESS, // compare symbol '<'
RULE_CMP_GREATER_AND_EQUAL, // compare symbol '>='
RULE_CMP_LESS_AND_EQUAL, // compare symbol '<='
} rule_cmp_type;
typedef enum {
RULE_FORWORD_SQLITE,
RULE_FORWORD_FDB,
RULE_FORWORD_MYSQL,
RULE_FORWORD_REPUB
} rule_forword_type;
typedef struct {
char **psa; // payload string array, for multi level json
char *pas; // payload field string or alias
char *filter; // payload field related filter
rule_cmp_type cmp_type; // payload field compare type
bool is_store; // payload value is store or not
uint8_t type; // payload field value type
void *value; // payload field value
} rule_payload;
typedef struct {
bool flag[9];
bool auto_inc;
uint8_t type;
void *value;
char **key_arr;
} rule_key;
typedef struct {
char *address;
uint8_t proto_ver;
char *clientid;
bool clean_start;
char *username;
char *password;
uint16_t keepalive;
char *topic;
void *sock;
} repub_t;
typedef struct {
char *table;
char *host;
char *username;
char *password;
void *conn;
} rule_mysql;
typedef struct {
/*
** flag[0] == RULE_QOS,
** flag[1] == RULE_ID,
** flag[2] == RULE_TOPIC,
** flag[3] == RULE_CLIENTID,
** flag[4] == RULE_USERNAME,
** flag[5] == RULE_PASSWORD,
** flag[6] == RULE_TIMESTAMP,
** flag[7] == RULE_PAYLOAD_ALL,
** flag[8] == RULE_PAYLOAD_FIELD,
*/
bool flag[9]; // if this field need to store
bool enabled; // if this rule is enabled
rule_cmp_type cmp_type[8]; // filter compare type
rule_forword_type forword_type; // forword type
char *topic; // topic parse from sql 'from'
char *as[8]; // if field string as a new string
rule_payload **payload; // this is for payload info
char **filter; // filter parse from sql 'where'
char *sqlite_table;
char *raw_sql;
uint32_t rule_id;
rule_key *key;
repub_t *repub;
rule_mysql *mysql;
} rule;
typedef struct {
/*
** 00000000 == OFF,
** 00000001 == Sqlite ON,
** 00000010 == Fdb ON,
** 00000100 == MySOL ON
** 00001000 == Repub ON
** 00010000
** 00100000
** 01000000
*/
uint8_t option;
/*
** rdb[0] == Sqlite
** rdb[1] == Fdb
** rdb[2] == MySOL
** rdb[3] == RePub
*/
void *rdb[3];
rule *rules;
char *sqlite_db;
char *mysql_db;
nng_mtx *rule_mutex;
} conf_rule;
int rule_find_key(const char *str, size_t len);
uint32_t rule_generate_rule_id(void);
char *rule_get_key_arr(char *p, rule_key *key);
bool rule_sql_parse(conf_rule *cr, char *sql);
repub_t *rule_repub_init(void);
void rule_repub_free(repub_t *repub);
void rule_free(rule *r);
bool rule_mysql_check(rule_mysql *mysql);
void rule_mysql_free(rule_mysql *mysql);
rule_mysql *rule_mysql_init(void);
#endif

View File

@ -0,0 +1,479 @@
#ifndef yyHEADER_H
#define yyHEADER_H 1
#define yyIN_HEADER 1
#line 6 "nng/src/supplemental/nanolib/scanner.h"
#line 8 "nng/src/supplemental/nanolib/scanner.h"
#define YY_INT_ALIGNED short int
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 4
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
/* end standard C headers. */
/* flex integer type definitions */
#ifndef FLEXINT_H
#define FLEXINT_H
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
#ifndef SIZE_MAX
#define SIZE_MAX (~(size_t)0)
#endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
/* begin standard C++ headers. */
/* TODO: this is always defined, so inline it */
#define yyconst const
#if defined(__GNUC__) && __GNUC__ >= 3
#define yynoreturn __attribute__((__noreturn__))
#else
#define yynoreturn
#endif
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k.
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
* Ditto for the __ia64__ case accordingly.
*/
#define YY_BUF_SIZE 32768
#else
#define YY_BUF_SIZE 16384
#endif /* __ia64__ */
#endif
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
extern int yyleng;
extern FILE *yyin, *yyout;
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
/* Whether we're considered to be at the beginning of a line.
* If so, '^' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
void yyrestart ( FILE *input_file );
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer );
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
void yy_delete_buffer ( YY_BUFFER_STATE b );
void yy_flush_buffer ( YY_BUFFER_STATE b );
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer );
void yypop_buffer_state ( void );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len );
void *yyalloc ( yy_size_t );
void *yyrealloc ( void *, yy_size_t );
void yyfree ( void * );
/* Begin user sect3 */
#define yywrap() (/*CONSTCOND*/1)
#define YY_SKIP_YYWRAP
extern int yylineno;
extern char *yytext;
#ifdef yytext_ptr
#undef yytext_ptr
#endif
#define yytext_ptr yytext
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
#define INITIAL 0
#define incl 1
#define inclr 2
#endif
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
* down here because we want the user's section 1 to have been scanned first.
* The user has a chance to override it with an option.
*/
#include <unistd.h>
#endif
#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endif
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int yylex_destroy ( void );
int yyget_debug ( void );
void yyset_debug ( int debug_flag );
YY_EXTRA_TYPE yyget_extra ( void );
void yyset_extra ( YY_EXTRA_TYPE user_defined );
FILE *yyget_in ( void );
void yyset_in ( FILE * _in_str );
FILE *yyget_out ( void );
void yyset_out ( FILE * _out_str );
int yyget_leng ( void );
char *yyget_text ( void );
int yyget_lineno ( void );
void yyset_lineno ( int _line_number );
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap ( void );
#else
extern int yywrap ( void );
#endif
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy ( char *, const char *, int );
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen ( const char * );
#endif
#ifndef YY_NO_INPUT
#endif
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k */
#define YY_READ_BUF_SIZE 16384
#else
#define YY_READ_BUF_SIZE 8192
#endif /* __ia64__ */
#endif
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
extern int yylex (void);
#define YY_DECL int yylex (void)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
#undef YY_NEW_FILE
#undef YY_FLUSH_BUFFER
#undef yy_set_bol
#undef yy_new_buffer
#undef yy_set_interactive
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
#ifndef yy_create_buffer_ALREADY_DEFINED
#undef yy_create_buffer
#endif
#ifndef yy_delete_buffer_ALREADY_DEFINED
#undef yy_delete_buffer
#endif
#ifndef yy_scan_buffer_ALREADY_DEFINED
#undef yy_scan_buffer
#endif
#ifndef yy_scan_string_ALREADY_DEFINED
#undef yy_scan_string
#endif
#ifndef yy_scan_bytes_ALREADY_DEFINED
#undef yy_scan_bytes
#endif
#ifndef yy_init_buffer_ALREADY_DEFINED
#undef yy_init_buffer
#endif
#ifndef yy_flush_buffer_ALREADY_DEFINED
#undef yy_flush_buffer
#endif
#ifndef yy_load_buffer_state_ALREADY_DEFINED
#undef yy_load_buffer_state
#endif
#ifndef yy_switch_to_buffer_ALREADY_DEFINED
#undef yy_switch_to_buffer
#endif
#ifndef yypush_buffer_state_ALREADY_DEFINED
#undef yypush_buffer_state
#endif
#ifndef yypop_buffer_state_ALREADY_DEFINED
#undef yypop_buffer_state
#endif
#ifndef yyensure_buffer_stack_ALREADY_DEFINED
#undef yyensure_buffer_stack
#endif
#ifndef yylex_ALREADY_DEFINED
#undef yylex
#endif
#ifndef yyrestart_ALREADY_DEFINED
#undef yyrestart
#endif
#ifndef yylex_init_ALREADY_DEFINED
#undef yylex_init
#endif
#ifndef yylex_init_extra_ALREADY_DEFINED
#undef yylex_init_extra
#endif
#ifndef yylex_destroy_ALREADY_DEFINED
#undef yylex_destroy
#endif
#ifndef yyget_debug_ALREADY_DEFINED
#undef yyget_debug
#endif
#ifndef yyset_debug_ALREADY_DEFINED
#undef yyset_debug
#endif
#ifndef yyget_extra_ALREADY_DEFINED
#undef yyget_extra
#endif
#ifndef yyset_extra_ALREADY_DEFINED
#undef yyset_extra
#endif
#ifndef yyget_in_ALREADY_DEFINED
#undef yyget_in
#endif
#ifndef yyset_in_ALREADY_DEFINED
#undef yyset_in
#endif
#ifndef yyget_out_ALREADY_DEFINED
#undef yyget_out
#endif
#ifndef yyset_out_ALREADY_DEFINED
#undef yyset_out
#endif
#ifndef yyget_leng_ALREADY_DEFINED
#undef yyget_leng
#endif
#ifndef yyget_text_ALREADY_DEFINED
#undef yyget_text
#endif
#ifndef yyget_lineno_ALREADY_DEFINED
#undef yyget_lineno
#endif
#ifndef yyset_lineno_ALREADY_DEFINED
#undef yyset_lineno
#endif
#ifndef yyget_column_ALREADY_DEFINED
#undef yyget_column
#endif
#ifndef yyset_column_ALREADY_DEFINED
#undef yyset_column
#endif
#ifndef yywrap_ALREADY_DEFINED
#undef yywrap
#endif
#ifndef yyget_lval_ALREADY_DEFINED
#undef yyget_lval
#endif
#ifndef yyset_lval_ALREADY_DEFINED
#undef yyset_lval
#endif
#ifndef yyget_lloc_ALREADY_DEFINED
#undef yyget_lloc
#endif
#ifndef yyset_lloc_ALREADY_DEFINED
#undef yyset_lloc
#endif
#ifndef yyalloc_ALREADY_DEFINED
#undef yyalloc
#endif
#ifndef yyrealloc_ALREADY_DEFINED
#undef yyrealloc
#endif
#ifndef yyfree_ALREADY_DEFINED
#undef yyfree
#endif
#ifndef yytext_ALREADY_DEFINED
#undef yytext
#endif
#ifndef yyleng_ALREADY_DEFINED
#undef yyleng
#endif
#ifndef yyin_ALREADY_DEFINED
#undef yyin
#endif
#ifndef yyout_ALREADY_DEFINED
#undef yyout
#endif
#ifndef yy_flex_debug_ALREADY_DEFINED
#undef yy_flex_debug
#endif
#ifndef yylineno_ALREADY_DEFINED
#undef yylineno
#endif
#ifndef yytables_fload_ALREADY_DEFINED
#undef yytables_fload
#endif
#ifndef yytables_destroy_ALREADY_DEFINED
#undef yytables_destroy
#endif
#ifndef yyTABLES_NAME_ALREADY_DEFINED
#undef yyTABLES_NAME
#endif
#line 74 "scanner.l"
#line 476 "nng/src/supplemental/nanolib/scanner.h"
#undef yyIN_HEADER
#endif /* yyHEADER_H */

View File

@ -0,0 +1,11 @@
#ifndef _NNG_SUPPLEMENTAL_NANOLIB_UTILS_H
#define _NNG_SUPPLEMENTAL_NANOLIB_UTILS_H
#include "nng/nng.h"
#include <ctype.h>
#include <stdio.h>
NNG_DECL void fatal(const char *msg, ...);
NNG_DECL void nng_fatal(const char *msg, int rv);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,222 @@
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
// This file is used to enable external TLS "engines", so
// that third party TLS libraries can be plugged in
#ifndef NNG_SUPPLEMENTAL_TLS_ENGINE_H
#define NNG_SUPPLEMENTAL_TLS_ENGINE_H
#include <nng/supplemental/tls/tls.h>
// Locking theory statement for TLS engines. The engine is assumed
// operate only from the context of threads called by the common
// framework. That is to say, the callbacks made by the engine
// should always be on a thread that has context from the framework
// calling into the engine. This means that the lower level send
// and receive functions can assume that they have lock ownership
// inherited on the stack.
// nng_tls_engine_conn represents the engine-specific private
// state for a TLS connection. It is provided here for type
// safety. Engine implementations should provide the structure
// definition locally.
typedef struct nng_tls_engine_conn nng_tls_engine_conn;
// nng_tls_engine_config represents the engine-specific private
// state for the TLS configuration. It is provided here for type
// safety. Engine implementations should provide the structure
// definition locally.
typedef struct nng_tls_engine_config nng_tls_engine_config;
typedef struct nng_tls_engine_conn_ops_s {
// size is the size of the engine's per-connection state.
// The framework will allocate this on behalf of the engine.
// Typically this will be sizeof (struct nng_tls_engine_conn).
size_t size;
// init is used to initialize a connection object.
// The passed in connection state will be aligned naturally,
// and zeroed. On success this returns 0, else an NNG error code.
int (*init)(nng_tls_engine_conn *, void *, nng_tls_engine_config *);
// fini destroys a connection object. This will
// be called only when no other external use of the connection
// object exists, and only on fully initialed connection objects.
void (*fini)(nng_tls_engine_conn *);
// close closes the connection object, but should not
// deallocate any memory. It may also issue a TLS close-notify.
void (*close)(nng_tls_engine_conn *);
// handshake attempts to complete the SSL handshake phase.
// It returns zero on success, or an error if one occurred.
// The value NNG_EAGAIN should be returned if underlying I/O
// is required to be completed first. The framework will
// ensure that the handshake completes before sending any data
// down.
int (*handshake)(nng_tls_engine_conn *);
// recv attempts to read data (decrypted) from the connection.
// It returns 0 on success, otherwise an error. The implementation
// should return NNG_EAGAIN if I/O to the underlying stream is
// required to complete the operation. On success, the count
// is updated to reflect the number of bytes actually received.
int (*recv)(nng_tls_engine_conn *, uint8_t *, size_t *);
// send attempts to write data to the underlying connection.
// It returns zero on success, otherwise an error. The implementation
// should return NNG_EAGAIN if I/O to the underlying stream is
// required to complete the operation. On success, the count
// is updated to reflect the number of bytes actually sent.
int (*send)(nng_tls_engine_conn *, const uint8_t *, size_t *);
// verified returns true if the connection is fully
// TLS verified, false otherwise.
bool (*verified)(nng_tls_engine_conn *);
// peer_cn returns the common name of the peer
// The return string needs to be freed.
char *(*peer_cn)(nng_tls_engine_conn *);
// peer_alt_names returns the subject alternative names.
// The return string list and its strings need to be freed.
char **(*peer_alt_names)(nng_tls_engine_conn *);
} nng_tls_engine_conn_ops;
typedef struct nng_tls_engine_config_ops_s {
// size is the size of the engine's configuration object.
// The framework will allocate this on behalf of the engine.
// Typically this will be sizeof (struct nng_tls_engine_config).
size_t size;
// init prepares the configuration object object.
// The mode indicates whether the object should be
// initialized for use as a TLS server or client.
// The config passed in will be aligned on a 64-bit boundary,
// and will be initialized to zero. On success this returns
// 0, else an NNG error code.
int (*init)(nng_tls_engine_config *, nng_tls_mode);
// fini is used to tear down the configuration object.
// This will only be called on objects that have been properly
// initialized with nte_config_init.
void (*fini)(nng_tls_engine_config *);
// server is used to set the server name. This can be used in SNI,
// and will also be used on the client to validate the identity.
// If this is not set, then no verification will be performed.
int (*server)(nng_tls_engine_config *, const char *);
// auth is used to configure the authentication mode. Values:
// NNG_AUTH_MODE_NONE
// No validation of the peer is performed. Public facing
// servers often use this.
// NNG_AUTH_MODE_OPTIONAL
// The peer's identity is validated if a certificate is presented.
// This is typically useful on servers.
// NNG_AUTH_MODE_REQUIRED
// The peer's certificate must be present and is verified.
// This is standard for the client, and on servers it is used
// when client (mutual) authentication is needed.
int (*auth)(nng_tls_engine_config *, nng_tls_auth_mode);
// ca_chain sets the configuration authorities that will be
// used to validate peers. An optional CRL is supplied as well.
// Both values are C strings (NUL terminated) containing
// PEM data. There may be multiple PEM blocks. The
// CRL may be NULL if not needed.
int (*ca_chain)(nng_tls_engine_config *, const char *, const char *);
// own_cert configures our identity -- the certificate containing
// our public key, our private key (which might be encrypted), and
// potentially a password used to decrypt the private key.
// All of these are C strings. The cert may actually be a chain
// which will be presented to our peer. This function may be
// called multiple times to register different keys with different
// parameters on a server. (For example, once for RSA parameters,
// and again later with EC parameters.) The certificate and the
// private key may be presented in the same file. The implementation
// is responsible for parsing out the relevant data. If the password
// is NULL, then the key file should be unencrypted. The supplied
// password may be ignored if the key is not encrypted. Not all
// engine implementations need support encryption of the key.
int (*own_cert)(
nng_tls_engine_config *, const char *, const char *, const char *);
// psk configures a PSK identity and key. This can be called
// once for clients, or multiple times for servers. However, not all
// implementations support multiple PSKs for a server.
int (*psk)(
nng_tls_engine_config *, const char *, const uint8_t *, size_t);
// version configures the minimum and maximum TLS versions. The
// engine should default to supporting TLS1.0 through 1.2, and
// optionally 1.3 if it can. The engine should restrict the
// the requested range to what it can support -- if no version
// within the range is supported (such as if NNG_TLS_1_3 is
// specified for both min and max, and the engine lacks support
// for v1.3, then NNG_ENOTSUP should be returned.
int (*version)(
nng_tls_engine_config *, nng_tls_version, nng_tls_version);
} nng_tls_engine_config_ops;
typedef enum nng_tls_engine_version_e {
NNG_TLS_ENGINE_V0 = 0,
NNG_TLS_ENGINE_V1 = 1, // adds FIPS, TLS 1.3 support
NNG_TLS_ENGINE_V2 = 2, // adds PSK support
NNG_TLS_ENGINE_VERSION = NNG_TLS_ENGINE_V2,
} nng_tls_engine_version;
typedef struct nng_tls_engine_s {
// _version is the engine version. This for now must
// be NNG_TLS_ENGINE_VERSION. If the version does not match
// then registration of the engine will fail.
nng_tls_engine_version version;
// config_ops is the operations for TLS configuration objects.
nng_tls_engine_config_ops *config_ops;
// conn_ops is the operations for TLS connections (stream-oriented).
nng_tls_engine_conn_ops *conn_ops;
// name contains the name of the engine, for example "wolfSSL".
// It is acceptable to append a version number as well.
const char *name;
// description contains a human readable description. This can
// supply information about the backing library, for example
// "mbed TLS v2.7"
const char *description;
// fips_mode is true if the engine is in FIPS mode.
// It is expected that this will be enabled either at compile
// time, or via environment variables at engine initialization.
// FIPS mode cannot be changed once the engine is registered.
bool fips_mode;
} nng_tls_engine;
NNG_DECL int nng_tls_engine_register(const nng_tls_engine *);
// nng_tls_engine_send is called by the engine to send data over the
// underlying connection. It returns zero on success, NNG_EAGAIN if
// the operation can't be completed yet (the transport is busy and cannot
// accept more data yet), or some other error. On success the count is
// updated with the number of bytes actually sent. The first argument
// is the context structure passed in when starting the engine.
NNG_DECL int nng_tls_engine_send(void *, const uint8_t *, size_t *);
// nng_tls_engine_recv is called byu the engine to receive data over
// the underlying connection. It returns zero on success, NNG_EAGAIN
// if the operation can't be completed yet (there is no data available
// for reading), or some other error. On success the count is updated
// with the number of bytes actually received.
NNG_DECL int nng_tls_engine_recv(void *, uint8_t *, size_t *);
#endif // NNG_SUPPLEMENTAL_TLS_ENGINE_H

View File

@ -0,0 +1,152 @@
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef NNG_SUPPLEMENTAL_TLS_TLS_H
#define NNG_SUPPLEMENTAL_TLS_TLS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <nng/nng.h>
// Note that TLS functions may be stubbed out if TLS is not enabled in
// the build.
// For some transports, we need TLS configuration, including certificates
// and so forth. A TLS configuration cannot be changed once it is in use.
typedef struct nng_tls_config nng_tls_config;
typedef enum nng_tls_mode {
NNG_TLS_MODE_CLIENT = 0,
NNG_TLS_MODE_SERVER = 1,
} nng_tls_mode;
typedef enum nng_tls_auth_mode {
NNG_TLS_AUTH_MODE_NONE = 0, // No verification is performed
NNG_TLS_AUTH_MODE_OPTIONAL = 1, // Verify cert if presented
NNG_TLS_AUTH_MODE_REQUIRED = 2, // Verify cert, close if invalid
} nng_tls_auth_mode;
// TLS version numbers. We encode the major number and minor number
// as separate byte fields. No support for SSL 3.0 or earlier -- older
// versions are known to be insecure and should not be used.
// When possible applications should restrict themselves to TLS 1.2 or better.
typedef enum nng_tls_version {
NNG_TLS_1_0 = 0x301,
NNG_TLS_1_1 = 0x302,
NNG_TLS_1_2 = 0x303,
NNG_TLS_1_3 = 0x304
} nng_tls_version;
// nng_tls_config_alloc creates a TLS configuration using
// reasonable defaults. This configuration can be shared
// with multiple pipes or services/servers.
NNG_DECL int nng_tls_config_alloc(nng_tls_config **, nng_tls_mode);
// nng_tls_config_hold increments the reference count on the TLS
// configuration object. The hold can be dropped by calling
// nng_tls_config_free later.
NNG_DECL void nng_tls_config_hold(nng_tls_config *);
// nng_tls_config_free drops the reference count on the TLS
// configuration object, and if zero, deallocates it.
NNG_DECL void nng_tls_config_free(nng_tls_config *);
// nng_tls_config_server_name sets the server name. This is
// called by clients to set the name that the server supplied
// certificate should be matched against. This can also cause
// the SNI to be sent to the server to tell it which cert to
// use if it supports more than one.
NNG_DECL int nng_tls_config_server_name(nng_tls_config *, const char *);
// nng_tls_config_ca_cert configures one or more CAs used for validation
// of peer certificates. Multiple CAs (and their chains) may be configured
// by either calling this multiple times, or by specifying a list of
// certificates as concatenated data. The final argument is an optional CRL
// (revocation list) for the CA, also in PEM. Both PEM strings are ASCIIZ
// format (except that the CRL may be NULL).
NNG_DECL int nng_tls_config_ca_chain(
nng_tls_config *, const char *, const char *);
// nng_tls_config_own_cert is used to load our own certificate and public
// key. For servers, this may be called more than once to configure multiple
// different keys, for example with different algorithms depending on what
// the peer supports. On the client, only a single option is available.
// The first two arguments are the cert (or validation chain) and the
// key as PEM format ASCIIZ strings. The final argument is an optional
// password and may be NULL.
NNG_DECL int nng_tls_config_own_cert(
nng_tls_config *, const char *, const char *, const char *);
// nng_tls_config_key is used to pass our own private key.
NNG_DECL int nng_tls_config_key(nng_tls_config *, const uint8_t *, size_t);
// nng_tls_config_pass is used to pass a password used to decrypt
// private keys that are encrypted.
NNG_DECL int nng_tls_config_pass(nng_tls_config *, const char *);
// nng_tls_config_auth_mode is used to configure the authentication mode use.
// The default is that servers have this off (i.e. no client authentication)
// and clients have it on (they verify the server), which matches typical
// practice.
NNG_DECL int nng_tls_config_auth_mode(nng_tls_config *, nng_tls_auth_mode);
// nng_tls_config_ca_file is used to pass a CA chain and optional CRL
// via the filesystem. If CRL data is present, it must be contained
// in the file, along with the CA certificate data. The format is PEM.
// The path name must be a legal file name.
NNG_DECL int nng_tls_config_ca_file(nng_tls_config *, const char *);
// nng_tls_config_cert_key_file is used to pass our own certificate and
// private key data via the filesystem. Both the key and certificate
// must be present as PEM blocks in the same file. A password is used to
// decrypt the private key if it is encrypted and the password supplied is not
// NULL. This may be called multiple times on servers, but only once on a
// client. (Servers can support multiple different certificates and keys for
// different cryptographic algorithms. Clients only get one.)
NNG_DECL int nng_tls_config_cert_key_file(
nng_tls_config *, const char *, const char *);
// nng_tls_config_psk_identity is used to pass TLS PSK parameters. The
// identity, and an associated key. Clients can only do this once.
// Servers can do it multiple times, potentially, to provide for different
// keys for different client identities. There is no way to remove these
// from a configuration.
NNG_DECL int nng_tls_config_psk(
nng_tls_config *, const char *, const uint8_t *, size_t);
// Configure supported TLS version. By default we usually restrict
// ourselves to TLS 1.2 and newer. We do not support older versions.
// If the implementation cannot support any version (for example if
// the minimum requested is 1.3 but the TLS implementation lacks support
// for TLS 1.3) then NNG_ENOTSUP will be returned.
NNG_DECL int nng_tls_config_version(
nng_tls_config *, nng_tls_version, nng_tls_version);
// nng_tls_engine_name returns the "name" of the TLS engine. If no
// TLS engine support is enabled, then "none" is returned.
NNG_DECL const char *nng_tls_engine_name(void);
// nng_tls_engine_description returns the "description" of the TLS engine.
// If no TLS engine support is enabled, then an empty string is returned.
NNG_DECL const char *nng_tls_engine_description(void);
// nng_tls_engine_fips_mode returns true if the engine is in FIPS 140-2 mode.
NNG_DECL bool nng_tls_engine_fips_mode(void);
#ifdef __cplusplus
}
#endif
#endif // NNG_SUPPLEMENTAL_TLS_TLS_H

View File

@ -0,0 +1,42 @@
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef NNG_SUPPLEMENTAL_UTIL_IDHASH_H
#define NNG_SUPPLEMENTAL_UTIL_IDHASH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nng/nng.h>
typedef struct nng_id_map_s nng_id_map;
#define NNG_MAP_RANDOM 1
// For NanoNNG
NNG_DECL void nng_id_map_foreach(
nng_id_map *map, void (*)(void *, void *));
NNG_DECL void nng_id_map_foreach2(nng_id_map *map,
void (*)(void *, void *, void *), void *);
NNG_DECL int nng_id_map_alloc(
nng_id_map **map, uint64_t lo, uint64_t hi, int flags);
NNG_DECL void nng_id_map_free(nng_id_map *map);
NNG_DECL void *nng_id_get(nng_id_map *, uint64_t);
NNG_DECL int nng_id_set(nng_id_map *, uint64_t, void *);
NNG_DECL int nng_id_alloc(nng_id_map *, uint64_t *, void *);
NNG_DECL int nng_id_remove(nng_id_map *, uint64_t);
NNG_DECL bool nng_id_visit(nng_id_map *, uint64_t *, void **, uint32_t *);
#ifdef __cplusplus
}
#endif
#endif // NNG_SUPPLEMENTAL_IDHASH_IDHASH_H

View File

@ -0,0 +1,50 @@
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef NNG_SUPPLEMENTAL_UTIL_OPTIONS_H
#define NNG_SUPPLEMENTAL_UTIL_OPTIONS_H
#include <stdbool.h>
#include <nng/nng.h>
#ifdef __cplusplus
extern "C" {
#endif
// This is a relatively simple "options parsing" library, used to
// parse command line options. We would use getopt(3), but there are
// two problems with getopt(3). First, it isn't available on all
// platforms (especially Win32), and second, it doesn't support long
// options. We *exclusively* support long options. POSIX style
// short option clustering is *NOT* supported.
struct nng_optspec {
const char *o_name; // Long style name (may be NULL for short only)
int o_short; // Short option (no clustering!)
int o_val; // Value stored on a good parse (>0)
bool o_arg; // Option takes an argument if true
};
typedef struct nng_optspec nng_optspec;
// Call with *optidx set to 1 to start parsing for a standard program.
// The val will store the value of the matched "o_val", optarg will be
// set to match the option string, and optidx will be increment appropriately.
// Returns -1 when the end of options is reached, 0 on success, or
// NNG_EINVAL if the option parse is invalid for any reason.
NNG_DECL int nng_opts_parse(int argc, char *const *argv,
const nng_optspec *opts, int *val, char **optarg, int *optidx);
#ifdef __cplusplus
}
#endif
#endif // NNG_SUPPLEMENTAL_UTIL_OPTIONS_H

View File

@ -0,0 +1,119 @@
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef NNG_SUPPLEMENTAL_UTIL_PLATFORM_H
#define NNG_SUPPLEMENTAL_UTIL_PLATFORM_H
// The declarations in this file are provided to assist with application
// portability. Conceptually these APIs are based on work we have already
// done for NNG internals, and we find that they are useful in building
// portable applications.
// If it is more natural to use native system APIs like pthreads or C11
// APIs or Windows APIs, then by all means please feel free to simply
// ignore this.
#include <stddef.h>
#include <stdint.h>
#include <nng/nng.h>
#ifdef __cplusplus
extern "C" {
#endif
// Return unix timestamp (milliseconds) .
NNG_DECL nng_time nng_timestamp(void);
// Get current process Id.
NNG_DECL int nng_getpid();
// nng_rwlock is a rwlock. TODO more comments
typedef struct nng_rwlock nng_rwlock;
NNG_DECL int nng_rwlock_alloc(nng_rwlock **);
NNG_DECL void nng_rwlock_free(nng_rwlock *);
NNG_DECL void nng_rwlock_rdlock(nng_rwlock *);
NNG_DECL void nng_rwlock_rwlock(nng_rwlock *);
NNG_DECL void nng_rwlock_unlock(nng_rwlock *);
//
// Atomics support. This will evolve over time.
//
// nng_atomic_flag supports only test-and-set and reset operations.
// This can be implemented without locks on any reasonable system, and
// it corresponds to C11 atomic flag.
typedef struct nni_atomic_flag nng_atomic_flag;
NNG_DECL bool nng_atomic_flag_test_and_set(nng_atomic_flag *);
NNG_DECL void nng_atomic_flag_reset(nng_atomic_flag *);
// nng_atomic_bool is for boolean flags that need to be checked without
// changing their value. This might require a lock on some systems.
typedef struct nni_atomic_bool nng_atomic_bool;
NNG_DECL int nng_atomic_alloc_bool(nng_atomic_bool **v);
NNG_DECL void nng_atomic_free_bool(nng_atomic_bool *v);
NNG_DECL void nng_atomic_set_bool(nng_atomic_bool *, bool);
NNG_DECL bool nng_atomic_get_bool(nng_atomic_bool *);
NNG_DECL bool nng_atomic_swap_bool(nng_atomic_bool *, bool);
typedef struct nni_atomic_u64 nng_atomic_u64;
NNG_DECL int nng_atomic_alloc64(nng_atomic_u64 **v);
NNG_DECL void nng_atomic_free64(nng_atomic_u64 *v);
NNG_DECL void nng_atomic_add64(nng_atomic_u64 *, uint64_t);
NNG_DECL void nng_atomic_sub64(nng_atomic_u64 *, uint64_t);
NNG_DECL uint64_t nng_atomic_get64(nng_atomic_u64 *);
NNG_DECL void nng_atomic_set64(nng_atomic_u64 *, uint64_t);
NNG_DECL uint64_t nng_atomic_swap64(nng_atomic_u64 *, uint64_t);
NNG_DECL uint64_t nng_atomic_dec64_nv(nng_atomic_u64 *);
NNG_DECL void nng_atomic_inc64(nng_atomic_u64 *);
// nng_atomic_cas64 is a compare and swap. The second argument is the
// value to compare against, and the third is the new value. Returns
// true if the value was set.
NNG_DECL bool nng_atomic_cas64(nng_atomic_u64 *, uint64_t, uint64_t);
// In a lot of circumstances, we want a simple atomic reference count,
// or atomic tunable values for integers like queue lengths or TTLs.
// These native integer forms should be preferred over the 64 bit versions
// unless larger bit sizes are truly needed. They will be more efficient
// on many platforms.
typedef struct nni_atomic_int nng_atomic_int;
NNG_DECL int nng_atomic_alloc(nng_atomic_int **v);
NNG_DECL void nng_atomic_free(nng_atomic_int *v);
NNG_DECL void nng_atomic_add(nng_atomic_int *, int);
NNG_DECL void nng_atomic_sub(nng_atomic_int *, int);
NNG_DECL int nng_atomic_get(nng_atomic_int *);
NNG_DECL void nng_atomic_set(nng_atomic_int *, int);
NNG_DECL int nng_atomic_swap(nng_atomic_int *, int);
NNG_DECL int nng_atomic_dec_nv(nng_atomic_int *);
NNG_DECL void nng_atomic_dec(nng_atomic_int *);
NNG_DECL void nng_atomic_inc(nng_atomic_int *);
// nng_atomic_cas is a compare and swap. The second argument is the
// value to compare against, and the third is the new value. Returns
// true if the value was set.
NNG_DECL bool nng_atomic_cas(nng_atomic_int *, int, int);
// atomic pointers. We only support a few operations.
typedef struct nni_atomic_ptr nng_atomic_ptr;
NNG_DECL int nng_atomic_alloc_ptr(nng_atomic_ptr **v);
NNG_DECL void nng_atomic_free_ptr(nng_atomic_ptr *v);
NNG_DECL void nng_atomic_set_ptr(nng_atomic_ptr *, void *);
NNG_DECL void * nng_atomic_get_ptr(nng_atomic_ptr *);
#ifdef __cplusplus
}
#endif
#endif // NNG_SUPPLEMENTAL_UTIL_PLATFORM_H