feature: add debug_plugin for development debugging

This commit is contained in:
luwenpeng
2024-08-01 11:40:00 +08:00
parent 48202b4d0a
commit 776090331e
16 changed files with 446 additions and 135 deletions

View File

@@ -1,6 +1,7 @@
add_subdirectory(log) add_subdirectory(log)
add_subdirectory(times) add_subdirectory(times)
add_subdirectory(tuple) add_subdirectory(tuple)
add_subdirectory(hexdump)
add_subdirectory(packet) add_subdirectory(packet)
add_subdirectory(packet_io) add_subdirectory(packet_io)
add_subdirectory(id_generator) add_subdirectory(id_generator)

View File

@@ -0,0 +1,3 @@
add_library(hexdump hexdump.cpp)
target_include_directories(hexdump PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(hexdump)

37
src/hexdump/hexdump.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "hexdump.h"
void hexdump_to_fd(int fd, const char *data, uint16_t len)
{
uint16_t i = 0;
uint16_t used = 0;
uint16_t offset = 0;
#define LINE_LEN 80
char line[LINE_LEN]; /* space needed 8+16*3+3+16 == 75 */
dprintf(fd, "dump data at [%p], len=%u\n", data, len);
while (offset < len)
{
/* format the line in the buffer, then use printf to usedput to screen */
used = snprintf(line, LINE_LEN, "%08X:", offset);
for (i = 0; ((offset + i) < len) && (i < 16); i++)
{
used += snprintf(line + used, LINE_LEN - used, " %02X", (data[offset + i] & 0xff));
}
for (; i <= 16; i++)
{
used += snprintf(line + used, LINE_LEN - used, " | ");
}
for (i = 0; (offset < len) && (i < 16); i++, offset++)
{
unsigned char c = data[offset];
if ((c < ' ') || (c > '~'))
{
c = '.';
}
used += snprintf(line + used, LINE_LEN - used, "%c", c);
}
dprintf(fd, "%s\n", line);
}
dprintf(fd, "\n");
}

15
src/hexdump/hexdump.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdio.h>
void hexdump_to_fd(int fd, const char *data, uint16_t len);
#ifdef __cplusplus
}
#endif

View File

@@ -2,6 +2,6 @@ add_library(packet packet_parse.cpp packet_craft.cpp packet_dump.cpp packet_util
target_include_directories(packet PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_include_directories(packet PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash) target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash)
target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/include) target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(packet tuple log) target_link_libraries(packet hexdump tuple log)
add_subdirectory(test) add_subdirectory(test)

View File

@@ -5,6 +5,7 @@
#include <sys/time.h> #include <sys/time.h>
#include "log.h" #include "log.h"
#include "hexdump.h"
#include "packet_dump.h" #include "packet_dump.h"
#include "packet_utils.h" #include "packet_utils.h"
@@ -78,16 +79,8 @@ int packet_dump_pcap(const struct packet *pkt, const char *file)
void packet_dump_hex(const struct packet *pkt, int fd) void packet_dump_hex(const struct packet *pkt, int fd)
{ {
const char *data = packet_get_raw_data(pkt);
uint16_t len = packet_get_raw_len(pkt); uint16_t len = packet_get_raw_len(pkt);
const char *data = packet_get_raw_data(pkt);
for (int i = 0; i < len; i++) hexdump_to_fd(fd, data, len);
{
if (i % 16 == 0)
{
dprintf(fd, "\n");
}
dprintf(fd, "%02x ", (unsigned char)data[i]);
}
dprintf(fd, "\n");
} }

View File

