//
// Created by Carl.Guo on 2024/6/28.
//

#ifndef EUSPACES_JAVA_COMMON_H
#define EUSPACES_JAVA_COMMON_H


#if defined(__x86_64__)
#define PT_LEN_REGS(x) (PT_REGS_RBP(x) - 0x10058);
#define PT_HTTP_RESP_REGS(x) PT_REGS_PARM2(x)
#elif defined(__aarch64__)
#define PT_LEN_REGS(x) PT_REGS_SP(x);
#define PT_HTTP_RESP_REGS(ctx) ({                \
	unsigned long res = 0;                       \
    long err = bpf_probe_read(&res, sizeof(res), \
            (void *) (PT_REGS_SP(ctx) - 48));    \
    if (err < 0) {                               \
        bpf_printk("bpf_probe_read failed with return code: %ld\n", err); \
        res = 0;                                 \
    }                                            \
    res;                                         \
})
#endif


#define L7_IOVEC_BUF_SIZE 1024
#define MAX_CHUNK 9

#define MIN_LEN 13
#define MAX_LEN 1022
//#define MAX_BUFFER_SIZE 65536

/**
 * key  :  7
 * ': ' :  2
 * val  : 123
 * \r\n :  2
 */
#define HEADER_LEN 134
#define JAVA_MAX_BUFFER_SIZE 65536



struct sock_t {
	u32 size;
	u32 header_offset_idx;
	u32 end_str_len;
	void * payload_char_p;
	void * payload_len_p;
	char payload[MAX_LEN];
	char header_stream[CW_STREAM_HEADER_LEN];
};

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct sock_t);
	__uint(max_entries, 1);
} socket_heap SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__type(key, u32); // 键类型为int
	__uint(value_size, JAVA_MAX_BUFFER_SIZE); // 数组的每个值的大小
	__uint(max_entries, 2); // 最大条目数为2
} large_array_map SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct sock_t);
	__uint(max_entries, 1);
} socket_res SEC(".maps");



struct ttt {
	char payload[IOVEC_BUF_SIZE];
};

struct ttt_h {
	char payload[1024];
};

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct ttt_h);
	__uint(max_entries, 1);
} iovec_header_heap SEC(".maps");

// 块
struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct ttt);
	__uint(max_entries, MAX_CHUNK);
} l7_iovec_buf_heap SEC(".maps");


struct stream_header_t {
	char header[135];
};

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, u32);
	__type(value, struct stream_header_t);
	__uint(max_entries, 1);
} stream_header_heap SEC(".maps");


static __always_inline void span_context_to_cw_string_stream(struct apm_span_context *ctx, char *buff, char type_from) {
	// W3C format: version (2 chars) - trace id (32 chars) - span id (16 chars) - sampled (2 chars)
	//	[type_from]:[sample]:[host_id]:[app_id]:[instance_id]:[trace_id]:[assumed_app_i d]:[span_id]
	//	2           2         16        16      16            32         16                16
	char *out = buff;
	*out++ = 'c';
	*out++ = 'w';
	*out++ = 't';
	*out++ = 'r';
	*out++ = 'a';
	*out++ = 'c';
	*out++ = 'e';
	*out++ = ':';
	*out++ = ' ';

	// Write type_from
	*out++ = '0';
	*out++ = type_from;
	*out++ = ':';

	// Write sample
	*out++ = '0';
	*out++ = '0';
	*out++ = ':';

	// Write host_id
	bytes_to_hex_string(ctx->host_id, APM_HOST_ID_SIZE, out);
	out += APM_HOST_ID_STRING_SIZE;
	*out++ = ':';

	// Write app_id
	bytes_to_hex_string(ctx->app_id, APM_APP_ID_SIZE, out);
	out += APM_APP_ID_STRING_SIZE;
	*out++ = ':';


	// Write instance_id
	bytes_to_hex_string(ctx->instance_id, APM_INSTANCE_ID_SIZE, out);
	out += APM_INSTANCE_ID_STRING_SIZE;
	*out++ = ':';

	// Write trace_id
	bytes_to_hex_string(ctx->trace_id, APM_TRACE_ID_SIZE, out);
	out += APM_TRACE_ID_STRING_SIZE;
	*out++ = ':';
	// Write assumed_app_id
	bytes_to_hex_string(ctx->assumed_app_id, APM_ASSUMED_APP_ID_SIZE, out);
	out += APM_ASSUMED_APP_ID_STRING_SIZE;
	*out++ = ':';

	// Write span_id
	bytes_to_hex_string(ctx->span_id, APM_SPAN_ID_SIZE, out);
	out += APM_SPAN_ID_STRING_SIZE;

	*out++ = '\r';
	*out++ = '\n';
	*out++ = '\0';
	out += 3;
}

#endif //EUSPACES_JAVA_COMMON_H
