<commit_before>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// Prevent warning when casting u32 as i64
#![allow(clippy::cast_lossless)]
#![allow(dead_code)]

use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use libc::{self, sched_param, timespec, CLOCK_MONOTONIC, PR_SET_TIMERSLACK, SCHED_RR};

use super::{Error, GpioState, Result};

// Only call sleep_ns() if we have enough time remaining
const SLEEP_THRESHOLD: i64 = 250_000;
// Reserve some time for busy waiting
const BUSYWAIT_MAX: i64 = 200_000;
// Subtract from the remaining busy wait time to account for get_time_ns() overhead
const BUSYWAIT_REMAINDER: i64 = 100;

static mut MSG_WAITING: AtomicBool = AtomicBool::new(false);

#[derive(Debug)]
enum Msg {
    Reconfigure(Duration, Duration),
    Stop,
}

#[derive(Debug)]
pub(crate) struct SoftPwm {
    pwm_thread: Option<thread::JoinHandle<Result<()>>>,
    sender: Sender<Msg>,
}

impl SoftPwm {
    pub(crate) fn new(
        pin: u8,
        gpio_state: Arc<GpioState>,
        period: Duration,
        pulse_width: Duration,
    ) -> SoftPwm {
        let (sender, receiver): (Sender<Msg>, Receiver<Msg>) = mpsc::channel();

        let pwm_thread = thread::spawn(move || -> Result<()> {
            // Set the scheduling policy to real-time round robin at the highest priority. This
            // will silently fail if we're not running as root.
            #[cfg(target_env = "gnu")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
            };

            #[cfg(target_env = "musl")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
                sched_ss_low_priority: 0,
                sched_ss_repl_period: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_init_budget: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_max_repl: 0,
            };

            unsafe {
                libc::sched_setscheduler(0, SCHED_RR, &params);
            }

            // Set timer slack to 1 ns (default = 50 µs). This is only relevant if we're unable
            // to set a real-time scheduling policy.
            unsafe {
                libc::prctl(PR_SET_TIMERSLACK, 1);
            }

            let mut period_ns =
                (period.as_secs() as i64 * 1_000_000_000) + period.subsec_nanos() as i64;

            let mut pulse_width_ns =
                (pulse_width.as_secs() as i64 * 1_000_000_000) + pulse_width.subsec_nanos() as i64;

            let mut start_ns = get_time_ns();

            loop {
                // PWM active
                if pulse_width_ns > 0 {
                    gpio_state.gpio_mem.set_high(pin);
                }

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if pulse_width_ns >= SLEEP_THRESHOLD {
                    sleep_ns(pulse_width_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining active time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    if (pulse_width_ns - (get_time_ns() - start_ns)) <= BUSYWAIT_REMAINDER {
                        break;
                    }
                }

                // PWM inactive
                gpio_state.gpio_mem.set_low(pin);

                // This is slightly faster than directly checking try_recv()
                if unsafe { MSG_WAITING.compare_and_swap(true, false, Ordering::AcqRel) } {
                    while let Ok(msg) = receiver.try_recv() {
                        match msg {
                            Msg::Reconfigure(period, pulse_width) => {
                                // Reconfigure period and pulse width
                                pulse_width_ns = (pulse_width.as_secs() as i64 * 1_000_000_000)
                                    + pulse_width.subsec_nanos() as i64;

                                period_ns = (period.as_secs() as i64 * 1_000_000_000)
                                    + period.subsec_nanos() as i64;

                                if pulse_width_ns > period_ns {
                                    pulse_width_ns = period_ns;
                                }
                            }
                            Msg::Stop => {
                                // The main thread asked us to stop
                                return Ok(());
                            }
                        }
                    }
                }

                let remaining_ns = period_ns - (get_time_ns() - start_ns);

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if remaining_ns >= SLEEP_THRESHOLD {
                    sleep_ns(remaining_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining inactive time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    let current_ns = get_time_ns();
                    if (period_ns - (current_ns - start_ns)) <= BUSYWAIT_REMAINDER {
                        start_ns = current_ns;
                        break;
                    }
                }
            }
        });

        SoftPwm {
            pwm_thread: Some(pwm_thread),
            sender,
        }
    }

    pub(crate) fn reconfigure(&mut self, period: Duration, pulse_width: Duration) {
        let _ = self.sender.send(Msg::Reconfigure(period, pulse_width));
        unsafe {
            MSG_WAITING.store(true, Ordering::Release);
        }
    }

    pub(crate) fn stop(&mut self) -> Result<()> {
        let _ = self.sender.send(Msg::Stop);
        unsafe {
            MSG_WAITING.store(true, Ordering::Release);
        }

        if let Some(pwm_thread) = self.pwm_thread.take() {
            match pwm_thread.join() {
                Ok(r) => return r,
                Err(_) => return Err(Error::ThreadPanic),
            }
        }

        Ok(())
    }
}

impl Drop for SoftPwm {
    fn drop(&mut self) {
        // Don't wait for the pwm thread to exit if the main thread is panicking,
        // because we could potentially block indefinitely while unwinding if the
        // pwm thread doesn't respond to the Stop message for some reason.
        if !thread::panicking() {
            let _ = self.stop();
        }
    }
}

#[inline(always)]
fn get_time_ns() -> i64 {
    let mut ts = timespec {
        tv_sec: 0,
        tv_nsec: 0,
    };

    unsafe {
        libc::clock_gettime(CLOCK_MONOTONIC, &mut ts);
    }

    (ts.tv_sec as i64 * 1_000_000_000) + ts.tv_nsec as i64
}

#[inline(always)]
fn sleep_ns(ns: i64) {
    let ts = timespec {
        tv_sec: (ns / 1_000_000_000) as i32,
        tv_nsec: (ns % 1_000_000_000) as i32,
    };

    unsafe {
        libc::clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, ptr::null_mut());
    }
}
<commit_msg>Add compatibility for 64-bit timespec fields<commit_after>// Copyright (c) 2017-2019 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

// Prevent warning when casting u32 as i64
#![allow(clippy::cast_lossless)]
#![allow(dead_code)]

use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use libc::{
    self, c_long, sched_param, time_t, timespec, CLOCK_MONOTONIC, PR_SET_TIMERSLACK, SCHED_RR,
};

use super::{Error, GpioState, Result};

// Only call sleep_ns() if we have enough time remaining
const SLEEP_THRESHOLD: i64 = 250_000;
// Reserve some time for busy waiting
const BUSYWAIT_MAX: i64 = 200_000;
// Subtract from the remaining busy wait time to account for get_time_ns() overhead
const BUSYWAIT_REMAINDER: i64 = 100;

static mut MSG_WAITING: AtomicBool = AtomicBool::new(false);

#[derive(Debug)]
enum Msg {
    Reconfigure(Duration, Duration),
    Stop,
}

#[derive(Debug)]
pub(crate) struct SoftPwm {
    pwm_thread: Option<thread::JoinHandle<Result<()>>>,
    sender: Sender<Msg>,
}

