diff --git a/trunk/configure b/trunk/configure index 5172a18ba..ed71ea623 100755 --- a/trunk/configure +++ b/trunk/configure @@ -228,7 +228,7 @@ MODULE_FILES=("srs_protocol_amf0" "srs_protocol_io" "srs_protocol_conn" "srs_pro "srs_protocol_rtmp_stack" "srs_protocol_utility" "srs_protocol_rtmp_msg_array" "srs_protocol_stream" "srs_protocol_raw_avc" "srs_protocol_rtsp_stack" "srs_protocol_http_stack" "srs_protocol_kbps" "srs_protocol_json" "srs_protocol_format" "srs_protocol_log" "srs_protocol_st" "srs_protocol_http_client" - "srs_protocol_http_conn" "srs_protocol_rtmp_conn") + "srs_protocol_http_conn" "srs_protocol_rtmp_conn" "srs_protocol_protobuf") if [[ $SRS_SRT == YES ]]; then MODULE_FILES+=("srs_protocol_srt") ModuleLibIncs+=(${LibSRTRoot}) diff --git a/trunk/src/app/srs_app_tencentcloud.cpp b/trunk/src/app/srs_app_tencentcloud.cpp index 130f2d19a..f493d9694 100644 --- a/trunk/src/app/srs_app_tencentcloud.cpp +++ b/trunk/src/app/srs_app_tencentcloud.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -159,161 +160,11 @@ namespace tencentcloud_api_sign { } } -// See https://developers.google.com/protocol-buffers/docs/encoding#varints -class SrsProtobufVarints -{ -private: - // See Go bits.Len64 of package math/bits. - static int bits_len64(uint64_t x) { - // See Go bits.len8tab of package math/bits. - static uint8_t bits_len8tab[256] = { - 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - }; - - int n = 0; - if (x >= (uint64_t)1<<32) { - x >>= 32; - n = 32; - } - if (x >= (uint64_t)1<<16) { - x >>= 16; - n += 16; - } - if (x >= (uint64_t)1<<8) { - x >>= 8; - n += 8; - } - return n + int(bits_len8tab[x]); - } -public: - // See Go protowire.SizeVarint of package google.golang.org/protobuf/encoding/protowire - static int sizeof_varint(uint64_t v) { - int n = bits_len64(v); - return int(9 * uint32_t(n) + 64) / 64; - } - // See Go protowire.AppendVarint of package google.golang.org/protobuf/encoding/protowire - static srs_error_t encode(SrsBuffer* b, uint64_t v) { - srs_error_t err = srs_success; - - if (!b->require(SrsProtobufVarints::sizeof_varint(v))) { - return srs_error_new(ERROR_PB_NO_SPACE, "require %d only %d bytes", v, b->left()); - } - - if (v < (uint64_t)1<<7) { - b->write_1bytes((uint8_t)v); - } else if (v < (uint64_t)1<<14) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>7)); - } else if (v < (uint64_t)1<<21) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>21)); - } else if (v < (uint64_t)1<<35) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>28)); - } else if (v < (uint64_t)1<<42) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>35)); - } else if (v < (uint64_t)1<<49) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>42)); - } else if(v < (uint64_t)1<<56) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>42)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>49)); - } else if (v < (uint64_t)1<<63) { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>42)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>49)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(v>>56)); - } else { - b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>42)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>49)&0x7f)|0x80)); - b->write_1bytes((uint8_t)(((v>>56)&0x7f)|0x80)); - b->write_1bytes((uint8_t)1); - } - - return err; - } -}; - -class SrsProtobufString -{ -public: - // See Go protowire.SizeBytes of package google.golang.org/protobuf/encoding/protowire - static int sizeof_string(const std::string& v) { - uint64_t n = v.length(); - return SrsProtobufVarints::sizeof_varint(uint64_t(n)) + n; - } - // See Go protowire.AppendString of package google.golang.org/protobuf/encoding/protowire - static srs_error_t encode(SrsBuffer* b, const std::string& v) { - srs_error_t err = srs_success; - - uint64_t n = v.length(); - if ((err = SrsProtobufVarints::encode(b, n)) != srs_success) { - return srs_error_wrap(err, "string size %d", n); - } - - if (!b->require(n)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require %d only %d byte", n, b->left()); - } - b->write_string(v); - - return err; - } -}; - // See https://cloud.tencent.com/document/api/614/16873 -class SrsClsLogContent +class SrsClsLogContent : public ISrsEncoder { private: - // required string key = 1; std::string key_; - // required string value = 2; std::string value_; public: SrsClsLogContent(); @@ -327,12 +178,10 @@ public: }; // See https://cloud.tencent.com/document/api/614/16873 -class SrsClsLog +class SrsClsLog : public ISrsEncoder { private: - // required int64 time = 1; int64_t time_; - // repeated Content contents= 2; std::vector contents_; public: SrsClsLog(); @@ -346,12 +195,10 @@ public: }; // See https://cloud.tencent.com/document/api/614/16873 -class SrsClsLogGroup +class SrsClsLogGroup : public ISrsEncoder { private: - // repeated Log logs= 1; std::vector logs_; - // optional string source = 4; std::string source_; public: SrsClsLogGroup(); @@ -368,7 +215,6 @@ public: class SrsClsLogGroupList { private: - // repeated LogGroup logGroupList = 1; std::vector groups_; public: SrsClsLogGroupList(); @@ -402,8 +248,8 @@ SrsClsLogContent* SrsClsLogContent::set_value(std::string v) uint64_t SrsClsLogContent::nb_bytes() { - uint64_t nn = 1 + SrsProtobufString::sizeof_string(key_); - nn += 1 + SrsProtobufString::sizeof_string(value_); + uint64_t nn = SrsProtobufKey::sizeof_key() + SrsProtobufString::sizeof_string(key_); + nn += SrsProtobufKey::sizeof_key() + SrsProtobufString::sizeof_string(value_); return nn; } @@ -411,21 +257,19 @@ srs_error_t SrsClsLogContent::encode(SrsBuffer* b) { srs_error_t err = srs_success; - // Encode the field key as [ID=1, TYPE=2(Length delimited)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); + // required string key = 1; + if ((err = SrsProtobufKey::encode(b, 1, SrsProtobufFieldString)) != srs_success) { + return srs_error_wrap(err, "key"); } - b->write_1bytes(0x0a); if ((err = SrsProtobufString::encode(b, key_)) != srs_success) { return srs_error_wrap(err, "encode key=%s", key_.c_str()); } - // Encode the field value as [ID=2, TYPE=2(Length delimited)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); + // required string value = 2; + if ((err = SrsProtobufKey::encode(b, 2, SrsProtobufFieldString)) != srs_success) { + return srs_error_wrap(err, "key"); } - b->write_1bytes(0x12); if ((err = SrsProtobufString::encode(b, value_)) != srs_success) { return srs_error_wrap(err, "encode value=%s", value_.c_str()); @@ -461,12 +305,11 @@ SrsClsLog* SrsClsLog::set_time(int64_t v) uint64_t SrsClsLog::nb_bytes() { - uint64_t nn = 1 + SrsProtobufVarints::sizeof_varint(time_); + uint64_t nn = SrsProtobufKey::sizeof_key() + SrsProtobufVarints::sizeof_varint(time_); for (std::vector::iterator it = contents_.begin(); it != contents_.end(); ++it) { SrsClsLogContent* content = *it; - uint64_t size = content->nb_bytes(); - nn += 1 + SrsProtobufVarints::sizeof_varint(size) + size; + nn += SrsProtobufKey::sizeof_key() + SrsProtobufObject::sizeof_object(content); } return nn; @@ -476,11 +319,10 @@ srs_error_t SrsClsLog::encode(SrsBuffer* b) { srs_error_t err = srs_success; - // Encode the field time as [ID=1, TYPE=0(Varint)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); + // required int64 time = 1; + if ((err = SrsProtobufKey::encode(b, 1, SrsProtobufFieldVarint)) != srs_success) { + return srs_error_wrap(err, "key"); } - b->write_1bytes(0x08); if ((err = SrsProtobufVarints::encode(b, time_)) != srs_success) { return srs_error_wrap(err, "encode time"); @@ -490,20 +332,12 @@ srs_error_t SrsClsLog::encode(SrsBuffer* b) for (std::vector::iterator it = contents_.begin(); it != contents_.end(); ++it) { SrsClsLogContent* content = *it; - // Encode the field contents as [ID=2, TYPE=2(Length delimited)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); - } - b->write_1bytes(0x12); - - // Encode the varint size of children. - uint64_t size = content->nb_bytes(); - if ((err = SrsProtobufVarints::encode(b, size)) != srs_success) { - return srs_error_wrap(err, "encode size=%d", (int)size); + // repeated Content contents= 2; + if ((err = SrsProtobufKey::encode(b, 2, SrsProtobufFieldObject)) != srs_success) { + return srs_error_wrap(err, "key"); } - // Encode the content itself. - if ((err = content->encode(b)) != srs_success) { + if ((err = SrsProtobufObject::encode(b, content)) != srs_success) { return srs_error_wrap(err, "encode content"); } } @@ -541,11 +375,10 @@ uint64_t SrsClsLogGroup::nb_bytes() uint64_t nn = 0; for (std::vector::iterator it = logs_.begin(); it != logs_.end(); ++it) { SrsClsLog* log = *it; - uint64_t size = log->nb_bytes(); - nn += 1 + SrsProtobufVarints::sizeof_varint(size) + size; + nn += SrsProtobufKey::sizeof_key() + SrsProtobufObject::sizeof_object(log); } - nn += 1 + SrsProtobufString::sizeof_string(source_); + nn += SrsProtobufKey::sizeof_key() + SrsProtobufString::sizeof_string(source_); return nn; } @@ -557,29 +390,20 @@ srs_error_t SrsClsLogGroup::encode(SrsBuffer* b) for (std::vector::iterator it = logs_.begin(); it != logs_.end(); ++it) { SrsClsLog* log = *it; - // Encode the field logs as [ID=1, TYPE=2(Length delimited)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); + // repeated Log logs= 1; + if ((err = SrsProtobufKey::encode(b, 1, SrsProtobufFieldObject)) != srs_success) { + return srs_error_wrap(err, "key"); } - b->write_1bytes(0x0a); - // Encode the varint size of children. - uint64_t size = log->nb_bytes(); - if ((err = SrsProtobufVarints::encode(b, size)) != srs_success) { - return srs_error_wrap(err, "encode size=%d", (int)size); - } - - // Encode the log itself. - if ((err = log->encode(b)) != srs_success) { + if ((err = SrsProtobufObject::encode(b, log)) != srs_success) { return srs_error_wrap(err, "encode log"); } } - // Encode the field source as [ID=4, TYPE=2(Length delimited)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); + // optional string source = 4; + if ((err = SrsProtobufKey::encode(b, 4, SrsProtobufFieldString)) != srs_success) { + return srs_error_wrap(err, "key"); } - b->write_1bytes(0x22); if ((err = SrsProtobufString::encode(b, source_)) != srs_success) { return srs_error_wrap(err, "encode source=%s", source_.c_str()); @@ -612,8 +436,7 @@ uint64_t SrsClsLogGroupList::nb_bytes() uint64_t nn = 0; for (std::vector::iterator it = groups_.begin(); it != groups_.end(); ++it) { SrsClsLogGroup* group = *it; - uint64_t size = group->nb_bytes(); - nn += 1 + SrsProtobufVarints::sizeof_varint(size) + size; + nn += SrsProtobufKey::sizeof_key() + SrsProtobufObject::sizeof_object(group); } return nn; } @@ -626,20 +449,12 @@ srs_error_t SrsClsLogGroupList::encode(SrsBuffer* b) for (std::vector::iterator it = groups_.begin(); it != groups_.end(); ++it) { SrsClsLogGroup* group = *it; - // Encode the field groups as [ID=1, TYPE=2(Length delimited)] - if (!b->require(1)) { - return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); - } - b->write_1bytes(0x0a); - - // Encode the varint size of children. - uint64_t size = group->nb_bytes(); - if ((err = SrsProtobufVarints::encode(b, size)) != srs_success) { - return srs_error_wrap(err, "encode size=%d", (int)size); + // repeated LogGroup logGroupList = 1; + if ((err = SrsProtobufKey::encode(b, 1, SrsProtobufFieldLengthDelimited)) != srs_success) { + return srs_error_wrap(err, "key"); } - // Encode the log group itself. - if ((err = group->encode(b)) != srs_success) { + if ((err = SrsProtobufObject::encode(b, group)) != srs_success) { return srs_error_wrap(err, "encode group"); } } diff --git a/trunk/src/kernel/srs_kernel_buffer.cpp b/trunk/src/kernel/srs_kernel_buffer.cpp index 35ed97787..b4ac382fb 100644 --- a/trunk/src/kernel/srs_kernel_buffer.cpp +++ b/trunk/src/kernel/srs_kernel_buffer.cpp @@ -339,6 +339,10 @@ void SrsBuffer::write_le8bytes(int64_t value) void SrsBuffer::write_string(string value) { + if (value.empty()) { + return; + } + srs_assert(require((int)value.length())); memcpy(p, value.data(), value.length()); @@ -347,6 +351,10 @@ void SrsBuffer::write_string(string value) void SrsBuffer::write_bytes(char* data, int size) { + if (size <= 0) { + return; + } + srs_assert(require(size)); memcpy(p, data, size); diff --git a/trunk/src/protocol/srs_protocol_protobuf.cpp b/trunk/src/protocol/srs_protocol_protobuf.cpp new file mode 100644 index 000000000..ae5812372 --- /dev/null +++ b/trunk/src/protocol/srs_protocol_protobuf.cpp @@ -0,0 +1,210 @@ +// +// Copyright (c) 2013-2022 The SRS Authors +// +// SPDX-License-Identifier: MIT or MulanPSL-2.0 +// + +#include + +#include +#include + +using namespace std; + +// See Go bits.Len64 of package math/bits. +int SrsProtobufVarints::bits_len64(uint64_t x) +{ + // See Go bits.len8tab of package math/bits. + static uint8_t bits_len8tab[256] = { + 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + }; + + int n = 0; + if (x >= (uint64_t)1<<32) { + x >>= 32; + n = 32; + } + if (x >= (uint64_t)1<<16) { + x >>= 16; + n += 16; + } + if (x >= (uint64_t)1<<8) { + x >>= 8; + n += 8; + } + return n + int(bits_len8tab[x]); +} + +// See Go protowire.SizeVarint of package google.golang.org/protobuf/encoding/protowire +int SrsProtobufVarints::sizeof_varint(uint64_t v) +{ + int n = bits_len64(v); + return int(9 * uint32_t(n) + 64) / 64; +} + +// See Go protowire.AppendVarint of package google.golang.org/protobuf/encoding/protowire +srs_error_t SrsProtobufVarints::encode(SrsBuffer* b, uint64_t v) +{ + srs_error_t err = srs_success; + + if (!b->require(SrsProtobufVarints::sizeof_varint(v))) { + return srs_error_new(ERROR_PB_NO_SPACE, "require %d only %d bytes", v, b->left()); + } + + if (v < (uint64_t)1<<7) { + b->write_1bytes((uint8_t)v); + } else if (v < (uint64_t)1<<14) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>7)); + } else if (v < (uint64_t)1<<21) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>14)); + } else if (v < (uint64_t)1<<28) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>21)); + } else if (v < (uint64_t)1<<35) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>28)); + } else if (v < (uint64_t)1<<42) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>35)); + } else if (v < (uint64_t)1<<49) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>42)); + } else if(v < (uint64_t)1<<56) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>42)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>49)); + } else if (v < (uint64_t)1<<63) { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>42)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>49)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(v>>56)); + } else { + b->write_1bytes((uint8_t)(((v>>0)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>7)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>14)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>21)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>28)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>35)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>42)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>49)&0x7f)|0x80)); + b->write_1bytes((uint8_t)(((v>>56)&0x7f)|0x80)); + b->write_1bytes((uint8_t)1); + } + + return err; +} + +// See Go protowire.SizeBytes of package google.golang.org/protobuf/encoding/protowire +int SrsProtobufString::sizeof_string(const std::string& v) +{ + uint64_t n = v.length(); + return SrsProtobufVarints::sizeof_varint(uint64_t(n)) + n; +} + +// See Go protowire.AppendString of package google.golang.org/protobuf/encoding/protowire +srs_error_t SrsProtobufString::encode(SrsBuffer* b, const std::string& v) +{ + srs_error_t err = srs_success; + + uint64_t n = v.length(); + if ((err = SrsProtobufVarints::encode(b, n)) != srs_success) { + return srs_error_wrap(err, "string size %d", n); + } + + // Ignore content if empty. + if (v.empty()) { + return err; + } + + if (!b->require(n)) { + return srs_error_new(ERROR_PB_NO_SPACE, "require %d only %d byte", n, b->left()); + } + b->write_string(v); + + return err; +} + +int SrsProtobufObject::sizeof_object(ISrsEncoder* obj) +{ + uint64_t size = obj->nb_bytes(); + return SrsProtobufVarints::sizeof_varint(size) + size; +} +srs_error_t SrsProtobufObject::encode(SrsBuffer* b, ISrsEncoder* obj) +{ + srs_error_t err = srs_success; + + // Encode the varint size of children. + uint64_t size = obj->nb_bytes(); + if ((err = SrsProtobufVarints::encode(b, size)) != srs_success) { + return srs_error_wrap(err, "encode size=%d", (int)size); + } + + // Encode the log group itself. + if ((err = obj->encode(b)) != srs_success) { + return srs_error_wrap(err, "encode group"); + } + + return err; +} + +int SrsProtobufKey::sizeof_key() +{ + return 1; +} + +srs_error_t SrsProtobufKey::encode(SrsBuffer* b, uint8_t fieldId, SrsProtobufField fieldType) +{ + srs_error_t err = srs_success; + + if (!b->require(1)) { + return srs_error_new(ERROR_PB_NO_SPACE, "require 1 byte"); + } + + uint8_t v = (fieldId << 3) | uint8_t(fieldType); + b->write_1bytes(v); + + return err; +} + diff --git a/trunk/src/protocol/srs_protocol_protobuf.hpp b/trunk/src/protocol/srs_protocol_protobuf.hpp new file mode 100644 index 000000000..b5f881c6b --- /dev/null +++ b/trunk/src/protocol/srs_protocol_protobuf.hpp @@ -0,0 +1,107 @@ +// +// Copyright (c) 2013-2022 The SRS Authors +// +// SPDX-License-Identifier: MIT or MulanPSL-2.0 +// + +#ifndef SRS_PROTOCOL_PROTOBUF_HPP +#define SRS_PROTOCOL_PROTOBUF_HPP + +#include + +#include + +class SrsBuffer; +class ISrsEncoder; + +// See https://developers.google.com/protocol-buffers/docs/encoding#varints +class SrsProtobufVarints +{ +private: + static int bits_len64(uint64_t x); +public: + static int sizeof_varint(uint64_t v); + static srs_error_t encode(SrsBuffer* b, uint64_t v); +}; + +// See https://developers.google.com/protocol-buffers/docs/encoding#strings +class SrsProtobufString +{ +public: + static int sizeof_string(const std::string& v); + static srs_error_t encode(SrsBuffer* b, const std::string& v); +}; + +// For embeded messages and packed repeated fields, see usage of SrsProtobufKey. +class SrsProtobufObject +{ +public: + static int sizeof_object(ISrsEncoder* obj); + static srs_error_t encode(SrsBuffer* b, ISrsEncoder* obj); +}; + +// See https://developers.google.com/protocol-buffers/docs/encoding#structure +enum SrsProtobufField +{ + // For int32, int64, uint32, uint64, sint32, sint64, bool, enum + SrsProtobufFieldVarint = 0, + // For fixed64, sfixed64, double + SrsProtobufField64bit = 1, + // For string, bytes, embedded messages, packed repeated fields + SrsProtobufFieldString = 2, + SrsProtobufFieldBytes = 2, + SrsProtobufFieldObject = 2, + SrsProtobufFieldLengthDelimited = 2, + // For fixed32, sfixed32, float + SrsProtobufField32bit = 5, +}; + +// See https://developers.google.com/protocol-buffers/docs/encoding#structure +// See https://cloud.tencent.com/document/api/614/16873 +// +//////////////////////////////////////////////////////////////////////////////// +// If key is string, for example: +// message Content { +// required string value = 2; +// } +// We can get the size of value: +// SrsProtobufKey::sizeof_key() + SrsProtobufString::sizeof_string(value_) +// And marshal as: +// SrsProtobufKey::encode(b, 2, SrsProtobufFieldString) +// SrsProtobufString::encode(b, value_) +// +//////////////////////////////////////////////////////////////////////////////// +// If key is varints, for example: +// message Log { +// required int64 time = 1; +// } +// We can get the size of logs: +// SrsProtobufKey::sizeof_key() + SrsProtobufVarints::sizeof_varint(time_) +// And marshal as: +// SrsProtobufKey::encode(b, 1, SrsProtobufFieldVarint) +// SrsProtobufVarints::encode(b, time_) +// +//////////////////////////////////////////////////////////////////////////////// +// If key is object(or embeded message, or packed repeated fields), for example: +// message LogGroupList { +// repeated LogGroup logGroupList = 1; +// } +// We can get the size of logs: +// for group in vector: +// size += SrsProtobufKey::sizeof_key() + SrsProtobufObject::sizeof_object(group) +// And marshal as: +// for group in vector: +// SrsProtobufKey::encode(b, 1, SrsProtobufFieldLengthDelimited) +// SrsProtobufObject::encode(b, group) +// Note that there is always a key and length for each repeat object. +class SrsProtobufKey +{ +public: + static int sizeof_key(); + // Each key in the streamed message is a varint with the value (field_number << 3) | wire_type – in other words, + // the last three bits of the number store the wire type. + static srs_error_t encode(SrsBuffer* b, uint8_t fieldId, SrsProtobufField fieldType); +}; + +#endif + diff --git a/trunk/src/utest/srs_utest_protocol.cpp b/trunk/src/utest/srs_utest_protocol.cpp index b63cf66fe..be24a46ee 100644 --- a/trunk/src/utest/srs_utest_protocol.cpp +++ b/trunk/src/utest/srs_utest_protocol.cpp @@ -17,6 +17,8 @@ using namespace std; #include #include #include +#include +#include MockEmptyIO::MockEmptyIO() { @@ -6455,3 +6457,251 @@ VOID TEST(ProtocolKbpsTest, WriteLargeIOVs) } } +VOID TEST(ProtocolProtobufTest, VarintsSize) +{ + EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x00)); + EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x70)); + EXPECT_EQ(1, SrsProtobufVarints::sizeof_varint( 0x7f)); + EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x80)); + EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x3ff0)); + EXPECT_EQ(2, SrsProtobufVarints::sizeof_varint( 0x3fff)); + EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x4000)); + EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x1ffff0)); + EXPECT_EQ(3, SrsProtobufVarints::sizeof_varint( 0x1fffff)); + EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x200000)); + EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x0ffffff0)); + EXPECT_EQ(4, SrsProtobufVarints::sizeof_varint( 0x0fffffff)); + EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x10000000)); + EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x7fffffff0)); + EXPECT_EQ(5, SrsProtobufVarints::sizeof_varint( 0x7ffffffff)); + EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x800000000)); + EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x3fffffffff0)); + EXPECT_EQ(6, SrsProtobufVarints::sizeof_varint( 0x3ffffffffff)); + EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x40000000000)); + EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x1fffffffffff0)); + EXPECT_EQ(7, SrsProtobufVarints::sizeof_varint( 0x1ffffffffffff)); + EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x2000000000000)); + EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x0fffffffffffff0)); + EXPECT_EQ(8, SrsProtobufVarints::sizeof_varint( 0x0ffffffffffffff)); + EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x100000000000000)); + EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x7ffffffffffffff0)); + EXPECT_EQ(9, SrsProtobufVarints::sizeof_varint( 0x7fffffffffffffff)); + EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0x8000000000000000)); + EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0xfffffffffffffff0)); + EXPECT_EQ(10, SrsProtobufVarints::sizeof_varint(0xffffffffffffffff)); +} + +VOID TEST(ProtocolProtobufTest, VarintsEncode) +{ + srs_error_t err = srs_success; + static char buf[128]; + + if (true) { + SrsBuffer b(buf, 1); uint8_t expect[] = {0x00}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 1); uint8_t expect[] = {0x70}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x70)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 1); uint8_t expect[] = {0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7f)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 2); uint8_t expect[] = {0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x80)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 2); uint8_t expect[] = {0xf0, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3ff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 2); uint8_t expect[] = {0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3fff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 3); uint8_t expect[] = {0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x4000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 3); uint8_t expect[] = {0xf0, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1ffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 3); uint8_t expect[] = {0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1fffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 4); uint8_t expect[] = {0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x200000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 4); uint8_t expect[] = {0xf0, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 4); uint8_t expect[] = {0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 5); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x10000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 5); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7fffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 5); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7ffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 6); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x800000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 6); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3fffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 6); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x3ffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 7); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x40000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 7); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1fffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 7); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x1ffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 8); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x2000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 8); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 8); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 9); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x100000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 9); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7ffffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 9); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x7fffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 10); uint8_t expect[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0x8000000000000000)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 10); uint8_t expect[] = {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xfffffffffffffff0)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } + if (true) { + SrsBuffer b(buf, 10); uint8_t expect[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}; + HELPER_ASSERT_SUCCESS(SrsProtobufVarints::encode(&b, 0xffffffffffffffff)); EXPECT_TRUE(srs_bytes_equals(buf, (char*)expect, sizeof(expect))); + } +} + +VOID TEST(ProtocolProtobufTest, String) +{ + srs_error_t err = srs_success; + static char buf[128]; + + if (true) { + EXPECT_EQ(1 + 10, SrsProtobufString::sizeof_string("HelloWorld")); + + SrsBuffer b(buf, 1 + 10); + HELPER_ASSERT_SUCCESS(SrsProtobufString::encode(&b, "HelloWorld")); + + uint8_t expect[] = {0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64}; + EXPECT_TRUE(srs_bytes_equals(buf, (char *) expect, sizeof(expect))); + } + + if (true) { + EXPECT_EQ(1, SrsProtobufString::sizeof_string("")); + + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufString::encode(&b, "")); + + uint8_t expect[] = {0x00}; + EXPECT_TRUE(srs_bytes_equals(buf, (char *) expect, sizeof(expect))); + } +} + +class MockProtobufObject : public ISrsEncoder +{ +public: + uint64_t nb_bytes() { + return 1; + } + srs_error_t encode(SrsBuffer* b) { + b->write_1bytes(0x0f); + return srs_success; + } +}; + +VOID TEST(ProtocolProtobufTest, FieldKey) +{ + srs_error_t err = srs_success; + static char buf[128]; + + EXPECT_EQ(2, SrsProtobufFieldString); + EXPECT_EQ(2, SrsProtobufFieldBytes); + EXPECT_EQ(2, SrsProtobufFieldObject); + EXPECT_EQ(2, SrsProtobufFieldLengthDelimited); + + EXPECT_EQ(1, SrsProtobufKey::sizeof_key()); + + MockProtobufObject obj; + EXPECT_EQ(2, SrsProtobufObject::sizeof_object(&obj)); + if (true) { + SrsBuffer b(buf, 2); + HELPER_ASSERT_SUCCESS(SrsProtobufObject::encode(&b, &obj)); + EXPECT_EQ(0x01, buf[0]); EXPECT_EQ(0x0f, buf[1]); + } + + // Encode the field key as [ID=1, TYPE=2(Length delimited)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 1, SrsProtobufFieldLengthDelimited)); + EXPECT_EQ(0x0a, buf[0]); + } + + // Encode the field value as [ID=2, TYPE=2(Length delimited)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 2, SrsProtobufFieldLengthDelimited)); + EXPECT_EQ(0x12, buf[0]); + } + + // Encode the field time as [ID=1, TYPE=0(Varint)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 1, SrsProtobufFieldVarint)); + EXPECT_EQ(0x08, buf[0]); + } + + // Encode the field source as [ID=4, TYPE=2(Length delimited)] + if (true) { + SrsBuffer b(buf, 1); + HELPER_ASSERT_SUCCESS(SrsProtobufKey::encode(&b, 4, SrsProtobufFieldLengthDelimited)); + EXPECT_EQ(0x22, buf[0]); + } +} +