@@ -986,79 +986,87 @@ const char *packet_parse(struct packet *pkt, const char *data, uint16_t len)
return parse_ether(pkt, data, len); return parse_ether(pkt, data, len);
} }
void packet_print(const struct packet *pkt) int packet_to_str(const struct packet *pkt, char *buff, int size)
{ {
if (pkt == NULL) if (pkt == NULL)
{ {
return; return 0;
} }
char buffer[2048] = {0}; int used = 0;
printf("packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n", memset(buff, 0, size);
used += snprintf(buff + used, size - used, "packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %u, layers_size: %u\n",
pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len, pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len,
pkt->layers_used, pkt->layers_size); pkt->layers_used, pkt->layers_size);
for (uint8_t i = 0; i < pkt->layers_used; i++) for (uint8_t i = 0; i < pkt->layers_used; i++)
{ {
int used = 0;
const struct raw_layer *layer = &pkt->layers[i]; const struct raw_layer *layer = &pkt->layers[i];
printf(" layer[%u]: %p, proto: %s, header: {offset: %u, ptr: %p, len: %u}, payload: {ptr: %p, len: %u}\n", used += snprintf(buff + used, size - used, "=> layer[%u]: %p, proto: %s, header: {offset: %u, ptr: %p, len: %u}, payload: {ptr: %p, len: %u}\n",
i, layer, layer_proto_to_str(layer->proto), layer->hdr_offset, i, layer, layer_proto_to_str(layer->proto), layer->hdr_offset,
layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len); layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len);
switch (layer->proto) switch (layer->proto)
{ {
case LAYER_PROTO_ETHER: case LAYER_PROTO_ETHER:
used = eth_hdr_to_str((const struct ethhdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += eth_hdr_to_str((const struct ethhdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_PWETH: case LAYER_PROTO_PWETH:
break; break;
case LAYER_PROTO_PPP: case LAYER_PROTO_PPP:
break; break;
case LAYER_PROTO_L2TP: case LAYER_PROTO_L2TP:
used = l2tp_hdr_to_str((const struct l2tp_hdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += l2tp_hdr_to_str((const struct l2tp_hdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_VLAN: case LAYER_PROTO_VLAN:
used = vlan_hdr_to_str((const struct vlan_hdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += vlan_hdr_to_str((const struct vlan_hdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_PPPOE: case LAYER_PROTO_PPPOE:
break; break;
case LAYER_PROTO_MPLS: case LAYER_PROTO_MPLS:
used = mpls_label_to_str((const struct mpls_label *)layer->hdr_ptr, buffer, sizeof(buffer)); used += mpls_label_to_str((const struct mpls_label *)layer->hdr_ptr, buff + used, size - used);
break; used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_IPV4: case LAYER_PROTO_IPV4:
used = ip4_hdr_to_str((const struct ip *)layer->hdr_ptr, buffer, sizeof(buffer)); used += ip4_hdr_to_str((const struct ip *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_IPV6: case LAYER_PROTO_IPV6:
used = ip6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += ip6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_IPAH: case LAYER_PROTO_IPAH:
break; break;
case LAYER_PROTO_GRE: case LAYER_PROTO_GRE:
used = gre_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buffer, sizeof(buffer)); used += gre_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_UDP: case LAYER_PROTO_UDP:
used = udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_TCP: case LAYER_PROTO_TCP:
used = tcp_hdr_to_str((const struct tcphdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += tcp_hdr_to_str((const struct tcphdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_ICMP: case LAYER_PROTO_ICMP:
break; break;
case LAYER_PROTO_ICMP6: case LAYER_PROTO_ICMP6:
break; break;
case LAYER_PROTO_VXLAN: case LAYER_PROTO_VXLAN:
used = vxlan_hdr_to_str((const struct vxlan_hdr *)layer->hdr_ptr, buffer, sizeof(buffer)); used += vxlan_hdr_to_str((const struct vxlan_hdr *)layer->hdr_ptr, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
case LAYER_PROTO_GTP_C: case LAYER_PROTO_GTP_C:
case LAYER_PROTO_GTP_U: case LAYER_PROTO_GTP_U:
used = gtp_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buffer, sizeof(buffer)); used += gtp_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buff + used, size - used);
used += snprintf(buff + used, size - used, "\n");
break; break;
default: default:
break; break;
} }
if (used)
{
printf(" %s\n", buffer);
}
} }
return used;
} }

View File

@@ -6,9 +6,20 @@ extern "C"
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
const char *packet_parse(struct packet *pkt, const char *data, uint16_t len); const char *packet_parse(struct packet *pkt, const char *data, uint16_t len);
void packet_print(const struct packet *pkt);
// bref : 1, output packet bref info
// bref : 0, output packet detail info
int packet_to_str(const struct packet *pkt, char *buff, int size);
static inline void packet_print(const struct packet *pkt)
{
char buff[4096];
packet_to_str(pkt, buff, sizeof(buff));
printf("%s\n", buff);
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -12,6 +12,7 @@
#include "packet_layer.h" #include "packet_layer.h"
#include "packet_parse.h" #include "packet_parse.h"
#include "packet_craft.h" #include "packet_craft.h"
#include "packet_utils.h"
#define PRINT_GREEN(fmt, ...) printf("\033[0;32m" fmt "\033[0m\n", ##__VA_ARGS__) #define PRINT_GREEN(fmt, ...) printf("\033[0;32m" fmt "\033[0m\n", ##__VA_ARGS__)
#define PRINT_RED(fmt, ...) printf("\033[0;31m" fmt "\033[0m\n", ##__VA_ARGS__) #define PRINT_RED(fmt, ...) printf("\033[0;31m" fmt "\033[0m\n", ##__VA_ARGS__)
@@ -191,6 +192,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP4_TCP)
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]); // printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]); EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
} }
packet_free(new_pkt);
} }
#endif #endif
@@ -336,6 +339,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP4_IP6_TCP)
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]); // printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]); EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
} }
packet_free(new_pkt);
} }
#endif #endif
@@ -574,6 +579,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]); // printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]); EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
} }
packet_free(new_pkt);
} }
#endif #endif
@@ -780,6 +787,8 @@ TEST(PACKET_CRAFT_TCP, ETH_IP4_GRE_IP6_TCP)
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]); // printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]); EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
} }
packet_free(new_pkt);
} }
#endif #endif
@@ -1011,6 +1020,8 @@ TEST(PACKET_CRAFT_UDP, ETH_VLAN_IPv6_IPv4_GRE_PPP_IPv4_UDP_DNS)
printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]); printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]); EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
} }
packet_free(new_pkt);
} }
#endif #endif