impl SoftPwm {
    pub(crate) fn new(
        pin: u8,
        gpio_state: Arc<GpioState>,
        period: Duration,
        pulse_width: Duration,
    ) -> SoftPwm {
        let (sender, receiver): (Sender<Msg>, Receiver<Msg>) = mpsc::channel();

        let pwm_thread = thread::spawn(move || -> Result<()> {
            // Set the scheduling policy to real-time round robin at the highest priority. This
            // will silently fail if we're not running as root.
            #[cfg(target_env = "gnu")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
            };

            #[cfg(target_env = "musl")]
            let params = sched_param {
                sched_priority: unsafe { libc::sched_get_priority_max(SCHED_RR) },
                sched_ss_low_priority: 0,
                sched_ss_repl_period: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_init_budget: timespec {
                    tv_sec: 0,
                    tv_nsec: 0,
                },
                sched_ss_max_repl: 0,
            };

            unsafe {
                libc::sched_setscheduler(0, SCHED_RR, &params);
            }

            // Set timer slack to 1 ns (default = 50 µs). This is only relevant if we're unable
            // to set a real-time scheduling policy.
            unsafe {
                libc::prctl(PR_SET_TIMERSLACK, 1);
            }

            let mut period_ns =
                (period.as_secs() as i64 * 1_000_000_000) + period.subsec_nanos() as i64;

            let mut pulse_width_ns =
                (pulse_width.as_secs() as i64 * 1_000_000_000) + pulse_width.subsec_nanos() as i64;

            let mut start_ns = get_time_ns();

            loop {
                // PWM active
                if pulse_width_ns > 0 {
                    gpio_state.gpio_mem.set_high(pin);
                }

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if pulse_width_ns >= SLEEP_THRESHOLD {
                    sleep_ns(pulse_width_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining active time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    if (pulse_width_ns - (get_time_ns() - start_ns)) <= BUSYWAIT_REMAINDER {
                        break;
                    }
                }

                // PWM inactive
                gpio_state.gpio_mem.set_low(pin);

                // This is slightly faster than directly checking try_recv()
                if unsafe { MSG_WAITING.compare_and_swap(true, false, Ordering::AcqRel) } {
                    while let Ok(msg) = receiver.try_recv() {
                        match msg {
                            Msg::Reconfigure(period, pulse_width) => {
                                // Reconfigure period and pulse width
                                pulse_width_ns = (pulse_width.as_secs() as i64 * 1_000_000_000)
                                    + pulse_width.subsec_nanos() as i64;

                                period_ns = (period.as_secs() as i64 * 1_000_000_000)
                                    + period.subsec_nanos() as i64;

                                if pulse_width_ns > period_ns {
                                    pulse_width_ns = period_ns;
                                }
                            }
                            Msg::Stop => {
                                // The main thread asked us to stop
                                return Ok(());
                            }
                        }
                    }
                }

                let remaining_ns = period_ns - (get_time_ns() - start_ns);

                // Sleep if we have enough time remaining, while reserving some time
                // for busy waiting to compensate for sleep taking longer than needed.
                if remaining_ns >= SLEEP_THRESHOLD {
                    sleep_ns(remaining_ns - BUSYWAIT_MAX);
                }

                // Busy-wait for the remaining inactive time, minus BUSYWAIT_REMAINDER
                // to account for get_time_ns() overhead
                loop {
                    let current_ns = get_time_ns();
                    if (period_ns - (current_ns - start_ns)) <= BUSYWAIT_REMAINDER {
                        start_ns = current_ns;
                        break;
                    }
                }
            }
        });

        SoftPwm {
            pwm_thread: Some(pwm_thread),
            sender,
        }
    }

    pub(crate) fn reconfigure(&mut self, period: Duration, pulse_width: Duration) {
        let _ = self.sender.send(Msg::Reconfigure(period, pulse_width));
        unsafe {
            MSG_WAITING.store(true, Ordering::Release);
        }
    }

    pub(crate) fn stop(&mut self) -> Result<()> {
        let _ = self.sender.send(Msg::Stop);
        unsafe {
            MSG_WAITING.store(true, Ordering::Release);
        }

        if let Some(pwm_thread) = self.pwm_thread.take() {
            match pwm_thread.join() {
                Ok(r) => return r,
                Err(_) => return Err(Error::ThreadPanic),
            }
        }

        Ok(())
    }
}

impl Drop for SoftPwm {
    fn drop(&mut self) {
        // Don't wait for the pwm thread to exit if the main thread is panicking,
        // because we could potentially block indefinitely while unwinding if the
        // pwm thread doesn't respond to the Stop message for some reason.
        if !thread::panicking() {
            let _ = self.stop();
        }
    }
}

#[inline(always)]
fn get_time_ns() -> i64 {
    let mut ts = timespec {
        tv_sec: 0,
        tv_nsec: 0,
    };

    unsafe {
        libc::clock_gettime(CLOCK_MONOTONIC, &mut ts);
    }

    (ts.tv_sec as i64 * 1_000_000_000) + ts.tv_nsec as i64
}

#[inline(always)]
fn sleep_ns(ns: i64) {
    let ts = timespec {
        tv_sec: (ns / 1_000_000_000) as time_t,
        tv_nsec: (ns % 1_000_000_000) as c_long,
    };

    unsafe {
        libc::clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, ptr::null_mut());
    }
}
<|endoftext|>


<commit_before>use std::panic;
use std::sync::Arc;

use crate::error;
use crate::result;
use crate::AnySocketAddr;
use crate::Error;

use crate::solicit::end_stream::EndStream;
use crate::solicit::header::*;

use futures::future;

use crate::common::types::Types;

use tokio::net::TcpStream;

use tls_api::TlsAcceptor;

use crate::solicit_async::*;

use crate::net::socket::SocketStream;

use crate::common::init_where::InitWhere;

use crate::common::conn::Conn;
use crate::common::conn::ConnStateSnapshot;
use crate::common::conn::SideSpecific;
use crate::common::conn_read::ConnReadSideCustom;
use crate::common::conn_write::CommonToWriteMessage;
use crate::common::conn_write::ConnWriteSideCustom;
use crate::common::sender::CommonSender;
use crate::common::stream::HttpStreamCommon;
use crate::common::stream::HttpStreamData;
use crate::common::stream::HttpStreamDataSpecific;
use crate::common::stream::InMessageStage;
use crate::common::stream_handler::StreamHandlerInternal;
use crate::common::stream_map::HttpStreamRef;
use crate::death::channel::DeathAwareSender;
use crate::death::channel::ErrorAwareDrop;
use crate::death::error_holder::ConnDiedType;
use crate::death::error_holder::SomethingDiedErrorHolder;
use crate::death::oneshot::death_aware_oneshot;
use crate::headers_place::HeadersPlace;
use crate::misc::any_to_string;
use crate::req_resp::RequestOrResponse;
use crate::server::handler::ServerHandler;
use crate::server::handler::ServerHandlerContext;
use crate::server::req::ServerRequest;
use crate::server::types::ServerTypes;
use crate::solicit::stream_id::StreamId;
use crate::ErrorCode;
use crate::ServerConf;
use crate::ServerResponse;
use crate::ServerTlsOption;
use std::future::Future;
use std::net::SocketAddr;
use std::pin::Pin;
use tokio::runtime::Handle;

pub struct ServerStreamData {}

impl HttpStreamDataSpecific for ServerStreamData {}

pub(crate) type ServerStream = HttpStreamCommon<ServerTypes>;

impl ServerStream {
    fn trailers_recvd(&mut self, headers: Headers) {
        if let Some(ref mut sender) = self.peer_tx {
            // TODO: reset on error
            sender.trailers(headers).ok();
        }
    }
}

impl HttpStreamData for ServerStream {
    type Types = ServerTypes;
}

pub(crate) struct ServerConnData {
    factory: Arc<dyn ServerHandler>,
}

impl SideSpecific for ServerConnData {}

#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/42303
type ServerInner<I> = Conn<ServerTypes, I>;

impl<I> ServerInner<I>
where
    I: SocketStream,
{
    fn new_stream_from_client(
        &mut self,
        stream_id: StreamId,
        headers: Headers,
        end_stream: EndStream,
    ) -> result::Result<HttpStreamRef<ServerTypes>> {
        if ServerTypes::init_where(stream_id) == InitWhere::Locally {
            return Err(error::Error::InitiatedStreamWithServerIdFromClient(
                stream_id,
            ));
        }

        if stream_id <= self.last_peer_stream_id {
            return Err(error::Error::StreamIdLeExistingStream(
                stream_id,
                self.last_peer_stream_id,
            ));
        }

        self.last_peer_stream_id = stream_id;

        debug!("new stream: {}", stream_id);

        let (_, out_window) = self.new_stream_data(
            stream_id,
            headers.content_length(),
            InMessageStage::AfterInitialHeaders,
            ServerStreamData {},
        );

        let in_window_size = self
            .streams
            .get_mut(stream_id)
            .unwrap()
            .stream()
            .in_window_size
            .size() as u32;

        let factory = self.specific.factory.clone();

        let sender = ServerResponse {
            common: CommonSender::new(stream_id, self.to_write_tx.clone(), out_window, false),
            drop_callback: None,
        };

        let context = ServerHandlerContext {
            loop_handle: self.loop_handle.clone(),
        };

        let mut stream_handler = None;
        let invoke_result = {
            let req = ServerRequest {
                headers,
                end_stream: end_stream == EndStream::Yes,
                stream_id,
                in_window_size,
                stream_handler: &mut stream_handler,
                to_write_tx: &self.to_write_tx,
            };

            panic::catch_unwind(panic::AssertUnwindSafe(|| {
                factory.start_request(context, req, sender)
            }))
        };

        let mut stream = self.streams.get_mut(stream_id).expect("get stream");

        match invoke_result {
            Ok(Ok(())) => {}
            Ok(Err(e)) => {
                warn!("handler returned error: {:?}", e);
                // Not closing stream because sender object
                // is now responsible for sending `RST_STREAM` on error.
            }
            Err(e) => {
                let e = any_to_string(e);
                warn!("handler panicked: {}", e);
            }
        }

        stream.stream().peer_tx = stream_handler;

        Ok(stream)
    }
}

