<commit_before>// Copyright 2017 CoreOS, Inc.
//
// 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.

//! aws ec2 metadata fetcher
//!
use retry;

use metadata::Metadata;

use errors::*;

fn url_for_key(key: &str) -> String {
    format!("http://169.254.169.254/2009-04-04/{}", key)
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
struct InstanceIdDoc {
    region: String,
}

pub fn fetch_metadata() -> Result<Metadata> {
    let client = retry::Client::new()
        .chain_err(|| format!("ec2: failed to create http client"))?
        .return_on_404(true);

    let instance_id: Option<String> = client.get(retry::Raw, url_for_key("meta-data/instance-id")).send()?;
    let public: Option<String> = client.get(retry::Raw, url_for_key("meta-data/public-ipv4")).send()?;
    let local: Option<String> = client.get(retry::Raw, url_for_key("meta-data/local-ipv4")).send()?;
    let hostname: Option<String> = client.get(retry::Raw, url_for_key("meta-data/hostname")).send()?;
    let availability_zone: Option<String> = client.get(retry::Raw, url_for_key("meta-data/placement/availability-zone")).send()?;
    let region: Option<String> = client.get(retry::Json, url_for_key("dynamic/instance-identity/document")).send()?
        .map(|instance_id_doc: InstanceIdDoc| instance_id_doc.region);

    let mut ssh_keys: Vec<String> = fetch_ssh_keys(client)?;

    Ok(Metadata::builder()
        .add_attribute_if_exists("EC2_REGION".to_owned(), region)
        .add_attribute_if_exists("EC2_INSTANCE_ID".to_owned(), instance_id)
        .add_attribute_if_exists("EC2_IPV4_PUBLIC".to_owned(), public)
        .add_attribute_if_exists("EC2_IPV4_LOCAL".to_owned(), local)
        .add_attribute_if_exists("EC2_HOSTNAME".to_owned(), hostname.clone())
        .add_attribute_if_exists("EC2_AVAILABILITY_ZONE".to_owned(), availability_zone)
        .set_hostname_if_exists(hostname)
        .add_ssh_keys(ssh_keys)
        .build())
}

fn fetch_ssh_keys(client: retry::Client) -> Result<Vec<String>> {
    let keydata: Option<String> = client.get(retry::Raw, url_for_key("meta-data/public-keys")).send()?;
    match keydata {
        Some(s) => {
            let mut res = Ok(Vec::new());
            for keyname in s.split_whitespace() {
                let tokens: Vec<&str> = keyname.split('=').collect();
                if tokens.len() != 2 {
                    res = Err("malformed public key".into());
                    break;
                }
                let ssh_key: String = client.get(retry::Raw, url_for_key(&format!("meta-data/public-keys/{}/openssh-key", tokens[0]))).send()?
                    .ok_or("missing ssh key")?;
                match res.as_mut() {
                    Ok(keys) => (*keys).push(ssh_key),
                    Err(_) => (),
                }
            }
            res
        }
        None => {
            Ok(Vec::new())
        }
    }
}
<commit_msg>providers/ec2: fix mutability warning<commit_after>// Copyright 2017 CoreOS, Inc.
//
// 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.

//! aws ec2 metadata fetcher
//!
use retry;

use metadata::Metadata;

use errors::*;

fn url_for_key(key: &str) -> String {
    format!("http://169.254.169.254/2009-04-04/{}", key)
}

#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
struct InstanceIdDoc {
    region: String,
}

pub fn fetch_metadata() -> Result<Metadata> {
    let client = retry::Client::new()
        .chain_err(|| format!("ec2: failed to create http client"))?
        .return_on_404(true);

    let instance_id: Option<String> = client.get(retry::Raw, url_for_key("meta-data/instance-id")).send()?;
    let public: Option<String> = client.get(retry::Raw, url_for_key("meta-data/public-ipv4")).send()?;
    let local: Option<String> = client.get(retry::Raw, url_for_key("meta-data/local-ipv4")).send()?;
    let hostname: Option<String> = client.get(retry::Raw, url_for_key("meta-data/hostname")).send()?;
    let availability_zone: Option<String> = client.get(retry::Raw, url_for_key("meta-data/placement/availability-zone")).send()?;
    let region: Option<String> = client.get(retry::Json, url_for_key("dynamic/instance-identity/document")).send()?
        .map(|instance_id_doc: InstanceIdDoc| instance_id_doc.region);

    let ssh_keys: Vec<String> = fetch_ssh_keys(client)?;

    Ok(Metadata::builder()
        .add_attribute_if_exists("EC2_REGION".to_owned(), region)
        .add_attribute_if_exists("EC2_INSTANCE_ID".to_owned(), instance_id)
        .add_attribute_if_exists("EC2_IPV4_PUBLIC".to_owned(), public)
        .add_attribute_if_exists("EC2_IPV4_LOCAL".to_owned(), local)
        .add_attribute_if_exists("EC2_HOSTNAME".to_owned(), hostname.clone())
        .add_attribute_if_exists("EC2_AVAILABILITY_ZONE".to_owned(), availability_zone)
        .set_hostname_if_exists(hostname)
        .add_ssh_keys(ssh_keys)
        .build())
}

fn fetch_ssh_keys(client: retry::Client) -> Result<Vec<String>> {
    let keydata: Option<String> = client.get(retry::Raw, url_for_key("meta-data/public-keys")).send()?;
    match keydata {
        Some(s) => {
            let mut res = Ok(Vec::new());
            for keyname in s.split_whitespace() {
                let tokens: Vec<&str> = keyname.split('=').collect();
                if tokens.len() != 2 {
                    res = Err("malformed public key".into());
                    break;
                }
                let ssh_key: String = client.get(retry::Raw, url_for_key(&format!("meta-data/public-keys/{}/openssh-key", tokens[0]))).send()?
                    .ok_or("missing ssh key")?;
                match res.as_mut() {
                    Ok(keys) => (*keys).push(ssh_key),
                    Err(_) => (),
                }
            }
            res
        }
        None => {
            Ok(Vec::new())
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::{TcpStream, ToSocketAddrs};
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, Sender};
use std::thread::{self, JoinHandle};
use util::codec::rpc;
use util::make_std_tcp_conn;
use protobuf::{self, MessageStatic};
use super::Result;

pub trait TRpcClient: Sync + Send {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic;
    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()>;
}

#[derive(Debug)]
pub struct RpcClient {
    stream: Mutex<TcpStream>,
}

const SOCKET_READ_TIMEOUT: u64 = 3;
const SOCKET_WRITE_TIMEOUT: u64 = 3;

impl RpcClient {
    pub fn new(addr: A) -> Result<RpcClient> {
        let stream = try!(make_std_tcp_conn(addr));
        try!(stream.set_read_timeout(Some(Duration::from_secs(SOCKET_READ_TIMEOUT))));
        try!(stream.set_write_timeout(Some(Duration::from_secs(SOCKET_WRITE_TIMEOUT))));
        Ok(RpcClient { stream: Mutex::new(stream) })
    }
}

impl TRpcClient for RpcClient {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        // TODO: reconnect if error
        let mut stream = self.stream.lock().unwrap();
        try!(rpc::encode_msg(&mut *stream, msg_id, message));
        let mut resp = P::new();
        match try!(rpc::decode_msg(&mut *stream, &mut resp)) {
            id if id == msg_id => Ok(resp),
            _ => Err(box_err!("pd response msg_id not match")),
        }
    }

    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()> {
        // TODO: reconnect if error
        let mut stream = self.stream.lock().unwrap();
        try!(rpc::encode_msg(&mut *stream, msg_id, message));
        match try!(rpc::decode_data(&mut *stream)) {
            (id, _) if id == msg_id => Ok(()),
            (id, _) => Err(box_err!("pd response msg_id not match, want {}, got {}", msg_id, id)),
        }
    }
}

#[derive(Debug)]
enum Msg {
    Rpc(u64, Box<protobuf::Message + Send>),
    Quit,
}

pub struct Client<C: TRpcClient + 'static> {
    msg_id: AtomicUsize,
    rpc_client: Arc<C>,
    tx: Mutex<Sender<Msg>>,
    handle: Option<JoinHandle<()>>,
}

impl<C: TRpcClient + 'static> Client<C> {
    pub fn new(rpc_client: C) -> Result<Client<C>> {
        let shared = Arc::new(rpc_client);
        let (tx, rx) = mpsc::channel();
        let handle = {
            let rpc_client = shared.clone();
            try!(thread::Builder::new()
                     .name("pd-client background worker".to_owned())
                     .spawn(move || {
                         info!("pd-client background worker starting");
                         while let Msg::Rpc(msg_id, msg) = rx.recv().unwrap() {
                             if let Err(e) = rpc_client.post(msg_id, msg.as_ref()) {
                                 error!("pd post error: {}", e);
                             } else {
                                 debug!("pd post done: {}", msg_id);
                             }
                         }
                         info!("pd-client background worker closing");
                     }))
        };
        Ok(Client {
            msg_id: AtomicUsize::new(0),
            rpc_client: shared.clone(),
            tx: Mutex::new(tx),
            handle: Some(handle),
        })
    }

    fn close(&mut self) {
        if let Err(e) = self.clone_tx().send(Msg::Quit) {
            error!("failed to send quit message to pd-client background worker: {}",
                   e);
        }
        let handle = self.handle.take().unwrap();
        if handle.join().is_err() {
            error!("failed to wait pd-client background worker quit");
        }
        info!("pd-client closed.");
    }

    pub fn send<M, P>(&self, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let id = self.alloc_msg_id();
        self.rpc_client.send(id, message)
    }

    pub fn post<M: protobuf::Message + Send>(&self, message: M) -> Result<()> {
        let id = self.alloc_msg_id();
        if let Err(e) = self.clone_tx().send(Msg::Rpc(id, box message)) {
            return Err(box_err!(format!("SendError: {:?}", e)));
        }
        Ok(())
    }

    fn alloc_msg_id(&self) -> u64 {
        self.msg_id.fetch_add(1, Ordering::Relaxed) as u64
    }

    fn clone_tx(&self) -> Sender<Msg> {
        let tx = self.tx.lock().unwrap();
        tx.clone()
    }
}

