diff --git a/HISTORY b/HISTORY index 3928aee..d3bf776 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.44 2020-02-12 +Version 1.44 2020-02-14 * add test file src/tests/test_pthread_lock.c * add uniq_skiplist.[hc] * add function split_string_ex @@ -8,6 +8,7 @@ Version 1.44 2020-02-12 * add function fc_memrchr * add function is_network_error * add function fast_mpool_log_stats + * add files: server_id_func.[hc] Version 1.43 2019-12-25 * replace function call system to getExecResult, diff --git a/src/Makefile.in b/src/Makefile.in index 1202649..d2b2f51 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -15,7 +15,7 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \ system_info.lo fast_blocked_queue.lo id_generator.lo \ char_converter.lo char_convert_loader.lo common_blocked_queue.lo \ multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \ - json_parser.lo buffered_file_writer.lo + json_parser.lo buffered_file_writer.lo server_id_func.lo FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ logger.o sockopt.o base64.o sched_thread.o \ @@ -27,7 +27,7 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \ system_info.o fast_blocked_queue.o id_generator.o \ char_converter.o char_convert_loader.o common_blocked_queue.o \ multi_socket_client.o skiplist_set.o uniq_skiplist.o \ - json_parser.o buffered_file_writer.o + json_parser.o buffered_file_writer.o server_id_func.lo HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ shared_func.h pthread_func.h ini_file_reader.h _os_define.h \ @@ -40,7 +40,7 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \ php7_ext_wrapper.h id_generator.h char_converter.h \ char_convert_loader.h common_blocked_queue.h \ multi_socket_client.h skiplist_set.h uniq_skiplist.h \ - fc_list.h json_parser.h buffered_file_writer.h + fc_list.h json_parser.h buffered_file_writer.h server_id_func.h ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS) diff --git a/src/ini_file_reader.c b/src/ini_file_reader.c index 86c6b94..0e377b0 100644 --- a/src/ini_file_reader.c +++ b/src/ini_file_reader.c @@ -2968,16 +2968,18 @@ void iniPrintItems(IniContext *pContext) hash_walk(&pContext->sections, iniPrintHashData, NULL); } -struct section_walk_arg { +struct section_name_walk_arg { IniSectionInfo *sections; + IniSectionNameFilterFunc filter_func; + void *args; int count; int size; }; -static int iniSectionWalkCallback(const int index, const HashData *data, - void *args) +static int iniSectionNameWalkCallback(const int index, + const HashData *data, void *args) { - struct section_walk_arg *walk_arg; + struct section_name_walk_arg *walk_arg; IniSection *pSection; char *section_name; int section_len; @@ -2988,7 +2990,13 @@ static int iniSectionWalkCallback(const int index, const HashData *data, return 0; } - walk_arg = (struct section_walk_arg *)args; + walk_arg = (struct section_name_walk_arg *)args; + if (walk_arg->filter_func != NULL && !walk_arg-> + filter_func(data->key, data->key_len, walk_arg->args)) + { + return 0; + } + if (walk_arg->count >= walk_arg->size) { return ENOSPC; @@ -3009,20 +3017,101 @@ static int iniSectionWalkCallback(const int index, const HashData *data, return 0; } -int iniGetSectionNames(IniContext *pContext, IniSectionInfo *sections, +int iniGetSectionNamesEx(IniContext *pContext, IniSectionNameFilterFunc + filter_func, void *args, IniSectionInfo *sections, const int max_size, int *nCount) { - struct section_walk_arg walk_arg; + struct section_name_walk_arg walk_arg; int result; walk_arg.sections = sections; - walk_arg.count = 0; + walk_arg.filter_func = filter_func; + walk_arg.args = args; walk_arg.size = max_size; - result = hash_walk(&pContext->sections, iniSectionWalkCallback, &walk_arg); + walk_arg.count = 0; + result = hash_walk(&pContext->sections, iniSectionNameWalkCallback, + &walk_arg); *nCount = walk_arg.count; return result; } +int iniGetSectionNames(IniContext *pContext, IniSectionInfo *sections, + const int max_size, int *nCount) +{ + return iniGetSectionNamesEx(pContext, NULL, NULL, + sections, max_size, nCount); +} + +static bool iniSectionNameFilterByPrefix(const char *section_name, + const int name_len, void *args) +{ + string_t *prefix; + + prefix = (string_t *)args; + if (name_len < prefix->len) { + return false; + } + return memcmp(section_name, prefix->str, prefix->len) == 0; +} + +int iniGetSectionNamesByPrefix(IniContext *pContext, const char *szPrefix, + IniSectionInfo *sections, const int max_size, int *nCount) +{ + string_t prefix; + + FC_SET_STRING(prefix, (char *)szPrefix); + return iniGetSectionNamesEx(pContext, iniSectionNameFilterByPrefix, + &prefix, sections, max_size, nCount); +} + +struct section_count_walk_arg { + IniSectionNameFilterFunc filter_func; + void *args; + int count; +}; + +static int iniSectionCountWalkCallback(const int index, + const HashData *data, void *args) +{ + struct section_count_walk_arg *walk_arg; + IniSection *pSection; + + pSection = (IniSection *)data->value; + if (pSection == NULL) + { + return 0; + } + + walk_arg = (struct section_count_walk_arg *)args; + if (walk_arg->filter_func == NULL || walk_arg-> + filter_func(data->key, data->key_len, walk_arg->args)) + { + walk_arg->count++; + } + + return 0; +} + +int iniGetSectionCountEx(IniContext *pContext, IniSectionNameFilterFunc + filter_func, void *args) +{ + struct section_count_walk_arg walk_arg; + + walk_arg.filter_func = filter_func; + walk_arg.args = args; + walk_arg.count = 0; + hash_walk(&pContext->sections, iniSectionCountWalkCallback, &walk_arg); + return walk_arg.count; +} + +int iniGetSectionCountByPrefix(IniContext *pContext, const char *szPrefix) +{ + string_t prefix; + + FC_SET_STRING(prefix, (char *)szPrefix); + return iniGetSectionCountEx(pContext, iniSectionNameFilterByPrefix, &prefix); +} + IniItem *iniGetSectionItems(const char *szSectionName, IniContext *pContext, int *nCount) { diff --git a/src/ini_file_reader.h b/src/ini_file_reader.h index 0528da2..0224518 100644 --- a/src/ini_file_reader.h +++ b/src/ini_file_reader.h @@ -16,8 +16,8 @@ #include "common_define.h" #include "hash.h" -#define FAST_INI_ITEM_NAME_LEN 64 -#define FAST_INI_ITEM_VALUE_LEN 256 +#define FAST_INI_ITEM_NAME_LEN 63 +#define FAST_INI_ITEM_VALUE_LEN 255 #define FAST_INI_ITEM_NAME_SIZE (FAST_INI_ITEM_NAME_LEN + 1) #define FAST_INI_ITEM_VALUE_SIZE (FAST_INI_ITEM_VALUE_LEN + 1) @@ -29,6 +29,9 @@ #define FAST_INI_FLAGS_NONE 0 #define FAST_INI_FLAGS_SHELL_EXECUTE 1 +typedef bool (*IniSectionNameFilterFunc)(const char *section_name, + const int name_len, void *args); + typedef struct ini_item { char name[FAST_INI_ITEM_NAME_SIZE]; @@ -244,7 +247,7 @@ static inline const char *iniGetConfigPath(IniContext *pContext) return pContext->config_path; } -/** return the items of global section +/** return the section names * parameters: * pContext: the ini context * sections: the section array @@ -255,6 +258,60 @@ static inline const char *iniGetConfigPath(IniContext *pContext) int iniGetSectionNames(IniContext *pContext, IniSectionInfo *sections, const int max_size, int *nCount); +/** return the section names + * parameters: + * pContext: the ini context + * prefix: the prefix of section name + * sections: the section array + * max_size: the max size of sections + * nCount: return the section count + * return: errno, 0 for success, != 0 for fail +*/ +int iniGetSectionNamesByPrefix(IniContext *pContext, const char *szPrefix, + IniSectionInfo *sections, const int max_size, int *nCount); + +/** return the section names + * parameters: + * pContext: the ini context + * filter_func: the section name filter function + * args: the extra data pointer + * sections: the section array + * max_size: the max size of sections + * nCount: return the section count + * return: errno, 0 for success, != 0 for fail +*/ +int iniGetSectionNamesEx(IniContext *pContext, IniSectionNameFilterFunc + filter_func, void *args, IniSectionInfo *sections, + const int max_size, int *nCount); + +/** get matched section count + * parameters: + * pContext: the ini context + * filter_func: the section name filter function + * args: the extra data pointer + * return: matched section count +*/ +int iniGetSectionCountEx(IniContext *pContext, IniSectionNameFilterFunc + filter_func, void *args); + +/** get matched section count + * parameters: + * pContext: the ini context + * prefix: the prefix of section name + * return: matched section count +*/ +int iniGetSectionCountByPrefix(IniContext *pContext, const char *szPrefix); + +/** get section count + * parameters: + * pContext: the ini context + * return: section count +*/ +static inline int iniGetSectionCount(IniContext *pContext) +{ + return pContext->sections.item_count; +} + /** return the items of global section * parameters: * pContext: the ini context diff --git a/src/server_id_func.c b/src/server_id_func.c new file mode 100644 index 0000000..f8515ca --- /dev/null +++ b/src/server_id_func.c @@ -0,0 +1,679 @@ +#include +#include +#include +#include +#include "logger.h" +#include "shared_func.h" +#include "sockopt.h" +#include "server_id_func.h" + +#define GROUP_SECTION_PREFIX_STR "group-" +#define GROUP_SECTION_PREFIX_LEN (sizeof(GROUP_SECTION_PREFIX_STR) - 1) + +#define SERVER_SECTION_PREFIX_STR "server-" +#define SERVER_SECTION_PREFIX_LEN (sizeof(SERVER_SECTION_PREFIX_STR) - 1) + +#define SERVER_ITEM_HOST_STR "host" +#define SERVER_ITEM_HOST_LEN (sizeof(SERVER_ITEM_HOST_STR) - 1) + +#define SERVER_ITEM_PORT_AFFIX_STR "-port" +#define SERVER_ITEM_PORT_AFFIX_LEN (sizeof(SERVER_ITEM_PORT_AFFIX_STR) - 1) + +#define NET_TYPE_OUTER_STR "outer" +#define NET_TYPE_INNER_STR "inner" + +#define SUB_NET_TYPE_INNER_10_STR1 "inner-10" +#define SUB_NET_TYPE_INNER_172_STR1 "inner-172" +#define SUB_NET_TYPE_INNER_192_STR1 "inner-192" + +#define SUB_NET_TYPE_INNER_10_STR2 "inner_10" +#define SUB_NET_TYPE_INNER_172_STR2 "inner_172" +#define SUB_NET_TYPE_INNER_192_STR2 "inner_192" + +#define SUB_NET_TYPE_INNER_10_STR3 "inner10" +#define SUB_NET_TYPE_INNER_172_STR3 "inner172" +#define SUB_NET_TYPE_INNER_192_STR3 "inner192" + +static int fc_server_cmp_server_id(const void *p1, const void *p2) +{ + return ((FCServerInfo *)p1)->id - ((FCServerInfo *)p2)->id; +} + +static int fc_server_cmp_ip_and_port(const void *p1, const void *p2) +{ + FCServerMap *m1; + FCServerMap *m2; + int result; + int sub; + int min; + + m1 = (FCServerMap *)p1; + m2 = (FCServerMap *)p2; + + sub = m1->ip_addr.len - m2->ip_addr.len; + if (sub < 0) { + min = m1->ip_addr.len; + } else { + min = m2->ip_addr.len; + } + + if (min > 0) { + result = memcmp(m1->ip_addr.str, m2->ip_addr.str, min); + if (result != 0) { + return result; + } + } + if (sub != 0) { + return sub; + } + + return m1->port - m2->port; +} + +FCServerInfo *fc_server_get_by_id(FCServerContext *ctx, + const int server_id) +{ + FCServerInfo target; + + target.id = server_id; + return (FCServerInfo *)bsearch(&target, + ctx->sorted_server_arrays.by_id.servers, + ctx->sorted_server_arrays.by_id.count, + sizeof(FCServerInfo), fc_server_cmp_server_id); +} + +static int fc_server_calc_ip_port_count(FCServerContext *ctx) +{ + FCServerInfo *server; + FCServerInfo *send; + FCGroupAddresses *gaddr; + FCGroupAddresses *gend; + int count; + + count = 0; + send = ctx->sorted_server_arrays.by_id.servers + + ctx->sorted_server_arrays.by_id.count; + for (server=ctx->sorted_server_arrays.by_id.servers; + servergroup_array.group_addrs + server->group_array.count; + for (gaddr=server->group_array.group_addrs; gaddraddress_array.count; + } + } + + return count; +} + +static int fc_server_init_ip_port_array(FCServerContext *ctx) +{ + int result; + int alloc_bytes; + int i; + FCServerMapArray *map_array; + FCServerMap *map; + FCServerInfo *server; + FCServerInfo *send; + FCGroupAddresses *gaddr; + FCGroupAddresses *gend; + + map_array = &ctx->sorted_server_arrays.by_ip_port; + + map_array->count = fc_server_calc_ip_port_count(ctx); + alloc_bytes = sizeof(FCServerMap) * map_array->count; + map_array->maps = (FCServerMap *)malloc(alloc_bytes); + if (map_array->maps == NULL) { + result = errno != 0 ? errno : ENOMEM; + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "errno: %d, error info: %s", __LINE__, + alloc_bytes, result, STRERROR(result)); + return result; + } + memset(map_array->maps, 0, alloc_bytes); + + send = ctx->sorted_server_arrays.by_id.servers + + ctx->sorted_server_arrays.by_id.count; + map = map_array->maps; + for (server=ctx->sorted_server_arrays.by_id.servers; + servergroup_array.group_addrs + server->group_array.count; + for (gaddr=server->group_array.group_addrs; gaddraddress_array.count; i++) { + map->server = server; + FC_SET_STRING(map->ip_addr, gaddr->address_array. + addrs[i].conn.ip_addr); + map->port = gaddr->address_array.addrs[i].conn.port; + map++; + } + } + } + + qsort(map_array->maps, map_array->count, sizeof(FCServerMap), + fc_server_cmp_ip_and_port); + return 0; +} + +static int fc_server_check_id_duplicated(FCServerContext *ctx, + const char *config_filename) +{ + FCServerInfo *previous; + FCServerInfo *current; + FCServerInfo *send; + + previous = ctx->sorted_server_arrays.by_id.servers + 0; + send = ctx->sorted_server_arrays.by_id.servers + + ctx->sorted_server_arrays.by_id.count; + for (current=ctx->sorted_server_arrays.by_id.servers + 1; + currentid == previous->id) { + logError("file: "__FILE__", line: %d, " + "config file: %s, duplicate server id: %d", + __LINE__, config_filename, current->id); + return EEXIST; + } + previous = current; + } + + return 0; +} + +static int fc_server_check_ip_port(FCServerContext *ctx, + const char *config_filename) +{ + FCServerMap *previous; + FCServerMap *current; + FCServerMap *end; + + previous = ctx->sorted_server_arrays.by_ip_port.maps + 0; + end = ctx->sorted_server_arrays.by_ip_port.maps + + ctx->sorted_server_arrays.by_ip_port.count; + for (current=ctx->sorted_server_arrays.by_ip_port.maps+1; + currentip_addr.str, previous->port, + previous->server->id, current->server->id); + + return EEXIST; + } + + previous = current; + } + + return 0; +} + +FCServerInfo *fc_server_get_by_ip_port_ex(FCServerContext *ctx, + const string_t *ip_addr, const int port) +{ + FCServerMap target; + FCServerMap *found; + + target.ip_addr = *ip_addr; + target.port = port; + found = (FCServerMap *)bsearch(&target, + ctx->sorted_server_arrays.by_ip_port.maps, + ctx->sorted_server_arrays.by_ip_port.count, + sizeof(FCServerMap), fc_server_cmp_ip_and_port); + if (found != NULL) { + return found->server; + } + + return NULL; +} + +static inline void fc_server_set_group_name(FCServerGroupInfo *ginfo, + const char *group_name) +{ + ginfo->group_name.str = ginfo->name_buff; + ginfo->group_name.len = snprintf(ginfo->name_buff, + sizeof(ginfo->name_buff) - 1, "%s", group_name); + if (ginfo->group_name.len == 0) { + return; + } + + fc_trim(ginfo->group_name.str); + ginfo->group_name.len = strlen(ginfo->group_name.str); +} + +static int fc_server_set_net_type(const char *config_filename, + FCServerGroupInfo *ginfo, const char *net_type) +{ + if (net_type == NULL || *net_type == '\0') { + ginfo->filter.net_type = FC_NET_TYPE_NONE; + return 0; + } + + if (strcasecmp(net_type, NET_TYPE_OUTER_STR) == 0) { + ginfo->filter.net_type = FC_NET_TYPE_OUTER; + } else if (strcasecmp(net_type, NET_TYPE_INNER_STR) == 0) { + ginfo->filter.net_type = FC_NET_TYPE_INNER; + } else if (strcasecmp(net_type, SUB_NET_TYPE_INNER_10_STR1) == 0 || + strcasecmp(net_type, SUB_NET_TYPE_INNER_10_STR2) == 0 || + strcasecmp(net_type, SUB_NET_TYPE_INNER_10_STR3) == 0) + { + ginfo->filter.net_type = FC_SUB_NET_TYPE_INNER_10; + } else if (strcasecmp(net_type, SUB_NET_TYPE_INNER_172_STR1) == 0 || + strcasecmp(net_type, SUB_NET_TYPE_INNER_172_STR2) == 0 || + strcasecmp(net_type, SUB_NET_TYPE_INNER_172_STR3) == 0) + { + ginfo->filter.net_type = FC_SUB_NET_TYPE_INNER_172; + } else if (strcasecmp(net_type, SUB_NET_TYPE_INNER_192_STR1) == 0 || + strcasecmp(net_type, SUB_NET_TYPE_INNER_192_STR2) == 0 || + strcasecmp(net_type, SUB_NET_TYPE_INNER_192_STR3) == 0) + { + ginfo->filter.net_type = FC_SUB_NET_TYPE_INNER_192; + } else { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, invalid net_type: %s", + __LINE__, config_filename, ginfo->group_name.str, net_type); + return EINVAL; + } + + return 0; +} + +static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo, + const char *ip_prefix) +{ + ginfo->filter.ip_prefix.str = ginfo->filter.prefix_buff; + if (ip_prefix != NULL) { + ginfo->filter.ip_prefix.len = snprintf(ginfo->filter.prefix_buff, + sizeof(ginfo->filter.prefix_buff) - 1, "%s", ip_prefix); + } +} + +static int fc_server_load_one_group(FCServerContext *ctx, + const char *config_filename, IniContext *ini_context, + const char *section_name) +{ + FCServerGroupInfo *current; + char new_name[FAST_INI_ITEM_NAME_SIZE]; + char *net_type; + char *ip_prefix; + int result; + + strcpy(new_name, section_name); + current = ctx->group_array.groups + ctx->group_array.count; + fc_server_set_group_name(current, new_name + GROUP_SECTION_PREFIX_LEN); + + if (current->group_name.len == 0) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, no group name!", + __LINE__, config_filename, section_name); + return EINVAL; + } + + current->port = iniGetIntValue(section_name, "port", + ini_context, ctx->default_port); + + net_type = iniGetStrValue(section_name, "net_type", ini_context); + if ((result=fc_server_set_net_type(config_filename, + current, net_type)) != 0) + { + return result; + } + + ip_prefix = iniGetStrValue(section_name, "ip_prefix", ini_context); + fc_server_set_ip_prefix(current, ip_prefix); + + ctx->group_array.count++; + return 0; +} + +static int fc_server_load_groups(FCServerContext *ctx, + const char *config_filename, IniContext *ini_context) +{ + int result; + int count; + IniSectionInfo sections[FC_MAX_GROUP_COUNT]; + IniSectionInfo *section; + IniSectionInfo *end; + + if ((result=iniGetSectionNamesByPrefix(ini_context, + GROUP_SECTION_PREFIX_STR, sections, + FC_MAX_GROUP_COUNT, &count)) != 0) + { + logError("file: "__FILE__", line: %d, " + "config filename: %s, get sections by prefix %s fail, " + "errno: %d, error info: %s", __LINE__, config_filename, + GROUP_SECTION_PREFIX_STR, result, STRERROR(result)); + return result; + } + + if (count == 0) { + ctx->group_array.count = 1; + fc_server_set_group_name(ctx->group_array.groups + 0, ""); + ctx->group_array.groups[0].port = iniGetIntValue(NULL, "port", + ini_context, ctx->default_port); + return 0; + } + + end = sections + count; + for (section=sections; sectionsection_name)) != 0) + { + return result; + } + } + + return 0; +} + +static int fc_server_check_alloc_servers(FCServerInfoArray *array) +{ + int new_alloc; + int bytes; + FCServerInfo *new_servers; + + if (array->count < array->alloc) { + return 0; + } + + new_alloc = array->alloc > 0 ? 2 * array->alloc : 2; + bytes = sizeof(FCServerInfo) * new_alloc; + new_servers = (FCServerInfo *)malloc(bytes); + if (new_servers == NULL) { + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail", __LINE__, bytes); + return ENOMEM; + } + + if (array->servers != NULL) { + memcpy(new_servers, array->servers, + sizeof(FCServerInfo) * array->count); + free(array->servers); + } + + array->servers = new_servers; + array->alloc = new_alloc; + return 0; +} + +static inline void fc_server_clear_server_port(FCServerGroupArray *array) +{ + FCServerGroupInfo *group; + FCServerGroupInfo *end; + + end = array->groups + array->count; + for (group=array->groups; groupserver_port = 0; + } +} + +static int fc_server_load_group_port(FCServerContext *ctx, + const string_t *group_name, char *port_str) +{ + //TODO + return 0; +} + +static int fc_server_load_hosts(FCServerContext *ctx, FCServerInfo *server, + const char *config_filename, IniContext *ini_context, + const char *section_name) +{ + IniItem *items; + IniItem *it; + IniItem *end; + char *hosts[FC_MAX_SERVER_IP_COUNT]; + int item_count; + int host_count; + int name_len; + int result; + string_t group_name; + + items = iniGetSectionItems(section_name, ini_context, &item_count); + if (item_count == 0) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, no items!", + __LINE__, config_filename, section_name); + return EINVAL; + } + + fc_server_clear_server_port(&ctx->group_array); + + host_count = 0; + end = items + item_count; + for (it=items; itname); + if (name_len > SERVER_ITEM_PORT_AFFIX_LEN && + memcmp(it->name + name_len - SERVER_ITEM_PORT_AFFIX_LEN, + SERVER_ITEM_PORT_AFFIX_STR, SERVER_ITEM_PORT_AFFIX_LEN) == 0) + { + group_name.str = it->name; + group_name.len = name_len - SERVER_ITEM_PORT_AFFIX_LEN; + if ((result=fc_server_load_group_port(ctx, + &group_name, it->value)) != 0) + { + return result; + } + } else if (name_len > SERVER_ITEM_HOST_LEN && memcmp(it->name, + SERVER_ITEM_HOST_STR, SERVER_ITEM_HOST_LEN) == 0) + { + if (host_count >= FC_MAX_SERVER_IP_COUNT) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, " + "too many %s items exceeds %d", __LINE__, + config_filename, section_name, + SERVER_ITEM_HOST_STR, FC_MAX_SERVER_IP_COUNT); + return ENOSPC; + } + + hosts[host_count++] = it->value; + } else { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, unkown item name: %s", + __LINE__, config_filename, section_name, it->name); + return EINVAL; + } + } + + if (host_count == 0) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, no item: %s!", + __LINE__, config_filename, section_name, + SERVER_ITEM_HOST_STR); + return ENOENT; + } + + /* +inner-port = 5106 +outer-port = 5107 + + current->port = iniGetIntValue(section_name, "port", + ini_context, ctx->default_port); + + */ + + return 0; +} + +static int fc_server_load_one_server(FCServerContext *ctx, + const char *config_filename, IniContext *ini_context, + const char *section_name) +{ + FCServerInfo *current; + char *endptr; + int result; + + if ((result=fc_server_check_alloc_servers(&ctx-> + sorted_server_arrays.by_id)) != 0) + { + return result; + } + + current = ctx->sorted_server_arrays.by_id.servers + + ctx->sorted_server_arrays.by_id.count; + + endptr = NULL; + current->id = strtol(section_name + SERVER_SECTION_PREFIX_LEN, &endptr, 10); + if (current->id <= 0 || endptr != NULL) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, section: %s, invalid server id! " + "server section format is [%s$id]", + __LINE__, config_filename, section_name, + SERVER_SECTION_PREFIX_STR); + return EINVAL; + } + + if ((result=fc_server_load_hosts(ctx, current, config_filename, + ini_context, section_name)) != 0) + { + return result; + } + + ctx->sorted_server_arrays.by_id.count++; + return 0; +} + +static int fc_server_load_servers(FCServerContext *ctx, + const char *config_filename, IniContext *ini_context) +{ +#define FIXED_SECTION_COUNT 16 + int result; + int count; + IniSectionInfo *sections; + IniSectionInfo fixed[FIXED_SECTION_COUNT]; + IniSectionInfo *section; + IniSectionInfo *end; + int alloc_bytes; + + count = iniGetSectionCountByPrefix(ini_context, SERVER_SECTION_PREFIX_STR); + if (count == 0) { + logError("file: "__FILE__", line: %d, " + "config filename: %s, no server section such as [%s$id]", + __LINE__, config_filename, SERVER_SECTION_PREFIX_STR); + return ENOENT; + } + + if (count < FIXED_SECTION_COUNT) { + sections = fixed; + } else { + alloc_bytes = sizeof(IniSectionInfo) * count; + sections = (IniSectionInfo *)malloc(alloc_bytes); + if (sections == NULL) { + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail", __LINE__, alloc_bytes); + return ENOMEM; + } + } + + do { + if ((result=iniGetSectionNamesByPrefix(ini_context, + SERVER_SECTION_PREFIX_STR, sections, + count, &count)) != 0) + { + logError("file: "__FILE__", line: %d, " + "config filename: %s, get sections by prefix %s fail, " + "errno: %d, error info: %s", __LINE__, config_filename, + SERVER_SECTION_PREFIX_STR, result, STRERROR(result)); + break; + } + + end = sections + count; + for (section=sections; sectionsection_name)) != 0) + { + break; + } + } + } while (0); + + if (sections != fixed) { + free(sections); + } + + return result; +} + +int fc_server_load_data(FCServerContext *ctx, IniContext *ini_context, + const char *config_filename) +{ + int result; + + if ((result=fc_server_load_groups(ctx, config_filename, + ini_context)) != 0) + { + return result; + } + + if ((result=fc_server_load_servers(ctx, config_filename, + ini_context)) != 0) + { + return result; + } + + qsort(ctx->sorted_server_arrays.by_id.servers, + ctx->sorted_server_arrays.by_id.count, + sizeof(FCServerInfo), fc_server_cmp_server_id); + if ((result=fc_server_check_id_duplicated(ctx, config_filename)) != 0) { + return result; + } + + if ((result=fc_server_init_ip_port_array(ctx)) != 0) { + return result; + } + + return fc_server_check_ip_port(ctx, config_filename); +} + +#define FC_SERVER_INIT_CONTEXT(ctx, port) \ + do { \ + memset(ctx, 0, sizeof(FCServerContext)); \ + ctx->default_port = port; \ + } while (0) + +int fc_server_load_from_file_ex(FCServerContext *ctx, + const char *config_filename, const int default_port) +{ + IniContext ini_context; + int result; + + FC_SERVER_INIT_CONTEXT(ctx, default_port); + if ((result=iniLoadFromFile(config_filename, &ini_context)) != 0) { + return result; + } + + result = fc_server_load_data(ctx, &ini_context, config_filename); + iniFreeContext(&ini_context); + return result; +} + +int fc_server_load_from_buffer_ex(FCServerContext *ctx, char *content, + const char *caption, const int default_port) +{ + IniContext ini_context; + int result; + + FC_SERVER_INIT_CONTEXT(ctx, default_port); + if ((result=iniLoadFromBuffer(content, &ini_context)) != 0) { + return result; + } + + result = fc_server_load_data(ctx, &ini_context, caption); + iniFreeContext(&ini_context); + return result; +} + +void fc_server_destroy(FCServerContext *ctx) +{ + if (ctx->sorted_server_arrays.by_ip_port.maps != NULL) { + free(ctx->sorted_server_arrays.by_ip_port.maps); + ctx->sorted_server_arrays.by_ip_port.maps = NULL; + ctx->sorted_server_arrays.by_ip_port.count = 0; + } + + if (ctx->sorted_server_arrays.by_id.servers != NULL) { + free(ctx->sorted_server_arrays.by_id.servers); + ctx->sorted_server_arrays.by_id.servers = NULL; + ctx->sorted_server_arrays.by_id.count = 0; + } +} diff --git a/src/server_id_func.h b/src/server_id_func.h new file mode 100644 index 0000000..593595e --- /dev/null +++ b/src/server_id_func.h @@ -0,0 +1,132 @@ +//server_id_func.h + +#ifndef _SERVER_ID_FUNC_H +#define _SERVER_ID_FUNC_H + +#include "common_define.h" +#include "connection_pool.h" +#include "ini_file_reader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FC_MAX_SERVER_IP_COUNT 8 +#define FC_MAX_GROUP_COUNT 4 + +typedef struct +{ + int net_type; + ConnectionInfo conn; +} FCAddressInfo; + +typedef struct +{ + string_t group_name; + int port; //default port + int server_port; //port in server section + struct { + int net_type; + string_t ip_prefix; + char prefix_buff[IP_ADDRESS_SIZE]; + } filter; + char name_buff[FAST_INI_ITEM_NAME_SIZE]; //group_name string holder +} FCServerGroupInfo; + +typedef struct +{ + int count; + FCServerGroupInfo groups[FC_MAX_GROUP_COUNT]; +} FCServerGroupArray; + +typedef struct +{ + FCServerGroupInfo *server_group; + struct { + int count; + FCAddressInfo addrs[FC_MAX_SERVER_IP_COUNT]; + } address_array; +} FCGroupAddresses; + +typedef struct +{ + int id; //server id + struct { + int count; + FCGroupAddresses group_addrs[FC_MAX_GROUP_COUNT]; + } group_array; +} FCServerInfo; + +typedef struct +{ + string_t ip_addr; + int port; + FCServerInfo *server; +} FCServerMap; + +typedef struct +{ + int alloc; + int count; + FCServerInfo *servers; +} FCServerInfoArray; + +typedef struct +{ + int count; + FCServerMap *maps; +} FCServerMapArray; + +typedef struct +{ + int default_port; + FCServerGroupArray group_array; + struct { + FCServerInfoArray by_id; //sorted by server id + FCServerMapArray by_ip_port; //sorted by IP and port + } sorted_server_arrays; +} FCServerContext; + +FCServerInfo *fc_server_get_by_id(FCServerContext *ctx, + const int server_id); + +FCServerInfo *fc_server_get_by_ip_port_ex(FCServerContext *ctx, + const string_t *ip_addr, const int port); + +static inline FCServerInfo *fc_server_get_by_ip_port(FCServerContext *ctx, + const char *ip_addr, const int port) +{ + string_t saddr; + FC_SET_STRING(saddr, (char *)ip_addr); + return fc_server_get_by_ip_port_ex(ctx, &saddr, port); +} + +int fc_server_load_from_file_ex(FCServerContext *ctx, + const char *config_filename, const int default_port); + +static inline int fc_server_load_from_file(FCServerContext *ctx, + const char *config_filename) +{ + const int default_port = 0; + return fc_server_load_from_file_ex(ctx, config_filename, default_port); +} + +int fc_server_load_from_buffer_ex(FCServerContext *ctx, char *content, + const char *caption, const int default_port); + +static inline int fc_server_load_from_buffer(FCServerContext *ctx, + char *content) +{ + const char *caption = "from-buffer"; + const int default_port = 0; + return fc_server_load_from_buffer_ex(ctx, content, caption, default_port); +} + +void fc_server_destroy(FCServerContext *ctx); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/sockopt.h b/src/sockopt.h index b4ed73c..808a811 100644 --- a/src/sockopt.h +++ b/src/sockopt.h @@ -19,6 +19,14 @@ #include #include "common_define.h" +#define FC_NET_TYPE_NONE 0 +#define FC_NET_TYPE_OUTER 1 //extranet IP +#define FC_NET_TYPE_INNER 2 //intranet IP + +#define FC_SUB_NET_TYPE_INNER_10 (FC_NET_TYPE_INNER | 4) +#define FC_SUB_NET_TYPE_INNER_172 (FC_NET_TYPE_INNER | 8) +#define FC_SUB_NET_TYPE_INNER_192 (FC_NET_TYPE_INNER | 16) + #define FAST_WRITE_BUFF_SIZE (256 * 1024) typedef struct fast_if_config { diff --git a/src/tests/servers.conf b/src/tests/servers.conf new file mode 100644 index 0000000..2587859 --- /dev/null +++ b/src/tests/servers.conf @@ -0,0 +1,34 @@ + +[group-inner] +port = 5108 + +# outer: extranet IP, such as 202.102.100.1 +# inner: intranet IP such as 172.16.1.5 or 192.168.3.17 +# inner-10: 10 leading network, such as 10.32.1.100 +# inner-172: 172 leading network, such as 172.17.0.4 +# inner-192: 192 leading network, such as 192.168.0.1 +net_type = inner-172 +ip_prefix = 172. + +[group-outer] +port = 5109 +net_type = outer +ip_prefix = + +# config a server +# section format: [server-$id] +# server id is a 32 bits natural number (1, 2, 3 etc.), +[server-1] + +# format: host[:port] +# host can be an IP or a hostname +# can occur more than once +host = 172.17.7.215 +host = 39.100.8.166 + + +[server-2] +inner-port = 5106 +outer-port = 5107 +host = 172.17.7.215 +host = 39.100.8.166