server: implement server

pull/7/head
Alexey Galakhov 8 years ago
parent 4714773370
commit 7dccc51277
  1. 36
      examples/autobahn-server.rs
  2. 71
      src/handshake/server.rs
  3. 1
      src/lib.rs
  4. 8
      src/server.rs

@ -0,0 +1,36 @@
#[macro_use] extern crate log;
extern crate env_logger;
extern crate ws2;
use std::net::{TcpListener, TcpStream};
use std::thread::spawn;
use ws2::server::accept;
use ws2::error::Result;
use ws2::handshake::Handshake;
fn handle_client(stream: TcpStream) -> Result<()> {
let mut socket = accept(stream).handshake_wait()?;
loop {
let msg = socket.read_message()?;
socket.write_message(msg)?;
}
}
fn main() {
env_logger::init().unwrap();
let server = TcpListener::bind("127.0.0.1:9001").unwrap();
for stream in server.incoming() {
spawn(move || {
match stream {
Ok(stream) => match handle_client(stream) {
Ok(_) => (),
Err(e) => warn!("Error in client: {}", e),
},
Err(e) => warn!("Error accepting stream: {}", e),
}
});
}
}

@ -1,9 +1,20 @@
use std::io::{Cursor, Read, Write};
use bytes::Buf;
use httparse;
use httparse::Status;
use input_buffer::{InputBuffer, MIN_READ};
use error::{Error, Result};
use super::{Headers, Httparse, FromHttparse, convert_key, MAX_HEADERS};
use super::{
Handshake,
HandshakeResult,
Headers,
Httparse,
FromHttparse,
convert_key,
MAX_HEADERS
};
use protocol::{WebSocket, Role};
/// Request from the client.
pub struct Request {
@ -56,6 +67,64 @@ impl<'h, 'b: 'h> FromHttparse<httparse::Request<'h, 'b>> for Request {
}
}
/// Server handshake
pub struct ServerHandshake<Stream> {
stream: Stream,
state: HandshakeState,
}
impl<Stream: Read + Write> ServerHandshake<Stream> {
/// Start a new server handshake on top of given stream.
pub fn new(stream: Stream) -> Self {
ServerHandshake {
stream: stream,
state: HandshakeState::ReceivingRequest(InputBuffer::with_capacity(MIN_READ)),
}
}
}
impl<Stream: Read + Write> Handshake for ServerHandshake<Stream> {
type Stream = WebSocket<Stream>;
fn handshake(mut self) -> Result<HandshakeResult<Self>> {
debug!("Performing server handshake...");
match self.state {
HandshakeState::ReceivingRequest(mut req_buf) => {
req_buf.reserve(MIN_READ, usize::max_value())
.map_err(|_| Error::Capacity("Header too long".into()))?;
req_buf.read_from(&mut self.stream)?;
let state = if let Some(req) = Request::parse(&mut req_buf)? {
let resp = req.reply()?;
HandshakeState::SendingResponse(Cursor::new(resp))
} else {
HandshakeState::ReceivingRequest(req_buf)
};
Ok(HandshakeResult::Incomplete(ServerHandshake {
state: state,
..self
}))
}
HandshakeState::SendingResponse(mut resp) => {
let size = self.stream.write(Buf::bytes(&resp))?;
Buf::advance(&mut resp, size);
if resp.has_remaining() {
Ok(HandshakeResult::Incomplete(ServerHandshake {
state: HandshakeState::SendingResponse(resp),
..self
}))
} else {
let ws = WebSocket::from_raw_socket(self.stream, Role::Server);
Ok(HandshakeResult::Done(ws))
}
}
}
}
}
enum HandshakeState {
ReceivingRequest(InputBuffer),
SendingResponse(Cursor<Vec<u8>>),
}
#[cfg(test)]
mod tests {

@ -22,6 +22,7 @@ extern crate utf8;
pub mod error;
pub mod protocol;
pub mod client;
pub mod server;
pub mod handshake;
mod input_buffer;

@ -0,0 +1,8 @@
use std::net::TcpStream;
use handshake::server::ServerHandshake;
/// Accept the given TcpStream as a WebSocket.
pub fn accept(stream: TcpStream) -> ServerHandshake<TcpStream> {
ServerHandshake::new(stream)
}
Loading…
Cancel
Save