use super::*;
impl H2Framer {
pub(crate) fn new(send_response: h2::server::SendResponse<Bytes>) -> Self {
Self {
send_response: Some(send_response),
send_stream: None,
finished: false,
}
}
pub(crate) fn reset(&mut self) {
if let Some(mut send_response) = self.get_mut_send_response().take() {
send_response.send_reset(h2::Reason::INTERNAL_ERROR);
}
if let Some(mut send_stream) = self.get_mut_send_stream().take() {
send_stream.send_reset(h2::Reason::INTERNAL_ERROR);
}
}
}
impl ResponseFramer for H2Framer {
fn send_head<'a>(
&'a mut self,
head: &'a FramedHead,
bodyless: bool,
) -> Pin<Box<dyn Future<Output = Result<(), ResponseError>> + Send + 'a>> {
Box::pin(async move {
let mut builder: http::response::Builder =
http::Response::builder().status(head.status_code as u16);
for (name, value) in head.headers.iter() {
let key: &str = name.as_str();
if key.starts_with(PSEUDO_HEADER_PREFIX)
|| is_hop_by_hop(key)
|| connection_nominates(&head.headers, key)
{
continue;
}
builder = builder.header(name.clone(), value.clone());
}
let response: ProtocolResponse<()> = builder
.body(())
.map_err(|error: ProtocolBuildError| ResponseError::Send(error.to_string()))?;
let mut send_response: h2::server::SendResponse<Bytes> = self
.get_mut_send_response()
.take()
.ok_or(ResponseError::Terminated)?;
if bodyless {
self.set_finished(true);
send_response
.send_response(response, true)
.map_err(|error: H2Error| ResponseError::Send(error.to_string()))?;
return Ok(());
}
let send_stream: H2SendStream = send_response
.send_response(response, false)
.map_err(|error: H2Error| ResponseError::Send(error.to_string()))?;
self.set_send_stream(Some(send_stream));
Ok(())
})
}
fn send_data<'a>(
&'a mut self,
data: &'a [u8],
) -> Pin<Box<dyn Future<Output = Result<(), ResponseError>> + Send + 'a>> {
Box::pin(async move {
if data.is_empty() || self.get_finished() {
return Ok(());
}
let Some(mut send_stream) = self.get_mut_send_stream().take() else {
return Err(ResponseError::Terminated);
};
let mut rest: &[u8] = data;
while !rest.is_empty() {
let granted: usize = next_h2_capacity(&mut send_stream, rest.len()).await?;
let take: usize = granted.min(rest.len());
let chunk: Bytes = Bytes::copy_from_slice(&rest[..take]);
rest = &rest[take..];
send_stream
.send_data(chunk, false)
.map_err(|error: H2Error| ResponseError::Send(error.to_string()))?;
}
self.set_send_stream(Some(send_stream));
Ok(())
})
}
fn finish<'a>(
&'a mut self,
) -> Pin<Box<dyn Future<Output = Result<(), ResponseError>> + Send + 'a>> {
Box::pin(async move {
if self.get_finished() {
return Ok(());
}
self.set_finished(true);
let Some(mut send_stream) = self.get_mut_send_stream().take() else {
return Ok(());
};
send_stream
.send_data(Bytes::new(), true)
.map_err(|error: H2Error| ResponseError::Send(error.to_string()))?;
Ok(())
})
}
}