<commit_before>// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//! ARM PL031 Real Time Clock
//!
//! This module implements a PL031 Real Time Clock (RTC) that provides to provides long time base counter.
//! This is achieved by generating an interrupt signal after counting for a programmed number of cycles of
//! a real-time clock input.
//!

use std::fmt;
use std::ops::Add;
use std::{io, result};

use byteorder::{ByteOrder, LittleEndian};

use crate::BusDevice;
use logger::{Metric, METRICS};
use sys_util::EventFd;
use time::{SteadyTime, Timespec};
//use bus::Error;

// As you can see in https://static.docs.arm.com/ddi0224/c/real_time_clock_pl031_r1p3_technical_reference_manual_DDI0224C.pdf
// at section 3.2 Summary of RTC registers, the total size occupied by this device is 0x000 -> 0xFFC + 4 = 0x1000.
// From 0x0 to 0x1C we have following registers:
const RTCDR: u64 = 0x0; // Data Register.
const RTCMR: u64 = 0x4; // Match Register.
const RTCLR: u64 = 0x8; // Load Regiser.
const RTCCR: u64 = 0xc; // Control Register.
const RTCIMSC: u64 = 0x10; // Interrupt Mask Set or Clear Register.
const RTCRIS: u64 = 0x14; // Raw Interrupt Status.
const RTCMIS: u64 = 0x18; // Masked Interrupt Status.
const RTCICR: u64 = 0x1c; // Interrupt Clear Register.
                          // From 0x020 to 0xFDC => reserved space.
                          // From 0xFE0 to 0x1000 => Peripheral and PrimeCell Identification Registers which are Read Only registers.
                          // AMBA standard devices have CIDs (Cell IDs) and PIDs (Peripheral IDs). The linux kernel will look for these in order to assert the identity
                          // of these devices (i.e look at the `amba_device_try_add` function).
                          // We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
const PL031_ID: [u8; 8] = [0x31, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
// We are only interested in the margins.
const AMBA_ID_LOW: u64 = 0xFE0;
const AMBA_ID_HIGH: u64 = 0x1000;

#[derive(Debug)]
pub enum Error {
    BadWriteOffset(u64),
    InterruptFailure(io::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::BadWriteOffset(offset) => write!(f, "Bad Write Offset: {}", offset),
            Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {}", e),
        }
    }
}
type Result<T> = result::Result<T, Error>;

/// A RTC device following the PL031 specification..
pub struct RTC {
    previous_now: SteadyTime,
    tick_offset: Timespec,
    // This is used for implementing the RTC alarm. However, in Firecracker we do not need it.
    match_value: u32,
    // Writes to this register load an update value into the RTC.
    load: u32,
    imsc: u32,
    ris: u32,
    interrupt_evt: EventFd,
}

impl RTC {
    /// Constructs an AMBA PL031 RTC device.
    pub fn new(interrupt_evt: EventFd) -> RTC {
        RTC {
            // This is used only for duration measuring purposes.
            previous_now: SteadyTime::now(),
            tick_offset: time::get_time(),
            match_value: 0,
            load: 0,
            imsc: 0,
            ris: 0,
            interrupt_evt,
        }
    }

    fn trigger_interrupt(&mut self) -> Result<()> {
        self.interrupt_evt.write(1).map_err(Error::InterruptFailure)
    }

    fn get_time(&self) -> u32 {
        let ts = self.tick_offset.add(SteadyTime::now() - self.previous_now);
        ts.sec as u32
    }

    fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
        match offset {
            RTCMR => {
                // The MR register is used for implementing the RTC alarm. A real time clock alarm is
                // a feature that can be used to allow a computer to 'wake up' after shut down to execute
                // tasks every day or on a certain day. It can sometimes be found in the 'Power Management'
                // section of a motherboard's BIOS setup. This is functionality that extends beyond
                // Firecracker intended use. However, we increment a metric just in case.
                self.match_value = val;
                METRICS.rtc.missed_write_count.inc();
            }
            RTCLR => {
                self.load = val;
                self.previous_now = SteadyTime::now();
                self.tick_offset = Timespec::new(i64::from(val), 0);
            }
            RTCIMSC => {
                self.imsc = val & 1;
                self.trigger_interrupt()?;
            }
            RTCICR => {
                // As per above mentioned doc, the interrupt is cleared by writing any data value to
                // the Interrupt Clear Register.
                self.ris = 0;
                self.trigger_interrupt()?;
            }
            RTCCR => (), // ignore attempts to turn off the timer.
            o => {
                return Err(Error::BadWriteOffset(o));
            }
        }
        Ok(())
    }
}

impl BusDevice for RTC {
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        let v;
        let mut read_ok = true;

