blob: 59855eb9cb73b9675146320cb3a3d191f11c2e24 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/*
* 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.
*/
import Foundation
public class TFramedTransport: TTransport {
public static let headerSize = 4
public static let initFrameSize = 1024
private static let defaultMaxLength = 16384000
public var transport: TTransport
private var writeBuffer = Data()
private var maxSize = TFramedTransport.defaultMaxLength
private var remainingBytes = 0
public init(transport: TTransport, maxSize: Int) {
self.transport = transport
self.maxSize = maxSize
}
public convenience init(transport: TTransport) {
self.init(transport: transport, maxSize: TFramedTransport.defaultMaxLength)
}
func readHeader() throws {
let read = try transport.readAll(size: TFramedTransport.headerSize)
remainingBytes = Int(decodeFrameSize(data: read))
}
/// Mark: - TTransport
public func read(size: Int) throws -> Data {
while (remainingBytes <= 0) {
try readHeader()
}
let toRead = min(size, remainingBytes)
if toRead < 0 {
try close()
throw TTransportError(error: .negativeSize,
message: "Read a negative frame size (\(toRead))!")
}
if toRead > maxSize {
try close()
throw TTransportError(error: .sizeLimit(limit: maxSize, got: toRead))
}
return try transport.readAll(size: toRead)
}
public func flush() throws {
// copy buffer and reset
let buff = writeBuffer
writeBuffer = Data()
if buff.count - TFramedTransport.headerSize < 0 {
throw TTransportError(error: .unknown)
}
let frameSize = encodeFrameSize(size: UInt32(buff.count))
try transport.write(data: frameSize)
try transport.write(data: buff)
try transport.flush()
}
public func write(data: Data) throws {
writeBuffer.append(data)
}
private func encodeFrameSize(size: UInt32) -> Data {
var data = Data()
data.append(Data([UInt8(0xff & (size >> 24))]))
data.append(Data([UInt8(0xff & (size >> 16))]))
data.append(Data([UInt8(0xff & (size >> 8))]))
data.append(Data([UInt8(0xff & (size))]))
return data
}
private func decodeFrameSize(data: Data) -> UInt32 {
var size: UInt32
size = (UInt32(data[0] & 0xff) << 24)
size |= (UInt32(data[1] & 0xff) << 16)
size |= (UInt32(data[2] & 0xff) << 8)
size |= (UInt32(data[3] & 0xff))
return size
}
public func close() throws {
try transport.close()
}
public func open() throws {
try transport.open()
}
public func isOpen() throws -> Bool {
return try transport.isOpen()
}
}
|