|
|
|
@ -199,25 +199,27 @@ auto ChaoticGoodServerTransport::SendCallInitialMetadataAndBody( |
|
|
|
|
auto ChaoticGoodServerTransport::CallOutboundLoop( |
|
|
|
|
uint32_t stream_id, CallInitiator call_initiator) { |
|
|
|
|
auto outgoing_frames = outgoing_frames_.MakeSender(); |
|
|
|
|
return Seq( |
|
|
|
|
Map(SendCallInitialMetadataAndBody(stream_id, outgoing_frames, |
|
|
|
|
call_initiator), |
|
|
|
|
[stream_id](absl::Status main_body_result) { |
|
|
|
|
GRPC_TRACE_VLOG(chaotic_good, 2) |
|
|
|
|
<< "CHAOTIC_GOOD: CallOutboundLoop: stream_id=" << stream_id |
|
|
|
|
<< " main_body_result=" << main_body_result; |
|
|
|
|
return Empty{}; |
|
|
|
|
}), |
|
|
|
|
call_initiator.PullServerTrailingMetadata(), |
|
|
|
|
// Capture the call_initator to ensure the underlying call_spine
|
|
|
|
|
// is alive until the SendFragment promise completes.
|
|
|
|
|
[stream_id, outgoing_frames, |
|
|
|
|
call_initiator](ServerMetadataHandle md) mutable { |
|
|
|
|
ServerFragmentFrame frame; |
|
|
|
|
frame.trailers = std::move(md); |
|
|
|
|
frame.stream_id = stream_id; |
|
|
|
|
return SendFragment(std::move(frame), outgoing_frames, call_initiator); |
|
|
|
|
}); |
|
|
|
|
return GRPC_LATENT_SEE_PROMISE( |
|
|
|
|
"CallOutboundLoop", |
|
|
|
|
Seq(Map(SendCallInitialMetadataAndBody(stream_id, outgoing_frames, |
|
|
|
|
call_initiator), |
|
|
|
|
[stream_id](absl::Status main_body_result) { |
|
|
|
|
GRPC_TRACE_VLOG(chaotic_good, 2) |
|
|
|
|
<< "CHAOTIC_GOOD: CallOutboundLoop: stream_id=" << stream_id |
|
|
|
|
<< " main_body_result=" << main_body_result; |
|
|
|
|
return Empty{}; |
|
|
|
|
}), |
|
|
|
|
call_initiator.PullServerTrailingMetadata(), |
|
|
|
|
// Capture the call_initator to ensure the underlying call_spine
|
|
|
|
|
// is alive until the SendFragment promise completes.
|
|
|
|
|
[stream_id, outgoing_frames, |
|
|
|
|
call_initiator](ServerMetadataHandle md) mutable { |
|
|
|
|
ServerFragmentFrame frame; |
|
|
|
|
frame.trailers = std::move(md); |
|
|
|
|
frame.stream_id = stream_id; |
|
|
|
|
return SendFragment(std::move(frame), outgoing_frames, |
|
|
|
|
call_initiator); |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto ChaoticGoodServerTransport::DeserializeAndPushFragmentToNewCall( |
|
|
|
@ -269,57 +271,59 @@ auto ChaoticGoodServerTransport::DeserializeAndPushFragmentToExistingCall( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto ChaoticGoodServerTransport::ReadOneFrame(ChaoticGoodTransport& transport) { |
|
|
|
|
return TrySeq( |
|
|
|
|
transport.ReadFrameBytes(), |
|
|
|
|
[this, transport = |
|
|
|
|
&transport](std::tuple<FrameHeader, BufferPair> frame_bytes) { |
|
|
|
|
const auto& frame_header = std::get<0>(frame_bytes); |
|
|
|
|
auto& buffers = std::get<1>(frame_bytes); |
|
|
|
|
return Switch( |
|
|
|
|
frame_header.type, |
|
|
|
|
Case(FrameType::kSettings, |
|
|
|
|
[]() -> absl::Status { |
|
|
|
|
return absl::InternalError("Unexpected settings frame"); |
|
|
|
|
}), |
|
|
|
|
Case(FrameType::kFragment, |
|
|
|
|
[this, &frame_header, &buffers, transport]() { |
|
|
|
|
return If( |
|
|
|
|
frame_header.flags.is_set(0), |
|
|
|
|
[this, &frame_header, &buffers, transport]() { |
|
|
|
|
return DeserializeAndPushFragmentToNewCall( |
|
|
|
|
frame_header, std::move(buffers), *transport); |
|
|
|
|
}, |
|
|
|
|
[this, &frame_header, &buffers, transport]() { |
|
|
|
|
return DeserializeAndPushFragmentToExistingCall( |
|
|
|
|
frame_header, std::move(buffers), *transport); |
|
|
|
|
}); |
|
|
|
|
}), |
|
|
|
|
Case(FrameType::kCancel, |
|
|
|
|
[this, &frame_header]() { |
|
|
|
|
absl::optional<CallInitiator> call_initiator = |
|
|
|
|
ExtractStream(frame_header.stream_id); |
|
|
|
|
GRPC_TRACE_LOG(chaotic_good, INFO) |
|
|
|
|
<< "Cancel stream " << frame_header.stream_id |
|
|
|
|
<< (call_initiator.has_value() ? " (active)" |
|
|
|
|
: " (not found)"); |
|
|
|
|
return If( |
|
|
|
|
call_initiator.has_value(), |
|
|
|
|
[&call_initiator]() { |
|
|
|
|
auto c = std::move(*call_initiator); |
|
|
|
|
return c.SpawnWaitable("cancel", [c]() mutable { |
|
|
|
|
c.Cancel(); |
|
|
|
|
return absl::OkStatus(); |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
[]() -> absl::Status { return absl::OkStatus(); }); |
|
|
|
|
}), |
|
|
|
|
Default([frame_header]() { |
|
|
|
|
return absl::InternalError( |
|
|
|
|
absl::StrCat("Unexpected frame type: ", |
|
|
|
|
static_cast<uint8_t>(frame_header.type))); |
|
|
|
|
})); |
|
|
|
|
}, |
|
|
|
|
[]() -> LoopCtl<absl::Status> { return Continue{}; }); |
|
|
|
|
return GRPC_LATENT_SEE_PROMISE( |
|
|
|
|
"ReadOneFrame", |
|
|
|
|
TrySeq( |
|
|
|
|
transport.ReadFrameBytes(), |
|
|
|
|
[this, transport = &transport]( |
|
|
|
|
std::tuple<FrameHeader, BufferPair> frame_bytes) { |
|
|
|
|
const auto& frame_header = std::get<0>(frame_bytes); |
|
|
|
|
auto& buffers = std::get<1>(frame_bytes); |
|
|
|
|
return Switch( |
|
|
|
|
frame_header.type, |
|
|
|
|
Case(FrameType::kSettings, |
|
|
|
|
[]() -> absl::Status { |
|
|
|
|
return absl::InternalError("Unexpected settings frame"); |
|
|
|
|
}), |
|
|
|
|
Case(FrameType::kFragment, |
|
|
|
|
[this, &frame_header, &buffers, transport]() { |
|
|
|
|
return If( |
|
|
|
|
frame_header.flags.is_set(0), |
|
|
|
|
[this, &frame_header, &buffers, transport]() { |
|
|
|
|
return DeserializeAndPushFragmentToNewCall( |
|
|
|
|
frame_header, std::move(buffers), *transport); |
|
|
|
|
}, |
|
|
|
|
[this, &frame_header, &buffers, transport]() { |
|
|
|
|
return DeserializeAndPushFragmentToExistingCall( |
|
|
|
|
frame_header, std::move(buffers), *transport); |
|
|
|
|
}); |
|
|
|
|
}), |
|
|
|
|
Case(FrameType::kCancel, |
|
|
|
|
[this, &frame_header]() { |
|
|
|
|
absl::optional<CallInitiator> call_initiator = |
|
|
|
|
ExtractStream(frame_header.stream_id); |
|
|
|
|
GRPC_TRACE_LOG(chaotic_good, INFO) |
|
|
|
|
<< "Cancel stream " << frame_header.stream_id |
|
|
|
|
<< (call_initiator.has_value() ? " (active)" |
|
|
|
|
: " (not found)"); |
|
|
|
|
return If( |
|
|
|
|
call_initiator.has_value(), |
|
|
|
|
[&call_initiator]() { |
|
|
|
|
auto c = std::move(*call_initiator); |
|
|
|
|
return c.SpawnWaitable("cancel", [c]() mutable { |
|
|
|
|
c.Cancel(); |
|
|
|
|
return absl::OkStatus(); |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
[]() -> absl::Status { return absl::OkStatus(); }); |
|
|
|
|
}), |
|
|
|
|
Default([frame_header]() { |
|
|
|
|
return absl::InternalError( |
|
|
|
|
absl::StrCat("Unexpected frame type: ", |
|
|
|
|
static_cast<uint8_t>(frame_header.type))); |
|
|
|
|
})); |
|
|
|
|
}, |
|
|
|
|
[]() -> LoopCtl<absl::Status> { return Continue{}; })); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto ChaoticGoodServerTransport::TransportReadLoop( |
|
|
|
@ -360,9 +364,13 @@ ChaoticGoodServerTransport::ChaoticGoodServerTransport( |
|
|
|
|
party_arena->SetContext<grpc_event_engine::experimental::EventEngine>( |
|
|
|
|
event_engine.get()); |
|
|
|
|
party_ = Party::Make(std::move(party_arena)); |
|
|
|
|
party_->Spawn("server-chaotic-writer", TransportWriteLoop(transport), |
|
|
|
|
party_->Spawn("server-chaotic-writer", |
|
|
|
|
GRPC_LATENT_SEE_PROMISE("ServerTransportWriteLoop", |
|
|
|
|
TransportWriteLoop(transport)), |
|
|
|
|
OnTransportActivityDone("writer")); |
|
|
|
|
party_->Spawn("server-chaotic-reader", TransportReadLoop(transport), |
|
|
|
|
party_->Spawn("server-chaotic-reader", |
|
|
|
|
GRPC_LATENT_SEE_PROMISE("ServerTransportReadLoop", |
|
|
|
|
TransportReadLoop(transport)), |
|
|
|
|
OnTransportActivityDone("reader")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|