Handle an upgraded connection (101 Switching Protocols). Forwards any overflow bytes from the upgrade response to the client, then either switches to a parsed WebSocket relay for opted-in message policy / credential rewriting or to raw bidirectional TCP copy for other upgrades.
(
client: &mut C,
upstream: &mut U,
overflow: Vec<u8>,
host: &str,
port: u16,
options: UpgradeRelayOptions<'_>,
)
| 589 | /// either switches to a parsed WebSocket relay for opted-in message policy / |
| 590 | /// credential rewriting or to raw bidirectional TCP copy for other upgrades. |
| 591 | pub(crate) async fn handle_upgrade<C, U>( |
| 592 | client: &mut C, |
| 593 | upstream: &mut U, |
| 594 | overflow: Vec<u8>, |
| 595 | host: &str, |
| 596 | port: u16, |
| 597 | options: UpgradeRelayOptions<'_>, |
| 598 | ) -> Result<()> |
| 599 | where |
| 600 | C: AsyncRead + AsyncWrite + Unpin + Send, |
| 601 | U: AsyncRead + AsyncWrite + Unpin + Send, |
| 602 | { |
| 603 | let use_websocket_relay = options.websocket_request |
| 604 | && (options.websocket.message_policy.inspects_messages() |
| 605 | || options.websocket.permessage_deflate |
| 606 | || (options.websocket.credential_rewrite && options.secret_resolver.is_some())); |
| 607 | let relay_mode = if use_websocket_relay { |
| 608 | "websocket parsed relay" |
| 609 | } else { |
| 610 | "raw bidirectional relay (L7 enforcement no longer active)" |
| 611 | }; |
| 612 | ocsf_emit!( |
| 613 | NetworkActivityBuilder::new(openshell_ocsf::ctx::ctx()) |
| 614 | .activity(ActivityId::Other) |
| 615 | .activity_name("Upgrade") |
| 616 | .severity(SeverityId::Informational) |
| 617 | .dst_endpoint(Endpoint::from_domain(host, port)) |
| 618 | .message(format!( |
| 619 | "101 Switching Protocols — {relay_mode} [host:{host} port:{port} overflow_bytes:{}]", |
| 620 | overflow.len() |
| 621 | )) |
| 622 | .build() |
| 623 | ); |
| 624 | if use_websocket_relay { |
| 625 | let resolver = if options.websocket.credential_rewrite { |
| 626 | options.secret_resolver.as_deref() |
| 627 | } else { |
| 628 | None |
| 629 | }; |
| 630 | let inspector = if options.websocket.message_policy.inspects_messages() { |
| 631 | match (options.engine, options.ctx) { |
| 632 | (Some(engine), Some(ctx)) => Some(crate::l7::websocket::InspectionOptions { |
| 633 | engine, |
| 634 | ctx, |
| 635 | enforcement: options.enforcement, |
| 636 | target: options.target.clone(), |
| 637 | query_params: options.query_params.clone(), |
| 638 | graphql_policy: options.websocket.message_policy.is_graphql(), |
| 639 | }), |
| 640 | _ => { |
| 641 | return Err(miette!( |
| 642 | "websocket message inspection missing policy context" |
| 643 | )); |
| 644 | } |
| 645 | } |
| 646 | } else { |
| 647 | None |
| 648 | }; |
no test coverage detected