<commit_before>extern crate hyper;
extern crate serde_json;

use request;

pub use types::{Account, CreateAccountResponse, EditAccountResponse};

impl Account {
    pub fn new(short_name: &str, author_name: &str, author_url: &str) -> Account {
        Account {
            short_name: short_name.to_string(),
            author_name: author_name.to_string(),
            author_url: author_url.to_string(),
            access_token: "".to_string(),
            auth_url: "".to_string(),
            page_count: 0,
        }
    }

    pub fn set_short_name(&mut self, short_name: &str) -> &mut Account {
        self.short_name = short_name.to_string();
        self
    }

    pub fn set_author_name(&mut self, author_name: &str) -> &mut Account {
        self.author_name = author_name.to_string();
        self
    }

    pub fn set_author_url(&mut self, author_url: &str) -> &mut Account {
        self.author_url = author_url.to_string();
        self
    }

    pub fn set_auth_url(&mut self, auth_url: &str) -> &mut Account {
        self.auth_url = auth_url.to_string();
        self
    }

    pub fn set_page_count(&mut self, page_count: &i32) -> &mut Account {
        self.page_count = page_count.clone();
        self
    }

    pub fn set_access_token(&mut self, access_token: &str) -> &mut Account {
        self.access_token = access_token.to_string();
        self
    }

    fn update(&mut self, new_acc: &Account) -> &mut Account {
        self.set_short_name(&new_acc.short_name);
        self.set_author_name(&new_acc.author_name);
        self.set_author_url(&new_acc.author_url);

        self
    }

    pub fn create_account(&mut self) -> Result<CreateAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/createAccount?short_name={}&author_name={}",
            self.short_name,
            self.author_name
        );
        let res_json = request::get(&url);
        let decoded: CreateAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token)
            .set_auth_url(&decoded.result.auth_url);

        Ok(decoded)
    }

    pub fn edit_accout_info(&mut self, acc: &Account) -> Result<EditAccountResponse, &str> {
        let url = String::from("https://api.telegra.ph/editAccountInfo?");
        let mut params: Vec<String> = vec![];

        let access_token = "access_token=".to_string() + &if acc.access_token.len() == 0 {
                self.access_token.clone()
            } else {
                acc.access_token.clone()
            };
        params.push(access_token);

        if acc.short_name.len() > 0 {
            let short_name = "short_name=".to_string() + &acc.short_name;
            params.push(short_name);
        }
        if acc.author_name.len() > 0 {
            let author_name = "author_name=".to_string() + &acc.author_name;
            params.push(author_name);
        }
        if acc.author_url.len() > 0 {
            let author_url = "author_url=".to_string() + &acc.author_url;
            params.push(author_url);
        }

        let url = url + &params.join("&");
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.update(&decoded.result);

        Ok(decoded)
    }

    pub fn get_account_info<'a>(access_token: &String, fields_list: &Vec<&str>) -> Result<EditAccountResponse, &'a str> {
        let fields = fields_list.iter()
            .map(|&field| "\"".to_string() + field + "\"")
            .collect::<Vec<String>>()
            .join(",");
        let fields = "[".to_string() + &fields + "]";
        let url = format!(
            "https://api.telegra.ph/getAccountInfo?access_token={}&fields={}",
            access_token,
            fields
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        Ok(decoded)
    }

        request::get(&url)
    }

}
<commit_msg>added revoke_access_token method<commit_after>extern crate hyper;
extern crate serde_json;

use request;

pub use types::{Account, CreateAccountResponse, EditAccountResponse};

impl Account {
    pub fn new(short_name: &str, author_name: &str, author_url: &str) -> Account {
        Account {
            short_name: short_name.to_string(),
            author_name: author_name.to_string(),
            author_url: author_url.to_string(),
            access_token: "".to_string(),
            auth_url: "".to_string(),
            page_count: 0,
        }
    }

    pub fn set_short_name(&mut self, short_name: &str) -> &mut Account {
        self.short_name = short_name.to_string();
        self
    }

    pub fn set_author_name(&mut self, author_name: &str) -> &mut Account {
        self.author_name = author_name.to_string();
        self
    }

    pub fn set_author_url(&mut self, author_url: &str) -> &mut Account {
        self.author_url = author_url.to_string();
        self
    }

    pub fn set_auth_url(&mut self, auth_url: &str) -> &mut Account {
        self.auth_url = auth_url.to_string();
        self
    }

    pub fn set_page_count(&mut self, page_count: &i32) -> &mut Account {
        self.page_count = page_count.clone();
        self
    }

    pub fn set_access_token(&mut self, access_token: &str) -> &mut Account {
        self.access_token = access_token.to_string();
        self
    }

    fn update(&mut self, new_acc: &Account) -> &mut Account {
        self.set_short_name(&new_acc.short_name);
        self.set_author_name(&new_acc.author_name);
        self.set_author_url(&new_acc.author_url);

        self
    }

    pub fn create_account(&mut self) -> Result<CreateAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/createAccount?short_name={}&author_name={}",
            self.short_name,
            self.author_name
        );
        let res_json = request::get(&url);
        let decoded: CreateAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token)
            .set_auth_url(&decoded.result.auth_url);

        Ok(decoded)
    }

    pub fn edit_accout_info(&mut self, acc: &Account) -> Result<EditAccountResponse, &str> {
        let url = String::from("https://api.telegra.ph/editAccountInfo?");
        let mut params: Vec<String> = vec![];

        let access_token = "access_token=".to_string() + &if acc.access_token.len() == 0 {
                self.access_token.clone()
            } else {
                acc.access_token.clone()
            };
        params.push(access_token);

        if acc.short_name.len() > 0 {
            let short_name = "short_name=".to_string() + &acc.short_name;
            params.push(short_name);
        }
        if acc.author_name.len() > 0 {
            let author_name = "author_name=".to_string() + &acc.author_name;
            params.push(author_name);
        }
        if acc.author_url.len() > 0 {
            let author_url = "author_url=".to_string() + &acc.author_url;
            params.push(author_url);
        }

        let url = url + &params.join("&");
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.update(&decoded.result);

        Ok(decoded)
    }

    pub fn get_account_info<'a>(access_token: &String, fields_list: &Vec<&str>) -> Result<EditAccountResponse, &'a str> {
        let fields = fields_list.iter()
            .map(|&field| "\"".to_string() + field + "\"")
            .collect::<Vec<String>>()
            .join(",");
        let fields = "[".to_string() + &fields + "]";
        let url = format!(
            "https://api.telegra.ph/getAccountInfo?access_token={}&fields={}",
            access_token,
            fields
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        Ok(decoded)
    }

    pub fn revoke_access_token(&mut self) -> Result<EditAccountResponse, &str> {
        let url = format!(
            "https://api.telegra.ph/revokeAccessToken?access_token={}",
            self.access_token
        );
        let res_json = request::get(&url);
        let decoded: EditAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token);

        Ok(decoded)
    }

}
<|endoftext|>


<commit_before>//! Access Control List (ACL) for shadowsocks
//!
//! This is for advance controlling server behaviors in both local and proxy servers.

use std::{
    fmt,
    fs::File,
    io::{self, BufRead, BufReader, Error, ErrorKind},
    net::{IpAddr, SocketAddr},
    path::Path,
};

use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use iprange::IpRange;
use regex::RegexSet;

use crate::{context::Context, relay::socks5::Address};

/// Strategy mode that ACL is running
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Mode {
    /// BlackList mode, rejects or bypasses all requests by default
    BlackList,
    /// WhiteList mode, accepts or proxies all requests by default
    WhiteList,
}

#[derive(Clone)]
struct Rules {
    ipv4: IpRange<Ipv4Net>,
    ipv6: IpRange<Ipv6Net>,
    rule: RegexSet,
}

impl fmt::Debug for Rules {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Rules {{ ipv4: {:?}, ipv6: {:?}, rule: [", self.ipv4, self.ipv6)?;

        let max_len = 2;
        let has_more = self.rule.len() > max_len;

        for (idx, r) in self.rule.patterns().iter().take(max_len).enumerate() {
            if idx > 0 {
                f.write_str(", ")?;
            }
            f.write_str(r)?;
        }

        if has_more {
            f.write_str(", ...")?;
        }

        f.write_str("] }")
    }
}

impl Rules {
    /// Create a new rule
    fn new(mut ipv4: IpRange<Ipv4Net>, mut ipv6: IpRange<Ipv6Net>, rule: RegexSet) -> Rules {
        // Optimization, merging networks
        ipv4.simplify();
        ipv6.simplify();

        Rules { ipv4, ipv6, rule }
    }

    /// Check if the specified address matches these rules
    fn check_address_matched(&self, addr: &Address) -> bool {
        match *addr {
            Address::SocketAddress(ref saddr) => self.check_ip_matched(saddr),
            Address::DomainNameAddress(ref domain, ..) => self.check_host_matched(domain),
        }
    }

    /// Check if the specified address matches any rules
    fn check_ip_matched(&self, addr: &SocketAddr) -> bool {
        match addr.ip() {
            IpAddr::V4(v4) => self.ipv4.contains(&v4),
            IpAddr::V6(v6) => self.ipv6.contains(&v6),
        }
    }

