<commit_before>//! Main entry point to the library.
//! See examples for documentation on how to use this struct.

use std::{env, ptr};
use std::any::Any;
use std::cell::UnsafeCell;
use std::ffi::CStr;

use DataDeviceManager;
use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
              WlShellManager, WlShellManagerHandler, XdgV6ShellManager, XdgV6ShellManagerHandler};
use render::GenericRenderer;
use types::seat::Seats;

use wayland_sys::server::{wl_display, wl_event_loop, WAYLAND_SERVER_HANDLE};
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
                  wlr_compositor, wlr_compositor_create, wlr_wl_shell, wlr_wl_shell_create,
                  wlr_xdg_shell_v6, wlr_xdg_shell_v6_create};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
pub static mut COMPOSITOR_PTR: *mut Compositor = 0 as *mut _;

#[allow(dead_code)]
pub struct Compositor {
    /// User data.
    pub data: Box<Any>,
    /// The list of seats.
    ///
    /// This is stored here due to their complicated memory model.
    ///
    /// Please refer to the `Seat` and `Seats` documentation to learn how to use this.
    pub seats: Seats,
    /// Manager for the inputs.
    input_manager: Option<Box<InputManager>>,
    /// Manager for the outputs.
    output_manager: Option<Box<OutputManager>>,
    /// Manager for Wayland shells.
    wl_shell_manager: Option<Box<WlShellManager>>,
    /// Manager for XDG shells v6.
    xdg_v6_shell_manager: Option<Box<XdgV6ShellManager>>,
    /// Pointer to wl_shell global.
    /// If wl_shell_manager is `None`, this value will be `NULL`.
    wl_shell_global: *mut wlr_wl_shell,
    /// Pointer to the xdg_shell_v6 global.
    /// If xdg_v6_shell_manager is `None`, this value will be `NULL`.
    xdg_v6_shell_global: *mut wlr_xdg_shell_v6,
    /// Pointer to the wlr_compositor.
    compositor: *mut wlr_compositor,
    /// Pointer to the wlroots backend in use.
    backend: *mut wlr_backend,
    /// Pointer to the wayland display.
    display: *mut wl_display,
    /// Pointer to the event loop.
    event_loop: *mut wl_event_loop,
    /// Shared memory buffer file descriptor.
    shm_fd: i32,
    /// Name of the Wayland socket that we are binding to.
    socket_name: String,
    /// Optional decoration manager extension.
    pub server_decoration_manager: Option<ServerDecorationManager>,
    /// The renderer used to draw things to the screen.
    pub renderer: Option<GenericRenderer>,
    /// The DnD manager
    data_device_manager: Option<DataDeviceManager>,
    /// The error from the panic, if there was one.
    panic_error: Option<Box<Any + Send>>
}

pub struct CompositorBuilder {
    input_manager_handler: Option<Box<InputManagerHandler>>,
    output_manager_handler: Option<Box<OutputManagerHandler>>,
    wl_shell_manager_handler: Option<Box<WlShellManagerHandler>>,
    xdg_v6_shell_manager_handler: Option<Box<XdgV6ShellManagerHandler>>,
    gles2: bool,
    server_decoration_manager: bool,
    data_device_manager: bool
}

impl CompositorBuilder {
    /// Make a new compositor builder.
    ///
    /// Unless otherwise noted, each option is `false`/`None`.
    pub fn new() -> Self {
        CompositorBuilder { gles2: false,
                            server_decoration_manager: false,
                            data_device_manager: false,
                            input_manager_handler: None,
                            output_manager_handler: None,
                            wl_shell_manager_handler: None,
                            xdg_v6_shell_manager_handler: None }
    }

    /// Set the handler for inputs.
    pub fn input_manager(mut self, input_manager_handler: Box<InputManagerHandler>) -> Self {
        self.input_manager_handler = Some(input_manager_handler);
        self
    }

    /// Set the handler for outputs.
    pub fn output_manager(mut self, output_manager_handler: Box<OutputManagerHandler>) -> Self {
        self.output_manager_handler = Some(output_manager_handler);
        self
    }

    /// Set the handler for Wayland shells.
    pub fn wl_shell_manager(mut self,
                            wl_shell_manager_handler: Box<WlShellManagerHandler>)
                            -> Self {
        self.wl_shell_manager_handler = Some(wl_shell_manager_handler);
        self
    }

    /// Set the handler for xdg v6 shells.
    pub fn xdg_shell_v6_manager(mut self,
                                xdg_v6_shell_manager_handler: Box<XdgV6ShellManagerHandler>)
                                -> Self {
        self.xdg_v6_shell_manager_handler = Some(xdg_v6_shell_manager_handler);
        self
    }

    /// Decide whether or not to enable the data device manager.
    ///
    /// This is used to do DnD, or "drag 'n drop" copy paste.
    pub fn data_device(mut self, data_device_manager: bool) -> Self {
        self.data_device_manager = data_device_manager;
        self
    }

    /// Decide whether or not to enable the GLES2 extension.
    pub fn gles2(mut self, gles2_renderer: bool) -> Self {
        self.gles2 = gles2_renderer;
        self
    }

    /// Decide whether or not to enable the server decoration manager protocol
    /// extension.
    pub fn server_decoration_manager(mut self, server_decoration_manager: bool) -> Self {
        self.server_decoration_manager = server_decoration_manager;
        self
    }

    /// Makes a new compositor that handles the setup of the graphical backend
    /// (e.g, Wayland, X11, or DRM).
    ///
    /// Also automatically opens the socket for clients to communicate to the
    /// compositor with.
    pub fn build_auto<D>(self, data: D) -> Compositor
        where D: Any + 'static
    {
        unsafe {
            let display =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) as *mut wl_display;
            let event_loop =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
            let backend = wlr_backend_autocreate(display as *mut _);
            if backend.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Could not auto-create backend");
            }
            // Set up shared memory buffer for Wayland clients.
            let shm_fd = wl_display_init_shm(display as *mut _);
            // Create optional extensions.
            let server_decoration_manager = if self.server_decoration_manager {
                ServerDecorationManager::new(display)
            } else {
                None
            };
            let data_device_manager = if self.data_device_manager {
                DataDeviceManager::new(display as _)
            } else {
                None
            };
            let compositor;
            let renderer = if self.gles2 {
                let gles2 = GenericRenderer::gles2_renderer(backend);
                // Set up wlr_compositor
                let gles2_ptr = gles2.as_ptr();
                compositor = wlr_compositor_create(display as *mut _, gles2_ptr);
                Some(gles2)
            } else {
                compositor = wlr_compositor_create(display as *mut _, ptr::null_mut());
                None
            };

            // Set up input manager, if the user provided it.
            let input_manager = self.input_manager_handler.map(|handler| {
                let mut input_manager = InputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_input as *mut _ as _,
                              input_manager.add_listener() as *mut _ as _);
                input_manager
            });

            // Set up output manager, if the user provided it.
            let output_manager = self.output_manager_handler.map(|handler| {
                let mut output_manager = OutputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_output as *mut _ as _,
                              output_manager.add_listener() as *mut _ as _);
                output_manager
            });

            // Set up wl_shell handler and associated Wayland global,
            // if user provided a manager for it.
            let mut wl_shell_global = ptr::null_mut();
            let wl_shell_manager = self.wl_shell_manager_handler.map(|handler| {
                wl_shell_global = wlr_wl_shell_create(display as *mut _);
                let mut wl_shell_manager = WlShellManager::new(handler);
                wl_signal_add(&mut (*wl_shell_global).events.new_surface as *mut _ as _,
                              wl_shell_manager.add_listener() as *mut _ as _);
                wl_shell_manager
            });

            // Set up the xdg_shell_v6 handler and associated Wayland global,
            // if user provided a manager for it.
            let mut xdg_v6_shell_global = ptr::null_mut();
            let xdg_v6_shell_manager = self.xdg_v6_shell_manager_handler.map(|handler| {
                xdg_v6_shell_global = wlr_xdg_shell_v6_create(display as *mut _);
                let mut xdg_v6_shell_manager = XdgV6ShellManager::new((vec![], handler));
                wl_signal_add(&mut (*xdg_v6_shell_global).events.new_surface as *mut _ as _,
                              xdg_v6_shell_manager.add_listener() as *mut _ as _);
                xdg_v6_shell_manager
            });

            // Open the socket to the Wayland server.
            let socket = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_add_socket_auto, display);
            if socket.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Unable to open wayland socket");
            }
            let socket_name = CStr::from_ptr(socket).to_string_lossy().into_owned();
            wlr_log!(L_DEBUG,
                     "Running compositor on wayland display {}",
                     socket_name);
            env::set_var("_WAYLAND_DISPLAY", socket_name.clone());
            Compositor { data: Box::new(data),
                         seats: Seats::default(),
                         socket_name,
                         input_manager,
                         output_manager,
                         wl_shell_manager,
                         wl_shell_global,
                         xdg_v6_shell_manager,
                         xdg_v6_shell_global,
                         data_device_manager,
                         compositor,
                         backend,
                         display,
                         event_loop,
                         shm_fd,
                         server_decoration_manager,
                         renderer,
                         panic_error: None }
        }
    }
}

