handle binary and text messages
This commit is contained in:
parent
45fd1b2ff1
commit
a6a238fff2
@ -309,6 +309,8 @@ impl Web3ProxyApp {
|
|||||||
) -> anyhow::Result<JsonRpcForwardedResponse> {
|
) -> anyhow::Result<JsonRpcForwardedResponse> {
|
||||||
trace!("Received request: {:?}", request);
|
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: how much should we retry? probably with a timeout and not with a count like this
|
||||||
// TODO: think more about this loop.
|
// TODO: think more about this loop.
|
||||||
// // TODO: add more to this span
|
// // TODO: add more to this span
|
||||||
|
@ -237,7 +237,14 @@ impl Web3Connections {
|
|||||||
let mut pending_synced_connections = SyncedConnections::default();
|
let mut pending_synced_connections = SyncedConnections::default();
|
||||||
|
|
||||||
while let Ok((new_block, rpc_id)) = block_receiver.recv_async().await {
|
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();
|
let new_block_hash = new_block.hash.unwrap();
|
||||||
|
|
||||||
// TODO: span with more in it?
|
// TODO: span with more in it?
|
||||||
|
@ -7,14 +7,18 @@ use axum::{
|
|||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Extension, Json, Router,
|
Extension, Json, Router,
|
||||||
};
|
};
|
||||||
use futures::stream::{SplitSink, SplitStream, StreamExt};
|
|
||||||
use futures::SinkExt;
|
use futures::SinkExt;
|
||||||
|
use futures::{
|
||||||
|
future::AbortHandle,
|
||||||
|
stream::{SplitSink, SplitStream, StreamExt},
|
||||||
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::value::RawValue;
|
use serde_json::value::RawValue;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::str::from_utf8_mut;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::{error, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::Web3ProxyApp,
|
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));
|
tokio::spawn(read_web3_socket(app, ws_rx, response_tx));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_web3_socket(
|
async fn handle_socket_payload(
|
||||||
app: Extension<Arc<Web3ProxyApp>>,
|
app: &Web3ProxyApp,
|
||||||
mut ws_rx: SplitStream<WebSocket>,
|
payload: &str,
|
||||||
response_tx: flume::Sender<Message>,
|
response_tx: &flume::Sender<Message>,
|
||||||
) {
|
subscriptions: &mut HashMap<String, AbortHandle>,
|
||||||
let mut subscriptions = HashMap::new();
|
) -> Message {
|
||||||
|
let (id, response) = match serde_json::from_str::<JsonRpcRequest>(payload) {
|
||||||
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) {
|
|
||||||
Ok(payload) => {
|
Ok(payload) => {
|
||||||
let id = payload.id.clone();
|
let id = payload.id.clone();
|
||||||
|
|
||||||
let response: anyhow::Result<JsonRpcForwardedResponseEnum> =
|
let response: anyhow::Result<JsonRpcForwardedResponseEnum> = if payload.method
|
||||||
if payload.method == "eth_subscribe" {
|
== "eth_subscribe"
|
||||||
|
{
|
||||||
// TODO: if we pass eth_subscribe the response_tx, we
|
// TODO: if we pass eth_subscribe the response_tx, we
|
||||||
let response = app
|
let response = app
|
||||||
.0
|
|
||||||
.eth_subscribe(id.clone(), payload, response_tx.clone())
|
.eth_subscribe(id.clone(), payload, response_tx.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
Ok((handle, response)) => {
|
Ok((handle, response)) => {
|
||||||
// TODO: better key
|
// TODO: better key
|
||||||
subscriptions.insert(
|
subscriptions.insert(response.result.as_ref().unwrap().to_string(), handle);
|
||||||
response.result.as_ref().unwrap().to_string(),
|
|
||||||
handle,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(response.into())
|
Ok(response.into())
|
||||||
}
|
}
|
||||||
@ -122,8 +118,7 @@ async fn read_web3_socket(
|
|||||||
} else if payload.method == "eth_unsubscribe" {
|
} else if payload.method == "eth_unsubscribe" {
|
||||||
let subscription_id = payload.params.unwrap().to_string();
|
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",
|
None => "false",
|
||||||
Some(handle) => {
|
Some(handle) => {
|
||||||
handle.abort();
|
handle.abort();
|
||||||
@ -131,17 +126,15 @@ async fn read_web3_socket(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = JsonRpcForwardedResponse::from_string(
|
let response =
|
||||||
partial_response.to_string(),
|
JsonRpcForwardedResponse::from_string(partial_response.to_string(), id.clone());
|
||||||
id.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(response.into())
|
Ok(response.into())
|
||||||
} else {
|
} else {
|
||||||
// TODO: if this is a subscription request, we need to do some special handling. something with channels
|
// TODO: if this is a subscription request, we need to do some special handling. something with channels
|
||||||
// TODO: just handle subscribe_newBlock
|
// TODO: just handle subscribe_newBlock
|
||||||
|
|
||||||
app.0.proxy_web3_rpc(payload.into()).await
|
app.proxy_web3_rpc(payload.into()).await
|
||||||
};
|
};
|
||||||
|
|
||||||
(id, response)
|
(id, response)
|
||||||
@ -164,9 +157,38 @@ async fn read_web3_socket(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Message::Text(response_str)
|
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),
|
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 {
|
match response_tx.send_async(response_msg).await {
|
||||||
|
Loading…
Reference in New Issue
Block a user