    /// Check if the specified host matches any rules
    fn check_host_matched(&self, host: &str) -> bool {
        self.rule.is_match(host)
    }
}

/// ACL rules
///
/// ## Sections
///
/// ACL File is formatted in sections, each section has a name with surrounded by brackets `[` and `]`
/// followed by Rules line by line.
///
/// ```plain
/// [SECTION-1]
/// RULE-1
/// RULE-2
/// RULE-3
///
/// [SECTION-2]
/// RULE-1
/// RULE-2
/// RULE-3
/// ```
///
/// Available sections are
///
/// - For local servers (`sslocal`, `ssredir`, ...)
///     * `[bypass_all]` - ACL runs in `BlackList` mode.
///     * `[proxy_all]` - ACL runs in `WhiteList` mode.
///     * `[bypass_list]` - Rules for connecting directly
///     * `[proxy_list]` - Rules for connecting through proxies
/// - For remote servers (`ssserver`)
///     * `[reject_all]` - ACL runs in `BlackList` mode.
///     * `[accept_all]` - ACL runs in `WhiteList` mode.
///     * `[black_list]` - Rules for rejecting
///     * `[white_list]` - Rules for allowing
///     * `[outbound_block_list]` - Rules for blocking outbound addresses.
///
/// ## Mode
///
/// Mode is the default ACL strategy for those addresses that are not in configuration file.
///
/// - `BlackList` - Bypasses / Rejects all addresses except those in `[proxy_list]` or `[white_list]`
/// - `WhiltList` - Proxies / Accepts all addresses except those in `[bypass_list]` or `[black_list]`
///
/// ## Rules
///
/// Rules can be either
///
/// - CIDR form network addresses, like `10.9.0.32/16`
/// - IP addresses, like `127.0.0.1` or `::1`
/// - Regular Expression for matching hosts, like `(^|\.)gmail\.com$`
#[derive(Debug, Clone)]
pub struct AccessControl {
    outbound_block: Rules,
    black_list: Rules,
    white_list: Rules,
    mode: Mode,
}

impl AccessControl {
    /// Load ACL rules from a file
    pub fn load_from_file<P: AsRef<Path>>(p: P) -> io::Result<AccessControl> {
        let fp = File::open(p)?;
        let r = BufReader::new(fp);

        let mut mode = Mode::BlackList;

        let mut outbound_block_ipv4 = IpRange::new();
        let mut outbound_block_ipv6 = IpRange::new();
        let mut outbound_block_rules = Vec::new();
        let mut bypass_ipv4 = IpRange::new();
        let mut bypass_ipv6 = IpRange::new();
        let mut bypass_rules = Vec::new();
        let mut proxy_ipv4 = IpRange::new();
        let mut proxy_ipv6 = IpRange::new();
        let mut proxy_rules = Vec::new();

        let mut curr_ipv4 = &mut bypass_ipv4;
        let mut curr_ipv6 = &mut bypass_ipv6;
        let mut curr_rules = &mut proxy_rules;

        for line in r.lines() {
            let line = line?;
            if line.is_empty() {
                continue;
            }

            // Comments
            if line.starts_with('#') {
                continue;
            }

            match line.as_str() {
                "[reject_all]" | "[bypass_all]" => {
                    mode = Mode::WhiteList;
                }
                "[accept_all]" | "[proxy_all]" => {
                    mode = Mode::BlackList;
                }
                "[outbound_block_list]" => {
                    curr_ipv4 = &mut outbound_block_ipv4;
                    curr_ipv6 = &mut outbound_block_ipv6;
                    curr_rules = &mut outbound_block_rules;
                }
                "[black_list]" | "[bypass_list]" => {
                    curr_ipv4 = &mut bypass_ipv4;
                    curr_ipv6 = &mut bypass_ipv6;
                    curr_rules = &mut bypass_rules;
                }
                "[white_list]" | "[proxy_list]" => {
                    curr_ipv4 = &mut proxy_ipv4;
                    curr_ipv6 = &mut proxy_ipv6;
                    curr_rules = &mut proxy_rules;
                }
                _ => {
                    match line.parse::<IpNet>() {
                        Ok(IpNet::V4(v4)) => {
                            curr_ipv4.add(v4);
                        }
                        Ok(IpNet::V6(v6)) => {
                            curr_ipv6.add(v6);
                        }
                        Err(..) => {
                            // Maybe it is a pure IpAddr
                            match line.parse::<IpAddr>() {
                                Ok(IpAddr::V4(v4)) => {
                                    curr_ipv4.add(Ipv4Net::from(v4));
                                }
                                Ok(IpAddr::V6(v6)) => {
                                    curr_ipv6.add(Ipv6Net::from(v6));
                                }
                                Err(..) => {
                                    // FIXME: If this line is not a valid regex, how can we know without actually compile it?
                                    curr_rules.push(line);
                                }
                            }
                        }
                    }
                }
            }
        }

        let outbound_block_regex = match RegexSet::new(outbound_block_rules) {
            Ok(r) => r,
            Err(err) => {
                let err = Error::new(ErrorKind::Other, format!("[outbound_block_list] regex error: {}", err));
                return Err(err);
            }
        };

        let bypass_regex = match RegexSet::new(bypass_rules) {
            Ok(r) => r,
            Err(err) => {
                let err = Error::new(
                    ErrorKind::Other,
                    format!("[black_list] or [bypass_list] regex error: {}", err),
                );
                return Err(err);
            }
        };

        let proxy_regex = match RegexSet::new(proxy_rules) {
            Ok(r) => r,
            Err(err) => {
                let err = Error::new(
                    ErrorKind::Other,
                    format!("[white_list] or [proxy_list] regex error: {}", err),
                );
                return Err(err);
            }
        };

        Ok(AccessControl {
            outbound_block: Rules::new(outbound_block_ipv4, outbound_block_ipv6, outbound_block_regex),
            black_list: Rules::new(bypass_ipv4, bypass_ipv6, bypass_regex),
            white_list: Rules::new(proxy_ipv4, proxy_ipv6, proxy_regex),
            mode,
        })
    }

    /// Check if domain name is in proxy_list.
    /// If so, it should be resolved from remote (for Android's DNS relay)
    pub async fn check_qname_in_proxy_list(&self, addr: &Address) -> bool {
        // Addresses in proxy_list will be proxied
        if self.white_list.check_address_matched(addr) {
            return true;
        }

        false
    }

    /// Check if target address should be bypassed (for client)
    ///
    /// FIXME: This function may perform a DNS resolution
    pub async fn check_target_bypassed(&self, context: &Context, addr: &Address) -> bool {
        // Addresses in bypass_list will be bypassed
        if self.black_list.check_address_matched(addr) {
            return true;
        }

        // Addresses in proxy_list will be proxied
        if self.white_list.check_address_matched(addr) {
            return false;
        }

        // Resolve hostname and check the list
        if cfg!(not(target_os = "android")) {
            if let Address::DomainNameAddress(ref host, port) = *addr {
                if let Ok(vaddr) = context.dns_resolve(host, port).await {
                    for addr in vaddr {
                        if self.black_list.check_ip_matched(&addr) {
                            return true;
                        }

                        if self.white_list.check_ip_matched(&addr) {
                            return false;
                        }
                    }
                }
            }
        }

        // default rule
        match self.mode {
            Mode::BlackList => false,
            Mode::WhiteList => true,
        }
    }

    /// Check if client address should be blocked (for server)
    pub fn check_client_blocked(&self, addr: &SocketAddr) -> bool {
        match self.mode {
            Mode::BlackList => {
                // Only clients in black_list will be blocked
                self.black_list.check_ip_matched(addr)
            }
            Mode::WhiteList => {
                // Only clients in white_list will be proxied
                !self.white_list.check_ip_matched(addr)
            }
        }
    }

    /// Check if outbound address is blocked (for server)
    ///
    /// NOTE: `Address::DomainName` is only validated by regex rules,
    ///       resolved addresses are checked in the `lookup_outbound_then!` macro
    pub fn check_outbound_blocked(&self, outbound: &Address) -> bool {
        self.outbound_block.check_address_matched(outbound)
    }

    /// Check resolved outbound address is blocked (for server)
    pub fn check_resolved_outbound_blocked(&self, outbound: &SocketAddr) -> bool {
        self.outbound_block.check_ip_matched(outbound)
    }
}
<commit_msg>Fixed bug, uses bypass_rules by default<commit_after>//! Access Control List (ACL) for shadowsocks
//!
//! This is for advance controlling server behaviors in both local and proxy servers.

use std::{
    fmt,
    fs::File,
    io::{self, BufRead, BufReader, Error, ErrorKind},
    net::{IpAddr, SocketAddr},
    path::Path,
};

use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use iprange::IpRange;
use regex::RegexSet;

use crate::{context::Context, relay::socks5::Address};

/// Strategy mode that ACL is running
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Mode {
    /// BlackList mode, rejects or bypasses all requests by default
    BlackList,
    /// WhiteList mode, accepts or proxies all requests by default
    WhiteList,
}

#[derive(Clone)]
struct Rules {
    ipv4: IpRange<Ipv4Net>,
    ipv6: IpRange<Ipv6Net>,
    rule: RegexSet,
}

impl fmt::Debug for Rules {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Rules {{ ipv4: {:?}, ipv6: {:?}, rule: [", self.ipv4, self.ipv6)?;

        let max_len = 2;
        let has_more = self.rule.len() > max_len;

        for (idx, r) in self.rule.patterns().iter().take(max_len).enumerate() {
            if idx > 0 {
                f.write_str(", ")?;
            }
            f.write_str(r)?;
        }

        if has_more {
            f.write_str(", ...")?;
        }

        f.write_str("] }")
    }
}

impl Rules {
    /// Create a new rule
    fn new(mut ipv4: IpRange<Ipv4Net>, mut ipv6: IpRange<Ipv6Net>, rule: RegexSet) -> Rules {
        // Optimization, merging networks
        ipv4.simplify();
        ipv6.simplify();

        Rules { ipv4, ipv6, rule }
    }

    /// Check if the specified address matches these rules
    fn check_address_matched(&self, addr: &Address) -> bool {
        match *addr {
            Address::SocketAddress(ref saddr) => self.check_ip_matched(saddr),
            Address::DomainNameAddress(ref domain, ..) => self.check_host_matched(domain),
        }
    }

    /// Check if the specified address matches any rules
    fn check_ip_matched(&self, addr: &SocketAddr) -> bool {
        match addr.ip() {
            IpAddr::V4(v4) => self.ipv4.contains(&v4),
            IpAddr::V6(v6) => self.ipv6.contains(&v6),
        }
    }

