OCT 配置文件增加DHCP Server配置支持

This commit is contained in:
huangxin 2022-11-17 15:27:32 +08:00
parent da06daecd6
commit ff84d9e173
9 changed files with 4219 additions and 42 deletions

View File

@ -76,23 +76,23 @@ application:
}; };
# DHCP Server Config # DHCP Server Config
#dhcp_server: { dhcp_server: {
# listen_on = ["192.168.30.1", "192.168.100.1"]; listen_on = ["192.168.30.1", "192.168.100.1"];
# http_client = ["192.168.30.1", "192.168.30.110", "192.168.100.1", "192.168.100.110"]; http_client = ["192.168.30.1", "192.168.30.110", "192.168.100.1", "192.168.100.110"];
#
# range_set: ( range_set: (
# { dhcp_range = "192.168.30.110-192.168.30.120"; { dhcp_range = "192.168.30.110-192.168.30.120";
# subnet_mask = "255.255.255.0"; subnet_mask = "255.255.255.0";
# domain_server = "114.114.114.114, 8.8.8.8"; domain_server = "114.114.114.114,8.8.8.8";
# gateway = "192.168.30.1"; gateway = "192.168.30.1";
# lease_time = 360; lease_time = 360;
# }, },
# { dhcp_range = "192.168.100.110-192.168.100.200"; { dhcp_range = "192.168.100.110-192.168.100.200";
# subnet_mask = "255.255.255.0"; subnet_mask = "255.255.255.0";
# domain_server = "114.114.114.114, 8.8.8.8"; domain_server = "114.114.114.114,8.8.8.8";
# gateway = "192.168.100.1"; gateway = "192.168.100.1";
# lease_time = 360; lease_time = 360;
# } }
# ); );
#}; };
} }

View File