impl<C: TRpcClient + 'static> Drop for Client<C> {
    fn drop(&mut self) {
        self.close()
    }
}

#[cfg(test)]
mod tests {
    use super::super::{Result, PdClient};
    use super::*;
    use protobuf;
    use bytes::ByteBuf;
    use util::codec::rpc;
    use kvproto::{metapb, pdpb};

    struct MockRpcClient;

    impl MockRpcClient {
        fn reply(&self, req: &pdpb::Request) -> pdpb::Response {
            assert!(req.has_header());
            let header = req.get_header();
            let (uuid, cluster_id) = (header.get_uuid(), header.get_cluster_id());

            let mut resp = pdpb::Response::new();
            let mut header = pdpb::ResponseHeader::new();
            header.set_uuid(uuid.to_vec());
            header.set_cluster_id(cluster_id);

            match req.get_cmd_type() {
                pdpb::CommandType::AllocId => {
                    let mut alloc = pdpb::AllocIdResponse::new();
                    alloc.set_id(42);
                    resp.set_alloc_id(alloc);
                }
                pdpb::CommandType::PutMeta => {
                    let meta = req.get_put_meta();
                    if meta.get_meta_type() == pdpb::MetaType::StoreType {
                        let store = meta.get_store();
                        assert_eq!(store.get_id(), 233);
                        assert_eq!(store.get_address(), "localhost");
                    }
                }
                _ => {
                    let mut err = pdpb::Error::new();
                    err.set_message(String::from("I've got a bad feeling about this"));
                    header.set_error(err);
                }
            }

            resp.set_header(header);
            resp.set_cmd_type(req.get_cmd_type());
            resp
        }
    }

    impl TRpcClient for MockRpcClient {
        fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

            where M: protobuf::Message,
                  P: protobuf::Message + Default
        {
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, message).unwrap();
            let mut req = pdpb::Request::new();
            rpc::decode_msg(&mut buf.flip(), &mut req).unwrap();

            let resp = self.reply(&req);
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, &resp).unwrap();
            let mut msg = P::default();
            rpc::decode_msg(&mut buf.flip(), &mut msg).unwrap();
            Ok(msg)
        }

        fn post<M: protobuf::Message + ?Sized>(&self, _: u64, _: &M) -> Result<()> {
            Ok(())
        }
    }

    #[test]
    fn test_pd_client() {
        let mut client = Client::new(MockRpcClient).unwrap();
        assert_eq!(client.alloc_id().unwrap(), 42u64);
        assert!(client.is_cluster_bootstrapped(1).is_err());

        let mut store = metapb::Store::new();
        store.set_id(233);
        store.set_address("localhost".to_owned());
        assert!(client.put_store(1, store).is_ok());
    }
}
<commit_msg>pd: extract a function for post msg.<commit_after>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::{TcpStream, ToSocketAddrs};
use std::time::Duration;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{self, Sender};
use std::thread::{self, JoinHandle};
use util::codec::rpc;
use util::make_std_tcp_conn;
use protobuf::{self, MessageStatic};
use super::Result;

pub trait TRpcClient: Sync + Send {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic;
    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()>;
}

#[derive(Debug)]
pub struct RpcClient {
    stream: Mutex<TcpStream>,
}

const SOCKET_READ_TIMEOUT: u64 = 3;
const SOCKET_WRITE_TIMEOUT: u64 = 3;

impl RpcClient {
    pub fn new(addr: A) -> Result<RpcClient> {
        let stream = try!(make_std_tcp_conn(addr));
        try!(stream.set_read_timeout(Some(Duration::from_secs(SOCKET_READ_TIMEOUT))));
        try!(stream.set_write_timeout(Some(Duration::from_secs(SOCKET_WRITE_TIMEOUT))));
        Ok(RpcClient { stream: Mutex::new(stream) })
    }

    fn post_msg<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<Vec<u8>> {
        // TODO: reconnect if error
        let mut stream = self.stream.lock().unwrap();
        try!(rpc::encode_msg(&mut *stream, msg_id, message));
        let (id, data) = try!(rpc::decode_data(&mut *stream));
        if id != msg_id {
            return Err(box_err!("pd response msg_id not match, want {}, got {}", msg_id, id));
        }

        Ok(data)
    }
}

impl TRpcClient for RpcClient {
    fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let mut resp = P::new();
        let data = try!(self.post_msg(msg_id, message));
        try!(rpc::decode_body(&data, &mut resp));
        Ok(resp)
    }

    fn post<M: protobuf::Message + ?Sized>(&self, msg_id: u64, message: &M) -> Result<()> {
        let _ = try!(self.post_msg(msg_id, message));
        Ok(())
    }
}

#[derive(Debug)]
enum Msg {
    Rpc(u64, Box<protobuf::Message + Send>),
    Quit,
}

pub struct Client<C: TRpcClient + 'static> {
    msg_id: AtomicUsize,
    rpc_client: Arc<C>,
    tx: Mutex<Sender<Msg>>,
    handle: Option<JoinHandle<()>>,
}

impl<C: TRpcClient + 'static> Client<C> {
    pub fn new(rpc_client: C) -> Result<Client<C>> {
        let shared = Arc::new(rpc_client);
        let (tx, rx) = mpsc::channel();
        let handle = {
            let rpc_client = shared.clone();
            try!(thread::Builder::new()
                     .name("pd-client background worker".to_owned())
                     .spawn(move || {
                         info!("pd-client background worker starting");
                         while let Msg::Rpc(msg_id, msg) = rx.recv().unwrap() {
                             if let Err(e) = rpc_client.post(msg_id, msg.as_ref()) {
                                 error!("pd post error: {}", e);
                             } else {
                                 debug!("pd post done: {}", msg_id);
                             }
                         }
                         info!("pd-client background worker closing");
                     }))
        };
        Ok(Client {
            msg_id: AtomicUsize::new(0),
            rpc_client: shared.clone(),
            tx: Mutex::new(tx),
            handle: Some(handle),
        })
    }

    fn close(&mut self) {
        if let Err(e) = self.clone_tx().send(Msg::Quit) {
            error!("failed to send quit message to pd-client background worker: {}",
                   e);
        }
        let handle = self.handle.take().unwrap();
        if handle.join().is_err() {
            error!("failed to wait pd-client background worker quit");
        }
        info!("pd-client closed.");
    }

    pub fn send<M, P>(&self, message: &M) -> Result

        where M: protobuf::Message,
              P: protobuf::Message + MessageStatic
    {
        let id = self.alloc_msg_id();
        self.rpc_client.send(id, message)
    }

    pub fn post<M: protobuf::Message + Send>(&self, message: M) -> Result<()> {
        let id = self.alloc_msg_id();
        if let Err(e) = self.clone_tx().send(Msg::Rpc(id, box message)) {
            return Err(box_err!(format!("SendError: {:?}", e)));
        }
        Ok(())
    }

    fn alloc_msg_id(&self) -> u64 {
        self.msg_id.fetch_add(1, Ordering::Relaxed) as u64
    }

    fn clone_tx(&self) -> Sender<Msg> {
        let tx = self.tx.lock().unwrap();
        tx.clone()
    }
}

impl<C: TRpcClient + 'static> Drop for Client<C> {
    fn drop(&mut self) {
        self.close()
    }
}

#[cfg(test)]
mod tests {
    use super::super::{Result, PdClient};
    use super::*;
    use protobuf;
    use bytes::ByteBuf;
    use util::codec::rpc;
    use kvproto::{metapb, pdpb};

    struct MockRpcClient;

    impl MockRpcClient {
        fn reply(&self, req: &pdpb::Request) -> pdpb::Response {
            assert!(req.has_header());
            let header = req.get_header();
            let (uuid, cluster_id) = (header.get_uuid(), header.get_cluster_id());

            let mut resp = pdpb::Response::new();
            let mut header = pdpb::ResponseHeader::new();
            header.set_uuid(uuid.to_vec());
            header.set_cluster_id(cluster_id);

            match req.get_cmd_type() {
                pdpb::CommandType::AllocId => {
                    let mut alloc = pdpb::AllocIdResponse::new();
                    alloc.set_id(42);
                    resp.set_alloc_id(alloc);
                }
                pdpb::CommandType::PutMeta => {
                    let meta = req.get_put_meta();
                    if meta.get_meta_type() == pdpb::MetaType::StoreType {
                        let store = meta.get_store();
                        assert_eq!(store.get_id(), 233);
                        assert_eq!(store.get_address(), "localhost");
                    }
                }
                _ => {
                    let mut err = pdpb::Error::new();
                    err.set_message(String::from("I've got a bad feeling about this"));
                    header.set_error(err);
                }
            }

            resp.set_header(header);
            resp.set_cmd_type(req.get_cmd_type());
            resp
        }
    }

