handle binary and text messages

This commit is contained in:
Bryan Stitt 2022-05-31 01:55:04 +00:00
parent 45fd1b2ff1
commit a6a238fff2
3 changed files with 104 additions and 73 deletions

View File

@ -309,6 +309,8 @@ impl Web3ProxyApp {
) -> anyhow::Result<JsonRpcForwardedResponse> {
trace!("Received request: {:?}", request);
// TODO: if eth_chainId or net_version, serve those without querying the backend
// TODO: how much should we retry? probably with a timeout and not with a count like this
// TODO: think more about this loop.
// // TODO: add more to this span

View File

@ -237,7 +237,14 @@ impl Web3Connections {
let mut pending_synced_connections = SyncedConnections::default();
while let Ok((new_block, rpc_id)) = block_receiver.recv_async().await {
let new_block_num = new_block.number.unwrap().as_u64();
// TODO: wth. how is this happening? need more logs
let new_block_num = match new_block.number {
Some(x) => x.as_u64(),
None => {
warn!(?new_block, "Block without number!");
continue;
}
};
let new_block_hash = new_block.hash.unwrap();
// TODO: span with more in it?

View File

@ -7,14 +7,18 @@ use axum::{
routing::{get, post},
Extension, Json, Router,
};
use futures::stream::{SplitSink, SplitStream, StreamExt};
use futures::SinkExt;
use futures::{
future::AbortHandle,
stream::{SplitSink, SplitStream, StreamExt},
};
use hashbrown::HashMap;
use serde_json::json;
use serde_json::value::RawValue;
use std::net::SocketAddr;
use std::str::from_utf8_mut;
use std::sync::Arc;
use tracing::{error, warn};
use tracing::{debug, error, info, warn};
use crate::{
app::Web3ProxyApp,
@ -84,36 +88,28 @@ async fn proxy_web3_socket(app: Extension<Arc<Web3ProxyApp>>, socket: WebSocket)
tokio::spawn(read_web3_socket(app, ws_rx, response_tx));
}
async fn read_web3_socket(
app: Extension<Arc<Web3ProxyApp>>,
mut ws_rx: SplitStream<WebSocket>,
response_tx: flume::Sender<Message>,
) {
let mut subscriptions = HashMap::new();
while let Some(Ok(msg)) = ws_rx.next().await {
// new message from our client. forward to a backend and then send it through response_tx
let response_msg = match msg {
Message::Text(payload) => {
let (id, response) = match serde_json::from_str::<JsonRpcRequest>(&payload) {
async fn handle_socket_payload(
app: &Web3ProxyApp,
payload: &str,
response_tx: &flume::Sender<Message>,
subscriptions: &mut HashMap<String, AbortHandle>,
) -> Message {
let (id, response) = match serde_json::from_str::<JsonRpcRequest>(payload) {
Ok(payload) => {
let id = payload.id.clone();
let response: anyhow::Result<JsonRpcForwardedResponseEnum> =
if payload.method == "eth_subscribe" {
let response: anyhow::Result<JsonRpcForwardedResponseEnum> = if payload.method
== "eth_subscribe"
{
// TODO: if we pass eth_subscribe the response_tx, we
let response = app
.0
.eth_subscribe(id.clone(), payload, response_tx.clone())
.await;
match response {
Ok((handle, response)) => {
// TODO: better key
subscriptions.insert(
response.result.as_ref().unwrap().to_string(),
handle,
);
subscriptions.insert(response.result.as_ref().unwrap().to_string(), handle);
Ok(response.into())
}
@ -122,8 +118,7 @@ async fn read_web3_socket(
} else if payload.method == "eth_unsubscribe" {
let subscription_id = payload.params.unwrap().to_string();
let partial_response = match subscriptions.remove(&subscription_id)
{
let partial_response = match subscriptions.remove(&subscription_id) {
None => "false",
Some(handle) => {
handle.abort();
@ -131,17 +126,15 @@ async fn read_web3_socket(
}
};
let response = JsonRpcForwardedResponse::from_string(
partial_response.to_string(),
id.clone(),
);
let response =
JsonRpcForwardedResponse::from_string(partial_response.to_string(), id.clone());
Ok(response.into())
} else {
// TODO: if this is a subscription request, we need to do some special handling. something with channels
// TODO: just handle subscribe_newBlock
app.0.proxy_web3_rpc(payload.into()).await
app.proxy_web3_rpc(payload.into()).await
};
(id, response)
@ -164,9 +157,38 @@ async fn read_web3_socket(
.unwrap();
Message::Text(response_str)
}
async fn read_web3_socket(
app: Extension<Arc<Web3ProxyApp>>,
mut ws_rx: SplitStream<WebSocket>,
response_tx: flume::Sender<Message>,
) {
let mut subscriptions = HashMap::new();
while let Some(Ok(msg)) = ws_rx.next().await {
// new message from our client. forward to a backend and then send it through response_tx
let response_msg = match msg {
Message::Text(payload) => {
handle_socket_payload(app.0.as_ref(), &payload, &response_tx, &mut subscriptions)
.await
}
Message::Ping(x) => Message::Pong(x),
_ => unimplemented!(),
Message::Pong(x) => {
debug!("pong: {:?}", x);
continue;
}
Message::Close(_) => {
info!("closing websocket connection");
break;
}
Message::Binary(mut payload) => {
// TODO: what should we do here?
let payload = from_utf8_mut(&mut payload).unwrap();
handle_socket_payload(app.0.as_ref(), payload, &response_tx, &mut subscriptions)
.await
}
};
match response_tx.send_async(response_msg).await {