View File

@@ -494,12 +494,25 @@ static void tcp_flags_to_str(uint8_t flags, char *buffer, size_t len)
} }
} }
int session_to_json(struct session *sess, char *buff, int size) int session_to_str(const struct session *sess, int bref, char *buff, int size)
{ {
memset(buff, 0, size); memset(buff, 0, size);
char flags[64] = {0}; char flags[64] = {0};
int used = 0; int used = 0;
if (bref)
{
used += snprintf(buff + used, size - used, "session id: %lu, addr: %s, type: %s, state: %s, dir: %s, c2s_rx_pkts: %lu, s2c_rx_pkts: %lu",
session_get_id(sess),
session_get0_readable_addr(sess),
session_type_to_str(session_get_type(sess)),
session_state_to_str(session_get_current_state(sess)),
flow_direction_to_str(session_get_current_flow_direction(sess)),
session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_RAW_PACKETS_RECEIVED),
session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_RAW_PACKETS_RECEIVED));
}
else
{
used += snprintf(buff + used, size - used, "{"); used += snprintf(buff + used, size - used, "{");
used += snprintf(buff + used, size - used, "\"id\":%" PRIu64 ",", session_get_id(sess)); used += snprintf(buff + used, size - used, "\"id\":%" PRIu64 ",", session_get_id(sess));
used += snprintf(buff + used, size - used, "\"start_timestamp\":%" PRIu64 ",", session_get_timestamp(sess, SESSION_TIMESTAMP_START)); used += snprintf(buff + used, size - used, "\"start_timestamp\":%" PRIu64 ",", session_get_timestamp(sess, SESSION_TIMESTAMP_START));
@@ -587,13 +600,7 @@ int session_to_json(struct session *sess, char *buff, int size)
} }
} }
used += snprintf(buff + used, size - used, "}"); used += snprintf(buff + used, size - used, "}");
}
return used; return used;
} }
void session_print(struct session *sess)
{
char buff[4096];
session_to_json(sess, buff, sizeof(buff));
printf("%s\n", buff);
}

