1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! Stream abstraction for rotor
//!
//! Assumptions:
//!
//! 1. You read data by length-prefixed or fixed-string-delimited chunks rather
//!    than byte-by-byte
//! 2. Each chunk fits memory
//! 3. Your data stream is not entirely full-duplex: while you can read and
//!    write simultaneously, when you apply pushback (i.e. waiting for bytes to
//!    be flushed), you can't do reads [*]
//!
//! [*] This matches HTTP perfectly, and most bidirectional interactive
//!     workflows (including based on websockets). But for some cases may be
//!     hard to implement. One such case is when you need to generate some
//!     output stream (you can't buffer it), and have to parse input stream at
//!     the same time.

extern crate netbuf;
extern crate memchr;
extern crate rotor;
extern crate time;
extern crate void;
#[macro_use] extern crate quick_error;


mod substr;
mod transport;
mod protocol;
mod stream;
mod accept;

pub use protocol::{Protocol, Expectation, Exception};
pub use accept::{Accepted};

use std::any::Any;
use std::io::{Read, Write};
use time::SteadyTime;

use rotor::{Machine, Evented, Timeout};
use rotor::mio::{TryAccept};

pub use netbuf::{Buf, MAX_BUF_SIZE};
pub type Deadline = SteadyTime;
pub type Request<M> = Option<(M, Expectation, Deadline)>;

// Any is needed to use Stream as a Seed for Machine
pub trait StreamSocket: Read + Write + Evented + Any {}

pub struct Transport<'a, S: StreamSocket> {
    sock: &'a mut S,
    inbuf: &'a mut Buf,
    outbuf: &'a mut Buf,
}

/// Socket acceptor State Machine
///
/// TODO(tailhook) Currently this panics when there is no slab space when
/// accepting a connection. This may be fixed by sleeping and retrying
pub enum Accept<M: Machine, A: TryAccept+Sized> {
    Server(A),
    Connection(M),
}

pub struct Stream<P: Protocol> {
    socket: P::Socket,
    fsm: P,
    expectation: Expectation,
    deadline: Deadline,
    timeout: Timeout,
    inbuf: Buf,
    outbuf: Buf,
}

struct StreamImpl<S: StreamSocket> {
    socket: S,
    deadline: Deadline,
    timeout: Timeout,
    inbuf: Buf,
    outbuf: Buf,
}

impl<T> StreamSocket for T where T: Read, T: Write, T: Evented, T:Any {}