        if offset < AMBA_ID_HIGH && offset >= AMBA_ID_LOW {
            let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
            v = u32::from(PL031_ID[index]);
        } else {
            v = match offset {
                RTCDR => self.get_time(),
                RTCMR => {
                    METRICS.rtc.missed_read_count.inc();
                    // Even though we are not implementing RTC alarm we return the last value
                    self.match_value
                }
                RTCLR => self.load,
                RTCCR => 1, // RTC is always enabled.
                RTCIMSC => self.imsc,
                RTCRIS => self.ris,
                RTCMIS => self.ris & self.imsc,
                _ => {
                    read_ok = false;
                    0
                }
            };
        }
        if read_ok && data.len() <= 4 {
            LittleEndian::write_u32(data, v);
        } else {
            warn!(
                "Invalid RTC PL031 read: offset {}, data length {}",
                offset,
                data.len()
            );
            METRICS.rtc.error_count.inc();
        }
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        if data.len() <= 4 {
            let v = LittleEndian::read_u32(data);
            if let Err(e) = self.handle_write(offset, v) {
                warn!("Failed to write to RTC PL031 device: {}", e);
                METRICS.rtc.error_count.inc();
            }
        } else {
            warn!(
                "Invalid RTC PL031 write: offset {}, data length {}",
                offset,
                data.len()
            );
            METRICS.rtc.error_count.inc();
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_rtc_read_write_and_event() {
        let mut rtc = RTC::new(EventFd::new().unwrap());
        let mut data = [0; 4];

        // Read and write to the MR register.
        LittleEndian::write_u32(&mut data, 123);
        rtc.write(RTCMR, &mut data);
        rtc.read(RTCMR, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(v, 123);

        // Read and write to the LR register.
        let v = time::get_time();
        LittleEndian::write_u32(&mut data, v.sec as u32);
        let tick_offset_before = rtc.tick_offset;
        let previous_now_before = rtc.previous_now;
        rtc.write(RTCLR, &mut data);

        assert!(rtc.tick_offset.sec == tick_offset_before.sec);
        assert!(rtc.previous_now > previous_now_before);

        rtc.read(RTCLR, &mut data);
        let v_read = LittleEndian::read_u32(&data);
        assert_eq!(v.sec as u32, v_read);

        // Read and write to IMSC register.
        // Test with non zero value.
        let non_zero = 1;
        LittleEndian::write_u32(&mut data, non_zero);
        rtc.write(RTCIMSC, &mut data);
        // The interrupt line should be on.
        assert!(rtc.interrupt_evt.read().unwrap() == 1);
        rtc.read(RTCIMSC, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(non_zero & 1, v);

        // Now test with 0.
        LittleEndian::write_u32(&mut data, 0);
        rtc.write(RTCIMSC, &mut data);
        rtc.read(RTCIMSC, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(0, v);

        // Read and write to the ICR register.
        LittleEndian::write_u32(&mut data, 1);
        rtc.write(RTCICR, &mut data);
        // The interrupt line should be on.
        assert!(rtc.interrupt_evt.read().unwrap() > 1);
        let v_before = LittleEndian::read_u32(&data);
        let no_errors_before = METRICS.rtc.error_count.count();

        rtc.read(RTCICR, &mut data);
        let no_errors_after = METRICS.rtc.error_count.count();
        let v = LittleEndian::read_u32(&data);
        // ICR is a  write only register. Data received should stay equal to data sent.
        assert_eq!(v, v_before);
        assert_eq!(no_errors_after - no_errors_before, 1);

        // Attempts to turn off the RTC should not go through.
        LittleEndian::write_u32(&mut data, 0);
        rtc.write(RTCCR, &mut data);
        rtc.read(RTCCR, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(v, 1);

        // Attempts to write beyond the writable space. Using here the space used to read
        // the CID and PID from.
        LittleEndian::write_u32(&mut data, 0);
        let no_errors_before = METRICS.rtc.error_count.count();
        rtc.write(AMBA_ID_LOW, &mut data);
        let no_errors_after = METRICS.rtc.error_count.count();
        assert_eq!(no_errors_after - no_errors_before, 1);
        // However, reading from the AMBA_ID_LOW should succeed upon read.

        let mut data = [0; 8];
        rtc.read(AMBA_ID_LOW, &mut data);
        let index = AMBA_ID_LOW + 3;
        assert_eq!(data[0], PL031_ID[((index - AMBA_ID_LOW) >> 2) as usize]);
    }
}
<commit_msg>aarch64: fix bug in rtc unit test<commit_after>// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//! ARM PL031 Real Time Clock
//!
//! This module implements a PL031 Real Time Clock (RTC) that provides to provides long time base counter.
//! This is achieved by generating an interrupt signal after counting for a programmed number of cycles of
//! a real-time clock input.
//!

use std::fmt;
use std::ops::Add;
use std::{io, result};

use byteorder::{ByteOrder, LittleEndian};

use crate::BusDevice;
use logger::{Metric, METRICS};
use sys_util::EventFd;
use time::{SteadyTime, Timespec};
//use bus::Error;

// As you can see in https://static.docs.arm.com/ddi0224/c/real_time_clock_pl031_r1p3_technical_reference_manual_DDI0224C.pdf
// at section 3.2 Summary of RTC registers, the total size occupied by this device is 0x000 -> 0xFFC + 4 = 0x1000.
// From 0x0 to 0x1C we have following registers:
const RTCDR: u64 = 0x0; // Data Register.
const RTCMR: u64 = 0x4; // Match Register.
const RTCLR: u64 = 0x8; // Load Regiser.
const RTCCR: u64 = 0xc; // Control Register.
const RTCIMSC: u64 = 0x10; // Interrupt Mask Set or Clear Register.
const RTCRIS: u64 = 0x14; // Raw Interrupt Status.
const RTCMIS: u64 = 0x18; // Masked Interrupt Status.
const RTCICR: u64 = 0x1c; // Interrupt Clear Register.
                          // From 0x020 to 0xFDC => reserved space.
                          // From 0xFE0 to 0x1000 => Peripheral and PrimeCell Identification Registers which are Read Only registers.
                          // AMBA standard devices have CIDs (Cell IDs) and PIDs (Peripheral IDs). The linux kernel will look for these in order to assert the identity
                          // of these devices (i.e look at the `amba_device_try_add` function).
                          // We are putting the expected values (look at 'Reset value' column from above mentioned document) in an array.
const PL031_ID: [u8; 8] = [0x31, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
// We are only interested in the margins.
const AMBA_ID_LOW: u64 = 0xFE0;
const AMBA_ID_HIGH: u64 = 0x1000;

#[derive(Debug)]
pub enum Error {
    BadWriteOffset(u64),
    InterruptFailure(io::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::BadWriteOffset(offset) => write!(f, "Bad Write Offset: {}", offset),
            Error::InterruptFailure(e) => write!(f, "Failed to trigger interrupt: {}", e),
        }
    }
}
type Result<T> = result::Result<T, Error>;

/// A RTC device following the PL031 specification..
pub struct RTC {
    previous_now: SteadyTime,
    tick_offset: Timespec,
    // This is used for implementing the RTC alarm. However, in Firecracker we do not need it.
    match_value: u32,
    // Writes to this register load an update value into the RTC.
    load: u32,
    imsc: u32,
    ris: u32,
    interrupt_evt: EventFd,
}

impl RTC {
    /// Constructs an AMBA PL031 RTC device.
    pub fn new(interrupt_evt: EventFd) -> RTC {
        RTC {
            // This is used only for duration measuring purposes.
            previous_now: SteadyTime::now(),
            tick_offset: time::get_time(),
            match_value: 0,
            load: 0,
            imsc: 0,
            ris: 0,
            interrupt_evt,
        }
    }

    fn trigger_interrupt(&mut self) -> Result<()> {
        self.interrupt_evt.write(1).map_err(Error::InterruptFailure)
    }

    fn get_time(&self) -> u32 {
        let ts = self.tick_offset.add(SteadyTime::now() - self.previous_now);
        ts.sec as u32
    }

    fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
        match offset {
            RTCMR => {
                // The MR register is used for implementing the RTC alarm. A real time clock alarm is
                // a feature that can be used to allow a computer to 'wake up' after shut down to execute
                // tasks every day or on a certain day. It can sometimes be found in the 'Power Management'
                // section of a motherboard's BIOS setup. This is functionality that extends beyond
                // Firecracker intended use. However, we increment a metric just in case.
                self.match_value = val;
                METRICS.rtc.missed_write_count.inc();
            }
            RTCLR => {
                self.load = val;
                self.previous_now = SteadyTime::now();
                self.tick_offset = Timespec::new(i64::from(val), 0);
            }
            RTCIMSC => {
                self.imsc = val & 1;
                self.trigger_interrupt()?;
            }
            RTCICR => {
                // As per above mentioned doc, the interrupt is cleared by writing any data value to
                // the Interrupt Clear Register.
                self.ris = 0;
                self.trigger_interrupt()?;
            }
            RTCCR => (), // ignore attempts to turn off the timer.
            o => {
                return Err(Error::BadWriteOffset(o));
            }
        }
        Ok(())
    }
}

impl BusDevice for RTC {
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        let v;
        let mut read_ok = true;

        if offset < AMBA_ID_HIGH && offset >= AMBA_ID_LOW {
            let index = ((offset - AMBA_ID_LOW) >> 2) as usize;
            v = u32::from(PL031_ID[index]);
        } else {
            v = match offset {
                RTCDR => self.get_time(),
                RTCMR => {
                    METRICS.rtc.missed_read_count.inc();
                    // Even though we are not implementing RTC alarm we return the last value
                    self.match_value
                }
                RTCLR => self.load,
                RTCCR => 1, // RTC is always enabled.
                RTCIMSC => self.imsc,
                RTCRIS => self.ris,
                RTCMIS => self.ris & self.imsc,
                _ => {
                    read_ok = false;
                    0
                }
            };
        }
        if read_ok && data.len() <= 4 {
            LittleEndian::write_u32(data, v);
        } else {
            warn!(
                "Invalid RTC PL031 read: offset {}, data length {}",
                offset,
                data.len()
            );
            METRICS.rtc.error_count.inc();
        }
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        if data.len() <= 4 {
            let v = LittleEndian::read_u32(data);
            if let Err(e) = self.handle_write(offset, v) {
                warn!("Failed to write to RTC PL031 device: {}", e);
                METRICS.rtc.error_count.inc();
            }
        } else {
            warn!(
                "Invalid RTC PL031 write: offset {}, data length {}",
                offset,
                data.len()
            );
            METRICS.rtc.error_count.inc();
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_rtc_read_write_and_event() {
        let mut rtc = RTC::new(EventFd::new().unwrap());
        let mut data = [0; 4];

        // Read and write to the MR register.
        LittleEndian::write_u32(&mut data, 123);
        rtc.write(RTCMR, &mut data);
        rtc.read(RTCMR, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(v, 123);

        // Read and write to the LR register.
        let v = time::get_time();
        LittleEndian::write_u32(&mut data, v.sec as u32);
        let tick_offset_before = rtc.tick_offset;
        let previous_now_before = rtc.previous_now;
        rtc.write(RTCLR, &mut data);

        assert!(rtc.tick_offset.sec == tick_offset_before.sec);
        assert!(rtc.previous_now > previous_now_before);

        rtc.read(RTCLR, &mut data);
        let v_read = LittleEndian::read_u32(&data);
        assert_eq!(v.sec as u32, v_read);

        // Read and write to IMSC register.
        // Test with non zero value.
        let non_zero = 1;
        LittleEndian::write_u32(&mut data, non_zero);
        rtc.write(RTCIMSC, &mut data);
        // The interrupt line should be on.
        assert!(rtc.interrupt_evt.read().unwrap() == 1);
        rtc.read(RTCIMSC, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(non_zero & 1, v);

        // Now test with 0.
        LittleEndian::write_u32(&mut data, 0);
        rtc.write(RTCIMSC, &mut data);
        rtc.read(RTCIMSC, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(0, v);

        // Read and write to the ICR register.
        LittleEndian::write_u32(&mut data, 1);
        rtc.write(RTCICR, &mut data);
        // The interrupt line should be on.
        assert!(rtc.interrupt_evt.read().unwrap() > 1);
        let v_before = LittleEndian::read_u32(&data);
        let no_errors_before = METRICS.rtc.error_count.count();

        rtc.read(RTCICR, &mut data);
        let no_errors_after = METRICS.rtc.error_count.count();
        let v = LittleEndian::read_u32(&data);
        // ICR is a  write only register. Data received should stay equal to data sent.
        assert_eq!(v, v_before);
        assert_eq!(no_errors_after - no_errors_before, 1);

        // Attempts to turn off the RTC should not go through.
        LittleEndian::write_u32(&mut data, 0);
        rtc.write(RTCCR, &mut data);
        rtc.read(RTCCR, &mut data);
        let v = LittleEndian::read_u32(&data);
        assert_eq!(v, 1);

        // Attempts to write beyond the writable space. Using here the space used to read
        // the CID and PID from.
        LittleEndian::write_u32(&mut data, 0);
        let no_errors_before = METRICS.rtc.error_count.count();
        rtc.write(AMBA_ID_LOW, &mut data);
        let no_errors_after = METRICS.rtc.error_count.count();
        assert_eq!(no_errors_after - no_errors_before, 1);
        // However, reading from the AMBA_ID_LOW should succeed upon read.

        let mut data = [0; 4];
        rtc.read(AMBA_ID_LOW, &mut data);
        let index = AMBA_ID_LOW + 3;
        assert_eq!(data[0], PL031_ID[((index - AMBA_ID_LOW) >> 2) as usize]);
    }
}
<|endoftext|>


<commit_before>/// Implements the [`Insertable`][insertable] trait for a given struct. This
/// macro should be called with the name of the table you wish to use the struct
/// with, followed by the entire struct body.
///
/// [insertable]: prelude/trait.Insertable.html
///
/// # Example
///
/// ```no_run
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, name -> VarChar, hair_color -> Nullable<VarChar>, } }
/// struct NewUser<'a> {
///     name: &'a str,
///     hair_color: &'a str,
/// }
///
/// Insertable! {
///     (users)
///     struct NewUser<'a> {
///         name: &'a str,
///         hair_color: &'a str,
///     }
/// }
/// # fn main() {}
/// ```
///
/// To avoid copying your struct definition, you can use the
/// [custom_derive crate][custom_derive].
///
/// ```ignore
/// custom_derive! {
///     #[derive(Insertable(users))]
///     struct NewUser<'a> {
///         name: &'a str,
///         hair_color: &'a str,
///     }
/// }
/// ```
///
/// You can also use this macro with tuple structs, but *all* fields must be
/// annotated with `#[column_name(name)]`. Additionally, a trailing comma after
/// the last field is required.
///
/// ```no_run
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, name -> VarChar, hair_color -> Nullable<VarChar>, } }
/// struct NewUser<'a>(&'a str, Option<&'a str>);
///
/// Insertable! {
///     (users)
///     struct NewUser<'a>(
///         #[column_name(name)]
///         &'a str,
///         #[column_name(hair_color)]
///         Option<&'a str>,
///     );
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! Insertable {
    // Strip meta items, pub (if present) and struct from definition
    (
        ($table_name:ident)
        $(#[$ignore:meta])*
        $(pub)* struct $($body:tt)*
    ) => {
        Insertable! {
            ($table_name)
            $($body)*
        }
    };

    // Handle struct with lifetimes
    (
        ($table_name:ident)
        $struct_name:ident <$($lifetime:tt),*>
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                struct_ty = $struct_name<$($lifetime),*>,
                lifetimes = ($($lifetime),*),
            ),
            callback = Insertable,
            body = $body,
        }
    };

    // Handle named struct with no lifetimes
    (
        ($table_name:ident)
        $struct_name:ident
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                struct_ty = $struct_name,
                lifetimes = (),
            ),
            callback = Insertable,
            body = $body,
        }
    };

    // Receive parsed fields of tuple struct from `__diesel_parse_struct_body`
    (
        (
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        fields = [$({
            column_name: $column_name:ident,
            field_ty: $field_ty:ty,
            field_kind: $field_kind:ident,
        })+],
    ) => {
        Insertable! {
            $($headers)*
            self_to_columns = $struct_name($(ref $column_name),+),
            columns = ($($column_name, $field_ty, $field_kind),+),
        }
    };

    // Receive parsed fields of normal struct from `__diesel_parse_struct_body`
    (
        (
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        fields = [$({
            field_name: $field_name:ident,
            column_name: $column_name:ident,
            field_ty: $field_ty:ty,
            field_kind: $field_kind:ident,
        })+],
    ) => {
        Insertable! {
            $($headers)*
            self_to_columns = $struct_name { $($field_name: ref $column_name),+ },
            columns = ($($column_name, $field_ty, $field_kind),+),
        }
    };

    (
        table_name = $table_name:ident,
        struct_ty = $struct_ty:ty,
        lifetimes = ($($lifetime:tt),*),
        self_to_columns = $self_to_columns:pat,
        columns = ($($column_name:ident, $field_ty:ty, $field_kind:ident),+),
    ) => { __diesel_parse_as_item! {
        impl<$($lifetime,)* 'insert, DB> $crate::persistable::Insertable<$table_name::table, DB>
            for &'insert $struct_ty where
                DB: $crate::backend::Backend,
                $('insert: $lifetime,)*
                ($(
                    $crate::persistable::ColumnInsertValue<
                        $table_name::$column_name,
                        $crate::expression::bound::Bound<
                            <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                            &'insert $field_ty,
                        >,
                    >
                ,)+): $crate::persistable::InsertValues<DB>,
        {
            type Values = ($(
                $crate::persistable::ColumnInsertValue<
                    $table_name::$column_name,
                    $crate::expression::bound::Bound<
                        <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                        &'insert $field_ty,
                    >,
                >
            ,)+);

            #[allow(non_shorthand_field_patterns)]
            fn values(self) -> Self::Values {
                use $crate::expression::{AsExpression, Expression};
                use $crate::persistable::ColumnInsertValue;
                let $self_to_columns = *self;
                ($(
                    Insertable_column_expr!($table_name::$column_name, $column_name, $field_kind)
                ,)+)
            }
        }
    }};
}

#[doc(hidden)]
#[macro_export]
macro_rules! Insertable_column_expr {
    ($column:path, $field_access:expr, option) => {
        match $field_access {
            &Some(ref value) => Insertable_column_expr!($column, value, regular),
            &None => ColumnInsertValue::Default($column),
        }
    };

    ($column:path, $field_access:expr, regular) => {
        ColumnInsertValue::Expression(
            $column,
            AsExpression::<<$column as Expression>::SqlType>
                ::as_expression($field_access),
        )
    };
}

#[cfg(test)]
#[allow(missing_debug_implementations, missing_copy_implementations)]
mod tests {
    use prelude::*;

    table! {
        users {
            id -> Integer,
            name -> VarChar,
            hair_color -> Nullable<VarChar>,
        }
    }

    #[test]
    fn simple_struct_definition() {
        struct NewUser {
            name: String,
            hair_color: String,
        }

        Insertable! {
            (users)
            struct NewUser {
                name: String,
                hair_color: String,
            }
        }

        let conn = connection();
        let new_user = NewUser { name: "Sean".into(), hair_color: "Black".into() };
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Black".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    macro_rules! test_struct_definition {
        ($test_name:ident, $($struct_def:tt)*) => {
            // FIXME: This module is to work around rust-lang/rust#31776
            // Remove the module and move the struct definition into the test function once
            // 1.9 is released. The `use` statements can be removed.
            //
            // The indentation is intentionally weird to avoid git churn when this is fixed.
            mod $test_name {
                use super::{users, connection};
                use prelude::*;
                __diesel_parse_as_item!($($struct_def)*);
            #[test]
            fn $test_name() {
                Insertable! {
                    (users)
                    $($struct_def)*
                }

                let conn = connection();
                let new_user = NewUser { name: "Sean".into(), hair_color: None };
                ::insert(&new_user).into(users::table).execute(&conn).unwrap();

                let saved = users::table.select((users::name, users::hair_color))
                    .load::<(String, Option<String>)>(&conn);
                let expected = vec![("Sean".to_string(), Some("Green".to_string()))];
                assert_eq!(Ok(expected), saved);
            }
            }
        }
    }

    test_struct_definition! {
        struct_with_option_field,
        struct NewUser {
            name: String,
            hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        pub_struct_definition,
        pub struct NewUser {
            name: String,
            hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        struct_with_pub_field,
        pub struct NewUser {
            pub name: String,
            hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        struct_with_pub_option_field,
        pub struct NewUser {
            name: String,
            pub hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        named_struct_with_borrowed_body,
        struct NewUser<'a> {
            name: &'a str,
            hair_color: Option<&'a str>,
        }
    }

    #[test]
    fn named_struct_with_renamed_field() {
        struct NewUser {
            my_name: String,
            hair_color: String,
        }

        Insertable! {
            (users)
            struct NewUser {
                #[column_name(name)]
                my_name: String,
                hair_color: String,
            }
        }

        let conn = connection();
        let new_user = NewUser { my_name: "Sean".into(), hair_color: "Black".into() };
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Black".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    #[test]
    fn named_struct_with_renamed_option_field() {
        struct NewUser {
            my_name: String,
            my_hair_color: Option<String>,
        }

        Insertable! {
            (users)
            struct NewUser {
                #[column_name(name)]
                my_name: String,
                #[column_name(hair_color)]
                my_hair_color: Option<String>,
            }
        }

        let conn = connection();
        let new_user = NewUser { my_name: "Sean".into(), my_hair_color: None };
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Green".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    #[test]
    fn tuple_struct() {
        struct NewUser<'a>(
            &'a str,
            Option<&'a str>,
        );

        Insertable! {
            (users)
            struct NewUser<'a>(
                #[column_name(name)]
                pub &'a str,
                #[column_name(hair_color)]
                Option<&'a str>,
            );
        }

        let conn = connection();
        let new_user = NewUser("Sean", None);
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Green".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    #[cfg(feature = "sqlite")]
    use sqlite::SqliteConnection;

    #[cfg(feature = "sqlite")]
    fn connection() -> SqliteConnection {
        let conn = SqliteConnection::establish(":memory:").unwrap();
        conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR NOT NULL, hair_color VARCHAR DEFAULT 'Green')").unwrap();
        conn
    }

    #[cfg(all(feature = "postgres", not(feature = "sqlite")))]
    use pg::PgConnection;
    #[cfg(all(feature = "postgres", not(feature = "sqlite")))]
    extern crate dotenv;

    #[cfg(all(feature = "postgres", not(feature = "sqlite")))]
    fn connection() -> PgConnection {
        use self::dotenv::dotenv;
        use std::env;

        dotenv().ok();
        let database_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL must be set to run tests");
        let conn = PgConnection::establish(&database_url).unwrap();
        conn.begin_test_transaction().unwrap();
        conn.execute("DROP TABLE IF EXISTS users").unwrap();
        conn.execute("CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, hair_color VARCHAR DEFAULT 'Green')").unwrap();
        conn
    }
}
<commit_msg>Add Missing Link to Documentation<commit_after>/// Implements the [`Insertable`][insertable] trait for a given struct. This
/// macro should be called with the name of the table you wish to use the struct
/// with, followed by the entire struct body.
///
/// [insertable]: prelude/trait.Insertable.html
///
/// # Example
///
/// ```no_run
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, name -> VarChar, hair_color -> Nullable<VarChar>, } }
/// struct NewUser<'a> {
///     name: &'a str,
///     hair_color: &'a str,
/// }
///
/// Insertable! {
///     (users)
///     struct NewUser<'a> {
///         name: &'a str,
///         hair_color: &'a str,
///     }
/// }
/// # fn main() {}
/// ```
///
/// To avoid copying your struct definition, you can use the
/// [custom_derive crate][custom_derive].
///
/// [custom_derive]: https://crates.io/crates/custom_derive
///
/// ```ignore
/// custom_derive! {
///     #[derive(Insertable(users))]
///     struct NewUser<'a> {
///         name: &'a str,
///         hair_color: &'a str,
///     }
/// }
/// ```
///
/// You can also use this macro with tuple structs, but *all* fields must be
/// annotated with `#[column_name(name)]`. Additionally, a trailing comma after
/// the last field is required.
///
/// ```no_run
/// # #[macro_use] extern crate diesel;
/// # table! { users { id -> Integer, name -> VarChar, hair_color -> Nullable<VarChar>, } }
/// struct NewUser<'a>(&'a str, Option<&'a str>);
///
/// Insertable! {
///     (users)
///     struct NewUser<'a>(
///         #[column_name(name)]
///         &'a str,
///         #[column_name(hair_color)]
///         Option<&'a str>,
///     );
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! Insertable {
    // Strip meta items, pub (if present) and struct from definition
    (
        ($table_name:ident)
        $(#[$ignore:meta])*
        $(pub)* struct $($body:tt)*
    ) => {
        Insertable! {
            ($table_name)
            $($body)*
        }
    };

    // Handle struct with lifetimes
    (
        ($table_name:ident)
        $struct_name:ident <$($lifetime:tt),*>
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                struct_ty = $struct_name<$($lifetime),*>,
                lifetimes = ($($lifetime),*),
            ),
            callback = Insertable,
            body = $body,
        }
    };

    // Handle named struct with no lifetimes
    (
        ($table_name:ident)
        $struct_name:ident
        $body:tt $(;)*
    ) => {
        __diesel_parse_struct_body! {
            (
                struct_name = $struct_name,
                table_name = $table_name,
                struct_ty = $struct_name,
                lifetimes = (),
            ),
            callback = Insertable,
            body = $body,
        }
    };

    // Receive parsed fields of tuple struct from `__diesel_parse_struct_body`
    (
        (
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        fields = [$({
            column_name: $column_name:ident,
            field_ty: $field_ty:ty,
            field_kind: $field_kind:ident,
        })+],
    ) => {
        Insertable! {
            $($headers)*
            self_to_columns = $struct_name($(ref $column_name),+),
            columns = ($($column_name, $field_ty, $field_kind),+),
        }
    };

    // Receive parsed fields of normal struct from `__diesel_parse_struct_body`
    (
        (
            struct_name = $struct_name:ident,
            $($headers:tt)*
        ),
        fields = [$({
            field_name: $field_name:ident,
            column_name: $column_name:ident,
            field_ty: $field_ty:ty,
            field_kind: $field_kind:ident,
        })+],
    ) => {
        Insertable! {
            $($headers)*
            self_to_columns = $struct_name { $($field_name: ref $column_name),+ },
            columns = ($($column_name, $field_ty, $field_kind),+),
        }
    };

    (
        table_name = $table_name:ident,
        struct_ty = $struct_ty:ty,
        lifetimes = ($($lifetime:tt),*),
        self_to_columns = $self_to_columns:pat,
        columns = ($($column_name:ident, $field_ty:ty, $field_kind:ident),+),
    ) => { __diesel_parse_as_item! {
        impl<$($lifetime,)* 'insert, DB> $crate::persistable::Insertable<$table_name::table, DB>
            for &'insert $struct_ty where
                DB: $crate::backend::Backend,
                $('insert: $lifetime,)*
                ($(
                    $crate::persistable::ColumnInsertValue<
                        $table_name::$column_name,
                        $crate::expression::bound::Bound<
                            <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                            &'insert $field_ty,
                        >,
                    >
                ,)+): $crate::persistable::InsertValues<DB>,
        {
            type Values = ($(
                $crate::persistable::ColumnInsertValue<
                    $table_name::$column_name,
                    $crate::expression::bound::Bound<
                        <$table_name::$column_name as $crate::expression::Expression>::SqlType,
                        &'insert $field_ty,
                    >,
                >
            ,)+);

            #[allow(non_shorthand_field_patterns)]
            fn values(self) -> Self::Values {
                use $crate::expression::{AsExpression, Expression};
                use $crate::persistable::ColumnInsertValue;
                let $self_to_columns = *self;
                ($(
                    Insertable_column_expr!($table_name::$column_name, $column_name, $field_kind)
                ,)+)
            }
        }
    }};
}

#[doc(hidden)]
#[macro_export]
macro_rules! Insertable_column_expr {
    ($column:path, $field_access:expr, option) => {
        match $field_access {
            &Some(ref value) => Insertable_column_expr!($column, value, regular),
            &None => ColumnInsertValue::Default($column),
        }
    };

    ($column:path, $field_access:expr, regular) => {
        ColumnInsertValue::Expression(
            $column,
            AsExpression::<<$column as Expression>::SqlType>
                ::as_expression($field_access),
        )
    };
}

#[cfg(test)]
#[allow(missing_debug_implementations, missing_copy_implementations)]
mod tests {
    use prelude::*;

    table! {
        users {
            id -> Integer,
            name -> VarChar,
            hair_color -> Nullable<VarChar>,
        }
    }

    #[test]
    fn simple_struct_definition() {
        struct NewUser {
            name: String,
            hair_color: String,
        }

        Insertable! {
            (users)
            struct NewUser {
                name: String,
                hair_color: String,
            }
        }

        let conn = connection();
        let new_user = NewUser { name: "Sean".into(), hair_color: "Black".into() };
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Black".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    macro_rules! test_struct_definition {
        ($test_name:ident, $($struct_def:tt)*) => {
            // FIXME: This module is to work around rust-lang/rust#31776
            // Remove the module and move the struct definition into the test function once
            // 1.9 is released. The `use` statements can be removed.
            //
            // The indentation is intentionally weird to avoid git churn when this is fixed.
            mod $test_name {
                use super::{users, connection};
                use prelude::*;
                __diesel_parse_as_item!($($struct_def)*);
            #[test]
            fn $test_name() {
                Insertable! {
                    (users)
                    $($struct_def)*
                }

                let conn = connection();
                let new_user = NewUser { name: "Sean".into(), hair_color: None };
                ::insert(&new_user).into(users::table).execute(&conn).unwrap();

                let saved = users::table.select((users::name, users::hair_color))
                    .load::<(String, Option<String>)>(&conn);
                let expected = vec![("Sean".to_string(), Some("Green".to_string()))];
                assert_eq!(Ok(expected), saved);
            }
            }
        }
    }

    test_struct_definition! {
        struct_with_option_field,
        struct NewUser {
            name: String,
            hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        pub_struct_definition,
        pub struct NewUser {
            name: String,
            hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        struct_with_pub_field,
        pub struct NewUser {
            pub name: String,
            hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        struct_with_pub_option_field,
        pub struct NewUser {
            name: String,
            pub hair_color: Option<String>,
        }
    }

    test_struct_definition! {
        named_struct_with_borrowed_body,
        struct NewUser<'a> {
            name: &'a str,
            hair_color: Option<&'a str>,
        }
    }

    #[test]
    fn named_struct_with_renamed_field() {
        struct NewUser {
            my_name: String,
            hair_color: String,
        }

        Insertable! {
            (users)
            struct NewUser {
                #[column_name(name)]
                my_name: String,
                hair_color: String,
            }
        }

        let conn = connection();
        let new_user = NewUser { my_name: "Sean".into(), hair_color: "Black".into() };
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Black".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    #[test]
    fn named_struct_with_renamed_option_field() {
        struct NewUser {
            my_name: String,
            my_hair_color: Option<String>,
        }

        Insertable! {
            (users)
            struct NewUser {
                #[column_name(name)]
                my_name: String,
                #[column_name(hair_color)]
                my_hair_color: Option<String>,
            }
        }

        let conn = connection();
        let new_user = NewUser { my_name: "Sean".into(), my_hair_color: None };
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Green".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    #[test]
    fn tuple_struct() {
        struct NewUser<'a>(
            &'a str,
            Option<&'a str>,
        );

        Insertable! {
            (users)
            struct NewUser<'a>(
                #[column_name(name)]
                pub &'a str,
                #[column_name(hair_color)]
                Option<&'a str>,
            );
        }

        let conn = connection();
        let new_user = NewUser("Sean", None);
        ::insert(&new_user).into(users::table).execute(&conn).unwrap();

        let saved = users::table.select((users::name, users::hair_color))
            .load::<(String, Option<String>)>(&conn);
        let expected = vec![("Sean".to_string(), Some("Green".to_string()))];
        assert_eq!(Ok(expected), saved);
    }

    #[cfg(feature = "sqlite")]
    use sqlite::SqliteConnection;

    #[cfg(feature = "sqlite")]
    fn connection() -> SqliteConnection {
        let conn = SqliteConnection::establish(":memory:").unwrap();
        conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR NOT NULL, hair_color VARCHAR DEFAULT 'Green')").unwrap();
        conn
    }

    #[cfg(all(feature = "postgres", not(feature = "sqlite")))]
    use pg::PgConnection;
    #[cfg(all(feature = "postgres", not(feature = "sqlite")))]
    extern crate dotenv;

    #[cfg(all(feature = "postgres", not(feature = "sqlite")))]
    fn connection() -> PgConnection {
        use self::dotenv::dotenv;
        use std::env;

        dotenv().ok();
        let database_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL must be set to run tests");
        let conn = PgConnection::establish(&database_url).unwrap();
        conn.begin_test_transaction().unwrap();
        conn.execute("DROP TABLE IF EXISTS users").unwrap();
        conn.execute("CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, hair_color VARCHAR DEFAULT 'Green')").unwrap();
        conn
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over win named pipes
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

//! Named pipes library

use miow::pipe::{NamedPipe, NamedPipeBuilder};
use miow::Overlapped;
use miow::iocp::CompletionPort;
use std;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::*;
use std::sync::Arc;
use jsonrpc_core::IoHandler;
use validator;

pub type Result<T> = std::result::Result<T, Error>;

const MAX_REQUEST_LEN: u32 = 65536;
const REQUEST_READ_BATCH: usize = 4096;
const POLL_PARK_TIMEOUT_MS: u64 = 10;
const STARTING_PIPE_TOKEN: u32 = 1;

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

pub struct PipeHandler {
    waiting_pipe: NamedPipe,
    io_handler: Arc<IoHandler>,
    handle_counter: u32,
}

impl PipeHandler {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<PipeHandler> {
        Ok(PipeHandler {
            waiting_pipe: try!(
                NamedPipeBuilder::new(addr)
                    .first(true)
                    .accept_remote(true)
                    .max_instances(255)
                    .inbound(true)
                    .outbound(true)
                    .out_buffer_size(MAX_REQUEST_LEN)
                    .in_buffer_size(MAX_REQUEST_LEN)
                    .create()
            ),
            io_handler: io_handler.clone(),
            handle_counter: STARTING_PIPE_TOKEN,
        })
    }

    fn handle_incoming(&mut self, addr: &str, stop: Arc<AtomicBool>) -> io::Result<()> {
        let cp = try!(CompletionPort::new(self.handle_counter));
        let pipe_token = self.handle_counter as usize + 1;
        try!(cp.add_handle(pipe_token, &self.waiting_pipe));

        let mut overlapped = Overlapped::zero();
        unsafe { try!(self.waiting_pipe.connect_overlapped(&mut overlapped)); };
        trace!(target: "ipc", "Waiting for client: [{}, {}] [{}]", self.handle_counter, pipe_token, addr);
        while !stop.load(Ordering::Relaxed) {
            if let Ok(status) = cp.get(None) {
                if status.token() == pipe_token
                {
                    trace!(target: "ipc", "Received connection to address [{}]", addr);
                    break;
                }
            }
            std::thread::park_timeout(std::time::Duration::from_millis(POLL_PARK_TIMEOUT_MS));
        }

        if stop.load(Ordering::Relaxed) {
            trace!(target: "ipc", "Stopped listening sequence [{}]", addr);
            return Ok(())
        }

        let mut connected_pipe = std::mem::replace::<NamedPipe>(&mut self.waiting_pipe,
            try!(NamedPipeBuilder::new(addr)
                .first(false)
                .accept_remote(true)
                .inbound(true)
                .outbound(true)
                .out_buffer_size(MAX_REQUEST_LEN)
                .in_buffer_size(MAX_REQUEST_LEN)
                .create()));
        self.handle_counter += 2;

        let thread_handler = self.io_handler.clone();
        std::thread::spawn(move || {
            let mut buf = vec![0u8; MAX_REQUEST_LEN as usize];
            let mut fin = REQUEST_READ_BATCH;
            loop {
                let start = fin - REQUEST_READ_BATCH;
                match connected_pipe.read(&mut buf[start..fin]) {
                    Ok(size) => {
                        let effective = &buf[0..start + size];
                        fin = fin + REQUEST_READ_BATCH;
                        if !validator::is_valid(effective) {
                            continue;
                        }
                        trace!(target: "ipc", "Received rpc request: {} bytes", effective.len());

                        if let Err(parse_err) = String::from_utf8(effective.to_vec())
                            .map(|rpc_msg|
                                 {
                                     trace!(target: "ipc", "Request: {}", &rpc_msg);
                                     let response: Option<String> = thread_handler.handle_request(&rpc_msg);

                                     if let Some(response_str) = response {
                                        trace!(target: "ipc", "Response: {}", &response_str);
                                        let response_bytes = response_str.into_bytes();
                                        if let Err(write_err) = connected_pipe.write_all(&response_bytes[..]) {
                                            trace!(target: "ipc", "Response write error: {:?}", write_err);
                                        }
                                        trace!(target: "ipc", "Sent rpc response:  {} bytes", response_bytes.len());
                                        connected_pipe.flush().unwrap();
                                    }
                                }
                            )
                        {
                            trace!(target: "ipc", "Response decode error: {:?}", parse_err);
                        }

                        fin = REQUEST_READ_BATCH;
                    },
                    Err(e) => {
                        // closed connection
                        trace!(target: "ipc", "Dropped connection {:?}", e);
                        break;
                    }
                }
            }
        });

        Ok(())
    }
}

pub struct Server {
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
    io_handler: Arc<IoHandler>,
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server> {
        Ok(Server {
            io_handler: io_handler.clone(),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in this thread)
    pub fn run(&self) -> Result<()> {
        let mut pipe_handler = try!(PipeHandler::start(&self.addr, &self.io_handler));
        loop  {
            try!(pipe_handler.handle_incoming(&self.addr, Arc::new(AtomicBool::new(false))));
        }
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<()> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        trace!(target: "ipc", "Started named pipes server [{}]", self.addr);

        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        let thread_handler = self.io_handler.clone();
        let addr = self.addr.clone();
        std::thread::spawn(move || {
            let mut pipe_handler = PipeHandler::start(&addr, &thread_handler).unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
                if let Err(pipe_listener_error) = pipe_handler.handle_incoming(&addr, thread_stopping.clone()) {
                    trace!(target: "ipc", "Pipe listening error: {:?}", pipe_listener_error);
                }
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });

        self.is_stopped.store(false, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop_async(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::park_timeout(std::time::Duration::new(0, 50)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop_async().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        // todo : no stable logging for windows?
        trace!(target: "ipc", "IPC Server : shutdown");
    }
}
<commit_msg>intendations<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over win named pipes
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

//! Named pipes library

use miow::pipe::{NamedPipe, NamedPipeBuilder};
use miow::Overlapped;
use miow::iocp::CompletionPort;
use std;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::*;
use std::sync::Arc;
use jsonrpc_core::IoHandler;
use validator;

pub type Result<T> = std::result::Result<T, Error>;

const MAX_REQUEST_LEN: u32 = 65536;
const REQUEST_READ_BATCH: usize = 4096;
const POLL_PARK_TIMEOUT_MS: u64 = 10;
const STARTING_PIPE_TOKEN: u32 = 1;

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

pub struct PipeHandler {
    waiting_pipe: NamedPipe,
    io_handler: Arc<IoHandler>,
    handle_counter: u32,
}

impl PipeHandler {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<PipeHandler> {
        Ok(PipeHandler {
            waiting_pipe: try!(
                NamedPipeBuilder::new(addr)
                    .first(true)
                    .accept_remote(true)
                    .max_instances(255)
                    .inbound(true)
                    .outbound(true)
                    .out_buffer_size(MAX_REQUEST_LEN)
                    .in_buffer_size(MAX_REQUEST_LEN)
                    .create()
            ),
            io_handler: io_handler.clone(),
            handle_counter: STARTING_PIPE_TOKEN,
        })
    }

    fn handle_incoming(&mut self, addr: &str, stop: Arc<AtomicBool>) -> io::Result<()> {
        let cp = try!(CompletionPort::new(self.handle_counter));
        let pipe_token = self.handle_counter as usize + 1;
        try!(cp.add_handle(pipe_token, &self.waiting_pipe));

        let mut overlapped = Overlapped::zero();
        unsafe { try!(self.waiting_pipe.connect_overlapped(&mut overlapped)); };
        trace!(target: "ipc", "Waiting for client: [{}, {}] [{}]", self.handle_counter, pipe_token, addr);
        while !stop.load(Ordering::Relaxed) {
            if let Ok(status) = cp.get(None) {
                if status.token() == pipe_token
                {
                    trace!(target: "ipc", "Received connection to address [{}]", addr);
                    break;
                }
            }
            std::thread::park_timeout(std::time::Duration::from_millis(POLL_PARK_TIMEOUT_MS));
        }

        if stop.load(Ordering::Relaxed) {
            trace!(target: "ipc", "Stopped listening sequence [{}]", addr);
            return Ok(())
        }

        let mut connected_pipe = std::mem::replace::<NamedPipe>(&mut self.waiting_pipe,
            try!(NamedPipeBuilder::new(addr)
                .first(false)
                .accept_remote(true)
                .inbound(true)
                .outbound(true)
                .out_buffer_size(MAX_REQUEST_LEN)
                .in_buffer_size(MAX_REQUEST_LEN)
                .create()));
        self.handle_counter += 2;

        let thread_handler = self.io_handler.clone();
        std::thread::spawn(move || {
            let mut buf = vec![0u8; MAX_REQUEST_LEN as usize];
            let mut fin = REQUEST_READ_BATCH;
            loop {
                let start = fin - REQUEST_READ_BATCH;
                trace!(target: "ipc", "Reading {} - {} of the buffer", start, fin);
                match connected_pipe.read(&mut buf[start..fin]) {
                    Ok(size) => {
                        let effective = &buf[0..start + size];
                        fin = fin + REQUEST_READ_BATCH;
                        if !validator::is_valid(effective) {
                            continue;
                        }
                        trace!(target: "ipc", "Received rpc request: {} bytes", effective.len());

                        if let Err(parse_err) = String::from_utf8(effective.to_vec())
                            .map(|rpc_msg|
                                 {
                                     trace!(target: "ipc", "Request: {}", &rpc_msg);
                                     let response: Option<String> = thread_handler.handle_request(&rpc_msg);

                                     if let Some(response_str) = response {
                                         trace!(target: "ipc", "Response: {}", &response_str);
                                         let response_bytes = response_str.into_bytes();
                                         if let Err(write_err) = connected_pipe.write_all(&response_bytes[..]) {
                                             trace!(target: "ipc", "Response write error: {:?}", write_err);
                                         }
                                         trace!(target: "ipc", "Sent rpc response:  {} bytes", response_bytes.len());
                                         connected_pipe.flush().unwrap();
                                    }
                                }
                            )
                        {
                            trace!(target: "ipc", "Response decode error: {:?}", parse_err);
                        }

                        fin = REQUEST_READ_BATCH;
                    },
                    Err(e) => {
                        // closed connection
                        trace!(target: "ipc", "Dropped connection {:?}", e);
                        break;
                    }
                }
            }
        });

        Ok(())
    }
}

pub struct Server {
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
    io_handler: Arc<IoHandler>,
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server> {
        Ok(Server {
            io_handler: io_handler.clone(),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in this thread)
    pub fn run(&self) -> Result<()> {
        let mut pipe_handler = try!(PipeHandler::start(&self.addr, &self.io_handler));
        loop  {
            try!(pipe_handler.handle_incoming(&self.addr, Arc::new(AtomicBool::new(false))));
        }
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<()> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        trace!(target: "ipc", "Started named pipes server [{}]", self.addr);

        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        let thread_handler = self.io_handler.clone();
        let addr = self.addr.clone();
        std::thread::spawn(move || {
            let mut pipe_handler = PipeHandler::start(&addr, &thread_handler).unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
                if let Err(pipe_listener_error) = pipe_handler.handle_incoming(&addr, thread_stopping.clone()) {
                    trace!(target: "ipc", "Pipe listening error: {:?}", pipe_listener_error);
                }
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });

        self.is_stopped.store(false, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop_async(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::park_timeout(std::time::Duration::new(0, 50)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop_async().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        // todo : no stable logging for windows?
        trace!(target: "ipc", "IPC Server : shutdown");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over win named pipes
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

//! Named pipes library

use miow::pipe::{NamedPipe, NamedPipeBuilder};
use std;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::*;
use std::sync::Arc;
use jsonrpc_core::IoHandler;
use validator;

pub type Result<T> = std::result::Result<T, Error>;

const MAX_REQUEST_LEN: u32 = 65536;
const REQUEST_READ_BATCH: usize = 4096;

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

pub struct PipeHandler {
    waiting_pipe: NamedPipe,
    io_handler: Arc<IoHandler>,
}

impl PipeHandler {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<PipeHandler> {
        Ok(PipeHandler {
            waiting_pipe: try!(
                NamedPipeBuilder::new(addr)
                    .first(true)
                    .accept_remote(true)
                    .max_instances(255)
                    .inbound(true)
                    .outbound(true)
                    .out_buffer_size(MAX_REQUEST_LEN)
                    .in_buffer_size(MAX_REQUEST_LEN)
                    .create()
            ),
            io_handler: io_handler.clone(),
        })
    }

    fn handle_incoming(&mut self, addr: &str, stop: Arc<AtomicBool>) -> io::Result<()> {
        trace!(target: "ipc", "Waiting for client: [{}]", addr);
		try!(self.waiting_pipe.connect());
		trace!(target: "ipc", "Received connection to address [{}]", addr);
        if stop.load(Ordering::Relaxed) {
            trace!(target: "ipc", "Stopped listening sequence [{}]", addr);
            return Ok(())
        }

        let mut connected_pipe = std::mem::replace::<NamedPipe>(&mut self.waiting_pipe,
            try!(NamedPipeBuilder::new(addr)
                .first(false)
                .accept_remote(true)
                .inbound(true)
                .outbound(true)
                .out_buffer_size(MAX_REQUEST_LEN)
                .in_buffer_size(MAX_REQUEST_LEN)
                .create()));

        let thread_handler = self.io_handler.clone();
        std::thread::spawn(move || {
            let mut buf = vec![0u8; MAX_REQUEST_LEN as usize];
            let mut fin = REQUEST_READ_BATCH;
            loop {
                let start = fin - REQUEST_READ_BATCH;
                trace!(target: "ipc", "Reading {} - {} of the buffer", start, fin);
                match connected_pipe.read(&mut buf[start..fin]) {
                    Ok(size) => {
                        let effective = &buf[0..start + size];
                        fin = fin + size;
                        if !validator::is_valid(effective) {
                            continue;
                        }
                        trace!(target: "ipc", "Received rpc request: {} bytes", effective.len());

                        if let Err(parse_err) = String::from_utf8(effective.to_vec())
                            .map(|rpc_msg|
                                 {
                                     trace!(target: "ipc", "Request: {}", &rpc_msg);
                                     let response: Option<String> = thread_handler.handle_request(&rpc_msg);

                                     if let Some(response_str) = response {
                                         trace!(target: "ipc", "Response: {}", &response_str);
                                         let response_bytes = response_str.into_bytes();
                                         if let Err(write_err) = connected_pipe.write_all(&response_bytes[..]).and_then(|_| connected_pipe.flush()) {
                                             trace!(target: "ipc", "Response write error: {:?}", write_err);
                                         }
                                         else {
                                             trace!(target: "ipc", "Sent rpc response:  {} bytes", response_bytes.len());
                                         }
                                    }
                                }
                            )
                        {
                            trace!(target: "ipc", "Request decode error: {:?}", parse_err);
                        }

                        fin = REQUEST_READ_BATCH;
                    },
                    Err(e) => {
                        // closed connection
                        trace!(target: "ipc", "Dropped connection {:?}", e);
                        break;
                    }
                }
            }
        });

        Ok(())
    }
}

pub struct Server {
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
    io_handler: Arc<IoHandler>,
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server> {
        Ok(Server {
            io_handler: io_handler.clone(),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in this thread)
    pub fn run(&self) -> Result<()> {
        let mut pipe_handler = try!(PipeHandler::start(&self.addr, &self.io_handler));
        loop  {
            try!(pipe_handler.handle_incoming(&self.addr, Arc::new(AtomicBool::new(false))));
        }
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<()> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        trace!(target: "ipc", "Started named pipes server [{}]", self.addr);

        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        let thread_handler = self.io_handler.clone();
        let addr = self.addr.clone();
        std::thread::spawn(move || {
            let mut pipe_handler = PipeHandler::start(&addr, &thread_handler).unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
				trace!(target: "ipc", "Accepting pipe connection");
                if let Err(pipe_listener_error) = pipe_handler.handle_incoming(&addr, thread_stopping.clone()) {
                    trace!(target: "ipc", "Pipe listening error: {:?}", pipe_listener_error);
                }
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });

        self.is_stopped.store(false, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop_async(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::park_timeout(std::time::Duration::new(0, 50)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop_async().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        // todo : no stable logging for windows?
        trace!(target: "ipc", "IPC Server : shutdown");
    }
}
<commit_msg>win request through-validator<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over win named pipes
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

//! Named pipes library

use miow::pipe::{NamedPipe, NamedPipeBuilder};
use std;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::*;
use std::sync::Arc;
use jsonrpc_core::IoHandler;
use validator;

pub type Result<T> = std::result::Result<T, Error>;

const MAX_REQUEST_LEN: u32 = 65536;
const REQUEST_READ_BATCH: usize = 4096;

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

pub struct PipeHandler {
    waiting_pipe: NamedPipe,
    io_handler: Arc<IoHandler>,
}

impl PipeHandler {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<PipeHandler> {
        Ok(PipeHandler {
            waiting_pipe: try!(
                NamedPipeBuilder::new(addr)
                    .first(true)
                    .accept_remote(true)
                    .max_instances(255)
                    .inbound(true)
                    .outbound(true)
                    .out_buffer_size(MAX_REQUEST_LEN)
                    .in_buffer_size(MAX_REQUEST_LEN)
                    .create()
            ),
            io_handler: io_handler.clone(),
        })
    }

    fn handle_incoming(&mut self, addr: &str, stop: Arc<AtomicBool>) -> io::Result<()> {
        trace!(target: "ipc", "Waiting for client: [{}]", addr);
		try!(self.waiting_pipe.connect());
		trace!(target: "ipc", "Received connection to address [{}]", addr);
        if stop.load(Ordering::Relaxed) {
            trace!(target: "ipc", "Stopped listening sequence [{}]", addr);
            return Ok(())
        }

        let mut connected_pipe = std::mem::replace::<NamedPipe>(&mut self.waiting_pipe,
            try!(NamedPipeBuilder::new(addr)
                .first(false)
                .accept_remote(true)
                .inbound(true)
                .outbound(true)
                .out_buffer_size(MAX_REQUEST_LEN)
                .in_buffer_size(MAX_REQUEST_LEN)
                .create()));

        let thread_handler = self.io_handler.clone();
        std::thread::spawn(move || {
            let mut buf = vec![0u8; MAX_REQUEST_LEN as usize];
            let mut fin = REQUEST_READ_BATCH;
            loop {
                let start = fin - REQUEST_READ_BATCH;
                trace!(target: "ipc", "Reading {} - {} of the buffer", start, fin);
                match connected_pipe.read(&mut buf[start..fin]) {
                    Ok(size) => {
                        let (requests, last_index) = {
                            let effective = &buf[0..start + size];
                            fin = fin + size;
                            trace!(target: "ipc", "Received rpc request: {} bytes", effective.len());

                            validator::extract_requests(effective)
                        };

                        if requests.len() > 0 {
                            let mut response_buf = Vec::new();
                            for rpc_msg in requests  {
                                let response: Option<String> = thread_handler.handle_request(&rpc_msg);

                                if let Some(response_str) = response {
                                    trace!(target: "ipc", "Response: {}", &response_str);
                                    response_buf.extend(response_str.into_bytes());
                                }
                            }

                            if let Err(write_err) = connected_pipe.write_all(&response_buf[..]).and_then(|_| connected_pipe.flush()) {
                                trace!(target: "ipc", "Response write error: {:?}", write_err);
                            }
                            else {
                                trace!(target: "ipc", "Sent rpc response: {} bytes", response_buf.len());
                            }

                            let leftover_len = start + size - (last_index + 1);
                            if leftover_len > 0 {
                                let leftover = buf[last_index + 1..start + size].to_vec();
                                buf[0..leftover_len].copy_from_slice(&leftover[..]);
                            }
                            fin = leftover_len + REQUEST_READ_BATCH;
                        }
                        else { continue; }
                    },
                    Err(e) => {
                        // closed connection
                        trace!(target: "ipc", "Dropped connection {:?}", e);
                        break;
                    }
                }
            }
        });

        Ok(())
    }
}

pub struct Server {
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
    io_handler: Arc<IoHandler>,
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server> {
        Ok(Server {
            io_handler: io_handler.clone(),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in this thread)
    pub fn run(&self) -> Result<()> {
        let mut pipe_handler = try!(PipeHandler::start(&self.addr, &self.io_handler));
        loop  {
            try!(pipe_handler.handle_incoming(&self.addr, Arc::new(AtomicBool::new(false))));
        }
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<()> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        trace!(target: "ipc", "Started named pipes server [{}]", self.addr);

        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        let thread_handler = self.io_handler.clone();
        let addr = self.addr.clone();
        std::thread::spawn(move || {
            let mut pipe_handler = PipeHandler::start(&addr, &thread_handler).unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
				trace!(target: "ipc", "Accepting pipe connection");
                if let Err(pipe_listener_error) = pipe_handler.handle_incoming(&addr, thread_stopping.clone()) {
                    trace!(target: "ipc", "Pipe listening error: {:?}", pipe_listener_error);
                }
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });

        self.is_stopped.store(false, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop_async(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::park_timeout(std::time::Duration::new(0, 50)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop_async().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        // todo : no stable logging for windows?
        trace!(target: "ipc", "IPC Server : shutdown");
    }
}
<|endoftext|>