    /// Check if the specified host matches any rules
    fn check_host_matched(&self, host: &str) -> bool {
        self.rule.is_match(host)
    }
}

/// ACL rules
///
/// ## Sections
///
/// ACL File is formatted in sections, each section has a name with surrounded by brackets `[` and `]`
/// followed by Rules line by line.
///
/// ```plain
/// [SECTION-1]
/// RULE-1
/// RULE-2
/// RULE-3
///
/// [SECTION-2]
/// RULE-1
/// RULE-2
/// RULE-3
/// ```
///
/// Available sections are
///
/// - For local servers (`sslocal`, `ssredir`, ...)
///     * `[bypass_all]` - ACL runs in `BlackList` mode.
///     * `[proxy_all]` - ACL runs in `WhiteList` mode.
///     * `[bypass_list]` - Rules for connecting directly
///     * `[proxy_list]` - Rules for connecting through proxies
/// - For remote servers (`ssserver`)
///     * `[reject_all]` - ACL runs in `BlackList` mode.
///     * `[accept_all]` - ACL runs in `WhiteList` mode.
///     * `[black_list]` - Rules for rejecting
///     * `[white_list]` - Rules for allowing
///     * `[outbound_block_list]` - Rules for blocking outbound addresses.
///
/// ## Mode
///
/// Mode is the default ACL strategy for those addresses that are not in configuration file.
///
/// - `BlackList` - Bypasses / Rejects all addresses except those in `[proxy_list]` or `[white_list]`
/// - `WhiltList` - Proxies / Accepts all addresses except those in `[bypass_list]` or `[black_list]`
///
/// ## Rules
///
/// Rules can be either
///
/// - CIDR form network addresses, like `10.9.0.32/16`
/// - IP addresses, like `127.0.0.1` or `::1`
/// - Regular Expression for matching hosts, like `(^|\.)gmail\.com$`
#[derive(Debug, Clone)]
pub struct AccessControl {
    outbound_block: Rules,
    black_list: Rules,
    white_list: Rules,
    mode: Mode,
}

impl AccessControl {
    /// Load ACL rules from a file
    pub fn load_from_file<P: AsRef<Path>>(p: P) -> io::Result<AccessControl> {
        let fp = File::open(p)?;
        let r = BufReader::new(fp);

        let mut mode = Mode::BlackList;

        let mut outbound_block_ipv4 = IpRange::new();
        let mut outbound_block_ipv6 = IpRange::new();
        let mut outbound_block_rules = Vec::new();
        let mut bypass_ipv4 = IpRange::new();
        let mut bypass_ipv6 = IpRange::new();
        let mut bypass_rules = Vec::new();
        let mut proxy_ipv4 = IpRange::new();
        let mut proxy_ipv6 = IpRange::new();
        let mut proxy_rules = Vec::new();

        let mut curr_ipv4 = &mut bypass_ipv4;
        let mut curr_ipv6 = &mut bypass_ipv6;
        let mut curr_rules = &mut bypass_rules;

        for line in r.lines() {
            let line = line?;
            if line.is_empty() {
                continue;
            }

            // Comments
            if line.starts_with('#') {
                continue;
            }

            match line.as_str() {
                "[reject_all]" | "[bypass_all]" => {
                    mode = Mode::WhiteList;
                }
                "[accept_all]" | "[proxy_all]" => {
                    mode = Mode::BlackList;
                }
                "[outbound_block_list]" => {
                    curr_ipv4 = &mut outbound_block_ipv4;
                    curr_ipv6 = &mut outbound_block_ipv6;
                    curr_rules = &mut outbound_block_rules;
                }
                "[black_list]" | "[bypass_list]" => {
                    curr_ipv4 = &mut bypass_ipv4;
                    curr_ipv6 = &mut bypass_ipv6;
                    curr_rules = &mut bypass_rules;
                }
                "[white_list]" | "[proxy_list]" => {
                    curr_ipv4 = &mut proxy_ipv4;
                    curr_ipv6 = &mut proxy_ipv6;
                    curr_rules = &mut proxy_rules;
                }
                _ => {
                    match line.parse::<IpNet>() {
                        Ok(IpNet::V4(v4)) => {
                            curr_ipv4.add(v4);
                        }
                        Ok(IpNet::V6(v6)) => {
                            curr_ipv6.add(v6);
                        }
                        Err(..) => {
                            // Maybe it is a pure IpAddr
                            match line.parse::<IpAddr>() {
                                Ok(IpAddr::V4(v4)) => {
                                    curr_ipv4.add(Ipv4Net::from(v4));
                                }
                                Ok(IpAddr::V6(v6)) => {
                                    curr_ipv6.add(Ipv6Net::from(v6));
                                }
                                Err(..) => {
                                    // FIXME: If this line is not a valid regex, how can we know without actually compile it?
                                    curr_rules.push(line);
                                }
                            }
                        }
                    }
                }
            }
        }

        let outbound_block_regex = match RegexSet::new(outbound_block_rules) {
            Ok(r) => r,
            Err(err) => {
                let err = Error::new(ErrorKind::Other, format!("[outbound_block_list] regex error: {}", err));
                return Err(err);
            }
        };

        let bypass_regex = match RegexSet::new(bypass_rules) {
            Ok(r) => r,
            Err(err) => {
                let err = Error::new(
                    ErrorKind::Other,
                    format!("[black_list] or [bypass_list] regex error: {}", err),
                );
                return Err(err);
            }
        };

        let proxy_regex = match RegexSet::new(proxy_rules) {
            Ok(r) => r,
            Err(err) => {
                let err = Error::new(
                    ErrorKind::Other,
                    format!("[white_list] or [proxy_list] regex error: {}", err),
                );
                return Err(err);
            }
        };

        Ok(AccessControl {
            outbound_block: Rules::new(outbound_block_ipv4, outbound_block_ipv6, outbound_block_regex),
            black_list: Rules::new(bypass_ipv4, bypass_ipv6, bypass_regex),
            white_list: Rules::new(proxy_ipv4, proxy_ipv6, proxy_regex),
            mode,
        })
    }

    /// Check if domain name is in proxy_list.
    /// If so, it should be resolved from remote (for Android's DNS relay)
    pub async fn check_qname_in_proxy_list(&self, addr: &Address) -> bool {
        // Addresses in proxy_list will be proxied
        if self.white_list.check_address_matched(addr) {
            return true;
        }

        false
    }

    /// Check if target address should be bypassed (for client)
    ///
    /// FIXME: This function may perform a DNS resolution
    pub async fn check_target_bypassed(&self, context: &Context, addr: &Address) -> bool {
        // Addresses in bypass_list will be bypassed
        if self.black_list.check_address_matched(addr) {
            return true;
        }

        // Addresses in proxy_list will be proxied
        if self.white_list.check_address_matched(addr) {
            return false;
        }

        // Resolve hostname and check the list
        if cfg!(not(target_os = "android")) {
            if let Address::DomainNameAddress(ref host, port) = *addr {
                if let Ok(vaddr) = context.dns_resolve(host, port).await {
                    for addr in vaddr {
                        if self.black_list.check_ip_matched(&addr) {
                            return true;
                        }

                        if self.white_list.check_ip_matched(&addr) {
                            return false;
                        }
                    }
                }
            }
        }

        // default rule
        match self.mode {
            Mode::BlackList => false,
            Mode::WhiteList => true,
        }
    }

    /// Check if client address should be blocked (for server)
    pub fn check_client_blocked(&self, addr: &SocketAddr) -> bool {
        match self.mode {
            Mode::BlackList => {
                // Only clients in black_list will be blocked
                self.black_list.check_ip_matched(addr)
            }
            Mode::WhiteList => {
                // Only clients in white_list will be proxied
                !self.white_list.check_ip_matched(addr)
            }
        }
    }

    /// Check if outbound address is blocked (for server)
    ///
    /// NOTE: `Address::DomainName` is only validated by regex rules,
    ///       resolved addresses are checked in the `lookup_outbound_then!` macro
    pub fn check_outbound_blocked(&self, outbound: &Address) -> bool {
        self.outbound_block.check_address_matched(outbound)
    }