impl Compositor {
    /// Enters the wayland event loop. Won't return until the compositor is
    /// shut off
    pub fn run(self) {
        unsafe {
            let compositor = UnsafeCell::new(self);
            if COMPOSITOR_PTR != 0 as _ {
                // NOTE Rationale for panicking:
                // * Nicer than an abort
                // * Not yet in C land
                panic!("A compositor is already running!")
            }
            COMPOSITOR_PTR = compositor.get();
            wlr_log!(L_INFO, "Starting compositor");
            if !wlr_backend_start((*compositor.get()).backend) {
                wlr_backend_destroy((*compositor.get()).backend);
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Failed to start backend");
            }
            env::set_var("WAYLAND_DISPLAY", (*COMPOSITOR_PTR).socket_name.clone());
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_display_run,
                          (*compositor.get()).display);
            match (*compositor.get()).panic_error.take() {
                None => {}
                Some(err) => {
                    // A panic occured, now we can re-throw it safely.
                    ::std::panic::resume_unwind(err)
                }
            }
        }
    }

    pub fn terminate(&mut self) {
        unsafe {
            COMPOSITOR_PTR = 0 as _;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_terminate, self.display);
        }
    }

    pub unsafe fn display(&self) -> *mut wl_display {
        self.display
    }

    pub unsafe fn event_loop(&self) -> *mut wl_event_loop {
        self.event_loop
    }

    /// Saves the panic error information in the compositor, to be re-thrown
    /// later when we are out of the C callback stack.
    pub(crate) fn save_panic_error(&mut self, error: Box<Any + Send>) {
        self.panic_error = Some(error);
    }
}

/// Terminates the compositor.
/// If one is not running, does nothing
pub fn terminate() {
    unsafe {
        if COMPOSITOR_PTR != 0 as _ {
            (*COMPOSITOR_PTR).terminate();
            COMPOSITOR_PTR = 0 as _
        }
    }
}
<commit_msg>call wlr_compositor_destroy in Compositor::drop<commit_after>//! Main entry point to the library.
//! See examples for documentation on how to use this struct.

use std::{env, ptr};
use std::any::Any;
use std::cell::UnsafeCell;
use std::ffi::CStr;

use DataDeviceManager;
use extensions::server_decoration::ServerDecorationManager;
use manager::{InputManager, InputManagerHandler, OutputManager, OutputManagerHandler,
              WlShellManager, WlShellManagerHandler, XdgV6ShellManager, XdgV6ShellManagerHandler};
use render::GenericRenderer;
use types::seat::Seats;

use wayland_sys::server::{wl_display, wl_event_loop, WAYLAND_SERVER_HANDLE};
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wlr_backend, wlr_backend_autocreate, wlr_backend_destroy, wlr_backend_start,
                  wlr_compositor, wlr_compositor_create, wlr_compositor_destroy, wlr_wl_shell,
                  wlr_wl_shell_create, wlr_xdg_shell_v6, wlr_xdg_shell_v6_create};
use wlroots_sys::wayland_server::sys::wl_display_init_shm;

/// Global compositor pointer, used to refer to the compositor state unsafely.
pub static mut COMPOSITOR_PTR: *mut Compositor = 0 as *mut _;

#[allow(dead_code)]
pub struct Compositor {
    /// User data.
    pub data: Box<Any>,
    /// The list of seats.
    ///
    /// This is stored here due to their complicated memory model.
    ///
    /// Please refer to the `Seat` and `Seats` documentation to learn how to use this.
    pub seats: Seats,
    /// Manager for the inputs.
    input_manager: Option<Box<InputManager>>,
    /// Manager for the outputs.
    output_manager: Option<Box<OutputManager>>,
    /// Manager for Wayland shells.
    wl_shell_manager: Option<Box<WlShellManager>>,
    /// Manager for XDG shells v6.
    xdg_v6_shell_manager: Option<Box<XdgV6ShellManager>>,
    /// Pointer to wl_shell global.
    /// If wl_shell_manager is `None`, this value will be `NULL`.
    wl_shell_global: *mut wlr_wl_shell,
    /// Pointer to the xdg_shell_v6 global.
    /// If xdg_v6_shell_manager is `None`, this value will be `NULL`.
    xdg_v6_shell_global: *mut wlr_xdg_shell_v6,
    /// Pointer to the wlr_compositor.
    compositor: *mut wlr_compositor,
    /// Pointer to the wlroots backend in use.
    backend: *mut wlr_backend,
    /// Pointer to the wayland display.
    display: *mut wl_display,
    /// Pointer to the event loop.
    event_loop: *mut wl_event_loop,
    /// Shared memory buffer file descriptor.
    shm_fd: i32,
    /// Name of the Wayland socket that we are binding to.
    socket_name: String,
    /// Optional decoration manager extension.
    pub server_decoration_manager: Option<ServerDecorationManager>,
    /// The renderer used to draw things to the screen.
    pub renderer: Option<GenericRenderer>,
    /// The DnD manager
    data_device_manager: Option<DataDeviceManager>,
    /// The error from the panic, if there was one.
    panic_error: Option<Box<Any + Send>>
}

pub struct CompositorBuilder {
    input_manager_handler: Option<Box<InputManagerHandler>>,
    output_manager_handler: Option<Box<OutputManagerHandler>>,
    wl_shell_manager_handler: Option<Box<WlShellManagerHandler>>,
    xdg_v6_shell_manager_handler: Option<Box<XdgV6ShellManagerHandler>>,
    gles2: bool,
    server_decoration_manager: bool,
    data_device_manager: bool
}

impl CompositorBuilder {
    /// Make a new compositor builder.
    ///
    /// Unless otherwise noted, each option is `false`/`None`.
    pub fn new() -> Self {
        CompositorBuilder { gles2: false,
                            server_decoration_manager: false,
                            data_device_manager: false,
                            input_manager_handler: None,
                            output_manager_handler: None,
                            wl_shell_manager_handler: None,
                            xdg_v6_shell_manager_handler: None }
    }

    /// Set the handler for inputs.
    pub fn input_manager(mut self, input_manager_handler: Box<InputManagerHandler>) -> Self {
        self.input_manager_handler = Some(input_manager_handler);
        self
    }

    /// Set the handler for outputs.
    pub fn output_manager(mut self, output_manager_handler: Box<OutputManagerHandler>) -> Self {
        self.output_manager_handler = Some(output_manager_handler);
        self
    }

    /// Set the handler for Wayland shells.
    pub fn wl_shell_manager(mut self,
                            wl_shell_manager_handler: Box<WlShellManagerHandler>)
                            -> Self {
        self.wl_shell_manager_handler = Some(wl_shell_manager_handler);
        self
    }

    /// Set the handler for xdg v6 shells.
    pub fn xdg_shell_v6_manager(mut self,
                                xdg_v6_shell_manager_handler: Box<XdgV6ShellManagerHandler>)
                                -> Self {
        self.xdg_v6_shell_manager_handler = Some(xdg_v6_shell_manager_handler);
        self
    }

    /// Decide whether or not to enable the data device manager.
    ///
    /// This is used to do DnD, or "drag 'n drop" copy paste.
    pub fn data_device(mut self, data_device_manager: bool) -> Self {
        self.data_device_manager = data_device_manager;
        self
    }

    /// Decide whether or not to enable the GLES2 extension.
    pub fn gles2(mut self, gles2_renderer: bool) -> Self {
        self.gles2 = gles2_renderer;
        self
    }

    /// Decide whether or not to enable the server decoration manager protocol
    /// extension.
    pub fn server_decoration_manager(mut self, server_decoration_manager: bool) -> Self {
        self.server_decoration_manager = server_decoration_manager;
        self
    }

    /// Makes a new compositor that handles the setup of the graphical backend
    /// (e.g, Wayland, X11, or DRM).
    ///
    /// Also automatically opens the socket for clients to communicate to the
    /// compositor with.
    pub fn build_auto<D>(self, data: D) -> Compositor
        where D: Any + 'static
    {
        unsafe {
            let display =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) as *mut wl_display;
            let event_loop =
                ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
            let backend = wlr_backend_autocreate(display as *mut _);
            if backend.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Could not auto-create backend");
            }
            // Set up shared memory buffer for Wayland clients.
            let shm_fd = wl_display_init_shm(display as *mut _);
            // Create optional extensions.
            let server_decoration_manager = if self.server_decoration_manager {
                ServerDecorationManager::new(display)
            } else {
                None
            };
            let data_device_manager = if self.data_device_manager {
                DataDeviceManager::new(display as _)
            } else {
                None
            };
            let compositor;
            let renderer = if self.gles2 {
                let gles2 = GenericRenderer::gles2_renderer(backend);
                // Set up wlr_compositor
                let gles2_ptr = gles2.as_ptr();
                compositor = wlr_compositor_create(display as *mut _, gles2_ptr);
                Some(gles2)
            } else {
                compositor = wlr_compositor_create(display as *mut _, ptr::null_mut());
                None
            };

            // Set up input manager, if the user provided it.
            let input_manager = self.input_manager_handler.map(|handler| {
                let mut input_manager = InputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_input as *mut _ as _,
                              input_manager.add_listener() as *mut _ as _);
                input_manager
            });

            // Set up output manager, if the user provided it.
            let output_manager = self.output_manager_handler.map(|handler| {
                let mut output_manager = OutputManager::new((vec![], handler));
                wl_signal_add(&mut (*backend).events.new_output as *mut _ as _,
                              output_manager.add_listener() as *mut _ as _);
                output_manager
            });

            // Set up wl_shell handler and associated Wayland global,
            // if user provided a manager for it.
            let mut wl_shell_global = ptr::null_mut();
            let wl_shell_manager = self.wl_shell_manager_handler.map(|handler| {
                wl_shell_global = wlr_wl_shell_create(display as *mut _);
                let mut wl_shell_manager = WlShellManager::new(handler);
                wl_signal_add(&mut (*wl_shell_global).events.new_surface as *mut _ as _,
                              wl_shell_manager.add_listener() as *mut _ as _);
                wl_shell_manager
            });

            // Set up the xdg_shell_v6 handler and associated Wayland global,
            // if user provided a manager for it.
            let mut xdg_v6_shell_global = ptr::null_mut();
            let xdg_v6_shell_manager = self.xdg_v6_shell_manager_handler.map(|handler| {
                xdg_v6_shell_global = wlr_xdg_shell_v6_create(display as *mut _);
                let mut xdg_v6_shell_manager = XdgV6ShellManager::new((vec![], handler));
                wl_signal_add(&mut (*xdg_v6_shell_global).events.new_surface as *mut _ as _,
                              xdg_v6_shell_manager.add_listener() as *mut _ as _);
                xdg_v6_shell_manager
            });

            // Open the socket to the Wayland server.
            let socket = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_add_socket_auto, display);
            if socket.is_null() {
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Unable to open wayland socket");
            }
            let socket_name = CStr::from_ptr(socket).to_string_lossy().into_owned();
            wlr_log!(L_DEBUG,
                     "Running compositor on wayland display {}",
                     socket_name);
            env::set_var("_WAYLAND_DISPLAY", socket_name.clone());
            Compositor { data: Box::new(data),
                         seats: Seats::default(),
                         socket_name,
                         input_manager,
                         output_manager,
                         wl_shell_manager,
                         wl_shell_global,
                         xdg_v6_shell_manager,
                         xdg_v6_shell_global,
                         data_device_manager,
                         compositor,
                         backend,
                         display,
                         event_loop,
                         shm_fd,
                         server_decoration_manager,
                         renderer,
                         panic_error: None }
        }
    }
}

impl Compositor {
    /// Enters the wayland event loop. Won't return until the compositor is
    /// shut off
    pub fn run(self) {
        unsafe {
            let compositor = UnsafeCell::new(self);
            if COMPOSITOR_PTR != 0 as _ {
                // NOTE Rationale for panicking:
                // * Nicer than an abort
                // * Not yet in C land
                panic!("A compositor is already running!")
            }
            COMPOSITOR_PTR = compositor.get();
            wlr_log!(L_INFO, "Starting compositor");
            if !wlr_backend_start((*compositor.get()).backend) {
                wlr_backend_destroy((*compositor.get()).backend);
                // NOTE Rationale for panicking:
                // * Won't be in C land just yet, so it's safe to panic
                // * Can always be returned in a Result instead, but for now
                //   if you auto create it's assumed you can't recover.
                panic!("Failed to start backend");
            }
            env::set_var("WAYLAND_DISPLAY", (*COMPOSITOR_PTR).socket_name.clone());
            ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                          wl_display_run,
                          (*compositor.get()).display);
            match (*compositor.get()).panic_error.take() {
                None => {}
                Some(err) => {
                    // A panic occured, now we can re-throw it safely.
                    ::std::panic::resume_unwind(err)
                }
            }
        }
    }

    pub fn terminate(&mut self) {
        unsafe {
            COMPOSITOR_PTR = 0 as _;
            ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_terminate, self.display);
        }
    }

    pub unsafe fn display(&self) -> *mut wl_display {
        self.display
    }

    pub unsafe fn event_loop(&self) -> *mut wl_event_loop {
        self.event_loop
    }

    /// Saves the panic error information in the compositor, to be re-thrown
    /// later when we are out of the C callback stack.
    pub(crate) fn save_panic_error(&mut self, error: Box<Any + Send>) {
        self.panic_error = Some(error);
    }
}

impl Drop for Compositor {
    fn drop(&mut self) {
        unsafe { wlr_compositor_destroy(self.compositor) }
    }
}

/// Terminates the compositor.
/// If one is not running, does nothing
pub fn terminate() {
    unsafe {
        if COMPOSITOR_PTR != 0 as _ {
            (*COMPOSITOR_PTR).terminate();
            COMPOSITOR_PTR = 0 as _
        }
    }
}
<|endoftext|>


<commit_before>pub fn sort(word: &'static str) -> String {
    let mut chars: Vec<char> = word.chars().collect();
    chars.sort();
    return chars.into_iter().collect();
}

fn extract_numbers(s: &str) -> Vec<String> {
    let mut num = String::new();
    let mut m = vec![];

    for c in s.chars() {
        if c.is_numeric() {
            num.push(c);
        }
        else {
            if !num.is_empty() {
                m.push(num.clone());
                num.clear();
            }
        }
    }

    if !num.is_empty() {
        m.push(num);
    }

    return m;
}

fn main() {
    let mystr1: &'static str = "This is a readonly string";

    for c in mystr1.chars().rev() {
        print!("{}", c);
    }

    println!("");

    let mut mystr2 = String::new();
    for c in mystr1.chars() {
        mystr2.push(c);
    }

    println!("{}", mystr2);

    mystr2 = "Hello World".to_string();

    println!("{}", mystr2);

    let num: u32 = 12;

    mystr2 = num.to_string();

    println!("{}", mystr2);

    let str = sort("abzerfdsgyiof");
    print!("{}", str);

    let mystr3 = "x12y7".to_string();
    let m: Vec<String> = extract_numbers(&mystr3); // -> ( "12", "7" )

    for x in m.iter() {
        println!("{}", x);
    }
}<commit_msg>formatted code<commit_after>pub fn sort(word: &'static str) -> String {
    let mut chars: Vec<char> = word.chars().collect();
    chars.sort();
    return chars.into_iter().collect();
}

fn extract_numbers(s: &str) -> Vec<String> {
    let mut num = String::new();
    let mut m = vec![];

    for c in s.chars() {
        if c.is_numeric() {
            num.push(c);
        }
        else {
            if !num.is_empty() {
                m.push(num.clone());
                num.clear();
            }
        }
    }

    if !num.is_empty() {
        m.push(num);
    }

    return m;
}

fn main() {
    let mystr1: &'static str = "This is a readonly string";

    for c in mystr1.chars().rev() {
        print!("{}", c);
    }

    println!("");

    let mut mystr2 = String::new();
    for c in mystr1.chars() {
        mystr2.push(c);
    }

    println!("{}", mystr2);

    mystr2 = "Hello World".to_string();

    println!("{}", mystr2);

    let num: u32 = 12;

    mystr2 = num.to_string();

    println!("{}", mystr2);

    let str = sort("abzerfdsgyiof");
    print!("{}", str);

    let mystr3 = "x12y7".to_string();
    let m: Vec<String> = extract_numbers(&mystr3); // -> ( "12", "7" )

    println!("");

    for x in m.iter() {
        println!("{}", x);
    }
}<|endoftext|>


<commit_before>extern crate ring;
extern crate udt;

use std::net::{UdpSocket, SocketAddr, IpAddr};
use std::str;
use std::fmt;
use udt::{UdtSocket, UdtError, UdtOpts, SocketType, SocketFamily};
use ring::aead;
use ring::rand;

// TODO config
const UDT_BUF_SIZE: i32 = 4096000;
pub const MAX_MESSAGE_SIZE: usize = 1024000;

pub mod crypto {
    use ring::aead;
    use ring::aead::{SealingKey, OpeningKey, Algorithm};
    use ring::rand::{SystemRandom, SecureRandom};
    static ALGORITHM: &'static Algorithm = &aead::CHACHA20_POLY1305;

    pub struct Handler {
        _working_buf: [u8; super::MAX_MESSAGE_SIZE],
        rand: SystemRandom,
        opening_key: OpeningKey,
        sealing_key: SealingKey,
    }

    pub fn gen_key() -> Vec<u8> {
        let rand = SystemRandom::new();
        let mut keybytes = vec![0u8; ALGORITHM.key_len()];
        rand.fill(&mut keybytes);
        keybytes
    }

    impl Handler {
        pub fn new(key: &[u8]) -> Handler {
            Handler {
                _working_buf: [0u8; super::MAX_MESSAGE_SIZE],
                rand: SystemRandom::new(),
                opening_key: aead::OpeningKey::new(ALGORITHM, key).unwrap(),
                sealing_key: aead::SealingKey::new(ALGORITHM, key).unwrap(),
            }
        }

        pub fn seal(&mut self, buf: &mut [u8], len: usize) -> Result<usize, ()> {
            let nonce_len = ALGORITHM.nonce_len();
            let max_suffix_len = ALGORITHM.max_overhead_len();

            assert!(nonce_len < u8::max_value() as usize,
                    "Uh, why is the nonce size this big?");

            assert!(len <= buf.len() - max_suffix_len,
                    "Buffer doesn't have enough suffix padding.");

            let mut nonce = vec![0u8; nonce_len];
            self.rand.fill(&mut nonce).unwrap();

            let mut sealed = vec![0u8; len + max_suffix_len];
            sealed[0..len].copy_from_slice(&buf[..len]);
            match aead::seal_in_place(&self.sealing_key,
                                      &nonce,
                                      &mut sealed,
                                      max_suffix_len,
                                      &[]) {
                Ok(seal_len) => {
                    buf[..nonce_len].copy_from_slice(&nonce[..]);
                    buf[nonce_len..nonce_len+seal_len].copy_from_slice(&sealed[..seal_len]);
                    Ok(nonce_len + seal_len)
                }
                Err(e) => {
                    Err(())
                }
            }
        }