pub(crate) enum ServerToWriteMessage {
    Common(CommonToWriteMessage),
}

impl ErrorAwareDrop for ServerToWriteMessage {
    type DiedType = ConnDiedType;

    fn drop_with_error(self, _error: Error) {
        // TODO
    }
}

impl From<CommonToWriteMessage> for ServerToWriteMessage {
    fn from(m: CommonToWriteMessage) -> Self {
        ServerToWriteMessage::Common(m)
    }
}

impl<I> ConnWriteSideCustom for Conn<ServerTypes, I>
where
    I: SocketStream,
{
    type Types = ServerTypes;

    fn process_message(&mut self, message: ServerToWriteMessage) -> result::Result<()> {
        match message {
            ServerToWriteMessage::Common(common) => self.process_common_message(common),
        }
    }
}

impl<I> ConnReadSideCustom for Conn<ServerTypes, I>
where
    I: SocketStream,
{
    type Types = ServerTypes;

    fn process_headers(
        &mut self,
        stream_id: StreamId,
        end_stream: EndStream,
        headers: Headers,
    ) -> result::Result<Option<HttpStreamRef<ServerTypes>>> {
        let existing_stream = self
            .get_stream_for_headers_maybe_send_error(stream_id)?
            .is_some();

        let headers_place = match existing_stream {
            true => HeadersPlace::Trailing,
            false => HeadersPlace::Initial,
        };

        if let Err(e) = headers.validate(RequestOrResponse::Request, headers_place) {
            warn!("invalid headers: {:?} {:?}", e, headers);
            self.send_rst_stream(stream_id, ErrorCode::ProtocolError)?;
            return Ok(None);
        }

        if !existing_stream {
            return self
                .new_stream_from_client(stream_id, headers, end_stream)
                .map(Some);
        }

        if end_stream == EndStream::No {
            warn!("more headers without end stream flag");
            self.send_rst_stream(stream_id, ErrorCode::ProtocolError)?;
            return Ok(None);
        }

        let mut stream = self.streams.get_mut(stream_id).unwrap();
        stream.stream().trailers_recvd(headers);
        Ok(Some(stream))
    }
}

pub struct ServerConn {
    write_tx: DeathAwareSender<ServerToWriteMessage>,
    conn_died_error_holder: SomethingDiedErrorHolder<ConnDiedType>,
}

