2727#include <gotracer/go_str.h>
2828#include <gotracer/go_stream_key.h>
2929#include <gotracer/hpack.h>
30- #include <gotracer/protocol_jsonrpc.h>
31- #include <gotracer/maps/jsonrpc_jump_table.h>
3230
3331#include <logger/bpf_dbg.h>
3432
3735
3836#include <pid/pid_helpers.h>
3937
40- enum { k_tail_jsonrpc = 0 };
4138static const char traceparent [] = "traceparent: " ;
42- static const char content_type [] = "content-type: " ;
4339
4440typedef struct http_client_data {
4541 s64 content_length ;
@@ -70,13 +66,11 @@ typedef struct server_http_func_invocation {
7066 u64 content_length ;
7167 u64 response_length ;
7268 u64 status ;
73- u64 body_addr ; // pointer to the body buffer
69+ u64 rpc_request_addr ; // pointer to the jsonrpc Request
7470 tp_info_t tp ;
75- unsigned char content_type [HTTP_CONTENT_TYPE_MAX_LEN ];
7671 u8 method [METHOD_MAX_LEN ];
7772 u8 path [PATH_MAX_LEN ];
78- u8 json_content_type ;
79- u8 _pad [4 ];
73+ u8 _pad [5 ];
8074} server_http_func_invocation_t ;
8175
8276struct {
@@ -98,18 +92,6 @@ static __always_inline unsigned char *temp_header_mem() {
9892 return bpf_map_lookup_elem (& temp_header_mem_store , & zero );
9993}
10094
101- struct {
102- __uint (type , BPF_MAP_TYPE_PERCPU_ARRAY );
103- __type (key , u32 );
104- __type (value , unsigned char [HTTP_BODY_MAX_LEN ]);
105- __uint (max_entries , 1 );
106- } temp_body_mem_store SEC (".maps" );
107-
108- static __always_inline unsigned char * temp_body_mem () {
109- const u32 zero = 0 ;
110- return bpf_map_lookup_elem (& temp_body_mem_store , & zero );
111- }
112-
11395/* HTTP Server */
11496
11597// This instrumentation attaches uprobe to the following function:
@@ -151,15 +133,6 @@ int obi_uprobe_ServeHTTP(struct pt_regs *ctx) {
151133 // TODO: if context propagation is supported, overwrite the header value in the map with the
152134 // new span context and the same thread id.
153135
154- // get content-type from readContinuedLineSlice
155- if (header_inv && header_inv -> content_type [0 ]) {
156- bpf_dbg_printk ("Found content type in ongoing request: %s" , header_inv -> content_type );
157- if (is_json_content_type ((void * )header_inv -> content_type ,
158- sizeof (header_inv -> content_type ))) {
159- invocation .json_content_type = 1 ;
160- }
161- }
162-
163136 // Get method from Request.Method
164137 if (!read_go_str ("method" ,
165138 req ,
@@ -311,13 +284,6 @@ static __always_inline void update_traceparent(server_http_func_invocation_t *in
311284 bpf_dbg_printk ("Found traceparent in header %s" , header_start );
312285}
313286
314- static __always_inline void update_content_type (server_http_func_invocation_t * inv ,
315- const unsigned char * header_start ) {
316- __builtin_memset (inv -> content_type , 0 , sizeof (inv -> content_type ));
317- __builtin_memcpy (inv -> content_type , header_start , sizeof (inv -> content_type ));
318- bpf_dbg_printk ("Found content-type in header %s" , inv -> content_type );
319- }
320-
321287static __always_inline void handle_traceparent_header (server_http_func_invocation_t * inv ,
322288 go_addr_key_t * g_key ,
323289 unsigned char * traceparent_start ) {
@@ -330,18 +296,6 @@ static __always_inline void handle_traceparent_header(server_http_func_invocatio
330296 }
331297}
332298
333- static __always_inline void handle_content_type_header (server_http_func_invocation_t * inv ,
334- go_addr_key_t * g_key ,
335- unsigned char * content_type_start ) {
336- if (inv ) {
337- update_content_type (inv , content_type_start );
338- } else {
339- server_http_func_invocation_t minimal_inv = {};
340- update_content_type (& minimal_inv , content_type_start );
341- bpf_map_update_elem (& ongoing_http_server_requests , g_key , & minimal_inv , BPF_ANY );
342- }
343- }
344-
345299// Matches the header in the buffer and returns a pointer to the value part of the header.
346300static __always_inline unsigned char * match_header (
347301 const unsigned char * buf , u32 safe_len , const char * header , u32 header_len , u32 value_len ) {
@@ -375,7 +329,6 @@ int obi_uprobe_readContinuedLineSliceReturns(struct pt_regs *ctx) {
375329 };
376330
377331 const u32 w3c_value_start = sizeof (traceparent ) - 1 ;
378- const u32 content_type_value_start = sizeof (content_type ) - 1 ;
379332
380333 server_http_func_invocation_t * inv = bpf_map_lookup_elem (& ongoing_http_server_requests , & g_key );
381334
@@ -385,12 +338,6 @@ int obi_uprobe_readContinuedLineSliceReturns(struct pt_regs *ctx) {
385338 handle_traceparent_header (inv , & g_key , traceparent_start );
386339 }
387340
388- unsigned char * content_type_start = match_header (
389- temp , safe_len , content_type , content_type_value_start , HTTP_CONTENT_TYPE_MAX_LEN );
390- if (content_type_start ) {
391- handle_content_type_header (inv , & g_key , content_type_start );
392- }
393-
394341 return 0 ;
395342}
396343
@@ -1299,99 +1246,68 @@ int obi_uprobe_netFdRead(struct pt_regs *ctx) {
12991246 return 0 ;
13001247}
13011248
1302- SEC ("uprobe/bodyRead " )
1303- int obi_uprobe_bodyRead (struct pt_regs * ctx ) {
1249+ SEC ("uprobe/jsonrpcReadRequestHeader " )
1250+ int obi_uprobe_jsonrpcReadRequestHeader (struct pt_regs * ctx ) {
13041251 void * goroutine_addr = GOROUTINE_PTR (ctx );
1305- bpf_dbg_printk ("=== uprobe/proc body read goroutine === " );
1252+ bpf_dbg_printk ("=== uprobe/proc jsonrpc read request header goroutine %lx === " ,
1253+ goroutine_addr );
1254+
13061255 go_addr_key_t g_key = {};
13071256 go_addr_key_from_id (& g_key , goroutine_addr );
13081257
1309- // Get the address of the slice struct (p)
1310- u64 body_addr = (u64 )GO_PARAM2 (ctx );
1311-
13121258 server_http_func_invocation_t * invocation =
13131259 bpf_map_lookup_elem (& ongoing_http_server_requests , & g_key );
13141260 if (!invocation ) {
13151261 return 0 ;
13161262 }
1317- invocation -> body_addr = body_addr ;
1263+ const u64 rpc_request_addr = (u64 )GO_PARAM2 (ctx );
1264+ bpf_dbg_printk ("rpc_request_addr %llx" , rpc_request_addr );
1265+ invocation -> rpc_request_addr = rpc_request_addr ;
13181266
13191267 return 0 ;
13201268}
13211269
1322- SEC ("uprobe/bodyReadRet" )
1323- int obi_uprobe_bodyReadReturn (struct pt_regs * ctx ) {
1324- bpf_dbg_printk ("=== uprobe/proc body read returns goroutine === " );
1270+ SEC ("uprobe/jsonrpcReadRequestHeaderRet" )
1271+ int obi_uprobe_jsonrpcReadRequestHeaderReturns (struct pt_regs * ctx ) {
13251272 void * goroutine_addr = GOROUTINE_PTR (ctx );
1273+ bpf_dbg_printk ("=== uprobe/proc jsonrpc read request header return goroutine %lx === " ,
1274+ goroutine_addr );
1275+
13261276 go_addr_key_t g_key = {};
13271277 go_addr_key_from_id (& g_key , goroutine_addr );
13281278
1329- u64 n = (u64 )GO_PARAM1 (ctx );
1330- bpf_dbg_printk ("n is %llu" , n );
1331-
13321279 server_http_func_invocation_t * invocation =
13331280 bpf_map_lookup_elem (& ongoing_http_server_requests , & g_key );
1334- if (!invocation ) {
1335- return 0 ;
1336- }
1337- if (n <= 0 || !invocation -> body_addr ) {
1338- return 0 ;
1339- }
1340- // json_content-type is set in invocation in ServeHTTP
1341- if (invocation -> json_content_type != 1 ) {
1342- bpf_dbg_printk ("content type is not json, skipping" );
1343- return 0 ;
1344- }
13451281
1346- unsigned char * body_buf = temp_body_mem ();
1347- if (!body_buf ) {
1282+ if (!invocation || !invocation -> rpc_request_addr ) {
13481283 return 0 ;
13491284 }
13501285
1351- const u32 safe_len = n > HTTP_BODY_MAX_LEN ? HTTP_BODY_MAX_LEN : n ;
1352- if (!read_go_str_n ("http body" , (void * )invocation -> body_addr , n , body_buf , safe_len )) {
1353- bpf_dbg_printk ("failed to read body, n=%llu, body_addr=%llx" , n , invocation -> body_addr );
1354- return 0 ;
1355- }
1356- // bpf_dbg_printk("body is %s", body_buf);
1357- bpf_tail_call (ctx , & jsonrpc_jump_table , k_tail_jsonrpc );
1358- return 0 ;
1359- }
1286+ off_table_t * ot = get_offsets_table ();
13601287
1361- //k_tail_jsonrpc
1362- SEC ("uprobe/readJsonrpcMethod" )
1363- int obi_read_jsonrpc_method (struct pt_regs * ctx ) {
1364- bpf_dbg_printk ("=== uprobe/proc read jsonrpc method === " );
1365- void * goroutine_addr = GOROUTINE_PTR (ctx );
1366- go_addr_key_t g_key = {};
1367- go_addr_key_from_id (& g_key , goroutine_addr );
1288+ const u64 rpc_request_addr = invocation -> rpc_request_addr ;
13681289
1369- server_http_func_invocation_t * invocation =
1370- bpf_map_lookup_elem (& ongoing_http_server_requests , & g_key );
1371- if (!invocation ) {
1372- bpf_dbg_printk ("can't find invocation info for server call" );
1290+ bpf_dbg_printk ("rpc_request_addr %llx" , rpc_request_addr );
1291+
1292+ const u64 method_len = peek_go_str_len (
1293+ "JSON-RPC method" ,
1294+ (void * )rpc_request_addr ,
1295+ go_offset_of (ot , (go_offset ){.v = _jsonrpc_request_header_service_method_pos }));
1296+
1297+ if (method_len == 0 ) {
13731298 return 0 ;
13741299 }
13751300
1376- // tail call is guaranteed to run on the same CPU as its caller
1377- // so we can shared the same buffer via a per-CPU map
1378- unsigned char * body_buf = temp_body_mem ();
1379- if (!body_buf ) {
1301+ if (!read_go_str ("JSON-RPC method" ,
1302+ (void * )rpc_request_addr ,
1303+ go_offset_of (ot , (go_offset ){.v = _jsonrpc_request_header_service_method_pos }),
1304+ invocation -> method ,
1305+ METHOD_MAX_LEN )) {
1306+ bpf_dbg_printk ("Failed to read JSON-RPC method from %llx" , rpc_request_addr );
13801307 return 0 ;
13811308 }
1382- if (is_jsonrpc2_body ((const unsigned char * )body_buf , HTTP_BODY_MAX_LEN )) {
1383- unsigned char method_buf [JSONRPC_METHOD_BUF_SIZE ] = {};
1384- u32 method_len = extract_jsonrpc2_method (
1385- (const unsigned char * )body_buf , HTTP_BODY_MAX_LEN , method_buf , sizeof (method_buf ));
1386- if (method_len > 0 ) {
1387- bpf_dbg_printk ("JSON-RPC method: %s" , method_buf );
1388- read_go_str_n ("JSON-RPC method" ,
1389- (void * )method_buf ,
1390- method_len ,
1391- invocation -> method ,
1392- sizeof (invocation -> method ));
1393- }
1394- }
1309+ bpf_dbg_printk ("read jsonrpc method %s" , invocation -> method );
1310+
13951311 return 0 ;
13961312}
13971313
0 commit comments