websockets-rs / rust-websocket

A WebSocket (RFC6455) library written in Rust
http://websockets-rs.github.io/rust-websocket/
MIT License
1.55k stars 223 forks source link

Should server example using coroutines be added? #144

Open vi opened 7 years ago

vi commented 7 years ago

I've created a port of "async-autobahn-server.rs" (sans error handling) using the futures-await / experimental coroutines.

#![feature(proc_macro, conservative_impl_trait, generators)]

extern crate websocket;
//extern crate futures;
extern crate futures_await as futures;
extern crate tokio_core;

use futures::prelude::*;

use websocket::message::OwnedMessage;
use websocket::async::Server;

use tokio_core::reactor::Core;
use futures::{Future, Sink, Stream};

type UsualClient = websocket::client::async::Framed<tokio_core::net::TcpStream, websocket::async::MessageCodec<websocket::OwnedMessage>>;

#[async]
fn serve_client(client: UsualClient) -> std::result::Result<(),()> {
    let (mut sink, stream) = client.split();
    #[async]
    for m in stream.map_err(|_|()) {
        if m.is_close() { break; }
        let fwd = match m {
            OwnedMessage::Ping(p) => OwnedMessage::Pong(p),
            OwnedMessage::Pong(_) => continue,
            _ => m,
        };
        sink = await!(sink.send(fwd).map_err(|_|()))?;
    }
    await!(sink.send(OwnedMessage::Close(None)).map_err(|_|()))?;
    Ok(())
}

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("127.0.0.1:9002", &handle).unwrap();

    let str = server.incoming().map_err(|_|());

    let f = async_block! {
        #[async]
        for (upgrade, addr) in str {
            // accept the request to be a ws connection
            println!("Got a connection from: {}", addr);
            let (client, _headers) = await!(upgrade.accept().map_err(|_|()))?;
            let f = serve_client(client);
            handle.spawn(f.map_err(|_|()).map(|_|()));
        }
        Ok::<(),()>(())
    };

    core.run(f).unwrap();
}

Should it be added to the examples or better to wait for stabilization of respective Rust features?

marcelbuesing commented 7 years ago

I think this looks great! You should probably create a pull request for it.

vi commented 7 years ago

How do I avoid annoying non-nightly users with a fails-to-build example then?

Also futures_await crate isn't even on crates.io. Looks like it already is.

vi commented 7 years ago

Note: published app based on this example to crates.io: wsbroad. Was previously only on Github. It also shows communication between connected clients.

marcelbuesing commented 7 years ago

Not sure what to say about the fails-to-build example, I guess the compiler message will make it obvious why the example fails to build with stable. I personally would not worry about that.

vi commented 7 years ago

But as far as I know cargo test also tries building all examples. Breaking cargo test on non-nightly is a bad idea.

marcelbuesing commented 7 years ago

Ah I was not aware of that. Seems your right, I just tested it. Maybe create an examples-nightly folder that is not picked up by cargo test.

illegalprime commented 6 years ago

@vi awesome stuff, merge it into some other folder until we figure out what to do with the build step.