213 lines
6.3 KiB
C++
213 lines
6.3 KiB
C++
#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 "hexdump.h"
|
|
#include "session_utils.h"
|
|
#include "packet_dump.h"
|
|
#include "packet_parse.h"
|
|
#include "stellar/packet.h"
|
|
#include "stellar/stellar_mq.h"
|
|
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
|
|
// 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)
|
|
{
|
|
if (msg == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (msg == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (msg == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
char buff[4096];
|
|
struct tcp_segment *seg = (struct tcp_segment *)msg;
|
|
struct plugin_ctx *ctx = (struct plugin_ctx *)plugin_ctx;
|
|
const char *data = tcp_segment_get_data(seg);
|
|
uint16_t len = tcp_segment_get_len(seg);
|
|
|
|
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", len, data);
|
|
|
|
pthread_spin_lock(&ctx->lock);
|
|
hexdump_to_fd(ctx->fd, data, 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_mq_get_topic_id(st, TOPIC_UDP);
|
|
ctx->tcp_topic_id = stellar_mq_get_topic_id(st, TOPIC_TCP);
|
|
ctx->tcp_stream_topic_id = stellar_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);
|
|
}
|
|
}
|
|
} |