summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-grpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-grpc.c')
-rw-r--r--epan/dissectors/packet-grpc.c137
1 files changed, 89 insertions, 48 deletions
diff --git a/epan/dissectors/packet-grpc.c b/epan/dissectors/packet-grpc.c
index a459fde..b71a272 100644
--- a/epan/dissectors/packet-grpc.c
+++ b/epan/dissectors/packet-grpc.c
@@ -136,11 +136,14 @@ static int ett_grpc_message = -1;
static int ett_grpc_encoded_entity = -1;
static dissector_handle_t grpc_handle;
+static dissector_handle_t grpc_web_handle;
+static dissector_handle_t grpc_web_text_handle;
static dissector_handle_t data_text_lines_handle;
/* the information used during dissecting a grpc message */
typedef struct {
gboolean is_request; /* is request or response message */
+ grpc_protocol_type_t proto_type;
const gchar* path; /* is http2 ":path" or http request_uri, format: "/" Service-Name "/" {method name} */
const gchar* content_type; /* is http2 or http content-type, like: application/grpc */
const gchar* encoding; /* is grpc-encoding header containing compressed method, for example "gzip" */
@@ -158,18 +161,6 @@ typedef struct {
*/
static dissector_table_t grpc_message_type_subdissector_table;
-static grpc_protocol_type_t
-get_grpc_protocol_type(const gchar* content_type) {
- if (content_type != NULL) {
- if (g_str_has_prefix(content_type, "application/grpc-web-text")) {
- return GRPC_PTYPE_GRPC_WEB_TEXT;
- } else if (g_str_has_prefix(content_type, "application/grpc-web")) {
- return GRPC_PTYPE_GRPC_WEB;
- }
- }
- return GRPC_PTYPE_GRPC;
-}
-
/* Try to dissect grpc message according to grpc message info or http2 content_type. */
static void
dissect_body_data(proto_tree *grpc_tree, packet_info *pinfo, tvbuff_t *tvb, const gint offset,
@@ -335,13 +326,11 @@ dissect_grpc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, grpc_co
guint32 message_length;
guint offset = 0;
guint tvb_len = tvb_reported_length(tvb);
- grpc_protocol_type_t proto_type;
const gchar* proto_name;
- DISSECTOR_ASSERT_HINT(grpc_ctx && grpc_ctx->content_type && grpc_ctx->path, "The content_type and path of grpc context must be set.");
+ DISSECTOR_ASSERT(grpc_ctx != NULL);
- proto_type = get_grpc_protocol_type(grpc_ctx->content_type);
- proto_name = val_to_str_const(proto_type, grpc_protocol_type_vals, "GRPC");
+ proto_name = val_to_str_const(grpc_ctx->proto_type, grpc_protocol_type_vals, "GRPC");
if (!grpc_embedded_under_http2 && proto_tree_get_parent_tree(tree)) {
tree = proto_tree_get_parent_tree(tree);
@@ -395,41 +384,31 @@ dissect_grpc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, grpc_co
return tvb_captured_length(tvb);
}
-static int
-dissect_grpc(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
+static grpc_context_info_t*
+get_grpc_context(packet_info *pinfo, const media_content_info_t *content_info)
{
- int ret;
http_req_res_t* curr_req_res;
- tvbuff_t* real_data_tvb;
- grpc_context_info_t grpc_ctx = { 0 };
- media_content_info_t* content_info = (media_content_info_t*)data;
- gboolean is_grpc_web_text = g_str_has_prefix(pinfo->match_string, "application/grpc-web-text");
-
- if (is_grpc_web_text) {
- real_data_tvb = base64_tvb_to_new_tvb(tvb, 0, tvb_reported_length(tvb));
- add_new_data_source(pinfo, real_data_tvb, "Decoded base64 body");
- } else {
- real_data_tvb = tvb;
- }
+ grpc_context_info_t* grpc_ctx = wmem_new0(pinfo->pool, grpc_context_info_t);
if (proto_is_frame_protocol(pinfo->layers, "http2")) {
- grpc_ctx.path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, FALSE);
- grpc_ctx.is_request = (grpc_ctx.path != NULL);
- if (grpc_ctx.path == NULL) {
+ grpc_ctx->path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, FALSE);
+ grpc_ctx->is_request = (grpc_ctx->path != NULL);
+ if (grpc_ctx->path == NULL) {
/* this must be response, so we get it from http2 request stream */
- grpc_ctx.path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, TRUE);
+ /* XXX - Not necessarily true if the data has errors. */
+ grpc_ctx->path = http2_get_header_value(pinfo, HTTP2_HEADER_PATH, TRUE);
}
- grpc_ctx.content_type = http2_get_header_value(pinfo, HTTP2_HEADER_CONTENT_TYPE, FALSE);
- grpc_ctx.encoding = http2_get_header_value(pinfo, HTTP2_HEADER_GRPC_ENCODING, FALSE);
+ grpc_ctx->content_type = http2_get_header_value(pinfo, HTTP2_HEADER_CONTENT_TYPE, FALSE);
+ grpc_ctx->encoding = http2_get_header_value(pinfo, HTTP2_HEADER_GRPC_ENCODING, FALSE);
}
else if (proto_is_frame_protocol(pinfo->layers, "http")) {
curr_req_res = (http_req_res_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_http, 0);
DISSECTOR_ASSERT_HINT(curr_req_res && content_info, "Unexpected error: HTTP request/reply or HTTP message info not available.");
- grpc_ctx.is_request = (content_info->type == MEDIA_CONTAINER_HTTP_REQUEST);
- grpc_ctx.path = curr_req_res->request_uri;
- grpc_ctx.content_type = pinfo->match_string; /* only for grpc-web(-text) over http1.1 */
+ grpc_ctx->is_request = (content_info->type == MEDIA_CONTAINER_HTTP_REQUEST);
+ grpc_ctx->path = curr_req_res->request_uri;
+ grpc_ctx->content_type = pinfo->match_string; /* only for grpc-web(-text) over http1.1 */
if (content_info->data) {
- grpc_ctx.encoding = (const gchar*)wmem_map_lookup((wmem_map_t *)content_info->data, HTTP2_HEADER_GRPC_ENCODING);
+ grpc_ctx->encoding = (const gchar*)wmem_map_lookup((wmem_map_t *)content_info->data, HTTP2_HEADER_GRPC_ENCODING);
}
}
else {
@@ -437,13 +416,52 @@ dissect_grpc(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
DISSECTOR_ASSERT_NOT_REACHED();
}
- ret = dissect_grpc_common(real_data_tvb, pinfo, tree, &grpc_ctx);
+ return grpc_ctx;
+}
- if (is_grpc_web_text) {
- /* convert reassembly the lengths of offset and remaining bytes back to the base64 lengths */
- pinfo->desegment_offset = BASE64_ENCODE_SIZE(pinfo->desegment_offset);
- pinfo->desegment_len = BASE64_ENCODE_SIZE(pinfo->desegment_len);
- }
+static int
+dissect_grpc(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
+{
+ grpc_context_info_t* grpc_ctx;
+ media_content_info_t* content_info = (media_content_info_t*)data;
+
+ grpc_ctx = get_grpc_context(pinfo, content_info);
+ grpc_ctx->proto_type = GRPC_PTYPE_GRPC;
+
+ return dissect_grpc_common(tvb, pinfo, tree, grpc_ctx);
+}
+
+static int
+dissect_grpc_web(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
+{
+ grpc_context_info_t* grpc_ctx;
+ media_content_info_t* content_info = (media_content_info_t*)data;
+
+ grpc_ctx = get_grpc_context(pinfo, content_info);
+ grpc_ctx->proto_type = GRPC_PTYPE_GRPC_WEB;
+
+ return dissect_grpc_common(tvb, pinfo, tree, grpc_ctx);
+}
+
+static int
+dissect_grpc_web_text(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
+{
+ int ret;
+ tvbuff_t* real_data_tvb;
+ grpc_context_info_t* grpc_ctx;
+ media_content_info_t* content_info = (media_content_info_t*)data;
+
+ real_data_tvb = base64_tvb_to_new_tvb(tvb, 0, tvb_reported_length(tvb));
+ add_new_data_source(pinfo, real_data_tvb, "Decoded base64 body");
+
+ grpc_ctx = get_grpc_context(pinfo, content_info);
+ grpc_ctx->proto_type = GRPC_PTYPE_GRPC_WEB_TEXT;
+
+ ret = dissect_grpc_common(real_data_tvb, pinfo, tree, grpc_ctx);
+
+ /* convert reassembly the lengths of offset and remaining bytes back to the base64 lengths */
+ pinfo->desegment_offset = BASE64_ENCODE_SIZE(pinfo->desegment_offset);
+ pinfo->desegment_len = BASE64_ENCODE_SIZE(pinfo->desegment_len);
return ret;
}
@@ -525,7 +543,9 @@ proto_register_grpc(void)
expert_grpc = expert_register_protocol(proto_grpc);
expert_register_field_array(expert_grpc, ei, array_length(ei));
- grpc_handle = register_dissector("grpc", dissect_grpc, proto_grpc);
+ grpc_handle = register_dissector_with_description("grpc", "gRPC", dissect_grpc, proto_grpc);
+ grpc_web_handle = register_dissector_with_description("grpc_web", "gRPC Web", dissect_grpc_web, proto_grpc);
+ grpc_web_text_handle = register_dissector_with_description("grpc_web_text", "gRPC Web Text", dissect_grpc_web_text, proto_grpc);
/*
* Dissectors can register themselves in this table as grpc message
@@ -539,17 +559,26 @@ proto_register_grpc(void)
void
proto_reg_handoff_grpc(void)
{
+ int i;
+
char *content_types[] = {
"application/grpc",
"application/grpc+proto",
"application/grpc+json",
+ NULL /* end flag */
+ };
+
+ char *content_types_web[] = {
"application/grpc-web",
"application/grpc-web+proto",
+ NULL /* end flag */
+ };
+
+ char *content_types_web_text[] = {
"application/grpc-web-text",
"application/grpc-web-text+proto",
NULL /* end flag */
};
- int i;
/* register native grpc handler */
for (i = 0; content_types[i]; i++) {
@@ -557,6 +586,18 @@ proto_reg_handoff_grpc(void)
dissector_add_string("media_type", content_types[i], grpc_handle);
}
+ /* register gRPC Web handler */
+ for (i = 0; content_types_web[i]; i++) {
+ dissector_add_string("streaming_content_type", content_types_web[i], grpc_web_handle);
+ dissector_add_string("media_type", content_types_web[i], grpc_web_handle);
+ }
+
+ /* register gRPC Web Text handler */
+ for (i = 0; content_types_web_text[i]; i++) {
+ dissector_add_string("streaming_content_type", content_types_web_text[i], grpc_web_text_handle);
+ dissector_add_string("media_type", content_types_web_text[i], grpc_web_text_handle);
+ }
+
proto_http = proto_get_id_by_filter_name("http");
data_text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_grpc);
}