    impl TRpcClient for MockRpcClient {
        fn send<M, P>(&self, msg_id: u64, message: &M) -> Result

            where M: protobuf::Message,
                  P: protobuf::Message + Default
        {
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, message).unwrap();
            let mut req = pdpb::Request::new();
            rpc::decode_msg(&mut buf.flip(), &mut req).unwrap();

            let resp = self.reply(&req);
            let mut buf = ByteBuf::mut_with_capacity(128);
            rpc::encode_msg(&mut buf, msg_id, &resp).unwrap();
            let mut msg = P::default();
            rpc::decode_msg(&mut buf.flip(), &mut msg).unwrap();
            Ok(msg)
        }

        fn post<M: protobuf::Message + ?Sized>(&self, _: u64, _: &M) -> Result<()> {
            Ok(())
        }
    }

    #[test]
    fn test_pd_client() {
        let mut client = Client::new(MockRpcClient).unwrap();
        assert_eq!(client.alloc_id().unwrap(), 42u64);
        assert!(client.is_cluster_bootstrapped(1).is_err());

        let mut store = metapb::Store::new();
        store.set_id(233);
        store.set_address("localhost".to_owned());
        assert!(client.put_store(1, store).is_ok());
    }
}
<|endoftext|>


<commit_before>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, RequestBuilder};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// https://is.gd provider
    IsGd,
    /// https://v.gd provider
    VGd,
    /// https://rlu.ru provider
    /// * Attention! If you send a lot of requests from one IP, it can be blocked. If you plan to add more then 100 URLs in one hour, please let the technical support know. Otherwise your IP can be blocked unexpectedly. Prior added URLs can be deleted.
    Rlu,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::IsGd => "is.gd",
            Provider::VGd => "v.gd",
            Provider::Rlu => "rlu.ru",
        }
    }
}

/// Returns a vector of all `Provider` variants.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::BnGy,
        Provider::IsGd,
        Provider::VGd,
        Provider::Rlu,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        return Some(string.to_owned())
    }
    None
}

fn bngy_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::VGd => vgd_parse(res),
        Provider::Rlu => rlu_parse(res),
    }
}

/// Prepares the Hyper client for a connection to a provider, providing the long
/// URL to be shortened.
pub fn prepare<'a>(url: &str, client: &'a Client, provider: Provider) -> RequestBuilder<'a> {
    match provider {
        Provider::BnGy => bngy_prepare(url, client),
        Provider::IsGd => isgd_prepare(url, client),
        Provider::VGd => vgd_prepare(url, client),
        Provider::Rlu => rlu_prepare(url, client),
    }
}
<commit_msg>trying to make a lazy post request<commit_after>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, RequestBuilder, Body};

use std::str;

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// https://is.gd provider
    IsGd,
    /// https://v.gd provider
    VGd,
    /// http://rlu.ru provider
    /// * Attention! If you send a lot of requests from one IP, it can be blocked. If you plan to add more then 100 URLs in one hour, please let the technical support know. Otherwise your IP can be blocked unexpectedly. Prior added URLs can be deleted.
    Rlu,
    /// http://bit.do provider
    BitDo,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::IsGd => "is.gd",
            Provider::VGd => "v.gd",
            Provider::Rlu => "rlu.ru",
            Provider::BitDo => "bit.do",
        }
    }
}

/// Returns a vector of all `Provider` variants.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::BnGy,
        Provider::IsGd,
        Provider::VGd,
        Provider::Rlu,
        Provider::BitDo,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        return Some(string.to_owned())
    }
    None
}

fn bngy_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
}

fn bitdo_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn bitdo_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    let mut h_url = hyper::Url::parse("http://bit.do/mod_perl/url-shortener.pl").unwrap();
    h_url.query_pairs_mut()
        .append_pair("action", "shorten")
        .append_pair("url", url)
        .append_pair("url2", "site2")
        .append_pair("url_hash", "")
        .append_pair("url_stats_is_private", &0.to_string());
    let strstr = &format!("action=shorten&url={}&url2=site2&url_hash=&url_stats_is_private=0", url).into_bytes();
    let string = str::from_utf8(strstr);
    client.post(h_url.as_str()).body(string.unwrap())

}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::VGd => vgd_parse(res),
        Provider::Rlu => rlu_parse(res),
        Provider::BitDo => bitdo_parse(res),
    }
}

/// Prepares the Hyper client for a connection to a provider, providing the long
/// URL to be shortened.
pub fn prepare<'a>(url: &str, client: &'a Client, provider: Provider) -> RequestBuilder<'a> {
    match provider {
        Provider::BnGy => bngy_prepare(url, client),
        Provider::IsGd => isgd_prepare(url, client),
        Provider::VGd => vgd_prepare(url, client),
        Provider::Rlu => rlu_prepare(url, client),
        Provider::BitDo => bitdo_prepare(url, client),
    }
}
<|endoftext|>


<commit_before>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type suseconds_t = i64;

