
 #include "java_common.h"

// #include "bpf_tracing.h"
// #include "bpf_helpers.h"
// #include <asm/ptrace.h>
// #include "bpf_base.h"
// #define ROCK_MAX_BUFFER_SIZE 65536

#define ROCK_MAX_LEN 1022

//struct sock_t {
//	int size;
//	int header_offset_idx;
//	char payload[ROCK_MAX_LEN];
//};
//
//struct {
//	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
//	__type(key, int);
//	__type(value, struct sock_t);
//	__uint(max_entries, 1);
//} socket_heap SEC(".maps");

struct {
	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
	__type(key, int);
	__type(value, struct apm_span_context);
	__uint(max_entries, 1);
} apm_span_context_heap SEC(".maps");

//struct {
//	__uint(type, BPF_MAP_TYPE_ARRAY);
//	__type(key, int); // 键类型为int
//	__uint(value_size, 124); // 数组的值的大小
//	__uint(max_entries, 1);
//} large_array_map SEC(".maps");

static __inline int is_http_header(const char *data)
{
	for (int i = 0; i < 512; i++)
	{
		if (data[i] == '\r' &&
		    data[i + 1] == '\n' &&
		    data[i + 2] == 'c' &&
		    data[i + 3] == 'w' &&
		    data[i + 4] == 't' &&
		    data[i + 5] == 'r' &&
		    data[i + 6] == 'a' &&
		    data[i + 7] == 'c' &&
		    data[i + 8] == 'e' &&
			data[i + 9] == ':' &&
			data[i + 10] == ' ') {
			return i + 11;
		}
	}
	return 0;
}

SEC("uprobe/Java_sun_nio_ch_FileDispatcherImpl_read0")
int uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0(struct pt_regs *ctx) {
	//计算 rbp-0x30
	bpf_printk("enter the uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0\n");
	unsigned long jhttpdata_ptr;
	jhttpdata_ptr = (ctx)->rbp;
	jhttpdata_ptr = jhttpdata_ptr - 0x70;
	// bpf_printk("enter rbp is %llx.\n", jhttpdata_ptr);
	jhttpdata_ptr = jhttpdata_ptr - 0x30;
	//p rbp - 0x30
	// bpf_printk("enter rbp -0x30 to rcx is %llx.\n", jhttpdata_ptr);

	// x/1gx (p rbp-0x30)
	unsigned long jbytechar_ptr;
	long ret = bpf_probe_read_user(&jbytechar_ptr, sizeof(unsigned long), (void *) jhttpdata_ptr);
	// bpf_printk("x/1gx (p rbp-0x30) value is %llx.\n", jbytechar_ptr);
	// bpf_printk("enter the uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0 ------22222222\n");
	if (ret != 0) {
		bpf_printk("Failed to read first level ptr: %d\n", ret);
		return 0;
	}
	if (!jbytechar_ptr) {
		// bpf_printk("First level pointer is null.\n");
		return 0;
	}
	// bpf_printk("enter the uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0 ----111111111\n");

	//x/s addr
	int key = 0;
	struct sock_t *map_data = bpf_map_lookup_elem(&socket_heap, &key);
	if (!map_data) {
		return 0;
	}
	long err = bpf_probe_read_user_str(map_data->payload, sizeof(map_data->payload), (void *) (jbytechar_ptr));
	if (err < 0) {
		// bpf_printk("bpf_probe_read_user failed with return code: %d\n", err);
		return 0;
	}

	bpf_printk("read data is : %s\n", map_data->payload);

//	 if (!is_http_request2(map_data->payload, 14))
//	 {
//	 	bpf_printk("not a http request\n");
//	 	return 0;
//	 }


	int offset = is_http_header(map_data->payload);
	bpf_printk("found the header, %d\n", offset);
	char *data;
	data = bpf_map_lookup_elem(&large_array_map, &key);
	if (!data)
		return 0;
	// struct apm_span_context cw_parent_span_context = {};
	struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap, &key);
	if (cw_parent_span_context == NULL){
		return -1;
	}
	if(offset > 0 && offset < 512 - 123)
	{
		__builtin_memcpy(data, &(map_data->payload[offset]), 123);
		// bpf_printk("found the data, %s\n", data);

		cw_string_to_span_context(data, cw_parent_span_context);
	}
	else
	{
		generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
	}
	// 保存 trace_id 到psc
	cw_save_parent_tracking_span(cw_parent_span_context);
	return 0;
}

// char __license[] SEC("license") = "Dual MIT/GPL";