    /// Check resolved outbound address is blocked (for server)
    pub fn check_resolved_outbound_blocked(&self, outbound: &SocketAddr) -> bool {
        self.outbound_block.check_ip_matched(outbound)
    }
}
<|endoftext|>


<commit_before>use Module;
use socket::Socket;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Gain {
    LV,
    HV,
}

impl ::std::convert::Into<String> for Gain {
    fn into(self) -> String {
        let s = match self {
            Gain::LV => "LV",
            Gain::HV => "HV",
        };

        String::from(s)
    }
}

impl ::std::str::FromStr for Gain {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "LV" => Ok(Gain::LV),
            "HV" => Ok(Gain::HV),
            gain => Err(format!("Unknow gain '{}'", gain)),
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Source {
    IN1,
    IN2,
}

impl ::std::convert::Into<String> for Source {
    fn into(self) -> String {
        let s = match self {
            Source::IN1 => "SOUR1",
            Source::IN2 => "SOUR2",
        };

        String::from(s)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Decimation {
    DEC_1,
    DEC_8,
    DEC_64,
    DEC_1024,
    DEC_8192,
    DEC_65536,
}

impl ::std::convert::Into<String> for Decimation {
    fn into(self) -> String {
        let s = match self {
            Decimation::DEC_1 => "1",
            Decimation::DEC_8 => "8",
            Decimation::DEC_64 => "64",
            Decimation::DEC_1024 => "1024",
            Decimation::DEC_8192 => "8192",
            Decimation::DEC_65536 => "65536",
        };

        String::from(s)
    }
}

impl ::std::str::FromStr for Decimation {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1" => Ok(Decimation::DEC_1),
            "8" => Ok(Decimation::DEC_8),
            "64" => Ok(Decimation::DEC_64),
            "1024" => Ok(Decimation::DEC_1024),
            "8192" => Ok(Decimation::DEC_8192),
            "65536" => Ok(Decimation::DEC_65536),
            decimation => Err(format!("Unknow decimation '{}'", decimation)),
        }
    }
}

impl ::std::convert::Into<SamplingRate> for Decimation {
    fn into(self) -> SamplingRate {
        match self {
            Decimation::DEC_1 => SamplingRate::RATE_125MHz,
            Decimation::DEC_8 => SamplingRate::RATE_15_6MHz,
            Decimation::DEC_64 => SamplingRate::RATE_1_9MHz,
            Decimation::DEC_1024 => SamplingRate::RATE_103_8kHz,
            Decimation::DEC_8192 => SamplingRate::RATE_15_2kHz,
            Decimation::DEC_65536 => SamplingRate::RATE_1_9kHz,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SamplingRate {
    RATE_125MHz,
    RATE_15_6MHz,
    RATE_1_9MHz,
    RATE_103_8kHz,
    RATE_15_2kHz,
    RATE_1_9kHz,
}

impl SamplingRate {
    pub fn get_buffer_duration(self) -> ::std::time::Duration {
        let (s, ns) = match self {
            SamplingRate::RATE_125MHz => (0, 131_072),
            SamplingRate::RATE_15_6MHz => (0, 1_049_000),
            SamplingRate::RATE_1_9MHz => (0, 8_389_000),
            SamplingRate::RATE_103_8kHz => (0, 134_218_000),
            SamplingRate::RATE_15_2kHz => (1, 740_000_000),
            SamplingRate::RATE_1_9kHz => (8, 590_000_000),
        };

        ::std::time::Duration::new(s, ns)
    }
}

impl ::std::fmt::Display for SamplingRate {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &SamplingRate::RATE_125MHz => "125 MHz",
            &SamplingRate::RATE_15_6MHz => "15.6 MHz",
            &SamplingRate::RATE_1_9MHz => "1.9 MHz",
            &SamplingRate::RATE_103_8kHz => "103.8 kHz",
            &SamplingRate::RATE_15_2kHz => "15.2 kHz",
            &SamplingRate::RATE_1_9kHz => "1.9 kHz",
        };

        write!(f, "{}", display)
    }
}

impl ::std::convert::Into<Decimation> for SamplingRate {
    fn into(self) -> Decimation {
        match self {
            SamplingRate::RATE_125MHz => Decimation::DEC_1,
            SamplingRate::RATE_15_6MHz => Decimation::DEC_8,
            SamplingRate::RATE_1_9MHz => Decimation::DEC_64,
            SamplingRate::RATE_103_8kHz => Decimation::DEC_1024,
            SamplingRate::RATE_15_2kHz => Decimation::DEC_8192,
            SamplingRate::RATE_1_9kHz => Decimation::DEC_65536,
        }
    }
}

impl ::std::convert::Into<String> for SamplingRate {
    fn into(self) -> String {
        let s = match self {
            SamplingRate::RATE_125MHz => "125MHz",
            SamplingRate::RATE_15_6MHz => "15_6MHz",
            SamplingRate::RATE_1_9MHz => "1_9MHz",
            SamplingRate::RATE_103_8kHz => "103_8kHz",
            SamplingRate::RATE_15_2kHz => "15_2kHz",
            SamplingRate::RATE_1_9kHz => "1_9kHz",
        };

        String::from(s)
    }
}

impl ::std::str::FromStr for SamplingRate {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "125000000 Hz" => Ok(SamplingRate::RATE_125MHz),
            "15600000 Hz" => Ok(SamplingRate::RATE_15_6MHz),
            "1900000 Hz" => Ok(SamplingRate::RATE_1_9MHz),
            "103800 Hz" => Ok(SamplingRate::RATE_103_8kHz),
            "15200 Hz" => Ok(SamplingRate::RATE_15_2kHz),
            "1900 Hz" => Ok(SamplingRate::RATE_1_9kHz),
            rate => Err(format!("Unknow sampling rate {}", rate)),
        }
    }
}

#[derive(Clone)]
pub struct Acquire {
    socket: ::std::cell::RefCell<Socket>,
    started: bool,
}

impl ::Module for Acquire {
    fn get_socket<'a>(&'a self) -> ::std::cell::RefMut<'a, ::socket::Socket> {
        self.socket.borrow_mut()
    }
}

impl Acquire {
    pub fn new(socket: Socket) -> Self {
        Acquire {
            socket: ::std::cell::RefCell::new(socket),
            started: false,
        }
    }

    /**
     * Starts acquisition.
     */
    pub fn start(&mut self) {
        self.send("ACQ:START");
        self.started = true;
    }

    /**
     * Stops acquisition.
     */
    pub fn stop(&mut self) {
        self.send("ACQ:STOP");
        self.started = false;
    }

    pub fn is_started(&self) -> bool {
        self.started
    }

    /**
     * Stops acquisition and sets all parameters to default values.
     */
    pub fn reset(&self) {
        self.send("ACQ:RST");
    }

    /**
     * Set decimation factor.
     */
    pub fn set_decimation(&self, decimation: Decimation) {
        self.send(format!("ACQ:DEC {}", Into::<String>::into(decimation)));
    }

    /**
     * Get decimation factor.
     */
    pub fn get_decimation(&self) -> Result<Decimation, String> {
        self.send("ACQ:DEC?");

        self.receive()
            .parse()
    }

    /**
     * Get sampling rate.
     *
     * # Panics
     *
     * Calling this command makes buffer overflow.
     * See https://github.com/RedPitaya/RedPitaya/pull/110
     */
    pub fn get_sampling_rate(&self) -> Result<SamplingRate, String> {
        self.send("ACQ:SRAT?");

        self.receive()
            .parse()
    }

    /**
     * Enable averaging.
     */
    pub fn enable_average(&self) {
        self.send("ACQ:AVG ON");
    }

    /**
     * Disable averaging.
     */
    pub fn disable_average(&self) {
        self.send("ACQ:AVG OFF");
    }

    /**
     * Get averaging status.
     */
    pub fn is_average_enabled(&self) -> bool {
        self.send("ACQ:AVG?");

        let message = self.receive();

        match message.as_str() {
            "ON" => true,
            _ => false,
        }
    }

    /**
     * Set gain settings to HIGH or LOW.
     *
     * This gain is referring to jumper settings on Red Pitaya fast analog inputs.
     */
    pub fn set_gain(&self, source: Source, gain: Gain) {
        self.send(format!("ACQ:{}:GAIN {}", Into::<String>::into(source), Into::<String>::into(gain)));
    }

    /**
     * Get gain settings to HIGH or LOW.
     */
    pub fn get_gain(&self, source: Source) -> Result<Gain, String> {
        self.send(format!("ACQ:{}:GAIN?", Into::<String>::into(source)));

        self.receive()
            .parse()
    }
}

#[cfg(test)]
mod test {
    macro_rules! acquire_assert {
        ($f:ident, $e:expr) => {
            let (rx, acquire) = create_acquire();

            acquire.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_sampling_rate_get_buffer_duration() {
        let duration = ::std::time::Duration::new(8, 590_000_000);

        assert_eq!(duration, ::acquire::SamplingRate::RATE_1_9kHz.get_buffer_duration());
    }

    #[test]
    fn test_start() {
        let (rx, mut acquire) = create_acquire();

        acquire.start();
        assert_eq!("ACQ:START\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_stop() {
        let (rx, mut acquire) = create_acquire();

        acquire.stop();
        assert_eq!("ACQ:STOP\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_is_started() {
        let (_, mut acquire) = create_acquire();

        assert_eq!(acquire.is_started(), false);
        acquire.start();
        assert_eq!(acquire.is_started(), true);
        acquire.stop();
        assert_eq!(acquire.is_started(), false);
    }

    #[test]
    fn test_reset() {
        acquire_assert!(reset, "ACQ:RST\r\n");
    }

    #[test]
    fn test_set_decimation() {
        let (rx, acquire) = create_acquire();

        acquire.set_decimation(::acquire::Decimation::DEC_8);
        assert_eq!("ACQ:DEC 8\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_decimation() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_decimation(), Ok(::acquire::Decimation::DEC_1));
    }

    #[test]
    fn test_get_sampling_rate() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_sampling_rate(), Ok(::acquire::SamplingRate::RATE_125MHz));
    }

    #[test]
    fn test_enable_average() {
        acquire_assert!(enable_average, "ACQ:AVG ON\r\n");
    }

    #[test]
    fn test_disable_average() {
        acquire_assert!(disable_average, "ACQ:AVG OFF\r\n");
    }

    #[test]
    fn test_is_average_enabled() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.is_average_enabled(), true);
    }

    #[test]
    fn test_set_gain() {
        let (rx, acquire) = create_acquire();

        acquire.set_gain(::acquire::Source::IN1, ::acquire::Gain::LV);
        assert_eq!("ACQ:SOUR1:GAIN LV\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_gain() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_gain(::acquire::Source::IN1), Ok(::acquire::Gain::HV));
    }

    fn create_acquire() -> (::std::sync::mpsc::Receiver<String>, ::acquire::Acquire) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::acquire::Acquire::new(socket))
    }
}
<commit_msg>[acquire] Implement Display for acquire::Gain<commit_after>use Module;
use socket::Socket;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Gain {
    LV,
    HV,
}

impl ::std::convert::Into<String> for Gain {
    fn into(self) -> String {
        let s = match self {
            Gain::LV => "LV",
            Gain::HV => "HV",
        };

        String::from(s)
    }
}

impl ::std::str::FromStr for Gain {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "LV" => Ok(Gain::LV),
            "HV" => Ok(Gain::HV),
            gain => Err(format!("Unknow gain '{}'", gain)),
        }
    }
}

impl ::std::fmt::Display for Gain {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Gain::LV => "LV",
            &Gain::HV => "HV",
        };

        write!(f, "{}", display)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Source {
    IN1,
    IN2,
}

impl ::std::convert::Into<String> for Source {
    fn into(self) -> String {
        let s = match self {
            Source::IN1 => "SOUR1",
            Source::IN2 => "SOUR2",
        };

        String::from(s)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Decimation {
    DEC_1,
    DEC_8,
    DEC_64,
    DEC_1024,
    DEC_8192,
    DEC_65536,
}

impl ::std::convert::Into<String> for Decimation {
    fn into(self) -> String {
        let s = match self {
            Decimation::DEC_1 => "1",
            Decimation::DEC_8 => "8",
            Decimation::DEC_64 => "64",
            Decimation::DEC_1024 => "1024",
            Decimation::DEC_8192 => "8192",
            Decimation::DEC_65536 => "65536",
        };

        String::from(s)
    }
}

impl ::std::str::FromStr for Decimation {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "1" => Ok(Decimation::DEC_1),
            "8" => Ok(Decimation::DEC_8),
            "64" => Ok(Decimation::DEC_64),
            "1024" => Ok(Decimation::DEC_1024),
            "8192" => Ok(Decimation::DEC_8192),
            "65536" => Ok(Decimation::DEC_65536),
            decimation => Err(format!("Unknow decimation '{}'", decimation)),
        }
    }
}