@ -8,7 +8,7 @@ INCLUDE_DIRECTORIES(include
./ ./include ../lwip/src/include ../lwip/src/arch_linux/include ../include ./ ./include ../lwip/src/include ../lwip/src/arch_linux/include ../include
../httpserver/include ../httpserver/src/haywire ../httpserver/src/haywire/configuration ../httpserver/include ../httpserver/src/haywire ../httpserver/src/haywire/configuration
${COMMON_INCLUDE}) ${COMMON_INCLUDE})
FILE(GLOB C_HEADS include/*.h include/uthash/*.h include/s2j/*.h) FILE(GLOB C_HEADS include/*.h include/uthash/*.h include/s2j/*.h vector/*.h)
AUX_SOURCE_DIRECTORY(json C_SRC) AUX_SOURCE_DIRECTORY(json C_SRC)
@ -24,9 +24,12 @@ AUX_SOURCE_DIRECTORY(mq C_SRC)
AUX_SOURCE_DIRECTORY(cmdline C_SRC) AUX_SOURCE_DIRECTORY(cmdline C_SRC)
AUX_SOURCE_DIRECTORY(crypto C_SRC) AUX_SOURCE_DIRECTORY(crypto C_SRC)
AUX_SOURCE_DIRECTORY(hardware C_SRC) AUX_SOURCE_DIRECTORY(hardware C_SRC)
AUX_SOURCE_DIRECTORY(vector C_SRC)
SET(CMAKE_C_STANDARD 99) SET(CMAKE_C_STANDARD 99)
SET_SOURCE_FILES_PROPERTIES(vector/zvector.c PROPERTIES COMPILE_FLAGS "-Wall -Wextra -flto")
ADD_DEFINITIONS(-DBUILD_VERSION="${GIT_VERSION}" ${COMMON_DEFINE}) ADD_DEFINITIONS(-DBUILD_VERSION="${GIT_VERSION}" ${COMMON_DEFINE})

View File

@ -14,6 +14,7 @@
#include "user_errno.h" #include "user_errno.h"
#include "crypto.h" #include "crypto.h"
#include "hardware.h" #include "hardware.h"
#include "zvector/zvector.h"
#define CFG_INT_VALUE(p) (p->value.longValue) #define CFG_INT_VALUE(p) (p->value.longValue)
#define CFG_BOOL_VALUE(p) (p->value.longValue == FALSE ? FALSE : TRUE) #define CFG_BOOL_VALUE(p) (p->value.longValue == FALSE ? FALSE : TRUE)
@ -65,13 +66,24 @@ do {
ADD_CFG_ITEM(CFG_HTTP_SVR_ADDR, "application.http_svr.listen_addr", VALUE_TYPE_STRING, "0.0.0.0", "Network address to listen on"); \ ADD_CFG_ITEM(CFG_HTTP_SVR_ADDR, "application.http_svr.listen_addr", VALUE_TYPE_STRING, "0.0.0.0", "Network address to listen on"); \
ADD_CFG_ITEM(CFG_HTTP_SVR_PORT, "application.http_svr.listen_port", VALUE_TYPE_INTEGRAL, "6789", "Network port to listen on"); \ ADD_CFG_ITEM(CFG_HTTP_SVR_PORT, "application.http_svr.listen_port", VALUE_TYPE_INTEGRAL, "6789", "Network port to listen on"); \
ADD_CFG_ITEM(CFG_HTTP_SVR_TCP_NODELAY, "application.http_svr.tcp_nodelay", VALUE_TYPE_BOOL, "1", "TCP delay switch"); \ ADD_CFG_ITEM(CFG_HTTP_SVR_TCP_NODELAY, "application.http_svr.tcp_nodelay", VALUE_TYPE_BOOL, "1", "TCP delay switch"); \
ADD_CFG_ITEM(CFG_DHCP_LISTEN_ON, "application.dhcp_server.listen_on", VALUE_TYPE_ARRAY_STR, "", "DHCP listen interface"); \
ADD_CFG_ITEM(CFG_DHCP_HTTP_CLIENT, "application.dhcp_server.http_client", VALUE_TYPE_ARRAY_STR, "", "DHCP http server client write list"); \
ADD_CFG_ITEM(CFG_DHCP_RANGE_SET, "application.dhcp_server.range_set", VALUE_TYPE_ARRAY_OBJ, "", "DHCP IP pool"); \
} while (0)// clang-format on } while (0)// clang-format on
typedef struct {
char rangAddr[256];
char subnet[20];
char dnsSvr[256];
char gateway[20];
unsigned int lease;
} OBJ_DHCP_RNG, *POBJ_DHCP_RNG;
typedef union { typedef union {
long long longValue; long long longValue;
char *strValue; char *strValue;
long double floatValue; long double floatValue;
vector array;
} CFG_VALUE, *PCFG_VALUE; } CFG_VALUE, *PCFG_VALUE;
typedef struct { typedef struct {
@ -173,6 +185,103 @@ static double load_float_value(const char *pKeyName, double defValue) {
return val; return val;
} }
static int cmp_str(const void *a, const void *b) {
return strcmp((const char *)a, (const char *)b);
}
static int load_array_str(const char *pKeyName, PCONFIG_ITEM pValue) {
int i;
config_setting_t *pItem = config_lookup(&g_cfgContent, pKeyName);
if (pItem) {
for (i = 0; i < config_setting_length(pItem); i++) {
const char *pVal = config_setting_get_string_elem(pItem, i);
if (pVal) {
zvect_index idx = 0;
if (!vect_bsearch(pValue->value.array, pVal, cmp_str, &idx)) {
vect_push(pValue->value.array, pVal);
pValue->isChanged = TRUE;
}
}
}
vect_shrink(pValue->value.array);
return ERR_SUCCESS;
}
return -ERR_ITEM_UNEXISTS;
}
static int cmp_dhcp_obj(const void *a, const void *b) {
POBJ_DHCP_RNG pV1 = (POBJ_DHCP_RNG)a;
POBJ_DHCP_RNG pV2 = (POBJ_DHCP_RNG)b;
if (strcmp(pV1->rangAddr, pV2->rangAddr) == 0 && strcmp(pV1->subnet, pV2->subnet) == 0
&& strcmp(pV1->dnsSvr, pV2->dnsSvr) == 0 && strcmp(pV1->gateway, pV2->gateway) == 0
&& pV1->lease == pV2->lease) {
return 0;
}
return -1;
}
static int load_array_obj(const char *pKeyName, PCONFIG_ITEM pValue) {
int i;
config_setting_t *pItem = config_lookup(&g_cfgContent, pKeyName);
if (!pItem) {
return -ERR_ITEM_UNEXISTS;
}
for (i = 0; i < config_setting_length(pItem); i++) {
OBJ_DHCP_RNG v, k;
config_setting_t *pObj = config_setting_get_elem(pItem, i);
switch (pValue->cfgId) {
case CFG_DHCP_RANGE_SET: {
zvect_index idx = -1;
const char *rangAddr, *subnet, *dnsSvr, *gateway;
memset(&v, 0, sizeof(OBJ_DHCP_RNG));
if (config_setting_lookup_string(pObj, "dhcp_range", &rangAddr)) {
strcpy(v.rangAddr, rangAddr);
}
if (config_setting_lookup_string(pObj, "subnet_mask", &subnet)) {
strcpy(v.subnet, subnet);
}
if (config_setting_lookup_string(pObj, "domain_server", &dnsSvr)) {
strcpy(v.dnsSvr, dnsSvr);
}
if (config_setting_lookup_string(pObj, "gateway", &gateway)) {
strcpy(v.gateway, gateway);
}
if (!config_setting_lookup_int(pObj, "lease_time", (int *)&v.lease)) {
v.lease = 0xFFFFFFFF;
}
if (pValue->value.array == NULL) {
pValue->value.array = vect_create(128, sizeof(OBJ_DHCP_RNG), ZV_SEC_WIPE);
}
if (!vect_bsearch(pValue->value.array, &v, cmp_dhcp_obj, &idx)) {
memcpy(&k, &v, sizeof(OBJ_DHCP_RNG));
vect_push(pValue->value.array, &k);
pValue->isChanged = TRUE;
printf("++++Add %s\n", k.rangAddr);
}
} break;
default:
break;
}
}
return ERR_SUCCESS;
}
static int setConfigItemValue(PCONFIG_ITEM pItem, const char *pValue) { static int setConfigItemValue(PCONFIG_ITEM pItem, const char *pValue) {
errno = 0; errno = 0;
@ -200,6 +309,11 @@ static int setConfigItemValue(PCONFIG_ITEM pItem, const char *pValue) {
} }
pItem->value.floatValue = val; pItem->value.floatValue = val;
} else if (pItem->valType == VALUE_TYPE_ARRAY_STR) {
pItem->value.array = vect_create(128, 512, ZV_SEC_WIPE);
} else if (pItem->valType == VALUE_TYPE_ARRAY_OBJ) {
pItem->value.array = NULL;
vect_create(128, sizeof(int), ZV_SEC_WIPE | ZV_BYREF);
} else { } else {
return -ERR_UN_SUPPORT; return -ERR_UN_SUPPORT;
} }
@ -323,6 +437,14 @@ static void refreshCfgFileCb() {
} }
break; break;
case VALUE_TYPE_ARRAY_STR:
load_array_str(pItem->pcfgKey, pItem);
break;
case VALUE_TYPE_ARRAY_OBJ:
load_array_obj(pItem->pcfgKey, pItem);
break;
default: default:
break; break;
} }
@ -338,9 +460,11 @@ static void refreshCfgFileCb() {
} }
const char *config_item_dump_fmt(const char *titleMessage) { const char *config_item_dump_fmt(const char *titleMessage) {
int i;
const char *pResp; const char *pResp;
PCONFIG_ITEM pItem, pTmp; PCONFIG_ITEM pItem, pTmp;
sds tmp, tmp2; char tmp2[256];
sds tmp;
sds s = sdsempty(); sds s = sdsempty();
if (titleMessage && strlen(titleMessage) > 0) { if (titleMessage && strlen(titleMessage) > 0) {
@ -349,23 +473,23 @@ const char *config_item_dump_fmt(const char *titleMessage) {
s = sdscat(s, s = sdscat(s,
"--------------------------------------------------------------------------------" "--------------------------------------------------------------------------------"
"---------------------------------------------------\n"); "-----------------------------------------------------------------------\n");
s = sdscat(s, s = sdscat(s,
"| id | Key Name | Configuration file key |" "| id | Key Name | Configuration file key |"
" value |\n"); " value |\n");
s = sdscat(s, s = sdscat(s,
"--------------------------------------------------------------------------------" "--------------------------------------------------------------------------------"
"---------------------------------------------------\n"); "-----------------------------------------------------------------------\n");
HASH_ITER(hh, g_pConfigItem, pItem, pTmp) { HASH_ITER(hh, g_pConfigItem, pItem, pTmp) {
tmp2 = sdsempty(); memset(tmp2, 0, 256);
tmp2 = sdscatprintf(tmp2, "%s%s", cfg_is_upgrade(pItem) ? "*" : " ", pItem->pStrId); sprintf(tmp2, "%s%s", cfg_is_upgrade(pItem) ? "*" : " ", pItem->pStrId);
switch (pItem->valType) { switch (pItem->valType) {
case VALUE_TYPE_BOOL: case VALUE_TYPE_BOOL:
s = sdscatprintf(s, s = sdscatprintf(s,
"|%4d | %-25s | %-45s | %-44s |\n", "|%4d | %-25s | %-45s | %-64s |\n",
pItem->cfgId, pItem->cfgId,
tmp2, tmp2,
pItem->pcfgKey, pItem->pcfgKey,
@ -373,11 +497,11 @@ const char *config_item_dump_fmt(const char *titleMessage) {
break; break;
case VALUE_TYPE_INTEGRAL: case VALUE_TYPE_INTEGRAL:
s = sdscatprintf( s = sdscatprintf(
s, "|%4d | %-25s | %-45s | %-44lld |\n", pItem->cfgId, tmp2, pItem->pcfgKey, CFG_INT_VALUE(pItem)); s, "|%4d | %-25s | %-45s | %-64lld |\n", pItem->cfgId, tmp2, pItem->pcfgKey, CFG_INT_VALUE(pItem));
break; break;
case VALUE_TYPE_FLOAT: case VALUE_TYPE_FLOAT:
s = sdscatprintf(s, s = sdscatprintf(s,
"|%4d | %-25s | %-45s | %-44Lf |\n", "|%4d | %-25s | %-45s | %-64Lf |\n",
pItem->cfgId, pItem->cfgId,
tmp2, tmp2,
pItem->pcfgKey, pItem->pcfgKey,
@ -386,22 +510,74 @@ const char *config_item_dump_fmt(const char *titleMessage) {
case VALUE_TYPE_STRING: case VALUE_TYPE_STRING:
tmp = sdsempty(); tmp = sdsempty();
tmp = sdscatprintf(tmp, "\"%s\"", CFG_STRING_VALUE(pItem)); tmp = sdscatprintf(tmp, "\"%s\"", CFG_STRING_VALUE(pItem));
if (sdslen(tmp) > 43) { if (sdslen(tmp) > 63) {
sdsrange(tmp, 0, 39); sdsrange(tmp, 0, 59);
sdscat(tmp, "...\""); tmp = sdscat(tmp, "...\"");
} }
s = sdscatprintf(s, "|%4d | %-25s | %-45s | %-44s |\n", pItem->cfgId, tmp2, pItem->pcfgKey, tmp); s = sdscatprintf(s, "|%4d | %-25s | %-45s | %-64s |\n", pItem->cfgId, tmp2, pItem->pcfgKey, tmp);
sdsfree(tmp); sdsfree(tmp);
break; break;
case VALUE_TYPE_ARRAY_STR:
tmp = sdsempty();
tmp = sdscat(tmp, "[");
for (i = 0; i < vect_size(pItem->value.array); i++) {
const char *p = (const char *)vect_get_at(pItem->value.array, i);
if (p) {
tmp = sdscatfmt(tmp, "\"%s\",", p);
}
}
sdsrange(tmp, 0, -2);
tmp = sdscat(tmp, "]");
//tmp = sdscatprintf(tmp, "\"%s\"", CFG_STRING_VALUE(pItem));
if (sdslen(tmp) > 63) {
sdsrange(tmp, 0, 58);
tmp = sdscat(tmp, "...\"]");
}
s = sdscatprintf(s, "|%4d | %-25s | %-45s | %-64s |\n", pItem->cfgId, tmp2, pItem->pcfgKey, tmp);
sdsfree(tmp);
break;
case VALUE_TYPE_ARRAY_OBJ:
for (i = 0; i < vect_size(pItem->value.array); i++) {
POBJ_DHCP_RNG p = (POBJ_DHCP_RNG)vect_get_at(pItem->value.array, i);
if (!p) {
continue;
}
sds title = sdsempty();
sds keyRang = sdsempty();
sds keySubnet = sdsempty();
sds keyDns = sdsempty();
sds keyGateway = sdsempty();
title = sdscatprintf(title, "%s[%d]", pItem->pcfgKey, i);
keyRang = sdscatprintf(keyRang, "\"%s\"", p->rangAddr);
keySubnet = sdscatprintf(keySubnet, "\"%s\"", p->subnet);
keyDns = sdscatprintf(keyDns, "\"%s\"", p->dnsSvr);
keyGateway = sdscatprintf(keyGateway, "\"%s\"", p->gateway);
s = sdscatprintf(s, "|%4d | %-25s | %-45s | %-64s |\n", pItem->cfgId, tmp2, title, "");
s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .dhcp_range", keyRang);
s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .subnet_mask", keySubnet);
s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .domain_server", keyDns);
s = sdscatprintf(s, "| | %-25s | %-45s | %-64s |\n", "", " .gateway", keyGateway);
s = sdscatprintf(s, "| | %-25s | %-45s | %-64u |\n", "", " .lease_time", p->lease);
sdsfree(title);
sdsfree(keyRang);
sdsfree(keySubnet);
sdsfree(keyDns);
sdsfree(keyGateway);
}
break;
default: default:
break; break;
} }
sdsfree(tmp2);
} }
s = sdscat(s, s = sdscat(s,
"--------------------------------------------------------------------------------" "--------------------------------------------------------------------------------"
"---------------------------------------------------\n"); "-----------------------------------------------------------------------\n");
pResp = strdup(s); pResp = strdup(s);
sdsfree(s); sdsfree(s);
@ -494,7 +670,6 @@ const char *cfg_get_string_value(CONFIG_ITEM_ID id) {
} }
} }
int init_config_system(const char *pCfgFile, const char *pKey) { int init_config_system(const char *pCfgFile, const char *pKey) {
if (!file_exists(pCfgFile)) { if (!file_exists(pCfgFile)) {
dzlog_error("Configuration file [%s] not exists\n", pCfgFile); dzlog_error("Configuration file [%s] not exists\n", pCfgFile);

View File

@ -11,11 +11,12 @@ extern "C" {
#define DEFAULT_INTEGRAL_ERR_VALUE (0x0AFFFFAA) #define DEFAULT_INTEGRAL_ERR_VALUE (0x0AFFFFAA)
typedef enum { typedef enum {
VALUE_TYPE_INTEGRAL = 0, VALUE_TYPE_INTEGRAL = 0,
VALUE_TYPE_FLOAT = 1, VALUE_TYPE_FLOAT = 1,
VALUE_TYPE_STRING = 2, VALUE_TYPE_STRING = 2,
VALUE_TYPE_BOOL = 3, VALUE_TYPE_BOOL = 3,
VALUE_TYPE_ARRAY = 4, VALUE_TYPE_ARRAY_STR = 4,
VALUE_TYPE_ARRAY_OBJ = 5,
} CONFIG_VALUE_TYPE; } CONFIG_VALUE_TYPE;
typedef enum { typedef enum {
@ -50,6 +51,9 @@ typedef enum {
CFG_HTTP_SVR_ADDR = 29, CFG_HTTP_SVR_ADDR = 29,
CFG_HTTP_SVR_PORT = 30, CFG_HTTP_SVR_PORT = 30,
CFG_HTTP_SVR_TCP_NODELAY = 31, CFG_HTTP_SVR_TCP_NODELAY = 31,
CFG_DHCP_LISTEN_ON = 32,
CFG_DHCP_HTTP_CLIENT = 33,
CFG_DHCP_RANGE_SET = 34,
CONFIG_ITEM_ID_MAX CONFIG_ITEM_ID_MAX
} CONFIG_ITEM_ID; } CONFIG_ITEM_ID;

View File

@ -0,0 +1,642 @@
/*
* Name: ZVector (Header)
* Purpose: Library to use Dynamic Arrays (Vectors) in C Language
* Author: Paolo Fabio Zaino
* Domain: General
* License: Copyright by Paolo Fabio Zaino, all rights reserved
* Distributed under MIT license
*
*/
#ifndef SRC_ZVECTOR_H_
#define SRC_ZVECTOR_H_
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#ifdef _cplusplus
extern "C" {
#endif
// Requires standard C libraries:
#include <stdarg.h>
#include <stdlib.h>
// First library included is zvector_checks,
// so we know on which platform and which features
// we can use:
#include "zvector_checks.h"
// Include vector configuration header
#include "zvector_config.h"
// Declare required structs:
typedef struct p_vector * vector;
// Declare required enums:
/*
* Vector Properties Flags can be used to tell ZVector
* which types of properties we want to enable for each
* given vector we are creating.
* Each vector can have multiple properties enabled at the
* same time, you can use the typical C form to specify multiple
* properties for the same vector:
*
* ZV_SEC_WIPE | ZV_BYREF
*
* The above will create a vector that supports passing items to
* it by reference (instead of copying them into the vector) and
* having Secure Wipe enabled, so that when an element is deleted
* its reference will also be fully zeroed out before freeing it.
*/
enum ZVECT_PROPERTIES {
ZV_NONE = 0, // Sets or Resets all vector's properties to 0.
ZV_SEC_WIPE = 1 << 0, // Sets the vector for automatic Secure Wipe of items.
ZV_BYREF = 1 << 1, // Sets the vector to store items by reference instead of copying them as per default.
ZV_CIRCULAR = 1 << 2, // Sets the vector to be a circular vector (so it will not grow in capacity automatically). Elements will be overwritten as in typical circular buffers!
ZV_NOLOCKING = 1 << 3, // This Property means the vector will not use mutexes, be careful using it!
};
enum ZVECT_ERR {
ZVERR_VECTUNDEF = -1,
ZVERR_IDXOUTOFBOUND = -2,
ZVERR_OUTOFMEM = -3,
ZVERR_VECTCORRUPTED = -4,
ZVERR_RACECOND = -5,
ZVERR_VECTTOOSMALL = -6,
ZVERR_VECTDATASIZE = -7,
ZVERR_VECTEMPTY = -8,
ZVERR_OPNOTALLOWED = -9
};
/*****************************
** Public API declaration: **
*****************************/
// Vector construction/Destruction and memory control:
/*
* vect_create creates and returns a new vector
* of the specified "capacity", with a storage area that
* can store items of "item_size" size and, if we want to
* have an automatic secure erasing enabled (ZV_SEC_WIPE
* ), we can simply pass ZV_SAFE_WIPE (or other flags too)
* after item_size. Flags syntax is the usual C flag sets:
* ZV_SEC_WIPE | ZV_BYREF etc.
*/
vector vect_create(zvect_index capacity, size_t item_size, uint32_t properties);
/*
* vect_destroy destroys the specified vector and, if
* secure_wipe is enabled, also ensure erasing each single
* value in the vector before destroying it.
*/
void vect_destroy(vector);
/*
* vect_shrink is useful when operating on systems with
* small amount of RAM, and it basically allows to shrink
* the vector capacity to match the actual used size, to
* save unused memory locations.
*/
void vect_shrink(vector const v);
#define vect_shrink_to_fit(x) vect_shrink(x)
/*
* vect_set_wipefunct allows you to pass ZVector a pointer to a custom
* function (of your creation) to securely wipe data from the vector v
* when automatic safe wipe is called.
*/
void vect_set_wipefunct(vector const v, void (*f1)(const void *item, size_t size));
// Vector state checks:
/*
* vect_is_empty returns true if the vector is empty
* and false if the vector is NOT empty.
*/
bool vect_is_empty(vector const v);
/*
* vect_size returns the actual size (the number of)
* USED slots in the vector storage.
*/
zvect_index vect_size(vector const v);
/*
* vect_clear clears out a vector and also resizes it
* to its initial capacity.
*/
void vect_clear(vector const v);
bool vect_check_status(const vector v, zvect_index flag_id);
bool vect_set_status(const vector v, zvect_index flag_id);
bool vect_clear_status(const vector v, zvect_index flag_id);
#if ( ZVECT_THREAD_SAFE == 1 )
// Vector Thread Safe functions:
/*
* vect_lock_enable allows you to enable thread safe
* code at runtime. It doesn't lock anything, it just
* enables globally ZVector thread safe code at
* runtime.
*
* Example of use:
* vect_lock_enable;
*/
void vect_lock_enable(void);
/*
* vect_lock_disable allows you to disable thread safe
* code at runtime. It doesn't lock anything, it just
* disables globally ZVector thread safe code at
* runtime.
*
* Example of use:
* vect_lock_disable;
*/
void vect_lock_disable(void);
/*
* vect_lock allows you to lock the given vector to
* have exclusive write access from your own thread.
* When you lock a vector directly then ZVector will
* NOT use its internal locking mechanism for that
* specific vector.
*
* Example of use: To lock a vector called v
* vect_lock(v);
*/
zvect_retval vect_lock(vector const v);
/*
* vect_trylock will try to lock the given vector to
* have exclusive write access from your own thread.
* When you lock a vector directly then ZVector will
* NOT use its internal locking mechanism for that
* specific vector.
*
* Example of use: To lock a vector called v
* vect_trylock(v);
*/
zvect_retval vect_trylock(vector const v);
/*
* vect_lock allows you to unlock the given vector that
* you have previously locked with vect_lock.
*
* Example of use: To unlock a vector called v
* vect_unlock(v);
*/
zvect_retval vect_unlock(vector const v);
/* TODO:
* zvect_retval vect_wait_for_signal(const vector v);
*
* zvect_retval vect_lock_after_signal(const vector v);
*/
zvect_retval vect_move_on_signal(vector const v1, vector v2,
const zvect_index s2,
const zvect_index e2,
zvect_retval (*f2)(void *, void *));
zvect_retval vect_send_signal(const vector v);
zvect_retval vect_broadcast_signal(const vector v);
zvect_retval vect_sem_wait(const vector v);
zvect_retval vect_sem_post(const vector v);
#endif // ( ZVECT_THREAD_SAFE == 1 )
/////////////////////////////////////////////////////
// Vector Data Storage functions:
/*
* vect_push and vect_pop are used to use the
* vector as a dynamic stack.
*
* int i = 3;
* vect_push(v, &i) pushes the element 3 at the
* back of the vector v, which
* corresponds to the top of a
* Stack.
*/
void vect_push(vector const v, const void *item);
/*
* vect_pop(v) "pops" (returns) the element
* at the back of the vector as
* a regular pop would do with
* an element at the top of a
* stack. Remember when you use
* vect_pop the element you
* receive is also removed from
* the vector!
*/
void *vect_pop(vector const v);
#define vect_pop_back(x) vect_pop(x)
/*
* vect_add adds a new item into the vector and,
* if required, will also reorganize the vector.
*
* int i = 3;
* vect_add(v, &i) will add the new item 3 in
* the vector v at the end
* (or back) of the vector v.
*/
void vect_add(vector const v, const void *item);
#define vect_push_back(x, y) vect_add(x, y)
/*
* int i = 4;
* vect_add_at(v, &i, 2) will add the new item 4 at
* position 2 in the vector v
* and move all the elements
* from the original 2nd onward
* of a position to make space
* for the new item 4.
*/
void vect_add_at(vector const v, const void *item, zvect_index index);
/*
* int i = 5;
* vect_add_front(v, &i) will add the new item 5 at
* the beginning of the vector
* v (or front) and will also
* move all the existing
* elements of one position in
* the vector to make space for
* the new item 5 at the front
* of vector v.
*/
void vect_add_front(vector const v, const void *item);
#define vect_push_front(x, y) vect_add_front(x, y)
/*
* vect_get returns an item from the specified vector
*
* vect_get(v) will return the ast element in
* the v vector (but will not remove
* the element as it happens in
* vect_pop(v)).
*/
void *vect_get(vector const v);
#define vect_back(v) vect_get(v)
/*
*
* vect_get_at(v, 3) will return the element at location
* 3 in the vector v.
*/
void *vect_get_at(vector const v, const zvect_index i);
#define vect_at(v, x) vect_get_at(v, x)
/*
* vect_get_front(v) will return the first element in
* the vector v.
*/
void *vect_get_front(vector const v);
#define vect_front(v) vect_get_front(v)
/*
*vect_put allows you to REPLACE an item
* in the vector.
*
* int i = 3;
* vect_put(v, &i) will replace the last element
* in the vector with 3.
*/
void vect_put(vector const v, const void *item);
/*
*
* int i = 4;
* vect_put_at(v, &i, 2) will replace the 3rd element
* (2 + 1, as vector's 1st item
* starts at v[0]) with the
* item 4.
*/
void vect_put_at(vector const v, const void *item, const zvect_index i);
/*
*
* int i = 5;
* vect_put_front(v, &i) will replace the 1st element
* of the vector with the item
* 5.
*/
void vect_put_front(vector const v, const void *item);
/*
* vect_remove removes an item from the vector
* and reorganise the vector. It also returns
* the item remove from the vector, so you can
* use it to simulate a stack behaviour as well.
*
* vect_remove(v) will remove and return the
* last item in the vector.
*/
void *vect_remove(vector const v);
/*
* vect_remove_at(v, 3) will remove the 3rd item in
* the vector and return it.
*/
void *vect_remove_at(vector const v, const zvect_index i);
/*
* vect_remove_front(v) will remove the 1st item in
* the vector and return it.
*/
void *vect_remove_front(vector const v);
/*
* vect_delete deletes an item from the vector
* and reorganise the vector. It does not return
* the item like remove.
*
* vect_delete(v) will delete and the last
* item in the vector.
*/
void vect_delete(vector const v);
/*
* vect_delete_at(v, 3) will delete the 3rd item in
* the vector.
*/
void vect_delete_at(vector const v, const zvect_index i);
/*
* vect_delete_range(v, 20, 30)
* will delete items from item
* 20 to item 30 in the vector
* v.
*/
void vect_delete_range(vector const v, const zvect_index first_element, const zvect_index last_element);
/*
*
* vect_delete_front(v) will delete the 1st item in
* the vector.
*/
void vect_delete_front(vector const v);
////////////
// Vector Data manipulation functions:
////////////
#ifdef ZVECT_DMF_EXTENSIONS
// Data Manipulation Functions extensions:
/*
* vect_swap is a function that allows you to swap two
* items in the same vector.
* You just pass the vector and the index of both the
* two items to swap.
*
* For example to swap item 3 with item 22 on vector v
* use:
* vect_swap(v, 3, 22);
*/
void vect_swap(vector const v, const zvect_index s, const zvect_index e);
/*
* vect_swap_range is a function that allows to swap
* a range of items in the same vector.
* You just pass the vector, the index of the first item
* to swap, the index of the last item to swap and the
* index of the first item to swap with.
*
* For example to swap items from 10 to 20 with items
* from 30 to 40 on vector v, use:
* vect_swap_range(v, 10, 20, 30);
*/
void vect_swap_range(vector const v, const zvect_index s1, const zvect_index e1, const zvect_index s2);
/*
* vect_rotate_left is a function that allows to rotate
* a vector of "i" positions to the left (or from the
* "front" to the "end").
*
* For example to rotate a vector called v of 5 positions
* to the left, use:
* vect_rotate_left(v, 5);
*/
void vect_rotate_left(vector const v, const zvect_index i);
/*
* vect_rotate_right is a function that allows to rotate
* a vector of "i" positions to the right (or from the
* "end" to the "front").
*
* For example to rotate a vector called v of 5 positions
* to the right, use:
* vect_rotate_right(v, 5);
*/
void vect_rotate_right(vector const v, const zvect_index i);
/*
* vect_qsort allows you to sort a given vector.
* The algorithm used to sort a vector is Quicksort with
* 3 ways partitioning which is generally much faster than
* traditional quicksort.
*
* To sort a vector you need to provide a custom function
* that allows vect_sort to determine the order and which
* elements of a vector are used to order it in the way
* you desire. It pretty much works as a regular C qsort
* function. It quite fast given that it only reorders
* pointers to your datastructures stored in the vector.
*
*/
void vect_qsort(vector const v, int (*compare_func)(const void *, const void*));
/*
* vect_bsearch is a function that allows to perform
* a binary search over the vector we pass to it to
* find the item "key" using the comparison function
* "f1".
*
* The specific algorithm used to implement vect_bsearch
* if my own re-implementation of the Adaptive Binary
* Search algorithm (from Igor van den Hoven) which has
* some improvements over the original one (look at the
* sources for more details).
*
* For example to search for the number 5 in a vector
* called v using a compare function called "my_compare"
* use:
* int i = 5;
* vect_bsearch(v, &i, my_compare);
*/
bool vect_bsearch(vector const v, const void *key, int (*f1)(const void *, const void *), zvect_index *item_index);
/*
* vect_add_ordered allows the insertion of new items in
* an ordered fashion. Please note that for this to work
* fine you should always use only ordered vectors or if
* an empty vector use vect_add_ordered only to add new
* values to it!
*
* As for any other ordered function you must provide
* your own compare function (syntax is the usual one,
* and it's the same as for regular CLib qsort function)
*
* To add item 3 to a vector called v using vect_add_ordered
* (assuming your compare function is called my_compare),
* use:
*
* vect_Add_ordered(v, 3, my_compare);
*/
void vect_add_ordered(vector const v, const void *value, int (*f1)(const void *, const void *));
#endif // ZVECT_DMF_EXTENSIONS
#ifdef ZVECT_SFMD_EXTENSIONS
// Single Function Multiple Data extensions:
/*
* vect_apply allows you to apply a C function to
* each item in the vector, so you just pass the vector,
* the function you want to execute against each item on
* a vector and make sure such function is declared and
* defined to accept a "void *" pointer which will be the
* pointer to the single item in the vector passed to your
* function. The function has no return value because it's
* not necessary if you receive the pointer to the item.
* You can simply update the content of the memory pointed
* by the item passed and that is much faster than having
* to deal with return values especially when you'll be
* using complex data structures as item of the vector.
*/
void vect_apply(vector const v, void (*f1)(void *));
/*
* vect_apply_if is a function that will apply "f1" C function
* to each and every item in vector v1, IF the return value of
* function f2 is true. So it allows what is known as conditional
* application. f2 will receive an item from v1 as first parameter
* and an item from v2 (at the same position of the item in v1) as
* second parameter. So, for example, if we want to increment all
* items in v1 of 10 if they are smaller than the corresponded item
* in v2 then we can simply use:
*
* vect_apply_if(v1, v2, increment_item, is_item_too_small);
*
* and make sure we have defined 'increment_item' and
* 'is_item_too_small' as:
*
* void increment_item(void *item1)
* {
* int *value = (int *)item1;
* *value +=10;
* }
*
* bool is_item_too_small(void *item1, void *item2)
* {
* if (*((int *)item1) < *((int *)item2))
* return true;
* return false;
* }
*/
void vect_apply_if(vector const v1, vector const v2, void (*f1)(void *), bool (*f2)(void *, void *));
// Operations with multiple vectors:
/*
* vect_copy is a function that allows to copy a specified
* set of elements from a vector to another.
* Please note: only vectors with the same data size (the
* parameter we pass during the creation of both vectors)
* can be copied into the other!
*
* vect_copy(v1, v2, 3, 5) will copy all the items in
* vector v2, from the 4th item
* till the 9th (3 + 5, remember
* vector items start from 0) in
* the vector v1. So at the end
* of the process you'll have such
* items copied at the end of v1.
*/
void vect_copy(vector const v1, vector const v2, zvect_index start, zvect_index max_elements);
/*
* vect_insert is a function that allows to copy a specified
* set of elements from a vector to another and "insert"
* them from a specified position in the destination vector.
* Please note: only vectors with the same data size (the
* parameter we pass during the creation of both vectors)
* can be copied into the other!
*
* vect_insert(v1, v2, 3, 5, 7) will copy all the items in
* vector v2, from the 4th item
* till the 9th (3 + 5, remember
* vector items start from 0) in
* the vector v1 from position 7.
* So at the end of the process
* you'll have such items "inserted"
* inside v1.
*/
void vect_insert(vector const v1, vector const v2, const zvect_index s2,
const zvect_index e2, const zvect_index s1);
/*
* vect_move is a function that allows to move a specified
* set of items from one vector to another.
* It will also re-organise the source vector and (obviously)
* expand the destination vector if needed.
* Please note: only vectors of the same data size can be moved
* one into the other!
*
* vect_move(v1, v2, 2, 2) will move items in v2 from the
* 3rd item in v2 till the 5th at
* the end of v1.
*/
void vect_move(vector const v1, vector const v2, zvect_index start, zvect_index max_elements);
/*
* vect_move_if is a function that allows to move a specified
* set of items from one vector to another if the condition
* returned by the function pointed by f2 function pointer
* is true.
* It will also re-organise the source vector and (obviously)
* expand the destination vector if needed.
* Please note: only vectors of the same data size can be moved
* one into the other!
*
* vect_move(v1, v2, 2, 2, check_data) will move items in v2 from the
* 3rd item in v2 till the 5th at
* the end of v1 if check_data returns
* true.
*/
zvect_retval vect_move_if(vector const v1, vector v2, const zvect_index s2,
const zvect_index e2, zvect_retval (*f2)(void *, void *));
/*
* vect_merge is a function that merges together 2 vectors of
* the same data size. At the end of the process, the source
* vector will be destroyed.
*
* vect_merge(v1, v2) will merge vector v2 to v1 and then
* destroy v2. So at the end of the job
* v1 will contain the old v1 items +
* all v2 items.
*/
void vect_merge(vector const v1, vector v2);
#endif // ZVECT_SFMD_EXTENSIONS
#ifdef _cplusplus
}
#endif
#endif // SRC_ZVECTOR_H_

View File

@ -0,0 +1,144 @@
/*
* Name: ZVector_Checks
* Purpose: Header used by ZVector Library to identify for which
* platform ZVector is being compiled.
* Author: Paolo Fabio Zaino
* Domain: General
* License: Copyright 2021 by Paolo Fabio Zaino, all rights reserved
* Distributed under MIT license
*
*/
#ifndef SRC_ZVECTOR_CHECKS_H_
#define SRC_ZVECTOR_CHECKS_H_
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
// Try to determine the Operating System being used:
#if defined(__APPLE__) && defined(__MACH__)
# define macOS
#endif
#if ( defined(__GNU__) || defined(__gnu_linux__) || \
defined(__linux__) || defined(macOS) )
# define OS_TYPE 1
#elif ( defined(__WIN32__) || defined(WIN32) || defined(_WIN32) )
# define OS_TYPE 2
#else
# define OS_TYPE 0
#endif
// Try to determine compiler being used:
#if defined(__GNUC__)
# define compiler gcc
# define ZVECT_COMPTYPE 1
# define COMP_MAJRELEASE (__GNUC__)
# define COMP_MINRELEASE (__GNUC_MINOR__)
# define COMP_PATRELEASE (__GNUC_PATCHLEVEL__)
#elif defined(_MSC_VER)
# define compiler msc
# define ZVECT_COMPTYPE 2
# define COMP_MAJRELEASE (_MSC_VER)
# define COMP_MINRELEASE 0
# define COMP_PATRELEASE 0
#elif defined(__clang__)
# define compiler clang
# define ZVECT_COMPTYPE 3
# define COMP_MAJRELEASE (__clang_major__)
# define COMP_MINRELEASE (__clang_minor__)
# define COMP_PATRELEASE (__clang_patchlevel__)
#elif defined(__INTEL_COMPILER) || defined(__ICC) || \
defined(__ECC) || defined(__ICL)
// For intel c compiler please remember to specify:
// /Qstd=c99 (on Windows)
// -std=c99 on Linux and/or macOS
# define compiler intelc
# define ZVECT_COMPTYPE 4
# define COMP_MAJRELEASE (__INTEL_COMPILER)
# define COMP_MINRELEASE 0
# define COMP_PATRELEASE 0
#elif defined (__LCC__)
# define compiler lcc
# define ZVECT_COMPTYPE 5
# define COMP_MAJRELEASE (__LCC)
# define COMP_MINRELEASE 0
# define COMP_PATRELEASE 0
#elif defined(__NORCROFT_C__) || defined(__CC_NORCROFT) || \
defined(__ARMCC_VERSION)
// For Norcroft C please remember to specify:
// -c99
# define compiler norcroftc
# define ZVECT_COMPTYPE 6
# define COMP_MAJRELEASE (__ARMCC_VERSION)
#elif defined(_CRAYC)
// For Cray C please remember to specify:
// -hc99
# define compiler crayc
# define ZVECT_COMPTYPE 10
# define COMP_MAJRELEASE (_RELEASE)
# define COMP_MINRELEASE (_RELEASE_MINOR)
# define COMP_PATRELEASE 0
#elif defined(__HP_cc)
// For HP CC please remember to specify:
// -ansi -std=c99
# define compiler hpc
# define ZVECT_COMPTYPE 11
# define COMP_MAJRELEASE 1
# define COMP_MINRELEASE 21
# define COMP_PATRELEASE 0
#elif defined(__IBMC__)
// For IBM C please remember to specify:
// C99 flags
# define compiler ibmc
# define ZVECT_COMPTYPE 12
#elif defined(__TINYC__)
# define compiler tinyc
# define ZVECT_COMPTYPE 6
# define COMP_MAJRELEASE 0
# define COMP_MINRELEASE 0
# define COMP_PATRELEASE 0
#else
# define compiler unknown
# define ZVECT_COMPTYPE 0
#endif
// Try to determine CPU Architecture:
#if defined(__aarch64__)
# define CPU_TYPE ARM64
# define Arch64
#elif defined(__aarch32__)
# define CPU_TYPE ARM32
# define Arch32
#elif defined(__amd64__) || defined(__x86_64__) || \
defined(__ia64__) || defined(_M_IA64) || \
defined(_M_AMD64) || defined(_M_X64)
# define CPU_TYPE x86_64
# define Arch64
#else
# define CPU_TYPE unknown
# define Arch32
#endif
// Start setting up macros based on the platform we detected
// above.
#if ( OS_TYPE == 1 )
// We are on a Unix-like OS so we can use pthreads!
# define MUTEX_TYPE 1
# elif ( OS_TYPE == 2 ) && ( defined(__CYGWIN__) || \
defined(__MINGW32__) || defined(__MINGW64__) )
// We are on MS Windows using CIGWIN so we can use pthreads!
# define MUTEX_TYPE 1
# elif ( OS_TYPE == 2 ) && ( !defined(__CYGWIN__) && \
!defined(__MINGW32__) && !defined(__MINGW64__) )
// We are on MS Windows, so we need to use
// Windows stuff:
# define MUTEX_TYPE 2
#else
// I have no idea on which platform are we,
// hence I have to use fake mutexes and go with the flow!
# define MUTEX_TYPE 0
#endif
#endif // SRC_ZVECTOR_CHECKS_H_