        pub fn open(&mut self, buf: &mut [u8]) -> Result<usize, String> {
            let nonce_len = ALGORITHM.nonce_len();
            if buf.len() < nonce_len {
                return Err("msg not long enough to contain nonce".into());
            } else if buf.len() > super::MAX_MESSAGE_SIZE {
                return Err("max message size exceeded".into());
            }
            let nonce = buf[..nonce_len].to_owned();
            self._working_buf[..buf.len()-nonce_len].copy_from_slice(&buf[nonce_len..]);

            match aead::open_in_place(&self.opening_key, &nonce, 0, &mut self._working_buf[..buf.len()-nonce_len], &[]) {
                Ok(opened_len) => {
                    buf[..opened_len].copy_from_slice(&self._working_buf[..opened_len]);
                    Ok(opened_len)
                }
                Err(_) => {
                    Err("decrypt failed".into())
                }
            }

        }
    }

    // Tests for the crypto module
    #[cfg(test)]
    mod test {

        #[test]
        fn raw_roundtrip() {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            rng.fill(&mut nonce_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; 1350];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];
            aead::seal_in_place(&key, &nonce_bytes,
                                &mut in_out, out_suffix_capacity,
                                &[]).unwrap();

            let opening_key = OpeningKey::new(super::ALGORITHM, &key_bytes).unwrap();
            let len = aead::open_in_place(&opening_key, &nonce_bytes,
                                          0, &mut in_out, &[]).unwrap();

            assert_eq!(len, 1350);
            assert_eq!(&in_out[..len], &data[..]);
        }

        #[test]
        fn roundtrip() {
            use ::rand;
            use ::rand::distributions::{IndependentSample, Range};
            // generate some data, seal it, and then make sure it unseals to the same thing
            let mut rng = rand::thread_rng();
            let between = Range::new(10, 10000);

            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let data_size: usize = between.ind_sample(&mut rng);
            let mut data = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            for i in 0..data_size {
                data[i] = rand::random();
            }

            let orig = data[..data_size].to_owned();

            let cipher_len = handler.seal(&mut data, data_size).unwrap();
            let decrypted_len = handler.open(&mut data[..cipher_len]).unwrap();
            assert_eq!(decrypted_len, data_size);
            assert_eq!(orig, &data[..decrypted_len], "original and decrypted don't match!");
        }

        //#[test]
        //fn key_sanity() {
        //    use std::collections::HashSet;
        //    use sodiumoxide::crypto::secretbox;
        //    use sodiumoxide::crypto::secretbox::xsalsa20poly1305::Key;

        //    let mut set: HashSet<[u8;32]> = HashSet::with_capacity(10000);

        //    for _ in 0..10000 {
        //        let key = secretbox::gen_key();
        //        let Key(keybytes) = key;
        //        assert!(set.insert(keybytes));
        //    }
        //}

        //#[test]
        //fn nonce_sanity() {
        //    use std::collections::HashSet;
        //    use sodiumoxide::crypto::secretbox;
        //    use sodiumoxide::crypto::secretbox::xsalsa20poly1305::Nonce;

        //    let mut set: HashSet<[u8;24]> = HashSet::with_capacity(10000);

        //    for _ in 0..10000 {
        //        let nonce = secretbox::gen_nonce();
        //        let Nonce(noncebytes) = nonce;
        //        assert!(set.insert(noncebytes));
        //    }
        //}
    }

    // #[cfg(all(feature = "nightly", test))]
    // mod bench {
    //    extern crate test;
    //
    //    #[bench]
    //    fn bench_seal(b: &mut test::Bencher) {
    //        use sodiumoxide::crypto::secretbox;
    //        let key = secretbox::gen_key();
    //        b.iter(move || super::seal(&[0; 1300], &key))
    //    }
    //
    //    #[bench]
    //    fn bench_gen_key(b: &mut test::Bencher) {
    //        use sodiumoxide::crypto::secretbox;
    //        b.iter(|| secretbox::gen_key());
    //    }
    // }
}

fn new_udt_socket() -> UdtSocket {
    udt::init();
    let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
    sock.setsockopt(UdtOpts::UDP_RCVBUF, UDT_BUF_SIZE).unwrap();
    sock.setsockopt(UdtOpts::UDP_SNDBUF, UDT_BUF_SIZE).unwrap();
    sock
}

fn send(sock: &UdtSocket, key: &aead::SealingKey, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
    unimplemented!();
    // FIXME don't unwrap, create an Error struct that can handle everything
    // if let Ok(sealed_len) = crypto::seal(buf, len, key) {
    //     sock.sendmsg(&buf[..sealed_len]).map(|_| ())
    // } else {
    //     Err(UdtError {
    //         err_code: -1,
    //         err_msg: "encryption failure".into(),
    //     })
    // }
}

fn recv(sock: &UdtSocket, key: &aead::OpeningKey, buf: &mut [u8]) -> Result<usize, UdtError> {
    unimplemented!();
    // let size = try!(sock.recvmsg(buf));
    // crypto::open(&mut buf[..size], key).map_err(|_| {
    //     UdtError {
    //         err_code: -1,
    //         err_msg: String::from("decryption failure"),
    //     }
    // })
}

pub struct PortRange {
    start: u16,
    end: u16,
}

pub trait Transceiver {
    fn send(&self, buf: &[u8]) -> Result<(), UdtError>;
    fn recv(&self, buf: &mut [u8]) -> Result<usize, UdtError>;
    fn close(&self) -> Result<(), UdtError>;
}

pub struct Server {
    pub ip_addr: IpAddr,
    pub port: u16,
    crypto: crypto::Handler,
    sock: UdtSocket,
}

pub struct Client {
    addr: SocketAddr,
    sock: UdtSocket,
    crypto: crypto::Handler,
}

pub struct ServerConnection<'a> {
    crypto: &'a crypto::Handler,
    sock: UdtSocket,
}

impl Client {
    pub fn new(addr: SocketAddr, key: &[u8]) -> Client {
        let sock = new_udt_socket();
        Client {
            addr: addr,
            sock: sock,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn connect(&self) -> Result<(), UdtError> {
        self.sock.connect(self.addr)
    }
}

impl Transceiver for Client {
    fn send(&self, buf: &[u8]) -> Result<(), UdtError> {
        unimplemented!();
        // send(&self.sock, &self.sealing_key, buf)
    }

    fn recv(&self, buf: &mut [u8]) -> Result<usize, UdtError> {
        unimplemented!();
        // recv(&self.sock, &self.opening_key, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl Server {
    pub fn get_open_port(range: &PortRange) -> Result<u16, ()> {
        for p in range.start..range.end {
            if let Ok(_) = UdpSocket::bind(&format!("0.0.0.0:{}", p)[..]) {
                return Ok(p);
            }
        }
        Err(())
    }

    pub fn new(ip_addr: IpAddr, port: u16, key: &[u8]) -> Server {
        let sock = new_udt_socket();
        sock.bind(SocketAddr::new(ip_addr, port)).unwrap();
        Server {
            sock: sock,
            ip_addr: ip_addr,
            port: port,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn listen(&self) -> Result<(), UdtError> {
        self.sock.listen(2)
    }

    pub fn accept(&self) -> Result<ServerConnection, UdtError> {
        self.sock.accept().map(|(sock, _)| {
            ServerConnection {
                crypto: &self.crypto,
                sock: sock,
            }
        })
    }
}

impl<'a> ServerConnection<'a> {
    pub fn getpeer(&self) -> Result<SocketAddr, UdtError> {
        self.sock.getpeername()
    }
}

impl<'a> Transceiver for ServerConnection<'a> {
    fn send(&self, buf: &[u8]) -> Result<(), UdtError> {
        unimplemented!();
        // send(&self.sock, self.key, buf)
    }

    fn recv(&self, buf: &mut [u8]) -> Result<usize, UdtError> {
        unimplemented!();
        // recv(&self.sock, self.key, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl<'a> PortRange {
    fn new(start: u16, end: u16) -> Result<PortRange, &'a str> {
        if start > end {
            Err("range end must be greater than or equal to start")
        } else {
            Ok(PortRange {
                start: start,
                end: end,
            })
        }
    }

    pub fn from(s: &str) -> Result<PortRange, &'a str> {
        let sections: Vec<&str> = s.split('-').collect();
        if sections.len() != 2 {
            return Err("Range must be specified in the form of \"<start>-<end>\"");
        }
        let (start, end) = (sections[0].parse::<u16>(), sections[1].parse::<u16>());
        if start.is_err() || end.is_err() {
            return Err("improperly formatted port range");
        }
        PortRange::new(start.unwrap(), end.unwrap())
    }
}

impl fmt::Display for PortRange {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}-{}", self.start, self.end)
    }
}
<commit_msg>clarify<commit_after>extern crate ring;
extern crate udt;

use std::net::{UdpSocket, SocketAddr, IpAddr};
use std::str;
use std::fmt;
use udt::{UdtSocket, UdtError, UdtOpts, SocketType, SocketFamily};
use ring::aead;
use ring::rand;

// TODO config
const UDT_BUF_SIZE: i32 = 4096000;
pub const MAX_MESSAGE_SIZE: usize = 1024000;

pub mod crypto {
    use ring::aead;
    use ring::aead::{SealingKey, OpeningKey, Algorithm};
    use ring::rand::{SystemRandom, SecureRandom};
    static ALGORITHM: &'static Algorithm = &aead::CHACHA20_POLY1305;

    pub struct Handler {
        _working_buf: [u8; super::MAX_MESSAGE_SIZE],
        rand: SystemRandom,
        opening_key: OpeningKey,
        sealing_key: SealingKey,
    }

    pub fn gen_key() -> Vec<u8> {
        let rand = SystemRandom::new();
        let mut keybytes = vec![0u8; ALGORITHM.key_len()];
        rand.fill(&mut keybytes);
        keybytes
    }

    impl Handler {
        pub fn new(key: &[u8]) -> Handler {
            Handler {
                _working_buf: [0u8; super::MAX_MESSAGE_SIZE],
                rand: SystemRandom::new(),
                opening_key: aead::OpeningKey::new(ALGORITHM, key).unwrap(),
                sealing_key: aead::SealingKey::new(ALGORITHM, key).unwrap(),
            }
        }

        pub fn seal(&mut self, buf: &mut [u8], len: usize) -> Result<usize, ()> {
            let nonce_len = ALGORITHM.nonce_len();
            let max_suffix_len = ALGORITHM.max_overhead_len();

            assert!(nonce_len < u8::max_value() as usize,
                    "Uh, why is the nonce size this big?");

            assert!(len <= buf.len() - max_suffix_len,
                    "Buffer doesn't have enough suffix padding.");

            let mut nonce = vec![0u8; nonce_len];
            self.rand.fill(&mut nonce).unwrap();

            let mut sealed = vec![0u8; len + max_suffix_len];
            sealed[0..len].copy_from_slice(&buf[..len]);
            match aead::seal_in_place(&self.sealing_key,
                                      &nonce,
                                      &mut sealed,
                                      max_suffix_len,
                                      &[]) {
                Ok(seal_len) => {
                    buf[..nonce_len].copy_from_slice(&nonce[..]);
                    buf[nonce_len..nonce_len+seal_len].copy_from_slice(&sealed[..seal_len]);
                    Ok(nonce_len + seal_len)
                }
                Err(e) => {
                    Err(())
                }
            }
        }

        pub fn open(&mut self, buf: &mut [u8]) -> Result<usize, String> {
            let nonce_len = ALGORITHM.nonce_len();

            if buf.len() < nonce_len {
                return Err("msg not long enough to contain nonce".into());
            } else if buf.len() > super::MAX_MESSAGE_SIZE {
                return Err("max message size exceeded".into());
            }

            let nonce = buf[..nonce_len].to_owned();

            aead::open_in_place(&self.opening_key, &nonce, nonce_len, buf, &[])
                .map_err(|_| String::from("decrypt failed"))
        }
    }

    // Tests for the crypto module
    #[cfg(test)]
    mod test {

        #[test]
        fn raw_roundtrip() {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            rng.fill(&mut nonce_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; 1350];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];
            aead::seal_in_place(&key, &nonce_bytes,
                                &mut in_out, out_suffix_capacity,
                                &[]).unwrap();

            let opening_key = OpeningKey::new(super::ALGORITHM, &key_bytes).unwrap();
            let len = aead::open_in_place(&opening_key, &nonce_bytes,
                                          0, &mut in_out, &[]).unwrap();

            assert_eq!(len, 1350);
            assert_eq!(&in_out[..len], &data[..]);
        }

        #[test]
        fn roundtrip() {
            use ::rand;
            use ::rand::distributions::{IndependentSample, Range};
            // generate some data, seal it, and then make sure it unseals to the same thing
            let mut rng = rand::thread_rng();
            let between = Range::new(10, 10000);

            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let data_size: usize = between.ind_sample(&mut rng);
            let mut data = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            for i in 0..data_size {
                data[i] = rand::random();
            }

            let orig = data[..data_size].to_owned();

            let cipher_len = handler.seal(&mut data, data_size).unwrap();
            let decrypted_len = handler.open(&mut data[..cipher_len]).unwrap();
            assert_eq!(decrypted_len, data_size);
            assert_eq!(orig, &data[..decrypted_len], "original and decrypted don't match!");
        }

        //#[test]
        //fn key_sanity() {
        //    use std::collections::HashSet;
        //    use sodiumoxide::crypto::secretbox;
        //    use sodiumoxide::crypto::secretbox::xsalsa20poly1305::Key;

        //    let mut set: HashSet<[u8;32]> = HashSet::with_capacity(10000);

        //    for _ in 0..10000 {
        //        let key = secretbox::gen_key();
        //        let Key(keybytes) = key;
        //        assert!(set.insert(keybytes));
        //    }
        //}

        //#[test]
        //fn nonce_sanity() {
        //    use std::collections::HashSet;
        //    use sodiumoxide::crypto::secretbox;
        //    use sodiumoxide::crypto::secretbox::xsalsa20poly1305::Nonce;

        //    let mut set: HashSet<[u8;24]> = HashSet::with_capacity(10000);

        //    for _ in 0..10000 {
        //        let nonce = secretbox::gen_nonce();
        //        let Nonce(noncebytes) = nonce;
        //        assert!(set.insert(noncebytes));
        //    }
        //}
    }

    #[cfg(all(feature = "nightly", test))]
    mod bench {
       extern crate test;

       // #[bench]
       // fn bench_seal(b: &mut test::Bencher) {
       //     let key = super::gen_key();
       //     let mut handler = super::Handler::new(&key);
       //     let mut buf = [0; super::super::MAX_MESSAGE_SIZE];
       //     b.bytes = 1300;
       //     b.iter(move || handler.seal(&mut buf, 1300))
       // }
    }
}

fn new_udt_socket() -> UdtSocket {
    udt::init();
    let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
    sock.setsockopt(UdtOpts::UDP_RCVBUF, UDT_BUF_SIZE).unwrap();
    sock.setsockopt(UdtOpts::UDP_SNDBUF, UDT_BUF_SIZE).unwrap();
    sock
}

fn send(sock: &UdtSocket, key: &aead::SealingKey, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
    unimplemented!();
    // FIXME don't unwrap, create an Error struct that can handle everything
    // if let Ok(sealed_len) = crypto::seal(buf, len, key) {
    //     sock.sendmsg(&buf[..sealed_len]).map(|_| ())
    // } else {
    //     Err(UdtError {
    //         err_code: -1,
    //         err_msg: "encryption failure".into(),
    //     })
    // }
}

fn recv(sock: &UdtSocket, key: &aead::OpeningKey, buf: &mut [u8]) -> Result<usize, UdtError> {
    unimplemented!();
    // let size = try!(sock.recvmsg(buf));
    // crypto::open(&mut buf[..size], key).map_err(|_| {
    //     UdtError {
    //         err_code: -1,
    //         err_msg: String::from("decryption failure"),
    //     }
    // })
}

pub struct PortRange {
    start: u16,
    end: u16,
}

pub trait Transceiver {
    fn send(&self, buf: &[u8]) -> Result<(), UdtError>;
    fn recv(&self, buf: &mut [u8]) -> Result<usize, UdtError>;
    fn close(&self) -> Result<(), UdtError>;
}

pub struct Server {
    pub ip_addr: IpAddr,
    pub port: u16,
    crypto: crypto::Handler,
    sock: UdtSocket,
}

pub struct Client {
    addr: SocketAddr,
    sock: UdtSocket,
    crypto: crypto::Handler,
}

pub struct ServerConnection<'a> {
    crypto: &'a crypto::Handler,
    sock: UdtSocket,
}