impl ::std::convert::Into<SamplingRate> for Decimation {
    fn into(self) -> SamplingRate {
        match self {
            Decimation::DEC_1 => SamplingRate::RATE_125MHz,
            Decimation::DEC_8 => SamplingRate::RATE_15_6MHz,
            Decimation::DEC_64 => SamplingRate::RATE_1_9MHz,
            Decimation::DEC_1024 => SamplingRate::RATE_103_8kHz,
            Decimation::DEC_8192 => SamplingRate::RATE_15_2kHz,
            Decimation::DEC_65536 => SamplingRate::RATE_1_9kHz,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SamplingRate {
    RATE_125MHz,
    RATE_15_6MHz,
    RATE_1_9MHz,
    RATE_103_8kHz,
    RATE_15_2kHz,
    RATE_1_9kHz,
}

impl SamplingRate {
    pub fn get_buffer_duration(self) -> ::std::time::Duration {
        let (s, ns) = match self {
            SamplingRate::RATE_125MHz => (0, 131_072),
            SamplingRate::RATE_15_6MHz => (0, 1_049_000),
            SamplingRate::RATE_1_9MHz => (0, 8_389_000),
            SamplingRate::RATE_103_8kHz => (0, 134_218_000),
            SamplingRate::RATE_15_2kHz => (1, 740_000_000),
            SamplingRate::RATE_1_9kHz => (8, 590_000_000),
        };

        ::std::time::Duration::new(s, ns)
    }
}

impl ::std::fmt::Display for SamplingRate {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &SamplingRate::RATE_125MHz => "125 MHz",
            &SamplingRate::RATE_15_6MHz => "15.6 MHz",
            &SamplingRate::RATE_1_9MHz => "1.9 MHz",
            &SamplingRate::RATE_103_8kHz => "103.8 kHz",
            &SamplingRate::RATE_15_2kHz => "15.2 kHz",
            &SamplingRate::RATE_1_9kHz => "1.9 kHz",
        };

        write!(f, "{}", display)
    }
}

impl ::std::convert::Into<Decimation> for SamplingRate {
    fn into(self) -> Decimation {
        match self {
            SamplingRate::RATE_125MHz => Decimation::DEC_1,
            SamplingRate::RATE_15_6MHz => Decimation::DEC_8,
            SamplingRate::RATE_1_9MHz => Decimation::DEC_64,
            SamplingRate::RATE_103_8kHz => Decimation::DEC_1024,
            SamplingRate::RATE_15_2kHz => Decimation::DEC_8192,
            SamplingRate::RATE_1_9kHz => Decimation::DEC_65536,
        }
    }
}

impl ::std::convert::Into<String> for SamplingRate {
    fn into(self) -> String {
        let s = match self {
            SamplingRate::RATE_125MHz => "125MHz",
            SamplingRate::RATE_15_6MHz => "15_6MHz",
            SamplingRate::RATE_1_9MHz => "1_9MHz",
            SamplingRate::RATE_103_8kHz => "103_8kHz",
            SamplingRate::RATE_15_2kHz => "15_2kHz",
            SamplingRate::RATE_1_9kHz => "1_9kHz",
        };

        String::from(s)
    }
}

impl ::std::str::FromStr for SamplingRate {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "125000000 Hz" => Ok(SamplingRate::RATE_125MHz),
            "15600000 Hz" => Ok(SamplingRate::RATE_15_6MHz),
            "1900000 Hz" => Ok(SamplingRate::RATE_1_9MHz),
            "103800 Hz" => Ok(SamplingRate::RATE_103_8kHz),
            "15200 Hz" => Ok(SamplingRate::RATE_15_2kHz),
            "1900 Hz" => Ok(SamplingRate::RATE_1_9kHz),
            rate => Err(format!("Unknow sampling rate {}", rate)),
        }
    }
}

#[derive(Clone)]
pub struct Acquire {
    socket: ::std::cell::RefCell<Socket>,
    started: bool,
}

impl ::Module for Acquire {
    fn get_socket<'a>(&'a self) -> ::std::cell::RefMut<'a, ::socket::Socket> {
        self.socket.borrow_mut()
    }
}

impl Acquire {
    pub fn new(socket: Socket) -> Self {
        Acquire {
            socket: ::std::cell::RefCell::new(socket),
            started: false,
        }
    }

    /**
     * Starts acquisition.
     */
    pub fn start(&mut self) {
        self.send("ACQ:START");
        self.started = true;
    }

    /**
     * Stops acquisition.
     */
    pub fn stop(&mut self) {
        self.send("ACQ:STOP");
        self.started = false;
    }

    pub fn is_started(&self) -> bool {
        self.started
    }

    /**
     * Stops acquisition and sets all parameters to default values.
     */
    pub fn reset(&self) {
        self.send("ACQ:RST");
    }

    /**
     * Set decimation factor.
     */
    pub fn set_decimation(&self, decimation: Decimation) {
        self.send(format!("ACQ:DEC {}", Into::<String>::into(decimation)));
    }

    /**
     * Get decimation factor.
     */
    pub fn get_decimation(&self) -> Result<Decimation, String> {
        self.send("ACQ:DEC?");

        self.receive()
            .parse()
    }

    /**
     * Get sampling rate.
     *
     * # Panics
     *
     * Calling this command makes buffer overflow.
     * See https://github.com/RedPitaya/RedPitaya/pull/110
     */
    pub fn get_sampling_rate(&self) -> Result<SamplingRate, String> {
        self.send("ACQ:SRAT?");

        self.receive()
            .parse()
    }

    /**
     * Enable averaging.
     */
    pub fn enable_average(&self) {
        self.send("ACQ:AVG ON");
    }

    /**
     * Disable averaging.
     */
    pub fn disable_average(&self) {
        self.send("ACQ:AVG OFF");
    }

    /**
     * Get averaging status.
     */
    pub fn is_average_enabled(&self) -> bool {
        self.send("ACQ:AVG?");

        let message = self.receive();

        match message.as_str() {
            "ON" => true,
            _ => false,
        }
    }

    /**
     * Set gain settings to HIGH or LOW.
     *
     * This gain is referring to jumper settings on Red Pitaya fast analog inputs.
     */
    pub fn set_gain(&self, source: Source, gain: Gain) {
        self.send(format!("ACQ:{}:GAIN {}", Into::<String>::into(source), Into::<String>::into(gain)));
    }

    /**
     * Get gain settings to HIGH or LOW.
     */
    pub fn get_gain(&self, source: Source) -> Result<Gain, String> {
        self.send(format!("ACQ:{}:GAIN?", Into::<String>::into(source)));

        self.receive()
            .parse()
    }
}

#[cfg(test)]
mod test {
    macro_rules! acquire_assert {
        ($f:ident, $e:expr) => {
            let (rx, acquire) = create_acquire();

            acquire.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_sampling_rate_get_buffer_duration() {
        let duration = ::std::time::Duration::new(8, 590_000_000);

        assert_eq!(duration, ::acquire::SamplingRate::RATE_1_9kHz.get_buffer_duration());
    }

    #[test]
    fn test_start() {
        let (rx, mut acquire) = create_acquire();

        acquire.start();
        assert_eq!("ACQ:START\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_stop() {
        let (rx, mut acquire) = create_acquire();

        acquire.stop();
        assert_eq!("ACQ:STOP\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_is_started() {
        let (_, mut acquire) = create_acquire();

        assert_eq!(acquire.is_started(), false);
        acquire.start();
        assert_eq!(acquire.is_started(), true);
        acquire.stop();
        assert_eq!(acquire.is_started(), false);
    }

    #[test]
    fn test_reset() {
        acquire_assert!(reset, "ACQ:RST\r\n");
    }

    #[test]
    fn test_set_decimation() {
        let (rx, acquire) = create_acquire();

        acquire.set_decimation(::acquire::Decimation::DEC_8);
        assert_eq!("ACQ:DEC 8\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_decimation() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_decimation(), Ok(::acquire::Decimation::DEC_1));
    }

    #[test]
    fn test_get_sampling_rate() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_sampling_rate(), Ok(::acquire::SamplingRate::RATE_125MHz));
    }

    #[test]
    fn test_enable_average() {
        acquire_assert!(enable_average, "ACQ:AVG ON\r\n");
    }

    #[test]
    fn test_disable_average() {
        acquire_assert!(disable_average, "ACQ:AVG OFF\r\n");
    }

    #[test]
    fn test_is_average_enabled() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.is_average_enabled(), true);
    }

    #[test]
    fn test_set_gain() {
        let (rx, acquire) = create_acquire();

        acquire.set_gain(::acquire::Source::IN1, ::acquire::Gain::LV);
        assert_eq!("ACQ:SOUR1:GAIN LV\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_gain() {
        let (_, acquire) = create_acquire();

        assert_eq!(acquire.get_gain(::acquire::Source::IN1), Ok(::acquire::Gain::HV));
    }

    fn create_acquire() -> (::std::sync::mpsc::Receiver<String>, ::acquire::Acquire) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::acquire::Acquire::new(socket))
    }
}
<|endoftext|>


<commit_before>extern crate rosc;

use std::{net, env, process};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage ./receive IP:PORT");
        process::exit(1);
    }

    match rosc::utils::parse_ip_and_port(&args[1]) {
        Ok((ip, port)) => {
            let sock = match net::UdpSocket::bind((ip, port)) {
                Ok(sock_ok) => sock_ok,
                Err(e) => {
                    println!("Could not bind socket: {}", e);
                    process::exit(1);
                }
            };
            println!("Listening to {}:{}", ip, port);

            let mut buf: [u8; rosc::decoder::MTP] = [0u8; rosc::decoder::MTP];

            loop {
                match sock.recv_from(&mut buf) {
                    Ok((size, addr)) => {
                        println!("addr: {}, size: {}", addr, size);
                        rosc::decoder::decode(&mut buf);
                    }
                    Err(e) => {
                        println!("Error receiving from socket: {}", e);
                        break;
                    }
                }
            }

            drop(sock);
        }
        Err(e) => println!("{}", e),
    }
}
<commit_msg>Updated and simplified receiver example<commit_after>extern crate rosc;