s! {
    pub struct timeval {
        pub tv_sec: time_t,
        pub tv_usec: suseconds_t,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 0x1000;
pub const S_IFCHR: mode_t = 0x2000;
pub const S_IFBLK: mode_t = 0x6000;
pub const S_IFDIR: mode_t = 0x4000;
pub const S_IFREG: mode_t = 0x8000;
pub const S_IFLNK: mode_t = 0xA000;
pub const S_IFSOCK: mode_t = 0xC000;
pub const S_IFMT: mode_t = 0xF000;
pub const S_IEXEC: mode_t = 0x40;
pub const S_IWRITE: mode_t = 0x80;
pub const S_IREAD: mode_t = 0x100;
pub const S_IRWXU: mode_t = 0x1C0;
pub const S_IXUSR: mode_t = 0x40;
pub const S_IWUSR: mode_t = 0x80;
pub const S_IRUSR: mode_t = 0x100;
pub const S_IRWXG: mode_t = 0x38;
pub const S_IXGRP: mode_t = 0x8;
pub const S_IWGRP: mode_t = 0x10;
pub const S_IRGRP: mode_t = 0x20;
pub const S_IRWXO: mode_t = 0x7;
pub const S_IXOTH: mode_t = 0x1;
pub const S_IWOTH: mode_t = 0x2;
pub const S_IROTH: mode_t = 0x4;

pub const F_DUPFD: ::c_int = 0;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
pub const F_SETFL: ::c_int = 4;

pub const O_RDONLY: ::c_int =     0x0001_0000;
pub const O_WRONLY: ::c_int =     0x0002_0000;
pub const O_RDWR: ::c_int =       0x0003_0000;
pub const O_NONBLOCK: ::c_int =   0x0004_0000;
pub const O_APPEND: ::c_int =     0x0008_0000;
pub const O_SHLOCK: ::c_int =     0x0010_0000;
pub const O_EXLOCK: ::c_int =     0x0020_0000;
pub const O_ASYNC: ::c_int =      0x0040_0000;
pub const O_FSYNC: ::c_int =      0x0080_0000;
pub const O_CLOEXEC: ::c_int =    0x0100_0000;
pub const O_CREAT: ::c_int =      0x0200_0000;
pub const O_TRUNC: ::c_int =      0x0400_0000;
pub const O_EXCL: ::c_int =       0x0800_0000;
pub const O_DIRECTORY: ::c_int =  0x1000_0000;
pub const O_STAT: ::c_int =       0x2000_0000;
pub const O_SYMLINK: ::c_int =    0x4000_0000;
pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;

pub const SIGHUP:    ::c_int = 1;
pub const SIGINT:    ::c_int = 2;
pub const SIGQUIT:   ::c_int = 3;
pub const SIGILL:    ::c_int = 4;
pub const SIGTRAP:   ::c_int = 5;
pub const SIGABRT:   ::c_int = 6;
pub const SIGBUS:    ::c_int = 7;
pub const SIGFPE:    ::c_int = 8;
pub const SIGKILL:   ::c_int = 9;
pub const SIGUSR1:   ::c_int = 10;
pub const SIGSEGV:   ::c_int = 11;
pub const SIGUSR2:   ::c_int = 12;
pub const SIGPIPE:   ::c_int = 13;
pub const SIGALRM:   ::c_int = 14;
pub const SIGTERM:   ::c_int = 15;
pub const SIGSTKFLT: ::c_int = 16;
pub const SIGCHLD:   ::c_int = 17;
pub const SIGCONT:   ::c_int = 18;
pub const SIGSTOP:   ::c_int = 19;
pub const SIGTSTP:   ::c_int = 20;
pub const SIGTTIN:   ::c_int = 21;
pub const SIGTTOU:   ::c_int = 22;
pub const SIGURG:    ::c_int = 23;
pub const SIGXCPU:   ::c_int = 24;
pub const SIGXFSZ:   ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF:   ::c_int = 27;
pub const SIGWINCH:  ::c_int = 28;
pub const SIGIO:     ::c_int = 29;
pub const SIGPWR:    ::c_int = 30;
pub const SIGSYS:    ::c_int = 31;

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
    pub fn close(fd: ::c_int) -> ::c_int;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}

pub use self::net::*;

mod net;
<commit_msg>Add `gethostname` support to Redox module<commit_after>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type suseconds_t = i64;

s! {
    pub struct timeval {
        pub tv_sec: time_t,
        pub tv_usec: suseconds_t,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 0x1000;
pub const S_IFCHR: mode_t = 0x2000;
pub const S_IFBLK: mode_t = 0x6000;
pub const S_IFDIR: mode_t = 0x4000;
pub const S_IFREG: mode_t = 0x8000;
pub const S_IFLNK: mode_t = 0xA000;
pub const S_IFSOCK: mode_t = 0xC000;
pub const S_IFMT: mode_t = 0xF000;
pub const S_IEXEC: mode_t = 0x40;
pub const S_IWRITE: mode_t = 0x80;
pub const S_IREAD: mode_t = 0x100;
pub const S_IRWXU: mode_t = 0x1C0;
pub const S_IXUSR: mode_t = 0x40;
pub const S_IWUSR: mode_t = 0x80;
pub const S_IRUSR: mode_t = 0x100;
pub const S_IRWXG: mode_t = 0x38;
pub const S_IXGRP: mode_t = 0x8;
pub const S_IWGRP: mode_t = 0x10;
pub const S_IRGRP: mode_t = 0x20;
pub const S_IRWXO: mode_t = 0x7;
pub const S_IXOTH: mode_t = 0x1;
pub const S_IWOTH: mode_t = 0x2;
pub const S_IROTH: mode_t = 0x4;

pub const F_DUPFD: ::c_int = 0;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
pub const F_SETFL: ::c_int = 4;

pub const O_RDONLY: ::c_int =     0x0001_0000;
pub const O_WRONLY: ::c_int =     0x0002_0000;
pub const O_RDWR: ::c_int =       0x0003_0000;
pub const O_NONBLOCK: ::c_int =   0x0004_0000;
pub const O_APPEND: ::c_int =     0x0008_0000;
pub const O_SHLOCK: ::c_int =     0x0010_0000;
pub const O_EXLOCK: ::c_int =     0x0020_0000;
pub const O_ASYNC: ::c_int =      0x0040_0000;
pub const O_FSYNC: ::c_int =      0x0080_0000;
pub const O_CLOEXEC: ::c_int =    0x0100_0000;
pub const O_CREAT: ::c_int =      0x0200_0000;
pub const O_TRUNC: ::c_int =      0x0400_0000;
pub const O_EXCL: ::c_int =       0x0800_0000;
pub const O_DIRECTORY: ::c_int =  0x1000_0000;
pub const O_STAT: ::c_int =       0x2000_0000;
pub const O_SYMLINK: ::c_int =    0x4000_0000;
pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;

pub const SIGHUP:    ::c_int = 1;
pub const SIGINT:    ::c_int = 2;
pub const SIGQUIT:   ::c_int = 3;
pub const SIGILL:    ::c_int = 4;
pub const SIGTRAP:   ::c_int = 5;
pub const SIGABRT:   ::c_int = 6;
pub const SIGBUS:    ::c_int = 7;
pub const SIGFPE:    ::c_int = 8;
pub const SIGKILL:   ::c_int = 9;
pub const SIGUSR1:   ::c_int = 10;
pub const SIGSEGV:   ::c_int = 11;
pub const SIGUSR2:   ::c_int = 12;
pub const SIGPIPE:   ::c_int = 13;
pub const SIGALRM:   ::c_int = 14;
pub const SIGTERM:   ::c_int = 15;
pub const SIGSTKFLT: ::c_int = 16;
pub const SIGCHLD:   ::c_int = 17;
pub const SIGCONT:   ::c_int = 18;
pub const SIGSTOP:   ::c_int = 19;
pub const SIGTSTP:   ::c_int = 20;
pub const SIGTTIN:   ::c_int = 21;
pub const SIGTTOU:   ::c_int = 22;
pub const SIGURG:    ::c_int = 23;
pub const SIGXCPU:   ::c_int = 24;
pub const SIGXFSZ:   ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF:   ::c_int = 27;
pub const SIGWINCH:  ::c_int = 28;
pub const SIGIO:     ::c_int = 29;
pub const SIGPWR:    ::c_int = 30;
pub const SIGSYS:    ::c_int = 31;

extern {
    pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
    pub fn close(fd: ::c_int) -> ::c_int;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}

pub use self::net::*;

mod net;
<|endoftext|>


<commit_before>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Secp256k1
//! Rust bindings for Pieter Wuille's secp256k1 library, which is used for
//! fast and accurate manipulation of ECDSA signatures on the secp256k1
//! curve. Such signatures are used extensively by the Bitcoin network
//! and its derivatives.
//!

#![crate_type = "lib"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![crate_name = "bitcoin-secp256k1-rs"]
#![comment = "Bindings and wrapper functions for bitcoin secp256k1 library."]
#![feature(phase)]
#![feature(macro_rules)]
#![feature(globs)]  // for tests only

// Coding conventions
#![deny(non_uppercase_pattern_statics)]
#![deny(uppercase_variables)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case_functions)]
#![deny(unused_mut)]
#![warn(missing_doc)]

extern crate libc;
extern crate sync;

use std::io::{IoError, IoResult};
use std::rand::OsRng;
use libc::c_int;
use sync::one::{Once, ONCE_INIT};

mod macros;
pub mod constants;
pub mod ffi;
pub mod key;

/// A tag used for recovering the public key from a compact signature
pub struct RecoveryId(i32);

/// An ECDSA signature
pub struct Signature(uint, [u8, ..constants::MAX_SIGNATURE_SIZE]);

impl Signature {
    /// Converts the signature to a mutable raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        let &Signature(_, ref mut data) = self;
        data.as_mut_slice().as_mut_ptr()
    }

    /// Converts the signature to a byte slice suitable for verification
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &Signature(len, ref data) = self;
        data.slice_to(len)
    }

    /// Returns the length of the signature
    #[inline]
    pub fn len(&self) -> uint {
        let &Signature(len, _) = self;
        len
    }
}

/// An ECDSA error
#[deriving(PartialEq, Eq, Clone, Show)]
pub enum Error {
    /// Signature failed verification
    IncorrectSignature,
    /// Bad public key
    InvalidPublicKey,
    /// Bad signature
    InvalidSignature,
    /// Bad secret key
    InvalidSecretKey,
    /// Bad nonce
    InvalidNonce,
    /// Rng problem
    RngError(IoError),
    /// Boolean-returning function returned the wrong boolean
    Unknown
}

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

static mut Secp256k1_init : Once = ONCE_INIT;

/// The secp256k1 engine, used to execute all signature operations
pub struct Secp256k1 {
    rng: IoResult<OsRng>
}

/// Does one-time initialization of the secp256k1 engine. Can be called
/// multiple times, and is called by the `Secp256k1` constructor. This
/// only needs to be called directly if you are using the library without
/// a `Secp256k1` object, e.g. batch key generation through
/// `key::PublicKey::from_secret_key`.
pub fn init() {
    unsafe {
        Secp256k1_init.doit(|| {
            ffi::secp256k1_start();
        });
    }
}

impl Secp256k1 {
    /// Constructs a new secp256k1 engine.
    pub fn new() -> Secp256k1 {
        init();
        Secp256k1 { rng: OsRng::new() }
    }

    /// Generates a random keypair. Convenience function for `key::SecretKey::new`
    /// and `key::PublicKey::from_secret_key`; call those functions directly for
    /// batch key generation.
    pub fn generate_keypair(&mut self, compressed: bool)
                            -> Result<(key::SecretKey, key::PublicKey)> {
        match self.rng {
            Ok(ref mut rng) => {
                let sk = key::SecretKey::new(rng);
                Ok((sk, key::PublicKey::from_secret_key(&sk, compressed)))
            }
            Err(ref e) => Err(RngError(e.clone()))
        }
    }

    /// Generates a random nonce. Convenience function for `key::Nonce::new`; call
    /// that function directly for batch nonce generation
    pub fn generate_nonce(&mut self) -> Result<key::Nonce> {
        match self.rng {
            Ok(ref mut rng) => Ok(key::Nonce::new(rng)),
            Err(ref e) => Err(RngError(e.clone()))
        }
    }

    /// Constructs a signature for `msg` using the secret key `sk` and nonce `nonce`
    pub fn sign(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
                -> Result<Signature> {
        let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
        let mut len = constants::MAX_SIGNATURE_SIZE as c_int;
        unsafe {
            if ffi::secp256k1_ecdsa_sign(msg.as_ptr(), msg.len() as c_int,
                                         sig.as_mut_slice().as_mut_ptr(), &mut len,
                                         sk.as_ptr(), nonce.as_ptr()) != 1 {
                return Err(InvalidNonce);
            }
            // This assertation is probably too late :)
            assert!(len as uint <= constants::MAX_SIGNATURE_SIZE);
        };
        Ok(Signature(len as uint, sig))
    }

    /// Constructs a compact signature for `msg` using the secret key `sk`
    pub fn sign_compact(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
                        -> Result<(Signature, RecoveryId)> {
        let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
        let mut recid = 0;
        unsafe {
            if ffi::secp256k1_ecdsa_sign_compact(msg.as_ptr(), msg.len() as c_int,
                                                 sig.as_mut_slice().as_mut_ptr(), sk.as_ptr(),
                                                 nonce.as_ptr(), &mut recid) != 1 {
                return Err(InvalidNonce);
            }
        };
        Ok((Signature(constants::MAX_COMPACT_SIGNATURE_SIZE, sig), RecoveryId(recid)))
    }

    /// Determines the public key for which `sig` is a valid signature for
    /// `msg`. Returns through the out-pointer `pubkey`.
    pub fn recover_compact(&self, msg: &[u8], sig: &[u8],
                           compressed: bool, recid: RecoveryId)
                            -> Result<key::PublicKey> {
        let mut pk = key::PublicKey::new(compressed);
        let RecoveryId(recid) = recid;

        unsafe {
            let mut len = 0;
            if ffi::secp256k1_ecdsa_recover_compact(msg.as_ptr(), msg.len() as c_int,
                                                    sig.as_ptr(), pk.as_mut_ptr(), &mut len,
                                                    if compressed {1} else {0},
                                                    recid) != 1 {
                return Err(InvalidSignature);
            }
            assert_eq!(len as uint, pk.len());
        };
        Ok(pk)
    }

    /// Checks that `sig` is a valid ECDSA signature for `msg` using the public
    /// key `pubkey`. Returns `Ok(true)` on success.
    pub fn verify(&self, msg: &[u8], sig: &[u8], pk: &key::PublicKey) -> Result<()> {
        let res = unsafe {
            ffi::secp256k1_ecdsa_verify(msg.as_ptr(), msg.len() as c_int,
                                        sig.as_ptr(), sig.len() as c_int,
                                        pk.as_ptr(), pk.len() as c_int)
        };

        match res {
            1 => Ok(()),
            0 => Err(IncorrectSignature),
            -1 => Err(InvalidPublicKey),
            -2 => Err(InvalidSignature),
            _ => unreachable!()
        }
    }
}

#[cfg(test)]
mod test {
    use std::rand;
    use std::rand::Rng;
    use key::PublicKey;

    use super::Secp256k1;
    use super::{InvalidPublicKey, IncorrectSignature, InvalidSignature};

    #[test]
    fn invalid_pubkey() {
        let s = Secp256k1::new();

        let mut msg = Vec::from_elem(32, 0u8);
        let sig = Vec::from_elem(32, 0u8);
        let pk = PublicKey::new(true);

        rand::task_rng().fill_bytes(msg.as_mut_slice());

        assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidPublicKey));
    }

    #[test]
    fn valid_pubkey_uncompressed() {
        let mut s = Secp256k1::new();

        let (_, pk) = s.generate_keypair(false).unwrap();

        let mut msg = Vec::from_elem(32, 0u8);
        let sig = Vec::from_elem(32, 0u8);

        rand::task_rng().fill_bytes(msg.as_mut_slice());

        assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
    }

    #[test]
    fn valid_pubkey_compressed() {
        let mut s = Secp256k1::new();

        let (_, pk) = s.generate_keypair(true).unwrap();
        let mut msg = Vec::from_elem(32, 0u8);
        let sig = Vec::from_elem(32, 0u8);

        rand::task_rng().fill_bytes(msg.as_mut_slice());

        assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
    }

    #[test]
    fn sign() {
        let mut s = Secp256k1::new();

        let mut msg = [0u8, ..32];
        rand::task_rng().fill_bytes(msg);

        let (sk, _) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        s.sign(msg.as_slice(), &sk, &nonce).unwrap();
    }

    #[test]
    fn sign_and_verify() {
        let mut s = Secp256k1::new();

        let mut msg = Vec::from_elem(32, 0u8);
        rand::task_rng().fill_bytes(msg.as_mut_slice());

        let (sk, pk) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();

        assert_eq!(s.verify(msg.as_slice(), sig.as_slice(), &pk), Ok(()));
    }

    #[test]
    fn sign_and_verify_fail() {
        let mut s = Secp256k1::new();

        let mut msg = Vec::from_elem(32, 0u8);
        rand::task_rng().fill_bytes(msg.as_mut_slice());

        let (sk, pk) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();

        rand::task_rng().fill_bytes(msg.as_mut_slice());
        assert_eq!(s.verify(msg.as_slice(), sig.as_slice(), &pk), Err(IncorrectSignature));
    }

    #[test]
    fn sign_compact_with_recovery() {
        let mut s = Secp256k1::new();

        let mut msg = [0u8, ..32];
        rand::task_rng().fill_bytes(msg.as_mut_slice());

        let (sk, pk) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        let (sig, recid) = s.sign_compact(msg.as_slice(), &sk, &nonce).unwrap();

        assert_eq!(s.recover_compact(msg.as_slice(), sig.as_slice(), false, recid), Ok(pk));
    }
}
<commit_msg>Change lint names for upstream<commit_after>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Secp256k1
//! Rust bindings for Pieter Wuille's secp256k1 library, which is used for
//! fast and accurate manipulation of ECDSA signatures on the secp256k1
//! curve. Such signatures are used extensively by the Bitcoin network
//! and its derivatives.
//!

#![crate_type = "lib"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![crate_name = "bitcoin-secp256k1-rs"]
#![comment = "Bindings and wrapper functions for bitcoin secp256k1 library."]
#![feature(phase)]
#![feature(macro_rules)]
#![feature(globs)]  // for tests only

// Coding conventions
#![deny(non_uppercase_statics)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![warn(missing_doc)]

extern crate libc;
extern crate sync;

use std::io::{IoError, IoResult};
use std::rand::OsRng;
use libc::c_int;
use sync::one::{Once, ONCE_INIT};

mod macros;
pub mod constants;
pub mod ffi;
pub mod key;

/// A tag used for recovering the public key from a compact signature
pub struct RecoveryId(i32);

/// An ECDSA signature
pub struct Signature(uint, [u8, ..constants::MAX_SIGNATURE_SIZE]);

impl Signature {
    /// Converts the signature to a mutable raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        let &Signature(_, ref mut data) = self;
        data.as_mut_slice().as_mut_ptr()
    }

    /// Converts the signature to a byte slice suitable for verification
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &Signature(len, ref data) = self;
        data.slice_to(len)
    }

    /// Returns the length of the signature
    #[inline]
    pub fn len(&self) -> uint {
        let &Signature(len, _) = self;
        len
    }
}