impl Client {
    pub fn new(addr: SocketAddr, key: &[u8]) -> Client {
        let sock = new_udt_socket();
        Client {
            addr: addr,
            sock: sock,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn connect(&self) -> Result<(), UdtError> {
        self.sock.connect(self.addr)
    }
}

impl Transceiver for Client {
    fn send(&self, buf: &[u8]) -> Result<(), UdtError> {
        unimplemented!();
        // send(&self.sock, &self.sealing_key, buf)
    }

    fn recv(&self, buf: &mut [u8]) -> Result<usize, UdtError> {
        unimplemented!();
        // recv(&self.sock, &self.opening_key, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl Server {
    pub fn get_open_port(range: &PortRange) -> Result<u16, ()> {
        for p in range.start..range.end {
            if let Ok(_) = UdpSocket::bind(&format!("0.0.0.0:{}", p)[..]) {
                return Ok(p);
            }
        }
        Err(())
    }

    pub fn new(ip_addr: IpAddr, port: u16, key: &[u8]) -> Server {
        let sock = new_udt_socket();
        sock.bind(SocketAddr::new(ip_addr, port)).unwrap();
        Server {
            sock: sock,
            ip_addr: ip_addr,
            port: port,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn listen(&self) -> Result<(), UdtError> {
        self.sock.listen(2)
    }

    pub fn accept(&self) -> Result<ServerConnection, UdtError> {
        self.sock.accept().map(|(sock, _)| {
            ServerConnection {
                crypto: &self.crypto,
                sock: sock,
            }
        })
    }
}

impl<'a> ServerConnection<'a> {
    pub fn getpeer(&self) -> Result<SocketAddr, UdtError> {
        self.sock.getpeername()
    }
}

impl<'a> Transceiver for ServerConnection<'a> {
    fn send(&self, buf: &[u8]) -> Result<(), UdtError> {
        unimplemented!();
        // send(&self.sock, self.key, buf)
    }

    fn recv(&self, buf: &mut [u8]) -> Result<usize, UdtError> {
        unimplemented!();
        // recv(&self.sock, self.key, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl<'a> PortRange {
    fn new(start: u16, end: u16) -> Result<PortRange, &'a str> {
        if start > end {
            Err("range end must be greater than or equal to start")
        } else {
            Ok(PortRange {
                start: start,
                end: end,
            })
        }
    }

    pub fn from(s: &str) -> Result<PortRange, &'a str> {
        let sections: Vec<&str> = s.split('-').collect();
        if sections.len() != 2 {
            return Err("Range must be specified in the form of \"<start>-<end>\"");
        }
        let (start, end) = (sections[0].parse::<u16>(), sections[1].parse::<u16>());
        if start.is_err() || end.is_err() {
            return Err("improperly formatted port range");
        }
        PortRange::new(start.unwrap(), end.unwrap())
    }
}

impl fmt::Display for PortRange {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}-{}", self.start, self.end)
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate mio;

use context::SharedContext;
use dummy_adapter::DummyAdapter;
use events::*;
use http_server::HttpServer;
use mio::EventLoop;
use service::{ Service, ServiceAdapter };

pub struct Controller {
    sender: EventSender,
    context: SharedContext
}

impl Controller {
    /// Construct a new `Controller`.
    ///
    /// ```
    /// # use service_manager::Controller;
    /// let controller = Controller::new();
    /// ```
    pub fn new(sender: EventSender, context: SharedContext) -> Controller {
        Controller {
            sender: sender,
            context: context
        }
    }

    pub fn start(&self) {
        println!("Starting controller");

        // Start the http server.
        let http_server = HttpServer::new(self.context.clone());
        http_server.start();

        // Start the dummy adapter.
        let dummy_adapter = DummyAdapter::new(self.sender.clone(), self.context.clone());
        dummy_adapter.start();
    }
}

impl mio::Handler for Controller {
    type Timeout = ();
    type Message = EventData;

    fn notify(&mut self,
              _: &mut EventLoop<Controller>,
              data: EventData) {
        println!("Receiving a notification! {}", data.description());

        let mut context = self.context.lock().unwrap();
        match data {
            EventData::ServiceStart { id } => {
                // The service should be added already, panic if that's not the
                // case.
                match context.get_service(&id) {
                    None => panic!(format!("Missing service with id {}", id)),
                    Some(_) => {}
                }

                println!("ServiceStart {} We now have {} services.", id, context.services_count());
            }
            EventData::ServiceStop { id } => {
                context.remove_service(id.clone());
                println!("ServiceStop {} We now have {} services.", id, context.services_count());
            }
            _ => { }
        }
    }
}
<commit_msg>Fix compilation error by being explicit in what we use<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate mio;

use context::SharedContext;
use dummy_adapter::DummyAdapter;
use events::{ EventData, EventSender };
use http_server::HttpServer;
use mio::EventLoop;
use service::{ Service, ServiceAdapter };

pub struct Controller {
    sender: EventSender,
    context: SharedContext
}

impl Controller {
    /// Construct a new `Controller`.
    ///
    /// ```
    /// # use service_manager::Controller;
    /// let controller = Controller::new();
    /// ```
    pub fn new(sender: EventSender, context: SharedContext) -> Controller {
        Controller {
            sender: sender,
            context: context
        }
    }

    pub fn start(&self) {
        println!("Starting controller");

        // Start the http server.
        let http_server = HttpServer::new(self.context.clone());
        http_server.start();

        // Start the dummy adapter.
        let dummy_adapter = DummyAdapter::new(self.sender.clone(), self.context.clone());
        dummy_adapter.start();
    }
}

impl mio::Handler for Controller {
    type Timeout = ();
    type Message = EventData;

    fn notify(&mut self,
              _: &mut EventLoop<Controller>,
              data: EventData) {
        println!("Receiving a notification! {}", data.description());

        let mut context = self.context.lock().unwrap();
        match data {
            EventData::ServiceStart { id } => {
                // The service should be added already, panic if that's not the
                // case.
                match context.get_service(&id) {
                    None => panic!(format!("Missing service with id {}", id)),
                    Some(_) => {}
                }

                println!("ServiceStart {} We now have {} services.", id, context.services_count());
            }
            EventData::ServiceStop { id } => {
                context.remove_service(id.clone());
                println!("ServiceStop {} We now have {} services.", id, context.services_count());
            }
            _ => { }
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use core::serial::*;
use std::io::Write;
use fst::MapBuilder;
use core::error::*;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use core::directory::Segment;
use core::directory::SegmentComponent;
use core::reader::*;

pub trait Codec {
    //
    // type SearchableSegmentImpl: SearchableSegment;
    //
    // fn open(segment: &Segment) -> Self::SearchableSegmentImpl;

    fn write<'a, I: SerializableSegment<'a>>(index: &'a I, segment: &'a Segment) -> Result<usize>;
}

pub struct SimpleCodec;

impl SimpleCodec {
    fn  write_postings<D: DocCursor, W: Write>(doc_it: D, postings: &mut W) -> Result<usize> {
        let mut written_bytes: usize = 4;
        match postings.write_u32::<LittleEndian>(doc_it.len() as u32) {
            Ok(_) => {},
            Err(_) => {
                let msg = String::from("Failed writing posting list length");
                return Err(Error::WriteError(msg));
            },
        }
        for doc_id in doc_it {
            println!("  Doc {}", doc_id);
            match postings.write_u32::<LittleEndian>(doc_id as u32) {
                Ok(_) => {},
                Err(_) => {
                    let msg = String::from("Failed while writing posting list");
                    return Err(Error::WriteError(msg));
                },
            }
            written_bytes += 4;
        }
        Ok(written_bytes)
    }
}

// TODO impl packed int
// TODO skip lists

impl Codec for SimpleCodec {

    // type SearchableSegmentImpl = SimpleSearchableSegment;
    //
    // fn open(segment: &Segment) -> SimpleSearchableSegment {
    //     SimpleSearchableSegment::new(segment)
    // }

    fn write<'a, I: SerializableSegment<'a>>(index: &'a I, segment: &'a Segment) -> Result<usize> {
        let term_write = try!(segment.open_writable(SegmentComponent::TERMS));
        let mut postings_write = try!(segment.open_writable(SegmentComponent::POSTINGS));
        let term_trie_builder_result = MapBuilder::new(term_write);
        if term_trie_builder_result.is_err() {
            // TODO include cause somehow
            return Err(Error::WriteError(String::from("Failed creating the term builder")));
        }
        let mut term_buffer: Vec<u8> = Vec::new();
        let mut term_trie_builder = term_trie_builder_result.unwrap();
        let mut term_cursor = index.term_cursor();
        let mut offset: usize = 0;
        loop {
            match term_cursor.next() {
                Some((term, doc_it)) => {
                    println!("{:?}", term);
                    term.write_into(&mut term_buffer);
                    match term_trie_builder.insert(&term_buffer, offset as u64) {
                        Ok(_) => {}
                        Err(_) => {
                            return Err(Error::WriteError(String::from("Failed while inserting into the fst")))
                        },
                    }
                    offset += try!(SimpleCodec::write_postings(doc_it, &mut postings_write));
                },
                None => {
                    break;
                }
            }
        }
        term_trie_builder.finish();
        Ok(0)

    }
}
<commit_msg>removed generic codecs<commit_after>use std::io;
use core::serial::*;
use std::io::Write;
use fst::MapBuilder;
use core::error::*;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use core::directory::Segment;
use core::directory::SegmentComponent;
use core::reader::*;

pub struct SimpleCodec;

impl SimpleCodec {
    fn  write_postings<D: DocCursor, W: Write>(doc_it: D, postings: &mut W) -> Result<usize> {
        let mut written_bytes: usize = 4;
        match postings.write_u32::<LittleEndian>(doc_it.len() as u32) {
            Ok(_) => {},
            Err(_) => {
                let msg = String::from("Failed writing posting list length");
                return Err(Error::WriteError(msg));
            },
        }
        for doc_id in doc_it {
            println!("  Doc {}", doc_id);
            match postings.write_u32::<LittleEndian>(doc_id as u32) {
                Ok(_) => {},
                Err(_) => {
                    let msg = String::from("Failed while writing posting list");
                    return Err(Error::WriteError(msg));
                },
            }
            written_bytes += 4;
        }
        Ok(written_bytes)
    }

    // TODO impl packed int
    // TODO skip lists

    pub fn write<'a, I: SerializableSegment<'a>>(index: &'a I, segment: &'a Segment) -> Result<usize> {
        let term_write = try!(segment.open_writable(SegmentComponent::TERMS));
        let mut postings_write = try!(segment.open_writable(SegmentComponent::POSTINGS));
        let term_trie_builder_result = MapBuilder::new(term_write);
        if term_trie_builder_result.is_err() {
            // TODO include cause somehow
            return Err(Error::WriteError(String::from("Failed creating the term builder")));
        }
        let mut term_buffer: Vec<u8> = Vec::new();
        let mut term_trie_builder = term_trie_builder_result.unwrap();
        let mut term_cursor = index.term_cursor();
        let mut offset: usize = 0;
        loop {
            match term_cursor.next() {
                Some((term, doc_it)) => {
                    println!("{:?}", term);
                    term.write_into(&mut term_buffer);
                    match term_trie_builder.insert(&term_buffer, offset as u64) {
                        Ok(_) => {}
                        Err(_) => {
                            return Err(Error::WriteError(String::from("Failed while inserting into the fst")))
                        },
                    }
                    offset += try!(SimpleCodec::write_postings(doc_it, &mut postings_write));
                },
                None => {
                    break;
                }
            }
        }
        term_trie_builder.finish();
        Ok(0)

    }
}
<|endoftext|>


<commit_before>extern crate toml;

use constants::*;
use self::toml::Table;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = WORKING_DIR_NAME;
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let path_to_config = path_to_dir.clone().join(CONFIG_FILE_NAME);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let path_to_ignore = path_to_dir.clone().join(IGNORE_FILE_NAME);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut fp) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match fp.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn walk_dir<P: AsRef<Path>>(path: P) -> Vec<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter(|de| de.is_ok())
            .flat_map(|de| {
                let path = de.unwrap().path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter(|f| f.is_ok())
        .map(|f| f.unwrap())
        .collect::<Vec<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with("."))
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    let table = read_config_file();
    println!("{:?}", table);
}

fn read_config_file() -> Table {
    let config_file = Path::new(WORKING_DIR_NAME).join(CONFIG_FILE_NAME);
    let mut fp      = match File::open(config_file) {
        Ok(fp)   => fp,
        Err(why) => panic!("{:?}", why),
    };
    let mut config = String::new();
    match fp.read_to_string(&mut config) {
        Ok(contents) => contents,
        Err(why)     => panic!("{:?}", why),
    };

    match toml::Parser::new(&config).parse() {
        Some(toml) => toml,
        None       => panic!("Error occurs on parsing \"{}\".", CONFIG_FILE_NAME),
    }
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    match fs::remove_dir_all(WORKING_DIR_NAME) {
        Ok(_)    => println!("  OK: Removed \"{}\" directory.", WORKING_DIR_NAME),
        Err(why) => panic!("{:?}", why),
    }
}
<commit_msg>Create read_ignore_file()<commit_after>extern crate toml;

use constants::*;
use self::toml::Table;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = WORKING_DIR_NAME;
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let path_to_config = path_to_dir.clone().join(CONFIG_FILE_NAME);
    create_setting_file(path_to_config, DEFAULT_CONFIG);

    let path_to_ignore = path_to_dir.clone().join(IGNORE_FILE_NAME);
    let ignore_contents = walk_dir(".").iter()
        .fold(String::new(), |c, f| c + &f + "\n");
    create_setting_file(path_to_ignore, ignore_contents);
}

fn create_setting_file<S: AsRef<str>>(path_to_file: PathBuf, contents: S) {
    let file_name = path_to_file.file_name().and_then(|f| f.to_str()).unwrap();
    if path_to_file.exists() && path_to_file.is_file() {
        println!("  OK: \"{}\" file has already exist.", file_name);
    } else {
        match File::create(&path_to_file) {
            Ok(mut fp) => {
                println!("  OK: Created \"{}\" file.", file_name);
                match fp.write(contents.as_ref().as_bytes()) {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn walk_dir<P: AsRef<Path>>(path: P) -> Vec<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter(|de| de.is_ok())
            .flat_map(|de| {
                let path = de.unwrap().path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter(|f| f.is_ok())
        .map(|f| f.unwrap())
        .collect::<Vec<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with("."))
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    let config = read_config_file();
    let ignore = read_ignore_file();

    println!("{:?}", config);
    println!("{:?}", ignore);
}

fn read_config_file() -> Table {
    let config_file = Path::new(WORKING_DIR_NAME).join(CONFIG_FILE_NAME);
    let mut fp      = match File::open(config_file) {
        Ok(fp)   => fp,
        Err(why) => panic!("{:?}", why),
    };
    let mut config = String::new();
    match fp.read_to_string(&mut config) {
        Ok(_)    => {},
        Err(why) => panic!("{:?}", why),
    };

    match toml::Parser::new(&config).parse() {
        Some(toml) => toml,
        None       => panic!("Error occurs on parsing \"{}\".", CONFIG_FILE_NAME),
    }
}

fn read_ignore_file() -> BTreeSet<String> {
    let ignore_file = Path::new(WORKING_DIR_NAME).join(IGNORE_FILE_NAME);
    let mut fp      = match File::open(ignore_file) {
        Ok(fp)   => fp,
        Err(why) => panic!("{:?}", why),
    };
    let mut contents = String::new();
    match fp.read_to_string(&mut contents) {
        Ok(_)    => {},
        Err(why) => panic!("{:?}", why),
    }
    contents
        .lines()
        .map(|l| l.trim().to_string())
        .collect::<BTreeSet<String>>()
}

pub fn burn() {
    println!("burn");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("Destroy ...");

    match fs::remove_dir_all(WORKING_DIR_NAME) {
        Ok(_)    => println!("  OK: Removed \"{}\" directory.", WORKING_DIR_NAME),
        Err(why) => panic!("{:?}", why),
    }
}
<|endoftext|>


<commit_before>//! CryptoAPI key providers.
use std::io;
use std::ptr;
use winapi::shared::minwindef as winapi;
use winapi::um::winbase;
use winapi::um::wincrypt;

use Inner;
use crypt_key::CryptKey;

/// A CryptoAPI handle to a provider of a key.
pub struct CryptProv(wincrypt::HCRYPTPROV);

impl Drop for CryptProv {
    fn drop(&mut self) {
        unsafe {
            wincrypt::CryptReleaseContext(self.0, 0);
        }
    }
}

inner!(CryptProv, wincrypt::HCRYPTPROV);

impl CryptProv {
    /// Imports a key into this provider.
    pub fn import<'a>(&'a mut self) -> ImportOptions<'a> {
        ImportOptions {
            prov: self,
            flags: 0,
        }
    }
}

/// A builder for `CryptProv`s.
pub struct AcquireOptions {
    container: Option<Vec<u16>>,
    provider: Option<Vec<u16>>,
    flags: winapi::DWORD,
}

impl AcquireOptions {
    /// Returns a new builder with default settings.
    pub fn new() -> AcquireOptions {
        AcquireOptions {
            container: None,
            provider: None,
            flags: 0,
        }
    }

    /// Sets the name for this key container.
    ///
    /// This should not be set if `verify_context` is set.
    pub fn container(&mut self, container: &str) -> &mut AcquireOptions {
        self.container = Some(container.encode_utf16().chain(Some(0)).collect());
        self
    }

    /// Sets the name of the CSP to be used.
    pub fn provider(&mut self, provider: &str) -> &mut AcquireOptions {
        self.provider = Some(provider.encode_utf16().chain(Some(0)).collect());
        self
    }

    /// If set, private keys will not be accessible or persisted.
    pub fn verify_context(&mut self, verify_context: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_VERIFYCONTEXT, verify_context)
    }

    /// If set, the container will be created.
    pub fn new_keyset(&mut self, new_keyset: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_NEWKEYSET, new_keyset)
    }

    /// If set, the container will be stored as a machine rather than user keys.
    pub fn machine_keyset(&mut self, machine_keyset: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_MACHINE_KEYSET, machine_keyset)
    }

    /// If set, an error will be returned if user intervention is required
    /// rather than displaying a dialog.
    pub fn silent(&mut self, silent: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_SILENT, silent)
    }

    fn flag(&mut self, flag: winapi::DWORD, on: bool) -> &mut AcquireOptions {
        if on {
            self.flags |= flag;
        } else {
            self.flags &= !flag;
        }

        self
    }

    /// Acquires a container.
    pub fn acquire(&self, type_: ProviderType) -> io::Result<CryptProv> {
        unsafe {
            let container = self.container.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null());
            let provider = self.provider.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null());

            let mut prov = 0;
            let res = wincrypt::CryptAcquireContextW(&mut prov,
                                                     container as *mut _,
                                                     provider as *mut _,
                                                     type_.0,
                                                     self.flags);
            if res == winapi::TRUE {
                Ok(CryptProv(prov))
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

/// An identifier of the type of cryptography provider to be used with a
/// container.
#[derive(Copy, Clone)]
pub struct ProviderType(winapi::DWORD);

#[allow(missing_docs)]
impl ProviderType {
    pub fn rsa_full() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_FULL)
    }

    pub fn rsa_aes() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_AES)
    }

    pub fn rsa_sig() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_SIG)
    }

