Skip to content

Instantly share code, notes, and snippets.

@ssrlive
Last active November 6, 2022 10:37
Show Gist options
  • Save ssrlive/be51467031e3a30fdd2dd7a6aa41a858 to your computer and use it in GitHub Desktop.
Save ssrlive/be51467031e3a30fdd2dd7a6aa41a858 to your computer and use it in GitHub Desktop.
fn main() {
let f = move || -> anyhow::Result<()> {
let url = url::Url::parse("ws://127.0.0.1:9001")?;
let (mut socket, response) = tungstenite::connect(url)?;
println!("Connected to the server");
println!("Response HTTP code: {}", response.status());
println!("Response contains the following headers:");
for (ref header, _value) in response.headers() {
println!("* {} : {}", header, _value.to_str()?);
}
socket.write_message(tungstenite::Message::Text("Hello WebSocket".into()))?;
loop {
let msg = socket.read_message()?;
println!("Received: {}", msg);
}
};
if let Err(e) = f() {
println!("Error: {}", e);
}
}
fn main() -> anyhow::Result<()> {
let server = std::net::TcpListener::bind("127.0.0.1:9001")?;
for stream in server.incoming() {
std::thread::spawn(move || {
let addr = stream.as_ref().unwrap().peer_addr().unwrap();
println!("New connection: {addr}");
let f = move || -> anyhow::Result<()> {
let mut websocket = tungstenite::accept(stream?)?;
loop {
let msg = websocket.read_message()?;
if msg.is_close() {
break;
}
println!("Received: {}", msg);
websocket.write_message(msg)?;
}
Ok(())
};
if let Err(e) = f() {
println!("Error: {e}");
}
println!("connection closed {addr}");
});
}
Ok(())
}
use env_logger;
use futures_util::{SinkExt, StreamExt};
use httparse;
use log::*;
use tokio::net::{TcpListener, TcpStream};
use tokio_tungstenite::accept_hdr_async;
use tungstenite::{
handshake::server::{ErrorResponse, Request, Response},
Result,
};
const TARGET_ADDRESS: &str = "Target-Address";
async fn accept_connection(stream: TcpStream) {
if let Err(e) = handle_connection(stream).await {
error!("{e}");
}
}
async fn check_uri_path(stream: &TcpStream, path: &str) -> Result<bool> {
let mut buf = [0; 512];
stream.peek(&mut buf).await?;
let mut headers = [httparse::EMPTY_HEADER; 512];
let mut req = httparse::Request::new(&mut headers);
req.parse(&buf)?;
if let Some(p) = req.path {
if p == path {
return Ok(true);
}
}
Ok(false)
}
async fn handle_connection(stream: TcpStream) -> Result<()> {
if !check_uri_path(&stream, "/my_secret_path").await? {
warn!("Invalid path");
}
let peer = stream.peer_addr()?;
let mut target_address = "".to_string();
let mut uri_path = "".to_string();
let check_headers_callback =
|req: &Request, res: Response| -> std::result::Result<Response, ErrorResponse> {
uri_path = req.uri().path().to_string();
req.headers().get(TARGET_ADDRESS).map(|value| {
if let Ok(value) = value.to_str() {
info!("The value of the \"{TARGET_ADDRESS}\" is: {}", value);
target_address = value.to_string();
}
});
Ok(res)
};
let mut ws_stream = accept_hdr_async(stream, check_headers_callback).await?;
info!("target address: \"{}\" uri path: \"{}\"", target_address, uri_path);
info!("New WebSocket connection: {}", peer);
while let Some(msg) = ws_stream.next().await {
let msg = msg?;
if msg.is_close() {
info!("WebSocket connection closed: {}", peer);
break;
}
if msg.is_text() || msg.is_binary() {
ws_stream.send(msg).await?;
}
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();
let addr = "0.0.0.0:9002";
let listener = TcpListener::bind(&addr).await?;
info!("Listening on: {}", addr);
while let Ok((stream, _)) = listener.accept().await {
tokio::spawn(accept_connection(stream));
}
Ok(())
}
@ssrlive
Copy link
Author

ssrlive commented Nov 5, 2022

Cargo.toml

[dependencies]
anyhow = "1.0.32"
tungstenite = "*"
url = { version = "2.1.0", optional = true }

Cargo.toml for ws-server2.rs

[dependencies]
log = "0.4"
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }
tokio = { version = "1.0.0", features = ["full"] }
tungstenite = { version = "0.17.3" }
tokio-tungstenite = { version = "*" }
env_logger = "0.9"
httparse = "1.8.0"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment