mirror of
https://github.com/apache/thrift.git
synced 2026-10-28 16:35:10 +08:00
Client: lua The binary, compact and JSON protocols refused only a negative list, set or map size, and the generated code reads one element per declared element. Lua has no MaxMessageSize that would bound the count otherwise, so the new limit gets a finite default instead of the "no limit of its own" default THRIFT-6291 gives MaxContainerSize. - TProtocol.lua: DEFAULT_MAX_CONTAINER_SIZE = 16384000, the value of the string and frame size limits, and TProtocolBase:checkContainerSize(). maxContainerSize on a protocol instance overrides the default; zero or less switches the limit off. - readListBegin, readSetBegin and readMapBegin of TBinaryProtocol, TCompactProtocol and TJSONProtocol call it before any element is read. - doc/specs/thrift-tconfiguration.md records the finite Lua default and the reason. - test/test_container_limits.lua covers the three protocols for list, set and map, at the limit and one over it, the default, the off values and skip. Its pure-Lua stand-in for libluabpack gains the int8_t wrap of 'c' and toVarint32, which the compact protocol needs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
316 lines
7.4 KiB
Lua
316 lines
7.4 KiB
Lua
--
|
|
-- Licensed to the Apache Software Foundation (ASF) under one
|
|
-- or more contributor license agreements. See the NOTICE file
|
|
-- distributed with this work for additional information
|
|
-- regarding copyright ownership. The ASF licenses this file
|
|
-- to you under the Apache License, Version 2.0 (the
|
|
-- "License"); you may not use this file except in compliance
|
|
-- with the License. You may obtain a copy of the License at
|
|
--
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
|
--
|
|
-- Unless required by applicable law or agreed to in writing,
|
|
-- software distributed under the License is distributed on an
|
|
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
-- KIND, either express or implied. See the License for the
|
|
-- specific language governing permissions and limitations
|
|
-- under the License.
|
|
--
|
|
|
|
require 'TProtocol'
|
|
local libluabpack = require 'libluabpack'
|
|
local libluabitwise = require 'libluabitwise'
|
|
|
|
TBinaryProtocol = __TObject.new(TProtocolBase, {
|
|
__type = 'TBinaryProtocol',
|
|
VERSION_MASK = -65536, -- 0xffff0000
|
|
VERSION_1 = -2147418112, -- 0x80010000
|
|
TYPE_MASK = 0x000000ff,
|
|
strictRead = false,
|
|
strictWrite = true
|
|
})
|
|
|
|
function TBinaryProtocol:writeMessageBegin(name, ttype, seqid)
|
|
if self.strictWrite then
|
|
self:writeI32(libluabitwise.bor(TBinaryProtocol.VERSION_1, ttype))
|
|
self:writeString(name)
|
|
self:writeI32(seqid)
|
|
else
|
|
self:writeString(name)
|
|
self:writeByte(ttype)
|
|
self:writeI32(seqid)
|
|
end
|
|
end
|
|
|
|
function TBinaryProtocol:writeMessageEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:writeStructBegin(name)
|
|
end
|
|
|
|
function TBinaryProtocol:writeStructEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:writeFieldBegin(name, ttype, id)
|
|
self:writeByte(ttype)
|
|
self:writeI16(id)
|
|
end
|
|
|
|
function TBinaryProtocol:writeFieldEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:writeFieldStop()
|
|
self:writeByte(TType.STOP);
|
|
end
|
|
|
|
function TBinaryProtocol:writeMapBegin(ktype, vtype, size)
|
|
self:writeByte(ktype)
|
|
self:writeByte(vtype)
|
|
self:writeI32(size)
|
|
end
|
|
|
|
function TBinaryProtocol:writeMapEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:writeListBegin(etype, size)
|
|
self:writeByte(etype)
|
|
self:writeI32(size)
|
|
end
|
|
|
|
function TBinaryProtocol:writeListEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:writeSetBegin(etype, size)
|
|
self:writeByte(etype)
|
|
self:writeI32(size)
|
|
end
|
|
|
|
function TBinaryProtocol:writeSetEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:writeBool(bool)
|
|
if bool then
|
|
self:writeByte(1)
|
|
else
|
|
self:writeByte(0)
|
|
end
|
|
end
|
|
|
|
function TBinaryProtocol:writeByte(byte)
|
|
local buff = libluabpack.bpack('c', byte)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TBinaryProtocol:writeI16(i16)
|
|
local buff = libluabpack.bpack('s', i16)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TBinaryProtocol:writeI32(i32)
|
|
local buff = libluabpack.bpack('i', i32)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TBinaryProtocol:writeUI32(i32)
|
|
local buff = libluabpack.bpack('I', i32)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TBinaryProtocol:writeI64(i64)
|
|
local buff = libluabpack.bpack('l', i64)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TBinaryProtocol:writeDouble(dub)
|
|
local buff = libluabpack.bpack('d', dub)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TBinaryProtocol:writeString(str)
|
|
-- Should be utf-8
|
|
self:writeI32(string.len(str))
|
|
self.trans:write(str)
|
|
end
|
|
|
|
function TBinaryProtocol:writeUuid(uuid)
|
|
self:writeUI32(uuid.two)
|
|
self:writeUI32(uuid.three)
|
|
self:writeUI32(uuid.zero)
|
|
self:writeUI32(uuid.one)
|
|
end
|
|
|
|
function TBinaryProtocol:readMessageBegin()
|
|
local sz, ttype, name, seqid = self:readI32()
|
|
if sz < 0 then
|
|
local version = libluabitwise.band(sz, TBinaryProtocol.VERSION_MASK)
|
|
if version ~= TBinaryProtocol.VERSION_1 then
|
|
terror(TProtocolException:new{
|
|
message = 'Bad version in readMessageBegin: ' .. sz
|
|
})
|
|
end
|
|
ttype = libluabitwise.band(sz, TBinaryProtocol.TYPE_MASK)
|
|
name = self:readString()
|
|
seqid = self:readI32()
|
|
else
|
|
if self.strictRead then
|
|
terror(TProtocolException:new{message = 'No protocol version header'})
|
|
end
|
|
-- The pre-versioned header names its own length, and it is the first
|
|
-- thing read off a connection. readString() holds every other declared
|
|
-- length to checkStringSize(); this one has to go through it as well.
|
|
self:checkStringSize(sz)
|
|
name = self.trans:readAll(sz)
|
|
ttype = self:readByte()
|
|
seqid = self:readI32()
|
|
end
|
|
return name, ttype, seqid
|
|
end
|
|
|
|
function TBinaryProtocol:readMessageEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:readStructBegin()
|
|
return nil
|
|
end
|
|
|
|
function TBinaryProtocol:readStructEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:readFieldBegin()
|
|
local ttype = self:readByte()
|
|
if ttype == TType.STOP then
|
|
return nil, ttype, 0
|
|
end
|
|
local id = self:readI16()
|
|
return nil, ttype, id
|
|
end
|
|
|
|
function TBinaryProtocol:readFieldEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:readMapBegin()
|
|
local ktype = self:readByte()
|
|
local vtype = self:readByte()
|
|
local size = self:readI32()
|
|
if size < 0 then
|
|
terror(TProtocolException:new{errorCode = TProtocolException.NEGATIVE_SIZE})
|
|
end
|
|
self:checkContainerSize(size)
|
|
return ktype, vtype, size
|
|
end
|
|
|
|
function TBinaryProtocol:readMapEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:readListBegin()
|
|
local etype = self:readByte()
|
|
local size = self:readI32()
|
|
if size < 0 then
|
|
terror(TProtocolException:new{errorCode = TProtocolException.NEGATIVE_SIZE})
|
|
end
|
|
self:checkContainerSize(size)
|
|
return etype, size
|
|
end
|
|
|
|
function TBinaryProtocol:readListEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:readSetBegin()
|
|
local etype = self:readByte()
|
|
local size = self:readI32()
|
|
if size < 0 then
|
|
terror(TProtocolException:new{errorCode = TProtocolException.NEGATIVE_SIZE})
|
|
end
|
|
self:checkContainerSize(size)
|
|
return etype, size
|
|
end
|
|
|
|
function TBinaryProtocol:readSetEnd()
|
|
end
|
|
|
|
function TBinaryProtocol:readBool()
|
|
local byte = self:readByte()
|
|
if byte == 0 then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
function TBinaryProtocol:readByte()
|
|
local buff = self.trans:readAll(1)
|
|
local val = libluabpack.bunpack('c', buff)
|
|
return val
|
|
end
|
|
|
|
function TBinaryProtocol:readI16()
|
|
local buff = self.trans:readAll(2)
|
|
local val = libluabpack.bunpack('s', buff)
|
|
return val
|
|
end
|
|
|
|
function TBinaryProtocol:readI32()
|
|
local buff = self.trans:readAll(4)
|
|
local val = libluabpack.bunpack('i', buff)
|
|
return val
|
|
end
|
|
|
|
function TBinaryProtocol:readUI32()
|
|
local buff = self.trans:readAll(4)
|
|
local val = libluabpack.bunpack('I', buff)
|
|
return val
|
|
end
|
|
|
|
function TBinaryProtocol:readI64()
|
|
local buff = self.trans:readAll(8)
|
|
local val = libluabpack.bunpack('l', buff)
|
|
return val
|
|
end
|
|
|
|
function TBinaryProtocol:readDouble()
|
|
local buff = self.trans:readAll(8)
|
|
local val = libluabpack.bunpack('d', buff)
|
|
return val
|
|
end
|
|
|
|
function TBinaryProtocol:readString()
|
|
local len = self:readI32()
|
|
if len < 0 then
|
|
terror(TProtocolException:new{errorCode = TProtocolException.NEGATIVE_SIZE})
|
|
end
|
|
self:checkStringSize(len)
|
|
local str = self.trans:readAll(len)
|
|
return str
|
|
end
|
|
|
|
function TBinaryProtocol:readUuid()
|
|
local a = self:readUI32()
|
|
local b = self:readUI32()
|
|
local c = self:readUI32()
|
|
local d = self:readUI32()
|
|
return TUUID:new {
|
|
zero = c,
|
|
one = d,
|
|
two = a,
|
|
three = b
|
|
}
|
|
end
|
|
|
|
TBinaryProtocolFactory = TProtocolFactory:new{
|
|
__type = 'TBinaryProtocolFactory',
|
|
strictRead = false
|
|
}
|
|
|
|
function TBinaryProtocolFactory:getProtocol(trans)
|
|
-- TODO Enforce that this must be a transport class (ie not a bool)
|
|
if not trans then
|
|
terror(TProtocolException:new{
|
|
message = 'Must supply a transport to ' .. ttype(self)
|
|
})
|
|
end
|
|
return TBinaryProtocol:new{
|
|
trans = trans,
|
|
strictRead = self.strictRead,
|
|
strictWrite = true
|
|
}
|
|
end
|