use std::{net, env, process};
use rosc::types::{OscPacket};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage ./receive IP:PORT");
        process::exit(1);
    }

    let (ip, port) = rosc::utils::parse_ip_and_port(&args[1]).unwrap();
    let sock = net::UdpSocket::bind((ip, port)).unwrap();
    println!("Listening to {}:{}", ip, port);

    let mut buf = [0u8; rosc::decoder::MTP];

    loop {
        match sock.recv_from(&mut buf) {
            Ok((size, addr)) => {
                println!("Received packet with size {} from: {}", size, addr);
                let packet = rosc::decoder::decode(&mut buf).unwrap();
                handle_packet(packet);
            }
            Err(e) => {
                println!("Error receiving from socket: {}", e);
                break;
            }
        }
    }

    drop(sock);
}

fn handle_packet(packet: OscPacket) {
    match packet {
        OscPacket::Message(msg) => {
            println!("OSC address: {}", msg.addr);
            match msg.args {
                Some(args) => {
                    println!("OSC arguments: {:?}", args);
                }
                None => println!("No arguments in message."),
            }
        }
        _ => (),
    }
}
<|endoftext|>


<commit_before>extern crate polydraw;
extern crate toml;

use polydraw::{Renderer, Application, Frame};
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

const NODE_DEFS: &'static str = r#"

   [frame]
   type = "frame"

   [poly-points]
   type = "[(i64, i64)]"
   data = [ [0, 0], [90, 1200], [261, 1735], [1443, 410] ]

   [translate-point]
   type = "pair"
   data = [
      { from = "frame" },
      { type = "i64", data = 0 } ]

   [add-operator]
   type = "add"
   data = [
      { from = "poly-points" },
      { from = "translate-point" } ]

   [poly]
   type = "poly"
   data = [
      { from = "add-operator" },
      { type = "(u8, u8, u8)", data = [0, 127, 255] } ]

   [poly-list]
   type = "list"
   data = [
      { from = "poly" } ]

   [layer]
   type = "layer"
   data = [
      { from = "poly-list" } ]

   [doc]
   type = "doc"
   data = [
      { from = "layer" } ]

"#;

type I64I64 = (i64, i64);
type U8U8U8 = (u8, u8, u8);
type VVI64I64 = Vec<Vec<I64I64>>;

#[derive(Debug)]
#[allow(dead_code)]
enum Data {
   None,
   I64(i64),
   F64(f64),
   I64I64(I64I64),
   U8U8U8(U8U8U8),
   VVI64I64(VVI64I64),
}

const NONE: Data = Data::None;

trait Node {
   fn process(&self, args: &[&Data]) -> Data;
}

struct AddNode {
   first: Data,
   second: Data,
}

impl AddNode {
   #[inline]
   fn new(first: Data, second: Data) -> Self {
      AddNode {
         first: first,
         second: second,
      }
   }
}

impl Node for AddNode {
   #[inline]
   fn process(&self, args: &[&Data]) -> Data {
      let in1 = in_value(args, 0, &self.first);
      let in2 = in_value(args, 1, &self.second);

      match (in1, in2) {
         (&Data::I64(ref v1), &Data::I64(ref v2)) => <(i64, i64)>::add(v1, v2),

         (&Data::F64(ref v1), &Data::I64(ref v2)) => <(f64, i64)>::add(v1, v2),
         (&Data::I64(ref v1), &Data::F64(ref v2)) => <(f64, i64)>::add(v2, v1),

         (&Data::I64I64(ref v1), &Data::I64(ref v2)) => <(I64I64, i64)>::add(v1, v2),
         (&Data::I64(ref v1), &Data::I64I64(ref v2)) => <(I64I64, i64)>::add(v2, v1),

         (&Data::VVI64I64(ref v1), &Data::I64I64(ref v2)) => <(VVI64I64, I64I64)>::add(v1, v2),
         (&Data::I64I64(ref v1), &Data::VVI64I64(ref v2)) => <(VVI64I64, I64I64)>::add(v2, v1),

         _ => NONE
      }
   }
}

trait Add<T1, T2> {
   fn add(v1: &T1, v2: &T2) -> Data;
}

impl Add<i64, i64> for (i64, i64) {
   #[inline]
   fn add(v1: &i64, v2: &i64) -> Data {
      Data::I64(*v1 + *v2)
   }
}

impl Add<f64, i64> for (f64, i64) {
   #[inline]
   fn add(v1: &f64, v2: &i64) -> Data {
      Data::F64(*v1 + *v2 as f64)
   }
}

impl Add<I64I64, i64> for (I64I64, i64) {
   #[inline]
   fn add(v1: &I64I64, v2: &i64) -> Data {
      Data::I64I64((v1.0 + *v2, v1.1 + *v2))
   }
}

impl Add<VVI64I64, I64I64> for (VVI64I64, I64I64) {
   #[inline]
   fn add(v1: &VVI64I64, v2: &I64I64) -> Data {
      let mut outer = Vec::with_capacity(v1.len());

      for src in v1 {
         let mut inner = Vec::with_capacity(src.len());

         for tuple in src {
            inner.push((tuple.0 + v2.0, tuple.1 + v2.1));
         }

         outer.push(inner);
      }

      Data::VVI64I64(outer)
   }
}

#[inline]
fn in_value<'a>(args: &'a[&'a Data], index: usize, initial: &'a Data) -> &'a Data {
   match args.get(index) {
      Some(passed) => match *passed {
         &Data::None => initial,
         _ => *passed
      },
      None => initial
   }
}

#[inline]
fn poly_from_data(data: &VVI64I64) -> Poly {
   let outer = points_from_coords(&data[0]);

   let mut inner = Vec::new();

   for inner_data in &data[1..] {
      inner.push(
         points_from_coords(inner_data)
      );
   }

   let poly = Poly::new_with_holes(
      outer, inner, RGB::new(81, 180, 200),
   );

   poly
}

#[inline]
fn points_from_coords(coords: &[(i64, i64)]) -> Vec<Point> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(Point::new(x + 120, y + 120))
   }

   points
}

struct NodeRenderer {
   renderer: DevelRenderer,
   frame: i64,
}

impl NodeRenderer {
   #[inline]
   pub fn new() -> Self {
      NodeRenderer {
         renderer: DevelRenderer::new(Scene::new()),
         frame: 0,
      }
   }
}

impl Renderer for NodeRenderer {
   #[inline]
   fn init(&mut self, width: u32, height: u32) {
      let mut parser = NodeParser::new();
      parser.parse(NODE_DEFS);

      self.renderer.init(width, height);
   }

   #[inline]
   fn render(&mut self, frame: &mut Frame) {
      let mut scene = Scene::new();

      let source = vec![vec![
         (90, 1200),
         (261, 1735),
         (1443, 410),
         (493, 174),
      ]];

      let add = AddNode::new(NONE, NONE);

      let destination = add.process(
         &[&Data::VVI64I64(source), &Data::I64I64((self.frame, 0))]
      );

      match destination {
         Data::VVI64I64(data) => scene.push(poly_from_data(&data)),
         _ => {}
      }

      self.renderer.set_scene(scene);

      self.renderer.render(frame);

      self.frame += 1;
   }
}

struct NodeParser;

impl NodeParser {
   fn new() -> Self {
      NodeParser {}
   }

   fn parse(&mut self, node_defs: &str) {
      let mut parser = toml::Parser::new(node_defs);

      match parser.parse() {
         Some(everything) => {
            for (node_id, value) in everything.iter() {
               match value {
                  &toml::Value::Table(ref node_table) => {
                     process_node(node_id, node_table);
                  },
                  _ => {
                     println!("`{}` is not a table ", node_id);
                  }
               }
            }
         },
         None => {
            println!("parse errors: {:?}", parser.errors);
         }
      }
   }

}

fn process_node(node_id: &str, node_table: &toml::Table) {
   let node_type = extract_node_type(node_id, node_table);

   println!("TYPE: {}", node_type);

   println!("{:?}", node_table);

   match node_type.as_ref() {
      "add" => create_add_node(node_id, node_table),
      "pair" => create_pair_node(node_id, node_table),
      _ => {
         println!("Unknown node type {:?} for: {}", node_type, node_id);
      }
   }

   println!("");
}

fn create_add_node(node_id: &str, node_table: &toml::Table) {
   println!("ADD NODE");

   let data_value = extract_data_value(node_id, node_table);

   println!("DATA {:?}", data_value);
}

fn create_pair_node(node_id: &str, node_table: &toml::Table) {
   println!("PAIR NODE");

   let data_value = extract_data_value(node_id, node_table);

   println!("DATA {:?}", data_value);

   let defaults = to_defaults(node_id, data_value);

   println!("defaults: {:?}", defaults);
}

fn extract_node_type<'a>(node_id: &str, node_table: &'a toml::Table) -> &'a str {
   match node_table.get("type") {
      Some(type_value) => {
         match type_value {
            &toml::Value::String(ref node_type) => node_type,
            _ => {
               panic!("node type not a string: {}", node_id);
            }
         }
      },
      None => {
         panic!("node without type: {}", node_id);
      }
   }
}

fn extract_data_value<'a>(node_id: &str, node_table: &'a toml::Table) -> &'a toml::Value {
   match node_table.get("data") {
      Some(data_value) => {
         data_value
      },
      None => {
         panic!("node without data: {}", node_id);
      }
   }
}

fn to_defaults(node_id: &str, data: &toml::Value) -> Vec<Data> {
   let array = match data {
      &toml::Value::Array(ref array) => array,
      _ => {
         panic!("data is not an array: {}", node_id);
      }
   };

   let mut result = Vec::with_capacity(array.len());

   for item in array.iter() {
      let table = match item {
         &toml::Value::Table(ref table) => table,
         _ => {
            panic!("value is not a table {:?}: {}", item, node_id);
         }
      };

      println!("item: {:?}", table);

      if table.get("from").is_some() {
         // Connection from a different node
         result.push(Data::None);
         continue;
      }

      result.push(
         extract_table_data(node_id, table)
      );
   }

   result
}

