use embedded_websocket as ws;
use embedded_websocket::WebSocketOptions;
use std::io::{Read, Write};
use std::net::TcpStream;
use std::str::Utf8Error;
use ws::{
WebSocket, WebSocketCloseStatusCode, WebSocketReceiveMessageType, WebSocketSendMessageType,
};
#[derive(Debug)]
pub enum WebClientError {
Io(std::io::Error),
WebSocket(ws::Error),
Utf8Error,
}
type Result<T> = std::result::Result<T, WebClientError>;
impl From<std::io::Error> for WebClientError {
fn from(err: std::io::Error) -> WebClientError {
WebClientError::Io(err)
}
}
impl From<ws::Error> for WebClientError {
fn from(err: ws::Error) -> WebClientError {
WebClientError::WebSocket(err)
}
}
impl From<Utf8Error> for WebClientError {
fn from(_: Utf8Error) -> WebClientError {
WebClientError::Utf8Error
}
}
pub fn template_client() -> Result<()> {
let mut buffer1: [u8; 1000] = [0; 1000];
let mut buffer2: [u8; 1000] = [0; 1000];
let mut websocket = ws::WebSocket::new_client(rand::thread_rng());
let websocket_options = WebSocketOptions {
path: "/chat",
host: "localhost",
origin: "http://localhost",
sub_protocols: None,
additional_headers: None,
};
let (_len, web_socket_key) = websocket.client_connect(&websocket_options, &mut buffer1)?;
let received_size = 0;
websocket.client_accept(&web_socket_key, &mut buffer1[..received_size])?;
let _len = websocket.write(
ws::WebSocketSendMessageType::Text,
true,
&"hello".as_bytes(),
&mut buffer1,
)?;
let ws_result = websocket.read(&buffer1[..received_size], &mut buffer2)?;
let _response = std::str::from_utf8(&buffer2[..ws_result.len_to])?;
let _len = websocket.close(
ws::WebSocketCloseStatusCode::NormalClosure,
None,
&mut buffer1,
)?;
let _ws_result = websocket.read(&buffer1[..received_size], &mut buffer2)?;
Ok(())
}
fn write_all(stream: &mut TcpStream, buffer: &[u8]) -> Result<()> {
let mut from = 0;
loop {
let bytes_sent = stream.write(&buffer[from..])?;
from = from + bytes_sent;
if from == buffer.len() {
break;
}
}
stream.flush()?;
Ok(())
}
fn main() -> Result<()> {
let address = "127.0.0.1:1337";
println!("Connecting to: {}", address);
let mut stream = TcpStream::connect(address)?;
println!("Connected.");
let mut buffer1: [u8; 4000] = [0; 4000];
let mut buffer2: [u8; 4000] = [0; 4000];
let mut ws_client = WebSocket::new_client(rand::thread_rng());
let websocket_options = WebSocketOptions {
path: "/chat",
host: "localhost",
origin: "http://localhost:1337",
sub_protocols: None,
additional_headers: None,
};
let (len, web_socket_key) = ws_client.client_connect(&websocket_options, &mut buffer1)?;
println!("Sending opening handshake: {} bytes", len);
write_all(&mut stream, &buffer1[..len])?;
let received_size = stream.read(&mut buffer1)?;
ws_client.client_accept(&web_socket_key, &mut buffer1[..received_size])?;
println!("Opening handshake completed successfully");
let message = "Hello, World!";
let send_size = ws_client.write(
WebSocketSendMessageType::Text,
true,
&message.as_bytes(),
&mut buffer1,
)?;
println!("Sending '{}': {} bytes", message, send_size);
write_all(&mut stream, &buffer1[..send_size])?;
let received_size = stream.read(&mut buffer1)?;
println!("Received: {} bytes", received_size);
let ws_result = ws_client.read(&buffer1[..received_size], &mut buffer2)?;
match ws_result.message_type {
WebSocketReceiveMessageType::Text => {
let s = std::str::from_utf8(&buffer2[..ws_result.len_to])?;
println!("Text reply from server: {}", s);
}
_ => {
let s = std::str::from_utf8(&buffer2[..ws_result.len_to])?;
println!(
"Unexpected response from server: {:?} {} bytes: {}",
ws_result.message_type, ws_result.len_to, s
);
}
}
let send_size = ws_client.close(WebSocketCloseStatusCode::NormalClosure, None, &mut buffer2)?;
stream.write(&buffer2[..send_size])?;
println!("Sent close handshake");
let received_size = stream.read(&mut buffer1)?;
println!("Received: {} bytes", received_size);
let ws_result = ws_client.read(&buffer1[..received_size], &mut buffer2)?;
match ws_result.message_type {
WebSocketReceiveMessageType::CloseCompleted => {
println!("Completed close handshake");
}
_ => {
println!(
"Received unexpected message: {:?} {} bytes",
ws_result.message_type, ws_result.len_to
);
}
}
Ok(())
}