rust/chg/src/attachio.rs
author Yuya Nishihara <yuya@tcha.org>
Fri, 10 Apr 2020 22:07:11 +0900
changeset 44738 1be605526c34
parent 44689 6bef9d43cc55
child 44749 cb5822e6e545
permissions -rw-r--r--
rust-chg: reimplement attach_io operation as async function In short, MessageLoop<Connection> was redesigned as Protocol<Connection>, and the protocol methods no longer consume self. API changes are briefly documented in the following page: https://docs.rs/tokio-hglib/0.3.0/tokio_hglib/struct.Protocol.html Differential Revision: https://phab.mercurial-scm.org/D8442
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
// Copyright 2018 Yuya Nishihara <yuya@tcha.org>
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     2
//
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
// This software may be used and distributed according to the terms of the
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
// GNU General Public License version 2 or any later version.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
//! Functions to send client-side fds over the command server channel.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     8
use std::io;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
use std::os::unix::io::AsRawFd;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    10
use tokio_hglib::codec::ChannelMessage;
44738
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    11
use tokio_hglib::{Connection, Protocol};
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
44689
6bef9d43cc55 rust-chg: use "crate::" to import local modules
Yuya Nishihara <yuya@tcha.org>
parents: 44688
diff changeset
    13
use crate::message;
6bef9d43cc55 rust-chg: use "crate::" to import local modules
Yuya Nishihara <yuya@tcha.org>
parents: 44688
diff changeset
    14
use crate::procutil;
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
44738
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    16
/// Sends client-side fds over the command server channel.
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    17
///
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
/// This works as follows:
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
/// 1. Client sends "attachio" request.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
/// 2. Server sends back 1-byte input request.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
/// 3. Client sends fds with 1-byte dummy payload in response.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
/// 4. Server returns the number of the fds received.
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
///
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
/// If the stderr is omitted, it will be redirected to the stdout. This
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
/// allows us to attach the pager stdin to both stdout and stderr, and
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
/// dispose of the client-side handle once attached.
44738
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    27
pub async fn attach_io(
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    28
    proto: &mut Protocol<impl Connection + AsRawFd>,
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    29
    stdin: impl AsRawFd,
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    30
    stdout: impl AsRawFd,
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    31
    stderr: Option<impl AsRawFd>,
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    32
) -> io::Result<()> {
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    33
    // TODO: unindent
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    34
    {
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    35
        proto.send_command("attachio").await?;
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    36
        loop {
44738
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    37
            match proto.fetch_response().await? {
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    38
                ChannelMessage::Data(b'r', data) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
                    let fd_cnt = message::parse_result_code(data)?;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
                    if fd_cnt == 3 {
44738
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    41
                        return Ok(());
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
                    } else {
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    43
                        return Err(io::Error::new(
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    44
                            io::ErrorKind::InvalidData,
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    45
                            "unexpected attachio result",
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    46
                        ));
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    47
                    }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    48
                }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    49
                ChannelMessage::Data(..) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    50
                    // just ignore data sent to uninteresting (optional) channel
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    51
                }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    52
                ChannelMessage::InputRequest(1) => {
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    53
                    // this may fail with EWOULDBLOCK in theory, but the
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    54
                    // payload is quite small, and the send buffer should
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    55
                    // be empty so the operation will complete immediately
44738
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    56
                    let sock_fd = proto.as_raw_fd();
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    57
                    let ifd = stdin.as_raw_fd();
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    58
                    let ofd = stdout.as_raw_fd();
1be605526c34 rust-chg: reimplement attach_io operation as async function
Yuya Nishihara <yuya@tcha.org>
parents: 44689
diff changeset
    59
                    let efd = stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    60
                    procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
                }
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    62
                ChannelMessage::InputRequest(..)
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    63
                | ChannelMessage::LineRequest(..)
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    64
                | ChannelMessage::SystemRequest(..) => {
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    65
                    return Err(io::Error::new(
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    66
                        io::ErrorKind::InvalidData,
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    67
                        "unsupported request while attaching io",
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39972
diff changeset
    68
                    ));
39972
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    69
                }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    70
            }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    71
        }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    72
    }
7a0ffdd4af78 rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    73
}