fn extract_table_data(node_id: &str, table: &toml::Table) -> Data {
   let type_str = match table.get("type") {
      Some(type_data) => {
         match type_data {
            &toml::Value::String(ref type_str) => type_str,
            _ => {
               panic!("Type not a string {:?}: {}", type_data, node_id);
            }
         }
      },
      None => {
         panic!("value table without a type {:?}: {}", table, node_id);
      }
   };

   let data = match table.get("data") {
      Some(data) => data,
      None => {
         panic!("value table without a data {:?}: {}", table, node_id);
      }
   };

   match type_str.as_ref() {
      "i64" => toml_to_i64(node_id, data),
      _ => {
         panic!("Unknown data type {}: {}", type_str, node_id);
      }
   }
}

fn toml_to_i64(node_id: &str, data: &toml::Value) -> Data {
   match data {
      &toml::Value::Integer(integer) => Data::I64(integer),
      _ => {
         panic!("Value not an integer {:?}: {}", data, node_id);
      }
   }
}

fn main() {
   let mut renderer = NodeRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Nodes")
      .size(1200, 800)
      .run();
}

<commit_msg>JoinNode definition<commit_after>extern crate polydraw;
extern crate toml;

use polydraw::{Renderer, Application, Frame};
use polydraw::devel::{Scene, Poly, DevelRenderer};
use polydraw::geom::point::Point;
use polydraw::draw::RGB;

const NODE_DEFS: &'static str = r#"

   [frame]
   type = "frame"

   [poly-points]
   type = "[(i64, i64)]"
   data = [ [0, 0], [90, 1200], [261, 1735], [1443, 410] ]

   [translate-point]
   type = "join"
   data = [
      { from = "frame" },
      { type = "i64", data = 0 } ]

   [add-operator]
   type = "add"
   data = [
      { from = "poly-points" },
      { from = "translate-point" } ]

   [poly]
   type = "poly"
   data = [
      { from = "add-operator" },
      { type = "(u8, u8, u8)", data = [0, 127, 255] } ]

   [poly-list]
   type = "list"
   data = [
      { from = "poly" } ]

   [layer]
   type = "layer"
   data = [
      { from = "poly-list" } ]

   [doc]
   type = "doc"
   data = [
      { from = "layer" } ]

"#;

type I64I64 = (i64, i64);
type U8U8U8 = (u8, u8, u8);
type VVI64I64 = Vec<Vec<I64I64>>;

#[derive(Debug)]
#[allow(dead_code)]
enum Data {
   None,
   U8(u8),
   I64(i64),
   F64(f64),
   I64I64(I64I64),
   U8U8U8(U8U8U8),
   VVI64I64(VVI64I64),
}

const NONE: Data = Data::None;

trait Node {
   fn process(&self, args: &[&Data]) -> Data;
}

struct AddNode {
   defaults: Vec<Data>,
}

impl AddNode {
   #[inline]
   fn new(defaults: Vec<Data>) -> Self {
      AddNode {
         defaults: defaults,
      }
   }
}

impl Node for AddNode {
   #[inline]
   fn process(&self, args: &[&Data]) -> Data {
      let in1 = in_value(args, 0, &self.defaults[0]);
      let in2 = in_value(args, 1, &self.defaults[1]);

      match (in1, in2) {
         (&Data::I64(ref v1), &Data::I64(ref v2)) => <(i64, i64)>::add(v1, v2),

         (&Data::F64(ref v1), &Data::I64(ref v2)) => <(f64, i64)>::add(v1, v2),
         (&Data::I64(ref v1), &Data::F64(ref v2)) => <(f64, i64)>::add(v2, v1),

         (&Data::I64I64(ref v1), &Data::I64(ref v2)) => <(I64I64, i64)>::add(v1, v2),
         (&Data::I64(ref v1), &Data::I64I64(ref v2)) => <(I64I64, i64)>::add(v2, v1),

         (&Data::VVI64I64(ref v1), &Data::I64I64(ref v2)) => <(VVI64I64, I64I64)>::add(v1, v2),
         (&Data::I64I64(ref v1), &Data::VVI64I64(ref v2)) => <(VVI64I64, I64I64)>::add(v2, v1),

         _ => NONE
      }
   }
}

trait Add<T1, T2> {
   fn add(v1: &T1, v2: &T2) -> Data;
}

impl Add<i64, i64> for (i64, i64) {
   #[inline]
   fn add(v1: &i64, v2: &i64) -> Data {
      Data::I64(*v1 + *v2)
   }
}

impl Add<f64, i64> for (f64, i64) {
   #[inline]
   fn add(v1: &f64, v2: &i64) -> Data {
      Data::F64(*v1 + *v2 as f64)
   }
}

impl Add<I64I64, i64> for (I64I64, i64) {
   #[inline]
   fn add(v1: &I64I64, v2: &i64) -> Data {
      Data::I64I64((v1.0 + *v2, v1.1 + *v2))
   }
}

impl Add<VVI64I64, I64I64> for (VVI64I64, I64I64) {
   #[inline]
   fn add(v1: &VVI64I64, v2: &I64I64) -> Data {
      let mut outer = Vec::with_capacity(v1.len());

      for src in v1 {
         let mut inner = Vec::with_capacity(src.len());

         for tuple in src {
            inner.push((tuple.0 + v2.0, tuple.1 + v2.1));
         }

         outer.push(inner);
      }

      Data::VVI64I64(outer)
   }
}

struct JoinNode {
   defaults: Vec<Data>,
}

impl JoinNode {
   #[inline]
   fn new(defaults: Vec<Data>) -> Self {
      JoinNode {
         defaults: defaults,
      }
   }

   #[inline]
   fn process_two(&self, args: &[&Data]) -> Data {
      let in1 = in_value(args, 0, &self.defaults[0]);
      let in2 = in_value(args, 1, &self.defaults[1]);

      match (in1, in2) {
         (&Data::I64(v1), &Data::I64(v2)) => Data::I64I64((v1, v2)),

         _ => NONE
      }
   }

   #[inline]
   fn process_three(&self, args: &[&Data]) -> Data {
      let in1 = in_value(args, 0, &self.defaults[0]);
      let in2 = in_value(args, 1, &self.defaults[1]);
      let in3 = in_value(args, 2, &self.defaults[3]);

      match (in1, in2, in3) {
         (&Data::U8(v1), &Data::U8(v2), &Data::U8(v3)) => Data::U8U8U8((v1, v2, v3)),

         _ => NONE
      }
   }
}

impl Node for JoinNode {
   #[inline]
   fn process(&self, args: &[&Data]) -> Data {
      match self.defaults.len() {
         2 => self.process_two(args),
         3 => self.process_three(args),
         _ => Data::None
      }
   }
}

#[inline]
fn in_value<'a>(args: &'a[&'a Data], index: usize, initial: &'a Data) -> &'a Data {
   match args.get(index) {
      Some(passed) => match *passed {
         &Data::None => initial,
         _ => *passed
      },
      None => initial
   }
}

#[inline]
fn poly_from_data(data: &VVI64I64) -> Poly {
   let outer = points_from_coords(&data[0]);

   let mut inner = Vec::new();

   for inner_data in &data[1..] {
      inner.push(
         points_from_coords(inner_data)
      );
   }

   let poly = Poly::new_with_holes(
      outer, inner, RGB::new(81, 180, 200),
   );

   poly
}

#[inline]
fn points_from_coords(coords: &[(i64, i64)]) -> Vec<Point> {
   let mut points = Vec::new();

   for &(x, y) in coords.iter() {
      points.push(Point::new(x + 120, y + 120))
   }

   points
}

struct NodeRenderer {
   renderer: DevelRenderer,
   frame: i64,
}

impl NodeRenderer {
   #[inline]
   pub fn new() -> Self {
      NodeRenderer {
         renderer: DevelRenderer::new(Scene::new()),
         frame: 0,
      }
   }
}

impl Renderer for NodeRenderer {
   #[inline]
   fn init(&mut self, width: u32, height: u32) {
      let mut parser = NodeParser::new();
      parser.parse(NODE_DEFS);

      self.renderer.init(width, height);
   }

   #[inline]
   fn render(&mut self, frame: &mut Frame) {
      let mut scene = Scene::new();

      let source = vec![vec![
         (90, 1200),
         (261, 1735),
         (1443, 410),
         (493, 174),
      ]];

      let add = AddNode::new(vec![NONE, NONE]);

      let destination = add.process(
         &[&Data::VVI64I64(source), &Data::I64I64((self.frame, 0))]
      );

      match destination {
         Data::VVI64I64(data) => scene.push(poly_from_data(&data)),
         _ => {}
      }

      self.renderer.set_scene(scene);

      self.renderer.render(frame);

      self.frame += 1;
   }
}

struct NodeParser;

impl NodeParser {
   fn new() -> Self {
      NodeParser {}
   }

   fn parse(&mut self, node_defs: &str) {
      let mut parser = toml::Parser::new(node_defs);

      match parser.parse() {
         Some(everything) => {
            for (node_id, value) in everything.iter() {
               match value {
                  &toml::Value::Table(ref node_table) => {
                     process_node(node_id, node_table);
                  },
                  _ => {
                     println!("`{}` is not a table ", node_id);
                  }
               }
            }
         },
         None => {
            println!("parse errors: {:?}", parser.errors);
         }
      }
   }

}

fn process_node(node_id: &str, node_table: &toml::Table) {
   let node_type = extract_node_type(node_id, node_table);

   println!("TYPE: {}", node_type);

   println!("{:?}", node_table);

   match node_type.as_ref() {
      "add" => create_add_node(node_id, node_table),
      "join" => create_join_node(node_id, node_table),
      _ => {
         println!("Unknown node type {:?} for: {}", node_type, node_id);
         println!("");
         return;
      }
   };

   println!("");
}

fn create_add_node(node_id: &str, node_table: &toml::Table) -> Box<Node> {
   println!("ADD NODE");

   let data_value = extract_data_value(node_id, node_table);

   println!("DATA {:?}", data_value);

   let defaults = to_defaults(node_id, data_value);

   println!("defaults: {:?}", defaults);

   Box::new(AddNode::new(defaults))
}

fn create_join_node(node_id: &str, node_table: &toml::Table) -> Box<Node> {
   println!("JOIN NODE");

   let data_value = extract_data_value(node_id, node_table);

   println!("DATA {:?}", data_value);

   let defaults = to_defaults(node_id, data_value);

   println!("defaults: {:?}", defaults);

   Box::new(JoinNode::new(defaults))
}

