@@ -14,6 +14,7 @@ public protocol ConnectionInfoProtocol {
1414
1515enum ConnectionError : Error {
1616 case receiveFailed
17+ case invalidLength
1718}
1819
1920public final class Connection < Handler: StreamHandler > : Sendable , ConnectionInfoProtocol {
@@ -42,26 +43,30 @@ public final class Connection<Handler: StreamHandler>: Sendable, ConnectionInfoP
4243 try ? connection. shutdown ( errorCode: abort ? 1 : 0 ) // TODO: define some error code
4344 }
4445
45- public func request( _ request: Handler . EphemeralHandler . Request ) async throws -> Data {
46+ public func decodeLength( from data: Data ) throws -> UInt32 {
47+ guard data. count >= 4 else {
48+ throw ConnectionError . invalidLength
49+ }
50+ return UInt32 ( littleEndian: data. withUnsafeBytes { $0. loadUnaligned ( as: UInt32 . self) } )
51+ }
52+
53+ public func request( _ request: Handler . EphemeralHandler . Request ) async throws -> [ Data ] {
4654 let data = try request. encode ( )
4755 let kind = request. kind
4856 let stream = try createStream ( kind: kind)
4957 try stream. send ( message: data)
50- // TODO: pipe this to decoder directly to be able to reject early
51- var response = Data ( )
58+
59+ var reps = [ Data ( ) ]
5260 while let nextData = await stream. receive ( ) {
53- response . append ( nextData)
54- break
55- }
56- guard response . count >= 4 else {
57- stream . close ( abort : true )
58- throw ConnectionError . receiveFailed
61+ if nextData. isEmpty { // fin flag
62+ break
63+ }
64+ let length = try decodeLength ( from : nextData . prefix ( 4 ) )
65+ let data = nextData . dropFirst ( 4 ) . prefix ( Int ( length ) )
66+ reps . append ( data )
5967 }
60- let lengthData = response. prefix ( 4 )
61- let length = UInt32 (
62- littleEndian: lengthData. withUnsafeBytes { $0. loadUnaligned ( as: UInt32 . self) }
63- )
64- return response. dropFirst ( 4 ) . prefix ( Int ( length) )
68+
69+ return reps
6570 }
6671
6772 @discardableResult
@@ -121,7 +126,6 @@ public final class Connection<Handler: StreamHandler>: Sendable, ConnectionInfoP
121126 return
122127 }
123128 if let upKind = Handler . PresistentHandler. StreamKind ( rawValue: byte) {
124- // TODO: handle duplicated UP streams
125129 presistentStreams. write { presistentStreams in
126130 presistentStreams [ upKind] = stream
127131 }
@@ -134,25 +138,20 @@ public final class Connection<Handler: StreamHandler>: Sendable, ConnectionInfoP
134138 var decoder = impl. ephemeralStreamHandler. createDecoder ( kind: ceKind)
135139
136140 let lengthData = await stream. receive ( count: 4 )
137- guard let lengthData else {
141+ guard let lengthData, let length = try ? decodeLength ( from : lengthData ) else {
138142 stream. close ( abort: true )
139143 logger. debug ( " Invalid request length " )
140144 return
141145 }
142- let length = UInt32 ( littleEndian: lengthData. withUnsafeBytes { $0. loadUnaligned ( as: UInt32 . self) } )
143- // sanity check for length
144- // TODO: pick better value
145146 guard length < 1024 * 1024 * 10 else {
146147 stream. close ( abort: true )
147148 logger. debug ( " Invalid request length: \( length) " )
148- // TODO: report bad peer
149149 return
150150 }
151151 let data = await stream. receive ( count: Int ( length) )
152152 guard let data else {
153153 stream. close ( abort: true )
154154 logger. debug ( " Invalid request data " )
155- // TODO: report bad peer
156155 return
157156 }
158157 let request = try decoder. decode ( data: data)
@@ -196,16 +195,12 @@ func presistentStreamRunLoop<Handler: StreamHandler>(
196195 do {
197196 while true {
198197 let lengthData = await stream. receive ( count: 4 )
199- guard let lengthData else {
198+ guard let lengthData, let length = try ? connection . decodeLength ( from : lengthData ) else {
200199 break
201200 }
202- let length = UInt32 ( littleEndian: lengthData. withUnsafeBytes { $0. loadUnaligned ( as: UInt32 . self) } )
203- // sanity check for length
204- // TODO: pick better value
205201 guard length < 1024 * 1024 * 10 else {
206202 stream. close ( abort: true )
207203 logger. debug ( " Invalid message length: \( length) " )
208- // TODO: report bad peer
209204 return
210205 }
211206 let data = await stream. receive ( count: Int ( length) )
0 commit comments