    pub fn rsa_schannel() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_SCHANNEL)
    }

    pub fn dss() -> ProviderType {
        ProviderType(wincrypt::PROV_DSS)
    }

    pub fn dss_dh() -> ProviderType {
        ProviderType(wincrypt::PROV_DSS_DH)
    }

    pub fn dh_schannel() -> ProviderType {
        ProviderType(wincrypt::PROV_DH_SCHANNEL)
    }

    pub fn fortezza() -> ProviderType {
        ProviderType(wincrypt::PROV_FORTEZZA)
    }

    pub fn ms_exchange() -> ProviderType {
        ProviderType(wincrypt::PROV_MS_EXCHANGE)
    }

    pub fn ssl() -> ProviderType {
        ProviderType(wincrypt::PROV_SSL)
    }

    pub fn as_raw(&self) -> winapi::DWORD {
        self.0
    }
}

/// A builder for key imports.
pub struct ImportOptions<'a> {
    prov: &'a mut CryptProv,
    flags: winapi::DWORD,
}

impl<'a> ImportOptions<'a> {
    /// Imports a DER-encoded private key.
    pub fn import(&mut self, der: &[u8]) -> io::Result<CryptKey> {
        unsafe {
            assert!(der.len() <= winapi::DWORD::max_value() as usize);
            let mut buf = ptr::null_mut();
            let mut len = 0;
            let res = wincrypt::CryptDecodeObjectEx(wincrypt::X509_ASN_ENCODING |
                                                    wincrypt::PKCS_7_ASN_ENCODING,
                                                    wincrypt::PKCS_RSA_PRIVATE_KEY,
                                                    der.as_ptr(),
                                                    der.len() as winapi::DWORD,
                                                    wincrypt::CRYPT_DECODE_ALLOC_FLAG,
                                                    ptr::null_mut(),
                                                    &mut buf as *mut _ as winapi::LPVOID,
                                                    &mut len);
            if res == winapi::FALSE {
                return Err(io::Error::last_os_error());
            }

            let mut key = 0;
            let res = wincrypt::CryptImportKey(self.prov.0, buf, len, 0, self.flags, &mut key);
            winbase::LocalFree(buf as *mut _);

            if res == winapi::TRUE {
                Ok(CryptKey::from_inner(key))
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

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

    #[test]
    fn rsa_key() {
        let key = include_bytes!("../test/key.key");

        let mut context = AcquireOptions::new()
            .verify_context(true)
            .acquire(ProviderType::rsa_full())
            .unwrap();
        context.import()
            .import(key)
            .unwrap();
    }
}
<commit_msg>Add PKCS8 Key Import Support (#56)<commit_after>//! CryptoAPI key providers.
use std::io;
use std::ptr;
use std::slice;
use winapi::shared::minwindef as winapi;
use winapi::um::winbase;
use winapi::um::wincrypt;

use Inner;
use crypt_key::CryptKey;

/// A CryptoAPI handle to a provider of a key.
pub struct CryptProv(wincrypt::HCRYPTPROV);

impl Drop for CryptProv {
    fn drop(&mut self) {
        unsafe {
            wincrypt::CryptReleaseContext(self.0, 0);
        }
    }
}

inner!(CryptProv, wincrypt::HCRYPTPROV);

impl CryptProv {
    /// Imports a key into this provider.
    pub fn import<'a>(&'a mut self) -> ImportOptions<'a> {
        ImportOptions {
            prov: self,
            flags: 0,
        }
    }
}

/// A builder for `CryptProv`s.
pub struct AcquireOptions {
    container: Option<Vec<u16>>,
    provider: Option<Vec<u16>>,
    flags: winapi::DWORD,
}

impl AcquireOptions {
    /// Returns a new builder with default settings.
    pub fn new() -> AcquireOptions {
        AcquireOptions {
            container: None,
            provider: None,
            flags: 0,
        }
    }

    /// Sets the name for this key container.
    ///
    /// This should not be set if `verify_context` is set.
    pub fn container(&mut self, container: &str) -> &mut AcquireOptions {
        self.container = Some(container.encode_utf16().chain(Some(0)).collect());
        self
    }

    /// Sets the name of the CSP to be used.
    pub fn provider(&mut self, provider: &str) -> &mut AcquireOptions {
        self.provider = Some(provider.encode_utf16().chain(Some(0)).collect());
        self
    }

    /// If set, private keys will not be accessible or persisted.
    pub fn verify_context(&mut self, verify_context: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_VERIFYCONTEXT, verify_context)
    }

    /// If set, the container will be created.
    pub fn new_keyset(&mut self, new_keyset: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_NEWKEYSET, new_keyset)
    }