fn extract_node_type<'a>(node_id: &str, node_table: &'a toml::Table) -> &'a str {
   match node_table.get("type") {
      Some(type_value) => {
         match type_value {
            &toml::Value::String(ref node_type) => node_type,
            _ => {
               panic!("node type not a string: {}", node_id);
            }
         }
      },
      None => {
         panic!("node without type: {}", node_id);
      }
   }
}

fn extract_data_value<'a>(node_id: &str, node_table: &'a toml::Table) -> &'a toml::Value {
   match node_table.get("data") {
      Some(data_value) => {
         data_value
      },
      None => {
         panic!("node without data: {}", node_id);
      }
   }
}

fn to_defaults(node_id: &str, data: &toml::Value) -> Vec<Data> {
   let array = match data {
      &toml::Value::Array(ref array) => array,
      _ => {
         panic!("data is not an array: {}", node_id);
      }
   };

   let mut result = Vec::with_capacity(array.len());

   for item in array.iter() {
      let table = match item {
         &toml::Value::Table(ref table) => table,
         _ => {
            panic!("value is not a table {:?}: {}", item, node_id);
         }
      };

      println!("item: {:?}", table);

      if table.get("from").is_some() {
         // Connection from a different node
         result.push(Data::None);
         continue;
      }

      result.push(
         extract_table_data(node_id, table)
      );
   }

   result
}

fn extract_table_data(node_id: &str, table: &toml::Table) -> Data {
   let type_str = match table.get("type") {
      Some(type_data) => {
         match type_data {
            &toml::Value::String(ref type_str) => type_str,
            _ => {
               panic!("Type not a string {:?}: {}", type_data, node_id);
            }
         }
      },
      None => {
         panic!("value table without a type {:?}: {}", table, node_id);
      }
   };

   let data = match table.get("data") {
      Some(data) => data,
      None => {
         panic!("value table without a data {:?}: {}", table, node_id);
      }
   };

   match type_str.as_ref() {
      "i64" => toml_to_i64(node_id, data),
      _ => {
         panic!("Unknown data type {}: {}", type_str, node_id);
      }
   }
}

fn toml_to_i64(node_id: &str, data: &toml::Value) -> Data {
   match data {
      &toml::Value::Integer(integer) => Data::I64(integer),
      _ => {
         panic!("Value not an integer {:?}: {}", data, node_id);
      }
   }
}

fn main() {
   let mut renderer = NodeRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Nodes")
      .size(1200, 800)
      .run();
}

<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::io;
use std::rc::{Rc, Weak};
use log::LogLevel;

use super::binary;
use super::client::Client;
use super::connection::{Connection, ConnectionId};
use super::ipv4_header::{IPv4Header, Protocol};
use super::ipv4_packet::IPv4Packet;
use super::selector::Selector;
use super::transport_header::TransportHeader;
use super::udp_connection::UDPConnection;

const TAG: &'static str = "Router";

pub struct Router {
    client: Weak<RefCell<Client>>,
    // there are typically only few connections per client, HashMap would be less efficient
    connections: Vec<Rc<RefCell<Connection>>>,
}

impl Router {
    pub fn new() -> Self {
        Self {
            client: Weak::new(),
            connections: Vec::new(),
        }
    }

    // expose client initialization after construction to break cyclic initialization dependencies
    pub fn set_client(&mut self, client: Weak<RefCell<Client>>) {
        self.client = client;
    }

    pub fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        if ipv4_packet.is_valid() {
            let (ipv4_header, transport) = ipv4_packet.split();
            let (transport_header, _) = transport.expect("No transport");
            if let Ok(connection) = self.connection(selector, &ipv4_header, &transport_header) {
                connection.borrow_mut().send_to_network(selector, ipv4_packet);
            } else {
                error!(target: TAG, "Cannot create route, dropping packet");
            }
        } else {
            warn!(target: TAG, "Dropping invalid packet");
            if log_enabled!(target: TAG, LogLevel::Trace) {
                trace!(target:TAG, "{}", binary::to_string(ipv4_packet.raw()));
            }
        }
    }

    fn connection(&mut self, selector: &mut Selector, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<&Rc<RefCell<Connection>>> {
        // TODO avoid cloning transport_header
        let id = ConnectionId::from_headers(ipv4_header.data(), &transport_header.data_clone());
        let index = match self.find_index(&id) {
            Some(index) => index,
            None => {
                let connection = Router::create_connection(selector, id, self.client.clone(), ipv4_header, transport_header)?;
                let index = self.connections.len();
                self.connections.push(connection);
                index
            }
        };
        Ok(self.connections.get_mut(index).unwrap())
    }

    fn create_connection(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Connection>>> {
        match id.protocol() {
            Protocol::TCP => Err(io::Error::new(io::ErrorKind::Other, "Not implemented yet")),
            Protocol::UDP => Ok(UDPConnection::new(selector, id, client, ipv4_header, transport_header)?),
            p => Err(io::Error::new(io::ErrorKind::Other, format!("Unsupported protocol: {:?}", p))),
        }
    }

    fn find_index(&self, id: &ConnectionId) -> Option<usize> {
        self.connections.iter().position(|connection| connection.borrow().id() == id)
    }

    pub fn remove(&mut self, connection: &Connection) {
        let index = self.connections.iter().position(|item| {
            // compare pointers to find the connection to remove
            binary::ptr_eq(connection, item.as_ptr())
        }).expect("Removing an unknown connection");
        self.connections.swap_remove(index);
    }

    pub fn clear(&mut self, selector: &mut Selector) {
        for connection in &mut self.connections {
            connection.borrow_mut().disconnect(selector);
        }
        self.connections.clear();
    }

    pub fn clean_expired_connections(&mut self, selector: &mut Selector) {
        for i in 0..self.connections.len() {
            let expired = {
                let mut connection = self.connections[i].borrow_mut();
                if connection.is_expired() {
                    debug!(target: TAG, "Removed expired connection: {}", connection.id());
                    connection.disconnect(selector);
                    true
                } else {
                    false
                }
            };
            if expired {
                self.connections.swap_remove(i);
            }
        }
    }
}
<commit_msg>Route TCP connections<commit_after>use std::cell::RefCell;
use std::io;
use std::rc::{Rc, Weak};
use log::LogLevel;

use super::binary;
use super::client::Client;
use super::connection::{Connection, ConnectionId};
use super::ipv4_header::{IPv4Header, Protocol};
use super::ipv4_packet::IPv4Packet;
use super::selector::Selector;
use super::tcp_connection::TCPConnection;
use super::transport_header::TransportHeader;
use super::udp_connection::UDPConnection;

const TAG: &'static str = "Router";

pub struct Router {
    client: Weak<RefCell<Client>>,
    // there are typically only few connections per client, HashMap would be less efficient
    connections: Vec<Rc<RefCell<Connection>>>,
}

impl Router {
    pub fn new() -> Self {
        Self {
            client: Weak::new(),
            connections: Vec::new(),
        }
    }

    // expose client initialization after construction to break cyclic initialization dependencies
    pub fn set_client(&mut self, client: Weak<RefCell<Client>>) {
        self.client = client;
    }

    pub fn send_to_network(&mut self, selector: &mut Selector, ipv4_packet: &IPv4Packet) {
        if ipv4_packet.is_valid() {
            let (ipv4_header, transport) = ipv4_packet.split();
            let (transport_header, _) = transport.expect("No transport");
            match self.connection(selector, &ipv4_header, &transport_header) {
                Ok(connection) => connection.borrow_mut().send_to_network(selector, ipv4_packet),
                Err(err) => error!(target: TAG, "Cannot create route, dropping packet: {}", err),
            }
        } else {
            warn!(target: TAG, "Dropping invalid packet");
            if log_enabled!(target: TAG, LogLevel::Trace) {
                trace!(target:TAG, "{}", binary::to_string(ipv4_packet.raw()));
            }
        }
    }

    fn connection(&mut self, selector: &mut Selector, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<&Rc<RefCell<Connection>>> {
        // TODO avoid cloning transport_header
        let id = ConnectionId::from_headers(ipv4_header.data(), &transport_header.data_clone());
        let index = match self.find_index(&id) {
            Some(index) => index,
            None => {
                let connection = Router::create_connection(selector, id, self.client.clone(), ipv4_header, transport_header)?;
                let index = self.connections.len();
                self.connections.push(connection);
                index
            }
        };
        Ok(self.connections.get_mut(index).unwrap())
    }

    fn create_connection(selector: &mut Selector, id: ConnectionId, client: Weak<RefCell<Client>>, ipv4_header: &IPv4Header, transport_header: &TransportHeader) -> io::Result<Rc<RefCell<Connection>>> {
        match id.protocol() {
            Protocol::TCP => Ok(TCPConnection::new(selector, id, client, ipv4_header, transport_header)?),
            Protocol::UDP => Ok(UDPConnection::new(selector, id, client, ipv4_header, transport_header)?),
            p => Err(io::Error::new(io::ErrorKind::Other, format!("Unsupported protocol: {:?}", p))),
        }
    }

    fn find_index(&self, id: &ConnectionId) -> Option<usize> {
        self.connections.iter().position(|connection| connection.borrow().id() == id)
    }

    pub fn remove(&mut self, connection: &Connection) {
        let index = self.connections.iter().position(|item| {
            // compare pointers to find the connection to remove
            binary::ptr_eq(connection, item.as_ptr())
        }).expect("Removing an unknown connection");
        self.connections.swap_remove(index);
    }

    pub fn clear(&mut self, selector: &mut Selector) {
        for connection in &mut self.connections {
            connection.borrow_mut().disconnect(selector);
        }
        self.connections.clear();
    }

    pub fn clean_expired_connections(&mut self, selector: &mut Selector) {
        for i in 0..self.connections.len() {
            let expired = {
                let mut connection = self.connections[i].borrow_mut();
                if connection.is_expired() {
                    debug!(target: TAG, "Removed expired connection: {}", connection.id());
                    connection.disconnect(selector);
                    true
                } else {
                    false
                }
            };
            if expired {
                self.connections.swap_remove(i);
            }
        }
    }
}
<|endoftext|>