use std::io::{self, Read, Write};
use super::{Connection, Error, Step};
fn ioerr(e: Error) -> io::Error {
io::Error::other(e)
}
#[cfg(unix)]
pub struct SignerSource {
fd: std::os::fd::RawFd,
}
#[cfg(unix)]
impl SignerSource {
pub fn new(readiness: &super::Readiness) -> Self {
use std::os::fd::AsRawFd;
SignerSource {
fd: readiness.as_raw_fd(),
}
}
}
#[cfg(unix)]
impl ::mio::event::Source for SignerSource {
fn register(
&mut self,
registry: &::mio::Registry,
token: ::mio::Token,
interests: ::mio::Interest,
) -> io::Result<()> {
::mio::unix::SourceFd(&self.fd).register(registry, token, interests)
}
fn reregister(
&mut self,
registry: &::mio::Registry,
token: ::mio::Token,
interests: ::mio::Interest,
) -> io::Result<()> {
::mio::unix::SourceFd(&self.fd).reregister(registry, token, interests)
}
fn deregister(&mut self, registry: &::mio::Registry) -> io::Result<()> {
::mio::unix::SourceFd(&self.fd).deregister(registry)
}
}
pub fn drive_handshake<S>(
conn: &mut Connection,
sock: &mut S,
poll: &mut ::mio::Poll,
sock_token: ::mio::Token,
signer_token: ::mio::Token,
) -> io::Result<()>
where
S: ::mio::event::Source + Read + Write,
{
use ::mio::{Events, Interest};
poll.registry()
.register(sock, sock_token, Interest::READABLE | Interest::WRITABLE)?;
let mut events = Events::with_capacity(8);
let result = drive_loop(conn, sock, poll, &mut events, sock_token, signer_token);
let _ = poll.registry().deregister(sock);
result
}
fn drive_loop<S>(
conn: &mut Connection,
sock: &mut S,
poll: &mut ::mio::Poll,
events: &mut ::mio::Events,
sock_token: ::mio::Token,
signer_token: ::mio::Token,
) -> io::Result<()>
where
S: ::mio::event::Source + Read + Write,
{
let _ = (sock_token, signer_token);
loop {
match conn.drive().map_err(ioerr)? {
Step::Complete => return Ok(()),
Step::WantWrite => {
let out = conn.pop().map_err(ioerr)?;
let mut off = 0;
while off < out.len() {
match sock.write(&out[off..]) {
Ok(0) => return Err(io::ErrorKind::WriteZero.into()),
Ok(n) => off += n,
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
poll.poll(events, None)?;
}
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
}
Step::WantRead => {
let mut buf = [0u8; 16 * 1024];
let mut progressed = false;
loop {
match sock.read(&mut buf) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"peer closed during handshake",
));
}
Ok(n) => {
let mut fed = 0;
while fed < n {
fed += conn.feed(&buf[fed..n]).map_err(ioerr)?;
}
progressed = true;
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => break,
Err(e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !progressed {
poll.poll(events, None)?;
}
}
Step::WantSigner(readiness) => {
#[cfg(unix)]
if let Some(r) = readiness {
let mut src = SignerSource::new(&r);
let mut spoll = ::mio::Poll::new()?;
spoll
.registry()
.register(&mut src, signer_token, ::mio::Interest::READABLE)?;
let mut sev = ::mio::Events::with_capacity(4);
loop {
spoll.poll(&mut sev, None)?;
if sev.iter().any(|ev| ev.token() == signer_token) {
break;
}
}
continue;
}
let _ = &readiness;
}
}
}
}