    /// If set, the container will be stored as a machine rather than user keys.
    pub fn machine_keyset(&mut self, machine_keyset: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_MACHINE_KEYSET, machine_keyset)
    }

    /// If set, an error will be returned if user intervention is required
    /// rather than displaying a dialog.
    pub fn silent(&mut self, silent: bool) -> &mut AcquireOptions {
        self.flag(wincrypt::CRYPT_SILENT, silent)
    }

    fn flag(&mut self, flag: winapi::DWORD, on: bool) -> &mut AcquireOptions {
        if on {
            self.flags |= flag;
        } else {
            self.flags &= !flag;
        }

        self
    }

    /// Acquires a container.
    pub fn acquire(&self, type_: ProviderType) -> io::Result<CryptProv> {
        unsafe {
            let container = self.container.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null());
            let provider = self.provider.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null());

            let mut prov = 0;
            let res = wincrypt::CryptAcquireContextW(&mut prov,
                                                     container as *mut _,
                                                     provider as *mut _,
                                                     type_.0,
                                                     self.flags);
            if res == winapi::TRUE {
                Ok(CryptProv(prov))
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

/// An identifier of the type of cryptography provider to be used with a
/// container.
#[derive(Copy, Clone)]
pub struct ProviderType(winapi::DWORD);

#[allow(missing_docs)]
impl ProviderType {
    pub fn rsa_full() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_FULL)
    }

    pub fn rsa_aes() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_AES)
    }

    pub fn rsa_sig() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_SIG)
    }

    pub fn rsa_schannel() -> ProviderType {
        ProviderType(wincrypt::PROV_RSA_SCHANNEL)
    }

    pub fn dss() -> ProviderType {
        ProviderType(wincrypt::PROV_DSS)
    }

    pub fn dss_dh() -> ProviderType {
        ProviderType(wincrypt::PROV_DSS_DH)
    }

    pub fn dh_schannel() -> ProviderType {
        ProviderType(wincrypt::PROV_DH_SCHANNEL)
    }

    pub fn fortezza() -> ProviderType {
        ProviderType(wincrypt::PROV_FORTEZZA)
    }

    pub fn ms_exchange() -> ProviderType {
        ProviderType(wincrypt::PROV_MS_EXCHANGE)
    }

    pub fn ssl() -> ProviderType {
        ProviderType(wincrypt::PROV_SSL)
    }

    pub fn as_raw(&self) -> winapi::DWORD {
        self.0
    }
}

/// A builder for key imports.
pub struct ImportOptions<'a> {
    prov: &'a mut CryptProv,
    flags: winapi::DWORD,
}

impl<'a> ImportOptions<'a> {
    /// Imports a DER-encoded PKCS1 private key.
    pub fn import(&mut self, der: &[u8]) -> io::Result<CryptKey> {
        unsafe {
            assert!(der.len() <= winapi::DWORD::max_value() as usize);
            let mut buf = ptr::null_mut();
            let mut len = 0;
            let res = wincrypt::CryptDecodeObjectEx(wincrypt::X509_ASN_ENCODING |
                                                    wincrypt::PKCS_7_ASN_ENCODING,
                                                    wincrypt::PKCS_RSA_PRIVATE_KEY,
                                                    der.as_ptr(),
                                                    der.len() as winapi::DWORD,
                                                    wincrypt::CRYPT_DECODE_ALLOC_FLAG,
                                                    ptr::null_mut(),
                                                    &mut buf as *mut _ as winapi::LPVOID,
                                                    &mut len);
            if res == winapi::FALSE {
                return Err(io::Error::last_os_error());
            }

            let mut key = 0;
            let res = wincrypt::CryptImportKey(self.prov.0, buf, len, 0, self.flags, &mut key);
            winbase::LocalFree(buf as *mut _);

            if res == winapi::TRUE {
                Ok(CryptKey::from_inner(key))
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }

    /// Imports a DER-encoded PKCS8 private key.
    pub fn import_pkcs8(&mut self, der: &[u8]) -> io::Result<CryptKey> {
        unsafe {
            assert!(der.len() <= winapi::DWORD::max_value() as usize);

            // Decode the der format into a CRYPT_PRIVATE_KEY_INFO struct
            let mut buf = ptr::null_mut();
            let mut len = 0;
            let res = wincrypt::CryptDecodeObjectEx(wincrypt::X509_ASN_ENCODING |
                                                    wincrypt::PKCS_7_ASN_ENCODING,
                                                    wincrypt::PKCS_PRIVATE_KEY_INFO,
                                                    der.as_ptr(),
                                                    der.len() as winapi::DWORD,
                                                    wincrypt::CRYPT_DECODE_ALLOC_FLAG,
                                                    ptr::null_mut(),
                                                    &mut buf as *mut _ as winapi::LPVOID,
                                                    &mut len);
            if res == winapi::FALSE {
                return Err(io::Error::last_os_error());
            }
            let pkey: wincrypt::CRYPT_PRIVATE_KEY_INFO = *buf;
            let pkey = pkey.PrivateKey;

            let res = self.import(&slice::from_raw_parts(pkey.pbData, pkey.cbData as usize));
            winbase::LocalFree(buf as *mut _);
            res
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use winapi::shared::ntdef;

    #[test]
    fn rsa_key() {
        let key = include_bytes!("../test/key.key");

        let mut context = AcquireOptions::new()
            .verify_context(true)
            .acquire(ProviderType::rsa_full())
            .unwrap();
        context.import()
            .import(key)
            .unwrap();
    }

    #[test]
    fn pkcs8_key() {
        let key = include_str!("../test/key.pem");
        let der = unsafe {
            let mut len = 0;
            assert!(wincrypt::CryptStringToBinaryA(key.as_ptr() as ntdef::LPCSTR,
                                                   key.len() as winapi::DWORD,
                                                   wincrypt::CRYPT_STRING_BASE64HEADER,
                                                   ptr::null_mut(),
                                                   &mut len,
                                                   ptr::null_mut(),
                                                   ptr::null_mut()) == winapi::TRUE);
            let mut buf = vec![0; len as usize];
            assert!(wincrypt::CryptStringToBinaryA(key.as_ptr() as ntdef::LPCSTR,
                                                   key.len() as winapi::DWORD,
                                                   wincrypt::CRYPT_STRING_BASE64HEADER,
                                                   buf.as_mut_ptr(),
                                                   &mut len,
                                                   ptr::null_mut(),
                                                   ptr::null_mut()) == winapi::TRUE);
            buf
        };
        let mut context = AcquireOptions::new()
            .verify_context(true)
            .acquire(ProviderType::rsa_full())
            .unwrap();
        context.import()
            .import_pkcs8(&der)
            .unwrap();
    }
}
<|endoftext|>