View File

@ -0,0 +1,84 @@
/*
* Name: Vector_config
* Purpose: Base configuration for the ZVector library
* Author: Paolo Fabio Zaino
* Domain: General
* License: Copyright by Paolo Fabio Zaino, all rights reserved
* Distributed under MIT license
*
*/
#ifndef SRC_ZVECTOR_CONFIG_H_
#define SRC_ZVECTOR_CONFIG_H_
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
// Include some standard C lib header
#include <stdint.h>
#include <stdbool.h>
// Data alignment configuration
#if ( ZVECT_COMPTYPE == 1 )
#define ZVECT_DATAALIGN __attribute__((aligned))
#define ZVECT_PACKING __attribute__((__packed__))
#define ZVECT_ALWAYSINLINE __attribute__ ((__always_inline__))
#else
#define ZVECT_DATAALIGN
#define ZVECT_PACKING
#define ZVECT_ALWAYSINLINE
#endif
// Default vector Index type
// This is set to unsigned int of 32bit
// size (so all different architectures
// and OS behaves in a similar way)
// If you want a larger index you can
// change it to, for example, uint64_t
typedef uint32_t zvect_index;
#define zvect_index_max 4294967295 // If you change zvect_index type make sure you update this value
// it's the maximum number that can be stored in a zvect_index.
// Default vector return type for
// error codes.
// Generally negative numbers identify
// an error.
// 0 identify completed successful
// Positive numbers identify return
// attributes, like 1 is generally true
typedef int32_t zvect_retval;
// Default vector storage size
// This will be used when the user
// specifies 0 (zero) as data type
// size.
#define ZVECT_DEFAULT_DATA_SIZE sizeof(int)
// Default vector capacity
// This will be used when the user
// does NOT specify an Initial Capacity
// or set it to 0 (zero):
#define ZVECT_INITIAL_CAPACITY 8
// The following options are handled by Make
// So you should not need to modify them here.
// Choose which type of memory functions you want
// to use for your case:
// 0 = Use Standard memcpy and memmove
// 1 = Use Optimized memcpy and memmove
#define ZVECT_MEMX_METHOD 0
// Enable/Disable thread safe code:
#define ZVECT_THREAD_SAFE 1
// Enable/Disbale reentrant code:
#define ZVECT_FULL_REENTRANT 0
// Enable/Disable DMF Extensions:
#define ZVECT_DMF_EXTENSIONS 1
// Enable/Disable SFMD Extensions:
#define ZVECT_SFMD_EXTENSIONS 1
#endif // SRC_ZVECTOR_CONFIG_H_

3124
srcs/libs/vector/zvector.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@
#ifdef OPENDHCPD_ON #ifdef OPENDHCPD_ON
#include "user_errno.h" #include "user_errno.h"
#include "libs/misc/sdsalloc.h"
#endif #endif
#ifdef OPENDHCPDDNS_ON #ifdef OPENDHCPDDNS_ON
@ -46,7 +47,7 @@ static void lwip_init_env() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ret; int ret;
hiredisResetAllocators();
#ifdef OPENDHCPDDNS_ON #ifdef OPENDHCPDDNS_ON
return dual_server_main(argc, argv); return dual_server_main(argc, argv);
#else #else