impl ServerConn {
    fn connected<F, I>(
        lh: &Handle,
        socket: impl Future<Output = crate::Result<I>> + Send,
        peer_addr: AnySocketAddr,
        conf: ServerConf,
        service: Arc<F>,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        F: ServerHandler,
        I: SocketStream,
    {
        let (future, write_tx, conn_died_error_holder) = Conn::<ServerTypes, I>::new(
            lh.clone(),
            ServerConnData { factory: service },
            conf.common,
            // TODO
            future::ok((peer_addr, socket)),
        );

        (
            ServerConn {
                write_tx,
                conn_died_error_holder,
            },
            future,
        )
    }

    pub fn new<S, A>(
        lh: &Handle,
        socket: Pin<Box<dyn SocketStream>>,
        peer_addr: AnySocketAddr,
        tls: ServerTlsOption<A>,
        conf: ServerConf,
        service: Arc<S>,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        S: ServerHandler,
        A: TlsAcceptor,
    {
        match tls {
            ServerTlsOption::Plain => {
                let socket = Box::pin(future::ok(socket));
                let (conn, f) = ServerConn::connected(lh, socket, peer_addr, conf, service);
                let f: Pin<Box<dyn Future<Output = ()> + Send>> = Box::pin(f);
                (conn, f)
            }
            ServerTlsOption::Tls(acceptor) => {
                let socket: HttpFutureSend<_> =
                    Box::pin(async move { Ok(acceptor.accept_with_socket(socket).await?) });
                let (conn, f) = ServerConn::connected(lh, socket, peer_addr, conf, service);
                let f: Pin<Box<dyn Future<Output = ()> + Send>> = Box::pin(f);
                (conn, Box::pin(f))
            }
        }
    }

    pub fn new_plain_single_thread<S>(
        lh: &Handle,
        socket: TcpStream,
        peer_addr: SocketAddr,
        conf: ServerConf,
        service: Arc<S>,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        S: ServerHandler,
    {
        let no_tls: ServerTlsOption<tls_api_stub::TlsAcceptor> = ServerTlsOption::Plain;
        ServerConn::new(
            lh,
            Box::pin(socket),
            AnySocketAddr::Inet(peer_addr),
            no_tls,
            conf,
            service,
        )
    }

    pub fn new_plain_single_thread_fn<F>(
        lh: &Handle,
        socket: TcpStream,
        peer_addr: SocketAddr,
        conf: ServerConf,
        f: F,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        F: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> result::Result<()>
            + Send
            + Sync
            + 'static,
    {
        struct HttpServiceFn<F>(F);

        impl<F> ServerHandler for HttpServiceFn<F>
        where
            F: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> result::Result<()>
                + Send
                + Sync
                + 'static,
        {
            fn start_request(
                &self,
                context: ServerHandlerContext,
                req: ServerRequest,
                resp: ServerResponse,
            ) -> result::Result<()> {
                (self.0)(context, req, resp)
            }
        }

        ServerConn::new_plain_single_thread(lh, socket, peer_addr, conf, Arc::new(HttpServiceFn(f)))
    }

    /// For tests
    pub fn dump_state(&self) -> HttpFutureSend<ConnStateSnapshot> {
        let (tx, rx) = death_aware_oneshot(self.conn_died_error_holder.clone());

        if let Err(_) = self.write_tx.unbounded_send(ServerToWriteMessage::Common(
            CommonToWriteMessage::DumpState(tx),
        )) {
            return Box::pin(future::err(error::Error::FailedToSendReqToDumpState));
        }

        Box::pin(rx)
    }
}
<commit_msg>Wrong todo<commit_after>use std::panic;
use std::sync::Arc;

use crate::error;
use crate::result;
use crate::AnySocketAddr;
use crate::Error;

use crate::solicit::end_stream::EndStream;
use crate::solicit::header::*;

use futures::future;

use crate::common::types::Types;

use tokio::net::TcpStream;

use tls_api::TlsAcceptor;

use crate::solicit_async::*;

use crate::net::socket::SocketStream;

use crate::common::init_where::InitWhere;

use crate::common::conn::Conn;
use crate::common::conn::ConnStateSnapshot;
use crate::common::conn::SideSpecific;
use crate::common::conn_read::ConnReadSideCustom;
use crate::common::conn_write::CommonToWriteMessage;
use crate::common::conn_write::ConnWriteSideCustom;
use crate::common::sender::CommonSender;
use crate::common::stream::HttpStreamCommon;
use crate::common::stream::HttpStreamData;
use crate::common::stream::HttpStreamDataSpecific;
use crate::common::stream::InMessageStage;
use crate::common::stream_handler::StreamHandlerInternal;
use crate::common::stream_map::HttpStreamRef;
use crate::death::channel::DeathAwareSender;
use crate::death::channel::ErrorAwareDrop;
use crate::death::error_holder::ConnDiedType;
use crate::death::error_holder::SomethingDiedErrorHolder;
use crate::death::oneshot::death_aware_oneshot;
use crate::headers_place::HeadersPlace;
use crate::misc::any_to_string;
use crate::req_resp::RequestOrResponse;
use crate::server::handler::ServerHandler;
use crate::server::handler::ServerHandlerContext;
use crate::server::req::ServerRequest;
use crate::server::types::ServerTypes;
use crate::solicit::stream_id::StreamId;
use crate::ErrorCode;
use crate::ServerConf;
use crate::ServerResponse;
use crate::ServerTlsOption;
use std::future::Future;
use std::net::SocketAddr;
use std::pin::Pin;
use tokio::runtime::Handle;

pub struct ServerStreamData {}

impl HttpStreamDataSpecific for ServerStreamData {}

pub(crate) type ServerStream = HttpStreamCommon<ServerTypes>;

impl ServerStream {
    fn trailers_recvd(&mut self, headers: Headers) {
        if let Some(ref mut sender) = self.peer_tx {
            // TODO: reset on error
            sender.trailers(headers).ok();
        }
    }
}

impl HttpStreamData for ServerStream {
    type Types = ServerTypes;
}

pub(crate) struct ServerConnData {
    factory: Arc<dyn ServerHandler>,
}

impl SideSpecific for ServerConnData {}

#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/42303
type ServerInner<I> = Conn<ServerTypes, I>;

impl<I> ServerInner<I>
where
    I: SocketStream,
{
    fn new_stream_from_client(
        &mut self,
        stream_id: StreamId,
        headers: Headers,
        end_stream: EndStream,
    ) -> result::Result<HttpStreamRef<ServerTypes>> {
        if ServerTypes::init_where(stream_id) == InitWhere::Locally {
            return Err(error::Error::InitiatedStreamWithServerIdFromClient(
                stream_id,
            ));
        }

        if stream_id <= self.last_peer_stream_id {
            return Err(error::Error::StreamIdLeExistingStream(
                stream_id,
                self.last_peer_stream_id,
            ));
        }

        self.last_peer_stream_id = stream_id;

        debug!("new stream: {}", stream_id);

        let (_, out_window) = self.new_stream_data(
            stream_id,
            headers.content_length(),
            InMessageStage::AfterInitialHeaders,
            ServerStreamData {},
        );

        let in_window_size = self
            .streams
            .get_mut(stream_id)
            .unwrap()
            .stream()
            .in_window_size
            .size() as u32;

        let factory = self.specific.factory.clone();

        let sender = ServerResponse {
            common: CommonSender::new(stream_id, self.to_write_tx.clone(), out_window, false),
            drop_callback: None,
        };

        let context = ServerHandlerContext {
            loop_handle: self.loop_handle.clone(),
        };

        let mut stream_handler = None;
        let invoke_result = {
            let req = ServerRequest {
                headers,
                end_stream: end_stream == EndStream::Yes,
                stream_id,
                in_window_size,
                stream_handler: &mut stream_handler,
                to_write_tx: &self.to_write_tx,
            };

            panic::catch_unwind(panic::AssertUnwindSafe(|| {
                factory.start_request(context, req, sender)
            }))
        };

        let mut stream = self.streams.get_mut(stream_id).expect("get stream");

        match invoke_result {
            Ok(Ok(())) => {}
            Ok(Err(e)) => {
                warn!("handler returned error: {:?}", e);
                // Not closing stream because sender object
                // is now responsible for sending `RST_STREAM` on error.
            }
            Err(e) => {
                let e = any_to_string(e);
                warn!("handler panicked: {}", e);
            }
        }

        stream.stream().peer_tx = stream_handler;

        Ok(stream)
    }
}

pub(crate) enum ServerToWriteMessage {
    Common(CommonToWriteMessage),
}

impl ErrorAwareDrop for ServerToWriteMessage {
    type DiedType = ConnDiedType;

    fn drop_with_error(self, _error: Error) {
        // TODO
    }
}

impl From<CommonToWriteMessage> for ServerToWriteMessage {
    fn from(m: CommonToWriteMessage) -> Self {
        ServerToWriteMessage::Common(m)
    }
}

impl<I> ConnWriteSideCustom for Conn<ServerTypes, I>
where
    I: SocketStream,
{
    type Types = ServerTypes;

    fn process_message(&mut self, message: ServerToWriteMessage) -> result::Result<()> {
        match message {
            ServerToWriteMessage::Common(common) => self.process_common_message(common),
        }
    }
}

impl<I> ConnReadSideCustom for Conn<ServerTypes, I>
where
    I: SocketStream,
{
    type Types = ServerTypes;

    fn process_headers(
        &mut self,
        stream_id: StreamId,
        end_stream: EndStream,
        headers: Headers,
    ) -> result::Result<Option<HttpStreamRef<ServerTypes>>> {
        let existing_stream = self
            .get_stream_for_headers_maybe_send_error(stream_id)?
            .is_some();

        let headers_place = match existing_stream {
            true => HeadersPlace::Trailing,
            false => HeadersPlace::Initial,
        };

        if let Err(e) = headers.validate(RequestOrResponse::Request, headers_place) {
            warn!("invalid headers: {:?} {:?}", e, headers);
            self.send_rst_stream(stream_id, ErrorCode::ProtocolError)?;
            return Ok(None);
        }

        if !existing_stream {
            return self
                .new_stream_from_client(stream_id, headers, end_stream)
                .map(Some);
        }

        if end_stream == EndStream::No {
            warn!("more headers without end stream flag");
            self.send_rst_stream(stream_id, ErrorCode::ProtocolError)?;
            return Ok(None);
        }

        let mut stream = self.streams.get_mut(stream_id).unwrap();
        stream.stream().trailers_recvd(headers);
        Ok(Some(stream))
    }
}

pub struct ServerConn {
    write_tx: DeathAwareSender<ServerToWriteMessage>,
    conn_died_error_holder: SomethingDiedErrorHolder<ConnDiedType>,
}

impl ServerConn {
    fn connected<F, I>(
        lh: &Handle,
        socket: impl Future<Output = crate::Result<I>> + Send,
        peer_addr: AnySocketAddr,
        conf: ServerConf,
        service: Arc<F>,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        F: ServerHandler,
        I: SocketStream,
    {
        let (future, write_tx, conn_died_error_holder) = Conn::<ServerTypes, I>::new(
            lh.clone(),
            ServerConnData { factory: service },
            conf.common,
            future::ok((peer_addr, socket)),
        );

        (
            ServerConn {
                write_tx,
                conn_died_error_holder,
            },
            future,
        )
    }

    pub fn new<S, A>(
        lh: &Handle,
        socket: Pin<Box<dyn SocketStream>>,
        peer_addr: AnySocketAddr,
        tls: ServerTlsOption<A>,
        conf: ServerConf,
        service: Arc<S>,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        S: ServerHandler,
        A: TlsAcceptor,
    {
        match tls {
            ServerTlsOption::Plain => {
                let socket = Box::pin(future::ok(socket));
                let (conn, f) = ServerConn::connected(lh, socket, peer_addr, conf, service);
                let f: Pin<Box<dyn Future<Output = ()> + Send>> = Box::pin(f);
                (conn, f)
            }
            ServerTlsOption::Tls(acceptor) => {
                let socket: HttpFutureSend<_> =
                    Box::pin(async move { Ok(acceptor.accept_with_socket(socket).await?) });
                let (conn, f) = ServerConn::connected(lh, socket, peer_addr, conf, service);
                let f: Pin<Box<dyn Future<Output = ()> + Send>> = Box::pin(f);
                (conn, Box::pin(f))
            }
        }
    }

    pub fn new_plain_single_thread<S>(
        lh: &Handle,
        socket: TcpStream,
        peer_addr: SocketAddr,
        conf: ServerConf,
        service: Arc<S>,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        S: ServerHandler,
    {
        let no_tls: ServerTlsOption<tls_api_stub::TlsAcceptor> = ServerTlsOption::Plain;
        ServerConn::new(
            lh,
            Box::pin(socket),
            AnySocketAddr::Inet(peer_addr),
            no_tls,
            conf,
            service,
        )
    }

    pub fn new_plain_single_thread_fn<F>(
        lh: &Handle,
        socket: TcpStream,
        peer_addr: SocketAddr,
        conf: ServerConf,
        f: F,
    ) -> (ServerConn, impl Future<Output = ()> + Send)
    where
        F: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> result::Result<()>
            + Send
            + Sync
            + 'static,
    {
        struct HttpServiceFn<F>(F);

        impl<F> ServerHandler for HttpServiceFn<F>
        where
            F: Fn(ServerHandlerContext, ServerRequest, ServerResponse) -> result::Result<()>
                + Send
                + Sync
                + 'static,
        {
            fn start_request(
                &self,
                context: ServerHandlerContext,
                req: ServerRequest,
                resp: ServerResponse,
            ) -> result::Result<()> {
                (self.0)(context, req, resp)
            }
        }

        ServerConn::new_plain_single_thread(lh, socket, peer_addr, conf, Arc::new(HttpServiceFn(f)))
    }

    /// For tests
    pub fn dump_state(&self) -> HttpFutureSend<ConnStateSnapshot> {
        let (tx, rx) = death_aware_oneshot(self.conn_died_error_holder.clone());

        if let Err(_) = self.write_tx.unbounded_send(ServerToWriteMessage::Common(
            CommonToWriteMessage::DumpState(tx),
        )) {
            return Box::pin(future::err(error::Error::FailedToSendReqToDumpState));
        }

        Box::pin(rx)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Grin server implementation, glues the different parts of the system (mostly
//! the peer-to-peer server, the blockchain and the transaction pool) and acts
//! as a facade.

use std::net::SocketAddr;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time;

use adapters::*;
use api;
use chain;
use core::{consensus, genesis, global};
use core::core::target::Difficulty;
use dandelion_monitor;
use miner;
use p2p;
use pool;
use seed;
use sync;
use types::*;
use stats::*;
use pow;
use util::LOGGER;

/// Grin server holding internal structures.
pub struct Server {
	/// server config
	pub config: ServerConfig,
	/// handle to our network server
	pub p2p: Arc<p2p::Server>,
	/// data store access
	pub chain: Arc<chain::Chain>,
	/// in-memory transaction pool
	tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
	/// Whether we're currently syncing
	currently_syncing: Arc<AtomicBool>,
	/// To be passed around to collect stats and info
	state_info: ServerStateInfo,
	/// Stop flag
	stop: Arc<AtomicBool>,
}

impl Server {
	/// Instantiates and starts a new server. Optionally takes a callback
	/// for the server to send an ARC copy of itself, to allow another process
	/// to poll info about the server status
	pub fn start<F>(config: ServerConfig, mut info_callback: F) -> Result<(), Error>
	where
		F: FnMut(Arc<Server>),
	{
		let mut mining_config = config.mining_config.clone();
		let serv = Arc::new(Server::new(config)?);
		if mining_config.as_mut().unwrap().enable_mining {
			{
				let mut mining_stats = serv.state_info.mining_stats.write().unwrap();
				mining_stats.is_enabled = true;
			}
			serv.start_miner(mining_config.unwrap());
		}

		info_callback(serv.clone());
		loop {
			thread::sleep(time::Duration::from_secs(1));
			if serv.stop.load(Ordering::Relaxed) {
				return Ok(());
			}
		}
	}

	/// Instantiates a new server associated with the provided future reactor.
	pub fn new(mut config: ServerConfig) -> Result<Server, Error> {
		let stop = Arc::new(AtomicBool::new(false));

		let pool_adapter = Arc::new(PoolToChainAdapter::new());
		let pool_net_adapter = Arc::new(PoolToNetAdapter::new());
		let tx_pool = Arc::new(RwLock::new(pool::TransactionPool::new(
			config.pool_config.clone(),
			pool_adapter.clone(),
			pool_net_adapter.clone(),
		)));

		let chain_adapter = Arc::new(ChainToPoolAndNetAdapter::new(tx_pool.clone()));

		let genesis = match config.chain_type {
			global::ChainTypes::Testnet1 => genesis::genesis_testnet1(),
			global::ChainTypes::Testnet2 => genesis::genesis_testnet2(),
			global::ChainTypes::AutomatedTesting => genesis::genesis_dev(),
			_ => pow::mine_genesis_block(config.mining_config.clone())?,
		};
		info!(LOGGER, "Starting server, genesis block: {}", genesis.hash(),);

		let shared_chain = Arc::new(chain::Chain::init(
			config.db_root.clone(),
			chain_adapter.clone(),
			genesis.clone(),
			pow::verify_size,
		)?);

		pool_adapter.set_chain(Arc::downgrade(&shared_chain));

		let currently_syncing = Arc::new(AtomicBool::new(true));
		let awaiting_peers = Arc::new(AtomicBool::new(false));

		let net_adapter = Arc::new(NetToChainAdapter::new(
			currently_syncing.clone(),
			Arc::downgrade(&shared_chain),
			tx_pool.clone(),
			config.clone(),
		));

		let p2p_config = config.p2p_config.clone();
		let p2p_server = Arc::new(p2p::Server::new(
			config.db_root.clone(),
			config.capabilities,
			p2p_config,
			net_adapter.clone(),
			genesis.hash(),
			stop.clone(),
		)?);
		chain_adapter.init(Arc::downgrade(&p2p_server.peers));
		pool_net_adapter.init(Arc::downgrade(&p2p_server.peers));
		net_adapter.init(Arc::downgrade(&p2p_server.peers));

		if config.seeding_type.clone() != Seeding::Programmatic {
			let seeder = match config.seeding_type.clone() {
				Seeding::None => {
					warn!(
						LOGGER,
						"No seed configured, will stay solo until connected to"
					);
					seed::predefined_seeds(vec![])
				}
				Seeding::List => seed::predefined_seeds(config.seeds.as_mut().unwrap().clone()),
				Seeding::WebStatic => seed::web_seeds(),
				_ => unreachable!(),
			};
			seed::connect_and_monitor(
				p2p_server.clone(),
				config.capabilities,
				seeder,
				stop.clone(),
			);
		}

		// Defaults to None (optional) in config file.
		// This translates to false here.
		let archive_mode = match config.archive_mode {
			None => false,
			Some(b) => b,
		};

		// Defaults to None (optional) in config file.
		// This translates to false here so we do not skip by default.
		let skip_sync_wait = match config.skip_sync_wait {
			None => false,
			Some(b) => b,
		};

		sync::run_sync(
			currently_syncing.clone(),
			awaiting_peers.clone(),
			p2p_server.peers.clone(),
			shared_chain.clone(),
			skip_sync_wait,
			archive_mode,
			stop.clone(),
		);

		let p2p_inner = p2p_server.clone();
		let _ = thread::Builder::new()
			.name("p2p-server".to_string())
			.spawn(move || p2p_inner.listen());

		info!(LOGGER, "Starting rest apis at: {}", &config.api_http_addr);

		api::start_rest_apis(
			config.api_http_addr.clone(),
			Arc::downgrade(&shared_chain),
			Arc::downgrade(&tx_pool),
			Arc::downgrade(&p2p_server.peers),
		);

		info!(
			LOGGER,
			"Starting dandelion monitor: {}", &config.api_http_addr
		);
		dandelion_monitor::monitor_transactions(
			config.pool_config.clone(),
			tx_pool.clone(),
			stop.clone(),
		);

		warn!(LOGGER, "Grin server started.");
		Ok(Server {
			config: config,
			p2p: p2p_server,
			chain: shared_chain,
			tx_pool: tx_pool,
			currently_syncing: currently_syncing,
			state_info: ServerStateInfo {
				awaiting_peers: awaiting_peers,
				..Default::default()
			},
			stop: stop,
		})
	}

	/// Asks the server to connect to a peer at the provided network address.
	pub fn connect_peer(&self, addr: SocketAddr) -> Result<(), Error> {
		self.p2p.connect(&addr)?;
		Ok(())
	}

	/// Number of peers
	pub fn peer_count(&self) -> u32 {
		self.p2p.peers.peer_count()
	}

	/// Start mining for blocks on a separate thread. Uses toy miner by default,
	/// mostly for testing, but can also load a plugin from cuckoo-miner
	pub fn start_miner(&self, config: pow::types::MinerConfig) {
		let cuckoo_size = global::sizeshift();
		let proof_size = global::proofsize();
		let currently_syncing = self.currently_syncing.clone();

		let mut miner = miner::Miner::new(
			config.clone(),
			self.chain.clone(),
			self.tx_pool.clone(),
			self.stop.clone(),
		);
		let mining_stats = self.state_info.mining_stats.clone();
		miner.set_debug_output_id(format!("Port {}", self.config.p2p_config.port));
		let _ = thread::Builder::new()
			.name("miner".to_string())
			.spawn(move || {
				// TODO push this down in the run loop so miner gets paused anytime we
				// decide to sync again
				let secs_5 = time::Duration::from_secs(5);
				while currently_syncing.load(Ordering::Relaxed) {
					thread::sleep(secs_5);
				}
				miner.run_loop(config.clone(), mining_stats, cuckoo_size as u32, proof_size);
			});
	}

	/// The chain head
	pub fn head(&self) -> chain::Tip {
		self.chain.head().unwrap()
	}

	/// The head of the block header chain
	pub fn header_head(&self) -> chain::Tip {
		self.chain.get_header_head().unwrap()
	}

	/// Returns a set of stats about this server. This and the ServerStats
	/// structure
	/// can be updated over time to include any information needed by tests or
	/// other
	/// consumers
	pub fn get_server_stats(&self) -> Result<ServerStats, Error> {
		let mining_stats = self.state_info.mining_stats.read().unwrap().clone();
		let awaiting_peers = self.state_info.awaiting_peers.load(Ordering::Relaxed);

		// Fill out stats on our current difficulty calculation
		// TODO: check the overhead of calculating this again isn't too much
		// could return it from next_difficulty, but would rather keep consensus
		// code clean. This may be handy for testing but not really needed
		// for release
		let diff_stats = {
			let diff_iter = self.chain.difficulty_iter();
			let last_blocks: Vec<Result<(u64, Difficulty), consensus::TargetError>> =
				global::difficulty_data_to_vector(diff_iter)
					.into_iter()
					.skip(consensus::MEDIAN_TIME_WINDOW as usize)
					.take(consensus::DIFFICULTY_ADJUST_WINDOW as usize)
					.collect();

			let mut last_time = last_blocks[0].clone().unwrap().0;
			let tip_height = self.chain.head().unwrap().height as i64;
			let earliest_block_height = tip_height as i64 - last_blocks.len() as i64;

			let mut i = 1;

			let diff_entries: Vec<DiffBlock> = last_blocks
				.iter()
				.skip(1)
				.map(|n| {
					let (time, diff) = n.clone().unwrap();
					let dur = time - last_time;
					let height = earliest_block_height + i + 1;
					i += 1;
					last_time = time;
					DiffBlock {
						block_number: height,
						difficulty: diff.into_num(),
						time: time,
						duration: dur,
					}
				})
				.collect();

			let block_time_sum = diff_entries.iter().fold(0, |sum, t| sum + t.duration);
			let block_diff_sum = diff_entries.iter().fold(0, |sum, d| sum + d.difficulty);
			DiffStats {
				height: tip_height as u64,
				last_blocks: diff_entries,
				average_block_time: block_time_sum / consensus::DIFFICULTY_ADJUST_WINDOW,
				average_difficulty: block_diff_sum / consensus::DIFFICULTY_ADJUST_WINDOW,
				window_size: consensus::DIFFICULTY_ADJUST_WINDOW,
			}
		};

		let peer_stats = self.p2p
			.peers
			.connected_peers()
			.into_iter()
			.map(|p| {
				let p = p.read().unwrap();
				PeerStats::from_peer(&p)
			})
			.collect();
		Ok(ServerStats {
			peer_count: self.peer_count(),
			head: self.head(),
			header_head: self.header_head(),
			is_syncing: self.currently_syncing.load(Ordering::Relaxed),
			awaiting_peers: awaiting_peers,
			mining_stats: mining_stats,
			peer_stats: peer_stats,
			diff_stats: diff_stats,
		})
	}

	/// Stop the server.
	pub fn stop(&self) {
		self.p2p.stop();
		self.stop.store(true, Ordering::Relaxed);
	}
}
<commit_msg>average over last 59 blocks (#917)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Grin server implementation, glues the different parts of the system (mostly
//! the peer-to-peer server, the blockchain and the transaction pool) and acts
//! as a facade.

use std::net::SocketAddr;
use std::sync::{Arc, RwLock};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time;

use adapters::*;
use api;
use chain;
use core::{consensus, genesis, global};
use core::core::target::Difficulty;
use dandelion_monitor;
use miner;
use p2p;
use pool;
use seed;
use sync;
use types::*;
use stats::*;
use pow;
use util::LOGGER;

/// Grin server holding internal structures.
pub struct Server {
	/// server config
	pub config: ServerConfig,
	/// handle to our network server
	pub p2p: Arc<p2p::Server>,
	/// data store access
	pub chain: Arc<chain::Chain>,
	/// in-memory transaction pool
	tx_pool: Arc<RwLock<pool::TransactionPool<PoolToChainAdapter>>>,
	/// Whether we're currently syncing
	currently_syncing: Arc<AtomicBool>,
	/// To be passed around to collect stats and info
	state_info: ServerStateInfo,
	/// Stop flag
	stop: Arc<AtomicBool>,
}

impl Server {
	/// Instantiates and starts a new server. Optionally takes a callback
	/// for the server to send an ARC copy of itself, to allow another process
	/// to poll info about the server status
	pub fn start<F>(config: ServerConfig, mut info_callback: F) -> Result<(), Error>
	where
		F: FnMut(Arc<Server>),
	{
		let mut mining_config = config.mining_config.clone();
		let serv = Arc::new(Server::new(config)?);
		if mining_config.as_mut().unwrap().enable_mining {
			{
				let mut mining_stats = serv.state_info.mining_stats.write().unwrap();
				mining_stats.is_enabled = true;
			}
			serv.start_miner(mining_config.unwrap());
		}

		info_callback(serv.clone());
		loop {
			thread::sleep(time::Duration::from_secs(1));
			if serv.stop.load(Ordering::Relaxed) {
				return Ok(());
			}
		}
	}

	/// Instantiates a new server associated with the provided future reactor.
	pub fn new(mut config: ServerConfig) -> Result<Server, Error> {
		let stop = Arc::new(AtomicBool::new(false));

		let pool_adapter = Arc::new(PoolToChainAdapter::new());
		let pool_net_adapter = Arc::new(PoolToNetAdapter::new());
		let tx_pool = Arc::new(RwLock::new(pool::TransactionPool::new(
			config.pool_config.clone(),
			pool_adapter.clone(),
			pool_net_adapter.clone(),
		)));

		let chain_adapter = Arc::new(ChainToPoolAndNetAdapter::new(tx_pool.clone()));

		let genesis = match config.chain_type {
			global::ChainTypes::Testnet1 => genesis::genesis_testnet1(),
			global::ChainTypes::Testnet2 => genesis::genesis_testnet2(),
			global::ChainTypes::AutomatedTesting => genesis::genesis_dev(),
			_ => pow::mine_genesis_block(config.mining_config.clone())?,
		};
		info!(LOGGER, "Starting server, genesis block: {}", genesis.hash(),);

		let shared_chain = Arc::new(chain::Chain::init(
			config.db_root.clone(),
			chain_adapter.clone(),
			genesis.clone(),
			pow::verify_size,
		)?);

		pool_adapter.set_chain(Arc::downgrade(&shared_chain));

		let currently_syncing = Arc::new(AtomicBool::new(true));
		let awaiting_peers = Arc::new(AtomicBool::new(false));

		let net_adapter = Arc::new(NetToChainAdapter::new(
			currently_syncing.clone(),
			Arc::downgrade(&shared_chain),
			tx_pool.clone(),
			config.clone(),
		));

		let p2p_config = config.p2p_config.clone();
		let p2p_server = Arc::new(p2p::Server::new(
			config.db_root.clone(),
			config.capabilities,
			p2p_config,
			net_adapter.clone(),
			genesis.hash(),
			stop.clone(),
		)?);
		chain_adapter.init(Arc::downgrade(&p2p_server.peers));
		pool_net_adapter.init(Arc::downgrade(&p2p_server.peers));
		net_adapter.init(Arc::downgrade(&p2p_server.peers));

		if config.seeding_type.clone() != Seeding::Programmatic {
			let seeder = match config.seeding_type.clone() {
				Seeding::None => {
					warn!(
						LOGGER,
						"No seed configured, will stay solo until connected to"
					);
					seed::predefined_seeds(vec![])
				}
				Seeding::List => seed::predefined_seeds(config.seeds.as_mut().unwrap().clone()),
				Seeding::WebStatic => seed::web_seeds(),
				_ => unreachable!(),
			};
			seed::connect_and_monitor(
				p2p_server.clone(),
				config.capabilities,
				seeder,
				stop.clone(),
			);
		}

		// Defaults to None (optional) in config file.
		// This translates to false here.
		let archive_mode = match config.archive_mode {
			None => false,
			Some(b) => b,
		};

		// Defaults to None (optional) in config file.
		// This translates to false here so we do not skip by default.
		let skip_sync_wait = match config.skip_sync_wait {
			None => false,
			Some(b) => b,
		};

		sync::run_sync(
			currently_syncing.clone(),
			awaiting_peers.clone(),
			p2p_server.peers.clone(),
			shared_chain.clone(),
			skip_sync_wait,
			archive_mode,
			stop.clone(),
		);

		let p2p_inner = p2p_server.clone();
		let _ = thread::Builder::new()
			.name("p2p-server".to_string())
			.spawn(move || p2p_inner.listen());

		info!(LOGGER, "Starting rest apis at: {}", &config.api_http_addr);

		api::start_rest_apis(
			config.api_http_addr.clone(),
			Arc::downgrade(&shared_chain),
			Arc::downgrade(&tx_pool),
			Arc::downgrade(&p2p_server.peers),
		);

		info!(
			LOGGER,
			"Starting dandelion monitor: {}", &config.api_http_addr
		);
		dandelion_monitor::monitor_transactions(
			config.pool_config.clone(),
			tx_pool.clone(),
			stop.clone(),
		);

		warn!(LOGGER, "Grin server started.");
		Ok(Server {
			config: config,
			p2p: p2p_server,
			chain: shared_chain,
			tx_pool: tx_pool,
			currently_syncing: currently_syncing,
			state_info: ServerStateInfo {
				awaiting_peers: awaiting_peers,
				..Default::default()
			},
			stop: stop,
		})
	}

	/// Asks the server to connect to a peer at the provided network address.
	pub fn connect_peer(&self, addr: SocketAddr) -> Result<(), Error> {
		self.p2p.connect(&addr)?;
		Ok(())
	}

	/// Number of peers
	pub fn peer_count(&self) -> u32 {
		self.p2p.peers.peer_count()
	}

	/// Start mining for blocks on a separate thread. Uses toy miner by default,
	/// mostly for testing, but can also load a plugin from cuckoo-miner
	pub fn start_miner(&self, config: pow::types::MinerConfig) {
		let cuckoo_size = global::sizeshift();
		let proof_size = global::proofsize();
		let currently_syncing = self.currently_syncing.clone();

		let mut miner = miner::Miner::new(
			config.clone(),
			self.chain.clone(),
			self.tx_pool.clone(),
			self.stop.clone(),
		);
		let mining_stats = self.state_info.mining_stats.clone();
		miner.set_debug_output_id(format!("Port {}", self.config.p2p_config.port));
		let _ = thread::Builder::new()
			.name("miner".to_string())
			.spawn(move || {
				// TODO push this down in the run loop so miner gets paused anytime we
				// decide to sync again
				let secs_5 = time::Duration::from_secs(5);
				while currently_syncing.load(Ordering::Relaxed) {
					thread::sleep(secs_5);
				}
				miner.run_loop(config.clone(), mining_stats, cuckoo_size as u32, proof_size);
			});
	}

	/// The chain head
	pub fn head(&self) -> chain::Tip {
		self.chain.head().unwrap()
	}

	/// The head of the block header chain
	pub fn header_head(&self) -> chain::Tip {
		self.chain.get_header_head().unwrap()
	}

	/// Returns a set of stats about this server. This and the ServerStats
	/// structure
	/// can be updated over time to include any information needed by tests or
	/// other
	/// consumers
	pub fn get_server_stats(&self) -> Result<ServerStats, Error> {
		let mining_stats = self.state_info.mining_stats.read().unwrap().clone();
		let awaiting_peers = self.state_info.awaiting_peers.load(Ordering::Relaxed);

		// Fill out stats on our current difficulty calculation
		// TODO: check the overhead of calculating this again isn't too much
		// could return it from next_difficulty, but would rather keep consensus
		// code clean. This may be handy for testing but not really needed
		// for release
		let diff_stats = {
			let diff_iter = self.chain.difficulty_iter();
			let last_blocks: Vec<Result<(u64, Difficulty), consensus::TargetError>> =
				global::difficulty_data_to_vector(diff_iter)
					.into_iter()
					.skip(consensus::MEDIAN_TIME_WINDOW as usize)
					.take(consensus::DIFFICULTY_ADJUST_WINDOW as usize)
					.collect();

			let mut last_time = last_blocks[0].clone().unwrap().0;
			let tip_height = self.chain.head().unwrap().height as i64;
			let earliest_block_height = tip_height as i64 - last_blocks.len() as i64;

			let mut i = 1;

			let diff_entries: Vec<DiffBlock> = last_blocks
				.iter()
				.skip(1)
				.map(|n| {
					let (time, diff) = n.clone().unwrap();
					let dur = time - last_time;
					let height = earliest_block_height + i + 1;
					i += 1;
					last_time = time;
					DiffBlock {
						block_number: height,
						difficulty: diff.into_num(),
						time: time,
						duration: dur,
					}
				})
				.collect();

			let block_time_sum = diff_entries.iter().fold(0, |sum, t| sum + t.duration);
			let block_diff_sum = diff_entries.iter().fold(0, |sum, d| sum + d.difficulty);
			DiffStats {
				height: tip_height as u64,
				last_blocks: diff_entries,
				average_block_time: block_time_sum / (consensus::DIFFICULTY_ADJUST_WINDOW - 1),
				average_difficulty: block_diff_sum / (consensus::DIFFICULTY_ADJUST_WINDOW - 1),
				window_size: consensus::DIFFICULTY_ADJUST_WINDOW,
			}
		};

		let peer_stats = self.p2p
			.peers
			.connected_peers()
			.into_iter()
			.map(|p| {
				let p = p.read().unwrap();
				PeerStats::from_peer(&p)
			})
			.collect();
		Ok(ServerStats {
			peer_count: self.peer_count(),
			head: self.head(),
			header_head: self.header_head(),
			is_syncing: self.currently_syncing.load(Ordering::Relaxed),
			awaiting_peers: awaiting_peers,
			mining_stats: mining_stats,
			peer_stats: peer_stats,
			diff_stats: diff_stats,
		})
	}

	/// Stop the server.
	pub fn stop(&self) {
		self.p2p.stop();
		self.stop.store(true, Ordering::Relaxed);
	}
}
<|endoftext|>


<commit_before><commit_msg>Incapsulated glfw inside Win<commit_after><|endoftext|>


<commit_before>use consumer::*;
use producer::*;
use std::marker::PhantomData;
use std::rc::Rc;
use stream::*;

struct TapState<C, F, T> {
    consumer: C,
    func: F,
    marker_t: PhantomData<T>,
}

pub struct Tap<S, F> {
    stream: S,
    func: F,
}

impl<C, F: FnMut(&T), T> Consumer<T> for TapState<C, F, T>
    where C: Consumer<T>,
          F: FnMut(&T)
{
    fn init(&mut self, producer: Rc<Producer>) {
        self.consumer.init(producer);
    }

    fn emit(&mut self, item: T) {
        (self.func)(&item);
        self.consumer.emit(item);
    }
}

impl<S, F, T> Stream<T> for Tap<S, F>
    where S: Stream<T>,
          F: FnMut(&T)
{
    fn consume<C: Consumer<T>>(self, consumer: C) {
        self.stream.consume(TapState {
            consumer: consumer,
            func: self.func,
            marker_t: PhantomData::<T>,
        });
    }
}

pub trait TappableStream<T>: Stream<T> {
    fn tap<F>(self, func: F) -> Tap<Self, F>
        where F: FnMut(&T),
              Self: Sized
    {
        Tap {
            stream: self,
            func: func,
        }
    }
}

impl<S, T> TappableStream<T> for S where S: Stream<T> {}
<commit_msg>add ref support for tap operator<commit_after>use consumer::*;
use producer::*;
use std::marker::PhantomData;
use std::rc::Rc;
use stream::*;

struct TapState<C, F, T> {
    consumer: C,
    func: F,
    marker_t: PhantomData<T>,
}

pub struct Tap<S, F> {
    stream: S,
    func: F,
}

impl<C, F: FnMut(&mut T), T> Consumer<T> for TapState<C, F, T>
    where C: Consumer<T>,
          F: FnMut(&mut T)
{
    fn init(&mut self, producer: Rc<Producer>) {
        self.consumer.init(producer);
    }

    fn emit(&mut self, mut item: T) {
        (self.func)(&mut item);
        self.consumer.emit(item);
    }
}

impl<C, F: FnMut(&T), T> ConsumerRef<T> for TapState<C, F, T>
    where C: ConsumerRef<T>,
          F: FnMut(&T)
{
    fn init(&mut self, producer: Rc<Producer>) {
        self.consumer.init(producer);
    }

    fn emit(&mut self, item: &T) {
        (self.func)(item);
        self.consumer.emit(item);
    }
}

impl<C, F: FnMut(&mut T), T> ConsumerRefMut<T> for TapState<C, F, T>
    where C: ConsumerRefMut<T>,
          F: FnMut(&mut T)
{
    fn init(&mut self, producer: Rc<Producer>) {
        self.consumer.init(producer);
    }

    fn emit(&mut self, item: &mut T) {
        (self.func)(item);
        self.consumer.emit(item);
    }
}

impl<S, F, T> Stream<T> for Tap<S, F>
    where S: Stream<T>,
          F: FnMut(&mut T)
{
    fn consume<C: Consumer<T>>(self, consumer: C) {
        self.stream.consume(TapState {
            consumer: consumer,
            func: self.func,
            marker_t: PhantomData::<T>,
        });
    }
}

impl<S, F, T> StreamRef<T> for Tap<S, F>
    where S: StreamRef<T>,
          F: FnMut(&T)
{
    fn consume<C: ConsumerRef<T>>(self, consumer: C) {
        self.stream.consume(TapState {
            consumer: consumer,
            func: self.func,
            marker_t: PhantomData::<T>,
        });
    }
}

impl<S, F, T> StreamRefMut<T> for Tap<S, F>
    where S: StreamRefMut<T>,
          F: FnMut(&mut T)
{
    fn consume<C: ConsumerRefMut<T>>(self, consumer: C) {
        self.stream.consume(TapState {
            consumer: consumer,
            func: self.func,
            marker_t: PhantomData::<T>,
        });
    }
}

pub trait TappableStream<T>: Stream<T> {
    fn tap<F>(self, func: F) -> Tap<Self, F>
        where F: FnMut(&mut T),
              Self: Sized
    {
        Tap {
            stream: self,
            func: func,
        }
    }
}

pub trait TappableStreamRef<T>: StreamRef<T> {
    fn tap<F>(self, func: F) -> Tap<Self, F>
        where F: FnMut(&T),
              Self: Sized
    {
        Tap {
            stream: self,
            func: func,
        }
    }
}

pub trait TappableStreamRefMut<T>: StreamRefMut<T> {
    fn tap<F>(self, func: F) -> Tap<Self, F>
        where F: FnMut(&mut T),
              Self: Sized
    {
        Tap {
            stream: self,
            func: func,
        }
    }
}

impl<S, T> TappableStream<T> for S where S: Stream<T> {}
impl<S, T> TappableStreamRef<T> for S where S: StreamRef<T> {}
impl<S, T> TappableStreamRefMut<T> for S where S: StreamRefMut<T> {}
<|endoftext|>


<commit_before>// Copyright (C) 2020 Jason Ish
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use crate::logger::log;
use crate::resource::Resource;
use rusqlite::params;

pub fn init_db(db: &mut rusqlite::Connection, prefix: &str) -> Result<(), rusqlite::Error> {
    let mut version = db
        .query_row("select max(version) from schema", params![], |row| {
            let version: i64 = row.get(0).unwrap();
            Ok(version)
        })
        .unwrap_or(0);

    loop {
        let filename = format!("{}/V{}.sql", prefix, version);
        let asset = Resource::get(&filename);
        if let Some(asset) = asset {
            if version == 0 {
                log::info!("Initializing SQLite database")
            } else {
                log::info!("Updating SQLite database to schema version {}", version);
            }
            let asset = String::from_utf8_lossy(&asset);
            let tx = db.transaction()?;
            tx.execute_batch(&asset)?;
            tx.execute(
                "INSERT INTO schema (version, timestamp) VALUES (?1, date('now'))",
                params![version],
            )?;
            tx.commit()?;
        } else {
            break;
        }
        version += 1;
    }

    Ok(())
}
<commit_msg>sqlite: fix migrations<commit_after>// Copyright (C) 2020 Jason Ish
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use crate::logger::log;
use crate::resource::Resource;
use rusqlite::params;

pub fn init_db(db: &mut rusqlite::Connection, prefix: &str) -> Result<(), rusqlite::Error> {
    let version = db
        .query_row("select max(version) from schema", params![], |row| {
            let version: i64 = row.get(0).unwrap();
            Ok(version)
        })
        .unwrap_or(-1);
    let mut next_version = version + 1;

    loop {
        let filename = format!("{}/V{}.sql", prefix, next_version);
        let asset = Resource::get(&filename);
        if let Some(asset) = asset {
            if version == 0 {
                log::info!("Initializing SQLite database")
            } else {
                log::info!(
                    prefix = prefix,
                    "Updating SQLite database to schema version {}",
                    version
                );
            }
            let asset = String::from_utf8_lossy(&asset);
            let tx = db.transaction()?;
            tx.execute_batch(&asset)?;
            tx.execute(
                "INSERT INTO schema (version, timestamp) VALUES (?1, date('now'))",
                params![next_version],
            )?;
            tx.commit()?;
        } else {
            break;
        }
        next_version += 1;
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! impl bool {}

#[cfg(not(boostrap_stdarch_ignore_this))]
#[lang = "bool"]
impl bool {
    /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(bool_to_option)]
    ///
    /// assert_eq!(false.then(0), None);
    /// assert_eq!(true.then(0), Some(0));
    /// ```
    #[unstable(feature = "bool_to_option", issue = "0")]
    #[inline]
    pub fn then<T>(self, t: T) -> Option<T> {
        if self {
            Some(t)
        } else {
            None
        }
    }

    /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(bool_to_option)]
    ///
    /// assert_eq!(false.then_with(|| 0), None);
    /// assert_eq!(true.then_with(|| 0), Some(0));
    /// ```
    #[unstable(feature = "bool_to_option", issue = "0")]
    #[inline]
    pub fn then_with<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
        if self {
            Some(f())
        } else {
            None
        }
    }
}
<commit_msg>Add tracking issue<commit_after>//! impl bool {}

#[cfg(not(boostrap_stdarch_ignore_this))]
#[lang = "bool"]
impl bool {
    /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(bool_to_option)]
    ///
    /// assert_eq!(false.then(0), None);
    /// assert_eq!(true.then(0), Some(0));
    /// ```
    #[unstable(feature = "bool_to_option", issue = "64260")]
    #[inline]
    pub fn then<T>(self, t: T) -> Option<T> {
        if self {
            Some(t)
        } else {
            None
        }
    }

    /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(bool_to_option)]
    ///
    /// assert_eq!(false.then_with(|| 0), None);
    /// assert_eq!(true.then_with(|| 0), Some(0));
    /// ```
    #[unstable(feature = "bool_to_option", issue = "64260")]
    #[inline]
    pub fn then_with<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
        if self {
            Some(f())
        } else {
            None
        }
    }
}
<|endoftext|>