/// An ECDSA error
#[deriving(PartialEq, Eq, Clone, Show)]
pub enum Error {
    /// Signature failed verification
    IncorrectSignature,
    /// Bad public key
    InvalidPublicKey,
    /// Bad signature
    InvalidSignature,
    /// Bad secret key
    InvalidSecretKey,
    /// Bad nonce
    InvalidNonce,
    /// Rng problem
    RngError(IoError),
    /// Boolean-returning function returned the wrong boolean
    Unknown
}

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

static mut Secp256k1_init : Once = ONCE_INIT;

/// The secp256k1 engine, used to execute all signature operations
pub struct Secp256k1 {
    rng: IoResult<OsRng>
}

/// Does one-time initialization of the secp256k1 engine. Can be called
/// multiple times, and is called by the `Secp256k1` constructor. This
/// only needs to be called directly if you are using the library without
/// a `Secp256k1` object, e.g. batch key generation through
/// `key::PublicKey::from_secret_key`.
pub fn init() {
    unsafe {
        Secp256k1_init.doit(|| {
            ffi::secp256k1_start();
        });
    }
}

impl Secp256k1 {
    /// Constructs a new secp256k1 engine.
    pub fn new() -> Secp256k1 {
        init();
        Secp256k1 { rng: OsRng::new() }
    }

    /// Generates a random keypair. Convenience function for `key::SecretKey::new`
    /// and `key::PublicKey::from_secret_key`; call those functions directly for
    /// batch key generation.
    pub fn generate_keypair(&mut self, compressed: bool)
                            -> Result<(key::SecretKey, key::PublicKey)> {
        match self.rng {
            Ok(ref mut rng) => {
                let sk = key::SecretKey::new(rng);
                Ok((sk, key::PublicKey::from_secret_key(&sk, compressed)))
            }
            Err(ref e) => Err(RngError(e.clone()))
        }
    }

    /// Generates a random nonce. Convenience function for `key::Nonce::new`; call
    /// that function directly for batch nonce generation
    pub fn generate_nonce(&mut self) -> Result<key::Nonce> {
        match self.rng {
            Ok(ref mut rng) => Ok(key::Nonce::new(rng)),
            Err(ref e) => Err(RngError(e.clone()))
        }
    }

    /// Constructs a signature for `msg` using the secret key `sk` and nonce `nonce`
    pub fn sign(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
                -> Result<Signature> {
        let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
        let mut len = constants::MAX_SIGNATURE_SIZE as c_int;
        unsafe {
            if ffi::secp256k1_ecdsa_sign(msg.as_ptr(), msg.len() as c_int,
                                         sig.as_mut_slice().as_mut_ptr(), &mut len,
                                         sk.as_ptr(), nonce.as_ptr()) != 1 {
                return Err(InvalidNonce);
            }
            // This assertation is probably too late :)
            assert!(len as uint <= constants::MAX_SIGNATURE_SIZE);
        };
        Ok(Signature(len as uint, sig))
    }

    /// Constructs a compact signature for `msg` using the secret key `sk`
    pub fn sign_compact(&self, msg: &[u8], sk: &key::SecretKey, nonce: &key::Nonce)
                        -> Result<(Signature, RecoveryId)> {
        let mut sig = [0, ..constants::MAX_SIGNATURE_SIZE];
        let mut recid = 0;
        unsafe {
            if ffi::secp256k1_ecdsa_sign_compact(msg.as_ptr(), msg.len() as c_int,
                                                 sig.as_mut_slice().as_mut_ptr(), sk.as_ptr(),
                                                 nonce.as_ptr(), &mut recid) != 1 {
                return Err(InvalidNonce);
            }
        };
        Ok((Signature(constants::MAX_COMPACT_SIGNATURE_SIZE, sig), RecoveryId(recid)))
    }

    /// Determines the public key for which `sig` is a valid signature for
    /// `msg`. Returns through the out-pointer `pubkey`.
    pub fn recover_compact(&self, msg: &[u8], sig: &[u8],
                           compressed: bool, recid: RecoveryId)
                            -> Result<key::PublicKey> {
        let mut pk = key::PublicKey::new(compressed);
        let RecoveryId(recid) = recid;

        unsafe {
            let mut len = 0;
            if ffi::secp256k1_ecdsa_recover_compact(msg.as_ptr(), msg.len() as c_int,
                                                    sig.as_ptr(), pk.as_mut_ptr(), &mut len,
                                                    if compressed {1} else {0},
                                                    recid) != 1 {
                return Err(InvalidSignature);
            }
            assert_eq!(len as uint, pk.len());
        };
        Ok(pk)
    }

    /// Checks that `sig` is a valid ECDSA signature for `msg` using the public
    /// key `pubkey`. Returns `Ok(true)` on success.
    pub fn verify(&self, msg: &[u8], sig: &[u8], pk: &key::PublicKey) -> Result<()> {
        let res = unsafe {
            ffi::secp256k1_ecdsa_verify(msg.as_ptr(), msg.len() as c_int,
                                        sig.as_ptr(), sig.len() as c_int,
                                        pk.as_ptr(), pk.len() as c_int)
        };

        match res {
            1 => Ok(()),
            0 => Err(IncorrectSignature),
            -1 => Err(InvalidPublicKey),
            -2 => Err(InvalidSignature),
            _ => unreachable!()
        }
    }
}

#[cfg(test)]
mod test {
    use std::rand;
    use std::rand::Rng;
    use key::PublicKey;

    use super::Secp256k1;
    use super::{InvalidPublicKey, IncorrectSignature, InvalidSignature};

    #[test]
    fn invalid_pubkey() {
        let s = Secp256k1::new();

        let mut msg = Vec::from_elem(32, 0u8);
        let sig = Vec::from_elem(32, 0u8);
        let pk = PublicKey::new(true);

        rand::task_rng().fill_bytes(msg.as_mut_slice());

        assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidPublicKey));
    }

    #[test]
    fn valid_pubkey_uncompressed() {
        let mut s = Secp256k1::new();

        let (_, pk) = s.generate_keypair(false).unwrap();

        let mut msg = Vec::from_elem(32, 0u8);
        let sig = Vec::from_elem(32, 0u8);

        rand::task_rng().fill_bytes(msg.as_mut_slice());

        assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
    }

    #[test]
    fn valid_pubkey_compressed() {
        let mut s = Secp256k1::new();

        let (_, pk) = s.generate_keypair(true).unwrap();
        let mut msg = Vec::from_elem(32, 0u8);
        let sig = Vec::from_elem(32, 0u8);

        rand::task_rng().fill_bytes(msg.as_mut_slice());

        assert_eq!(s.verify(msg.as_mut_slice(), sig.as_slice(), &pk), Err(InvalidSignature));
    }

    #[test]
    fn sign() {
        let mut s = Secp256k1::new();

        let mut msg = [0u8, ..32];
        rand::task_rng().fill_bytes(msg);

        let (sk, _) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        s.sign(msg.as_slice(), &sk, &nonce).unwrap();
    }

    #[test]
    fn sign_and_verify() {
        let mut s = Secp256k1::new();

        let mut msg = Vec::from_elem(32, 0u8);
        rand::task_rng().fill_bytes(msg.as_mut_slice());

        let (sk, pk) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();

        assert_eq!(s.verify(msg.as_slice(), sig.as_slice(), &pk), Ok(()));
    }

    #[test]
    fn sign_and_verify_fail() {
        let mut s = Secp256k1::new();

        let mut msg = Vec::from_elem(32, 0u8);
        rand::task_rng().fill_bytes(msg.as_mut_slice());

        let (sk, pk) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        let sig = s.sign(msg.as_slice(), &sk, &nonce).unwrap();

        rand::task_rng().fill_bytes(msg.as_mut_slice());
        assert_eq!(s.verify(msg.as_slice(), sig.as_slice(), &pk), Err(IncorrectSignature));
    }

    #[test]
    fn sign_compact_with_recovery() {
        let mut s = Secp256k1::new();

        let mut msg = [0u8, ..32];
        rand::task_rng().fill_bytes(msg.as_mut_slice());

        let (sk, pk) = s.generate_keypair(false).unwrap();
        let nonce = s.generate_nonce().unwrap();

        let (sig, recid) = s.sign_compact(msg.as_slice(), &sk, &nonce).unwrap();

        assert_eq!(s.recover_compact(msg.as_slice(), sig.as_slice(), false, recid), Ok(pk));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use rustc::ty::layout::{Size, Align};
use rustc_mir::interpret::{Pointer, Memory};
use crate::stacked_borrows::Tag;
use crate::*;

#[derive(Default)]
pub struct EnvVars {
    map: HashMap<Vec<u8>, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    ) {
        if ecx.machine.communicate {
            for (name, value) in std::env::vars() {
                let value = alloc_env_value(value.as_bytes(), ecx.memory_mut());
                ecx.machine.env_vars.map.insert(name.into_bytes(), value);
            }
        }
    }
}

fn alloc_env_value<'mir, 'tcx>(
    bytes: &[u8],
    memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let tcx = {memory.tcx.tcx};
    let length = bytes.len() as u64;
    // `+1` for the null terminator.
    let ptr = memory.allocate(
        Size::from_bytes(length + 1),
        Align::from_bytes(1).unwrap(),
        MiriMemoryKind::Env.into(),
    );
    // We just allocated these, so the write cannot fail.
    let alloc = memory.get_mut(ptr.alloc_id).unwrap();
    alloc.write_bytes(&tcx, ptr, &bytes).unwrap();
    let trailing_zero_ptr = ptr.offset(
        Size::from_bytes(length),
        &tcx,
    ).unwrap();
    alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap();
    ptr
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.memory().read_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            Some(&var) => Scalar::Ptr(var),
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.memory().read_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?;
            if !name.is_empty() && !name.contains(&b'=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let value_copy = alloc_env_value(&value, this.memory_mut());
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), value_copy) {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.contains(&b'=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }
}
<commit_msg>Auto merge of #925 - christianpoveda:environ-shim, r=RalfJung<commit_after>use std::collections::HashMap;

use rustc::ty::layout::{Size, Align};
use rustc_mir::interpret::{Pointer, Memory};
use crate::stacked_borrows::Tag;
use crate::*;

#[derive(Default)]
pub struct EnvVars {
    /// Stores pointers to the environment variables. These variables must be stored as
    /// null-terminated C strings with the `"{name}={value}"` format.
    map: HashMap<Vec<u8>, Pointer<Tag>>,
}

impl EnvVars {
    pub(crate) fn init<'mir, 'tcx>(
        ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    ) {
        if ecx.machine.communicate {
            for (name, value) in std::env::vars() {
                let var_ptr = alloc_env_var(name.as_bytes(), value.as_bytes(), ecx.memory_mut());
                ecx.machine.env_vars.map.insert(name.into_bytes(), var_ptr);
            }
        }
    }
}

fn alloc_env_var<'mir, 'tcx>(
    name: &[u8],
    value: &[u8],
    memory: &mut Memory<'mir, 'tcx, Evaluator<'tcx>>,
) -> Pointer<Tag> {
    let bytes = [name, b"=", value].concat();
    let tcx = {memory.tcx.tcx};
    let length = bytes.len() as u64;
    // `+1` for the null terminator.
    let ptr = memory.allocate(
        Size::from_bytes(length + 1),
        Align::from_bytes(1).unwrap(),
        MiriMemoryKind::Env.into(),
    );
    // We just allocated these, so the write cannot fail.
    let alloc = memory.get_mut(ptr.alloc_id).unwrap();
    alloc.write_bytes(&tcx, ptr, &bytes).unwrap();
    let trailing_zero_ptr = ptr.offset(
        Size::from_bytes(length),
        &tcx,
    ).unwrap();
    alloc.write_bytes(&tcx, trailing_zero_ptr, &[0]).unwrap();
    ptr
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn getenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, Scalar<Tag>> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let name = this.memory().read_c_str(name_ptr)?;
        Ok(match this.machine.env_vars.map.get(name) {
            // The offset is used to strip the "{name}=" part of the string.
            Some(var_ptr) => Scalar::Ptr(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?),
            None => Scalar::ptr_null(&*this.tcx),
        })
    }

    fn setenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
        value_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let value_ptr = this.read_scalar(value_op)?.not_undef()?;
        let value = this.memory().read_c_str(value_ptr)?;
        let mut new = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?;
            if !name.is_empty() && !name.contains(&b'=') {
                new = Some((name.to_owned(), value.to_owned()));
            }
        }
        if let Some((name, value)) = new {
            let var_ptr = alloc_env_var(&name, &value, this.memory_mut());
            if let Some(var) = this.machine.env_vars.map.insert(name.to_owned(), var_ptr) {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }

    fn unsetenv(
        &mut self,
        name_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let name_ptr = this.read_scalar(name_op)?.not_undef()?;
        let mut success = None;
        if !this.is_null(name_ptr)? {
            let name = this.memory().read_c_str(name_ptr)?.to_owned();
            if !name.is_empty() && !name.contains(&b'=') {
                success = Some(this.machine.env_vars.map.remove(&name));
            }
        }
        if let Some(old) = success {
            if let Some(var) = old {
                this.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
            }
            Ok(0)
        } else {
            Ok(-1)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// 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.

use structure::*;

use approx::ApproxEq;
use matrix::{Matrix2, Matrix3, Matrix4};
use num::{BaseFloat, BaseNum};
use point::{Point2, Point3};
use rotation::*;
use vector::{Vector2, Vector3};

/// A trait representing an [affine
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
/// can be applied to points or vectors. An affine transformation is one which
pub trait Transform<P: EuclideanSpace>: Sized {
    /// Create an identity transformation. That is, a transformation which
    /// does nothing.
    fn one() -> Self;

    /// Create a transformation that rotates a vector to look at `center` from
    /// `eye`, using `up` for orientation.
    fn look_at(eye: P, center: P, up: P::Diff) -> Self;

    /// Transform a vector using this transform.
    fn transform_vector(&self, vec: P::Diff) -> P::Diff;

    /// Transform a point using this transform.
    fn transform_point(&self, point: P) -> P;

    /// Transform a vector as a point using this transform.
    #[inline]
    fn transform_as_point(&self, vec: P::Diff) -> P::Diff {
        self.transform_point(P::from_vec(vec)).to_vec()
    }

    /// Combine this transform with another, yielding a new transformation
    /// which has the effects of both.
    fn concat(&self, other: &Self) -> Self;

    /// Create a transform that "un-does" this one.
    fn inverse_transform(&self) -> Option<Self>;

    /// Combine this transform with another, in-place.
    #[inline]
    fn concat_self(&mut self, other: &Self) {
        *self = Self::concat(self, other);
    }
}

/// A generic transformation consisting of a rotation,
/// displacement vector and scale amount.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Decomposed<V: VectorSpace, R> {
    pub scale: V::Scalar,
    pub rot: R,
    pub disp: V,
}

impl<P: EuclideanSpace, R: Rotation<P>> Transform<P> for Decomposed<P::Diff, R> where
    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
    <P as EuclideanSpace>::Scalar: BaseFloat,
    // FIXME: Investigate why this is needed!
    <P as EuclideanSpace>::Diff: VectorSpace,
{
    #[inline]
    fn one() -> Decomposed<P::Diff, R> {
        Decomposed {
            scale: P::Scalar::one(),
            rot: R::one(),
            disp: P::Diff::zero(),
        }
    }

    #[inline]
    fn look_at(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
        let rot = R::look_at(center - eye, up);
        let disp = rot.rotate_vector(P::origin() - eye);
        Decomposed {
            scale: P::Scalar::one(),
            rot: rot,
            disp: disp,
        }
    }

    #[inline]
    fn transform_vector(&self, vec: P::Diff) -> P::Diff {
        self.rot.rotate_vector(vec * self.scale)
    }

    #[inline]
    fn transform_point(&self, point: P) -> P {
        self.rot.rotate_point(point * self.scale) + self.disp
    }

    fn concat(&self, other: &Decomposed<P::Diff, R>) -> Decomposed<P::Diff, R> {
        Decomposed {
            scale: self.scale * other.scale,
            rot: self.rot.concat(&other.rot),
            disp: self.transform_as_point(other.disp.clone()),
        }
    }

    fn inverse_transform(&self) -> Option<Decomposed<P::Diff, R>> {
        if self.scale.approx_eq(&P::Scalar::zero()) {
            None
        } else {
            let s = P::Scalar::one() / self.scale;
            let r = self.rot.invert();
            let d = r.rotate_vector(self.disp.clone()) * -s;
            Some(Decomposed {
                scale: s,
                rot: r,
                disp: d,
            })
        }
    }
}

pub trait Transform2<S: BaseNum>: Transform<Point2<S>> + Into<Matrix3<S>> {}
pub trait Transform3<S: BaseNum>: Transform<Point3<S>> + Into<Matrix4<S>> {}

impl<S: BaseFloat, R: Rotation2<S>> From<Decomposed<Vector2<S>, R>> for Matrix3<S> {
    fn from(dec: Decomposed<Vector2<S>, R>) -> Matrix3<S> {
        let m: Matrix2<_> = dec.rot.into();
        let mut m: Matrix3<_> = (&m * dec.scale).into();
        m.z = dec.disp.extend(S::one());
        m
    }
}

impl<S: BaseFloat, R: Rotation3<S>> From<Decomposed<Vector3<S>, R>> for Matrix4<S> {
    fn from(dec: Decomposed<Vector3<S>, R>) -> Matrix4<S> {
        let m: Matrix3<_> = dec.rot.into();
        let mut m: Matrix4<_> = (&m * dec.scale).into();
        m.w = dec.disp.extend(S::one());
        m
    }
}

impl<S: BaseFloat, R: Rotation2<S>> Transform2<S> for Decomposed<Vector2<S>, R> {}

impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<Vector3<S>, R> {}
<commit_msg>Remove transforma_as_point method<commit_after>// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// 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.

use structure::*;

use approx::ApproxEq;
use matrix::{Matrix2, Matrix3, Matrix4};
use num::{BaseFloat, BaseNum};
use point::{Point2, Point3};
use rotation::*;
use vector::{Vector2, Vector3};

/// A trait representing an [affine
/// transformation](https://en.wikipedia.org/wiki/Affine_transformation) that
/// can be applied to points or vectors. An affine transformation is one which
pub trait Transform<P: EuclideanSpace>: Sized {
    /// Create an identity transformation. That is, a transformation which
    /// does nothing.
    fn one() -> Self;

    /// Create a transformation that rotates a vector to look at `center` from
    /// `eye`, using `up` for orientation.
    fn look_at(eye: P, center: P, up: P::Diff) -> Self;

    /// Transform a vector using this transform.
    fn transform_vector(&self, vec: P::Diff) -> P::Diff;

    /// Transform a point using this transform.
    fn transform_point(&self, point: P) -> P;

    /// Combine this transform with another, yielding a new transformation
    /// which has the effects of both.
    fn concat(&self, other: &Self) -> Self;

    /// Create a transform that "un-does" this one.
    fn inverse_transform(&self) -> Option<Self>;

    /// Combine this transform with another, in-place.
    #[inline]
    fn concat_self(&mut self, other: &Self) {
        *self = Self::concat(self, other);
    }
}

/// A generic transformation consisting of a rotation,
/// displacement vector and scale amount.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Decomposed<V: VectorSpace, R> {
    pub scale: V::Scalar,
    pub rot: R,
    pub disp: V,
}

impl<P: EuclideanSpace, R: Rotation<P>> Transform<P> for Decomposed<P::Diff, R> where
    // FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
    <P as EuclideanSpace>::Scalar: BaseFloat,
    // FIXME: Investigate why this is needed!
    <P as EuclideanSpace>::Diff: VectorSpace,
{
    #[inline]
    fn one() -> Decomposed<P::Diff, R> {
        Decomposed {
            scale: P::Scalar::one(),
            rot: R::one(),
            disp: P::Diff::zero(),
        }
    }

    #[inline]
    fn look_at(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
        let rot = R::look_at(center - eye, up);
        let disp = rot.rotate_vector(P::origin() - eye);
        Decomposed {
            scale: P::Scalar::one(),
            rot: rot,
            disp: disp,
        }
    }

    #[inline]
    fn transform_vector(&self, vec: P::Diff) -> P::Diff {
        self.rot.rotate_vector(vec * self.scale)
    }

    #[inline]
    fn transform_point(&self, point: P) -> P {
        self.rot.rotate_point(point * self.scale) + self.disp
    }

    fn concat(&self, other: &Decomposed<P::Diff, R>) -> Decomposed<P::Diff, R> {
        Decomposed {
            scale: self.scale * other.scale,
            rot: self.rot.concat(&other.rot),
            disp: self.disp + other.disp,
        }
    }

    fn inverse_transform(&self) -> Option<Decomposed<P::Diff, R>> {
        if self.scale.approx_eq(&P::Scalar::zero()) {
            None
        } else {
            let s = P::Scalar::one() / self.scale;
            let r = self.rot.invert();
            let d = r.rotate_vector(self.disp.clone()) * -s;
            Some(Decomposed {
                scale: s,
                rot: r,
                disp: d,
            })
        }
    }
}

pub trait Transform2<S: BaseNum>: Transform<Point2<S>> + Into<Matrix3<S>> {}
pub trait Transform3<S: BaseNum>: Transform<Point3<S>> + Into<Matrix4<S>> {}

impl<S: BaseFloat, R: Rotation2<S>> From<Decomposed<Vector2<S>, R>> for Matrix3<S> {
    fn from(dec: Decomposed<Vector2<S>, R>) -> Matrix3<S> {
        let m: Matrix2<_> = dec.rot.into();
        let mut m: Matrix3<_> = (&m * dec.scale).into();
        m.z = dec.disp.extend(S::one());
        m
    }
}

impl<S: BaseFloat, R: Rotation3<S>> From<Decomposed<Vector3<S>, R>> for Matrix4<S> {
    fn from(dec: Decomposed<Vector3<S>, R>) -> Matrix4<S> {
        let m: Matrix3<_> = dec.rot.into();
        let mut m: Matrix4<_> = (&m * dec.scale).into();
        m.w = dec.disp.extend(S::one());
        m
    }
}

impl<S: BaseFloat, R: Rotation2<S>> Transform2<S> for Decomposed<Vector2<S>, R> {}

impl<S: BaseFloat, R: Rotation3<S>> Transform3<S> for Decomposed<Vector3<S>, R> {}
<|endoftext|>


<commit_before>//! Transports for communicating with the docker daemon

extern crate hyper;

use hyper::Client;
use hyper::client::Body;
use hyper::header;
use hyper::mime;
use self::super::{Error, Result};
use self::hyper::buffer::BufReader;
use self::hyper::header::ContentType;
use self::hyper::status::StatusCode;
use hyper::method::Method;
use std::fmt;
use std::io::Read;
use hyperlocal::DomainUrl;

pub fn tar() -> ContentType {
    ContentType(mime::Mime(mime::TopLevel::Application,
                           mime::SubLevel::Ext(String::from("tar")),
                           vec![]))
}

/// Transports are types which define the means of communication
/// with the docker daemon
pub enum Transport {
    /// A network tcp interface
    Tcp {
        client: Client,
        host: String,
    },
    /// A Unix domain socket
    Unix {
        client: Client,
        path: String,
    },
}

impl fmt::Debug for Transport {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Transport::Tcp { ref host, .. } => write!(f, "Tcp({})", host),
            Transport::Unix { ref path, .. } => write!(f, "Unix({})", path),
        }
    }
}

impl Transport {
    pub fn request<'a, B>(&'a self,
                          method: Method,
                          endpoint: &str,
                          body: Option<(B, ContentType)>)
                          -> Result<String>
        where B: Into<Body<'a>>
    {
        let mut res = try!(self.stream(method, endpoint, body));
        let mut body = String::new();
        try!(res.read_to_string(&mut body));
        debug!("{} raw response: {}", endpoint, body);
        Ok(body)
    }

    pub fn stream<'c, B>(&'c self,
                         method: Method,
                         endpoint: &str,
                         body: Option<(B, ContentType)>)
                         -> Result<Box<Read>>
        where B: Into<Body<'c>>
    {
        let headers = {
            let mut headers = header::Headers::new();
            headers.set(header::Host{ hostname: "".to_owned(), port: None });
            headers
        };
        let req = match *self {
            Transport::Tcp { ref client, ref host } => {
                client.request(method, &format!("{}{}", host, endpoint)[..])
            }
            Transport::Unix {  ref client, ref path } => {
                client.request(method, DomainUrl::new(&path, endpoint))
            }
        }.headers(headers);

        let embodied = match body {
            Some((b, c)) => req.header(c).body(b),
            _ => req,
        };
        let res = try!(embodied.send());
        match res.status {
            StatusCode::Ok | StatusCode::Created | StatusCode::SwitchingProtocols => {
                Ok(Box::new(res))
            }
            StatusCode::NoContent => Ok(Box::new(BufReader::new("".as_bytes()))),
            // todo: constantize these
            StatusCode::BadRequest => {
                Err(Error::Fault {
                    code: res.status,
                    message: "bad parameter".to_owned(),
                })
            }
            StatusCode::NotFound => {
                Err(Error::Fault {
                    code: res.status,
                    message: "not found".to_owned(),
                })
            }
            StatusCode::NotAcceptable => {
                Err(Error::Fault {
                    code: res.status,
                    message: "not acceptable".to_owned(),
                })
            }
            StatusCode::Conflict => {
                Err(Error::Fault {
                    code: res.status,
                    message: "conflict found".to_owned(),
                })
            }
            StatusCode::InternalServerError => {
                Err(Error::Fault {
                    code: res.status,
                    message: "internal server error".to_owned(),
                })
            }
            _ => unreachable!(),
        }
    }
}
<commit_msg>The transport extracts a message from the response JSON if possible<commit_after>//! Transports for communicating with the docker daemon

extern crate hyper;

use hyper::Client;
use hyper::client::Body;
use hyper::client::response::Response;
use hyper::header;
use hyper::mime;
use self::super::{Error, Result};
use self::hyper::buffer::BufReader;
use self::hyper::header::ContentType;
use self::hyper::status::StatusCode;
use hyper::method::Method;
use std::fmt;
use std::io::Read;
use hyperlocal::DomainUrl;
use rustc_serialize::json;

pub fn tar() -> ContentType {
    ContentType(mime::Mime(mime::TopLevel::Application,
                           mime::SubLevel::Ext(String::from("tar")),
                           vec![]))
}

/// Transports are types which define the means of communication
/// with the docker daemon
pub enum Transport {
    /// A network tcp interface
    Tcp {
        client: Client,
        host: String,
    },
    /// A Unix domain socket
    Unix {
        client: Client,
        path: String,
    },
}

impl fmt::Debug for Transport {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Transport::Tcp { ref host, .. } => write!(f, "Tcp({})", host),
            Transport::Unix { ref path, .. } => write!(f, "Unix({})", path),
        }
    }
}

impl Transport {
    pub fn request<'a, B>(&'a self,
                          method: Method,
                          endpoint: &str,
                          body: Option<(B, ContentType)>)
                          -> Result<String>
        where B: Into<Body<'a>>
    {
        let mut res = try!(self.stream(method, endpoint, body));
        let mut body = String::new();
        try!(res.read_to_string(&mut body));
        debug!("{} raw response: {}", endpoint, body);
        Ok(body)
    }

    pub fn stream<'c, B>(&'c self,
                         method: Method,
                         endpoint: &str,
                         body: Option<(B, ContentType)>)
                         -> Result<Box<Read>>
        where B: Into<Body<'c>>
    {
        let headers = {
            let mut headers = header::Headers::new();
            headers.set(header::Host{ hostname: "".to_owned(), port: None });
            headers
        };
        let req = match *self {
            Transport::Tcp { ref client, ref host } => {
                client.request(method, &format!("{}{}", host, endpoint)[..])
            }
            Transport::Unix {  ref client, ref path } => {
                client.request(method, DomainUrl::new(&path, endpoint))
            }
        }.headers(headers);

        let embodied = match body {
            Some((b, c)) => req.header(c).body(b),
            _ => req,
        };
        let mut res = try!(embodied.send());
        match res.status {
            StatusCode::Ok | StatusCode::Created | StatusCode::SwitchingProtocols => {
                Ok(Box::new(res))
            }
            StatusCode::NoContent => Ok(Box::new(BufReader::new("".as_bytes()))),
            // todo: constantize these
            StatusCode::BadRequest => {
                Err(Error::Fault {
                    code: res.status,
                    message: get_error_message(&mut res).unwrap_or("bad parameter".to_owned()),
                })
            }
            StatusCode::NotFound => {
                Err(Error::Fault {
                    code: res.status,
                    message: get_error_message(&mut res).unwrap_or("not found".to_owned()),
                })
            }
            StatusCode::NotAcceptable => {
                Err(Error::Fault {
                    code: res.status,
                    message: get_error_message(&mut res).unwrap_or("not acceptable".to_owned()),
                })
            }
            StatusCode::Conflict => {
                Err(Error::Fault {
                    code: res.status,
                    message: get_error_message(&mut res).unwrap_or("conflict found".to_owned()),
                })
            }
            StatusCode::InternalServerError => {
                Err(Error::Fault {
                    code: res.status,
                    message: get_error_message(&mut res).unwrap_or("internal server error".to_owned())
                })
            }
            _ => unreachable!(),
        }
    }
}

/// Extract the error message content from an HTTP response that
/// contains a Docker JSON error structure.
fn get_error_message(res: &mut Response) -> Option<String> {
    let mut output = String::new();
    if res.read_to_string(&mut output).is_ok() {
        let json_response = json::Json::from_str(output.as_str()).ok();
        let message = json_response.as_ref()
            .and_then(|x| x.as_object())
            .and_then(|x| x.get("message"))
            .and_then(|x| x.as_string())
            .map(|x| x.to_owned());

        message
    }
    else {
        None
    }
}
<|endoftext|>