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,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