mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Handle more Redis RESP3 protocol pieces
This passes the "minimum protocol version" along in the reply and adds support for attributes, which were added relatively recently.
This commit is contained in:
parent
b34d3ff2f0
commit
64443e5e5a
13 changed files with 115 additions and 30 deletions
|
@ -402,7 +402,9 @@ public function is_hello(data: RESP::ClientData): bool {
|
|||
}
|
||||
|
||||
type ReplyData = struct {
|
||||
value: optional<bytes>;
|
||||
attributes: optional<bytes>;
|
||||
value: bytes;
|
||||
min_protocol_version: uint8;
|
||||
};
|
||||
|
||||
public type ReplyType = enum {
|
||||
|
@ -429,6 +431,25 @@ function bulk_string_content(bulk: RESP::BulkString): bytes {
|
|||
return b"";
|
||||
}
|
||||
|
||||
function stringify_map(data: RESP::Map): bytes {
|
||||
local res = b"{";
|
||||
local first = True;
|
||||
local i = 0;
|
||||
# num_elements refers to the number of map entries, each with 2 entries
|
||||
# in the raw data
|
||||
while (i < data.num_elements) {
|
||||
if (!first)
|
||||
res += b", ";
|
||||
res += stringify(data.raw_data[i * 2]);
|
||||
res += b": ";
|
||||
res += stringify(data.raw_data[(i * 2) + 1]);
|
||||
i += 1;
|
||||
first = False;
|
||||
}
|
||||
res += b"}";
|
||||
return res;
|
||||
}
|
||||
|
||||
# Returns the bytes string value of this, or Null if it cannot.
|
||||
function stringify(data: RESP::Data): bytes {
|
||||
if (data?.simple_string)
|
||||
|
@ -463,20 +484,7 @@ function stringify(data: RESP::Data): bytes {
|
|||
else if (data?.verbatim_string)
|
||||
return bulk_string_content(data.verbatim_string);
|
||||
else if (data?.map_) {
|
||||
local res = b"{";
|
||||
local first = True;
|
||||
local i = 0;
|
||||
while (i < data.map_.num_elements) {
|
||||
if (!first)
|
||||
res += b", ";
|
||||
res += stringify(data.map_.raw_data[i]);
|
||||
res += b": ";
|
||||
res += stringify(data.map_.raw_data[i + 1]);
|
||||
i += 2;
|
||||
first = False;
|
||||
}
|
||||
res += b"}";
|
||||
return res;
|
||||
return stringify_map(data.map_);
|
||||
} else if (data?.set_) {
|
||||
local res = b"(";
|
||||
local first = True;
|
||||
|
@ -506,5 +514,25 @@ function stringify(data: RESP::Data): bytes {
|
|||
|
||||
# Gets the server reply in a simpler form
|
||||
public function make_server_reply(data: RESP::ServerData): ReplyData {
|
||||
return [$value = stringify(data.data)];
|
||||
local min_protocol_version: uint8 = 2;
|
||||
switch (data.data.ty) {
|
||||
case RESP::DataType::NULL,
|
||||
RESP::DataType::BOOLEAN,
|
||||
RESP::DataType::DOUBLE,
|
||||
RESP::DataType::BIG_NUM,
|
||||
RESP::DataType::BULK_ERROR,
|
||||
RESP::DataType::VERBATIM_STRING,
|
||||
RESP::DataType::MAP,
|
||||
RESP::DataType::SET,
|
||||
RESP::DataType::PUSH: min_protocol_version = 3;
|
||||
default: min_protocol_version = 2;
|
||||
}
|
||||
|
||||
local attributes: optional<bytes> = Null;
|
||||
if (data.data?.attributes) {
|
||||
min_protocol_version = 3;
|
||||
attributes = stringify_map(data.data.attributes);
|
||||
}
|
||||
|
||||
return [$attributes = attributes, $value = stringify(data.data), $min_protocol_version = min_protocol_version];
|
||||
}
|
||||
|
|
|
@ -89,6 +89,15 @@ public type ServerData = unit {
|
|||
type Data = unit(depth: uint8&) {
|
||||
%synchronize-after = b"\x0d\x0a";
|
||||
ty: uint8 &convert=DataType($$);
|
||||
|
||||
# Attributes are special, they precede the actual data
|
||||
if (self.ty == DataType::ATTRIBUTE) {
|
||||
attributes: Map(depth);
|
||||
: uint8 &convert=DataType($$) {
|
||||
self.ty = $$;
|
||||
}
|
||||
};
|
||||
|
||||
switch (self.ty) {
|
||||
DataType::SIMPLE_STRING -> simple_string: SimpleString(False);
|
||||
DataType::SIMPLE_ERROR -> simple_error: SimpleString(True);
|
||||
|
@ -135,6 +144,7 @@ type DataType = enum {
|
|||
BULK_ERROR = '!',
|
||||
VERBATIM_STRING = '=',
|
||||
MAP = '%',
|
||||
ATTRIBUTE = '|',
|
||||
SET = '~',
|
||||
PUSH = '>',
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue