/* * @file tfe_utils.h * This file provides common usage marcos and helper functions. */ #pragma once #include #include #include #include //scan_dir #include #include #include "kafka.h" #define LOG_TAG_CTRLPKT "CTRL_PACKET" #define LOG_TAG_STABLE "SESSION_TABLE" #define LOG_TAG_PKTIO "PACKET_IO" #define TFE_STRING_MAX 2048 #define TFE_PATH_MAX 256 #define TFE_SYMBOL_MAX 64 #define TFE_THREAD_MAX 256 #define TFE_FAKE_C_DEFAULT_TTL 60 #define TFE_FAKE_S_DEFAULT_TTL 65 #define UUID_LEN 16 #define UUID_STRING_SIZE 37 #ifndef TFE_CONFIG_BACKLOG_DEFAULT #define TFE_CONFIG_BACKLOG_DEFAULT 20 #endif #define ALLOC(type, number) ((type *)calloc(sizeof(type), number)) #define FREE(p) {free(*p);*p=NULL;} #define TFE_STRUCT_ALLOC(struct_type) __extension__ \ ({ \ ((struct_type) * ) __struct_ptr; \ __struct_ptr = ((struct_type) *)malloc(sizeof((struct_type))); \ __struct_ptr; \ }) #define likely(expr) __builtin_expect((expr), 1) #define unlikely(expr) __builtin_expect((expr), 0) #define UNUSED __attribute__((unused)) extern void * g_default_logger; extern bool g_print_to_stderr; extern thread_local unsigned int __currect_thread_id; #define TFE_LOG_ERROR(handler, fmt, ...) \ do \ { \ if (g_print_to_stderr) \ { \ fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ } \ if (MESA_handle_runtime_log_level_enabled(handler, RLOG_LV_FATAL)) \ { \ MESA_handle_runtime_log(handler, RLOG_LV_FATAL, __FUNCTION__, fmt, ##__VA_ARGS__); \ } \ } while (0) #define TFE_LOG_INFO(handler, fmt, ...) \ do \ { \ if (g_print_to_stderr) \ { \ fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ } \ if (MESA_handle_runtime_log_level_enabled(handler, RLOG_LV_INFO)) \ { \ MESA_handle_runtime_log(handler, RLOG_LV_INFO, __FUNCTION__, fmt, ##__VA_ARGS__); \ } \ } while (0) #define TFE_LOG_DEBUG(handler, fmt, ...) \ do \ { \ if (g_print_to_stderr) \ { \ fprintf(stderr, fmt "\n", ##__VA_ARGS__); \ } \ if (MESA_handle_runtime_log_level_enabled(handler, RLOG_LV_DEBUG)) \ { \ MESA_handle_runtime_log(handler, RLOG_LV_DEBUG, __FUNCTION__, fmt, ##__VA_ARGS__); \ } \ } while (0) #define CHECK_OR_EXIT(condition, fmt, ...) \ do { if(!(condition)) { TFE_LOG_ERROR(g_default_logger, fmt, ##__VA_ARGS__); exit(EXIT_FAILURE); } } while(0) \ #define DIE(fmt, ...) \ do { TFE_LOG_ERROR(g_default_logger, "DIE: " fmt, ##__VA_ARGS__); abort(); } while(0) \ #define CHECK_OR_DIE(condition, fmt, ...) \ do { if(!(condition)) { TFE_LOG_ERROR(g_default_logger, fmt, ##__VA_ARGS__); abort(); } } while(0) \ #define TFE_STREAM_LOG_DEBUG(stream, fmt, ...) #define TFE_STREAM_LOG_INFO(stream, fmt, ...) #define TFE_STREAM_LOG_ERROR(stream, fmt, ...) do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while(0) #define TFE_STREAM_TRACE_TAG_INFO(stream, tag, fmt, ...) #define TFE_STREAM_TRACE_TAG_VERBOSE(stream, tag, fmt, ...) #ifndef offsetof /** Return the offset of a field in a structure. */ #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) #endif /** * Return pointer to the wrapping struct instance. * * Example: * * struct wrapper { * ... * struct child c; * ... * }; * * struct child *x = obtain(...); * struct wrapper *w = container_of(x, struct wrapper, c); */ #ifndef container_of #define container_of(ptr, type, member) __extension__ ({ \ const typeof(((type *)0)->member) *_ptr = (ptr); \ __attribute__((unused)) type *_target_ptr = (type *)(ptr); \ (type *)(((uintptr_t)_ptr) - offsetof(type, member)); \ }) #endif #define ATOMIC_INC(x) __atomic_fetch_add(x,1,__ATOMIC_RELAXED) #define ATOMIC_DEC(x) __atomic_fetch_sub(x,1,__ATOMIC_RELAXED) #define ATOMIC_READ(x) __atomic_load_n(x, __ATOMIC_RELAXED) //#define ATOMIC_READ(x) __atomic_fetch_add(x,0,__ATOMIC_RELAXED) #define ATOMIC_ADD(x, y) __atomic_fetch_add(x,y,__ATOMIC_RELAXED) #define ATOMIC_ZERO(x) __atomic_fetch_and(x,0,__ATOMIC_RELAXED) #define ATOMIC_SET(x,y) __atomic_store_n(x,y,__ATOMIC_RELAXED) #define ATOMIC_EXCHANGE(x,y) __atomic_exchange_n(x,y,__ATOMIC_RELAXED) #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif char* tfe_strdup(const char* s); char *tfe_thread_safe_ctime(const time_t *tp, char *buf, int len); #define TFE_SET_USED(x) (void)(x) #define TFE_PTR_ADD(ptr, x) ((void*)((uintptr_t)(ptr) + (x))) #define TFE_PTR_SUB(ptr, x) ((void*)((uintptr_t)ptr - (x))) #define TFE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2)) #define TFE_DIM(x) (sizeof (x) / sizeof ((x)[0])) #ifndef TAILQ_FOREACH_SAFE #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #endif #include #include static inline void tfe_hexdump2file(FILE *f, const char * title, const void * buf, unsigned int len) { unsigned int i, out, ofs; const unsigned char *data = (const unsigned char *)buf; #define LINE_LEN 80 char line[LINE_LEN]; /* space needed 8+16*3+3+16 == 75 */ fprintf(f, "%s at [%p], len=%u\n", (title)? title : " Dump data", data, len); ofs = 0; while (ofs < len) { /* format the line in the buffer, then use printf to output to screen */ out = snprintf(line, LINE_LEN, "%08X:", ofs); for (i = 0; ((ofs + i) < len) && (i < 16); i++) out += snprintf(line+out, LINE_LEN - out, " %02X", (data[ofs+i] & 0xff)); for(; i <= 16; i++) out += snprintf(line+out, LINE_LEN - out, " | "); for(i = 0; (ofs < len) && (i < 16); i++, ofs++) { unsigned char c = data[ofs]; if ( (c < ' ') || (c > '~')) c = '.'; out += snprintf(line+out, LINE_LEN - out, "%c", c); } fprintf(f, "%s\n", line); } fflush(f); #undef LINE_LEN } static inline unsigned char* tfe_hexdump(unsigned char *dst, unsigned char *src, size_t len) { static unsigned char hex[] = "0123456789abcdef"; while (len--) { *dst++ = hex[*src >> 4]; *dst++ = hex[*src++ & 0xf]; } return dst; } int tfe_scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *)); char *tfe_read_file(const char *filename, size_t *filelen); const char * tfe_version(); int tfe_decode_base64url(u_char *dst, u_char *src); /****************************************************************************** * sids ******************************************************************************/ typedef uint16_t sid_t; #define MR_SID_LIST_MAXLEN 8 struct sids { int num; sid_t elems[MR_SID_LIST_MAXLEN]; }; void sids_write_once(struct sids *dst, struct sids *src); void sids_copy(struct sids *dst, struct sids *src); /****************************************************************************** * route_ctx ******************************************************************************/ struct route_ctx { char data[64]; int len; }; int route_ctx_is_empty(struct route_ctx *ctx); void route_ctx_copy(struct route_ctx *dst, struct route_ctx *src); /****************************************************************************** * protocol ******************************************************************************/ struct udp_hdr { u_int16_t uh_sport; /* source port */ u_int16_t uh_dport; /* destination port */ u_int16_t uh_ulen; /* udp length */ u_int16_t uh_sum; /* udp checksum */ } __attribute__((__packed__)); int str_to_mac(const char *str, char *mac_buff); int get_mac_by_device_name(const char *dev_name, char *mac_buff);