@@ -292,6 +292,12 @@ private enum GRPCStreamStateMachineState {
292292 self . inboundMessageBuffer = previousState. inboundMessageBuffer
293293 }
294294
295+ init ( previousState: ClientOpenServerOpenState ) {
296+ self . framer = previousState. framer
297+ self . compressor = previousState. compressor
298+ self . inboundMessageBuffer = previousState. inboundMessageBuffer
299+ }
300+
295301 init ( previousState: ClientOpenServerClosedState ) {
296302 self . framer = previousState. framer
297303 self . compressor = previousState. compressor
@@ -388,12 +394,24 @@ struct GRPCStreamStateMachine {
388394 }
389395 }
390396
391- mutating func receive( buffer: ByteBuffer , endStream: Bool ) throws {
397+ enum OnBufferReceivedAction : Equatable {
398+ case readInbound
399+
400+ // Client-specific actions
401+
402+ // This will be returned when the server sends a data frame with EOS set.
403+ // This is invalid as per the protocol specification, because the server
404+ // can only close by sending trailers, not by setting EOS when sending
405+ // a message.
406+ case endRPCAndForwardErrorStatus( Status )
407+ }
408+
409+ mutating func receive( buffer: ByteBuffer , endStream: Bool ) throws -> OnBufferReceivedAction {
392410 switch self . configuration {
393411 case . client:
394- try self . clientReceive ( buffer: buffer, endStream: endStream)
412+ return try self . clientReceive ( buffer: buffer, endStream: endStream)
395413 case . server:
396- try self . serverReceive ( buffer: buffer, endStream: endStream)
414+ return try self . serverReceive ( buffer: buffer, endStream: endStream)
397415 }
398416 }
399417
@@ -729,7 +747,7 @@ extension GRPCStreamStateMachine {
729747 }
730748
731749 let statusMessage =
732- metadata. firstString ( forKey: . grpcStatusMessage)
750+ metadata. firstString ( forKey: . grpcStatusMessage, canonicalForm : false )
733751 . map { GRPCStatusMessageMarshaller . unmarshall ( $0) } ?? " "
734752
735753 var convertedMetadata = Metadata ( headers: metadata)
@@ -860,38 +878,68 @@ extension GRPCStreamStateMachine {
860878 }
861879 }
862880
863- private mutating func clientReceive( buffer: ByteBuffer , endStream: Bool ) throws {
881+ private mutating func clientReceive(
882+ buffer: ByteBuffer ,
883+ endStream: Bool
884+ ) throws -> OnBufferReceivedAction {
864885 // This is a message received by the client, from the server.
865886 switch self . state {
866887 case . clientIdleServerIdle:
867888 try self . invalidState (
868889 " Cannot have received anything from server if client is not yet open. "
869890 )
891+
870892 case . clientOpenServerIdle, . clientClosedServerIdle:
871893 try self . invalidState (
872894 " Server cannot have sent a message before sending the initial metadata. "
873895 )
896+
874897 case . clientOpenServerOpen( var state) :
898+ if endStream {
899+ // This is invalid as per the protocol specification, because the server
900+ // can only close by sending trailers, not by setting EOS when sending
901+ // a message.
902+ self . state = . clientClosedServerClosed( . init( previousState: state) )
903+ return . endRPCAndForwardErrorStatus(
904+ Status (
905+ code: . internalError,
906+ message: """
907+ Server sent EOS alongside a data frame, but server is only allowed \
908+ to close by sending status and trailers.
909+ """
910+ )
911+ )
912+ }
913+
875914 try state. deframer. process ( buffer: buffer) { deframedMessage in
876915 state. inboundMessageBuffer. append ( deframedMessage)
877916 }
917+ self . state = . clientOpenServerOpen( state)
918+ return . readInbound
919+
920+ case . clientClosedServerOpen( var state) :
878921 if endStream {
879- self . state = . clientOpenServerClosed( . init( previousState: state) )
880- } else {
881- self . state = . clientOpenServerOpen( state)
922+ self . state = . clientClosedServerClosed( . init( previousState: state) )
923+ return . endRPCAndForwardErrorStatus(
924+ Status (
925+ code: . internalError,
926+ message: """
927+ Server sent EOS alongside a data frame, but server is only allowed \
928+ to close by sending status and trailers.
929+ """
930+ )
931+ )
882932 }
883- case . clientClosedServerOpen ( var state ) :
933+
884934 // The client may have sent the end stream and thus it's closed,
885935 // but the server may still be responding.
886936 // The client must have a deframer set up, so force-unwrap is okay.
887937 try state. deframer!. process ( buffer: buffer) { deframedMessage in
888938 state. inboundMessageBuffer. append ( deframedMessage)
889939 }
890- if endStream {
891- self . state = . clientClosedServerClosed( . init( previousState: state) )
892- } else {
893- self . state = . clientClosedServerOpen( state)
894- }
940+ self . state = . clientClosedServerOpen( state)
941+ return . readInbound
942+
895943 case . clientOpenServerClosed, . clientClosedServerClosed:
896944 try self . invalidState (
897945 " Cannot have received anything from a closed server. "
@@ -1314,7 +1362,10 @@ extension GRPCStreamStateMachine {
13141362 }
13151363 }
13161364
1317- private mutating func serverReceive( buffer: ByteBuffer , endStream: Bool ) throws {
1365+ private mutating func serverReceive(
1366+ buffer: ByteBuffer ,
1367+ endStream: Bool
1368+ ) throws -> OnBufferReceivedAction {
13181369 switch self . state {
13191370 case . clientIdleServerIdle:
13201371 try self . invalidState (
@@ -1354,6 +1405,7 @@ extension GRPCStreamStateMachine {
13541405 " Client can't send a message if closed. "
13551406 )
13561407 }
1408+ return . readInbound
13571409 }
13581410
13591411 private mutating func serverNextOutboundFrame( ) throws -> OnNextOutboundFrame {
@@ -1443,10 +1495,11 @@ internal enum GRPCHTTP2Keys: String {
14431495}
14441496
14451497extension HPACKHeaders {
1446- internal func firstString( forKey key: GRPCHTTP2Keys ) -> String ? {
1447- self . values ( forHeader: key. rawValue, canonicalForm: true ) . first ( where: { _ in true } ) . map {
1448- String ( $0)
1449- }
1498+ internal func firstString( forKey key: GRPCHTTP2Keys , canonicalForm: Bool = true ) -> String ? {
1499+ self . values ( forHeader: key. rawValue, canonicalForm: canonicalForm) . first ( where: { _ in true } )
1500+ . map {
1501+ String ( $0)
1502+ }
14501503 }
14511504
14521505 internal mutating func add( _ value: String , forKey key: GRPCHTTP2Keys ) {
0 commit comments