├── src ├── gnb_buf.h ├── gnb_fixed_list_store.h ├── gnb_buf.c ├── gnb_buf_type.h ├── gnb_fixed_list_store.c ├── gnb_fixed_list.h ├── gnb_platform.h ├── gnb_block.h ├── gnb_fixed_pool.h ├── gnb_event.c ├── gnb_alloc.h ├── service │ ├── gnb_udp_over_tcp.h │ ├── gnb_udp_over_tcp.c │ ├── uot_udp_service.c │ └── uot_tcp_service.c ├── gnb_time.h ├── gnb_daemon.c ├── gnb_log_type.h ├── gnb_doubly_linked_list.h ├── gnb_address_type.h ├── gnb_time.c ├── gnb_fixed_list.c ├── gnb_payload16.h ├── gnb_fixed_pool.c ├── gnb_event.h ├── gnb_alloc.c ├── gnb_address.h ├── gnb_hash32.h ├── gnb_network_service.h ├── gnb_lru32.h ├── event │ ├── epoll_event_handler.c │ ├── select_event_handler.c │ └── kqueue_event_handler.c ├── gnb_doubly_linked_list.c ├── gnb_payload16.c ├── gnb_log.h ├── gnb_lru32.c ├── gnb_log.c ├── gnb_address.c └── gnb_hash32.c ├── docs └── disclaimer.md ├── Makefile.bsd ├── Makefile.mingw_x86_64 ├── Makefile.linux ├── libs └── hash │ └── murmurhash.c ├── Makefile.inc └── README.md /src/gnb_buf.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_buf_t_h 2 | #define gnb_buf_t_h 3 | 4 | #include "gnb_alloc.h" 5 | 6 | #include "gnb_buf_type.h" 7 | 8 | gnb_zbuf_t* gnb_zbuf_create(size_t size); 9 | gnb_zbuf_t* gnb_zbuf_heap_alloc(gnb_heap_t *heap, size_t size); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /docs/disclaimer.md: -------------------------------------------------------------------------------- 1 | # 免责声明 2 | 3 | [GNB](https://gitee.com/gnbdev/gnb "GNB")是一个开源的去中心化的具有极致内网穿透能力的通过P2P进行三层网络交换的VPN。 4 | 5 | [gnb_udp_over_tcp](https://gitee.com/gnbdev/gnb_udp_over_tcp "gnb_udp_over_tcp")是一个为GNB开发的通过tcp链路中转UDP分组转发的服务,也可以为其他基于UDP协议的服务中转数据。 6 | 7 | 用户使用本项目的软件及相关项目源码、脚本、配置文件即表示用户并同意以下免责条款。 8 | 9 | 在一个计算机及计算机所在网络中部署运行GNB及衍生项目的软件会涉及该计算机及所在网络的安全,请用户在部署运行GNB及衍生项目的软件之前务必确认用户的计算机及所在的计算机网络的管理者是否允许用户这样做,并且要严格遵循用户所在地的法律法规。 10 | 11 | GNB开发组织不对用户部署运行GNB及衍生项目的软件的行为造成的任何后果负责。 12 | -------------------------------------------------------------------------------- /src/gnb_fixed_list_store.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_fixed_list_store_h 2 | #define gnb_fixed_list_store_h 3 | 4 | #include "gnb_alloc.h" 5 | 6 | typedef struct _gnb_fixed_list_store_t{ 7 | 8 | uint32_t num; 9 | uint32_t size; 10 | 11 | void *array[0]; 12 | 13 | }gnb_fixed_list_store_t; 14 | 15 | gnb_fixed_list_store_t* gnb_fixed_list_store_create(gnb_heap_t *heap,uint32_t size, uint32_t block_size); 16 | 17 | void gnb_fixed_list_store_release(gnb_heap_t *heap, gnb_fixed_list_store_t *fixed_list_store); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/gnb_buf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "gnb_buf.h" 5 | 6 | 7 | gnb_zbuf_t* gnb_zbuf_heap_alloc(gnb_heap_t *heap, size_t size){ 8 | 9 | gnb_zbuf_t *zbuf = (gnb_zbuf_t *)gnb_heap_alloc(heap, sizeof(gnb_zbuf_t) + size ); 10 | 11 | zbuf->start = zbuf->block; 12 | 13 | zbuf->end = zbuf->start + size; 14 | 15 | zbuf->pos = zbuf->start; 16 | zbuf->las = zbuf->start; 17 | 18 | return zbuf; 19 | 20 | } 21 | 22 | 23 | void gnb_zbuf_reset(gnb_zbuf_t *zbuf){ 24 | 25 | zbuf->pos = zbuf->start; 26 | zbuf->las = zbuf->start; 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Makefile.bsd: -------------------------------------------------------------------------------- 1 | CFLAGS=-I./src 2 | 3 | GNB_UDP_OVER_TCP=gnb_udp_over_tcp 4 | 5 | include Makefile.inc 6 | 7 | GNB_EVENT_OBJS += ./src/event/kqueue_event_handler.o 8 | GNB_EVENT_OBJS += ./src/event/select_event_handler.o 9 | 10 | all:$(GNB_UDP_OVER_TCP) 11 | 12 | $(GNB_UDP_OVER_TCP): $(GNB_UDP_OVER_TCP_OBJS) $(GNB_EVENT_OBJS) 13 | $(CC) -o ${GNB_UDP_OVER_TCP} $(GNB_UDP_OVER_TCP_OBJS) $(GNB_EVENT_OBJS) 14 | 15 | 16 | %.o:%.c 17 | $(CC) -c -o $@ $< $(CFLAGS) 18 | 19 | 20 | clean: 21 | rm -f ./src/*.o 22 | rm -f ./libs/hash/*.o 23 | rm -f ./src/service/*.o ./src/event/*.o 24 | rm -f $(GNB_UDP_OVER_TCP) 25 | rm -f core 26 | 27 | -------------------------------------------------------------------------------- /Makefile.mingw_x86_64: -------------------------------------------------------------------------------- 1 | CFLAGS= -I./src 2 | 3 | LDFLAGS=-lwsock32 -lws2_32 -lmingwex 4 | 5 | GNB_UDP_OVER_TCP=gnb_udp_over_tcp.exe 6 | 7 | include Makefile.inc 8 | 9 | GNB_EVENT_OBJS += ./src/event/select_event_handler.o 10 | 11 | all:$(GNB_UDP_OVER_TCP) 12 | 13 | $(GNB_UDP_OVER_TCP): $(GNB_UDP_OVER_TCP_OBJS) $(GNB_EVENT_OBJS) 14 | $(CC) -o ${GNB_UDP_OVER_TCP} $(GNB_UDP_OVER_TCP_OBJS) $(GNB_EVENT_OBJS) $(LDFLAGS) 15 | 16 | 17 | %.o:%.c 18 | $(CC) -c -o $@ $< $(CFLAGS) 19 | 20 | clean: 21 | rm -f ./src/*.o 22 | rm -f ./libs/hash/*.o 23 | rm -f ./src/service/*.o ./src/event/*.o 24 | rm -f $(GNB_UDP_OVER_TCP) 25 | rm -f core 26 | 27 | -------------------------------------------------------------------------------- /Makefile.linux: -------------------------------------------------------------------------------- 1 | CFLAGS=-I./src 2 | 3 | 4 | GNB_UDP_OVER_TCP=gnb_udp_over_tcp 5 | 6 | 7 | include Makefile.inc 8 | 9 | 10 | GNB_EVENT_OBJS += ./src/event/epoll_event_handler.o 11 | GNB_EVENT_OBJS += ./src/event/select_event_handler.o 12 | 13 | all:$(GNB_UDP_OVER_TCP) 14 | 15 | $(GNB_UDP_OVER_TCP): $(GNB_UDP_OVER_TCP_OBJS) $(GNB_EVENT_OBJS) 16 | $(CC) -o ${GNB_UDP_OVER_TCP} $(GNB_UDP_OVER_TCP_OBJS) $(GNB_EVENT_OBJS) 17 | 18 | 19 | %.o:%.c 20 | $(CC) -c -o $@ $< $(CFLAGS) 21 | 22 | 23 | clean: 24 | rm -f src/*.o 25 | rm -f ./libs/hash/*.o 26 | rm -f src/service/*.o src/event/*.o 27 | rm -f $(GNB_UDP_OVER_TCP) *.exe 28 | rm -f core 29 | 30 | -------------------------------------------------------------------------------- /src/gnb_buf_type.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_buf_type_h 2 | #define gnb_buf_type_h 3 | 4 | typedef struct _gnb_buf_t{ 5 | 6 | unsigned char *start; 7 | unsigned char *end; 8 | 9 | unsigned char *pos; 10 | unsigned char *las; 11 | 12 | }gnb_buf_t; 13 | 14 | 15 | //the z mean Arrays of Length Zero 16 | typedef struct _gnb_zbuf_t{ 17 | 18 | unsigned char *start; 19 | unsigned char *end; 20 | 21 | unsigned char *pos; 22 | unsigned char *las; 23 | 24 | unsigned char block[0]; 25 | 26 | }gnb_zbuf_t; 27 | 28 | 29 | #define GNB_BUF_LEN(b) (int)(b->las - b->pos) 30 | 31 | #define GNB_BUF_REMAIN(b) (int)(b->end - b->las) 32 | 33 | #define GNB_BUF_SIZE(b) (int)(b->end - b->start) 34 | 35 | #define GNB_BUF_RESET(zbuf) zbuf->pos=zbuf->las=zbuf->start 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/gnb_fixed_list_store.c: -------------------------------------------------------------------------------- 1 | #include "gnb_fixed_list_store.h" 2 | 3 | #include 4 | 5 | gnb_fixed_list_store_t* gnb_fixed_list_store_create(gnb_heap_t *heap,uint32_t size, uint32_t block_size){ 6 | 7 | gnb_fixed_list_store_t *fixed_list_store = (gnb_fixed_list_store_t *)gnb_heap_alloc(heap, sizeof(gnb_fixed_list_store_t) + size*sizeof(void*) + block_size *size); 8 | 9 | int i; 10 | 11 | void *p = fixed_list_store->array + size*sizeof(void*); 12 | 13 | for( i=0; iarray[i] = p; 16 | } 17 | 18 | fixed_list_store->num = 0; 19 | fixed_list_store->size = size; 20 | 21 | return fixed_list_store; 22 | 23 | } 24 | 25 | 26 | void gnb_fixed_list_store_release(gnb_heap_t *heap, gnb_fixed_list_store_t *fixed_list_store){ 27 | gnb_heap_free(heap,fixed_list_store); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/gnb_fixed_list.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_fixed_list_h 2 | #define gnb_fixed_list_h 3 | 4 | #include "gnb_alloc.h" 5 | 6 | typedef struct _gnb_fixed_list_data_t{ 7 | 8 | uint32_t idx; 9 | void *udata; 10 | 11 | }gnb_fixed_list_data_t; 12 | 13 | 14 | typedef struct _gnb_fixed_list_t{ 15 | 16 | gnb_heap_t *heap; 17 | 18 | uint32_t size; 19 | 20 | uint32_t num; 21 | 22 | void *block; 23 | 24 | gnb_fixed_list_data_t **array; 25 | 26 | }gnb_fixed_list_t; 27 | 28 | 29 | gnb_fixed_list_t* gnb_fixed_list_create(gnb_heap_t *heap,uint32_t size); 30 | 31 | void gnb_fixed_list_release(gnb_fixed_list_t *list); 32 | 33 | gnb_fixed_list_data_t* gnb_fixed_list_push(gnb_fixed_list_t *list, void *udata); 34 | 35 | void gnb_fixed_list_pop(gnb_fixed_list_t *list, gnb_fixed_list_data_t *fixed_list_node); 36 | 37 | #define GNB_FIX_LIST_UDATA(list_data) (list_data!=NULL?list_data->udata:NULL) 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /libs/hash/murmurhash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //from nginx source code 5 | uint32_t murmurhash_hash(unsigned char *data, size_t len){ 6 | 7 | uint32_t h, k; 8 | 9 | h = 0 ^ (uint32_t)len; 10 | 11 | while (len >= 4) { 12 | k = data[0]; 13 | k |= data[1] << 8; 14 | k |= data[2] << 16; 15 | k |= data[3] << 24; 16 | 17 | k *= 0x5bd1e995; 18 | k ^= k >> 24; 19 | k *= 0x5bd1e995; 20 | 21 | h *= 0x5bd1e995; 22 | h ^= k; 23 | 24 | data += 4; 25 | len -= 4; 26 | } 27 | 28 | switch (len) { 29 | case 3: 30 | h ^= data[2] << 16; 31 | /* fall through */ 32 | case 2: 33 | h ^= data[1] << 8; 34 | /* fall through */ 35 | case 1: 36 | h ^= data[0]; 37 | h *= 0x5bd1e995; 38 | } 39 | 40 | h ^= h >> 13; 41 | h *= 0x5bd1e995; 42 | h ^= h >> 15; 43 | 44 | return h; 45 | } 46 | -------------------------------------------------------------------------------- /src/gnb_platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_PLATFORM_H 19 | #define GNB_PLATFORM_H 20 | 21 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) 22 | #define __UNIX_LIKE_OS__ 1 23 | #endif 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /Makefile.inc: -------------------------------------------------------------------------------- 1 | GNB_EVENT_OBJS = \ 2 | ./src/gnb_event.o \ 3 | ./src/gnb_network_service.o \ 4 | ./src/gnb_address.o \ 5 | ./src/gnb_buf.o \ 6 | ./src/gnb_lru32.o \ 7 | ./src/gnb_doubly_linked_list.o \ 8 | ./src/gnb_hash32.o \ 9 | ./libs/hash/murmurhash.o \ 10 | ./src/gnb_payload16.o \ 11 | ./src/gnb_time.o \ 12 | ./src/gnb_fixed_list.o \ 13 | ./src/gnb_fixed_list_store.o \ 14 | ./src/gnb_fixed_pool.o \ 15 | ./src/gnb_alloc.o 16 | 17 | 18 | GNB_UDP_OVER_TCP_OBJS = \ 19 | ./src/service/gnb_udp_over_tcp.o \ 20 | ./src/service/uot_udp_service.o \ 21 | ./src/service/uot_tcp_service.o \ 22 | ./src/gnb_daemon.o \ 23 | ./src/gnb_log.o 24 | 25 | -------------------------------------------------------------------------------- /src/gnb_block.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_BLOCK_H 19 | #define GNB_BLOCK_H 20 | 21 | #include 22 | 23 | typedef struct _gnb_block32_t { 24 | uint32_t size; 25 | unsigned char data[0]; 26 | }gnb_block32_t; 27 | 28 | 29 | #define GNB_BLOCK_VOID(block) *(void **)&block->data 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/gnb_fixed_pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_FIXED_POOL_H 19 | #define GNB_FIXED_POOL_H 20 | 21 | #include 22 | 23 | #include "gnb_alloc.h" 24 | 25 | typedef struct _gnb_fixed_pool_t gnb_fixed_pool_t; 26 | 27 | gnb_fixed_pool_t* gnb_fixed_pool_create(gnb_heap_t *heap, uint32_t array_len, uint32_t bsize); 28 | 29 | void* gnb_fixed_pool_pop(gnb_fixed_pool_t *fixed_pool); 30 | 31 | uint32_t gnb_fixed_pool_push(gnb_fixed_pool_t *fixed_pool, void *block); 32 | 33 | void gnb_fixed_pool_release(gnb_heap_t *heap,gnb_fixed_pool_t *fixed_pool); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/gnb_event.c: -------------------------------------------------------------------------------- 1 | #include "gnb_platform.h" 2 | 3 | #include "gnb_event.h" 4 | 5 | 6 | #if defined(__UNIX_LIKE_OS__) 7 | extern gnb_event_cmd select_event_cmd; 8 | #endif 9 | 10 | 11 | #if defined(__linux__) 12 | extern gnb_event_cmd epoll_event_cmd; 13 | #endif 14 | 15 | #if defined(__FreeBSD__) 16 | extern gnb_event_cmd kqueue_event_cmd; 17 | #endif 18 | 19 | 20 | #if defined(__OpenBSD__) 21 | extern gnb_event_cmd kqueue_event_cmd; 22 | #endif 23 | 24 | #if defined(__APPLE__) 25 | extern gnb_event_cmd kqueue_event_cmd; 26 | #endif 27 | 28 | 29 | #if defined(_WIN32) 30 | extern gnb_event_cmd select_event_cmd; 31 | #endif 32 | 33 | 34 | gnb_event_cmd* gnb_create_event_cmd(){ 35 | 36 | int i; 37 | gnb_event_cmd *event_cmd; 38 | 39 | 40 | #if defined(__FreeBSD__) 41 | event_cmd = &kqueue_event_cmd; 42 | #endif 43 | 44 | 45 | #if defined(__OpenBSD__) 46 | event_cmd = &kqueue_event_cmd; 47 | #endif 48 | 49 | #if defined(__APPLE__) 50 | event_cmd = &kqueue_event_cmd; 51 | #endif 52 | 53 | 54 | #if defined(__linux__) 55 | event_cmd = &epoll_event_cmd; 56 | #endif 57 | 58 | #if defined(_WIN32) 59 | event_cmd = &select_event_cmd; 60 | #endif 61 | 62 | //For Test!! 63 | //event_cmd = &select_event_cmd; 64 | //event_cmd = &kqueue_event_cmd; 65 | 66 | return event_cmd; 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/gnb_alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_ALLOC_H 19 | #define GNB_ALLOC_H 20 | 21 | #include 22 | #include 23 | 24 | typedef struct _gnb_heap_fragment_t gnb_heap_fragment_t; 25 | 26 | typedef struct _gnb_heap_t{ 27 | 28 | uint32_t max_fragment; 29 | uint32_t fragment_nums; 30 | uint32_t alloc_byte; 31 | uint32_t ralloc_byte; 32 | gnb_heap_fragment_t *fragment_list[0]; 33 | 34 | }gnb_heap_t; 35 | 36 | gnb_heap_t* gnb_heap_create(uint32_t max_fragment); 37 | 38 | void* gnb_heap_alloc(gnb_heap_t *gnb_heap, uint32_t size); 39 | 40 | void gnb_heap_free(gnb_heap_t *gnb_heap, void *p); 41 | 42 | void gnb_heap_clean(gnb_heap_t *gnb_heap); 43 | 44 | void gnb_heap_release(gnb_heap_t *gnb_heap); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/service/gnb_udp_over_tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_udp_over_tcp_h 2 | #define gnb_udp_over_tcp_h 3 | 4 | #include 5 | 6 | #include "gnb_platform.h" 7 | #include "gnb_payload16.h" 8 | 9 | #define UTO_MAX_TCP_PAYLOAD_SIZE 4096 10 | 11 | #define GNB_UOT_KEEPALIVE_TIMEOUT_SEC 15 12 | 13 | typedef struct _udp_over_tcp_service_conf_t{ 14 | 15 | int tcp; 16 | int udp; 17 | 18 | uint16_t listen_port; 19 | 20 | #ifdef __UNIX_LIKE_OS__ 21 | uint8_t daemon; 22 | #endif 23 | 24 | char *tcp_address; 25 | uint16_t tcp_port; 26 | 27 | char *des_udp_address; 28 | uint16_t des_udp_port; 29 | 30 | }udp_over_tcp_service_conf_t; 31 | 32 | #define GNB_LOG_ID_UOT 1 33 | 34 | 35 | #define GNB_PAYLOAD_TYPE_TCP_KEEPALIVE 'k' 36 | #define GNB_PAYLOAD_SUB_TYPE_TCP_PING 'r' 37 | #define GNB_PAYLOAD_SUB_TYPE_TCP_PONG 'p' 38 | 39 | #define GNB_PAYLOAD_TYPE_UDP_OVER_TCP 'o' 40 | #define GNB_PAYLOAD_SUB_TYPE_UDP_TO_TCP 'u' 41 | #define GNB_PAYLOAD_SUB_TYPE_TCP_TO_UDP 't' 42 | 43 | 44 | #pragma pack(push, 1) 45 | 46 | typedef struct _uot_keepalive_frame_t { 47 | 48 | uint64_t src_ts_usec; 49 | 50 | unsigned char text[16]; 51 | 52 | }__attribute__ ((__packed__)) uot_keepalive_frame_t; 53 | 54 | #pragma pack(pop) 55 | 56 | typedef struct _uot_channel_t{ 57 | 58 | gnb_connection_t *tcp_conn; 59 | 60 | gnb_connection_t *udp_conn; 61 | 62 | gnb_payload16_ctx_t *gnb_payload16_ctx; 63 | 64 | gnb_network_service_t *service; 65 | 66 | uint64_t last_reconnect_time_sec; 67 | uint64_t keepalive_ts_sec; 68 | uint64_t last_send_keepalive_ts_sec; 69 | 70 | }uot_channel_t; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/gnb_time.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_TIME_H 19 | #define GNB_TIME_H 20 | 21 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) 22 | #define __UNIX_LIKE_OS__ 1 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | uint64_t gnb_timestamp_sec(); 30 | 31 | /*微秒*/ 32 | uint64_t gnb_timestamp_usec(); 33 | 34 | 35 | //format:"%Y_%m_%d_%H.%M.%S" 36 | void gnb_now_timef(const char *format, char *buffer, size_t buffer_size); 37 | 38 | void gnb_timef(const char *format, time_t t, char *buffer, size_t buffer_size); 39 | 40 | /* 41 | 获得当前月的当天数字 42 | */ 43 | int gnb_now_mday(); 44 | 45 | int gnb_now_yday(); 46 | 47 | #define GNB_TIME_STRING_MAX 64 48 | 49 | #ifdef __UNIX_LIKE_OS__ 50 | #define GNB_SLEEP_MILLISECOND(millisecond) usleep(1000 * millisecond) 51 | #endif 52 | 53 | #if defined(_WIN32) 54 | #define GNB_SLEEP_MILLISECOND(millisecond) Sleep(millisecond) 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/gnb_daemon.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gnb_platform.h" 24 | 25 | #ifdef __UNIX_LIKE_OS__ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #endif 33 | 34 | 35 | #ifdef __UNIX_LIKE_OS__ 36 | 37 | int gnb_daemon(){ 38 | 39 | int ret; 40 | 41 | int fd; 42 | 43 | pid_t pid; 44 | 45 | pid = fork(); 46 | 47 | if ( 0 != pid ){ 48 | exit(0); 49 | } 50 | 51 | setsid(); 52 | 53 | signal(SIGHUP,SIG_IGN); 54 | 55 | pid = fork(); 56 | 57 | if ( 0 != pid ){ 58 | exit(0); 59 | } 60 | 61 | ret = chdir("/"); 62 | 63 | umask(0); 64 | 65 | fd = open("/dev/null", O_RDWR); 66 | 67 | if ( -1 == fd ){ 68 | return -1; 69 | } 70 | 71 | ret = dup2(fd, STDIN_FILENO); 72 | 73 | if ( -1 == ret ) { 74 | return -2; 75 | } 76 | 77 | ret = dup2(fd, STDOUT_FILENO); 78 | 79 | if ( -1 == ret ) { 80 | return -3; 81 | } 82 | 83 | return 0; 84 | 85 | } 86 | 87 | 88 | void save_pid(const char *pid_file){ 89 | 90 | FILE *file; 91 | 92 | file = fopen(pid_file,"w"); 93 | 94 | if (NULL==file){ 95 | printf("open pid file[%s] err\n",pid_file); 96 | exit(1); 97 | } 98 | 99 | int pid = getpid(); 100 | 101 | fprintf(file,"%d",pid); 102 | 103 | fclose(file); 104 | 105 | } 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/gnb_log_type.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_LOG_TYPE_H 19 | #define GNB_LOG_TYPE_H 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef _WIN32 26 | 27 | #ifndef NAME_MAX 28 | #define NAME_MAX 255 29 | #endif 30 | 31 | #endif 32 | 33 | typedef struct _gnb_log_config_t { 34 | 35 | char log_name[20]; 36 | 37 | uint8_t console_level; 38 | 39 | uint8_t file_level; 40 | 41 | uint8_t udp_level; 42 | 43 | }gnb_log_config_t; 44 | 45 | #define GNB_MAX_LOG_ID 128 46 | 47 | typedef struct _gnb_log_ctx_t { 48 | 49 | #define GNB_LOG_OUTPUT_NONE (0x0) 50 | #define GNB_LOG_OUTPUT_STDOUT (0x1) 51 | #define GNB_LOG_OUTPUT_FILE (0x1 << 1) 52 | #define GNB_LOG_OUTPUT_UDP (0x1 << 2) 53 | 54 | unsigned char output_type; 55 | 56 | char log_file_path[PATH_MAX]; 57 | 58 | //char log_file_prefix[32]; 59 | 60 | char log_file_name_std[PATH_MAX+NAME_MAX]; 61 | char log_file_name_debug[PATH_MAX+NAME_MAX]; 62 | char log_file_name_error[PATH_MAX+NAME_MAX]; 63 | 64 | 65 | int std_fd; 66 | int debug_fd; 67 | int error_fd; 68 | 69 | 70 | int pre_std_fd; 71 | int pre_debug_fd; 72 | int pre_error_fd; 73 | 74 | 75 | int pre_mday; 76 | 77 | uint8_t addr4[4]; 78 | uint16_t port4; 79 | 80 | uint8_t addr6[16]; 81 | uint16_t port6; 82 | 83 | int socket6_fd; 84 | int socket4_fd; 85 | 86 | 87 | #define GNB_LOG_UDP_TYPE_TEXT 0 88 | #define GNB_LOG_UDP_TYPE_BINARY 1 89 | uint8_t log_udp_type; 90 | 91 | //如果 log_udp_type 为 GNB_LOG_UDP_TYPE_BINARY,就需要提供gnb_payload的类型 92 | char log_payload_type; 93 | 94 | gnb_log_config_t config_table[GNB_MAX_LOG_ID]; 95 | 96 | }gnb_log_ctx_t; 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /src/gnb_doubly_linked_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_DOUBLY_LINKED_LIST_H 19 | #define GNB_DOUBLY_LINKED_LIST_H 20 | 21 | #include 22 | 23 | #include "gnb_alloc.h" 24 | 25 | typedef struct _gnb_doubly_linked_list_node_t gnb_doubly_linked_list_node_t; 26 | 27 | typedef struct _gnb_doubly_linked_list_t gnb_doubly_linked_list_t; 28 | 29 | typedef struct _gnb_doubly_linked_list_node_t{ 30 | 31 | gnb_doubly_linked_list_node_t *pre; 32 | 33 | gnb_doubly_linked_list_node_t *nex; 34 | 35 | void *data; 36 | 37 | }gnb_doubly_linked_list_node_t; 38 | 39 | 40 | typedef struct _gnb_doubly_linked_list_t{ 41 | 42 | gnb_heap_t *heap; 43 | 44 | gnb_doubly_linked_list_node_t *head; 45 | 46 | gnb_doubly_linked_list_node_t *tail; 47 | 48 | uint32_t num; 49 | 50 | }gnb_doubly_linked_list_t; 51 | 52 | 53 | void gnb_doubly_linked_list_node_set(gnb_doubly_linked_list_node_t *dl_node,void *data); 54 | 55 | 56 | gnb_doubly_linked_list_t* gnb_doubly_linked_list_create(gnb_heap_t *heap); 57 | void gnb_doubly_linked_list_release(gnb_doubly_linked_list_t *doubly_linked_list); 58 | 59 | 60 | int gnb_doubly_linked_list_add(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node); 61 | 62 | gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_head(gnb_doubly_linked_list_t *doubly_linked_list); 63 | gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_tail(gnb_doubly_linked_list_t *doubly_linked_list); 64 | 65 | 66 | int gnb_doubly_linked_list_pop(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node); 67 | 68 | int gnb_doubly_linked_list_move_head(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gnb_udp_over_tcp 2 | [GNB](https://github.com/gnbdev/gnb "GNB")是一个开源的去中心化的具有极致内网穿透能力的通过P2P进行三层网络交换的VPN。 3 | 4 | GNB节点间通过UDP协议传输数据,在一些网络环境下的路由器/防火墙会对UDP分组实施QOS策略,因此通过tcp链路转发GNB数据是不需要改动GNB通讯协议又可以提升GNB网络适应能力的一个办法。 5 | 6 | gnb_udp_over_tcp 是一个为GNB开发的通过tcp链路中转UDP分组转发的服务。 7 | 8 | # 通过 gnb_udp_over_tcp 中继 GNB 数据 9 | 10 | ## 演示环境 11 | 远端GNB节点 ip地址 为 192.168.1.25 12 | GNB UDP 端口 9025 13 | GNB TUN ip 10.1.0.25 14 | 远端 GNB 配置文件不需要调整 15 | 16 | 中继服务器 ip地址为 192.168.1.11 17 | ``` 18 | [gnb_1010] 19 | | 20 | udp 21 | | 22 | [udp_over_tcp udp:127.0.0.1:5001] (./gnb_udp_over_tcp -u -l 5001 192.168.1.11 6000) 23 | | 24 | tcp 25 | | 26 | [udp_over_tcp tcp:192.168.1.11:6000] (./gnb_udp_over_tcp -t -l 6000 192.168.1.25 9025) 27 | | 28 | udp 29 | | 30 | [gnb_1025 udp:192.168.1.25:9025] 31 | ``` 32 | 33 | 在 192.168.1.11 上执行 34 | ```sh 35 | ./gnb_udp_over_tcp -t -l 6000 192.168.1.25 9025 36 | ``` 37 | 38 | 本地ip地址为 192.168.1.10 39 | GNB TUN ip 10.1.0.10 40 | 41 | 42 | 本地 GNB conf/1010/address.conf 内容为 43 | ``` 44 | n|1025|127.0.0.1|5001 45 | ``` 46 | 47 | address.conf中不要配置 i 类型的GNB节点 48 | 49 | 在 192.168.1.10 上执行 50 | ```sh 51 | ./gnb_udp_over_tcp -u -l 5001 192.168.1.11 6000 52 | ``` 53 | 启动本地的GNB节点后 ping 10.1.0.25 检验是否能够ping通。 54 | 55 | 56 | 57 | # gnb_udp_over_tcp可以为其他基于UDP协议的服务中转数据 58 | ## 用nc作本地测试演示 59 | ``` 60 | [netcat] (nc -u 127.0.0.1 5001) 61 | | 62 | udp 63 | | 64 | [udp_over_tcp udp:127.0.0.1:5001] (./gnb_udp_over_tcp -u -l 5001 127.0.0.1 6000) 65 | | 66 | tcp 67 | | 68 | [udp_over_tcp tcp:127.0.0.1:6000] (./gnb_udp_over_tcp -t -l 6000 127.0.0.1 7000) 69 | | 70 | udp 71 | | 72 | [netcat udp:127.0.0.1:7000] (nc -u -l 7000) 73 | ``` 74 | 75 | ## Step1 76 | 用 nc 监听 7000 udp 端口 77 | 78 | ```sh 79 | nc -u -l 7000 80 | ``` 81 | 82 | ## Step2 83 | 启动 gnb_udp_over_tcp 的 tcp端: 监听 tcp 6000 端口,每个接入该端口的tcp链路将建立起一个udp socket构成一个channel,tcp链路收到的报文发往 127.0.0.1 的 UDP 7000端口,从udp端收到的数据将发往tcp链路的另一端。 84 | gnb_udp_over_tcp的tcp端可以同时接入多个tcp连接并且转发到同一个目的地址的udp端口。 85 | 86 | ```sh 87 | ./gnb_udp_over_tcp -t -l 6000 127.0.0.1 7000 88 | ``` 89 | 90 | 91 | ## Step3 92 | 启动 gnb_udp_over_tcp 的 udp端: 监听 udp 5001 端口,与 127.0.0.1 tcp 端口 6000 建立tcp链路,udp 端收到的数据发往tcp链路的另一端,从tcp链路收到的数据发往udp端。 93 | ```sh 94 | ./gnb_udp_over_tcp -u -l 5001 127.0.0.1 6000 95 | ``` 96 | 97 | ## Step4 98 | 用 nc 访问 127.0.0.1 的 5001 udp 端口,检验数据是否被成功转发。 99 | 100 | ```sh 101 | nc -u 127.0.0.1 5001 102 | ``` 103 | 104 | --- 105 | [免责声明](docs/disclaimer.md) 106 | -------------------------------------------------------------------------------- /src/gnb_address_type.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_ADDRESS_TYPE_H 19 | #define GNB_ADDRESS_TYPE_H 20 | 21 | #include "gnb_platform.h" 22 | 23 | #ifdef __UNIX_LIKE_OS__ 24 | #include 25 | #include 26 | #endif 27 | 28 | 29 | #ifdef _WIN32 30 | #include 31 | #include 32 | #endif 33 | 34 | #include 35 | #include 36 | 37 | #define GNB_IP6_PORT_STRING_SIZE ( 46 + 2 + sizeof("65535") + 1 ) 38 | #define GNB_IP4_PORT_STRING_SIZE ( 16 + 1 + sizeof("65535") + 1 ) 39 | 40 | typedef struct _gnb_address_t{ 41 | 42 | int type; //AF_INET AF_INET6 43 | 44 | //更新该地址的 socket 索引 45 | uint8_t socket_idx; 46 | 47 | //最后更新时间 48 | uint64_t ts_sec; 49 | 50 | //延时 可以经过ping pong后算出 51 | uint64_t delay_usec; 52 | 53 | union{ 54 | uint8_t addr4[4]; 55 | uint8_t addr6[16]; 56 | }address; 57 | 58 | #define m_address4 address.addr4 59 | #define m_address6 address.addr6 60 | 61 | //网络字节序 62 | uint16_t port; 63 | 64 | }gnb_address_t; 65 | 66 | 67 | typedef struct _gnb_address_list_t{ 68 | 69 | size_t size; 70 | size_t num; 71 | uint64_t update_sec; 72 | gnb_address_t array[0]; 73 | 74 | }gnb_address_list_t; 75 | 76 | 77 | #define GNB_MAX_ADDR_RING 128 78 | 79 | typedef struct _gnb_address_ring_t{ 80 | 81 | int cur_index; 82 | 83 | gnb_address_list_t *address_list; 84 | 85 | }gnb_address_ring_t; 86 | 87 | 88 | typedef struct _gnb_sockaddress_t{ 89 | 90 | int addr_type; // AF_INET AF_INET6 91 | int protocol; //SOCK_STREAM SOCK_DGRAM 92 | 93 | union{ 94 | struct sockaddr_in in; 95 | struct sockaddr_in6 in6; 96 | }addr; 97 | #define m_in4 addr.in 98 | #define m_in6 addr.in6 99 | 100 | //在确定 addr_type 是 AF_INET 或 AF_INET6 后,就能确定这个长度了,可以去掉这个成员 101 | socklen_t socklen; 102 | 103 | }gnb_sockaddress_t; 104 | 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /src/gnb_time.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #ifdef _WIN32 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #define _POSIX_C_SOURCE 1 28 | //使得 localtime_r 等函数有效 29 | 30 | #endif 31 | 32 | #include 33 | #include 34 | 35 | #include "gnb_time.h" 36 | 37 | /*秒*/ 38 | uint64_t gnb_timestamp_sec(){ 39 | int ret; 40 | struct timeval cur_time; 41 | uint64_t u64; 42 | ret = gettimeofday(&cur_time,NULL); 43 | if (0!=ret) { 44 | return 0; 45 | } 46 | 47 | u64 = (uint64_t)cur_time.tv_sec; 48 | 49 | return u64; 50 | 51 | } 52 | 53 | uint64_t gnb_timestamp_usec(){ 54 | int ret; 55 | struct timeval cur_time; 56 | uint64_t u64; 57 | ret = gettimeofday(&cur_time,NULL); 58 | if (0!=ret) { 59 | return 0; 60 | } 61 | u64 = (uint64_t)cur_time.tv_sec*1000000 + cur_time.tv_usec; 62 | return u64; 63 | } 64 | 65 | 66 | 67 | void gnb_now_timef(const char *format, char *buffer, size_t buffer_size){ 68 | 69 | time_t t; 70 | 71 | struct tm ltm; 72 | 73 | time (&t); 74 | 75 | localtime_r(&t, <m); 76 | 77 | strftime (buffer,buffer_size,format,<m); 78 | 79 | } 80 | 81 | 82 | 83 | void gnb_timef(const char *format, time_t t, char *buffer, size_t buffer_size){ 84 | 85 | struct tm ltm; 86 | 87 | localtime_r(&t, <m); 88 | 89 | strftime (buffer,buffer_size,format,<m); 90 | 91 | } 92 | 93 | 94 | 95 | int gnb_now_mday(){ 96 | 97 | time_t t; 98 | 99 | struct tm ltm; 100 | 101 | time (&t); 102 | 103 | localtime_r(&t, <m); 104 | 105 | return ltm.tm_mday; 106 | 107 | } 108 | 109 | int gnb_now_yday(){ 110 | 111 | time_t t; 112 | 113 | struct tm ltm; 114 | 115 | time (&t); 116 | 117 | localtime_r(&t, <m); 118 | 119 | return ltm.tm_yday; 120 | 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/gnb_fixed_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stdlib.h" 3 | #include "string.h" 4 | 5 | #include "gnb_fixed_list.h" 6 | 7 | 8 | gnb_fixed_list_t* gnb_fixed_list_create(gnb_heap_t *heap,uint32_t size){ 9 | 10 | uint32_t i; 11 | 12 | gnb_fixed_list_t *list = (gnb_fixed_list_t *)gnb_heap_alloc(heap, sizeof(gnb_fixed_list_t)); 13 | 14 | memset(list, 0, sizeof(gnb_fixed_list_t)); 15 | 16 | list->heap = heap; 17 | 18 | list->block = (gnb_fixed_list_data_t *)gnb_heap_alloc(heap, sizeof(gnb_fixed_list_data_t) * size); 19 | 20 | list->array = (gnb_fixed_list_data_t **)gnb_heap_alloc(heap, sizeof(gnb_fixed_list_data_t *) * size); 21 | 22 | list->size = size; 23 | list->num = 0; 24 | 25 | void *p; 26 | 27 | p = list->block; 28 | 29 | for (i=0; isize; i++) { 30 | list->array[i] = p; 31 | p += sizeof(gnb_fixed_list_data_t); 32 | } 33 | 34 | return list; 35 | 36 | } 37 | 38 | 39 | gnb_fixed_list_data_t* gnb_fixed_list_push(gnb_fixed_list_t *list, void *udata){ 40 | 41 | if ( list->size == list->num ) { 42 | return NULL; 43 | } 44 | 45 | gnb_fixed_list_data_t *fixed_list_node = list->array[list->num]; 46 | 47 | fixed_list_node->udata = udata; 48 | 49 | fixed_list_node->idx = list->num; 50 | 51 | list->num++; 52 | 53 | return fixed_list_node; 54 | 55 | } 56 | 57 | 58 | void gnb_fixed_list_pop(gnb_fixed_list_t *list, gnb_fixed_list_data_t *fixed_list_node){ 59 | 60 | if ( 0 == list->num ) { 61 | //发生错误了 62 | return; 63 | } 64 | 65 | if ( 1 == list->num ) { 66 | list->num = 0; 67 | return; 68 | } 69 | 70 | gnb_fixed_list_data_t *last_node = list->array[list->num - 1]; 71 | 72 | if ( fixed_list_node->idx > (list->size-1) ) { 73 | //发生错误了 74 | return; 75 | } 76 | 77 | if ( last_node->idx > (list->size-1) ) { 78 | //发生错误了 79 | return; 80 | } 81 | 82 | if ( 1 == list->num ) { 83 | if ( fixed_list_node->idx != last_node->idx ){ 84 | //发生错误了 85 | return; 86 | } 87 | goto finish; 88 | } 89 | 90 | if( last_node->idx == fixed_list_node->idx ){ 91 | goto finish; 92 | } 93 | 94 | 95 | last_node->idx = fixed_list_node->idx; 96 | 97 | list->array[last_node->idx] = last_node; 98 | 99 | 100 | finish: 101 | 102 | list->num--; 103 | return; 104 | 105 | } 106 | 107 | 108 | void gnb_fixed_list_release(gnb_fixed_list_t *list){ 109 | 110 | gnb_heap_free(list->heap,list->block); 111 | gnb_heap_free(list->heap,list->array); 112 | gnb_heap_free(list->heap,list); 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/gnb_payload16.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_PAYLOAD16_H 19 | #define GNB_PAYLOAD16_H 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #pragma pack(push, 1) 28 | typedef struct _gnb_payload16_t{ 29 | uint16_t size; 30 | unsigned char type; 31 | unsigned char sub_type; 32 | unsigned char data[0]; 33 | } __attribute__ ((packed)) gnb_payload16_t; 34 | #pragma pack(pop) 35 | 36 | #define GNB_PAYLOAD16_HEAD_SIZE 4 37 | 38 | #define GNB_MAX_PAYLOAD_SIZE 65535 39 | 40 | gnb_payload16_t* gnb_payload16_init(char type,uint16_t data_size); 41 | 42 | gnb_payload16_t* gnb_payload16_create(char type, void *data, uint16_t data_size); 43 | 44 | gnb_payload16_t *gnb_payload16_dup(gnb_payload16_t *gnb_payload16_in); 45 | 46 | void gnb_payload16_free(gnb_payload16_t *gnb_payload16); 47 | 48 | uint16_t gnb_payload16_set_size(gnb_payload16_t *gnb_payload16, uint16_t new_size); 49 | 50 | uint16_t gnb_payload16_size(gnb_payload16_t *gnb_payload16); 51 | 52 | uint16_t gnb_payload16_set_data_len(gnb_payload16_t *gnb_payload16, uint16_t new_len); 53 | 54 | uint16_t gnb_payload16_data_len(gnb_payload16_t *gnb_payload16); 55 | 56 | typedef struct _gnb_payload16_ctx_t{ 57 | 58 | //当前 当前payload(frame) 已收到的字节数 59 | //r_len足2字节时,接收的数据存 gnb_payload 60 | //r_len 不足2字节时,接收的数据存 buffer 61 | int r_len; 62 | 63 | unsigned char buffer[2]; 64 | 65 | //传入payload 66 | gnb_payload16_t *gnb_payload16; 67 | //传入的 payload 内存块大小 68 | uint32_t max_payload_size; 69 | 70 | void *udata; 71 | 72 | }gnb_payload16_ctx_t; 73 | 74 | gnb_payload16_ctx_t* gnb_payload16_ctx_init(uint16_t max_payload_size); 75 | 76 | void gnb_payload16_ctx_free(gnb_payload16_ctx_t *gnb_payload16_ctx); 77 | 78 | typedef int (*gnb_payload16_handle_cb_t)(gnb_payload16_t *gnb_payload16, void *ctx); 79 | 80 | int gnb_payload16_handle(void *data, size_t data_size, gnb_payload16_ctx_t *gnb_payload16_ctx, gnb_payload16_handle_cb_t cb); 81 | 82 | #define GNB_PAYLOAD16_FRAME_SIZE(payload) gnb_payload16_size(payload) 83 | #define GNB_PAYLOAD16_DATA_SIZE(payload) gnb_payload16_data_len(payload) 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/gnb_fixed_pool.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include "gnb_fixed_pool.h" 22 | 23 | typedef struct _gnb_fixed_pool_t{ 24 | 25 | uint32_t num; 26 | 27 | uint32_t bsize; 28 | 29 | void *block; 30 | 31 | uint32_t array_len; 32 | 33 | void *array[0]; 34 | 35 | }gnb_fixed_pool_t; 36 | 37 | 38 | gnb_fixed_pool_t* gnb_fixed_pool_create(gnb_heap_t *heap, uint32_t array_len, uint32_t bsize){ 39 | 40 | gnb_fixed_pool_t *fixed_pool; 41 | 42 | fixed_pool = (gnb_fixed_pool_t *)gnb_heap_alloc(heap, sizeof(gnb_fixed_pool_t) + sizeof(void *) * array_len ); 43 | 44 | fixed_pool->num = array_len; 45 | 46 | fixed_pool->bsize = bsize; 47 | 48 | fixed_pool->block = gnb_heap_alloc(heap,bsize * array_len); 49 | 50 | memset(fixed_pool->block, 0, bsize * array_len); 51 | 52 | fixed_pool->array_len = array_len; 53 | 54 | int i; 55 | 56 | void *p; 57 | 58 | p = fixed_pool->block; 59 | 60 | for (i=0; iarray[i] = p; 62 | p += bsize; 63 | } 64 | 65 | return fixed_pool; 66 | 67 | } 68 | 69 | 70 | void* gnb_fixed_pool_pop(gnb_fixed_pool_t *fixed_pool){ 71 | 72 | if ( 0 == fixed_pool->num ){ 73 | return NULL; 74 | } 75 | 76 | void *block; 77 | 78 | block = fixed_pool->array[fixed_pool->num-1]; 79 | 80 | fixed_pool->array[fixed_pool->num-1] = NULL; 81 | 82 | fixed_pool->num--; 83 | 84 | return block; 85 | 86 | } 87 | 88 | 89 | uint32_t gnb_fixed_pool_push(gnb_fixed_pool_t *fixed_pool, void *block){ 90 | 91 | if ( fixed_pool->array_len == fixed_pool->num ) { 92 | return 0; 93 | } 94 | 95 | if ( NULL != fixed_pool->array[fixed_pool->num] ){ 96 | return -1; 97 | } 98 | 99 | fixed_pool->array[fixed_pool->num] = block; 100 | 101 | fixed_pool->num++; 102 | 103 | return fixed_pool->num; 104 | 105 | } 106 | 107 | void gnb_fixed_pool_release(gnb_heap_t *heap,gnb_fixed_pool_t *fixed_pool){ 108 | gnb_heap_free(heap, fixed_pool->block); 109 | gnb_heap_free(heap, fixed_pool); 110 | } 111 | -------------------------------------------------------------------------------- /src/gnb_event.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_event_h 2 | #define gnb_event_h 3 | 4 | #include "gnb_alloc.h" 5 | 6 | #define MAX_GET_GNB_EVENT 100 7 | 8 | 9 | #define GNB_EVENT_OP_ADD (0x0) 10 | #define GNB_EVENT_OP_DEL (0x1) 11 | #define GNB_EVENT_OP_ENABLE (0x1 << 1) 12 | #define GNB_EVENT_OP_DISABLE (0x1 << 2) 13 | 14 | 15 | typedef struct _gnb_event_t { 16 | 17 | int fd; 18 | 19 | #define GNB_EVENT_FD_TCP4_LISTEN 0x8 20 | #define GNB_EVENT_FD_TCP6_LISTEN 0x4 21 | #define GNB_EVENT_FD_TCPV4_CONNECT 0x3 22 | #define GNB_EVENT_FD_TCPV6_CONNECT 0x1 23 | #define GNB_EVENT_FD_UDP4_SOCKET 0x2 24 | #define GNB_EVENT_FD_UDP6_SOCKET 0x7 25 | int fd_type; 26 | 27 | void *udata; 28 | 29 | #define GNB_EVENT_TYPE_NONE (0x0) 30 | #define GNB_EVENT_TYPE_READ (0x1) 31 | #define GNB_EVENT_TYPE_WRITE (0x1 << 1) 32 | #define GNB_EVENT_TYPE_TIMER (0x1 << 2) 33 | #define GNB_EVENT_TYPE_EOF (0x1 << 3) 34 | #define GNB_EVENT_TYPE_ERROR (0x1 << 4) 35 | 36 | 37 | //在处理事件过程中如果遇到这个标记位意味着 这个事件已经处理完,event已经放回 event_fixed_pool 中,该事件不需要再处理了 38 | //出现这种情况的原因是在 gnb_get_event_cmd 过程中 一个conn有1个以上的事件出现在ev_lst中,例如在 kqueue中可能 同时有读与写的事件又或者一个写事件和连接断开的事件, 39 | //当处理 handler 在处理第一个事件时关闭释放了这个 conn 的资源,会把event标记为GNB_EVENT_TYPE_FINISH,并把 event 放回 event_fixed_pool 40 | //此时 这个 event 对应内存块虽然可以访问,但是这个event已不再关联到conn等资源了,GNB_EVENT_TYPE_FINISH 这个标志位就是告知事件处理过程不要处理这个event。 41 | #define GNB_EVENT_TYPE_FINISH (0x1 << 5) 42 | int ev_type; 43 | 44 | int index; 45 | 46 | void *uevent; 47 | 48 | }gnb_event_t; 49 | 50 | 51 | typedef struct _gnb_event_array_t{ 52 | 53 | size_t size; 54 | 55 | size_t nevent; 56 | 57 | gnb_event_t *list[0]; 58 | 59 | }gnb_event_array_t; 60 | 61 | 62 | typedef struct _gnb_event_cmd gnb_event_cmd; 63 | 64 | 65 | typedef int (*gnb_init_event_cmd)(gnb_event_cmd *event_cmd, size_t max_event); 66 | 67 | typedef int (*gnb_add_event_cmd)(gnb_event_cmd *event_cmd, gnb_event_t *ev, int ev_type); 68 | 69 | typedef int (*gnb_set_event_cmd)(gnb_event_cmd *event_cmd, gnb_event_t *ev, int op, int ev_type); 70 | 71 | typedef int (*gnb_del_event_cmd)(gnb_event_cmd *event_cmd, gnb_event_t *ev); 72 | 73 | typedef int (*gnb_get_event_cmd)(gnb_event_cmd *event_cmd, gnb_event_t **ev_lst, int *num_ev); 74 | 75 | typedef int (*gnb_finish_event_cmd)(gnb_event_cmd *event_cmd); 76 | 77 | typedef struct _gnb_event_cmd { 78 | 79 | char *mod_name; 80 | 81 | gnb_heap_t *heap; 82 | 83 | struct _gnb_event_cmd *self; 84 | 85 | gnb_init_event_cmd init_event; 86 | gnb_add_event_cmd add_event; 87 | gnb_set_event_cmd set_event; 88 | gnb_del_event_cmd del_event; 89 | gnb_get_event_cmd get_event; 90 | gnb_finish_event_cmd finish_event; 91 | 92 | void *event_handler_ctx; 93 | 94 | }gnb_event_cmd; 95 | 96 | gnb_event_cmd* gnb_create_event_cmd(); 97 | 98 | #endif 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/gnb_alloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "stdlib.h" 19 | #include "string.h" 20 | 21 | #include "gnb_alloc.h" 22 | 23 | #ifndef offsetof 24 | #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 25 | #endif 26 | 27 | #ifndef container_of 28 | 29 | #define container_of(ptr, type, member) ({ \ 30 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 31 | (type *)( (char *)__mptr - offsetof(type,member) );}) 32 | #endif 33 | 34 | 35 | typedef struct _gnb_heap_fragment_t{ 36 | uint32_t size; 37 | uint32_t idx; 38 | unsigned char block[0]; 39 | }gnb_heap_fragment_t; 40 | 41 | 42 | gnb_heap_t* gnb_heap_create(uint32_t max_fragment){ 43 | 44 | gnb_heap_t *gnb_heap = (gnb_heap_t *)malloc( sizeof(gnb_heap_t) + sizeof(gnb_heap_fragment_t) * max_fragment ); 45 | 46 | if (NULL==gnb_heap) { 47 | return NULL; 48 | } 49 | 50 | memset(gnb_heap, 0, sizeof(gnb_heap_t)); 51 | 52 | gnb_heap->max_fragment = max_fragment; 53 | gnb_heap->fragment_nums = 0; 54 | 55 | return gnb_heap; 56 | 57 | } 58 | 59 | 60 | void* gnb_heap_alloc(gnb_heap_t *gnb_heap, uint32_t size){ 61 | 62 | if ( 0 == size ) { 63 | return NULL; 64 | } 65 | 66 | if ( gnb_heap->max_fragment == gnb_heap->fragment_nums ) { 67 | printf("gnb heap is full\n"); 68 | exit(0); 69 | return NULL; 70 | } 71 | 72 | if ( size > (uint32_t)(1024l * 1024l * 1024l) - 1 ) { 73 | return NULL; 74 | } 75 | 76 | gnb_heap_fragment_t *fragment = malloc( sizeof(gnb_heap_fragment_t) + sizeof(unsigned char) * size ); 77 | 78 | if ( NULL == fragment ) { 79 | return NULL; 80 | } 81 | 82 | fragment->idx = gnb_heap->fragment_nums; 83 | gnb_heap->fragment_list[ gnb_heap->fragment_nums ] = fragment; 84 | gnb_heap->fragment_nums++; 85 | 86 | gnb_heap->alloc_byte += size; 87 | gnb_heap->ralloc_byte += sizeof(gnb_heap_fragment_t)+size; 88 | 89 | return (void *)fragment->block; 90 | 91 | } 92 | 93 | 94 | void gnb_heap_free(gnb_heap_t *gnb_heap, void *p){ 95 | 96 | gnb_heap_fragment_t *fragment; 97 | 98 | if ( 0 == gnb_heap->fragment_nums ) { 99 | //发生错误了 100 | return; 101 | } 102 | 103 | if ( NULL == p ) { 104 | return; 105 | } 106 | 107 | fragment = container_of(p, struct _gnb_heap_fragment_t, block); 108 | 109 | gnb_heap_fragment_t *last_fragment = gnb_heap->fragment_list[gnb_heap->fragment_nums - 1]; 110 | 111 | if ( fragment->idx > (gnb_heap->max_fragment-1) ) { 112 | //发生错误了 113 | return; 114 | } 115 | 116 | if ( last_fragment->idx > (gnb_heap->max_fragment-1) ) { 117 | //发生错误了 118 | return; 119 | } 120 | 121 | if ( 1 == gnb_heap->fragment_nums ) { 122 | if ( fragment->idx != last_fragment->idx ){ 123 | //发生错误了 124 | return; 125 | } 126 | goto finish; 127 | } 128 | 129 | if( last_fragment->idx == fragment->idx ){ 130 | goto finish; 131 | } 132 | 133 | gnb_heap->alloc_byte -= fragment->size; 134 | gnb_heap->ralloc_byte -= (sizeof(gnb_heap_fragment_t)+fragment->size); 135 | 136 | last_fragment->idx = fragment->idx; 137 | 138 | gnb_heap->fragment_list[last_fragment->idx] = last_fragment; 139 | 140 | finish: 141 | 142 | gnb_heap->fragment_nums--; 143 | 144 | free(fragment); 145 | 146 | } 147 | 148 | 149 | void gnb_heap_clean(gnb_heap_t *gnb_heap){ 150 | 151 | int i; 152 | 153 | if( 0 == gnb_heap->fragment_nums ){ 154 | return; 155 | } 156 | 157 | for ( i=0; i < gnb_heap->fragment_nums; i++ ) { 158 | free(gnb_heap->fragment_list[i]); 159 | } 160 | 161 | gnb_heap->fragment_nums = 0; 162 | gnb_heap->alloc_byte = 0; 163 | gnb_heap->ralloc_byte = 0; 164 | 165 | } 166 | 167 | 168 | void gnb_heap_release(gnb_heap_t *gnb_heap){ 169 | 170 | gnb_heap_clean(gnb_heap); 171 | 172 | free(gnb_heap); 173 | 174 | } 175 | -------------------------------------------------------------------------------- /src/gnb_address.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_ADDRESS_H 19 | #define GNB_ADDRESS_H 20 | 21 | #include "gnb_address_type.h" 22 | 23 | #define GNB_ADDRESS_LIFE_TIME_TS_SEC 120 24 | #define GNB_ADDRESS_AVAILABLE(address,now_sec) (now_sec - address->ts_sec) < GNB_ADDRESS_LIFE_TIME_TS_SEC ? 1:0 25 | 26 | /* 27 | 当 gnb_addr_secure 为非零时将不输出的完整的ip地址 28 | */ 29 | extern uint8_t gnb_addr_secure; 30 | 31 | 32 | unsigned long long gnb_ntohll(unsigned long long val); 33 | unsigned long long gnb_htonll(unsigned long long val); 34 | 35 | char get_netmask_class(uint32_t addr4); 36 | 37 | gnb_address_list_t* gnb_create_address_list(size_t size); 38 | void gnb_address_list_release(gnb_address_list_t *address_list); 39 | 40 | //返回 -1 没有找到, >0 为 address 在 list 中的索引编号 41 | int gnb_address_list_find(gnb_address_list_t *address_list, gnb_address_t *address); 42 | 43 | //把 address 放进列表中一个空的项里 44 | void gnb_address_list_update(gnb_address_list_t *address_list, gnb_address_t *address); 45 | 46 | 47 | void gnb_set_address4(gnb_address_t *address, struct sockaddr_in *in); 48 | void gnb_set_address6(gnb_address_t *address, struct sockaddr_in6 *in6); 49 | 50 | static char gnb_static_ip_port_string_buffer1[GNB_IP6_PORT_STRING_SIZE]; 51 | static char gnb_static_ip_port_string_buffer2[GNB_IP6_PORT_STRING_SIZE]; 52 | static char gnb_static_ip_port_string_buffer3[GNB_IP6_PORT_STRING_SIZE]; 53 | 54 | char * gnb_get_ip_port_string(gnb_address_t *address, char *dest, uint8_t addr_secure); 55 | 56 | #define GNB_IP_PORT_STR1(address) gnb_get_ip_port_string(address,gnb_static_ip_port_string_buffer1,gnb_addr_secure) 57 | #define GNB_IP_PORT_STR2(address) gnb_get_ip_port_string(address,gnb_static_ip_port_string_buffer2,gnb_addr_secure) 58 | 59 | 60 | char * gnb_get_address4string(void *byte4, char *dest, uint8_t addr_secure); 61 | char * gnb_get_address6string(void *byte16, char *dest, uint8_t addr_secure); 62 | 63 | #define GNB_ADDR4STR1(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer1,gnb_addr_secure) 64 | #define GNB_ADDR4STR2(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer2,gnb_addr_secure) 65 | #define GNB_ADDR6STR1(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer1,gnb_addr_secure) 66 | #define GNB_ADDR6STR2(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer2,gnb_addr_secure) 67 | 68 | 69 | #define GNB_ADDR4STR_PLAINTEXT1(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer1,0) 70 | #define GNB_ADDR4STR_PLAINTEXT2(byte4) gnb_get_address4string(byte4,gnb_static_ip_port_string_buffer2,0) 71 | #define GNB_ADDR6STR_PLAINTEXT1(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer1,0) 72 | #define GNB_ADDR6STR_PLAINTEXT2(byte16) gnb_get_address6string(byte16,gnb_static_ip_port_string_buffer2,0) 73 | 74 | 75 | char * gnb_get_socket4string(struct sockaddr_in *in, char *dest, uint8_t addr_secure); 76 | char * gnb_get_socket6string(struct sockaddr_in6 *in6, char *dest, uint8_t addr_secure); 77 | 78 | #define GNB_SOCKADDR4STR1(in) gnb_get_socket4string(in, gnb_static_ip_port_string_buffer1,gnb_addr_secure) 79 | #define GNB_SOCKADDR6STR1(in6) gnb_get_socket6string(in6,gnb_static_ip_port_string_buffer1,gnb_addr_secure) 80 | #define GNB_SOCKADDR4STR2(in) gnb_get_socket4string(in, gnb_static_ip_port_string_buffer2,gnb_addr_secure) 81 | #define GNB_SOCKADDR6STR2(in6) gnb_get_socket6string(in6,gnb_static_ip_port_string_buffer2,gnb_addr_secure) 82 | #define GNB_SOCKADDR4STR3(in) gnb_get_socket4string(in, gnb_static_ip_port_string_buffer3,gnb_addr_secure) 83 | #define GNB_SOCKADDR6STR3(in6) gnb_get_socket6string(in6,gnb_static_ip_port_string_buffer3,gnb_addr_secure) 84 | 85 | 86 | char * gnb_get_sockaddress_string(gnb_sockaddress_t *sockaddress,char *dest, uint8_t addr_secure); 87 | #define GNB_SOCKETADDRSTR1(sockaddress) gnb_get_sockaddress_string(sockaddress,gnb_static_ip_port_string_buffer1,gnb_addr_secure) 88 | 89 | int gnb_cmp_sockaddr_in6(struct sockaddr_in6 *in1, struct sockaddr_in6 *in2); 90 | int gnb_cmp_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2); 91 | 92 | 93 | #define GNB_PROTOCOL_UDP 0x1 94 | #define GNB_PROTOCOL_TCP 0x2 95 | void gnb_set_sockaddress4(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port); 96 | void gnb_set_sockaddress6(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port); 97 | 98 | gnb_address_t gnb_get_address4_from_string(const char *sockaddress4_string); 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/gnb_hash32.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_HASH32_H 19 | #define GNB_HASH32_H 20 | 21 | #include 22 | #include 23 | 24 | #ifndef __u_char_defined 25 | typedef unsigned char u_char; 26 | #define __u_char_defined 27 | #endif 28 | 29 | #include "gnb_alloc.h" 30 | #include "gnb_block.h" 31 | 32 | typedef struct _gnb_kv32_t gnb_kv32_t; 33 | 34 | typedef struct _gnb_kv32_t{ 35 | gnb_block32_t *key; 36 | gnb_block32_t *value; 37 | gnb_kv32_t *nex; 38 | }gnb_kv32_t; 39 | 40 | typedef struct _gnb_hash32_bucket_t gnb_hash32_bucket_t; 41 | 42 | typedef struct _gnb_hash32_map_t{ 43 | 44 | gnb_heap_t *heap; 45 | 46 | uint32_t bucket_num; 47 | 48 | uint32_t kv_num; 49 | 50 | gnb_hash32_bucket_t **buckets; 51 | 52 | } gnb_hash32_map_t; 53 | 54 | 55 | gnb_hash32_map_t *gnb_hash32_create(gnb_heap_t *heap, uint32_t bucket_num,uint32_t kv_num); 56 | 57 | void gnb_hash32_release(gnb_hash32_map_t *hash32_map); 58 | 59 | gnb_kv32_t* gnb_hash32_set(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len); 60 | 61 | int gnb_hash32_store(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len); 62 | 63 | gnb_kv32_t* gnb_hash32_get(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len); 64 | 65 | gnb_kv32_t* gnb_hash32_del(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len); 66 | 67 | void gnb_kv32_release(gnb_hash32_map_t *hash_map, gnb_kv32_t *kv); 68 | 69 | gnb_kv32_t** gnb_hash32_array(gnb_hash32_map_t *hash32_map, uint32_t *num); 70 | 71 | 72 | #define GNB_HASH32_UINT32_SET(hash32_map,uint32key,value) gnb_hash32_set(hash32_map,(u_char *)&uint32key,sizeof(uint32_t),value,0) 73 | #define GNB_HASH32_UINT32_STORE(hash32_map,uint32key,value,value_len) gnb_hash32_store(hash32_map,(u_char *)&uint32key,sizeof(uint32_t),value,value_len) 74 | #define GNB_HASH32_UINT32_GET(hash32_map,uint32key) gnb_hash32_get(hash32_map,(u_char *)&uint32key,sizeof(uint32_t)) 75 | 76 | #define GNB_HASH32_UINT32_GET_PTR(hash32_map,uint32key) GNB_HASH32_VALUE_PTR(gnb_hash32_get(hash32_map,(u_char *)&uint32key,sizeof(uint32_t))) 77 | #define GNB_HASH32_UINT32_DEL(hash32_map,uint32key) gnb_hash32_del(hash32_map,(u_char *)&uint32key,sizeof(uint32_t)) 78 | uint32_t* gnb_hash32_uint32_keys(gnb_hash32_map_t *hash32_map, uint32_t *num); 79 | 80 | 81 | #define GNB_HASH32_UINT64_SET(hash32_map,uint64key,value) gnb_hash32_set(hash32_map,(u_char *)&uint64key,sizeof(uint64_t),value,0) 82 | #define GNB_HASH32_UINT64_STORE(hash32_map,uint64key,value,value_len) gnb_hash32_store(hash32_map,(u_char *)&uint64key,sizeof(uint64_t),value,value_len) 83 | #define GNB_HASH32_UINT64_GET(hash32_map,uint64key) gnb_hash32_get(hash32_map,(u_char *)&uint64key,sizeof(uint64_t)) 84 | #define GNB_HASH32_UINT64_GET_PTR(hash32_map,uint64key) GNB_HASH32_VALUE_PTR(gnb_hash32_get(hash32_map,(u_char *)&uint64key,sizeof(uint64_t))) 85 | #define GNB_HASH32_UINT64_DEL(hash32_map,uint64key) gnb_hash32_del(hash32_map,(u_char *)&uint64key,sizeof(uint64_t)) 86 | uint64_t* gnb_hash32_uint64_keys(gnb_hash32_map_t *hash32_map, uint32_t *num); 87 | 88 | 89 | #define GNB_HASH32_SET(hash32_map,string,string_len,value) gnb_hash32_set(hash32_map, string, (uint32_t)string_len, value, 0) 90 | #define GNB_HASH32_STORE(hash32_map,string,string_len,value,value_len) gnb_hash32_store(hash32_map,string,(uint32_t)string_len,value,(uint32_t)value_len) 91 | #define GNB_HASH32_GET(hash32_map,key_string,key_string_len) gnb_hash32_get(hash32_map,key_string,(uint32_t)key_string_len) 92 | #define GNB_HASH32_GET_PTR(hash32_map,key_string,key_string_len) GNB_HASH32_VALUE_PTR(gnb_hash32_get(hash32_map,key_string,(uint32_t)key_string_len)) 93 | #define GNB_HASH32_DEL(hash32_map,string,string_len) gnb_hash32_del(hash32_map,string,(uint32_t)string_len) 94 | 95 | 96 | u_char** gnb_hash32_string_keys(gnb_hash32_map_t *hash32_map, uint32_t *num); 97 | 98 | 99 | #define GNB_HASH32_UINT32_KEY(kv32) (*(uint32_t *)kv32->key->data) 100 | #define GNB_HASH32_UINT32_VALUE(kv32) (*(uint32_t *)kv32->value->data) 101 | 102 | #define GNB_HASH32_UINT64_KEY(kv32) (*(uint64_t *)kv32->key->data) 103 | #define GNB_HASH32_UINT64_VALUE(kv32) (*(uint64_t *)kv32->key->data) 104 | 105 | #define GNB_HASH32_STRING_KEY(kv32) ((unsigned char *)kv32->key->data) 106 | #define GNB_HASH32_STRING_VALUE(kv32) ((unsigned char *)kv32->value->data) 107 | 108 | #define GNB_HASH32_KEY_SIZE(kv32) (kv32->key->size) 109 | #define GNB_HASH32_VALUE_SIZE(kv32) (kv32->value->size) 110 | 111 | #define GNB_HASH32_KEY_PTR(kv32) kv32!=NULL?(*(void **)&kv32->key->data):NULL 112 | #define GNB_HASH32_VALUE_PTR(kv32) kv32!=NULL?(*(void **)&kv32->value->data):NULL 113 | 114 | #define GNB_HASH32_VALUE(kv32) kv32!=NULL?kv32->value:NULL 115 | 116 | 117 | #define GNB_HASH32_GET_VALUE(hash32_map,key,key_len) ( GNB_HASH32_VALUE( gnb_hash32_get(hash32_map,key,key_len) ) ) 118 | 119 | #define GNB_HASH32_UINT32_GET_VALUE(hash32_map,uint32key) ( GNB_HASH32_VALUE( gnb_hash32_get(hash32_map,(u_char *)&uint32key,sizeof(uint32_t)) ) ) 120 | 121 | #endif 122 | 123 | -------------------------------------------------------------------------------- /src/gnb_network_service.h: -------------------------------------------------------------------------------- 1 | #ifndef gnb_network_service_h 2 | #define gnb_network_service_h 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "gnb_buf.h" 10 | #include "gnb_event.h" 11 | #include "gnb_fixed_pool.h" 12 | #include "gnb_address_type.h" 13 | #include "gnb_log_type.h" 14 | 15 | 16 | typedef struct _gnb_connection_t{ 17 | 18 | int fd; 19 | 20 | #define TCP_CONNECT_INIT 0x0 21 | #define TCP_CONNECT_SUCCESS 0x1 22 | #define TCP_CONNECT_WAIT 0x2 23 | #define TCP_CONNECT_FAIL 0x3 24 | #define UDP_CHANNEL 0x4 25 | 26 | 27 | #define TCP_CONNECT_FINISH 0x5 28 | #define UDP_CHANNEL_FINISH 0x6 29 | int status; 30 | 31 | gnb_sockaddress_t local_sockaddress; 32 | gnb_sockaddress_t remote_sockaddress; 33 | 34 | // 创建该tcp连接时的 listen socket 句柄 35 | int listen_tcp_fd; 36 | 37 | uint64_t keepalive_ts_sec; 38 | 39 | gnb_zbuf_t *recv_zbuf; 40 | 41 | gnb_zbuf_t *send_zbuf; 42 | 43 | gnb_event_t *event; 44 | 45 | uint64_t n_recv; 46 | uint64_t n_send; 47 | 48 | uint64_t n_recv_total; 49 | uint64_t n_send_total; 50 | 51 | 52 | //存放针对这个地址端口的服务的一些信息 53 | void *conn_data; 54 | 55 | void *udata; 56 | 57 | }gnb_connection_t; 58 | 59 | 60 | 61 | typedef struct _gnb_network_service_t gnb_network_service_t; 62 | 63 | typedef int (*gnb_service_init_cb_t)(gnb_network_service_t *service); 64 | 65 | typedef int (*gnb_service_listen_cb_t)(gnb_network_service_t *service); 66 | 67 | typedef int (*gnb_service_accept_cb_t)(gnb_network_service_t *service, gnb_connection_t *conn); 68 | 69 | typedef int (*gnb_service_connect_cb_t)(gnb_network_service_t *service, gnb_connection_t *conn); 70 | 71 | typedef int (*gnb_service_recv_cb_t)(gnb_network_service_t *service, gnb_connection_t *conn); 72 | 73 | typedef int (*gnb_service_send_cb_t)(gnb_network_service_t *service, gnb_connection_t *conn); 74 | 75 | typedef int (*gnb_service_close_cb_t)(gnb_network_service_t *service, gnb_connection_t *conn); 76 | 77 | typedef int (*gnb_service_idle_cb_t)(gnb_network_service_t *service); 78 | 79 | 80 | 81 | 82 | typedef struct _gnb_conn_array_t{ 83 | 84 | size_t size; 85 | 86 | gnb_connection_t conn[0]; 87 | 88 | }gnb_conn_array_t; 89 | 90 | 91 | 92 | typedef struct _gnb_network_service_t{ 93 | 94 | gnb_heap_t *heap; 95 | 96 | gnb_log_ctx_t *log; 97 | 98 | gnb_fixed_pool_t *event_fixed_pool; 99 | 100 | size_t recv_zbuf_size; 101 | size_t send_zbuf_size; 102 | 103 | gnb_event_cmd *event_cmd; 104 | 105 | gnb_conn_array_t *conn_array; 106 | 107 | #define m_conn0 conn_array->conn[0] 108 | #define m_conn1 conn_array->conn[1] 109 | #define m_conn2 conn_array->conn[2] 110 | 111 | #define m_local_sockaddress0 conn_array->conn[0].local_sockaddress 112 | #define m_local_sockaddress1 conn_array->conn[1].local_sockaddress 113 | #define m_local_sockaddress2 conn_array->conn[2].local_sockaddress 114 | #define m_local_sockaddress3 conn_array->conn[3].local_sockaddress 115 | #define m_local_sockaddress4 conn_array->conn[4].local_sockaddress 116 | 117 | #define m_remote_sockaddress0 conn_array->conn[0].remote_sockaddress 118 | #define m_remote_sockaddress1 conn_array->conn[1].remote_sockaddress 119 | #define m_remote_sockaddress2 conn_array->conn[2].remote_sockaddress 120 | #define m_remote_sockaddress3 conn_array->conn[3].remote_sockaddress 121 | #define m_remote_sockaddress4 conn_array->conn[4].remote_sockaddress 122 | 123 | #define m_conn0_fd conn_array->conn[0].fd 124 | #define m_conn1_fd conn_array->conn[1].fd 125 | #define m_conn2_fd conn_array->conn[2].fd 126 | #define m_conn3_fd conn_array->conn[3].fd 127 | #define m_conn4_fd conn_array->conn[4].fd 128 | 129 | gnb_service_init_cb_t init_cb; 130 | gnb_service_listen_cb_t listen_cb; 131 | gnb_service_accept_cb_t accept_cb; 132 | gnb_service_connect_cb_t connect_cb; 133 | gnb_service_recv_cb_t recv_cb; 134 | 135 | //告知发送的情况,缓冲区剩余字节或全部发送成功 136 | gnb_service_send_cb_t send_cb; 137 | gnb_service_close_cb_t close_cb; 138 | gnb_service_idle_cb_t idle_cb; 139 | 140 | 141 | struct timeval now_timeval; 142 | uint64_t now_time_sec; 143 | uint64_t now_time_usec; 144 | 145 | void *ctx; 146 | 147 | void *service_conf; 148 | 149 | }gnb_network_service_t; 150 | 151 | 152 | 153 | gnb_network_service_t* gnb_network_service_create(gnb_network_service_t *service_mod, gnb_log_ctx_t *log, size_t max_event); 154 | 155 | int gnb_network_service_init(gnb_network_service_t *service, void *service_conf); 156 | 157 | void gnb_network_service_destroy(gnb_network_service_t *service); 158 | 159 | int gnb_network_service_listen(gnb_network_service_t *service); 160 | 161 | //考虑增加一个这样的 callback 机制为 client 做一些初始化连接的工作 162 | int gnb_network_service_init_channel(gnb_network_service_t *service); 163 | 164 | void gnb_network_service_loop(gnb_network_service_t *service); 165 | 166 | 167 | #define GNB_SERVICE_NOTIFY_SEND(service, conn) service->event_cmd->set_event(service->event_cmd, conn->event, GNB_EVENT_OP_ENABLE, GNB_EVENT_TYPE_WRITE) 168 | #define GNB_SERVICE_DEL_EVENT(service, event) service->event_cmd->del_event(service->event_cmd, event) 169 | 170 | 171 | gnb_connection_t* gnb_connection_create(gnb_network_service_t *service); 172 | void gnb_connection_release(gnb_network_service_t *service, gnb_connection_t *conn); 173 | 174 | void gnb_connection_close(gnb_network_service_t *service, gnb_connection_t *conn); 175 | 176 | int gnb_network_service_connect(gnb_network_service_t *service, gnb_connection_t *conn); 177 | 178 | int gnb_network_service_udp_channel(gnb_network_service_t *service, gnb_connection_t *conn); 179 | 180 | int gnb_network_service_udp_send(gnb_network_service_t *service, gnb_connection_t *conn); 181 | 182 | #define GNB_EVENT_PAYLOAD_TYPE_UDPLOG 0x45 183 | 184 | #define GNB_LOG_ID_EVENT_CORE 0 185 | 186 | 187 | #endif 188 | 189 | -------------------------------------------------------------------------------- /src/gnb_lru32.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_LRU32_H 19 | #define GNB_LRU32_H 20 | 21 | #include 22 | #include 23 | 24 | #include "gnb_alloc.h" 25 | #include "gnb_fixed_pool.h" 26 | #include "gnb_hash32.h" 27 | #include "gnb_doubly_linked_list.h" 28 | 29 | typedef struct _gnb_lru32_t gnb_lru32_t; 30 | typedef struct _gnb_lru32_node_t gnb_lru32_node_t; 31 | 32 | typedef struct _gnb_lru32_node_t{ 33 | gnb_doubly_linked_list_node_t *dl_node; // dll_node->data -> gnb_lru32_node_t* 34 | gnb_kv32_t *kv; // 保存在 hashmap 中的kv,使得在双向链表这端可以通过key去存取 hashmap 35 | void *udata; // -> lru payload 36 | }gnb_lru32_node_t; 37 | 38 | 39 | typedef struct _gnb_lru32_t{ 40 | 41 | gnb_heap_t *heap; 42 | 43 | gnb_doubly_linked_list_t *doubly_linked_list; 44 | 45 | gnb_hash32_map_t *lru_node_map; //save type: gnb_lru32_node_t 46 | 47 | uint32_t size; 48 | 49 | uint32_t max_size; 50 | 51 | //lru 可以存数据的指针也可以申请一块内存把数据拷贝到该内存块 52 | //存入的数据块的大小,如果为0,用同样的key每次set进去都要释放此前为存储数据块申请的内存, 53 | //如果不等于0,存入数据的时候就使用之前申请好的内存 54 | uint32_t block_size; 55 | 56 | gnb_fixed_pool_t *lru_node_fixed_pool; 57 | gnb_fixed_pool_t *dl_node_fixed_pool; 58 | gnb_fixed_pool_t *udata_fixed_pool; 59 | 60 | }gnb_lru32_t; 61 | 62 | 63 | /* 64 | 如果用 gnb_lru32_set 和 gnb_lru32_store 保存 数据 到 lru, block_size 设为0 65 | 如果用 gnb_lru32_block_set 保存 数据 到 lru, block_size 设为 block 的大小,这对于保存一些容量相同的数据,可以避免频繁申请/释放内存 66 | */ 67 | gnb_lru32_t *gnb_lru32_create(gnb_heap_t *heap, uint32_t max_size,uint32_t block_size); 68 | 69 | //需要释放完 lru 里的lru_node->udata,才能执行这个函数 70 | //释放到操作是 迭代执行 gnb_lru32_pop_head 或 gnb_lru32_pop_tail,直到返回为NULL 71 | //由于lru_node->udata存放的是调用者的私有数据,因此释放时需要由调用者自行处理 72 | void gnb_lru32_release(gnb_lru32_t *lru); 73 | 74 | 75 | //这个函数传入的 data 需要调用者申请内存和释放内存 76 | //如果set入data前发现链表已经满了,就立即返回当前传入的data由调用者释放 77 | //如果set入data后发现链表满了,就dropt掉tail,并返回tail的data由调用者释放 78 | void* gnb_lru32_put(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data); 79 | #define GNB_LRU32_PUT(lru,key,key_len,data) gnb_lru32_put(lru, (unsigned char *)key, (uint32_t)key_len, data) 80 | 81 | 82 | //传入的 data 会在 lru 内部申请一块内存,拷贝一份,当链表满了需要丢弃tail的节点时,tail节点绑定的这块内存也会被gnb_lru32_set释放 83 | void gnb_lru32_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data, uint32_t size); 84 | #define GNB_LRU32_STORE(lru,key,key_len,data,size) gnb_lru32_store(lru, (unsigned char *)key, (uint32_t)key_len, data, (uint32_t)size) 85 | 86 | //传入的data会拷贝到lru中一块内存里,相同的key存入数据会覆盖之前的数据, 87 | //每个key对应的内存块是预先申请好的,大小一致的,在调用gnb_lru32_creates时通过block_size设定 88 | //用这个函数保存小块数据到lru是效率最高的,不需要频繁申请/释放内存 89 | void gnb_lru32_fixed_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data); 90 | #define GNB_LRU32_FIXED_STORE(lru,key,key_len,data) gnb_lru32_fixed_store(lru,(unsigned char *)key,(uint32_t)key_len, data) 91 | 92 | 93 | //这个函数不会把命中的节点移到链表首部,需要调用 gnb_lru32_movetohead 实现 94 | gnb_lru32_node_t* gnb_lru32_hash_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); 95 | #define GNB_LRU32_HASH_GET(lru,key,key_len) gnb_lru32_hash_get(lru,key,(uint32_t)key_len); 96 | 97 | //如果命中,会调用 gnb_lru32_movetohead 把命中的节点移动到链表首部 98 | gnb_lru32_node_t* gnb_lru32_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); 99 | #define GNB_LRU32_GET(lru,key,key_len) gnb_lru32_get(lru,key,(uint32_t)key_len); 100 | 101 | 102 | #define GNB_LRU32_VALUE(b) b!=NULL?b->udata:NULL 103 | #define GNB_LRU32_HASH_GET_VALUE(lru,key,key_len) GNB_LRU32_VALUE( gnb_lru32_hash_get(lru, (unsigned char *)key, (uint32_t)key_len) ) 104 | #define GNB_LRU32_GET_VALUE(lru,key,key_len) GNB_LRU32_VALUE( gnb_lru32_get(lru, (unsigned char *)key, (uint32_t)key_len) ) 105 | 106 | 107 | void gnb_lru32_movetohead(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); 108 | #define GNB_LRU32_MOVETOHEAD(lru,key,key_len) gnb_lru32_movetohead(lru, (unsigned char *)key, (uint32_t)key_len) 109 | 110 | void* gnb_lru32_pop_by_key(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len); 111 | #define GNB_LRU32_POP_BY_KEY(lru,key,key_len) gnb_lru32_pop_by_key(lru,key,(uint32_t)key_len) 112 | 113 | 114 | void* gnb_lru32_pop_head(gnb_lru32_t *lru); 115 | void* gnb_lru32_pop_tail(gnb_lru32_t *lru); 116 | 117 | void* gnb_lru32_get_head(gnb_lru32_t *lru); 118 | void* gnb_lru32_get_tail(gnb_lru32_t *lru); 119 | 120 | #define GNB_LRU32_UINT32_PUT(lru,key,data) gnb_lru32_put(lru, (unsigned char *)(&key), sizeof(uint32_t), data) 121 | #define GNB_LRU32_UINT32_STORE(lru,key,data,size) gnb_lru32_store(lru, (unsigned char *)(&key), sizeof(uint32_t), data, (uint32_t)size) 122 | #define GNB_LRU32_UINT32_FIX_STORE(lru,key,data) gnb_lru32_fix_store(lru, (unsigned char *)(&key), sizeof(uint32_t), data) 123 | #define GNB_LRU32_UINT32_HASH_GET(lru,key) gnb_lru32_hash_get(lru,(unsigned char *)*&key),sizeof(uint32_t)); 124 | #define GNB_LRU32_UINT32_GET(lru,key) gnb_lru32_get(lru,(unsigned char *)(&key),sizeof(uint32_t)); 125 | 126 | #define GNB_LRU32_UINT32_POP_BY_KEY(lru,key) gnb_lru32_pop_by_key(lru, (unsigned char *)(&key), sizeof(uint32_t)) 127 | #define GNB_LRU32_UINT32_MOVETOHEAD(lru,key) gnb_lru32_movetohead(lru, (unsigned char *)(&key), sizeof(uint32_t)) 128 | 129 | #define GNB_LRU32_UINT32_HASH_GET_VALUE(lru,key) GNB_LRU32_VALUE( gnb_lru32_hash_get(lru, (unsigned char *)(&key), sizeof(uint32_t)) ) 130 | #define GNB_LRU32_UINT32_GET_VALUE(lru,key) GNB_LRU32_VALUE( gnb_lru32_get(lru, (unsigned char *)(&key), sizeof(uint32_t)) ) 131 | 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /src/event/epoll_event_handler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "gnb_event.h" 9 | #include "gnb_fixed_pool.h" 10 | 11 | #define MAX_EPOLL_FD 8192 12 | 13 | typedef struct _epoll_handler_ctx_t{ 14 | 15 | gnb_heap_t *heap; 16 | 17 | gnb_fixed_pool_t *epoll_event_fixed_pool; 18 | 19 | 20 | int epoll_fd; 21 | 22 | //out event list for epoll 23 | struct epoll_event eventlist[MAX_GET_GNB_EVENT]; 24 | 25 | gnb_event_array_t *event_array; 26 | 27 | 28 | }epoll_handler_ctx_t; 29 | 30 | 31 | static int init_event(gnb_event_cmd *event_cmd, size_t max_event) { 32 | 33 | epoll_handler_ctx_t *handler_ctx = gnb_heap_alloc(event_cmd->heap, sizeof(epoll_handler_ctx_t)); 34 | 35 | memset(handler_ctx,0,sizeof(epoll_handler_ctx_t)); 36 | 37 | handler_ctx->epoll_event_fixed_pool = gnb_fixed_pool_create(event_cmd->heap, max_event, sizeof(struct epoll_event)); 38 | 39 | handler_ctx->epoll_fd = epoll_create(MAX_EPOLL_FD); 40 | 41 | if (-1 == handler_ctx->epoll_fd) { 42 | perror("epoll_create"); 43 | } 44 | 45 | event_cmd->event_handler_ctx = handler_ctx; 46 | 47 | return 0; 48 | } 49 | 50 | 51 | static int add_event(gnb_event_cmd *event_cmd, gnb_event_t *ev, int ev_type) { 52 | 53 | int ret = 0; 54 | 55 | epoll_handler_ctx_t *handler_ctx = event_cmd->event_handler_ctx; 56 | 57 | ev->uevent = gnb_fixed_pool_pop(handler_ctx->epoll_event_fixed_pool); 58 | 59 | struct epoll_event *epoll_ev = (struct epoll_event *)ev->uevent; 60 | memset(epoll_ev,0,sizeof(struct epoll_event)); 61 | 62 | epoll_ev->events = EPOLLRDHUP; 63 | 64 | if ( GNB_EVENT_TYPE_READ & ev_type) { 65 | epoll_ev->events |= EPOLLIN; 66 | } 67 | 68 | if ( GNB_EVENT_TYPE_WRITE & ev_type) { 69 | epoll_ev->events |= EPOLLOUT; 70 | } 71 | 72 | epoll_ev->data.ptr = (void*)ev; 73 | 74 | ret = epoll_ctl(handler_ctx->epoll_fd, EPOLL_CTL_ADD, ev->fd, ev->uevent); 75 | 76 | if (ret != 0) { 77 | perror("add_event epoll_ctl"); 78 | } 79 | 80 | return 0; 81 | } 82 | 83 | 84 | static int del_event(gnb_event_cmd *event_cmd, gnb_event_t *ev) { 85 | 86 | int ret; 87 | 88 | epoll_handler_ctx_t *handler_ctx = event_cmd->event_handler_ctx; 89 | 90 | ret = epoll_ctl(handler_ctx->epoll_fd, EPOLL_CTL_DEL, ev->fd, ev->uevent); 91 | 92 | gnb_fixed_pool_push(handler_ctx->epoll_event_fixed_pool, (void *)ev->uevent); 93 | 94 | return 0; 95 | 96 | } 97 | 98 | 99 | static int set_event(gnb_event_cmd *event_cmd, gnb_event_t *ev, int op, int ev_type) { 100 | 101 | epoll_handler_ctx_t *handler_ctx = event_cmd->event_handler_ctx; 102 | 103 | struct epoll_event *epoll_ev = (struct epoll_event *)ev->uevent; 104 | 105 | int ev_op; 106 | 107 | int ret = 0; 108 | 109 | switch (op) { 110 | 111 | case GNB_EVENT_OP_ENABLE: 112 | 113 | if( GNB_EVENT_TYPE_READ & ev_type ){ 114 | epoll_ev->events |= EPOLLIN; 115 | } 116 | 117 | if( GNB_EVENT_TYPE_WRITE & ev_type ){ 118 | epoll_ev->events |= EPOLLOUT; 119 | } 120 | 121 | //epoll_ev->events |= EPOLLRDHUP; 122 | 123 | break; 124 | 125 | case GNB_EVENT_OP_DISABLE: 126 | 127 | 128 | if ( GNB_EVENT_TYPE_READ & ev_type ) { 129 | epoll_ev->events &= ~EPOLLIN; 130 | } 131 | 132 | if ( GNB_EVENT_TYPE_WRITE & ev_type ) { 133 | epoll_ev->events &= ~EPOLLOUT; 134 | } 135 | 136 | break; 137 | 138 | default: 139 | break; 140 | 141 | }; 142 | 143 | ev_op = EPOLL_CTL_MOD; 144 | 145 | ret = epoll_ctl(handler_ctx->epoll_fd, ev_op, ev->fd, epoll_ev); 146 | 147 | if (ret != 0) { 148 | perror("set_event epoll_ctl"); 149 | } 150 | 151 | return 0; 152 | 153 | } 154 | 155 | 156 | static int get_event(gnb_event_cmd *event_cmd, gnb_event_t **ev_lst, int *nevents){ 157 | 158 | epoll_handler_ctx_t *handler_ctx = event_cmd->event_handler_ctx; 159 | 160 | gnb_event_t *ev; 161 | 162 | //int timewait = 1; 163 | int timewait = 1000; 164 | 165 | int i; 166 | int nepevent = 0; 167 | 168 | nepevent = epoll_wait(handler_ctx->epoll_fd, handler_ctx->eventlist, *nevents, timewait); 169 | 170 | if (nepevent < 0) { 171 | *nevents = 0; 172 | perror("epoll_wait"); 173 | return 1; 174 | } 175 | 176 | *nevents = nepevent; 177 | 178 | for (i = 0; i < nepevent; i++) { 179 | 180 | ev_lst[i] = (gnb_event_t*)handler_ctx->eventlist[i].data.ptr; 181 | 182 | ev_lst[i]->ev_type = GNB_EVENT_TYPE_NONE; 183 | 184 | if ( EPOLLRDHUP & handler_ctx->eventlist[i].events) { 185 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_EOF; 186 | } 187 | 188 | if ( EPOLLHUP & handler_ctx->eventlist[i].events) { 189 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_ERROR; 190 | } 191 | 192 | if ( EPOLLERR & handler_ctx->eventlist[i].events) { 193 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_ERROR; 194 | } 195 | 196 | if ( EPOLLIN & handler_ctx->eventlist[i].events) { 197 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_READ; 198 | } 199 | 200 | if ( EPOLLOUT & handler_ctx->eventlist[i].events) { 201 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_WRITE; 202 | } 203 | 204 | }/*end for*/ 205 | 206 | return 0; 207 | } 208 | 209 | 210 | static int finish_event(gnb_event_cmd *event_cmd){ 211 | 212 | epoll_handler_ctx_t *handler_ctx = (epoll_handler_ctx_t *)event_cmd->event_handler_ctx; 213 | 214 | gnb_fixed_pool_release(handler_ctx->heap, handler_ctx->epoll_event_fixed_pool); 215 | 216 | gnb_heap_free(event_cmd->heap, handler_ctx->eventlist); 217 | gnb_heap_free(event_cmd->heap, event_cmd->event_handler_ctx); 218 | 219 | return 0; 220 | 221 | } 222 | 223 | 224 | gnb_event_cmd epoll_event_cmd = { 225 | 226 | .mod_name = "epoll_event", 227 | 228 | .heap = NULL, 229 | 230 | .self = &epoll_event_cmd, 231 | 232 | .init_event = init_event, 233 | 234 | .add_event = add_event, 235 | .set_event = set_event, 236 | .del_event = del_event, 237 | .get_event = get_event, 238 | 239 | .finish_event = finish_event, 240 | 241 | .event_handler_ctx = NULL 242 | 243 | }; 244 | 245 | 246 | -------------------------------------------------------------------------------- /src/event/select_event_handler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "gnb_platform.h" 6 | 7 | 8 | #ifdef _WIN32 9 | #include 10 | #include 11 | #endif 12 | 13 | #include 14 | 15 | #ifdef __UNIX_LIKE_OS__ 16 | #include 17 | #endif 18 | 19 | #include 20 | 21 | #include "gnb_event.h" 22 | 23 | typedef struct _select_handler_ctx_t{ 24 | 25 | int maxfd; 26 | 27 | fd_set readfd_set; 28 | fd_set writefd_set; 29 | fd_set exceptfd_set; 30 | gnb_event_array_t *event_array; 31 | 32 | }select_handler_ctx_t; 33 | 34 | 35 | static int init_event(gnb_event_cmd *event_cmd, size_t max_event) { 36 | 37 | select_handler_ctx_t *handler_ctx = malloc(sizeof(select_handler_ctx_t)); 38 | 39 | memset(handler_ctx,0,sizeof(select_handler_ctx_t)); 40 | 41 | handler_ctx->maxfd = -1; 42 | 43 | FD_ZERO(&handler_ctx->readfd_set); 44 | FD_ZERO(&handler_ctx->writefd_set); 45 | FD_ZERO(&handler_ctx->exceptfd_set); 46 | 47 | handler_ctx->event_array = (gnb_event_array_t *)malloc( sizeof(gnb_event_array_t) + sizeof(gnb_event_t) * max_event ); 48 | 49 | memset(handler_ctx->event_array, 0, sizeof(gnb_event_array_t) + sizeof(gnb_event_t) * max_event); 50 | 51 | handler_ctx->event_array->size = max_event; 52 | 53 | event_cmd->event_handler_ctx = handler_ctx; 54 | 55 | return 0; 56 | 57 | } 58 | 59 | 60 | 61 | static int add_event (gnb_event_cmd *event_cmd, gnb_event_t *ev, int ev_type) { 62 | 63 | select_handler_ctx_t *handler_ctx = (select_handler_ctx_t *)event_cmd->event_handler_ctx; 64 | 65 | if ( handler_ctx->event_array->nevent >= handler_ctx->event_array->size ){ 66 | 67 | return -1; 68 | } 69 | 70 | if( ev->fd > handler_ctx->maxfd ){ 71 | 72 | handler_ctx->maxfd = ev->fd; 73 | } 74 | 75 | /* ************************************ */ 76 | handler_ctx->event_array->list[ handler_ctx->event_array->nevent ] = ev; 77 | ev->index = handler_ctx->event_array->nevent; 78 | handler_ctx->event_array->nevent++; 79 | /* ************************************ */ 80 | 81 | if ( GNB_EVENT_TYPE_READ & ev_type){ 82 | FD_SET(ev->fd, &handler_ctx->readfd_set); 83 | } 84 | 85 | if ( GNB_EVENT_TYPE_WRITE & ev_type){ 86 | FD_SET(ev->fd, &handler_ctx->writefd_set); 87 | } 88 | 89 | FD_SET(ev->fd, &handler_ctx->exceptfd_set); 90 | 91 | //如果ev->uevent为NULL,目前的机制将无法删除事件 92 | ev->uevent = &ev->fd; 93 | 94 | return 0; 95 | 96 | } 97 | 98 | 99 | 100 | static int set_event ( gnb_event_cmd *event_cmd, gnb_event_t *ev, int op, int ev_type ) { 101 | 102 | select_handler_ctx_t *handler_ctx = (select_handler_ctx_t *)event_cmd->event_handler_ctx; 103 | 104 | switch (op) { 105 | 106 | case GNB_EVENT_OP_ENABLE: 107 | 108 | if( GNB_EVENT_TYPE_WRITE & ev_type ){ 109 | FD_SET(ev->fd, &handler_ctx->writefd_set); 110 | } 111 | 112 | if( GNB_EVENT_TYPE_READ & ev_type ){ 113 | FD_SET(ev->fd, &handler_ctx->readfd_set); 114 | } 115 | 116 | break; 117 | 118 | case GNB_EVENT_OP_DISABLE: 119 | 120 | if ( GNB_EVENT_TYPE_WRITE & ev_type ) { 121 | FD_CLR(ev->fd, &handler_ctx->writefd_set); 122 | } 123 | 124 | if ( GNB_EVENT_TYPE_READ & ev_type ) { 125 | FD_CLR(ev->fd, &handler_ctx->readfd_set); 126 | } 127 | 128 | break; 129 | 130 | default: 131 | break; 132 | 133 | }; 134 | 135 | return 0; 136 | 137 | } 138 | 139 | 140 | 141 | static int del_event ( gnb_event_cmd *event_cmd, gnb_event_t *ev ) { 142 | 143 | select_handler_ctx_t *handler_ctx = (select_handler_ctx_t *)event_cmd->event_handler_ctx; 144 | 145 | if ( 0 == handler_ctx->event_array->nevent ){ 146 | goto finish; 147 | } 148 | 149 | if ( ev->index > handler_ctx->event_array->nevent ){ 150 | goto finish; 151 | } 152 | 153 | /* ************************************ */ 154 | gnb_event_t *last_event = handler_ctx->event_array->list[ handler_ctx->event_array->nevent-1 ]; 155 | last_event->index = ev->index; 156 | handler_ctx->event_array->list[ last_event->index ] = last_event; 157 | handler_ctx->event_array->nevent--; 158 | /* ************************************ */ 159 | 160 | finish: 161 | 162 | FD_CLR(ev->fd, &handler_ctx->readfd_set); 163 | FD_CLR(ev->fd, &handler_ctx->writefd_set); 164 | FD_CLR(ev->fd, &handler_ctx->exceptfd_set); 165 | 166 | return 0; 167 | } 168 | 169 | 170 | 171 | static int get_event (gnb_event_cmd *event_cmd, gnb_event_t **ev_lst, int *nevents) { 172 | 173 | select_handler_ctx_t *handler_ctx = (select_handler_ctx_t *)event_cmd->event_handler_ctx; 174 | 175 | fd_set readfds; 176 | fd_set writefds; 177 | fd_set exceptfds; 178 | int n_ready; 179 | 180 | int idx = 0; 181 | 182 | struct timeval timeout; 183 | timeout.tv_sec = 0l; 184 | timeout.tv_usec = 10000l; 185 | 186 | readfds = handler_ctx->readfd_set; 187 | writefds = handler_ctx->writefd_set; 188 | exceptfds = handler_ctx->exceptfd_set; 189 | 190 | n_ready = select( handler_ctx->maxfd + 1, &readfds, &writefds, &exceptfds, &timeout ); 191 | 192 | if ( -1 == n_ready ) { 193 | 194 | if ( EINTR == errno ) { 195 | goto finish; 196 | }else{ 197 | goto finish; 198 | } 199 | 200 | } 201 | 202 | if ( 0 == n_ready ) { 203 | goto finish; 204 | } 205 | 206 | int i; 207 | 208 | int ev_type; 209 | 210 | for ( i = 0; i < handler_ctx->event_array->nevent; i++ ) { 211 | 212 | ev_type = GNB_EVENT_TYPE_NONE; 213 | 214 | if ( FD_ISSET(handler_ctx->event_array->list[i]->fd, &readfds) ){ 215 | ev_type |= GNB_EVENT_TYPE_READ; 216 | } 217 | 218 | if ( FD_ISSET(handler_ctx->event_array->list[i]->fd, &writefds) ){ 219 | ev_type |= GNB_EVENT_TYPE_WRITE; 220 | } 221 | 222 | if ( FD_ISSET(handler_ctx->event_array->list[i]->fd, &exceptfds) ){ 223 | ev_type |= GNB_EVENT_TYPE_ERROR; 224 | } 225 | 226 | if ( GNB_EVENT_TYPE_NONE != ev_type ){ 227 | ev_lst[idx] = handler_ctx->event_array->list[i]; 228 | ev_lst[idx]->ev_type = ev_type; 229 | idx++; 230 | } 231 | 232 | if ( idx == n_ready ){ 233 | break; 234 | } 235 | 236 | 237 | } 238 | 239 | finish: 240 | 241 | *nevents = idx; 242 | 243 | return 0; 244 | 245 | } 246 | 247 | static int finish_event(gnb_event_cmd *event_cmd){ 248 | 249 | select_handler_ctx_t *handler_ctx = (select_handler_ctx_t *)event_cmd->event_handler_ctx; 250 | 251 | free(handler_ctx->event_array); 252 | 253 | free(event_cmd->event_handler_ctx); 254 | 255 | return 0; 256 | } 257 | 258 | gnb_event_cmd select_event_cmd = { 259 | 260 | .mod_name = "select_event", 261 | 262 | .heap = NULL, 263 | 264 | .self = &select_event_cmd, 265 | 266 | .init_event = init_event, 267 | 268 | .add_event = add_event, 269 | .set_event = set_event, 270 | .del_event = del_event, 271 | .get_event = get_event, 272 | 273 | .finish_event = finish_event, 274 | 275 | .event_handler_ctx = NULL 276 | 277 | }; 278 | 279 | -------------------------------------------------------------------------------- /src/gnb_doubly_linked_list.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include "gnb_doubly_linked_list.h" 21 | 22 | void gnb_doubly_linked_list_node_set(gnb_doubly_linked_list_node_t *doubly_linked_list_node,void *data){ 23 | doubly_linked_list_node->data = data; 24 | } 25 | 26 | 27 | gnb_doubly_linked_list_t* gnb_doubly_linked_list_create(gnb_heap_t *heap){ 28 | 29 | gnb_doubly_linked_list_t *doubly_linked_list = (gnb_doubly_linked_list_t *)gnb_heap_alloc(heap,sizeof(gnb_doubly_linked_list_t)); 30 | 31 | memset(doubly_linked_list,0,sizeof(gnb_doubly_linked_list_t)); 32 | doubly_linked_list->heap = heap; 33 | return doubly_linked_list; 34 | 35 | } 36 | 37 | 38 | void gnb_doubly_linked_list_release(gnb_doubly_linked_list_t *doubly_linked_list){ 39 | gnb_heap_free(doubly_linked_list->heap,doubly_linked_list); 40 | } 41 | 42 | 43 | int gnb_doubly_linked_list_add(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node){ 44 | 45 | if( 0==doubly_linked_list->num ){ 46 | doubly_linked_list->head = dl_node; 47 | dl_node->pre = NULL; 48 | dl_node->nex = NULL; 49 | doubly_linked_list->tail = dl_node; 50 | goto finish; 51 | } 52 | 53 | if( 1==doubly_linked_list->num ){ 54 | 55 | dl_node->pre = NULL; 56 | dl_node->nex = doubly_linked_list->head; 57 | doubly_linked_list->head->pre = dl_node; 58 | 59 | doubly_linked_list->tail = doubly_linked_list->head; 60 | 61 | doubly_linked_list->head = dl_node; 62 | 63 | goto finish; 64 | 65 | } 66 | 67 | dl_node->pre = NULL; 68 | dl_node->nex = doubly_linked_list->head; 69 | 70 | doubly_linked_list->head->pre = dl_node; 71 | 72 | doubly_linked_list->head = dl_node; 73 | 74 | finish: 75 | doubly_linked_list->num++; 76 | 77 | return 0; 78 | } 79 | 80 | 81 | gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_head(gnb_doubly_linked_list_t *doubly_linked_list){ 82 | 83 | gnb_doubly_linked_list_node_t *dl_node; 84 | 85 | if( 0 == doubly_linked_list->num ){ 86 | return NULL; 87 | } 88 | 89 | if( 1 == doubly_linked_list->num ){ 90 | 91 | if ( doubly_linked_list->head != doubly_linked_list->tail ){ 92 | return NULL; 93 | } 94 | 95 | dl_node = doubly_linked_list->head; 96 | 97 | doubly_linked_list->head = NULL; 98 | doubly_linked_list->tail = NULL; 99 | doubly_linked_list->num = 0; 100 | 101 | return dl_node; 102 | } 103 | 104 | if ( doubly_linked_list->head == doubly_linked_list->tail ){ 105 | return NULL; 106 | } 107 | 108 | dl_node = doubly_linked_list->head; 109 | 110 | doubly_linked_list->head = dl_node->nex; 111 | 112 | doubly_linked_list->head->pre = NULL; 113 | 114 | doubly_linked_list->num--; 115 | 116 | return dl_node; 117 | 118 | } 119 | 120 | 121 | gnb_doubly_linked_list_node_t* gnb_doubly_linked_list_pop_tail(gnb_doubly_linked_list_t *doubly_linked_list){ 122 | 123 | gnb_doubly_linked_list_node_t *dl_node; 124 | 125 | if( 0 == doubly_linked_list->num ){ 126 | return NULL; 127 | } 128 | 129 | if( 1 == doubly_linked_list->num ){ 130 | 131 | if ( doubly_linked_list->head != doubly_linked_list->tail ){ 132 | return NULL; 133 | } 134 | 135 | dl_node = doubly_linked_list->tail; 136 | 137 | doubly_linked_list->head = NULL; 138 | doubly_linked_list->tail = NULL; 139 | doubly_linked_list->num = 0; 140 | 141 | return dl_node; 142 | } 143 | 144 | if ( doubly_linked_list->head == doubly_linked_list->tail ){ 145 | return NULL; 146 | } 147 | 148 | dl_node = doubly_linked_list->tail; 149 | 150 | doubly_linked_list->tail = dl_node->pre; 151 | 152 | doubly_linked_list->tail->nex = NULL; 153 | 154 | doubly_linked_list->num--; 155 | 156 | return dl_node; 157 | 158 | } 159 | 160 | 161 | 162 | int gnb_doubly_linked_list_move_head(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node){ 163 | 164 | if(1==doubly_linked_list->num || 2==doubly_linked_list->num){ 165 | return 0; 166 | } 167 | 168 | gnb_doubly_linked_list_node_t *pre_node = dl_node->pre; 169 | gnb_doubly_linked_list_node_t *nex_node = dl_node->nex; 170 | 171 | if( NULL == pre_node ){ 172 | //is header 173 | return 0; 174 | } 175 | 176 | if( NULL != nex_node ){ 177 | nex_node->pre = pre_node; 178 | }else{ 179 | doubly_linked_list->tail = pre_node; 180 | } 181 | 182 | pre_node->nex = nex_node; 183 | 184 | dl_node->nex = doubly_linked_list->head; 185 | 186 | doubly_linked_list->head->pre = dl_node; 187 | 188 | doubly_linked_list->head = dl_node; 189 | 190 | dl_node->pre = NULL; 191 | 192 | return 0; 193 | } 194 | 195 | 196 | int gnb_doubly_linked_list_pop(gnb_doubly_linked_list_t *doubly_linked_list, gnb_doubly_linked_list_node_t *dl_node){ 197 | 198 | 199 | if( 0==doubly_linked_list->num ){ 200 | return 0; 201 | } 202 | 203 | gnb_doubly_linked_list_node_t *pre_node = dl_node->pre; 204 | gnb_doubly_linked_list_node_t *nex_node = dl_node->nex; 205 | 206 | if( NULL == pre_node && NULL == nex_node ){ 207 | 208 | if ( doubly_linked_list->head != dl_node ){ 209 | return -1; 210 | } 211 | 212 | if ( doubly_linked_list->tail != dl_node ){ 213 | return -1; 214 | } 215 | 216 | if( 1 != doubly_linked_list->num ){ 217 | return -1; 218 | } 219 | 220 | 221 | doubly_linked_list->head = NULL; 222 | doubly_linked_list->tail = NULL; 223 | doubly_linked_list->num = 0; 224 | 225 | return 0; 226 | 227 | } 228 | 229 | if( NULL == pre_node ){ 230 | //is header 231 | if ( doubly_linked_list->head != dl_node ){ 232 | return -1; 233 | } 234 | 235 | if( 1 == doubly_linked_list->num ){ 236 | return -1; 237 | } 238 | 239 | nex_node->pre = NULL; 240 | doubly_linked_list->head = nex_node; 241 | doubly_linked_list->num--; 242 | 243 | return 0; 244 | } 245 | 246 | 247 | if ( NULL==nex_node ){ 248 | //is tail 249 | if ( doubly_linked_list->tail != dl_node ){ 250 | return -1; 251 | } 252 | 253 | if( 1 == doubly_linked_list->num ){ 254 | return -1; 255 | } 256 | 257 | pre_node->nex = NULL; 258 | doubly_linked_list->tail = pre_node; 259 | doubly_linked_list->num--; 260 | 261 | return 0; 262 | } 263 | 264 | pre_node->nex = nex_node; 265 | nex_node->pre = pre_node; 266 | doubly_linked_list->num--; 267 | 268 | return 0; 269 | } 270 | -------------------------------------------------------------------------------- /src/event/kqueue_event_handler.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "gnb_event.h" 13 | #include "gnb_fixed_pool.h" 14 | 15 | typedef struct _fd_events_t{ 16 | 17 | #define READ_KEVENT 0 18 | #define WRITE_KEVENT 1 19 | struct kevent changelist[2]; 20 | 21 | }fd_events_t; 22 | 23 | 24 | typedef struct _kqueue_handler_ctx_t{ 25 | 26 | gnb_heap_t *heap; 27 | 28 | gnb_fixed_pool_t *fd_events_fixed_pool; 29 | 30 | int kqueue_fd; 31 | 32 | struct kevent *eventlist; 33 | 34 | 35 | 36 | 37 | gnb_event_array_t *event_array; 38 | 39 | }kqueue_handler_ctx_t; 40 | 41 | 42 | 43 | static int init_event(gnb_event_cmd *event_cmd, size_t max_event){ 44 | 45 | kqueue_handler_ctx_t *handler_ctx = malloc(sizeof(kqueue_handler_ctx_t)); 46 | 47 | memset(handler_ctx, 0, sizeof(kqueue_handler_ctx_t)); 48 | 49 | handler_ctx->heap = event_cmd->heap; 50 | 51 | handler_ctx->kqueue_fd = kqueue(); 52 | 53 | handler_ctx->fd_events_fixed_pool = gnb_fixed_pool_create(handler_ctx->heap, max_event, sizeof(fd_events_t)); 54 | 55 | handler_ctx->eventlist = (struct kevent *)malloc( sizeof(struct kevent) * max_event ); 56 | memset(handler_ctx->eventlist, 0, sizeof(struct kevent) * max_event); 57 | 58 | handler_ctx->event_array = (gnb_event_array_t *)malloc( sizeof(gnb_event_array_t) + sizeof(gnb_event_t) * max_event ); 59 | 60 | memset(handler_ctx->event_array, 0, sizeof(gnb_event_array_t) + sizeof(gnb_event_t) * max_event); 61 | 62 | handler_ctx->event_array->size = max_event; 63 | 64 | event_cmd->event_handler_ctx = handler_ctx; 65 | 66 | return 0; 67 | 68 | } 69 | 70 | 71 | static int add_event(gnb_event_cmd *event_cmd, gnb_event_t *ev, int ev_type){ 72 | 73 | kqueue_handler_ctx_t *handler_ctx = (kqueue_handler_ctx_t *)event_cmd->event_handler_ctx; 74 | 75 | if ( handler_ctx->event_array->nevent >= handler_ctx->event_array->size ){ 76 | return -1; 77 | } 78 | 79 | /* ************************************ */ 80 | handler_ctx->event_array->list[ handler_ctx->event_array->nevent ] = ev; 81 | ev->index = handler_ctx->event_array->nevent; 82 | handler_ctx->event_array->nevent++; 83 | /* ************************************ */ 84 | 85 | fd_events_t *fd_events = gnb_fixed_pool_pop(handler_ctx->fd_events_fixed_pool); 86 | if (NULL==fd_events) { 87 | return -1; 88 | } 89 | 90 | memset(fd_events, 0, sizeof(fd_events_t)); 91 | 92 | ev->uevent = fd_events; 93 | 94 | fd_events->changelist[READ_KEVENT].ident = ev->fd; 95 | fd_events->changelist[READ_KEVENT].filter = EVFILT_READ; 96 | 97 | if ( GNB_EVENT_TYPE_READ & ev_type) { 98 | fd_events->changelist[READ_KEVENT].flags = EV_ADD | EV_ENABLE; 99 | }else{ 100 | fd_events->changelist[READ_KEVENT].flags = EV_ADD | EV_DISABLE; 101 | } 102 | 103 | fd_events->changelist[READ_KEVENT].flags = EV_ADD | EV_ENABLE; 104 | fd_events->changelist[READ_KEVENT].fflags = 0; 105 | fd_events->changelist[READ_KEVENT].data = 0; 106 | fd_events->changelist[READ_KEVENT].udata = (void*)ev; 107 | 108 | 109 | fd_events->changelist[WRITE_KEVENT].ident = ev->fd; 110 | fd_events->changelist[WRITE_KEVENT].filter = EVFILT_WRITE; 111 | 112 | if ( GNB_EVENT_TYPE_WRITE & ev_type) { 113 | fd_events->changelist[WRITE_KEVENT].flags = EV_ADD | EV_ENABLE; 114 | }else{ 115 | fd_events->changelist[WRITE_KEVENT].flags = EV_ADD | EV_DISABLE; 116 | } 117 | 118 | fd_events->changelist[WRITE_KEVENT].fflags = 0; 119 | fd_events->changelist[WRITE_KEVENT].data = 0; 120 | fd_events->changelist[WRITE_KEVENT].udata = (void*)ev; 121 | 122 | kevent( handler_ctx->kqueue_fd, fd_events->changelist, 2, NULL, 0, NULL ); 123 | 124 | return 0; 125 | 126 | } 127 | 128 | 129 | static int set_event(gnb_event_cmd *event_cmd, gnb_event_t *ev, int op, int ev_type){ 130 | 131 | kqueue_handler_ctx_t *handler_ctx = (kqueue_handler_ctx_t *)event_cmd->event_handler_ctx; 132 | 133 | fd_events_t *fd_events = (fd_events_t *)ev->uevent; 134 | 135 | uint16_t flags; 136 | 137 | switch (op) { 138 | 139 | case GNB_EVENT_OP_ENABLE: 140 | flags = EV_ENABLE; 141 | break; 142 | case GNB_EVENT_OP_DISABLE: 143 | flags = EV_DISABLE; 144 | break; 145 | default: 146 | break; 147 | 148 | }; 149 | 150 | if( GNB_EVENT_TYPE_READ & ev_type ){ 151 | fd_events->changelist[READ_KEVENT].flags = flags; 152 | kevent( handler_ctx->kqueue_fd, &fd_events->changelist[READ_KEVENT], 1, NULL, 0, NULL ); 153 | } 154 | 155 | if( GNB_EVENT_TYPE_WRITE & ev_type ){ 156 | fd_events->changelist[WRITE_KEVENT].flags = flags; 157 | kevent( handler_ctx->kqueue_fd, &fd_events->changelist[WRITE_KEVENT], 1, NULL, 0, NULL ); 158 | } 159 | 160 | return 0; 161 | } 162 | 163 | 164 | static int del_event(gnb_event_cmd *event_cmd, gnb_event_t *ev){ 165 | 166 | int ret; 167 | 168 | kqueue_handler_ctx_t *handler_ctx = (kqueue_handler_ctx_t *)event_cmd->event_handler_ctx; 169 | 170 | fd_events_t *fd_events = (fd_events_t *)ev->uevent; 171 | 172 | if ( 0 == handler_ctx->event_array->nevent ){ 173 | goto finish; 174 | } 175 | 176 | if ( ev->index > handler_ctx->event_array->nevent ){ 177 | goto finish; 178 | } 179 | 180 | /* ************************************ */ 181 | gnb_event_t *last_event = handler_ctx->event_array->list[ handler_ctx->event_array->nevent-1 ]; 182 | last_event->index = ev->index; 183 | handler_ctx->event_array->list[ last_event->index ] = last_event; 184 | handler_ctx->event_array->nevent--; 185 | /* ************************************ */ 186 | 187 | finish: 188 | 189 | fd_events->changelist[READ_KEVENT].flags = EV_DELETE; 190 | fd_events->changelist[WRITE_KEVENT].flags = EV_DELETE; 191 | 192 | kevent( handler_ctx->kqueue_fd, fd_events->changelist, 2, NULL, 0, NULL ); 193 | 194 | ret = gnb_fixed_pool_push(handler_ctx->fd_events_fixed_pool, (void *)fd_events); 195 | 196 | return 0; 197 | } 198 | 199 | 200 | static int get_event(gnb_event_cmd *event_cmd, gnb_event_t **ev_lst, int *nevents){ 201 | 202 | kqueue_handler_ctx_t *handler_ctx = (kqueue_handler_ctx_t *)event_cmd->event_handler_ctx; 203 | 204 | struct timespec ts; 205 | 206 | int num_kq_event = 0; 207 | 208 | ts.tv_sec = 1; 209 | ts.tv_nsec = 10*1000*1000; 210 | 211 | num_kq_event = kevent( handler_ctx->kqueue_fd, NULL, 0, handler_ctx->eventlist, *nevents, &ts ); 212 | 213 | if ( -1 == num_kq_event ) { 214 | *nevents = 0; 215 | return -1; 216 | } 217 | 218 | if ( num_kq_event < *nevents ) { 219 | *nevents = num_kq_event; 220 | } 221 | 222 | if (0==num_kq_event) { 223 | return num_kq_event; 224 | } 225 | 226 | int i; 227 | 228 | for (i=0; ieventlist[i].udata; 231 | 232 | ev_lst[i]->ev_type = GNB_EVENT_TYPE_NONE; 233 | 234 | switch (handler_ctx->eventlist[i].filter) { 235 | 236 | case EVFILT_READ: 237 | ev_lst[i]->ev_type = GNB_EVENT_TYPE_READ; 238 | break; 239 | 240 | case EVFILT_WRITE: 241 | ev_lst[i]->ev_type = GNB_EVENT_TYPE_WRITE; 242 | break; 243 | 244 | default: 245 | break; 246 | 247 | } 248 | 249 | if( handler_ctx->eventlist[i].flags & EV_ERROR ){ 250 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_ERROR; 251 | } 252 | 253 | if( handler_ctx->eventlist[i].flags & EV_EOF ){ 254 | ev_lst[i]->ev_type |= GNB_EVENT_TYPE_EOF; 255 | } 256 | 257 | } 258 | 259 | return 0; 260 | 261 | } 262 | 263 | 264 | static int finish_event(gnb_event_cmd *event_cmd){ 265 | 266 | kqueue_handler_ctx_t *handler_ctx = (kqueue_handler_ctx_t *)event_cmd->event_handler_ctx; 267 | 268 | gnb_fixed_pool_release(handler_ctx->heap, handler_ctx->fd_events_fixed_pool); 269 | 270 | free(handler_ctx->eventlist); 271 | 272 | free(handler_ctx->event_array); 273 | 274 | free(event_cmd->event_handler_ctx); 275 | 276 | return 0; 277 | } 278 | 279 | 280 | 281 | gnb_event_cmd kqueue_event_cmd = { 282 | 283 | .mod_name = "kqueue_event", 284 | 285 | .heap = NULL, 286 | 287 | .self = &kqueue_event_cmd, 288 | 289 | .init_event = init_event, 290 | 291 | .add_event = add_event, 292 | .set_event = set_event, 293 | .del_event = del_event, 294 | .get_event = get_event, 295 | 296 | .finish_event = finish_event, 297 | 298 | .event_handler_ctx = NULL 299 | 300 | }; 301 | 302 | -------------------------------------------------------------------------------- /src/gnb_payload16.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) 22 | #include 23 | #endif 24 | 25 | #ifdef _WIN32 26 | #include 27 | #include 28 | #endif 29 | 30 | #include "gnb_payload16.h" 31 | 32 | gnb_payload16_t* gnb_payload16_init(char type,uint16_t data_size){ 33 | 34 | gnb_payload16_t *gnb_payload16 = (gnb_payload16_t *)malloc(sizeof(gnb_payload16_t) + sizeof(char)*data_size); 35 | 36 | memset(gnb_payload16, 0, sizeof(gnb_payload16_t) + sizeof(char)*data_size); 37 | 38 | gnb_payload16->type = type; 39 | 40 | gnb_payload16->size = htons(sizeof(gnb_payload16_t) + sizeof(char)*data_size); 41 | 42 | return gnb_payload16; 43 | } 44 | 45 | gnb_payload16_t* gnb_payload16_create(char type, void *data, uint16_t data_size){ 46 | 47 | gnb_payload16_t *gnb_payload16 = gnb_payload16_init(type,data_size); 48 | 49 | memcpy(gnb_payload16->data,data,data_size); 50 | 51 | return gnb_payload16; 52 | 53 | } 54 | 55 | gnb_payload16_t *gnb_payload16_dup(gnb_payload16_t *gnb_payload16_in){ 56 | 57 | uint16_t size = ntohs(gnb_payload16_in->size); 58 | 59 | gnb_payload16_t *gnb_payload16 = (gnb_payload16_t *)malloc( size ); 60 | 61 | memcpy(gnb_payload16, gnb_payload16_in, size); 62 | 63 | return gnb_payload16; 64 | 65 | } 66 | 67 | uint16_t gnb_payload16_set_size(gnb_payload16_t *gnb_payload16, uint16_t new_size){ 68 | 69 | gnb_payload16->size = htons(new_size); 70 | 71 | return new_size; 72 | } 73 | 74 | uint16_t gnb_payload16_size(gnb_payload16_t *gnb_payload16){ 75 | uint16_t size = ntohs(gnb_payload16->size); 76 | return size; 77 | } 78 | 79 | uint16_t gnb_payload16_set_data_len(gnb_payload16_t *gnb_payload16, uint16_t new_len){ 80 | gnb_payload16->size = htons(new_len+GNB_PAYLOAD16_HEAD_SIZE); 81 | return new_len; 82 | } 83 | 84 | uint16_t gnb_payload16_data_len(gnb_payload16_t *gnb_payload16){ 85 | uint16_t size = ntohs(gnb_payload16->size) - GNB_PAYLOAD16_HEAD_SIZE; 86 | return size; 87 | } 88 | 89 | void gnb_payload16_free(gnb_payload16_t *gnb_payload16){ 90 | free(gnb_payload16); 91 | } 92 | 93 | 94 | gnb_payload16_ctx_t* gnb_payload16_ctx_init(uint16_t max_payload_size){ 95 | 96 | gnb_payload16_ctx_t *gnb_payload16_ctx = (gnb_payload16_ctx_t*)malloc(sizeof(gnb_payload16_ctx_t)); 97 | 98 | gnb_payload16_ctx->r_len = 0; 99 | gnb_payload16_ctx->gnb_payload16 = gnb_payload16_init(0x0, max_payload_size); 100 | gnb_payload16_ctx->max_payload_size = max_payload_size; 101 | gnb_payload16_ctx->udata = NULL; 102 | 103 | return gnb_payload16_ctx; 104 | 105 | } 106 | 107 | 108 | void gnb_payload16_ctx_free(gnb_payload16_ctx_t *gnb_payload16_ctx) { 109 | 110 | free(gnb_payload16_ctx->gnb_payload16); 111 | free(gnb_payload16_ctx); 112 | 113 | } 114 | 115 | 116 | 117 | 118 | #define GNB_FRAME_STATUS_HEAD 0 119 | #define GNB_FRAME_STATUS_PART 1 120 | int gnb_payload16_handle(void *data, size_t data_size, gnb_payload16_ctx_t *gnb_payload16_ctx, gnb_payload16_handle_cb_t cb) { 121 | 122 | uint32_t receive_bytes_offset = 0; 123 | 124 | ssize_t remain_data_len; 125 | 126 | int frame_status; 127 | 128 | uint16_t frame_size; 129 | 130 | //这里检查到来的数据是否刚好是一个完整的frame,这样对于短小的frame,可以提升处理速度 131 | if ( 0 == gnb_payload16_ctx->r_len && data_size > GNB_PAYLOAD16_HEAD_SIZE ){ 132 | 133 | frame_size = ntohs(*(uint16_t *)data); 134 | 135 | if (0==frame_size){ 136 | return -1; 137 | } 138 | 139 | if ( (int)frame_size > GNB_MAX_PAYLOAD_SIZE ) { 140 | return -2; 141 | } 142 | 143 | if ( frame_size == data_size) { 144 | 145 | if ( frame_size > gnb_payload16_ctx->max_payload_size ){ 146 | return -3; 147 | } 148 | 149 | memcpy( (void *)gnb_payload16_ctx->gnb_payload16, data, frame_size); 150 | 151 | cb(gnb_payload16_ctx->gnb_payload16, gnb_payload16_ctx->udata); 152 | return 0; 153 | } 154 | 155 | } 156 | 157 | 158 | do{ 159 | 160 | remain_data_len = data_size - receive_bytes_offset; 161 | 162 | if ( gnb_payload16_ctx->r_len >= 2 ) { 163 | frame_status = GNB_FRAME_STATUS_PART; 164 | } else { 165 | frame_status = GNB_FRAME_STATUS_HEAD; 166 | } 167 | 168 | switch ( frame_status ) { 169 | 170 | case GNB_FRAME_STATUS_PART: 171 | //对于长的frame,这个case出现的概率比较大,所以放前面 172 | 173 | frame_size = ntohs(*(uint16_t *)gnb_payload16_ctx->buffer); 174 | 175 | if ( frame_size > gnb_payload16_ctx->max_payload_size ){ 176 | return -4; 177 | } 178 | 179 | if ( remain_data_len >= (frame_size - gnb_payload16_ctx->r_len) ) { 180 | 181 | //未处理的数据 大于 整个fram的未接收的数据,此时可以得到一个完整的frame 182 | memcpy( (void *)gnb_payload16_ctx->gnb_payload16+gnb_payload16_ctx->r_len, data+receive_bytes_offset, (frame_size-gnb_payload16_ctx->r_len) ); 183 | receive_bytes_offset += (frame_size-gnb_payload16_ctx->r_len); 184 | 185 | gnb_payload16_ctx->r_len += (frame_size-gnb_payload16_ctx->r_len); 186 | 187 | //得到一个完整的 frame 通过 callback函数 传进去处理 188 | cb(gnb_payload16_ctx->gnb_payload16, gnb_payload16_ctx->udata); 189 | 190 | gnb_payload16_ctx->r_len = 0; 191 | //此时由于 gnb_payload16_ctx->r_len == 0,状态会切换到 FE_FRAME_STATUS_HEAD 192 | 193 | } else { 194 | 195 | //未处理的数据 小于 整个fram的未接收的数据,此时还不可以得到一个完整的frame 196 | //退出处理函数,等下次数据的到来 197 | memcpy( (void *)gnb_payload16_ctx->gnb_payload16+gnb_payload16_ctx->r_len, data+receive_bytes_offset, remain_data_len); 198 | 199 | gnb_payload16_ctx->r_len += remain_data_len; 200 | 201 | receive_bytes_offset += remain_data_len; 202 | return 0; 203 | 204 | } 205 | 206 | break; 207 | 208 | case GNB_FRAME_STATUS_HEAD: 209 | 210 | //这里其实不算太复杂,就是要处理一些极端的情况 211 | if ( 0 == gnb_payload16_ctx->r_len ) { 212 | //ctx的暂存区为空的情况下,未处理的数据大于 2 byte,此时可以获得frame的首部 213 | if (remain_data_len >=2){ 214 | 215 | memcpy(gnb_payload16_ctx->buffer, data+receive_bytes_offset, 2); 216 | receive_bytes_offset += 2; 217 | gnb_payload16_ctx->r_len = 2; 218 | 219 | } else { 220 | //ctx的暂存区为空的情况下,未处理的数据小于 2 byte,此时无法获得frame的首部 221 | //先把 < 2byte 的数据放入ctx的暂存区 222 | memcpy(gnb_payload16_ctx->buffer, data+receive_bytes_offset, remain_data_len); 223 | receive_bytes_offset += remain_data_len; 224 | gnb_payload16_ctx->r_len = remain_data_len; 225 | 226 | return 0; 227 | } 228 | 229 | } else if ( gnb_payload16_ctx->r_len > 0 ) { 230 | 231 | if ( remain_data_len >= (2 - gnb_payload16_ctx->r_len) ){ 232 | //ctx的暂存区已经有数据的情况下,ctx的暂存区的数据 合并上 未处理的数据能够取到 2byte 的frame首部 233 | memcpy(gnb_payload16_ctx->buffer+gnb_payload16_ctx->r_len, data+receive_bytes_offset, 2-gnb_payload16_ctx->r_len); 234 | receive_bytes_offset += (2-gnb_payload16_ctx->r_len); 235 | gnb_payload16_ctx->r_len += (2-gnb_payload16_ctx->r_len); 236 | 237 | } else { 238 | //ctx的暂存区已经有数据的情况下,ctx的暂存区的数据 合并上 未处理的数据还是不足取到 2byte 的frame首部 239 | //退出处理函数,等下次数据的到来 240 | memcpy(gnb_payload16_ctx->buffer+gnb_payload16_ctx->r_len, data+receive_bytes_offset, remain_data_len); 241 | 242 | gnb_payload16_ctx->r_len += remain_data_len; 243 | 244 | return 0; 245 | } 246 | 247 | } 248 | 249 | if ( 2 == gnb_payload16_ctx->r_len ){ 250 | //已经取到2byte 的frame首部 251 | 252 | frame_size = ntohs(*(uint16_t *)gnb_payload16_ctx->buffer); 253 | 254 | //检查frame首部(frame长度)是否合法 255 | if ( 0 == frame_size ) { 256 | return -1; 257 | } 258 | 259 | if ( (int)frame_size > GNB_MAX_PAYLOAD_SIZE ) { 260 | return -2; 261 | } 262 | 263 | //根据 frame_size 创建 payload 结构体 264 | if ( frame_size > gnb_payload16_ctx->max_payload_size ){ 265 | return -3; 266 | } 267 | //gnb_payload16_ctx->gnb_payload16 = gnb_payload16_init(0x0,frame_size); 268 | memcpy( (void *)gnb_payload16_ctx->gnb_payload16, gnb_payload16_ctx->buffer, 2); 269 | //此时,由于gnb_payload16_ctx->r_len == 2,因此在循环的时候,状态会切换到 FE_FRAME_STATUS_PART 270 | 271 | } 272 | 273 | break; 274 | 275 | default: 276 | //Error!!! 277 | break; 278 | } 279 | 280 | }while( (data_size - receive_bytes_offset) > 0 ); 281 | 282 | return 0; 283 | } 284 | 285 | -------------------------------------------------------------------------------- /src/gnb_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2019 gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef GNB_LOG_H 19 | #define GNB_LOG_H 20 | 21 | #include 22 | 23 | #include "gnb_log_type.h" 24 | 25 | gnb_log_ctx_t* gnb_log_ctx_create(); 26 | 27 | 28 | #define GNB_LOG_TYPE_STD 0 29 | #define GNB_LOG_TYPE_DEBUG 1 30 | #define GNB_LOG_TYPE_ERROR 2 31 | 32 | 33 | //log level越大,日志信息越详细,0不输出日志 34 | #define GNB_LOG_LEVEL_UNSET 0xFF 35 | 36 | #define GNB_LOG_LEVEL0 0 37 | #define GNB_LOG_LEVEL1 1 38 | #define GNB_LOG_LEVEL2 2 39 | #define GNB_LOG_LEVEL3 3 40 | 41 | 42 | /* 43 | level 控制 console file udp 的输出 44 | 45 | STD DEBUG ERROR 只是作为一种日志的内置标签,不通过 level 细分控制 46 | 47 | 要控制 debug 输出,可以让STD 使用小的level,DEBUG用高的level 48 | */ 49 | 50 | void gnb_logf(gnb_log_ctx_t *log, uint8_t log_type, uint8_t log_id, uint8_t level, const char *format, ...); 51 | 52 | int gnb_log_udp_open(gnb_log_ctx_t *log); 53 | 54 | int gnb_log_file_rotate(gnb_log_ctx_t *log); 55 | 56 | 57 | int gnb_log_udp_set_addr4(gnb_log_ctx_t *log, char *ip, uint16_t port4); 58 | int gnb_log_udp_set_addr6(gnb_log_ctx_t *log, char *ip, uint16_t port6); 59 | 60 | 61 | int gnb_log_udp_set_addr4_string(gnb_log_ctx_t *log, char *sockaddress4_string); 62 | 63 | 64 | #define GNB_LOG1(log,log_id,format,...) \ 65 | do{ \ 66 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 67 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL1 || \ 68 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL1 || \ 69 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL1) \ 70 | ){ \ 71 | gnb_logf(log,GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL1, format, ##__VA_ARGS__); \ 72 | } \ 73 | }while(0); 74 | 75 | 76 | #define GNB_LOG2(log,log_id,format,...) \ 77 | do{ \ 78 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 79 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL2 || \ 80 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL2 || \ 81 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL2) \ 82 | ){ \ 83 | gnb_logf(log,GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL2, format, ##__VA_ARGS__); \ 84 | } \ 85 | }while(0); 86 | 87 | #define GNB_LOG3(log,log_id,format,...) \ 88 | do{ \ 89 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 90 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL3 || \ 91 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL3 || \ 92 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL3) \ 93 | ){ \ 94 | gnb_logf(log,GNB_LOG_TYPE_STD, log_id, GNB_LOG_LEVEL3, format, ##__VA_ARGS__); \ 95 | } \ 96 | }while(0); 97 | 98 | 99 | 100 | 101 | #define GNB_DEBUG1(log,log_id,format,...) \ 102 | do{ \ 103 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 104 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL1 || \ 105 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL1 || \ 106 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL1) \ 107 | ){ \ 108 | gnb_logf(log,GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL1, format, ##__VA_ARGS__); \ 109 | } \ 110 | }while(0); 111 | 112 | 113 | #define GNB_DEBUG2(log,log_id,format,...) \ 114 | do{ \ 115 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 116 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL2 || \ 117 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL2 || \ 118 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL2) \ 119 | ){ \ 120 | gnb_logf(log,GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL2, format, ##__VA_ARGS__); \ 121 | } \ 122 | }while(0); 123 | 124 | #define GNB_DEBUG3(log,log_id,format,...) \ 125 | do{ \ 126 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 127 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL3 || \ 128 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL3 || \ 129 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL3) \ 130 | ){ \ 131 | gnb_logf(log,GNB_LOG_TYPE_DEBUG, log_id, GNB_LOG_LEVEL3, format, ##__VA_ARGS__); \ 132 | } \ 133 | }while(0); 134 | 135 | 136 | 137 | 138 | #define GNB_ERROR1(log,log_id,format,...) \ 139 | do{ \ 140 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 141 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL1 || \ 142 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL1 || \ 143 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL1) \ 144 | ){ \ 145 | gnb_logf(log,GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL1, format, ##__VA_ARGS__); \ 146 | } \ 147 | }while(0); 148 | 149 | 150 | #define GNB_ERROR2(log,log_id,format,...) \ 151 | do{ \ 152 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 153 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL2 || \ 154 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL2 || \ 155 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL2) \ 156 | ){ \ 157 | gnb_logf(log,GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL2, format, ##__VA_ARGS__); \ 158 | } \ 159 | }while(0); 160 | 161 | #define GNB_ERROR3(log,log_id,format,...) \ 162 | do{ \ 163 | if ( NULL != log && GNB_LOG_OUTPUT_NONE != log->output_type && \ 164 | (log->config_table[log_id].console_level >= GNB_LOG_LEVEL3 || \ 165 | log->config_table[log_id].file_level >= GNB_LOG_LEVEL3 || \ 166 | log->config_table[log_id].udp_level >= GNB_LOG_LEVEL3) \ 167 | ){ \ 168 | gnb_logf(log,GNB_LOG_TYPE_ERROR, log_id, GNB_LOG_LEVEL3, format, ##__VA_ARGS__); \ 169 | } \ 170 | }while(0); 171 | 172 | 173 | 174 | #endif 175 | 176 | -------------------------------------------------------------------------------- /src/service/gnb_udp_over_tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "gnb_platform.h" 7 | #include "gnb_network_service.h" 8 | #include "gnb_udp_over_tcp.h" 9 | 10 | #include "gnb_log.h" 11 | 12 | #define LOG_UDP6 0x29 13 | #define LOG_UDP4 0x2A 14 | #define LOG_UDP_TYPE 0x2B 15 | 16 | #define SET_LOG_FILE_PATH 0x29 17 | #define SET_LOG_UDP6 0x2A 18 | #define SET_LOG_UDP4 0x2B 19 | #define SET_LOG_UDP_TYPE 0x2C 20 | #define SET_CONSOLE_LOG_LEVEL 0x2D 21 | 22 | 23 | #define SET_FILE_LOG_LEVEL 0x2E 24 | #define SET_UDP_LOG_LEVEL 0x2F 25 | 26 | int gnb_daemon(); 27 | 28 | extern gnb_network_service_t uot_udp_service_mod; 29 | extern gnb_network_service_t uot_tcp_service_mod; 30 | 31 | 32 | static void show_useage(int argc,char *argv[]){ 33 | 34 | printf("GNB udp over tcp Service version 1.2.1 protocol version 1.2.1\n"); 35 | printf("Build[%s %s]\n",__DATE__,__TIME__); 36 | printf("Copyright (C) 2020 gnbdev\n"); 37 | printf("Usage: %s [-u] [-t]\n", argv[0]); 38 | printf("Command Summary:\n"); 39 | 40 | printf(" -t, --tcp tcp side\n"); 41 | printf(" -u, --udp udp side\n"); 42 | 43 | printf(" -l, --listen listen port\n"); 44 | 45 | #ifdef __UNIX_LIKE_OS__ 46 | printf(" -d, --daemon daemon\n"); 47 | #endif 48 | 49 | printf(" --log-udp4 send log to the address ipv4 default is '127.0.0.1:6000'\n"); 50 | printf(" --log-udp-type the log udp type 'binary' or 'text' default is 'binary'\n"); 51 | 52 | printf(" --log-console-level log-console-level 0-3\n"); 53 | printf(" --log-file-level log-file-level 0-3\n" ); 54 | printf(" --log-udp-level log-udp-level 0-3\n"); 55 | printf(" --verbose verbose mode\n"); 56 | printf(" --help\n"); 57 | 58 | printf("example:\n"); 59 | printf("%s -u -l $listen_udp_port $tcp_address $tcp_port\n", argv[0]); 60 | printf("%s -t -l $listen_tcp_port $des_address $des_udp_port\n",argv[0]); 61 | 62 | } 63 | 64 | 65 | 66 | static void setup_log_ctx(udp_over_tcp_service_conf_t *conf, gnb_log_ctx_t *log, char *log_path, char *log_udp_sockaddress4_string, uint8_t log_console_level, uint8_t log_file_level, uint8_t log_udp_level){ 67 | 68 | int rc; 69 | 70 | log->output_type = GNB_LOG_OUTPUT_STDOUT; 71 | 72 | if ( 0!=conf->daemon ) { 73 | log->output_type = GNB_LOG_OUTPUT_NONE; 74 | } 75 | 76 | if ( NULL != log_path ) { 77 | 78 | snprintf(log->log_file_path, PATH_MAX, "%s", log_path); 79 | 80 | snprintf(log->log_file_name_std, PATH_MAX+NAME_MAX, "%s/std.log", log_path); 81 | snprintf(log->log_file_name_debug, PATH_MAX+NAME_MAX, "%s/debug.log", log_path); 82 | snprintf(log->log_file_name_error, PATH_MAX+NAME_MAX, "%s/error.log", log_path); 83 | 84 | log->output_type |= GNB_LOG_OUTPUT_FILE; 85 | 86 | } else { 87 | 88 | log->log_file_path[0] = '\0'; 89 | 90 | } 91 | 92 | snprintf(log->config_table[GNB_LOG_ID_EVENT_CORE].log_name, 20, "GNB_EVENT"); 93 | snprintf(log->config_table[GNB_LOG_ID_UOT].log_name, 20, "UOT"); 94 | 95 | log->config_table[GNB_LOG_ID_EVENT_CORE].console_level = log_console_level; 96 | log->config_table[GNB_LOG_ID_EVENT_CORE].file_level = log_file_level; 97 | log->config_table[GNB_LOG_ID_EVENT_CORE].udp_level = log_udp_level; 98 | 99 | log->config_table[GNB_LOG_ID_UOT].console_level = log_console_level; 100 | log->config_table[GNB_LOG_ID_UOT].file_level = log_file_level; 101 | log->config_table[GNB_LOG_ID_UOT].udp_level = log_udp_level; 102 | 103 | 104 | gnb_log_file_rotate(log); 105 | 106 | gnb_log_udp_open(log); 107 | 108 | log->log_payload_type = GNB_EVENT_PAYLOAD_TYPE_UDPLOG; 109 | 110 | if ( '\0' != log_udp_sockaddress4_string[0] ) { 111 | rc = gnb_log_udp_set_addr4_string(log, log_udp_sockaddress4_string); 112 | log->output_type |= GNB_LOG_OUTPUT_UDP; 113 | } 114 | 115 | return; 116 | 117 | } 118 | 119 | 120 | int main (int argc,char *argv[]){ 121 | 122 | int udp_opt = 0; 123 | int tcp_opt = 0; 124 | 125 | int verbose_opt = 0; 126 | 127 | char *address = NULL; 128 | uint16_t port = 0; 129 | 130 | uint8_t log_console_level = GNB_LOG_LEVEL1; 131 | uint8_t log_file_level = GNB_LOG_LEVEL1; 132 | uint8_t log_udp_level = GNB_LOG_LEVEL1; 133 | 134 | uint8_t log_udp_type; 135 | 136 | char *log_path = NULL; 137 | 138 | gnb_log_ctx_t *log; 139 | gnb_network_service_t *service; 140 | 141 | udp_over_tcp_service_conf_t *udp_over_tcp_service_conf; 142 | 143 | udp_over_tcp_service_conf = (udp_over_tcp_service_conf_t *)malloc(sizeof(udp_over_tcp_service_conf_t)); 144 | 145 | memset(udp_over_tcp_service_conf,0,sizeof(udp_over_tcp_service_conf_t)); 146 | 147 | char log_udp_sockaddress4_string[16 + 1 + sizeof("65535")]; 148 | memset(log_udp_sockaddress4_string, 0, 16 + 1 + sizeof("65535")); 149 | 150 | int flag; 151 | 152 | struct option long_options[] = { 153 | 154 | { "udp", no_argument, 0, 'u' }, 155 | { "tcp", no_argument, 0, 't' }, 156 | 157 | { "listen", required_argument, 0, 'l' }, 158 | 159 | #ifdef __UNIX_LIKE_OS__ 160 | { "daemon", no_argument, 0, 'd' }, 161 | #endif 162 | 163 | { "log-file-path", required_argument, 0, SET_LOG_FILE_PATH }, 164 | 165 | { "log-udp6", optional_argument, &flag, LOG_UDP6 }, 166 | { "log-udp4", optional_argument, &flag, LOG_UDP4 }, 167 | { "log-udp-type", required_argument, 0, LOG_UDP_TYPE }, 168 | 169 | { "log-console-level", required_argument, 0, SET_CONSOLE_LOG_LEVEL }, 170 | { "log-file-level", required_argument, 0, SET_FILE_LOG_LEVEL }, 171 | { "log-udp-level", required_argument, 0, SET_UDP_LOG_LEVEL }, 172 | 173 | { "verbose", no_argument, 0, 'V' }, 174 | { "help", no_argument, 0, 'h' }, 175 | 176 | { 0, 0, 0, 0 } 177 | 178 | }; 179 | 180 | int opt; 181 | 182 | while (1) { 183 | 184 | int option_index = 0; 185 | 186 | opt = getopt_long (argc, argv, "l:utdVh",long_options, &option_index); 187 | 188 | if ( opt == -1 ) { 189 | break; 190 | } 191 | 192 | switch (opt) { 193 | 194 | case 'l': 195 | udp_over_tcp_service_conf->listen_port = (uint16_t)strtol(optarg, NULL, 0); 196 | break; 197 | 198 | #ifdef __UNIX_LIKE_OS__ 199 | case 'd': 200 | udp_over_tcp_service_conf->daemon = 1; 201 | break; 202 | #endif 203 | 204 | case 'u': 205 | udp_opt = 1; 206 | break; 207 | 208 | case 't': 209 | tcp_opt = 1; 210 | break; 211 | 212 | case SET_LOG_FILE_PATH: 213 | log_path = optarg; 214 | break; 215 | 216 | case SET_LOG_UDP_TYPE: 217 | 218 | if ( !strncmp(optarg, "binary", 16) ) { 219 | log_udp_type = GNB_LOG_UDP_TYPE_BINARY; 220 | } else { 221 | log_udp_type = GNB_LOG_UDP_TYPE_TEXT; 222 | } 223 | 224 | break; 225 | 226 | case SET_CONSOLE_LOG_LEVEL: 227 | log_console_level = (uint8_t)strtoul(optarg, NULL, 10); 228 | break; 229 | 230 | case SET_FILE_LOG_LEVEL: 231 | log_file_level = (uint8_t)strtoul(optarg, NULL, 10); 232 | break; 233 | 234 | case SET_UDP_LOG_LEVEL: 235 | log_udp_level = (uint8_t)strtoul(optarg, NULL, 10); 236 | break; 237 | 238 | case 'V': 239 | verbose_opt = 1; 240 | break; 241 | 242 | case 'h': 243 | show_useage(argc,argv); 244 | exit(0); 245 | 246 | default: 247 | break; 248 | 249 | } 250 | 251 | if ( 0 == opt ) { 252 | 253 | switch (flag) { 254 | 255 | case LOG_UDP4: 256 | 257 | if ( NULL != optarg ) { 258 | snprintf(log_udp_sockaddress4_string, 16 + 1 + sizeof("65535"), "%s", optarg); 259 | } else { 260 | snprintf(log_udp_sockaddress4_string, 16 + 1 + sizeof("65535"), "%s", "127.0.0.1:6000"); 261 | } 262 | 263 | break; 264 | 265 | default: 266 | break; 267 | } 268 | 269 | continue; 270 | 271 | } 272 | 273 | } 274 | 275 | 276 | if ( 0 == udp_over_tcp_service_conf->listen_port ) { 277 | show_useage(argc,argv); 278 | exit(0); 279 | } 280 | 281 | if ( (optind+2) == argc ) { 282 | address = argv[optind]; 283 | port = (uint16_t)strtol((const char *)argv[optind+1], NULL, 0); 284 | } else { 285 | show_useage(argc,argv); 286 | exit(0); 287 | } 288 | 289 | 290 | if ( (0==udp_opt && 0==tcp_opt) || (0!=udp_opt && 0!=tcp_opt) ) { 291 | show_useage(argc,argv); 292 | exit(0); 293 | } 294 | 295 | #ifdef __UNIX_LIKE_OS__ 296 | if ( udp_over_tcp_service_conf->daemon ) { 297 | gnb_daemon(); 298 | } 299 | #endif 300 | 301 | log = gnb_log_ctx_create(); 302 | 303 | if ( 0 == udp_over_tcp_service_conf->daemon && 1==verbose_opt ) { 304 | log_console_level = 3; 305 | log_udp_level = 3; 306 | } 307 | 308 | setup_log_ctx(udp_over_tcp_service_conf, log, log_path, log_udp_sockaddress4_string, log_console_level, log_file_level, log_udp_level); 309 | 310 | if ( 0 != udp_opt ) { 311 | udp_over_tcp_service_conf->tcp_address = address; 312 | udp_over_tcp_service_conf->tcp_port = port; 313 | service = gnb_network_service_create(&uot_udp_service_mod, log, 1024); 314 | gnb_network_service_init(service, udp_over_tcp_service_conf); 315 | } 316 | 317 | if ( 0 != tcp_opt ) { 318 | udp_over_tcp_service_conf->des_udp_address = address; 319 | udp_over_tcp_service_conf->des_udp_port = port; 320 | service = gnb_network_service_create(&uot_tcp_service_mod, log, 1024); 321 | gnb_network_service_init(service, udp_over_tcp_service_conf); 322 | } 323 | 324 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "log init.\n"); 325 | 326 | gnb_network_service_listen(service); 327 | gnb_network_service_loop(service); 328 | 329 | return 0; 330 | 331 | } 332 | -------------------------------------------------------------------------------- /src/gnb_lru32.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include "gnb_lru32.h" 22 | #include "gnb_doubly_linked_list.h" 23 | 24 | static gnb_lru32_node_t *gnb_lru32_node_fixed_pool_pop(gnb_lru32_t *lru){ 25 | 26 | gnb_lru32_node_t *lru_node = NULL; 27 | 28 | lru_node = gnb_fixed_pool_pop(lru->lru_node_fixed_pool); 29 | 30 | lru_node->dl_node = gnb_fixed_pool_pop(lru->dl_node_fixed_pool); 31 | 32 | if (0 != lru->block_size) { 33 | lru_node->udata = gnb_fixed_pool_pop(lru->udata_fixed_pool); 34 | } 35 | 36 | return lru_node; 37 | 38 | } 39 | 40 | 41 | static void gnb_lru32_node_fixed_pool_push(gnb_lru32_t *lru, gnb_lru32_node_t *lru_node){ 42 | 43 | gnb_fixed_pool_push(lru->dl_node_fixed_pool,lru_node->dl_node); 44 | 45 | if (0 != lru->block_size) { 46 | gnb_fixed_pool_push(lru->udata_fixed_pool,lru_node->udata); 47 | } 48 | 49 | gnb_fixed_pool_push(lru->lru_node_fixed_pool,lru_node); 50 | 51 | } 52 | 53 | 54 | gnb_lru32_t *gnb_lru32_create(gnb_heap_t *heap, uint32_t max_size,uint32_t block_size){ 55 | 56 | gnb_lru32_t *lru = (gnb_lru32_t *)gnb_heap_alloc(heap,sizeof(gnb_lru32_t)); 57 | 58 | lru->heap = heap; 59 | 60 | lru->max_size = max_size; 61 | 62 | lru->size = 0; 63 | 64 | lru->block_size = block_size; 65 | 66 | lru->lru_node_map = gnb_hash32_create(heap,max_size,max_size); 67 | 68 | if (NULL==lru->lru_node_map) { 69 | gnb_heap_free(heap,lru); 70 | return NULL; 71 | } 72 | 73 | lru->doubly_linked_list = gnb_doubly_linked_list_create(lru->heap); 74 | 75 | if ( 0 != lru->block_size ){ 76 | lru->udata_fixed_pool = gnb_fixed_pool_create(heap,max_size, lru->block_size); 77 | } 78 | 79 | lru->dl_node_fixed_pool = gnb_fixed_pool_create(heap,max_size, sizeof(gnb_doubly_linked_list_node_t)); 80 | 81 | lru->lru_node_fixed_pool = gnb_fixed_pool_create(heap,max_size, sizeof(gnb_lru32_node_t)); 82 | 83 | return lru; 84 | 85 | } 86 | 87 | 88 | void gnb_lru32_release(gnb_lru32_t *lru){ 89 | 90 | if ( 0 != lru->block_size ){ 91 | gnb_fixed_pool_release(lru->heap,lru->udata_fixed_pool); 92 | } 93 | 94 | gnb_fixed_pool_release(lru->heap,lru->dl_node_fixed_pool); 95 | gnb_fixed_pool_release(lru->heap,lru->lru_node_fixed_pool); 96 | 97 | gnb_hash32_release(lru->lru_node_map); 98 | 99 | gnb_doubly_linked_list_release(lru->doubly_linked_list); 100 | 101 | gnb_heap_free(lru->heap,lru); 102 | 103 | } 104 | 105 | 106 | void* gnb_lru32_put(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data){ 107 | 108 | gnb_lru32_node_t *lru_node; 109 | 110 | lru_node = gnb_lru32_get(lru, key, key_len); 111 | 112 | if ( NULL != lru_node ) { 113 | 114 | if (data==lru_node->udata) { 115 | return NULL; 116 | } 117 | 118 | lru_node->udata = data; 119 | return NULL; 120 | 121 | } 122 | 123 | void *pop_udata = NULL; 124 | if ( lru->size >= lru->max_size ) { 125 | pop_udata = gnb_lru32_pop_tail(lru); 126 | } 127 | 128 | lru_node = gnb_lru32_node_fixed_pool_pop(lru); 129 | 130 | if (NULL==lru_node) { 131 | //如果链表满了无法set进去,就把传入的指针返回,让调用者处理 132 | return data; 133 | } 134 | 135 | lru_node->udata = data; 136 | 137 | gnb_doubly_linked_list_add(lru->doubly_linked_list, lru_node->dl_node); 138 | 139 | gnb_hash32_set(lru->lru_node_map, key, (uint32_t)key_len, lru_node, 0); 140 | lru_node->kv = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); 141 | 142 | gnb_doubly_linked_list_node_set(lru_node->dl_node,lru_node); 143 | 144 | lru->size++; 145 | 146 | return pop_udata; 147 | 148 | } 149 | 150 | 151 | void gnb_lru32_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data, uint32_t size){ 152 | 153 | gnb_lru32_node_t *lru_node; 154 | 155 | lru_node = gnb_lru32_get(lru, key, key_len); 156 | 157 | if ( NULL != lru_node ) { 158 | 159 | if (NULL!=lru_node->udata) { 160 | gnb_heap_free(lru->heap,lru_node->udata); 161 | } 162 | 163 | lru_node->udata = gnb_heap_alloc(lru->heap,size); 164 | memcpy(lru_node->udata,data,size); 165 | 166 | return; 167 | } 168 | 169 | void *pop_udata = NULL; 170 | 171 | if ( lru->size >= lru->max_size ) { 172 | pop_udata = gnb_lru32_pop_tail(lru); 173 | if (NULL!=pop_udata) { 174 | gnb_heap_free(lru->heap,pop_udata); 175 | } 176 | } 177 | 178 | lru_node = gnb_lru32_node_fixed_pool_pop(lru); 179 | 180 | if (NULL==lru_node) { 181 | return; 182 | } 183 | 184 | lru_node->udata = gnb_heap_alloc(lru->heap,size); 185 | memcpy(lru_node->udata,data,size); 186 | 187 | gnb_doubly_linked_list_add(lru->doubly_linked_list, lru_node->dl_node); 188 | 189 | gnb_hash32_set(lru->lru_node_map, key, (uint32_t)key_len, lru_node, 0); 190 | lru_node->kv = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); 191 | 192 | gnb_doubly_linked_list_node_set(lru_node->dl_node,lru_node); 193 | 194 | lru->size++; 195 | 196 | return; 197 | 198 | } 199 | 200 | 201 | void gnb_lru32_fixed_store(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len, void *data){ 202 | 203 | gnb_lru32_node_t *lru_node; 204 | 205 | if( 0 == lru->block_size ){ 206 | return; 207 | } 208 | 209 | lru_node = gnb_lru32_get(lru, key, key_len); 210 | 211 | if ( NULL != lru_node ) { 212 | memcpy(lru_node->udata,data,lru->block_size); 213 | return; 214 | } 215 | 216 | void *pop_udata = NULL; 217 | 218 | if ( lru->size >= lru->max_size ) { 219 | pop_udata = gnb_lru32_pop_tail(lru); 220 | } 221 | 222 | lru_node = gnb_lru32_node_fixed_pool_pop(lru); 223 | 224 | if (NULL==lru_node) { 225 | return; 226 | } 227 | 228 | memcpy(lru_node->udata,data,lru->block_size); 229 | 230 | gnb_doubly_linked_list_add(lru->doubly_linked_list, lru_node->dl_node); 231 | 232 | gnb_hash32_set(lru->lru_node_map, key, (uint32_t)key_len, lru_node, 0); 233 | lru_node->kv = gnb_hash32_get(lru->lru_node_map, key, (uint32_t)key_len); 234 | 235 | gnb_doubly_linked_list_node_set(lru_node->dl_node,lru_node); 236 | 237 | lru->size++; 238 | 239 | return; 240 | 241 | } 242 | 243 | 244 | gnb_lru32_node_t* gnb_lru32_hash_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ 245 | 246 | gnb_kv32_t *kv32 = gnb_hash32_get(lru->lru_node_map,key, (uint32_t)key_len); 247 | 248 | if (NULL==kv32) { 249 | return NULL; 250 | } 251 | gnb_lru32_node_t *lru_node = GNB_HASH32_VALUE_PTR(kv32); 252 | 253 | return lru_node; 254 | } 255 | 256 | 257 | gnb_lru32_node_t* gnb_lru32_get(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ 258 | 259 | gnb_kv32_t *kv32 = gnb_hash32_get(lru->lru_node_map,key, (uint32_t)key_len); 260 | if (NULL==kv32) { 261 | return NULL; 262 | } 263 | gnb_lru32_node_t *lru_node = GNB_HASH32_VALUE_PTR(kv32); 264 | 265 | if ( NULL != lru_node ) { 266 | gnb_doubly_linked_list_move_head(lru->doubly_linked_list, lru_node->dl_node); 267 | } 268 | 269 | return lru_node; 270 | 271 | } 272 | 273 | 274 | void gnb_lru32_movetohead(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ 275 | 276 | gnb_kv32_t *kv32 = gnb_hash32_get(lru->lru_node_map,key, (uint32_t)key_len); 277 | if (NULL==kv32) { 278 | return; 279 | } 280 | 281 | gnb_lru32_node_t *lru_node = GNB_HASH32_VALUE_PTR(kv32); 282 | 283 | if ( NULL != lru_node ) { 284 | gnb_doubly_linked_list_move_head(lru->doubly_linked_list, lru_node->dl_node); 285 | } 286 | 287 | } 288 | 289 | 290 | void* gnb_lru32_pop_by_key(gnb_lru32_t *lru, unsigned char *key, uint32_t key_len){ 291 | 292 | gnb_lru32_node_t *pop_lru_node; 293 | 294 | gnb_doubly_linked_list_node_t *dl_node; 295 | 296 | void *pop_udata; 297 | 298 | pop_lru_node = gnb_lru32_get(lru, key, key_len); 299 | 300 | if ( NULL == pop_lru_node ) { 301 | return NULL; 302 | } 303 | 304 | dl_node = pop_lru_node->dl_node; 305 | 306 | gnb_doubly_linked_list_pop(lru->doubly_linked_list, dl_node); 307 | 308 | pop_udata = pop_lru_node->udata; 309 | 310 | gnb_kv32_t *kv32 = gnb_hash32_del(lru->lru_node_map, pop_lru_node->kv->key->data, pop_lru_node->kv->key->size); 311 | if (NULL!=kv32) { 312 | gnb_kv32_release(lru->lru_node_map,kv32); 313 | } 314 | 315 | gnb_lru32_node_fixed_pool_push(lru, pop_lru_node); 316 | 317 | lru->size--; 318 | 319 | return pop_udata; 320 | 321 | } 322 | 323 | 324 | void* gnb_lru32_pop_head(gnb_lru32_t *lru){ 325 | 326 | void *pop_udata = NULL; 327 | 328 | gnb_lru32_node_t *pop_lru_node; 329 | 330 | gnb_doubly_linked_list_node_t *head_dl_node; 331 | 332 | if ( 0 == lru->size || NULL==lru->doubly_linked_list->head ){ 333 | return NULL; 334 | } 335 | 336 | pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->head->data; 337 | 338 | if ( NULL==pop_lru_node ) { 339 | return NULL; 340 | } 341 | 342 | pop_udata = pop_lru_node->udata; 343 | 344 | gnb_kv32_t *kv32 = gnb_hash32_del(lru->lru_node_map, pop_lru_node->kv->key->data, pop_lru_node->kv->key->size); 345 | if (NULL!=kv32) { 346 | gnb_kv32_release(lru->lru_node_map,kv32); 347 | } 348 | 349 | gnb_lru32_node_fixed_pool_push(lru, pop_lru_node); 350 | 351 | head_dl_node = gnb_doubly_linked_list_pop_head(lru->doubly_linked_list); 352 | 353 | lru->size--; 354 | 355 | return pop_udata; 356 | 357 | } 358 | 359 | 360 | void* gnb_lru32_pop_tail(gnb_lru32_t *lru){ 361 | 362 | void *pop_udata = NULL; 363 | 364 | gnb_lru32_node_t *pop_lru_node; 365 | 366 | if ( 0 == lru->size || NULL==lru->doubly_linked_list->tail ){ 367 | return NULL; 368 | } 369 | 370 | gnb_doubly_linked_list_node_t *tail_dl_node; 371 | 372 | pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->tail->data; 373 | 374 | if (NULL==pop_lru_node) { 375 | return NULL; 376 | } 377 | 378 | pop_udata = pop_lru_node->udata; 379 | 380 | gnb_kv32_t *kv32 = gnb_hash32_del(lru->lru_node_map, pop_lru_node->kv->key->data, pop_lru_node->kv->key->size); 381 | 382 | if (NULL!=kv32) { 383 | gnb_kv32_release(lru->lru_node_map,kv32); 384 | } 385 | 386 | gnb_lru32_node_fixed_pool_push(lru, pop_lru_node); 387 | 388 | tail_dl_node = gnb_doubly_linked_list_pop_tail(lru->doubly_linked_list); 389 | 390 | lru->size--; 391 | 392 | return pop_udata; 393 | 394 | } 395 | 396 | 397 | void* gnb_lru32_get_head(gnb_lru32_t *lru){ 398 | 399 | void *pop_udata = NULL; 400 | 401 | gnb_lru32_node_t *pop_lru_node; 402 | 403 | if ( 0 == lru->size || NULL==lru->doubly_linked_list->head ){ 404 | return NULL; 405 | } 406 | 407 | pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->head->data; 408 | 409 | if ( NULL==pop_lru_node ) { 410 | return NULL; 411 | } 412 | 413 | pop_udata = pop_lru_node->udata; 414 | 415 | return pop_udata; 416 | 417 | } 418 | 419 | 420 | void* gnb_lru32_get_tail(gnb_lru32_t *lru){ 421 | 422 | void *pop_udata = NULL; 423 | 424 | gnb_lru32_node_t *pop_lru_node; 425 | 426 | if ( 0 == lru->size || NULL==lru->doubly_linked_list->tail ){ 427 | return NULL; 428 | } 429 | 430 | pop_lru_node = (gnb_lru32_node_t *)lru->doubly_linked_list->tail->data; 431 | 432 | if (NULL==pop_lru_node) { 433 | return NULL; 434 | } 435 | 436 | pop_udata = pop_lru_node->udata; 437 | 438 | return pop_udata; 439 | 440 | } 441 | -------------------------------------------------------------------------------- /src/service/uot_udp_service.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gnb_network_service.h" 4 | #include "gnb_udp_over_tcp.h" 5 | 6 | #include "gnb_address.h" 7 | #include "gnb_alloc.h" 8 | #include "gnb_hash32.h" 9 | #include "gnb_buf.h" 10 | #include "gnb_payload16.h" 11 | #include "gnb_address.h" 12 | #include "gnb_log.h" 13 | 14 | 15 | #define DEFAULT_TCP_RECONNECT_INTERVAL_TIME_SEC 5 16 | 17 | #define GNB_UOT_SEND_KEEPALIVE_INTERVAL_TIME_SEC 3 18 | 19 | 20 | typedef struct _uot_udp_service_ctx_t{ 21 | 22 | uot_channel_t *channel; 23 | 24 | }uot_udp_service_ctx_t; 25 | 26 | 27 | static int try_tcp_connect(gnb_network_service_t *service){ 28 | 29 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)service->ctx; 30 | 31 | uot_channel_t *channel = service_ctx->channel; 32 | 33 | udp_over_tcp_service_conf_t *udp_over_tcp_service_conf = (udp_over_tcp_service_conf_t *)service->service_conf; 34 | 35 | int rc; 36 | 37 | gnb_connection_t *conn = gnb_connection_create(service); 38 | 39 | gnb_set_sockaddress4(&conn->remote_sockaddress, GNB_PROTOCOL_TCP, udp_over_tcp_service_conf->tcp_address, udp_over_tcp_service_conf->tcp_port); 40 | 41 | conn->udata = channel; 42 | 43 | channel->tcp_conn = conn; 44 | channel->tcp_conn->udata = channel; 45 | channel->keepalive_ts_sec = service->now_time_sec; 46 | channel->last_reconnect_time_sec = service->now_time_sec; 47 | 48 | rc = gnb_network_service_connect(service, channel->tcp_conn); 49 | 50 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "try to connect %s rc=%d\n", GNB_SOCKETADDRSTR1(&conn->remote_sockaddress), rc); 51 | 52 | return rc; 53 | 54 | } 55 | 56 | 57 | static int service_init_cb(gnb_network_service_t *service){ 58 | 59 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)gnb_heap_alloc(service->heap, sizeof(uot_udp_service_ctx_t)); 60 | service->ctx = service_ctx; 61 | 62 | uot_channel_t *channel = gnb_heap_alloc(service->heap, sizeof(uot_channel_t)); 63 | 64 | memset(channel,0,sizeof(uot_channel_t)); 65 | 66 | channel->gnb_payload16_ctx = gnb_payload16_ctx_init(UTO_MAX_TCP_PAYLOAD_SIZE); 67 | channel->gnb_payload16_ctx->udata = channel; 68 | channel->service = service; 69 | 70 | service_ctx->channel = channel; 71 | 72 | return 0; 73 | 74 | } 75 | 76 | 77 | static int service_listen_cb(gnb_network_service_t *service){ 78 | 79 | udp_over_tcp_service_conf_t *udp_over_tcp_service_conf = (udp_over_tcp_service_conf_t *)service->service_conf; 80 | 81 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)service->ctx; 82 | 83 | uot_channel_t *channel = service_ctx->channel; 84 | 85 | service->conn_array = (gnb_conn_array_t *)gnb_heap_alloc(service->heap, sizeof(gnb_conn_array_t) + sizeof(gnb_connection_t) * 1); 86 | service->conn_array->size = 1; 87 | 88 | gnb_set_sockaddress4(&service->m_local_sockaddress0, GNB_PROTOCOL_UDP, "0.0.0.0", udp_over_tcp_service_conf->listen_port); 89 | 90 | channel->udp_conn = &service->conn_array->conn[0]; 91 | channel->udp_conn->udata = channel; 92 | 93 | try_tcp_connect(service); 94 | 95 | return 0; 96 | 97 | } 98 | 99 | 100 | static int service_connect_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 101 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "connect %s successed!\n", GNB_SOCKETADDRSTR1(&conn->remote_sockaddress)); 102 | return 0; 103 | } 104 | 105 | 106 | static void handle_keepalive(gnb_payload16_t *payload16, uot_channel_t *channel){ 107 | 108 | gnb_connection_t *udp_conn = channel->udp_conn; 109 | gnb_network_service_t *service = channel->service; 110 | channel->keepalive_ts_sec = service->now_time_sec; 111 | 112 | } 113 | 114 | 115 | static void tcp_to_udp(gnb_payload16_t *payload16, uot_channel_t *channel){ 116 | 117 | gnb_connection_t *tcp_conn = channel->tcp_conn; 118 | gnb_connection_t *udp_conn = channel->udp_conn; 119 | 120 | gnb_network_service_t *service = (gnb_network_service_t *)channel->service; 121 | 122 | uint32_t payload_size = gnb_payload16_size(payload16); 123 | uint32_t payload_data_len = gnb_payload16_data_len(payload16); 124 | 125 | GNB_BUF_RESET(udp_conn->send_zbuf); 126 | 127 | if ( payload_size > GNB_BUF_REMAIN(udp_conn->send_zbuf) ) { 128 | //Drop the udp payload 129 | return; 130 | } 131 | 132 | memcpy(udp_conn->send_zbuf->pos, payload16->data, gnb_payload16_data_len(payload16)); 133 | 134 | udp_conn->send_zbuf->las += gnb_payload16_data_len(payload16); 135 | 136 | ssize_t n_send = gnb_network_service_udp_send(service, udp_conn); 137 | 138 | if ( -1 == n_send ) { 139 | //add log 140 | GNB_SERVICE_NOTIFY_SEND(service, udp_conn); 141 | } 142 | 143 | if ( n_send > 0 ) { 144 | //add log 145 | GNB_BUF_RESET(udp_conn->send_zbuf); 146 | } 147 | 148 | return ; 149 | 150 | } 151 | 152 | 153 | static int payload16_handle_callback(gnb_payload16_t *payload16, void *ctx) { 154 | 155 | uot_channel_t *channel = (uot_channel_t *)ctx; 156 | 157 | switch ( payload16->type ) { 158 | 159 | case GNB_PAYLOAD_TYPE_UDP_OVER_TCP: 160 | tcp_to_udp(payload16, channel); 161 | break; 162 | 163 | case GNB_PAYLOAD_TYPE_TCP_KEEPALIVE: 164 | handle_keepalive(payload16, channel); 165 | break; 166 | 167 | default: 168 | break; 169 | } 170 | 171 | return 0; 172 | 173 | } 174 | 175 | 176 | static void handle_udp(gnb_network_service_t *service, uot_channel_t *channel){ 177 | 178 | gnb_connection_t *tcp_conn = channel->tcp_conn; 179 | gnb_connection_t *udp_conn = channel->udp_conn; 180 | 181 | int recv_len; 182 | 183 | recv_len = (GNB_BUF_LEN(udp_conn->recv_zbuf)); 184 | 185 | if ( recv_len > GNB_BUF_SIZE(tcp_conn->send_zbuf) ) { 186 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "udp side tcp buffer is small conn[%s]\n", GNB_SOCKETADDRSTR1(&tcp_conn->remote_sockaddress)); 187 | GNB_BUF_RESET(udp_conn->recv_zbuf); 188 | return; 189 | } 190 | 191 | if ( recv_len > GNB_BUF_REMAIN(tcp_conn->send_zbuf) ) { 192 | GNB_BUF_RESET(udp_conn->recv_zbuf); 193 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "udp side tcp buffer is FULL! conn[%s]\n", GNB_SOCKETADDRSTR1(&tcp_conn->remote_sockaddress)); 194 | goto finish; 195 | } 196 | 197 | gnb_payload16_t *payload16; 198 | payload16 = (gnb_payload16_t *)tcp_conn->send_zbuf->las; 199 | gnb_payload16_set_data_len(payload16,recv_len); 200 | payload16->type = GNB_PAYLOAD_TYPE_UDP_OVER_TCP; 201 | memcpy(payload16->data, udp_conn->recv_zbuf->pos, recv_len); 202 | 203 | tcp_conn->send_zbuf->las += gnb_payload16_size(payload16); 204 | 205 | finish: 206 | 207 | GNB_BUF_RESET(udp_conn->recv_zbuf); 208 | 209 | GNB_SERVICE_NOTIFY_SEND(service, tcp_conn); 210 | 211 | } 212 | 213 | 214 | static void handle_tcp(gnb_network_service_t *service, uot_channel_t *channel){ 215 | 216 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)service->ctx; 217 | 218 | gnb_connection_t *tcp_conn = channel->tcp_conn; 219 | gnb_connection_t *udp_conn = channel->udp_conn; 220 | 221 | int recv_len; 222 | int ret; 223 | 224 | recv_len = (GNB_BUF_LEN(tcp_conn->recv_zbuf)); 225 | 226 | ret = gnb_payload16_handle(tcp_conn->recv_zbuf->pos, recv_len, channel->gnb_payload16_ctx, payload16_handle_callback); 227 | 228 | if ( ret < 0 ) { 229 | tcp_conn->status = TCP_CONNECT_FINISH; 230 | return; 231 | } 232 | 233 | GNB_BUF_RESET(tcp_conn->recv_zbuf); 234 | 235 | channel->keepalive_ts_sec = service->now_time_sec; 236 | 237 | } 238 | 239 | 240 | static int service_recv_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 241 | 242 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)service->ctx; 243 | 244 | uot_channel_t *channel = NULL; 245 | 246 | int recv_len; 247 | 248 | channel = (uot_channel_t *)conn->udata; 249 | 250 | if ( NULL==channel ) { 251 | return 0; 252 | } 253 | 254 | if ( GNB_EVENT_FD_UDP4_SOCKET == conn->event->fd_type ) { 255 | handle_udp(service, channel); 256 | goto finish; 257 | } 258 | 259 | if ( GNB_EVENT_FD_TCPV4_CONNECT == conn->event->fd_type ) { 260 | handle_tcp(service, channel); 261 | goto finish; 262 | } 263 | 264 | finish: 265 | 266 | GNB_LOG2(service->log, GNB_LOG_ID_UOT,"recv=%lu total=%lu \n", conn->n_recv, conn->n_recv_total); 267 | 268 | return 0; 269 | 270 | } 271 | 272 | 273 | static int service_send_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 274 | 275 | GNB_BUF_RESET(conn->send_zbuf); 276 | GNB_LOG2(service->log, GNB_LOG_ID_UOT,"send=%lu total=%lu \n", conn->n_send, conn->n_send_total); 277 | return 0; 278 | 279 | } 280 | 281 | 282 | static int service_close_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 283 | 284 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)service->ctx; 285 | uot_channel_t *channel = NULL; 286 | 287 | channel = (uot_channel_t *)conn->udata; 288 | gnb_connection_release(service, channel->tcp_conn); 289 | channel->tcp_conn = NULL; 290 | 291 | return 0; 292 | 293 | } 294 | 295 | 296 | static void send_keepalive_frame(gnb_network_service_t *service, gnb_connection_t *tcp_conn){ 297 | 298 | gnb_payload16_t *payload16; 299 | 300 | uot_keepalive_frame_t *uot_keepalive_frame; 301 | 302 | if ( ( sizeof(gnb_payload16_t) + sizeof(uot_keepalive_frame_t) ) > GNB_BUF_REMAIN(tcp_conn->send_zbuf) ) { 303 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "try to send keepalive udp side tcp buffer is FULL! conn[%s]\n", GNB_SOCKETADDRSTR1(&tcp_conn->remote_sockaddress)); 304 | goto finish; 305 | } 306 | 307 | payload16 = (gnb_payload16_t *)tcp_conn->send_zbuf->las; 308 | 309 | payload16->type = GNB_PAYLOAD_TYPE_TCP_KEEPALIVE; 310 | gnb_payload16_set_data_len(payload16, sizeof(uot_keepalive_frame_t) ); 311 | 312 | uot_keepalive_frame = (uot_keepalive_frame_t *)payload16->data; 313 | uot_keepalive_frame->src_ts_usec = gnb_htonll(service->now_time_sec); 314 | snprintf(uot_keepalive_frame->text, 16, "keepalive"); 315 | 316 | tcp_conn->send_zbuf->las += gnb_payload16_size(payload16); 317 | 318 | finish: 319 | 320 | GNB_SERVICE_NOTIFY_SEND(service, tcp_conn); 321 | 322 | } 323 | 324 | 325 | static int service_idle_cb(gnb_network_service_t *service){ 326 | 327 | uot_udp_service_ctx_t *service_ctx = (uot_udp_service_ctx_t *)service->ctx; 328 | uot_channel_t *channel = service_ctx->channel; 329 | uint64_t keepalive_timeout_sec; 330 | 331 | int rc; 332 | 333 | if ( NULL == channel->tcp_conn ) { 334 | 335 | if( (service->now_time_sec - channel->last_reconnect_time_sec) > DEFAULT_TCP_RECONNECT_INTERVAL_TIME_SEC ) { 336 | rc = try_tcp_connect(service); 337 | } 338 | 339 | return 0; 340 | 341 | } 342 | 343 | if ( (service->now_time_sec - channel->last_send_keepalive_ts_sec) > GNB_UOT_SEND_KEEPALIVE_INTERVAL_TIME_SEC ) { 344 | send_keepalive_frame(service, channel->tcp_conn); 345 | channel->last_send_keepalive_ts_sec = service->now_time_sec; 346 | return 0; 347 | } 348 | 349 | keepalive_timeout_sec = service->now_time_sec - channel->keepalive_ts_sec; 350 | 351 | GNB_LOG2(service->log, GNB_LOG_ID_UOT, "keepalive_ts_sec=%d keepalive_timeout_sec=%d/%d\n", channel->keepalive_ts_sec, keepalive_timeout_sec, GNB_UOT_KEEPALIVE_TIMEOUT_SEC); 352 | 353 | if ( keepalive_timeout_sec > GNB_UOT_KEEPALIVE_TIMEOUT_SEC ) { 354 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "connection %s time out sec=%d\n", GNB_SOCKETADDRSTR1(&channel->tcp_conn->remote_sockaddress), keepalive_timeout_sec); 355 | gnb_connection_close(service, channel->tcp_conn); 356 | gnb_connection_release(service, channel->tcp_conn); 357 | channel->tcp_conn = NULL; 358 | } 359 | 360 | return 0; 361 | 362 | } 363 | 364 | 365 | gnb_network_service_t uot_udp_service_mod = { 366 | 367 | .recv_zbuf_size = (1024 *128), 368 | .send_zbuf_size = (1024 *128), 369 | 370 | .event_cmd = NULL, 371 | .conn_array = NULL, 372 | 373 | .init_cb = service_init_cb, 374 | .listen_cb = service_listen_cb, 375 | .accept_cb = NULL, 376 | .connect_cb = service_connect_cb, 377 | .recv_cb = service_recv_cb, 378 | .send_cb = service_send_cb, 379 | .close_cb = service_close_cb, 380 | .idle_cb = service_idle_cb, 381 | 382 | .ctx = NULL 383 | 384 | }; 385 | -------------------------------------------------------------------------------- /src/gnb_log.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #endif 33 | 34 | 35 | #ifdef _WIN32 36 | 37 | #undef _WIN32_WINNT 38 | #define _WIN32_WINNT 0x0600 39 | 40 | #include 41 | #include 42 | 43 | #endif 44 | 45 | 46 | #include "gnb_log.h" 47 | #include "gnb_time.h" 48 | #include "gnb_payload16.h" 49 | 50 | 51 | #define GNB_LOG_LINE_MAX 1024*4 52 | 53 | static void open_log_file(gnb_log_ctx_t *log){ 54 | 55 | log->std_fd = open(log->log_file_name_std, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); 56 | log->debug_fd = open(log->log_file_name_debug, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); 57 | log->error_fd = open(log->log_file_name_error, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR); 58 | 59 | } 60 | 61 | 62 | static void close_log_file_pre_fd(gnb_log_ctx_t *log){ 63 | 64 | if ( log->pre_std_fd > 0 ) { 65 | close(log->pre_std_fd); 66 | log->pre_std_fd = -1; 67 | } 68 | 69 | if ( log->pre_debug_fd > 0 ) { 70 | close(log->pre_debug_fd); 71 | log->pre_debug_fd = -1; 72 | } 73 | 74 | if ( log->pre_error_fd > 0 ) { 75 | close(log->pre_error_fd); 76 | log->pre_error_fd = -1; 77 | } 78 | 79 | } 80 | 81 | 82 | static void log_file_output(gnb_log_ctx_t *log, uint8_t log_type, char *log_string, int log_string_len){ 83 | 84 | int ret; 85 | 86 | switch (log_type) { 87 | 88 | case GNB_LOG_TYPE_STD: 89 | ret = write(log->std_fd, log_string, log_string_len); 90 | break; 91 | 92 | case GNB_LOG_TYPE_DEBUG: 93 | ret = write(log->debug_fd, log_string, log_string_len); 94 | break; 95 | 96 | case GNB_LOG_TYPE_ERROR: 97 | ret = write(log->error_fd, log_string, log_string_len); 98 | break; 99 | 100 | default: 101 | break; 102 | 103 | } 104 | 105 | } 106 | 107 | 108 | static void log_console_output(int log_type, char *log_string, int log_string_len){ 109 | 110 | int rc; 111 | 112 | switch (log_type) { 113 | 114 | case GNB_LOG_TYPE_STD: 115 | case GNB_LOG_TYPE_DEBUG: 116 | rc = write(STDOUT_FILENO, log_string, log_string_len); 117 | break; 118 | 119 | case GNB_LOG_TYPE_ERROR: 120 | rc = write(STDERR_FILENO, log_string, log_string_len); 121 | break; 122 | 123 | default: 124 | break; 125 | 126 | } 127 | 128 | } 129 | 130 | 131 | static void log_udp_output(gnb_log_ctx_t *log, uint8_t log_type, char *log_string, int log_string_len){ 132 | 133 | struct sockaddr_in6 saddr6; 134 | struct sockaddr_in saddr4; 135 | 136 | if ( log->socket6_fd >0 ) { 137 | 138 | memset(&saddr6,0, sizeof(struct sockaddr_in6)); 139 | saddr6.sin6_family = AF_INET6; 140 | saddr6.sin6_port = log->port6; 141 | memcpy(&saddr6.sin6_addr, log->addr6, 16); 142 | 143 | sendto(log->socket6_fd, log_string, 144 | log_string_len, 0, 145 | (struct sockaddr *)&saddr6, sizeof(struct sockaddr_in6)); 146 | 147 | } 148 | 149 | if ( log->socket4_fd >0 ) { 150 | 151 | memset(&saddr4,0, sizeof(struct sockaddr_in)); 152 | saddr4.sin_family = AF_INET; 153 | saddr4.sin_port = log->port4; 154 | 155 | memcpy(&saddr4.sin_addr.s_addr, log->addr4, 4); 156 | 157 | sendto(log->socket4_fd, log_string, 158 | log_string_len, 0, 159 | (struct sockaddr *)&saddr4, sizeof(struct sockaddr_in)); 160 | 161 | } 162 | 163 | } 164 | 165 | 166 | 167 | static void log_udp_binary_output(gnb_log_ctx_t *log, uint8_t log_type, uint8_t log_id, char *log_string_buffer, int log_string_len){ 168 | 169 | struct sockaddr_in6 saddr6; 170 | struct sockaddr_in saddr4; 171 | 172 | uint16_t data_size = (uint16_t)log_string_len; 173 | 174 | gnb_payload16_t *gnb_payload16 = (gnb_payload16_t *)log_string_buffer; 175 | 176 | gnb_payload16->type = log->log_payload_type; 177 | 178 | gnb_payload16->sub_type = log_id; 179 | 180 | gnb_payload16_set_data_len(gnb_payload16, data_size); 181 | 182 | if ( log->socket6_fd >0 ) { 183 | 184 | memset(&saddr6,0, sizeof(struct sockaddr_in)); 185 | saddr6.sin6_family = AF_INET6; 186 | saddr6.sin6_port = log->port6; 187 | memcpy(&saddr6.sin6_addr, log->addr6, 16); 188 | 189 | sendto(log->socket6_fd, (void *)gnb_payload16, 190 | data_size+4, 0, 191 | (struct sockaddr *)&saddr6, sizeof(struct sockaddr_in6)); 192 | 193 | } 194 | 195 | if ( log->socket4_fd >0 ) { 196 | 197 | memset(&saddr4,0, sizeof(struct sockaddr_in)); 198 | saddr4.sin_family = AF_INET; 199 | saddr4.sin_port = log->port4; 200 | 201 | memcpy(&saddr4.sin_addr.s_addr, log->addr4, 4); 202 | 203 | sendto(log->socket4_fd, (void *)gnb_payload16, 204 | data_size+4, 0, 205 | (struct sockaddr *)&saddr4, sizeof(struct sockaddr_in)); 206 | 207 | } 208 | 209 | } 210 | 211 | 212 | void gnb_logf(gnb_log_ctx_t *log, uint8_t log_type, uint8_t log_id, uint8_t level, const char *format, ...){ 213 | 214 | char now_time_string[GNB_TIME_STRING_MAX]; 215 | 216 | char log_string_buffer[GNB_LOG_LINE_MAX+4]; 217 | 218 | char *log_string; 219 | 220 | int log_string_len; 221 | int len; 222 | 223 | char *p; 224 | 225 | //加上 一个 offset 4 用于后面的 udp binary output 可以加上一个4字节的 gnb_payload 首部 226 | log_string = log_string_buffer+4; 227 | 228 | p = log_string; 229 | 230 | gnb_now_timef("%y-%m-%d %H:%M:%S", now_time_string, GNB_TIME_STRING_MAX); 231 | 232 | len = snprintf(p, GNB_LOG_LINE_MAX, "%s %s ", now_time_string, log->config_table[log_id].log_name); 233 | 234 | log_string_len = len; 235 | 236 | if ( log_string_len > GNB_LOG_LINE_MAX ) { 237 | return; 238 | } 239 | 240 | p += log_string_len; 241 | 242 | va_list ap; 243 | 244 | va_start(ap, format); 245 | 246 | len = vsnprintf(p, GNB_LOG_LINE_MAX, format, ap); 247 | 248 | va_end(ap); 249 | 250 | log_string_len += len; 251 | 252 | if ( log_string_len > GNB_LOG_LINE_MAX ) { 253 | return; 254 | } 255 | 256 | if ( log->output_type & GNB_LOG_OUTPUT_STDOUT ) { 257 | log_console_output(log_type, log_string, log_string_len); 258 | } 259 | 260 | if ( log->output_type & GNB_LOG_OUTPUT_FILE ) { 261 | log_file_output(log, log_type, log_string, log_string_len); 262 | } 263 | 264 | if ( log->output_type & GNB_LOG_OUTPUT_UDP ) { 265 | 266 | if (GNB_LOG_UDP_TYPE_BINARY == log->log_udp_type) { 267 | log_udp_binary_output(log, log_type, log_id, log_string_buffer, log_string_len); 268 | } else { 269 | log_udp_output(log, log_type, log_string, log_string_len); 270 | } 271 | 272 | } 273 | 274 | } 275 | 276 | 277 | int gnb_log_udp_open(gnb_log_ctx_t *log){ 278 | 279 | struct sockaddr_in6 svr_addr6; 280 | struct sockaddr_in svr_addr; 281 | 282 | int on; 283 | 284 | int ret; 285 | 286 | log->socket6_fd = socket(AF_INET6, SOCK_DGRAM, 0); 287 | on = 1; 288 | setsockopt(log->socket6_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on)); 289 | on = 1; 290 | setsockopt(log->socket6_fd, IPPROTO_IPV6, IPV6_V6ONLY,(char *)&on, sizeof(on)); 291 | memset(&svr_addr6,0, sizeof(struct sockaddr_in6)); 292 | svr_addr6.sin6_family = AF_INET6; 293 | svr_addr6.sin6_port = 0; 294 | svr_addr6.sin6_addr = in6addr_any; 295 | ret = bind(log->socket6_fd, (struct sockaddr *)&svr_addr6, sizeof(struct sockaddr_in6)); 296 | 297 | 298 | log->socket4_fd = socket(AF_INET, SOCK_DGRAM, 0); 299 | on = 1; 300 | setsockopt(log->socket4_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on) ); 301 | memset(&svr_addr,0, sizeof(struct sockaddr_in)); 302 | svr_addr.sin_family = AF_INET; 303 | svr_addr.sin_port = 0; 304 | svr_addr.sin_addr.s_addr = htonl(INADDR_ANY); 305 | ret = bind(log->socket4_fd, (struct sockaddr *)&svr_addr, sizeof(struct sockaddr_in)); 306 | 307 | memcpy(log->addr6, &in6addr_loopback, 16); 308 | log->port6 = htons(9000); 309 | 310 | *((uint32_t *)log->addr4) = htonl(INADDR_LOOPBACK); 311 | log->port4 = htons(9000); 312 | 313 | return 0; 314 | 315 | } 316 | 317 | 318 | int gnb_log_udp_set_addr4(gnb_log_ctx_t *log, char *ip, uint16_t port4){ 319 | 320 | inet_pton(AF_INET, ip, (struct in_addr *)log->addr4); 321 | 322 | log->port4 = htons(port4); 323 | 324 | return 0; 325 | } 326 | 327 | 328 | int gnb_log_udp_set_addr6(gnb_log_ctx_t *log, char *ip, uint16_t port6){ 329 | 330 | inet_pton(AF_INET6, ip, (struct in6_addr *)log->addr6); 331 | 332 | log->port6 = htons(port6); 333 | 334 | return 0; 335 | } 336 | 337 | 338 | int gnb_log_udp_set_addr4_string(gnb_log_ctx_t *log, char *sockaddress4_string){ 339 | 340 | unsigned long int ul; 341 | 342 | #define MAX_SOCKADDRESS_STRING ( 16 + 1 + sizeof("65535") ) 343 | 344 | char sockaddress4_string_copy[MAX_SOCKADDRESS_STRING+1]; 345 | 346 | int sockaddress4_string_len = strlen(sockaddress4_string); 347 | 348 | if (sockaddress4_string_len > MAX_SOCKADDRESS_STRING ) { 349 | return -1; 350 | } 351 | 352 | strncpy(sockaddress4_string_copy, sockaddress4_string, MAX_SOCKADDRESS_STRING); 353 | 354 | int i; 355 | 356 | char *p = sockaddress4_string_copy; 357 | 358 | for( i=0; iport4 = htons(port); 379 | 380 | inet_pton(AF_INET, sockaddress4_string_copy, (struct in_addr *)log->addr4); 381 | 382 | return 0; 383 | 384 | } 385 | 386 | 387 | gnb_log_ctx_t* gnb_log_ctx_create(){ 388 | 389 | gnb_log_ctx_t *log = (gnb_log_ctx_t *)malloc(sizeof(gnb_log_ctx_t)); 390 | 391 | memset(log, 0, sizeof(gnb_log_ctx_t)); 392 | 393 | log->std_fd = -1; 394 | log->debug_fd = -1; 395 | log->error_fd = -1; 396 | 397 | log->pre_std_fd = -1; 398 | log->pre_debug_fd = -1; 399 | log->pre_error_fd = -1; 400 | 401 | log->socket6_fd = -1; 402 | log->socket4_fd = -1; 403 | 404 | return log; 405 | 406 | } 407 | 408 | 409 | int gnb_log_file_rotate(gnb_log_ctx_t *log){ 410 | 411 | char now_time_string[GNB_TIME_STRING_MAX]; 412 | 413 | char archive_name[PATH_MAX+NAME_MAX]; 414 | 415 | int mday = gnb_now_mday(); 416 | 417 | if (mday == log->pre_mday) { 418 | close_log_file_pre_fd(log); 419 | return 0; 420 | } 421 | 422 | if ( !(log->output_type & GNB_LOG_OUTPUT_FILE) ) { 423 | return 1; 424 | } 425 | 426 | log->pre_mday = mday; 427 | 428 | gnb_now_timef("%Y_%m_%d",now_time_string,GNB_TIME_STRING_MAX); 429 | 430 | snprintf(archive_name, PATH_MAX+NAME_MAX, "%s/std_%s.log.arc", log->log_file_path, now_time_string); 431 | rename( (const char *)log->log_file_name_std, (const char *)archive_name ); 432 | log->pre_std_fd = log->std_fd; 433 | 434 | log->pre_debug_fd = log->debug_fd; 435 | snprintf(archive_name, PATH_MAX+NAME_MAX, "%s/debug_%s.log.arc", log->log_file_path, now_time_string); 436 | rename( (const char *)log->log_file_name_debug, (const char *)archive_name ); 437 | 438 | 439 | log->pre_error_fd = log->error_fd; 440 | snprintf(archive_name, PATH_MAX+NAME_MAX, "%s/error_%s.log.arc", log->log_file_path, now_time_string); 441 | rename( (const char *)log->log_file_name_error, (const char *)archive_name ); 442 | 443 | open_log_file(log); 444 | 445 | return 0; 446 | 447 | } 448 | -------------------------------------------------------------------------------- /src/service/uot_tcp_service.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "gnb_network_service.h" 5 | #include "gnb_udp_over_tcp.h" 6 | 7 | #include "gnb_address.h" 8 | #include "gnb_alloc.h" 9 | #include "gnb_lru32.h" 10 | #include "gnb_buf.h" 11 | #include "gnb_payload16.h" 12 | #include "gnb_log.h" 13 | 14 | 15 | typedef struct _uot_table_t{ 16 | 17 | gnb_sockaddress_t remote_udp_sockaddress; 18 | 19 | }uot_table_t; 20 | 21 | 22 | typedef struct _uot_tcp_service_ctx_t{ 23 | 24 | gnb_lru32_t *channel_lru; 25 | 26 | }uot_tcp_service_ctx_t; 27 | 28 | 29 | static void send_keepalive_echo_frame(gnb_network_service_t *service, gnb_connection_t *tcp_conn){ 30 | 31 | gnb_payload16_t *payload16; 32 | 33 | uot_keepalive_frame_t *uot_keepalive_frame; 34 | 35 | if ( ( sizeof(gnb_payload16_t) + sizeof(uot_keepalive_frame_t) ) > GNB_BUF_REMAIN(tcp_conn->send_zbuf) ) { 36 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "try to send keepalive echo tcp buffer is FULL! conn[%s]\n", GNB_SOCKETADDRSTR1(&tcp_conn->remote_sockaddress)); 37 | goto finish; 38 | } 39 | 40 | payload16 = (gnb_payload16_t *)tcp_conn->send_zbuf->las; 41 | 42 | payload16->type = GNB_PAYLOAD_TYPE_TCP_KEEPALIVE; 43 | 44 | gnb_payload16_set_data_len(payload16, sizeof(uot_keepalive_frame_t) ); 45 | 46 | uot_keepalive_frame = (uot_keepalive_frame_t *)payload16->data; 47 | uot_keepalive_frame->src_ts_usec = gnb_htonll(service->now_time_sec); 48 | snprintf(uot_keepalive_frame->text, 16, "keepalive echo"); 49 | 50 | tcp_conn->send_zbuf->las += gnb_payload16_size(payload16); 51 | 52 | finish: 53 | 54 | GNB_SERVICE_NOTIFY_SEND(service, tcp_conn); 55 | 56 | } 57 | 58 | 59 | static int service_init_cb(gnb_network_service_t *service){ 60 | 61 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)gnb_heap_alloc(service->heap, sizeof(uot_tcp_service_ctx_t)); 62 | 63 | service_ctx->channel_lru = gnb_lru32_create(service->heap, 1024, sizeof(uot_channel_t)); 64 | 65 | service->ctx = service_ctx; 66 | 67 | service->conn_array = (gnb_conn_array_t *)gnb_heap_alloc(service->heap, sizeof(gnb_conn_array_t) + sizeof(gnb_connection_t) * 1); 68 | service->conn_array->size = 1; 69 | 70 | return 0; 71 | 72 | } 73 | 74 | 75 | static int service_listen_cb(gnb_network_service_t *service){ 76 | 77 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 78 | 79 | udp_over_tcp_service_conf_t *udp_over_tcp_service_conf = (udp_over_tcp_service_conf_t *)service->service_conf; 80 | 81 | gnb_set_sockaddress4(&service->m_local_sockaddress0, GNB_PROTOCOL_TCP, "0.0.0.0", udp_over_tcp_service_conf->listen_port); 82 | 83 | uot_table_t *uot_table0 = gnb_heap_alloc(service->heap, sizeof(uot_table_t)); 84 | 85 | gnb_set_sockaddress4(&uot_table0->remote_udp_sockaddress, GNB_PROTOCOL_UDP, udp_over_tcp_service_conf->des_udp_address, udp_over_tcp_service_conf->des_udp_port); 86 | 87 | service->m_conn0.conn_data = uot_table0; 88 | 89 | return 0; 90 | 91 | } 92 | 93 | 94 | static int service_accept_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 95 | 96 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 97 | 98 | uot_table_t *uot_table = (uot_table_t *)conn->conn_data; 99 | 100 | uot_channel_t *channel = gnb_heap_alloc(service->heap, sizeof(uot_channel_t)); 101 | 102 | channel->tcp_conn = conn; 103 | 104 | channel->udp_conn = gnb_connection_create(service); 105 | channel->udp_conn->remote_sockaddress = uot_table->remote_udp_sockaddress; 106 | 107 | gnb_network_service_udp_channel(service, channel->udp_conn); 108 | 109 | channel->tcp_conn->udata = channel; 110 | channel->udp_conn->udata = channel; 111 | channel->service = service; 112 | 113 | channel->gnb_payload16_ctx = gnb_payload16_ctx_init(UTO_MAX_TCP_PAYLOAD_SIZE); 114 | channel->gnb_payload16_ctx->udata =channel; 115 | 116 | channel->keepalive_ts_sec = service->now_time_sec; 117 | 118 | uot_channel_t *pop_channel; 119 | 120 | pop_channel = GNB_LRU32_UINT32_PUT(service_ctx->channel_lru, channel->tcp_conn->fd, (void *)channel); 121 | 122 | if ( NULL != pop_channel ) { 123 | 124 | gnb_connection_close(service, pop_channel->tcp_conn); 125 | gnb_connection_close(service, pop_channel->udp_conn); 126 | 127 | gnb_connection_release(service, pop_channel->udp_conn); 128 | gnb_connection_release(service, pop_channel->tcp_conn); 129 | 130 | gnb_heap_free(service->heap, pop_channel); 131 | gnb_heap_free(service->heap, pop_channel); 132 | 133 | } 134 | 135 | return 0; 136 | 137 | } 138 | 139 | 140 | static void handle_udp(gnb_network_service_t *service, uot_channel_t *channel){ 141 | 142 | gnb_connection_t *udp_conn = channel->udp_conn; 143 | gnb_connection_t *tcp_conn = channel->tcp_conn; 144 | 145 | int recv_len; 146 | 147 | recv_len = (GNB_BUF_LEN(udp_conn->recv_zbuf)); 148 | 149 | if ( recv_len > GNB_BUF_SIZE(tcp_conn->send_zbuf) ) { 150 | 151 | GNB_BUF_RESET(udp_conn->recv_zbuf); 152 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "tcp side send buffer is small conn[%s]\n", GNB_SOCKETADDRSTR1(&tcp_conn->remote_sockaddress)); 153 | return; 154 | 155 | } 156 | 157 | if ( recv_len > GNB_BUF_REMAIN(tcp_conn->send_zbuf) ) { 158 | 159 | GNB_BUF_RESET(udp_conn->recv_zbuf); 160 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "tcp side tcp buffer is FULL! conn[%s]\n", GNB_SOCKETADDRSTR1(&tcp_conn->remote_sockaddress)); 161 | goto finish; 162 | 163 | } 164 | 165 | gnb_payload16_t *payload16; 166 | 167 | payload16 = (gnb_payload16_t *)tcp_conn->send_zbuf->las; 168 | 169 | gnb_payload16_set_data_len(payload16,recv_len); 170 | 171 | payload16->type = GNB_PAYLOAD_TYPE_UDP_OVER_TCP; 172 | 173 | memcpy(payload16->data, udp_conn->recv_zbuf->pos, recv_len); 174 | 175 | tcp_conn->send_zbuf->las += gnb_payload16_size(payload16); 176 | 177 | finish: 178 | 179 | GNB_BUF_RESET(udp_conn->recv_zbuf); 180 | 181 | GNB_SERVICE_NOTIFY_SEND(service, tcp_conn); 182 | 183 | } 184 | 185 | 186 | static void handle_keepalive(gnb_payload16_t *payload16, uot_channel_t *channel){ 187 | 188 | gnb_connection_t *udp_conn = channel->udp_conn; 189 | gnb_network_service_t *service = channel->service; 190 | 191 | channel->keepalive_ts_sec = service->now_time_sec; 192 | 193 | send_keepalive_echo_frame(service, channel->tcp_conn); 194 | 195 | } 196 | 197 | 198 | static void tcp_to_udp(gnb_payload16_t *payload16, uot_channel_t *channel){ 199 | 200 | gnb_connection_t *tcp_conn = channel->tcp_conn; 201 | gnb_connection_t *udp_conn = channel->udp_conn; 202 | 203 | gnb_network_service_t *service = (gnb_network_service_t *)channel->service; 204 | 205 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 206 | 207 | uint32_t payload_size = gnb_payload16_size(payload16); 208 | uint32_t payload_data_len = gnb_payload16_data_len(payload16); 209 | 210 | GNB_BUF_RESET(udp_conn->send_zbuf); 211 | 212 | if ( payload_size > GNB_BUF_REMAIN(udp_conn->send_zbuf) ) { 213 | //Drop the udp payload 214 | return; 215 | } 216 | 217 | memcpy(udp_conn->send_zbuf->pos, payload16->data, gnb_payload16_data_len(payload16)); 218 | 219 | udp_conn->send_zbuf->las += gnb_payload16_data_len(payload16); 220 | 221 | ssize_t n_send = gnb_network_service_udp_send(service, udp_conn); 222 | 223 | if ( -1 == n_send ) { 224 | GNB_SERVICE_NOTIFY_SEND(service, udp_conn); 225 | } 226 | 227 | if ( n_send > 0 ) { 228 | GNB_BUF_RESET(udp_conn->send_zbuf); 229 | } 230 | 231 | return ; 232 | 233 | } 234 | 235 | 236 | static int payload16_handle_callback(gnb_payload16_t *payload16, void *ctx) { 237 | 238 | uot_channel_t *channel = (uot_channel_t *)ctx; 239 | 240 | switch ( payload16->type ) { 241 | 242 | case GNB_PAYLOAD_TYPE_UDP_OVER_TCP: 243 | tcp_to_udp(payload16, channel); 244 | break; 245 | 246 | case GNB_PAYLOAD_TYPE_TCP_KEEPALIVE: 247 | handle_keepalive(payload16, channel); 248 | break; 249 | 250 | default: 251 | break; 252 | } 253 | 254 | return 0; 255 | 256 | } 257 | 258 | 259 | static void handle_tcp(gnb_network_service_t *service, uot_channel_t *channel){ 260 | 261 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 262 | 263 | gnb_connection_t *tcp_conn = channel->tcp_conn; 264 | gnb_connection_t *udp_conn = channel->udp_conn; 265 | 266 | int recv_len; 267 | int ret; 268 | 269 | recv_len = (GNB_BUF_LEN(tcp_conn->recv_zbuf)); 270 | 271 | ret = gnb_payload16_handle(tcp_conn->recv_zbuf->pos, recv_len, channel->gnb_payload16_ctx, payload16_handle_callback); 272 | 273 | if ( ret < 0 ) { 274 | tcp_conn->status = TCP_CONNECT_FINISH; 275 | return; 276 | } 277 | 278 | GNB_BUF_RESET(tcp_conn->recv_zbuf); 279 | 280 | channel->keepalive_ts_sec = service->now_time_sec; 281 | 282 | } 283 | 284 | 285 | static int service_recv_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 286 | 287 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 288 | 289 | uot_channel_t *channel = NULL; 290 | 291 | int recv_len; 292 | 293 | channel = (uot_channel_t *)conn->udata; 294 | 295 | if ( NULL==channel ) { 296 | return 0; 297 | } 298 | 299 | if ( GNB_EVENT_FD_UDP4_SOCKET == conn->event->fd_type ) { 300 | handle_udp(service, channel); 301 | goto finish; 302 | } 303 | 304 | if ( GNB_EVENT_FD_TCPV4_CONNECT == conn->event->fd_type ) { 305 | handle_tcp(service, channel); 306 | goto finish; 307 | } 308 | 309 | finish: 310 | 311 | GNB_LOG2(service->log, GNB_LOG_ID_UOT,"send=%lu total=%lu \n", conn->n_recv, conn->n_recv_total); 312 | 313 | return 0; 314 | 315 | } 316 | 317 | 318 | static int service_send_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 319 | 320 | GNB_BUF_RESET(conn->send_zbuf); 321 | GNB_LOG2(service->log, GNB_LOG_ID_UOT,"send=%lu total=%lu \n", conn->n_send, conn->n_send_total); 322 | 323 | return 0; 324 | 325 | } 326 | 327 | 328 | static int service_close_cb(gnb_network_service_t *service, gnb_connection_t *conn){ 329 | 330 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 331 | 332 | uot_channel_t *channel = NULL; 333 | 334 | channel = (uot_channel_t *)conn->udata; 335 | 336 | GNB_LRU32_UINT32_POP_BY_KEY(service_ctx->channel_lru, conn->fd); 337 | 338 | gnb_connection_close(service, channel->udp_conn); 339 | 340 | gnb_connection_release(service, channel->udp_conn); 341 | gnb_connection_release(service, conn); 342 | 343 | free(channel->gnb_payload16_ctx); 344 | 345 | gnb_heap_free(service->heap, channel); 346 | 347 | return 0; 348 | 349 | } 350 | 351 | 352 | static int service_idle_cb(gnb_network_service_t *service){ 353 | 354 | uint64_t keepalive_timeout_sec; 355 | 356 | uot_tcp_service_ctx_t *service_ctx = (uot_tcp_service_ctx_t *)service->ctx; 357 | 358 | uot_channel_t *tail_channel = (uot_channel_t *)gnb_lru32_get_tail(service_ctx->channel_lru); 359 | 360 | if ( NULL == tail_channel ) { 361 | return 0; 362 | } 363 | 364 | keepalive_timeout_sec = service->now_time_sec - tail_channel->keepalive_ts_sec; 365 | 366 | GNB_LOG2(service->log, GNB_LOG_ID_UOT, "keepalive_timeout_sec=%d/%d\n", keepalive_timeout_sec, GNB_UOT_KEEPALIVE_TIMEOUT_SEC); 367 | 368 | if ( keepalive_timeout_sec > GNB_UOT_KEEPALIVE_TIMEOUT_SEC ) { 369 | 370 | GNB_LOG1(service->log, GNB_LOG_ID_UOT, "connection %s time out sec=%d\n", GNB_SOCKETADDRSTR1(&tail_channel->tcp_conn->remote_sockaddress), keepalive_timeout_sec); 371 | 372 | tail_channel = (uot_channel_t *)gnb_lru32_pop_tail(service_ctx->channel_lru); 373 | 374 | gnb_connection_close(service, tail_channel->tcp_conn); 375 | gnb_connection_close(service, tail_channel->udp_conn); 376 | 377 | gnb_connection_release(service, tail_channel->udp_conn); 378 | gnb_connection_release(service, tail_channel->tcp_conn); 379 | 380 | gnb_heap_free(service->heap, tail_channel); 381 | 382 | } 383 | 384 | return 0; 385 | 386 | } 387 | 388 | 389 | gnb_network_service_t uot_tcp_service_mod = { 390 | 391 | .recv_zbuf_size = (1024 *128), 392 | .send_zbuf_size = (1024 *128), 393 | 394 | .event_cmd = NULL, 395 | 396 | .conn_array = NULL, 397 | 398 | .init_cb = service_init_cb, 399 | .listen_cb = service_listen_cb, 400 | .accept_cb = service_accept_cb, 401 | .connect_cb = NULL, 402 | .recv_cb = service_recv_cb, 403 | .send_cb = service_send_cb, 404 | .close_cb = service_close_cb, 405 | .idle_cb = service_idle_cb, 406 | 407 | .ctx = NULL 408 | 409 | }; 410 | -------------------------------------------------------------------------------- /src/gnb_address.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gnb_platform.h" 24 | 25 | #ifdef __UNIX_LIKE_OS__ 26 | #include 27 | #include 28 | #endif 29 | 30 | #ifdef _WIN32 31 | 32 | #undef _WIN32_WINNT 33 | #define _WIN32_WINNT 0x0600 34 | 35 | #include 36 | #include 37 | 38 | #define _POSIX 39 | #define __USE_MINGW_ALARM 40 | #endif 41 | 42 | 43 | #include "gnb_address.h" 44 | 45 | uint8_t gnb_addr_secure = 0; 46 | 47 | unsigned long long gnb_htonll(unsigned long long val){ 48 | 49 | #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ 50 | uint64_t rv= 0; 51 | uint8_t x= 0; 52 | for(x= 0; x < 8; x++){ 53 | rv= (rv << 8) | (val & 0xff); 54 | val >>= 8; 55 | } 56 | return rv; 57 | #endif 58 | 59 | #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ 60 | return val; 61 | #endif 62 | 63 | } 64 | 65 | 66 | unsigned long long gnb_ntohll(unsigned long long val){ 67 | 68 | #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ 69 | uint64_t rv= 0; 70 | uint8_t x= 0; 71 | for(x= 0; x < 8; x++){ 72 | rv= (rv << 8) | (val & 0xff); 73 | val >>= 8; 74 | } 75 | return rv; 76 | #endif 77 | 78 | #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ 79 | return val; 80 | #endif 81 | 82 | } 83 | 84 | 85 | char get_netmask_class(uint32_t addr4){ 86 | 87 | if ( !(~(IN_CLASSA_NET) & ntohl(addr4)) ){ 88 | return 'a'; 89 | } 90 | 91 | if ( !(~(IN_CLASSB_NET) & ntohl(addr4)) ){ 92 | return 'b'; 93 | } 94 | 95 | if ( !(~(IN_CLASSC_NET) & ntohl(addr4)) ){ 96 | return 'c'; 97 | } 98 | 99 | return 'n'; 100 | 101 | } 102 | 103 | 104 | gnb_address_list_t* gnb_create_address_list(size_t size){ 105 | 106 | gnb_address_list_t *address_list; 107 | 108 | address_list = (gnb_address_list_t *)malloc( sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*size ); 109 | 110 | memset(address_list, 0, sizeof(gnb_address_list_t) + sizeof(gnb_address_t)*size); 111 | 112 | address_list->size = size; 113 | address_list->num = 0; 114 | 115 | return address_list; 116 | 117 | } 118 | 119 | void gnb_address_list_release(gnb_address_list_t *address_list){ 120 | free(address_list); 121 | } 122 | 123 | 124 | int gnb_address_list_find(gnb_address_list_t *address_list, gnb_address_t *address) { 125 | 126 | int i; 127 | 128 | for ( i=0; i < address_list->num; i++ ) { 129 | 130 | if ( address->type != address_list->array[i].type ){ 131 | continue; 132 | } 133 | 134 | if ( AF_INET == address->type && 0 == memcmp(address_list->array[i].m_address4, address->m_address4, 4) ){ 135 | return i; 136 | } 137 | 138 | if ( AF_INET6 == address->type && 0 == memcmp(address_list->array[i].m_address6, address->m_address6, 16)){ 139 | return i; 140 | } 141 | 142 | } 143 | 144 | return -1; 145 | } 146 | 147 | 148 | int gnb_address_list_get_free_idx(gnb_address_list_t *address_list) { 149 | 150 | int free_idx = 0; 151 | 152 | uint64_t min_ts_sec = address_list->array[free_idx].ts_sec; 153 | 154 | int i; 155 | 156 | for ( i=0; i < address_list->size; i++ ) { 157 | 158 | if ( 0 == address_list->array[i].port ){ 159 | free_idx = i; 160 | break; 161 | } 162 | 163 | if ( address_list->array[i].ts_sec <= min_ts_sec ) { 164 | min_ts_sec = address_list->array[i].ts_sec; 165 | free_idx = i; 166 | } 167 | 168 | } 169 | 170 | return free_idx; 171 | 172 | } 173 | 174 | 175 | void gnb_address_list_update(gnb_address_list_t *address_list, gnb_address_t *address){ 176 | 177 | int idx = 0; 178 | 179 | idx = gnb_address_list_find(address_list, address); 180 | 181 | if ( -1 != idx ){ 182 | goto finish; 183 | } 184 | 185 | idx = gnb_address_list_get_free_idx(address_list); 186 | 187 | finish: 188 | 189 | if ( 0 == address_list->array[idx].port ){ 190 | 191 | if( address_list->num < address_list->size ){ 192 | address_list->num += 1; 193 | }else if(address_list->num > address_list->size){ 194 | address_list->num = address_list->size; 195 | } 196 | 197 | } 198 | 199 | memcpy( &address_list->array[idx], address, sizeof(gnb_address_t) ); 200 | 201 | } 202 | 203 | 204 | void gnb_set_address4(gnb_address_t *address, struct sockaddr_in *in){ 205 | 206 | address->type = AF_INET; 207 | 208 | address->port = in->sin_port; 209 | 210 | memcpy(&address->address.addr4, &in->sin_addr.s_addr ,sizeof(struct in_addr)); 211 | 212 | } 213 | 214 | 215 | void gnb_set_address6(gnb_address_t *address, struct sockaddr_in6 *in6){ 216 | 217 | address->type = AF_INET6; 218 | address->port = in6->sin6_port; 219 | memcpy(&address->address.addr6, &in6->sin6_addr ,sizeof(struct in6_addr)); 220 | 221 | } 222 | 223 | 224 | char * gnb_get_address4string(void *byte4, char *dest, uint8_t addr_secure){ 225 | 226 | inet_ntop(AF_INET, byte4, dest, INET_ADDRSTRLEN); 227 | 228 | char *p; 229 | 230 | if(addr_secure){ 231 | 232 | p = dest; 233 | 234 | while( '\0' != *p ){ 235 | 236 | if( '.' == *p ){ 237 | break; 238 | } 239 | 240 | *p = '*'; 241 | 242 | p++; 243 | 244 | } 245 | 246 | } 247 | 248 | return dest; 249 | } 250 | 251 | 252 | char * gnb_get_address6string(void *byte16, char *dest, uint8_t addr_secure){ 253 | 254 | inet_ntop(AF_INET6, byte16, dest, INET6_ADDRSTRLEN); 255 | 256 | char *p; 257 | 258 | if(addr_secure){ 259 | 260 | p = dest; 261 | 262 | while( '\0' != *p ){ 263 | 264 | if( ':' == *p ){ 265 | break; 266 | } 267 | 268 | *p = '*'; 269 | 270 | p++; 271 | 272 | } 273 | 274 | } 275 | 276 | return dest; 277 | } 278 | 279 | 280 | char * gnb_get_socket4string(struct sockaddr_in *in, char *dest, uint8_t addr_secure){ 281 | 282 | char buf[INET_ADDRSTRLEN]; 283 | inet_ntop(AF_INET, &in->sin_addr, buf, INET_ADDRSTRLEN); 284 | snprintf(dest, GNB_IP4_PORT_STRING_SIZE,"%s:%d",buf,ntohs(in->sin_port)); 285 | 286 | char *p; 287 | 288 | if(addr_secure){ 289 | 290 | p = dest; 291 | 292 | while( '\0' != *p ){ 293 | 294 | if( '.' == *p ){ 295 | break; 296 | } 297 | 298 | *p = '*'; 299 | 300 | p++; 301 | 302 | } 303 | 304 | } 305 | 306 | return dest; 307 | } 308 | 309 | 310 | char * gnb_get_socket6string(struct sockaddr_in6 *in6, char *dest, uint8_t addr_secure){ 311 | 312 | char buf[INET6_ADDRSTRLEN]; 313 | inet_ntop(AF_INET6, &in6->sin6_addr, buf, INET6_ADDRSTRLEN); 314 | snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"[%s:%d]",buf,ntohs(in6->sin6_port)); 315 | 316 | char *p; 317 | 318 | if(addr_secure){ 319 | 320 | p = dest+1; 321 | 322 | while( '\0' != *p ){ 323 | 324 | if( ':' == *p ){ 325 | break; 326 | } 327 | 328 | *p = '*'; 329 | 330 | p++; 331 | 332 | } 333 | 334 | } 335 | 336 | return dest; 337 | } 338 | 339 | 340 | char * gnb_get_sockaddress_string(gnb_sockaddress_t *sockaddress, char *dest, uint8_t addr_secure){ 341 | 342 | if ( AF_INET6 == sockaddress->addr_type ){ 343 | dest = gnb_get_socket6string(&sockaddress->addr.in6,dest,addr_secure); 344 | }else if ( AF_INET == sockaddress->addr_type ){ 345 | dest = gnb_get_socket4string(&sockaddress->addr.in,dest,addr_secure); 346 | } 347 | 348 | return dest; 349 | 350 | } 351 | 352 | 353 | char * gnb_get_ip_port_string(gnb_address_t *address, char *dest, uint8_t addr_secure){ 354 | 355 | char buf[INET6_ADDRSTRLEN]; 356 | 357 | char *p; 358 | 359 | p = dest; 360 | 361 | if ( AF_INET6 == address->type ){ 362 | inet_ntop(AF_INET6, &address->address.addr6, buf, INET6_ADDRSTRLEN); 363 | snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"[%s:%d]",buf,ntohs(address->port)); 364 | p++; 365 | }else if( AF_INET == address->type ){ 366 | inet_ntop(AF_INET, &address->address.addr4, buf, INET_ADDRSTRLEN); 367 | snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"%s:%d",buf,ntohs(address->port)); 368 | }else{ 369 | snprintf(dest, GNB_IP6_PORT_STRING_SIZE,"NONE_ADDRESS"); 370 | } 371 | 372 | if(addr_secure){ 373 | 374 | while( '\0' != *p ){ 375 | 376 | if( '.' == *p || ':' == *p ){ 377 | break; 378 | } 379 | 380 | *p = '*'; 381 | 382 | p++; 383 | 384 | } 385 | 386 | } 387 | 388 | return dest; 389 | } 390 | 391 | 392 | int gnb_cmp_sockaddr_in6(struct sockaddr_in6 *in1, struct sockaddr_in6 *in2){ 393 | 394 | if ( in1->sin6_port != in2->sin6_port ){ 395 | return 1; 396 | } 397 | 398 | if ( 0 != memcmp( &in1->sin6_addr, &in2->sin6_addr, 16) ){ 399 | return 2; 400 | } 401 | 402 | return 0; 403 | 404 | } 405 | 406 | 407 | int gnb_cmp_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2){ 408 | 409 | if ( in1->sin_port != in2->sin_port ){ 410 | return 1; 411 | } 412 | 413 | if ( in1->sin_addr.s_addr != in2->sin_addr.s_addr ){ 414 | return 2; 415 | } 416 | 417 | return 0; 418 | 419 | } 420 | 421 | 422 | void gnb_set_sockaddress4(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port){ 423 | 424 | sockaddress->addr_type = AF_INET; 425 | 426 | if (GNB_PROTOCOL_TCP == protocol){ 427 | sockaddress->protocol = SOCK_STREAM; 428 | }else if (GNB_PROTOCOL_UDP == protocol){ 429 | sockaddress->protocol = SOCK_DGRAM; 430 | }else{ 431 | sockaddress->protocol = SOCK_DGRAM; 432 | } 433 | 434 | memset(&sockaddress->m_in4,0, sizeof(struct sockaddr_in)); 435 | 436 | sockaddress->m_in4.sin_family = AF_INET; 437 | 438 | if ( NULL != host ){ 439 | inet_pton(AF_INET, host, (struct in_addr *)&sockaddress->m_in4.sin_addr.s_addr); 440 | }else{ 441 | sockaddress->m_in4.sin_addr.s_addr = htonl(INADDR_ANY); 442 | } 443 | 444 | sockaddress->m_in4.sin_port = htons(port); 445 | 446 | sockaddress->socklen = sizeof(struct sockaddr_in); 447 | 448 | } 449 | 450 | 451 | void gnb_set_sockaddress6(gnb_sockaddress_t *sockaddress, int protocol, const char *host, int port){ 452 | 453 | sockaddress->addr_type = AF_INET6; 454 | 455 | if (GNB_PROTOCOL_TCP == protocol){ 456 | sockaddress->protocol = SOCK_STREAM; 457 | }else if (GNB_PROTOCOL_UDP == protocol){ 458 | sockaddress->protocol = SOCK_DGRAM; 459 | }else{ 460 | sockaddress->protocol = SOCK_DGRAM; 461 | } 462 | 463 | memset(&sockaddress->m_in6,0, sizeof(struct sockaddr_in6)); 464 | 465 | sockaddress->m_in6.sin6_family = AF_INET6; 466 | 467 | if ( NULL != host ){ 468 | inet_pton( AF_INET6, host, &sockaddress->m_in6.sin6_addr); 469 | }else{ 470 | sockaddress->m_in6.sin6_addr = in6addr_any; 471 | } 472 | 473 | sockaddress->m_in6.sin6_port = htons(port); 474 | 475 | sockaddress->socklen = sizeof(struct sockaddr_in6); 476 | 477 | } 478 | 479 | 480 | gnb_address_t gnb_get_address4_from_string(const char *sockaddress4_string){ 481 | 482 | gnb_address_t address; 483 | 484 | memset(&address,0,sizeof(gnb_address_t)); 485 | 486 | unsigned long int ul; 487 | 488 | char sockaddress4_string_copy[16]; 489 | 490 | int sockaddress4_string_len = strlen(sockaddress4_string); 491 | 492 | memcpy(sockaddress4_string_copy, sockaddress4_string, sockaddress4_string_len); 493 | 494 | int i; 495 | 496 | char *p = sockaddress4_string_copy; 497 | 498 | for( i=0; iarray[0], address, sizeof(gnb_address_t) ); 555 | address_list->num = 1; 556 | 557 | } 558 | -------------------------------------------------------------------------------- /src/gnb_hash32.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) gnbdev 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include "gnb_hash32.h" 21 | 22 | 23 | typedef struct _gnb_hash32_bucket_t{ 24 | uint32_t chain_len; 25 | gnb_kv32_t *kv_chain; 26 | }gnb_hash32_bucket_t; 27 | 28 | 29 | uint32_t murmurhash_hash(unsigned char *data, size_t len); 30 | 31 | 32 | gnb_hash32_map_t *gnb_hash32_create(gnb_heap_t *heap, uint32_t bucket_num, uint32_t kv_num){ 33 | 34 | gnb_hash32_map_t *hash32_map = gnb_heap_alloc(heap, sizeof(gnb_hash32_map_t)); 35 | 36 | if ( NULL == hash32_map ) { 37 | return NULL; 38 | } 39 | 40 | memset(hash32_map, 0, sizeof(gnb_hash32_map_t)); 41 | 42 | hash32_map->heap = heap; 43 | 44 | hash32_map->buckets = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_hash32_bucket_t *) * bucket_num ); 45 | 46 | if ( NULL == hash32_map->buckets ) { 47 | return NULL; 48 | } 49 | 50 | hash32_map->bucket_num = bucket_num; 51 | 52 | uint32_t i; 53 | 54 | void *p = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_hash32_bucket_t)*bucket_num ); 55 | 56 | if ( NULL == p ) { 57 | return NULL; 58 | } 59 | 60 | memset(p, 0, sizeof(gnb_hash32_bucket_t)*bucket_num); 61 | 62 | for ( i=0; ibuckets[i] = p; 64 | p += sizeof(gnb_hash32_bucket_t); 65 | } 66 | 67 | return hash32_map; 68 | 69 | } 70 | 71 | 72 | void gnb_hash32_release(gnb_hash32_map_t *hash32_map){ 73 | gnb_heap_free(hash32_map->heap, hash32_map); 74 | } 75 | 76 | 77 | gnb_kv32_t *gnb_kv32_create(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, u_char *value, uint32_t value_len){ 78 | 79 | uint32_t r_key_len; 80 | uint32_t r_value_len; 81 | 82 | if ( 0 != key_len ) { 83 | r_key_len = key_len; 84 | }else{ 85 | r_key_len = sizeof(void *); 86 | } 87 | 88 | if ( 0 != value_len ) { 89 | r_value_len = value_len; 90 | }else{ 91 | r_value_len = sizeof(void *); 92 | } 93 | 94 | gnb_kv32_t *kv = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_kv32_t) + sizeof(gnb_block32_t) + r_key_len + sizeof(gnb_block32_t) + r_value_len ); 95 | 96 | if ( NULL == kv ) { 97 | return NULL; 98 | } 99 | 100 | void *p = (void *)kv; 101 | kv->key = p + sizeof(gnb_kv32_t); 102 | kv->value = p + sizeof(gnb_kv32_t) + sizeof(gnb_block32_t) + key_len; 103 | kv->nex = NULL; 104 | 105 | memcpy(kv->key->data, key, key_len); 106 | kv->key->size = key_len; 107 | 108 | if ( 0 != value_len ){ 109 | memcpy(kv->value->data, value, value_len); 110 | kv->value->size = value_len; 111 | } else { 112 | //直接存 void* 113 | GNB_BLOCK_VOID(kv->value) = value; 114 | kv->value->size = 0; 115 | } 116 | 117 | return kv; 118 | } 119 | 120 | 121 | void gnb_kv32_release(gnb_hash32_map_t *hash_map, gnb_kv32_t *kv){ 122 | 123 | gnb_heap_free(hash_map->heap, kv); 124 | 125 | } 126 | 127 | 128 | gnb_kv32_t *gnb_hash32_set(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len){ 129 | 130 | gnb_kv32_t *kv = NULL; 131 | 132 | uint32_t hashcode = murmurhash_hash(key, key_len); 133 | 134 | uint32_t bucket_idx = hashcode % hash32_map->bucket_num; 135 | 136 | gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; 137 | 138 | if ( NULL == bucket->kv_chain ){ 139 | bucket->kv_chain = gnb_kv32_create(hash32_map, key, key_len, value, value_len); 140 | bucket->kv_chain->nex = NULL; 141 | bucket->chain_len = 1; 142 | hash32_map->kv_num++; 143 | goto finish; 144 | } 145 | 146 | gnb_kv32_t *kv_chain = bucket->kv_chain; 147 | gnb_kv32_t *pre_kv_chain = kv_chain; 148 | 149 | do{ 150 | 151 | if ( key_len != kv_chain->key->size ) { 152 | pre_kv_chain = kv_chain; 153 | kv_chain = kv_chain->nex; 154 | continue; 155 | } 156 | 157 | if ( !memcmp(kv_chain->key->data, key, key_len) ) { 158 | 159 | kv = kv_chain; 160 | 161 | if ( 0 != value_len ){ 162 | memcpy(kv->value->data, value, value_len); 163 | kv->value->size = value_len; 164 | } else { 165 | //直接存 void* 166 | GNB_BLOCK_VOID(kv->value) = value; 167 | kv->value->size = 0; 168 | } 169 | 170 | break; 171 | 172 | } 173 | 174 | pre_kv_chain = kv_chain; 175 | kv_chain = kv_chain->nex; 176 | 177 | }while (kv_chain); 178 | 179 | if ( NULL == kv ){ 180 | pre_kv_chain->nex = gnb_kv32_create(hash32_map, key, key_len, value, value_len); 181 | bucket->chain_len++; 182 | hash32_map->kv_num++; 183 | goto finish; 184 | } 185 | 186 | finish: 187 | 188 | return kv; 189 | 190 | } 191 | 192 | 193 | int gnb_hash32_store(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len, void *value, uint32_t value_len){ 194 | 195 | gnb_kv32_t *kv = NULL; 196 | 197 | uint32_t hashcode = murmurhash_hash(key, key_len); 198 | 199 | uint32_t bucket_idx = hashcode % hash32_map->bucket_num; 200 | 201 | gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; 202 | 203 | if ( NULL == bucket->kv_chain ){ 204 | bucket->kv_chain = gnb_kv32_create(hash32_map, key, key_len, value, value_len); 205 | bucket->chain_len = 1; 206 | hash32_map->kv_num++; 207 | goto finish; 208 | } 209 | 210 | gnb_kv32_t *kv_chain = bucket->kv_chain; 211 | gnb_kv32_t *pre_kv_chain = kv_chain; 212 | 213 | do{ 214 | 215 | if ( key_len != kv_chain->key->size ) { 216 | pre_kv_chain = kv_chain; 217 | kv_chain = kv_chain->nex; 218 | continue; 219 | } 220 | 221 | if ( !memcmp(kv_chain->key->data, key, key_len) ) { 222 | 223 | gnb_kv32_release(hash32_map, kv_chain); 224 | 225 | if ( bucket->kv_chain != kv_chain ) { 226 | 227 | pre_kv_chain->nex = gnb_kv32_create(hash32_map, key, key_len, value, value_len); 228 | 229 | } else { 230 | 231 | bucket->kv_chain = gnb_kv32_create(hash32_map, key, key_len, value, value_len); 232 | } 233 | 234 | break; 235 | } 236 | 237 | pre_kv_chain = kv_chain; 238 | kv_chain = kv_chain->nex; 239 | 240 | }while (kv_chain); 241 | 242 | if ( NULL == kv ){ 243 | pre_kv_chain->nex = gnb_kv32_create(hash32_map, key, key_len, value, value_len); 244 | bucket->chain_len++; 245 | hash32_map->kv_num++; 246 | goto finish; 247 | } 248 | 249 | finish: 250 | 251 | return 0; 252 | 253 | } 254 | 255 | 256 | gnb_kv32_t *gnb_hash32_get(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len){ 257 | 258 | gnb_kv32_t *kv = NULL; 259 | 260 | uint32_t hashcode = murmurhash_hash(key, key_len); 261 | 262 | uint32_t bucket_idx = hashcode % hash32_map->bucket_num; 263 | 264 | gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; 265 | 266 | if ( NULL == bucket->kv_chain ){ 267 | goto finish; 268 | } 269 | 270 | gnb_kv32_t *kv_chain = bucket->kv_chain; 271 | 272 | do{ 273 | 274 | if ( key_len != kv_chain->key->size ) { 275 | kv_chain = kv_chain->nex; 276 | continue; 277 | } 278 | 279 | if ( !memcmp(kv_chain->key->data, key, key_len) ) { 280 | kv = kv_chain; 281 | break; 282 | } 283 | 284 | kv_chain = kv_chain->nex; 285 | 286 | }while (kv_chain); 287 | 288 | finish: 289 | 290 | return kv; 291 | 292 | } 293 | 294 | 295 | gnb_kv32_t *gnb_hash32_del(gnb_hash32_map_t *hash32_map, u_char *key, uint32_t key_len){ 296 | 297 | gnb_kv32_t *old_kv = NULL; 298 | 299 | uint32_t hashcode = murmurhash_hash(key, key_len); 300 | 301 | uint32_t bucket_idx = hashcode % hash32_map->bucket_num; 302 | 303 | gnb_hash32_bucket_t *bucket = hash32_map->buckets[bucket_idx]; 304 | 305 | if ( NULL == bucket->kv_chain ){ 306 | goto finish; 307 | } 308 | 309 | gnb_kv32_t *kv_chain = bucket->kv_chain; 310 | 311 | if ( !memcmp(kv_chain->key->data, key, key_len) ) { 312 | 313 | old_kv = kv_chain; 314 | 315 | hash32_map->kv_num--; 316 | 317 | if ( 1 == bucket->chain_len ){ 318 | bucket->kv_chain = NULL; 319 | bucket->chain_len = 0; 320 | }else{ 321 | bucket->kv_chain = kv_chain->nex; 322 | bucket->chain_len--; 323 | } 324 | goto finish; 325 | 326 | } 327 | 328 | gnb_kv32_t *pre_kv_chain = kv_chain; 329 | 330 | kv_chain = kv_chain->nex; 331 | 332 | if ( NULL == kv_chain ) { 333 | goto finish; 334 | } 335 | 336 | do{ 337 | 338 | if ( key_len != kv_chain->key->size ) { 339 | pre_kv_chain = kv_chain; 340 | kv_chain = kv_chain->nex; 341 | continue; 342 | } 343 | 344 | if ( !memcmp(kv_chain->key->data, key, key_len) ) { 345 | pre_kv_chain->nex = kv_chain->nex; 346 | old_kv = kv_chain; 347 | bucket->chain_len--; 348 | hash32_map->kv_num--; 349 | break; 350 | } 351 | 352 | pre_kv_chain = kv_chain; 353 | kv_chain = kv_chain->nex; 354 | 355 | }while (kv_chain); 356 | 357 | finish: 358 | 359 | return old_kv; 360 | 361 | } 362 | 363 | 364 | gnb_kv32_t **gnb_hash32_array(gnb_hash32_map_t *hash32_map, uint32_t *num){ 365 | 366 | gnb_kv32_t *kv; 367 | 368 | gnb_kv32_t ** kv_array = NULL; 369 | 370 | gnb_hash32_bucket_t *bucket; 371 | 372 | if ( 0 == hash32_map->kv_num ){ 373 | *num = 0; 374 | return NULL; 375 | } 376 | 377 | if ( hash32_map->kv_num < (*num) ){ 378 | *num = hash32_map->kv_num; 379 | } 380 | 381 | kv_array = gnb_heap_alloc(hash32_map->heap, sizeof(gnb_kv32_t *) * (*num) ); 382 | 383 | uint32_t i,j; 384 | uint32_t idx = 0; 385 | 386 | for (i=0; ibucket_num; i++) { 387 | 388 | bucket = hash32_map->buckets[i]; 389 | 390 | if ( 0 == bucket->chain_len ) { 391 | continue; 392 | } 393 | 394 | kv = bucket->kv_chain; 395 | 396 | for (j=0; jchain_len; j++) { 397 | kv_array[idx] = kv; 398 | idx++; 399 | kv = kv->nex; 400 | } 401 | 402 | } 403 | 404 | return kv_array; 405 | 406 | } 407 | 408 | 409 | uint32_t* gnb_hash32_uint32_keys(gnb_hash32_map_t *hash32_map, uint32_t *num){ 410 | 411 | gnb_kv32_t *kv; 412 | 413 | uint32_t *uint32_array = NULL; 414 | 415 | gnb_hash32_bucket_t *bucket; 416 | 417 | if ( 0 == hash32_map->kv_num ){ 418 | *num = 0; 419 | return NULL; 420 | } 421 | 422 | if ( hash32_map->kv_num < (*num) ){ 423 | *num = hash32_map->kv_num; 424 | } 425 | 426 | uint32_array = gnb_heap_alloc(hash32_map->heap, sizeof(uint32_t) * (*num) ); 427 | 428 | uint32_t i,j; 429 | uint32_t idx = 0; 430 | 431 | for (i=0; ibucket_num; i++) { 432 | 433 | bucket = hash32_map->buckets[i]; 434 | 435 | if ( 0 == bucket->chain_len ) { 436 | continue; 437 | } 438 | 439 | kv = bucket->kv_chain; 440 | 441 | for (j=0; jchain_len; j++) { 442 | uint32_array[idx] = GNB_HASH32_UINT32_KEY(kv); 443 | idx++; 444 | kv = kv->nex; 445 | } 446 | 447 | } 448 | 449 | return uint32_array; 450 | 451 | } 452 | 453 | 454 | uint64_t* gnb_hash32_uint64_keys(gnb_hash32_map_t *hash32_map, uint32_t *num){ 455 | 456 | gnb_kv32_t *kv; 457 | uint64_t *uint64_array = NULL; 458 | 459 | gnb_hash32_bucket_t *bucket; 460 | 461 | if ( 0 == hash32_map->kv_num ){ 462 | *num = 0; 463 | return NULL; 464 | } 465 | 466 | if ( hash32_map->kv_num < (*num) ){ 467 | *num = hash32_map->kv_num; 468 | } 469 | 470 | uint64_array = gnb_heap_alloc(hash32_map->heap, sizeof(uint64_t) * (*num) ); 471 | 472 | uint32_t i,j; 473 | uint32_t idx = 0; 474 | 475 | for (i=0; ibucket_num; i++) { 476 | 477 | bucket = hash32_map->buckets[i]; 478 | 479 | if ( 0 == bucket->chain_len ) { 480 | continue; 481 | } 482 | 483 | kv = bucket->kv_chain; 484 | 485 | for (j=0; jchain_len; j++) { 486 | uint64_array[idx] = GNB_HASH32_UINT64_KEY(kv); 487 | idx++; 488 | kv = kv->nex; 489 | } 490 | 491 | } 492 | 493 | return uint64_array; 494 | 495 | } 496 | 497 | 498 | u_char** gnb_hash32_string_keys(gnb_hash32_map_t *hash32_map, uint32_t *num){ 499 | 500 | gnb_kv32_t *kv; 501 | u_char** string_array = NULL; 502 | 503 | gnb_hash32_bucket_t *bucket; 504 | 505 | if ( 0 == hash32_map->kv_num ){ 506 | *num = 0; 507 | return NULL; 508 | } 509 | 510 | if ( hash32_map->kv_num < (*num) ){ 511 | *num = hash32_map->kv_num; 512 | } 513 | 514 | string_array = gnb_heap_alloc(hash32_map->heap, sizeof(u_char*) * (*num) ); 515 | 516 | uint32_t i,j; 517 | uint32_t idx = 0; 518 | 519 | for (i=0; ibucket_num; i++) { 520 | 521 | bucket = hash32_map->buckets[i]; 522 | 523 | if ( 0 == bucket->chain_len ) { 524 | continue; 525 | } 526 | 527 | kv = bucket->kv_chain; 528 | 529 | for (j=0; jchain_len; j++) { 530 | string_array[idx] = GNB_HASH32_STRING_KEY(kv); 531 | idx++; 532 | kv = kv->nex; 533 | } 534 | 535 | } 536 | 537 | return string_array; 538 | 539 | } 540 | 541 | --------------------------------------------------------------------------------