View File

@@ -6,6 +6,7 @@ extern "C"
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include "stellar/session.h" #include "stellar/session.h"
@@ -131,8 +132,16 @@ const char *session_state_to_str(enum session_state state);
const char *session_type_to_str(enum session_type type); const char *session_type_to_str(enum session_type type);
const char *flow_direction_to_str(enum flow_direction dir); const char *flow_direction_to_str(enum flow_direction dir);
int session_to_json(struct session *sess, char *buff, int size); // bref : 1, output session bref info
void session_print(struct session *sess); // bref : 0, output session detail info
int session_to_str(const struct session *sess, int bref, char *buff, int size);
static inline void session_print(const struct session *sess)
{
char buff[4096];
session_to_str(sess, 0, buff, sizeof(buff));
printf("%s\n", buff);
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -1,2 +1,3 @@
add_subdirectory(packet_inject) add_subdirectory(packet_inject)
add_subdirectory(packet_tool) add_subdirectory(packet_tool)
add_subdirectory(debug_plugin)

View File

@@ -0,0 +1,8 @@
# build libdebug_plugin.so
add_library(debug_plugin SHARED debug_plugin.cpp)
# Note: The debug plugin here uses stellar_core instead of stellar_devel, in order to output more session/packet information for development debugging.
target_link_libraries(debug_plugin stellar_core toml)
target_include_directories(debug_plugin PUBLIC ${CMAKE_SOURCE_DIR}/include/)
set_target_properties(debug_plugin PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/version.map")
file(COPY ./conf/ DESTINATION ./conf/)

View File

@@ -0,0 +1,4 @@
[[plugin]]
path = "./plugin/libdebug_plugin.so"
init = "debug_plugin_init"
exit = "debug_plugin_exit"

View File

@@ -0,0 +1,196 @@
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <time.h>
#include <pthread.h>
#include <arpa/inet.h>
#include "log.h"
#include "hexdump.h"
#include "session_utils.h"
#include "tcp_reassembly.h"
#include "packet_dump.h"
#include "packet_parse.h"
#include "packet_utils.h"
#include "stellar/session_mq.h"
// NOTE: packet hexdump or tcp segment hexdump may be too long, so we need direct output to fd, instead of using log_print
static void log_print(int fd, const char *module, const char *fmt, ...)
{
static unsigned char weekday_str[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static unsigned char month_str[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int nwrite;
char buf[4096 * 2] = {0};
char *p = buf;
char *end = buf + sizeof(buf);
va_list args;
struct tm local;
time_t t;
time(&t);
localtime_r(&t, &local);
// add time
p += snprintf(p, end - p, "%s %s %d %02d:%02d:%02d %d ",
weekday_str[local.tm_wday], month_str[local.tm_mon], local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec, local.tm_year + 1900);
// add tid
p += snprintf(p, end - p, "%lu ", pthread_self());
// add module
p += snprintf(p, end - p, "(%s), ", module);
// add content
va_start(args, fmt);
p += vsnprintf(p, end - p, fmt, args);
va_end(args);
// add end of line
p += snprintf(p, end - p, "\n");
do
{
nwrite = write(fd, buf, p - buf);
} while (nwrite == -1 && errno == EINTR);
}
struct plugin_ctx
{
struct stellar *st;
int sess_plug_id;
int tcp_topic_id;
int udp_topic_id;
int tcp_stream_topic_id;
int fd;
pthread_spinlock_t lock; // for hexdump thread safe
};
static void *on_sess_new(struct session *sess, void *plugin_ctx)
{
char buff[4096];
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
memset(buff, 0, sizeof(buff));
session_to_str(sess, 1, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "sess new: %s", buff);
return NULL;
}
static void on_sess_free(struct session *sess, void *sess_ctx, void *plugin_ctx)
{
char buff[4096];
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
memset(buff, 0, sizeof(buff));
session_to_str(sess, 0, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "sess free: %s", buff);
}
static void on_sess_udp_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
{
char buff[4096];
struct packet *pkt = (struct packet *)msg;
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
memset(buff, 0, sizeof(buff));
session_to_str(sess, 1, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "on UDP msg: %s", buff);
memset(buff, 0, sizeof(buff));
packet_to_str(pkt, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "rx UDP packet: \n%s", buff);
pthread_spin_lock(&ctx->lock);
packet_dump_hex(pkt, ctx->fd);
pthread_spin_unlock(&ctx->lock);
}
static void on_sess_tcp_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
{
char buff[4096];
struct packet *pkt = (struct packet *)msg;
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
memset(buff, 0, sizeof(buff));
session_to_str(sess, 1, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "on TCP msg: %s", buff);
memset(buff, 0, sizeof(buff));
packet_to_str(pkt, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "rx TCP packet: \n%s", buff);
pthread_spin_lock(&ctx->lock);
packet_dump_hex(pkt, ctx->fd);
pthread_spin_unlock(&ctx->lock);
}
static void on_sess_tcp_stream_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx)
{
char buff[4096];
struct tcp_segment *seg = (struct tcp_segment *)msg;
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
memset(buff, 0, sizeof(buff));
session_to_str(sess, 1, buff, sizeof(buff) - 1);
log_print(ctx->fd, "debug plugin", "on TCP stream msg: %s", buff);
log_print(ctx->fd, "debug plugin", "rx TCP segment: len: %d, data: %p\n", seg->len, seg->data);
pthread_spin_lock(&ctx->lock);
hexdump_to_fd(ctx->fd, (const char *)seg->data, seg->len);
pthread_spin_unlock(&ctx->lock);
}
/******************************************************************************
* Plugin API
******************************************************************************/
extern "C"
{
void *debug_plugin_init(struct stellar *st)
{
struct plugin_ctx *ctx = (struct plugin_ctx *)calloc(1, sizeof(struct plugin_ctx));
if (ctx == NULL)
{
return NULL;
}
ctx->fd = open("./log/debug_plugin.log", O_WRONLY | O_APPEND | O_CREAT, 0644);
if (ctx->fd == -1)
{
ctx->fd = STDOUT_FILENO;
}
pthread_spin_init(&ctx->lock, PTHREAD_PROCESS_PRIVATE);
ctx->st = st;
ctx->sess_plug_id = stellar_session_plugin_register(st, on_sess_new, on_sess_free, ctx);
ctx->udp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_UDP);
ctx->tcp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP);
ctx->tcp_stream_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP_STREAM);
stellar_session_mq_subscribe(st, ctx->udp_topic_id, on_sess_udp_msg, ctx->sess_plug_id);
stellar_session_mq_subscribe(st, ctx->tcp_topic_id, on_sess_tcp_msg, ctx->sess_plug_id);
stellar_session_mq_subscribe(st, ctx->tcp_stream_topic_id, on_sess_tcp_stream_msg, ctx->sess_plug_id);
log_print(ctx->fd, "debug plugin", "init");
return ctx;
}
void debug_plugin_exit(void *plugin_ctx)
{
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
if (ctx)
{
log_print(ctx->fd, "debug plugin", "exit");
if (ctx->fd > 0)
{
close(ctx->fd);
}
pthread_spin_destroy(&ctx->lock);
free(ctx);
}
}
}

View File

@@ -0,0 +1,7 @@
DEBUG_PLUGIN {
global:
debug_plugin_init;
debug_plugin_exit;
local: *;
};