Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions grpc/src/client/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,10 @@ impl Invoke for Arc<ActiveChannel> {
let mut i = self.lb_watcher.iter();
loop {
let Some(state) = i.next().await else {
return FailingRecvStream::new_stream_pair(StatusError::new(
StatusCodeError::Internal,
"channel has been closed",
));
return FailingRecvStream::new_stream_pair(
StatusError::new(StatusCodeError::Internal, "channel has been closed"),
None,
);
};
let result = &state.picker.pick(&headers);
match result {
Expand All @@ -381,7 +381,7 @@ impl Invoke for Arc<ActiveChannel> {
// Continue and retry the RPC with the next picker.
}
PickResult::Fail(status) => {
return FailingRecvStream::new_stream_pair(status.clone());
return FailingRecvStream::new_stream_pair(status.clone(), None);
}
PickResult::Drop(status) => {
todo!("dropped pick: {:?}", status);
Expand Down
4 changes: 3 additions & 1 deletion grpc/src/client/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,9 @@ mod test {
.unwrap();
assert_eq!(controller.recv_req().await.0, one);
controller
.send_resp(ResponseStreamItem::Headers(ResponseHeaders::default()))
.send_resp(ResponseStreamItem::Headers(ResponseHeaders::new(
crate::core::test_peer_info(),
)))
.await;

let resp = rx.recv(&mut ByteRecvMsg::new()).await;
Expand Down
2 changes: 1 addition & 1 deletion grpc/src/client/metadata_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ mod tests {
// Send a Headers response on the call.
let mut resp_md = MetadataMap::new();
resp_md.insert("x-resp-header", "resp-value".parse().unwrap());
let mut headers = ResponseHeaders::default();
let mut headers = ResponseHeaders::new(crate::core::test_peer_info());
*headers.metadata_mut() = resp_md;
controller
.send_resp(ResponseStreamItem::Headers(headers))
Expand Down
43 changes: 39 additions & 4 deletions grpc/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ use std::time::Instant;

use tonic::async_trait;

use crate::core::PeerInfo;
use crate::core::RecvMessage;
use crate::core::SendMessage;
use crate::metadata::MetadataMap;
Expand Down Expand Up @@ -367,15 +368,19 @@ impl<'a> RecvStream for Box<dyn DynRecvStream + 'a> {
}

/// Contains all information transmitted in the response headers of an RPC.
#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone)]
pub struct ResponseHeaders {
metadata: MetadataMap,
peer_info: PeerInfo,
}

impl ResponseHeaders {
/// Returns a default ResponseHeaders instance.
pub fn new() -> Self {
Self::default()
pub fn new(peer_info: PeerInfo) -> Self {
Self {
metadata: MetadataMap::default(),
peer_info,
}
}

/// Replaces the metadata of self with `metadata`.
Expand All @@ -397,6 +402,17 @@ impl ResponseHeaders {
pub(crate) fn into_metadata(self) -> MetadataMap {
self.metadata
}

/// Replaces the peer_info of self with `peer_info`.
pub fn with_peer_info(mut self, peer_info: PeerInfo) -> Self {
self.peer_info = peer_info;
self
}

/// Replaces the peer_info of self with `peer_info`.
pub fn peer_info(&self) -> &PeerInfo {
&self.peer_info
}
}

/// Contains all information transmitted in the request headers of an RPC.
Expand Down Expand Up @@ -427,7 +443,7 @@ impl RequestHeaders {
}

/// Returns the full (e.g. "/Service/Method") method name for these headers.
pub fn method_name(&self) -> &str {
pub fn method_name(&self) -> &String {
&self.method_name
}

Expand All @@ -454,6 +470,7 @@ impl RequestHeaders {
pub struct Trailers {
status: crate::Result<()>,
metadata: MetadataMap,
peer_info: Option<PeerInfo>,
}

impl Trailers {
Expand All @@ -462,6 +479,7 @@ impl Trailers {
Self {
status,
metadata: MetadataMap::default(),
peer_info: None,
}
}

Expand Down Expand Up @@ -497,6 +515,23 @@ impl Trailers {
self.status
}

/// Replaces the peer info in self with `peer_info`.
pub fn with_peer_info(mut self, peer_info: Option<PeerInfo>) -> Self {
self.peer_info = peer_info;
self
}

/// Returns the peer info in the trailers, if present. Peer information
/// will not be available in trailers in any the following circumstances:
///
/// 1. A ResponseHeaders was already present on the response stream.
///
/// 2. The error was generated locally on the client before a connection was
/// chosen for the RPC.
pub fn peer_info(&self) -> &Option<PeerInfo> {
&self.peer_info
}

pub(crate) fn into_parts(self) -> (crate::Result<()>, MetadataMap) {
(self.status, self.metadata)
}
Expand Down
34 changes: 20 additions & 14 deletions grpc/src/client/stream_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use crate::client::SendOptions;
use crate::client::SendStream;
use crate::client::Trailers;
use crate::client::interceptor::Intercept;
use crate::core::PeerInfo;
use crate::core::RecvMessage;
use crate::core::SendMessage;

Expand Down Expand Up @@ -181,12 +182,15 @@ impl SendStream for NopSendStream {

pub(crate) struct FailingRecvStream {
status: Option<StatusError>,
peer_info: Option<PeerInfo>,
}

impl RecvStream for FailingRecvStream {
async fn recv(&mut self, msg: &mut dyn RecvMessage) -> ResponseStreamItem {
match self.status.take() {
Some(status) => ResponseStreamItem::Trailers(Trailers::new(Err(status))),
Some(status) => ResponseStreamItem::Trailers(
Trailers::new(Err(status)).with_peer_info(self.peer_info.take()),
),
None => ResponseStreamItem::StreamClosed,
}
}
Expand All @@ -195,11 +199,13 @@ impl RecvStream for FailingRecvStream {
impl FailingRecvStream {
pub(crate) fn new_stream_pair(
status: StatusError,
peer_info: Option<PeerInfo>,
) -> (Box<dyn DynSendStream>, Box<dyn DynRecvStream>) {
(
Box::new(NopSendStream),
Box::new(Self {
status: Some(status),
peer_info,
}),
)
}
Expand Down Expand Up @@ -240,11 +246,11 @@ mod test {
let scenarios = [
vec![ResponseStreamItem::StreamClosed],
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::StreamClosed,
],
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::StreamClosed,
],
Expand All @@ -268,13 +274,13 @@ mod test {
async fn test_validator_headers_repeated() {
let scenarios = [
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
],
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
],
];

Expand All @@ -296,7 +302,7 @@ mod test {
let scenarios = [
vec![ResponseStreamItem::Trailers(Trailers::new(Ok(())))],
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Trailers(Trailers::new(Ok(()))),
],
];
Expand All @@ -317,7 +323,7 @@ mod test {
#[tokio::test]
async fn test_validator_unary_multiple_messages() {
let scenarios = [vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::Message,
]];
Expand All @@ -338,7 +344,7 @@ mod test {
#[tokio::test]
async fn test_validator_successful_stream() {
let scenarios = [vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::Message,
ResponseStreamItem::Message,
Expand All @@ -358,7 +364,7 @@ mod test {
#[tokio::test]
async fn test_validator_erroring_stream() {
let scenarios = [vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::Message,
ResponseStreamItem::Message,
Expand All @@ -384,7 +390,7 @@ mod test {
#[tokio::test]
async fn test_validator_successful_unary() {
let scenarios = [vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::Trailers(Trailers::new(Ok(()))),
]];
Expand All @@ -406,14 +412,14 @@ mod test {
StatusError::new(StatusCodeError::Aborted, "some err"),
)))],
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Trailers(Trailers::new(Err(StatusError::new(
StatusCodeError::Aborted,
"some err",
)))),
],
vec![
ResponseStreamItem::Headers(ResponseHeaders::default()),
ResponseStreamItem::Headers(ResponseHeaders::new(crate::core::test_peer_info())),
ResponseStreamItem::Message,
ResponseStreamItem::Trailers(Trailers::new(Err(StatusError::new(
StatusCodeError::Aborted,
Expand Down
20 changes: 11 additions & 9 deletions grpc/src/client/subchannel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ use crate::client::transport::SecurityOpts;
use crate::client::transport::TransportOptions;
use crate::client::transport::http_connect::HttpConnectHandshaker;
use crate::core::Address;
use crate::credentials::SecurityInfo;
use crate::core::PeerInfo;
use crate::credentials::call::CallDetails;
use crate::credentials::call::ClientConnectionSecurityInfo as CallClientConnectionSecurityInfo;
use crate::credentials::common::Authority;
Expand Down Expand Up @@ -86,7 +86,7 @@ impl Backoff for NopBackoff {

struct ReadyState {
service: Box<dyn DynInvoke>,
security_info: SecurityInfo,
peer_info: PeerInfo,
authority: Authority,
}

Expand Down Expand Up @@ -195,11 +195,13 @@ impl DynInvoke for InternalSubchannel {
};

let fail_with = |status| -> (Box<dyn DynSendStream>, Box<dyn DynRecvStream>) {
FailingRecvStream::new_stream_pair(status)
FailingRecvStream::new_stream_pair(status, Some(state.peer_info.clone()))
};

if let Some(call_creds) = call_creds {
if call_creds.minimum_channel_security_level() > state.security_info.security_level() {
if call_creds.minimum_channel_security_level()
> state.peer_info.security_info().security_level()
{
return fail_with(StatusError::new(
StatusCodeError::Unauthenticated,
"transport: cannot send secure credentials on an insecure connection",
Expand All @@ -209,9 +211,9 @@ impl DynInvoke for InternalSubchannel {
let call_details = create_call_details(&state.authority, headers.method_name());

let channel_sec_info = CallClientConnectionSecurityInfo::new(
state.security_info.security_protocol(),
state.security_info.security_level(),
state.security_info.attributes().clone(),
state.peer_info.security_info().security_protocol(),
state.peer_info.security_info().security_level(),
state.peer_info.security_info().attributes().clone(),
);

if let Err(s) = call_creds
Expand Down Expand Up @@ -376,10 +378,10 @@ fn begin_connecting_if_idle(data: Arc<Mutex<InternalSubchannelData>>) {
}
result = transport_builder.dyn_connect(&address, runtime, &security_opts, &transport_opts) => {
match result {
Ok((service, security_info, disconnection_listener)) => {
Ok((service, peer_info, disconnection_listener)) => {
move_to_ready(data, Arc::new(ReadyState{
service,
security_info,
peer_info,
authority: security_opts.authority}), disconnection_listener).await;
}
Err(e) => {
Expand Down
8 changes: 4 additions & 4 deletions grpc/src/client/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use http::HeaderValue;
use crate::client::DynInvoke;
use crate::client::Invoke;
use crate::core::Address;
use crate::core::PeerInfo;
use crate::credentials::ChannelCredentials;
use crate::credentials::SecurityInfo;
use crate::credentials::client::ClientHandshakeInfo;
use crate::credentials::common::Authority;
use crate::rt::GrpcRuntime;
Expand Down Expand Up @@ -98,7 +98,7 @@ pub(crate) trait Transport: Sync {
) -> Result<
(
Self::Service,
SecurityInfo,
PeerInfo,
oneshot::Receiver<Result<(), String>>,
),
String,
Expand All @@ -116,7 +116,7 @@ pub(crate) trait DynTransport: Send + Sync {
) -> Result<
(
Box<dyn DynInvoke>,
SecurityInfo,
PeerInfo,
oneshot::Receiver<Result<(), String>>,
),
String,
Expand All @@ -134,7 +134,7 @@ impl<T: Transport> DynTransport for T {
) -> Result<
(
Box<dyn DynInvoke>,
SecurityInfo,
PeerInfo,
oneshot::Receiver<Result<(), String>>,
),
String,
Expand Down
Loading
Loading