(state: WsState, user: Option<ExistingUser>, peer_addr: IpAddr, mut ws: WebSocket)
| 337 | } |
| 338 | |
| 339 | async fn run_ws(state: WsState, user: Option<ExistingUser>, peer_addr: IpAddr, mut ws: WebSocket) { |
| 340 | let mut client = match init_ws(state, user, peer_addr, &mut ws).await { |
| 341 | Ok(client) => client, |
| 342 | Err(e) => { |
| 343 | // We omit most detail from the error message we send to the client, to |
| 344 | // avoid giving attackers unnecessary information during auth. AdapterErrors |
| 345 | // are safe to return because they're generated after authentication. |
| 346 | debug!("WS request failed init: {}", e); |
| 347 | let reason: Utf8Bytes = match e.downcast_ref::<AdapterError>() { |
| 348 | Some(error) => error.to_string().into(), |
| 349 | None => "unauthorized".to_string().into(), |
| 350 | }; |
| 351 | let _ = ws |
| 352 | .send(Message::Close(Some(CloseFrame { |
| 353 | code: CloseCode::Protocol.into(), |
| 354 | reason, |
| 355 | }))) |
| 356 | .await; |
| 357 | return; |
| 358 | } |
| 359 | }; |
| 360 | |
| 361 | // Successful auth, send startup messages. |
| 362 | let mut msgs = Vec::new(); |
| 363 | let session = client.client.session(); |
| 364 | for var in session.vars().notify_set() { |
| 365 | msgs.push(WebSocketResponse::ParameterStatus(ParameterStatus { |
| 366 | name: var.name().to_string(), |
| 367 | value: var.value(), |
| 368 | })); |
| 369 | } |
| 370 | msgs.push(WebSocketResponse::BackendKeyData(BackendKeyData { |
| 371 | conn_id: session.conn_id().unhandled(), |
| 372 | secret_key: session.secret_key(), |
| 373 | })); |
| 374 | msgs.push(WebSocketResponse::ReadyForQuery( |
| 375 | session.transaction_code().into(), |
| 376 | )); |
| 377 | for msg in msgs { |
| 378 | let _ = ws |
| 379 | .send(Message::Text( |
| 380 | serde_json::to_string(&msg).expect("must serialize").into(), |
| 381 | )) |
| 382 | .await; |
| 383 | } |
| 384 | |
| 385 | // Send any notices that might have been generated on startup. |
| 386 | let notices = session.drain_notices(); |
| 387 | if let Err(err) = forward_notices(&mut ws, notices).await { |
| 388 | debug!("failed to forward notices to WebSocket, {err:?}"); |
| 389 | return; |
| 390 | } |
| 391 | |
| 392 | loop { |
| 393 | // Handle timeouts first so we don't execute any statements when there's a pending timeout. |
| 394 | let msg = select! { |
| 395 | biased; |
| 396 |
no test coverage detected