<commit_before>use std::borrow::Borrow;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::iter::FromIterator;

use url::Url;

use crate::core::dependency::Kind;
use crate::core::{Dependency, PackageId, PackageIdSpec, Summary, Target};
use crate::util::errors::CargoResult;
use crate::util::Graph;

use super::encode::Metadata;

/// Represents a fully-resolved package dependency graph. Each node in the graph
/// is a package and edges represent dependencies between packages.
///
/// Each instance of `Resolve` also understands the full set of features used
/// for each package.
#[derive(PartialEq)]
pub struct Resolve {
    /// A graph, whose vertices are packages and edges are dependency specifications
    /// from `Cargo.toml`. We need a `Vec` here because the same package
    /// might be present in both `[dependencies]` and `[build-dependencies]`.
    graph: Graph<PackageId, Vec<Dependency>>,
    replacements: HashMap<PackageId, PackageId>,
    reverse_replacements: HashMap<PackageId, PackageId>,
    empty_features: HashSet<String>,
    features: HashMap<PackageId, HashSet<String>>,
    checksums: HashMap<PackageId, Option<String>>,
    metadata: Metadata,
    unused_patches: Vec<PackageId>,
    // A map from packages to a set of their public dependencies
    public_dependencies: HashMap<PackageId, HashSet<PackageId>>,
}

impl Resolve {
    pub fn new(
        graph: Graph<PackageId, Vec<Dependency>>,
        replacements: HashMap<PackageId, PackageId>,
        features: HashMap<PackageId, HashSet<String>>,
        checksums: HashMap<PackageId, Option<String>>,
        metadata: Metadata,
        unused_patches: Vec<PackageId>,
    ) -> Resolve {
        let reverse_replacements = replacements.iter().map(|(&p, &r)| (r, p)).collect();
        let public_dependencies = graph
            .iter()
            .map(|p| {
                let public_deps = graph
                    .edges(p)
                    .filter(|(_, deps)| {
                        deps.iter()
                            .any(|d| d.kind() == Kind::Normal && d.is_public())
                    })
                    .map(|(dep_package, _)| *dep_package)
                    .collect::<HashSet<PackageId>>();

                (*p, public_deps)
            })
            .collect();

        Resolve {
            graph,
            replacements,
            features,
            checksums,
            metadata,
            unused_patches,
            empty_features: HashSet::new(),
            reverse_replacements,
            public_dependencies,
        }
    }

    /// Resolves one of the paths from the given dependent package up to
    /// the root.
    pub fn path_to_top<'a>(&'a self, pkg: &'a PackageId) -> Vec<&'a PackageId> {
        self.graph.path_to_top(pkg)
    }

    pub fn register_used_patches(&mut self, patches: &HashMap<Url, Vec<Summary>>) {
        for summary in patches.values().flat_map(|v| v) {
            if self.iter().any(|id| id == summary.package_id()) {
                continue;
            }
            self.unused_patches.push(summary.package_id());
        }
    }

    pub fn merge_from(&mut self, previous: &Resolve) -> CargoResult<()> {
        // Given a previous instance of resolve, it should be forbidden to ever
        // have a checksums which *differ*. If the same package ID has differing
        // checksums, then something has gone wrong such as:
        //
        // * Something got seriously corrupted
        // * A "mirror" isn't actually a mirror as some changes were made
        // * A replacement source wasn't actually a replacment, some changes
        //   were made
        //
        // In all of these cases, we want to report an error to indicate that
        // something is awry. Normal execution (esp just using crates.io) should
        // never run into this.
        for (id, cksum) in previous.checksums.iter() {
            if let Some(mine) = self.checksums.get(id) {
                if mine == cksum {
                    continue;
                }

                // If the previous checksum wasn't calculated, the current
                // checksum is `Some`. This may indicate that a source was
                // erroneously replaced or was replaced with something that
                // desires stronger checksum guarantees than can be afforded
                // elsewhere.
                if cksum.is_none() {
                    failure::bail!(
                        "\
checksum for `{}` was not previously calculated, but a checksum could now \
be calculated

this could be indicative of a few possible situations:

    * the source `{}` did not previously support checksums,
      but was replaced with one that does
    * newer Cargo implementations know how to checksum this source, but this
      older implementation does not
    * the lock file is corrupt
",
                        id,
                        id.source_id()
                    )

                // If our checksum hasn't been calculated, then it could mean
                // that future Cargo figured out how to checksum something or
                // more realistically we were overridden with a source that does
                // not have checksums.
                } else if mine.is_none() {
                    failure::bail!(
                        "\
checksum for `{}` could not be calculated, but a checksum is listed in \
the existing lock file

this could be indicative of a few possible situations:

    * the source `{}` supports checksums,
      but was replaced with one that doesn't
    * the lock file is corrupt

unable to verify that `{0}` is the same as when the lockfile was generated
",
                        id,
                        id.source_id()
                    )

                // If the checksums aren't equal, and neither is None, then they
                // must both be Some, in which case the checksum now differs.
                // That's quite bad!
                } else {
                    failure::bail!(
                        "\
checksum for `{}` changed between lock files

this could be indicative of a few possible errors:

    * the lock file is corrupt
    * a replacement source in use (e.g., a mirror) returned a different checksum
    * the source itself may be corrupt in one way or another

unable to verify that `{0}` is the same as when the lockfile was generated
",
                        id
                    );
                }
            }
        }

        // Be sure to just copy over any unknown metadata.
        self.metadata = previous.metadata.clone();
        Ok(())
    }

    pub fn contains<Q: ?Sized>(&self, k: &Q) -> bool
    where
        PackageId: Borrow<Q>,
        Q: Ord + Eq,
    {
        self.graph.contains(k)
    }

    pub fn sort(&self) -> Vec<PackageId> {
        self.graph.sort()
    }

    pub fn iter<'a>(&'a self) -> impl Iterator<Item = PackageId> + 'a {
        self.graph.iter().cloned()
    }

    pub fn deps(&self, pkg: PackageId) -> impl Iterator<Item = (PackageId, &[Dependency])> {
        self.graph
            .edges(&pkg)
            .map(move |&(id, ref deps)| (self.replacement(id).unwrap_or(id), deps.as_slice()))
    }

    pub fn deps_not_replaced<'a>(&'a self, pkg: PackageId) -> impl Iterator<Item = PackageId> + 'a {
        self.graph.edges(&pkg).map(|&(id, _)| id)
    }

    pub fn replacement(&self, pkg: PackageId) -> Option<PackageId> {
        self.replacements.get(&pkg).cloned()
    }

    pub fn replacements(&self) -> &HashMap<PackageId, PackageId> {
        &self.replacements
    }

    pub fn features(&self, pkg: PackageId) -> &HashSet<String> {
        self.features.get(&pkg).unwrap_or(&self.empty_features)
    }

    pub fn is_public_dep(&self, pkg: PackageId, dep: PackageId) -> bool {
        self.public_dependencies
            .get(&pkg)
            .map(|public_deps| public_deps.contains(&dep))
            .unwrap_or_else(|| panic!("Unknown dependency {:?} for package {:?}", dep, pkg))
    }

    pub fn features_sorted(&self, pkg: PackageId) -> Vec<&str> {
        let mut v = Vec::from_iter(self.features(pkg).iter().map(|s| s.as_ref()));
        v.sort_unstable();
        v
    }

    pub fn query(&self, spec: &str) -> CargoResult<PackageId> {
        PackageIdSpec::query_str(spec, self.iter())
    }

    pub fn unused_patches(&self) -> &[PackageId] {
        &self.unused_patches
    }

    pub fn checksums(&self) -> &HashMap<PackageId, Option<String>> {
        &self.checksums
    }

    pub fn metadata(&self) -> &Metadata {
        &self.metadata
    }

    pub fn extern_crate_name(
        &self,
        from: PackageId,
        to: PackageId,
        to_target: &Target,
    ) -> CargoResult<String> {
        let deps = if from == to {
            &[]
        } else {
            self.dependencies_listed(from, to)
        };

        let crate_name = to_target.crate_name();
        let mut names = deps.iter().map(|d| {
            d.explicit_name_in_toml()
                .map(|s| s.as_str().replace("-", "_"))
                .unwrap_or_else(|| crate_name.clone())
        });
        let name = names.next().unwrap_or_else(|| crate_name.clone());
        for n in names {
            failure::ensure!(
                n == name,
                "the crate `{}` depends on crate `{}` multiple times with different names",
                from,
                to,
            );
        }
        Ok(name)
    }

    fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &[Dependency] {
        // We've got a dependency on `from` to `to`, but this dependency edge
        // may be affected by [replace]. If the `to` package is listed as the
        // target of a replacement (aka the key of a reverse replacement map)
        // then we try to find our dependency edge through that. If that fails
        // then we go down below assuming it's not replaced.
        //
        // Note that we don't treat `from` as if it's been replaced because
        // that's where the dependency originates from, and we only replace
        // targets of dependencies not the originator.
        if let Some(replace) = self.reverse_replacements.get(&to) {
            if let Some(deps) = self.graph.edge(&from, replace) {
                return deps;
            }
        }
        match self.graph.edge(&from, &to) {
            Some(ret) => ret,
            None => panic!("no Dependency listed for `{}` => `{}`", from, to),
        }
    }
}

impl fmt::Debug for Resolve {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(fmt, "graph: {:?}", self.graph)?;
        writeln!(fmt, "\nfeatures: {{")?;
        for (pkg, features) in &self.features {
            writeln!(fmt, "  {}: {:?}", pkg, features)?;
        }
        write!(fmt, "}}")
    }
}
<commit_msg>Fix typo in comment<commit_after>use std::borrow::Borrow;
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::iter::FromIterator;

use url::Url;

use crate::core::dependency::Kind;
use crate::core::{Dependency, PackageId, PackageIdSpec, Summary, Target};
use crate::util::errors::CargoResult;
use crate::util::Graph;

use super::encode::Metadata;

/// Represents a fully-resolved package dependency graph. Each node in the graph
/// is a package and edges represent dependencies between packages.
///
/// Each instance of `Resolve` also understands the full set of features used
/// for each package.
#[derive(PartialEq)]
pub struct Resolve {
    /// A graph, whose vertices are packages and edges are dependency specifications
    /// from `Cargo.toml`. We need a `Vec` here because the same package
    /// might be present in both `[dependencies]` and `[build-dependencies]`.
    graph: Graph<PackageId, Vec<Dependency>>,
    replacements: HashMap<PackageId, PackageId>,
    reverse_replacements: HashMap<PackageId, PackageId>,
    empty_features: HashSet<String>,
    features: HashMap<PackageId, HashSet<String>>,
    checksums: HashMap<PackageId, Option<String>>,
    metadata: Metadata,
    unused_patches: Vec<PackageId>,
    // A map from packages to a set of their public dependencies
    public_dependencies: HashMap<PackageId, HashSet<PackageId>>,
}

impl Resolve {
    pub fn new(
        graph: Graph<PackageId, Vec<Dependency>>,
        replacements: HashMap<PackageId, PackageId>,
        features: HashMap<PackageId, HashSet<String>>,
        checksums: HashMap<PackageId, Option<String>>,
        metadata: Metadata,
        unused_patches: Vec<PackageId>,
    ) -> Resolve {
        let reverse_replacements = replacements.iter().map(|(&p, &r)| (r, p)).collect();
        let public_dependencies = graph
            .iter()
            .map(|p| {
                let public_deps = graph
                    .edges(p)
                    .filter(|(_, deps)| {
                        deps.iter()
                            .any(|d| d.kind() == Kind::Normal && d.is_public())
                    })
                    .map(|(dep_package, _)| *dep_package)
                    .collect::<HashSet<PackageId>>();

                (*p, public_deps)
            })
            .collect();

        Resolve {
            graph,
            replacements,
            features,
            checksums,
            metadata,
            unused_patches,
            empty_features: HashSet::new(),
            reverse_replacements,
            public_dependencies,
        }
    }

    /// Resolves one of the paths from the given dependent package up to
    /// the root.
    pub fn path_to_top<'a>(&'a self, pkg: &'a PackageId) -> Vec<&'a PackageId> {
        self.graph.path_to_top(pkg)
    }

    pub fn register_used_patches(&mut self, patches: &HashMap<Url, Vec<Summary>>) {
        for summary in patches.values().flat_map(|v| v) {
            if self.iter().any(|id| id == summary.package_id()) {
                continue;
            }
            self.unused_patches.push(summary.package_id());
        }
    }

    pub fn merge_from(&mut self, previous: &Resolve) -> CargoResult<()> {
        // Given a previous instance of resolve, it should be forbidden to ever
        // have a checksums which *differ*. If the same package ID has differing
        // checksums, then something has gone wrong such as:
        //
        // * Something got seriously corrupted
        // * A "mirror" isn't actually a mirror as some changes were made
        // * A replacement source wasn't actually a replacement, some changes
        //   were made
        //
        // In all of these cases, we want to report an error to indicate that
        // something is awry. Normal execution (esp just using crates.io) should
        // never run into this.
        for (id, cksum) in previous.checksums.iter() {
            if let Some(mine) = self.checksums.get(id) {
                if mine == cksum {
                    continue;
                }

                // If the previous checksum wasn't calculated, the current
                // checksum is `Some`. This may indicate that a source was
                // erroneously replaced or was replaced with something that
                // desires stronger checksum guarantees than can be afforded
                // elsewhere.
                if cksum.is_none() {
                    failure::bail!(
                        "\
checksum for `{}` was not previously calculated, but a checksum could now \
be calculated

this could be indicative of a few possible situations:

    * the source `{}` did not previously support checksums,
      but was replaced with one that does
    * newer Cargo implementations know how to checksum this source, but this
      older implementation does not
    * the lock file is corrupt
",
                        id,
                        id.source_id()
                    )

                // If our checksum hasn't been calculated, then it could mean
                // that future Cargo figured out how to checksum something or
                // more realistically we were overridden with a source that does
                // not have checksums.
                } else if mine.is_none() {
                    failure::bail!(
                        "\
checksum for `{}` could not be calculated, but a checksum is listed in \
the existing lock file

this could be indicative of a few possible situations:

    * the source `{}` supports checksums,
      but was replaced with one that doesn't
    * the lock file is corrupt

unable to verify that `{0}` is the same as when the lockfile was generated
",
                        id,
                        id.source_id()
                    )

                // If the checksums aren't equal, and neither is None, then they
                // must both be Some, in which case the checksum now differs.
                // That's quite bad!
                } else {
                    failure::bail!(
                        "\
checksum for `{}` changed between lock files

this could be indicative of a few possible errors:

    * the lock file is corrupt
    * a replacement source in use (e.g., a mirror) returned a different checksum
    * the source itself may be corrupt in one way or another

unable to verify that `{0}` is the same as when the lockfile was generated
",
                        id
                    );
                }
            }
        }

        // Be sure to just copy over any unknown metadata.
        self.metadata = previous.metadata.clone();
        Ok(())
    }

    pub fn contains<Q: ?Sized>(&self, k: &Q) -> bool
    where
        PackageId: Borrow<Q>,
        Q: Ord + Eq,
    {
        self.graph.contains(k)
    }

    pub fn sort(&self) -> Vec<PackageId> {
        self.graph.sort()
    }

    pub fn iter<'a>(&'a self) -> impl Iterator<Item = PackageId> + 'a {
        self.graph.iter().cloned()
    }

    pub fn deps(&self, pkg: PackageId) -> impl Iterator<Item = (PackageId, &[Dependency])> {
        self.graph
            .edges(&pkg)
            .map(move |&(id, ref deps)| (self.replacement(id).unwrap_or(id), deps.as_slice()))
    }

    pub fn deps_not_replaced<'a>(&'a self, pkg: PackageId) -> impl Iterator<Item = PackageId> + 'a {
        self.graph.edges(&pkg).map(|&(id, _)| id)
    }

    pub fn replacement(&self, pkg: PackageId) -> Option<PackageId> {
        self.replacements.get(&pkg).cloned()
    }

    pub fn replacements(&self) -> &HashMap<PackageId, PackageId> {
        &self.replacements
    }

    pub fn features(&self, pkg: PackageId) -> &HashSet<String> {
        self.features.get(&pkg).unwrap_or(&self.empty_features)
    }

    pub fn is_public_dep(&self, pkg: PackageId, dep: PackageId) -> bool {
        self.public_dependencies
            .get(&pkg)
            .map(|public_deps| public_deps.contains(&dep))
            .unwrap_or_else(|| panic!("Unknown dependency {:?} for package {:?}", dep, pkg))
    }

    pub fn features_sorted(&self, pkg: PackageId) -> Vec<&str> {
        let mut v = Vec::from_iter(self.features(pkg).iter().map(|s| s.as_ref()));
        v.sort_unstable();
        v
    }

    pub fn query(&self, spec: &str) -> CargoResult<PackageId> {
        PackageIdSpec::query_str(spec, self.iter())
    }

    pub fn unused_patches(&self) -> &[PackageId] {
        &self.unused_patches
    }

    pub fn checksums(&self) -> &HashMap<PackageId, Option<String>> {
        &self.checksums
    }

    pub fn metadata(&self) -> &Metadata {
        &self.metadata
    }

    pub fn extern_crate_name(
        &self,
        from: PackageId,
        to: PackageId,
        to_target: &Target,
    ) -> CargoResult<String> {
        let deps = if from == to {
            &[]
        } else {
            self.dependencies_listed(from, to)
        };

        let crate_name = to_target.crate_name();
        let mut names = deps.iter().map(|d| {
            d.explicit_name_in_toml()
                .map(|s| s.as_str().replace("-", "_"))
                .unwrap_or_else(|| crate_name.clone())
        });
        let name = names.next().unwrap_or_else(|| crate_name.clone());
        for n in names {
            failure::ensure!(
                n == name,
                "the crate `{}` depends on crate `{}` multiple times with different names",
                from,
                to,
            );
        }
        Ok(name)
    }

    fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &[Dependency] {
        // We've got a dependency on `from` to `to`, but this dependency edge
        // may be affected by [replace]. If the `to` package is listed as the
        // target of a replacement (aka the key of a reverse replacement map)
        // then we try to find our dependency edge through that. If that fails
        // then we go down below assuming it's not replaced.
        //
        // Note that we don't treat `from` as if it's been replaced because
        // that's where the dependency originates from, and we only replace
        // targets of dependencies not the originator.
        if let Some(replace) = self.reverse_replacements.get(&to) {
            if let Some(deps) = self.graph.edge(&from, replace) {
                return deps;
            }
        }
        match self.graph.edge(&from, &to) {
            Some(ret) => ret,
            None => panic!("no Dependency listed for `{}` => `{}`", from, to),
        }
    }
}

impl fmt::Debug for Resolve {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(fmt, "graph: {:?}", self.graph)?;
        writeln!(fmt, "\nfeatures: {{")?;
        for (pkg, features) in &self.features {
            writeln!(fmt, "  {}: {:?}", pkg, features)?;
        }
        write!(fmt, "}}")
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, libc, rustc_macro, proc_macro)]
#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate clap;
#[macro_use] extern crate serde_derive;
extern crate env_logger;
extern crate mio;
extern crate yxorp;
extern crate toml;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate libc;
extern crate slab;

mod config;
mod command;
mod state;

use std::net::{UdpSocket,ToSocketAddrs};
use std::sync::mpsc::{channel};
use std::collections::HashMap;
use std::thread::{self,JoinHandle};
use std::env;
use yxorp::network::{self,ProxyOrder};
use yxorp::network::metrics::{METRICS,ProxyMetrics};
use log::{LogRecord,LogLevelFilter,LogLevel};
use env_logger::LogBuilder;
use clap::{App,Arg};
use mio::{channel,Poll};

use command::{Listener,ListenerType};

fn main() {
  let pid = unsafe { libc::getpid() };
  let format = move |record: &LogRecord| {
    match record.level() {
    LogLevel::Debug | LogLevel::Trace => format!("{}\t{}\t{}\t{}\t{}\t|\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args(), record.location().module_path()),
    _ => format!("{}\t{}\t{}\t{}\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args())

    }
  };

  let mut builder = LogBuilder::new();
  builder.format(format).filter(None, LogLevelFilter::Info);

  let matches = App::new("I will not name this thing yxorp")
                        .version(crate_version!())
                        .about("hot reconfigurable proxy")
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true)
                                    .required(true))
                        .get_matches();

  let config_file = matches.value_of("config").unwrap();

  if let Ok(config) = config::Config::load_from_path(config_file) {
    if let Some(log_level) = config.log_level {
     builder.parse(&log_level);
    }

    builder.init().unwrap();
    info!("starting up");

    let metrics_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
    let metrics_host   = (&config.metrics.address[..], config.metrics.port).to_socket_addrs().unwrap().next().unwrap();
    METRICS.lock().unwrap().set_up_remote(metrics_socket, metrics_host);
    let metrics_guard = ProxyMetrics::run();

    let mut listeners = HashMap::new();
    let mut jh_opt: Option<JoinHandle<()>> = None;

    for (ref tag, ref ls) in config.listeners {
      let jh_opt = match ls.listener_type {
        ListenerType::HTTP => {
          //FIXME: make safer
          if let Some(conf) = ls.to_http() {
            for index in 1..ls.worker_count.unwrap_or(1) {
              let (sender, receiver) = channel::<network::ServerMessage>();
              let mut poll = Poll::new().unwrap();
              let (tx, rx) = channel::channel::<ProxyOrder>();
              let config = conf.clone();
              thread::spawn(move || {
                network::http::start_listener(config, sender, poll, rx);
              });
              let t = format!("{}-{}", tag, index);
              let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
              listeners.insert(t, l);
            }
            let (sender, receiver) = channel::<network::ServerMessage>();
            let mut poll = Poll::new().unwrap();
            let (tx, rx) = channel::channel::<ProxyOrder>();
            //FIXME: keep this to get a join guard
            let jg = thread::spawn(move || {
              network::http::start_listener(conf, sender, poll, rx);
            });
            let t = format!("{}-{}", tag, 0);
            let l =  Listener::new(tag.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
            listeners.insert(tag.clone(), l);
            Some(jg)
          } else {
            None
          }
        },
        ListenerType::HTTPS => {
          if let Some(conf) = ls.to_tls() {
            for index in 1..ls.worker_count.unwrap_or(1) {
              let (sender, receiver) = channel::<network::ServerMessage>();
              let mut poll = Poll::new().unwrap();
              let (tx, rx) = channel::channel::<ProxyOrder>();
              let config = conf.clone();
              thread::spawn(move || {
                network::tls::start_listener(config, sender, poll, rx);
              });
              let t = format!("{}-{}", tag, index);
              let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
              listeners.insert(t, l);
            }
            let (sender, receiver) = channel::<network::ServerMessage>();
            let mut poll = Poll::new().unwrap();
            let (tx, rx) = channel::channel::<ProxyOrder>();
            //FIXME: keep this to get a join guard
            let jg = thread::spawn(move || {
              network::tls::start_listener(conf, sender, poll, rx);
            });
            let t = format!("{}-{}", tag, 0);
            let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
            listeners.insert(t, l);
            Some(jg)
          } else {
            None
          }
        },
        _ => unimplemented!()
      };
    };

    let buffer_size     = config.command_buffer_size.unwrap_or(10000);
    let max_buffer_size = config.max_command_buffer_size.unwrap_or(buffer_size * 2);
    command::start(config.command_socket, listeners, config.saved_state, buffer_size, max_buffer_size);
    //FIXME: really join on all threads?
    if let Some(jh) = jh_opt {
      let _ = jh.join();
      info!("good bye");
    }
  } else {
    println!("could not load configuration file at '{}', stopping", config_file);
  }
}

<commit_msg>fix a tag<commit_after>#![feature(custom_derive, plugin, libc, rustc_macro, proc_macro)]
#[macro_use] extern crate nom;
#[macro_use] extern crate log;
#[macro_use] extern crate clap;
#[macro_use] extern crate serde_derive;
extern crate env_logger;
extern crate mio;
extern crate yxorp;
extern crate toml;
extern crate rustc_serialize;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate libc;
extern crate slab;

mod config;
mod command;
mod state;

use std::net::{UdpSocket,ToSocketAddrs};
use std::sync::mpsc::{channel};
use std::collections::HashMap;
use std::thread::{self,JoinHandle};
use std::env;
use yxorp::network::{self,ProxyOrder};
use yxorp::network::metrics::{METRICS,ProxyMetrics};
use log::{LogRecord,LogLevelFilter,LogLevel};
use env_logger::LogBuilder;
use clap::{App,Arg};
use mio::{channel,Poll};

use command::{Listener,ListenerType};

fn main() {
  let pid = unsafe { libc::getpid() };
  let format = move |record: &LogRecord| {
    match record.level() {
    LogLevel::Debug | LogLevel::Trace => format!("{}\t{}\t{}\t{}\t{}\t|\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args(), record.location().module_path()),
    _ => format!("{}\t{}\t{}\t{}\t{}",
      time::now_utc().rfc3339(), time::precise_time_ns(), pid,
      record.level(), record.args())

    }
  };

  let mut builder = LogBuilder::new();
  builder.format(format).filter(None, LogLevelFilter::Info);

  let matches = App::new("I will not name this thing yxorp")
                        .version(crate_version!())
                        .about("hot reconfigurable proxy")
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true)
                                    .required(true))
                        .get_matches();

  let config_file = matches.value_of("config").unwrap();

  if let Ok(config) = config::Config::load_from_path(config_file) {
    if let Some(log_level) = config.log_level {
     builder.parse(&log_level);
    }

    builder.init().unwrap();
    info!("starting up");

    let metrics_socket = UdpSocket::bind("0.0.0.0:0").unwrap();
    let metrics_host   = (&config.metrics.address[..], config.metrics.port).to_socket_addrs().unwrap().next().unwrap();
    METRICS.lock().unwrap().set_up_remote(metrics_socket, metrics_host);
    let metrics_guard = ProxyMetrics::run();

    let mut listeners = HashMap::new();
    let mut jh_opt: Option<JoinHandle<()>> = None;

    for (ref tag, ref ls) in config.listeners {
      let jh_opt = match ls.listener_type {
        ListenerType::HTTP => {
          //FIXME: make safer
          if let Some(conf) = ls.to_http() {
            for index in 1..ls.worker_count.unwrap_or(1) {
              let (sender, receiver) = channel::<network::ServerMessage>();
              let mut poll = Poll::new().unwrap();
              let (tx, rx) = channel::channel::<ProxyOrder>();
              let config = conf.clone();
              thread::spawn(move || {
                network::http::start_listener(config, sender, poll, rx);
              });
              let t = format!("{}-{}", tag, index);
              let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
              listeners.insert(t, l);
            }
            let (sender, receiver) = channel::<network::ServerMessage>();
            let mut poll = Poll::new().unwrap();
            let (tx, rx) = channel::channel::<ProxyOrder>();
            //FIXME: keep this to get a join guard
            let jg = thread::spawn(move || {
              network::http::start_listener(conf, sender, poll, rx);
            });
            let t = format!("{}-{}", tag, 0);
            let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
            listeners.insert(t, l);
            Some(jg)
          } else {
            None
          }
        },
        ListenerType::HTTPS => {
          if let Some(conf) = ls.to_tls() {
            for index in 1..ls.worker_count.unwrap_or(1) {
              let (sender, receiver) = channel::<network::ServerMessage>();
              let mut poll = Poll::new().unwrap();
              let (tx, rx) = channel::channel::<ProxyOrder>();
              let config = conf.clone();
              thread::spawn(move || {
                network::tls::start_listener(config, sender, poll, rx);
              });
              let t = format!("{}-{}", tag, index);
              let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
              listeners.insert(t, l);
            }
            let (sender, receiver) = channel::<network::ServerMessage>();
            let mut poll = Poll::new().unwrap();
            let (tx, rx) = channel::channel::<ProxyOrder>();
            //FIXME: keep this to get a join guard
            let jg = thread::spawn(move || {
              network::tls::start_listener(conf, sender, poll, rx);
            });
            let t = format!("{}-{}", tag, 0);
            let l =  Listener::new(t.clone(), ls.listener_type, ls.address.clone(), ls.port, tx, receiver);
            listeners.insert(t, l);
            Some(jg)
          } else {
            None
          }
        },
        _ => unimplemented!()
      };
    };

    let buffer_size     = config.command_buffer_size.unwrap_or(10000);
    let max_buffer_size = config.max_command_buffer_size.unwrap_or(buffer_size * 2);
    command::start(config.command_socket, listeners, config.saved_state, buffer_size, max_buffer_size);
    //FIXME: really join on all threads?
    if let Some(jh) = jh_opt {
      let _ = jh.join();
      info!("good bye");
    }
  } else {
    println!("could not load configuration file at '{}', stopping", config_file);
  }
}

<|endoftext|>


<commit_before>import std::term;
import io::writer_util;
import codemap::span;

export emitter, emit;
export level, fatal, error, warning, note;
export span_handler, handler, mk_span_handler, mk_handler;
export codemap_span_handler, codemap_handler;
export ice_msg;
export expect;

type emitter = fn@(cmsp: option<(codemap::codemap, span)>,
                   msg: str, lvl: level);

iface span_handler {
    fn span_fatal(sp: span, msg: str) -> !;
    fn span_err(sp: span, msg: str);
    fn span_warn(sp: span, msg: str);
    fn span_note(sp: span, msg: str);
    fn span_bug(sp: span, msg: str) -> !;
    fn span_unimpl(sp: span, msg: str) -> !;
    fn handler() -> handler;
}

iface handler {
    fn fatal(msg: str) -> !;
    fn err(msg: str);
    fn bump_err_count();
    fn has_errors() -> bool;
    fn abort_if_errors();
    fn warn(msg: str);
    fn note(msg: str);
    fn bug(msg: str) -> !;
    fn unimpl(msg: str) -> !;
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level);
}

type handler_t = @{
    mut err_count: uint,
    emit: emitter
};

type codemap_t = @{
    handler: handler,
    cm: codemap::codemap
};

impl codemap_span_handler of span_handler for codemap_t {
    fn span_fatal(sp: span, msg: str) -> ! {
        self.handler.emit(some((self.cm, sp)), msg, fatal);
        fail;
    }
    fn span_err(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, error);
        self.handler.bump_err_count();
    }
    fn span_warn(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, warning);
    }
    fn span_note(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, note);
    }
    fn span_bug(sp: span, msg: str) -> ! {
        self.span_fatal(sp, ice_msg(msg));
    }
    fn span_unimpl(sp: span, msg: str) -> ! {
        self.span_bug(sp, "unimplemented " + msg);
    }
    fn handler() -> handler {
        self.handler
    }
}

impl codemap_handler of handler for handler_t {
    fn fatal(msg: str) -> ! {
        self.emit(none, msg, fatal);
        fail;
    }
    fn err(msg: str) {
        self.emit(none, msg, error);
        self.bump_err_count();
    }
    fn bump_err_count() {
        self.err_count += 1u;
    }
    fn has_errors() -> bool { self.err_count > 0u }
    fn abort_if_errors() {
        if self.err_count > 0u {
            let s = #fmt["aborting due to %u previous errors",
                         self.err_count];
            self.fatal(s);
        }
    }
    fn warn(msg: str) {
        self.emit(none, msg, warning);
    }
    fn note(msg: str) {
        self.emit(none, msg, note);
    }
    fn bug(msg: str) -> ! {
        self.fatal(ice_msg(msg));
    }
    fn unimpl(msg: str) -> ! { self.bug("unimplemented " + msg); }
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level) {
        self.emit(cmsp, msg, lvl);
    }
}

fn ice_msg(msg: str) -> str {
    #fmt["internal compiler error: %s", msg]
}

fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler {
    @{ handler: handler, cm: cm } as span_handler
}

fn mk_handler(emitter: option<emitter>) -> handler {

    let emit = alt emitter {
      some(e) { e }
      none {
        let f = fn@(cmsp: option<(codemap::codemap, span)>,
            msg: str, t: level) {
            emit(cmsp, msg, t);
        };
        f
      }
    };

    @{
        mut err_count: 0u,
        emit: emit
    } as handler
}

enum level {
    fatal,
    error,
    warning,
    note,
}

fn diagnosticstr(lvl: level) -> str {
    alt lvl {
      fatal { "error" }
      error { "error" }
      warning { "warning" }
      note { "note" }
    }
}

fn diagnosticcolor(lvl: level) -> u8 {
    alt lvl {
      fatal { term::color_bright_red }
      error { term::color_bright_red }
      warning { term::color_bright_yellow }
      note { term::color_bright_green }
    }
}

fn print_diagnostic(topic: str, lvl: level, msg: str) {
    if str::is_not_empty(topic) {
        io::stderr().write_str(#fmt["%s ", topic]);
    }
    if term::color_supported() {
        term::fg(io::stderr(), diagnosticcolor(lvl));
    }
    io::stderr().write_str(#fmt["%s:", diagnosticstr(lvl)]);
    if term::color_supported() {
        term::reset(io::stderr());
    }
    io::stderr().write_str(#fmt[" %s\n", msg]);
}

fn emit(cmsp: option<(codemap::codemap, span)>,
        msg: str, lvl: level) {
    alt cmsp {
      some((cm, sp)) {
        let sp = codemap::adjust_span(cm,sp);
        let ss = codemap::span_to_str(sp, cm);
        let lines = codemap::span_to_lines(sp, cm);
        print_diagnostic(ss, lvl, msg);
        highlight_lines(cm, sp, lines);
        print_macro_backtrace(cm, sp);
      }
      none {
        print_diagnostic("", lvl, msg);
      }
    }
}

fn highlight_lines(cm: codemap::codemap, sp: span,
                   lines: @codemap::file_lines) {

    let fm = lines.file;

    // arbitrarily only print up to six lines of the error
    let max_lines = 6u;
    let mut elided = false;
    let mut display_lines = lines.lines;
    if vec::len(display_lines) > max_lines {
        display_lines = vec::slice(display_lines, 0u, max_lines);
        elided = true;
    }
    // Print the offending lines
    for display_lines.each {|line|
        io::stderr().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
        let s = codemap::get_line(fm, line as int) + "\n";
        io::stderr().write_str(s);
    }
    if elided {
        let last_line = display_lines[vec::len(display_lines) - 1u];
        let s = #fmt["%s:%u ", fm.name, last_line + 1u];
        let mut indent = str::len(s);
        let mut out = "";
        while indent > 0u { out += " "; indent -= 1u; }
        out += "...\n";
        io::stderr().write_str(out);
    }

    // If there's one line at fault we can easily point to the problem
    if vec::len(lines.lines) == 1u {
        let lo = codemap::lookup_char_pos(cm, sp.lo);
        let mut digits = 0u;
        let mut num = (lines.lines[0] + 1u) / 10u;

        // how many digits must be indent past?
        while num > 0u { num /= 10u; digits += 1u; }

        // indent past |name:## | and the 0-offset column location
        let mut left = str::len(fm.name) + digits + lo.col + 3u;
        let mut s = "";
        while left > 0u { str::push_char(s, ' '); left -= 1u; }

        s += "^";
        let hi = codemap::lookup_char_pos(cm, sp.hi);
        if hi.col != lo.col {
            // the ^ already takes up one space
            let mut width = hi.col - lo.col - 1u;
            while width > 0u { str::push_char(s, '~'); width -= 1u; }
        }
        io::stderr().write_str(s + "\n");
    }
}

fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
    option::iter (sp.expn_info) {|ei|
        let ss = option::map_default(ei.callie.span, "",
                               bind codemap::span_to_str(_, cm));
        print_diagnostic(ss, note,
                         #fmt("in expansion of #%s", ei.callie.name));
        let ss = codemap::span_to_str(ei.call_site, cm);
        print_diagnostic(ss, note, "expansion site");
        print_macro_backtrace(cm, ei.call_site);
    }
}

fn expect<T: copy>(diag: span_handler,
                   opt: option<T>, msg: fn() -> str) -> T {
    alt opt {
       some(t) { t }
       none { diag.handler().bug(msg()); }
    }
}
<commit_msg>syntax: More grammatical error message<commit_after>import std::term;
import io::writer_util;
import codemap::span;

export emitter, emit;
export level, fatal, error, warning, note;
export span_handler, handler, mk_span_handler, mk_handler;
export codemap_span_handler, codemap_handler;
export ice_msg;
export expect;

type emitter = fn@(cmsp: option<(codemap::codemap, span)>,
                   msg: str, lvl: level);

iface span_handler {
    fn span_fatal(sp: span, msg: str) -> !;
    fn span_err(sp: span, msg: str);
    fn span_warn(sp: span, msg: str);
    fn span_note(sp: span, msg: str);
    fn span_bug(sp: span, msg: str) -> !;
    fn span_unimpl(sp: span, msg: str) -> !;
    fn handler() -> handler;
}

iface handler {
    fn fatal(msg: str) -> !;
    fn err(msg: str);
    fn bump_err_count();
    fn has_errors() -> bool;
    fn abort_if_errors();
    fn warn(msg: str);
    fn note(msg: str);
    fn bug(msg: str) -> !;
    fn unimpl(msg: str) -> !;
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level);
}

type handler_t = @{
    mut err_count: uint,
    emit: emitter
};

type codemap_t = @{
    handler: handler,
    cm: codemap::codemap
};

impl codemap_span_handler of span_handler for codemap_t {
    fn span_fatal(sp: span, msg: str) -> ! {
        self.handler.emit(some((self.cm, sp)), msg, fatal);
        fail;
    }
    fn span_err(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, error);
        self.handler.bump_err_count();
    }
    fn span_warn(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, warning);
    }
    fn span_note(sp: span, msg: str) {
        self.handler.emit(some((self.cm, sp)), msg, note);
    }
    fn span_bug(sp: span, msg: str) -> ! {
        self.span_fatal(sp, ice_msg(msg));
    }
    fn span_unimpl(sp: span, msg: str) -> ! {
        self.span_bug(sp, "unimplemented " + msg);
    }
    fn handler() -> handler {
        self.handler
    }
}

impl codemap_handler of handler for handler_t {
    fn fatal(msg: str) -> ! {
        self.emit(none, msg, fatal);
        fail;
    }
    fn err(msg: str) {
        self.emit(none, msg, error);
        self.bump_err_count();
    }
    fn bump_err_count() {
        self.err_count += 1u;
    }
    fn has_errors() -> bool { self.err_count > 0u }
    fn abort_if_errors() {
        let s;
        alt self.err_count {
          0u { ret; }
          1u { s = "aborting due to previous error"; }
          _  { s = #fmt["aborting due to %u previous errors",
                        self.err_count]; }
        }
        self.fatal(s);
    }
    fn warn(msg: str) {
        self.emit(none, msg, warning);
    }
    fn note(msg: str) {
        self.emit(none, msg, note);
    }
    fn bug(msg: str) -> ! {
        self.fatal(ice_msg(msg));
    }
    fn unimpl(msg: str) -> ! { self.bug("unimplemented " + msg); }
    fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level) {
        self.emit(cmsp, msg, lvl);
    }
}

fn ice_msg(msg: str) -> str {
    #fmt["internal compiler error: %s", msg]
}

fn mk_span_handler(handler: handler, cm: codemap::codemap) -> span_handler {
    @{ handler: handler, cm: cm } as span_handler
}

fn mk_handler(emitter: option<emitter>) -> handler {

    let emit = alt emitter {
      some(e) { e }
      none {
        let f = fn@(cmsp: option<(codemap::codemap, span)>,
            msg: str, t: level) {
            emit(cmsp, msg, t);
        };
        f
      }
    };

    @{
        mut err_count: 0u,
        emit: emit
    } as handler
}

enum level {
    fatal,
    error,
    warning,
    note,
}

fn diagnosticstr(lvl: level) -> str {
    alt lvl {
      fatal { "error" }
      error { "error" }
      warning { "warning" }
      note { "note" }
    }
}

fn diagnosticcolor(lvl: level) -> u8 {
    alt lvl {
      fatal { term::color_bright_red }
      error { term::color_bright_red }
      warning { term::color_bright_yellow }
      note { term::color_bright_green }
    }
}

fn print_diagnostic(topic: str, lvl: level, msg: str) {
    if str::is_not_empty(topic) {
        io::stderr().write_str(#fmt["%s ", topic]);
    }
    if term::color_supported() {
        term::fg(io::stderr(), diagnosticcolor(lvl));
    }
    io::stderr().write_str(#fmt["%s:", diagnosticstr(lvl)]);
    if term::color_supported() {
        term::reset(io::stderr());
    }
    io::stderr().write_str(#fmt[" %s\n", msg]);
}

fn emit(cmsp: option<(codemap::codemap, span)>,
        msg: str, lvl: level) {
    alt cmsp {
      some((cm, sp)) {
        let sp = codemap::adjust_span(cm,sp);
        let ss = codemap::span_to_str(sp, cm);
        let lines = codemap::span_to_lines(sp, cm);
        print_diagnostic(ss, lvl, msg);
        highlight_lines(cm, sp, lines);
        print_macro_backtrace(cm, sp);
      }
      none {
        print_diagnostic("", lvl, msg);
      }
    }
}

fn highlight_lines(cm: codemap::codemap, sp: span,
                   lines: @codemap::file_lines) {

    let fm = lines.file;

    // arbitrarily only print up to six lines of the error
    let max_lines = 6u;
    let mut elided = false;
    let mut display_lines = lines.lines;
    if vec::len(display_lines) > max_lines {
        display_lines = vec::slice(display_lines, 0u, max_lines);
        elided = true;
    }
    // Print the offending lines
    for display_lines.each {|line|
        io::stderr().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
        let s = codemap::get_line(fm, line as int) + "\n";
        io::stderr().write_str(s);
    }
    if elided {
        let last_line = display_lines[vec::len(display_lines) - 1u];
        let s = #fmt["%s:%u ", fm.name, last_line + 1u];
        let mut indent = str::len(s);
        let mut out = "";
        while indent > 0u { out += " "; indent -= 1u; }
        out += "...\n";
        io::stderr().write_str(out);
    }

    // If there's one line at fault we can easily point to the problem
    if vec::len(lines.lines) == 1u {
        let lo = codemap::lookup_char_pos(cm, sp.lo);
        let mut digits = 0u;
        let mut num = (lines.lines[0] + 1u) / 10u;

        // how many digits must be indent past?
        while num > 0u { num /= 10u; digits += 1u; }

        // indent past |name:## | and the 0-offset column location
        let mut left = str::len(fm.name) + digits + lo.col + 3u;
        let mut s = "";
        while left > 0u { str::push_char(s, ' '); left -= 1u; }

        s += "^";
        let hi = codemap::lookup_char_pos(cm, sp.hi);
        if hi.col != lo.col {
            // the ^ already takes up one space
            let mut width = hi.col - lo.col - 1u;
            while width > 0u { str::push_char(s, '~'); width -= 1u; }
        }
        io::stderr().write_str(s + "\n");
    }
}

fn print_macro_backtrace(cm: codemap::codemap, sp: span) {
    option::iter (sp.expn_info) {|ei|
        let ss = option::map_default(ei.callie.span, "",
                               bind codemap::span_to_str(_, cm));
        print_diagnostic(ss, note,
                         #fmt("in expansion of #%s", ei.callie.name));
        let ss = codemap::span_to_str(ei.call_site, cm);
        print_diagnostic(ss, note, "expansion site");
        print_macro_backtrace(cm, ei.call_site);
    }
}

fn expect<T: copy>(diag: span_handler,
                   opt: option<T>, msg: fn() -> str) -> T {
    alt opt {
       some(t) { t }
       none { diag.handler().bug(msg()); }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

pub mod anoncreds;
pub mod crypto;
pub mod ledger;
pub mod pairwise;
pub mod pool;
pub mod did;
pub mod wallet;
pub mod blob_storage;
pub mod non_secrets;
pub mod payments;

#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(i32)]
pub enum ErrorCode
{
    Success = 0,

    // Common errors

    // Caller passed invalid value as param 1 (null, invalid json and etc..)
    CommonInvalidParam1 = 100,

    // Caller passed invalid value as param 2 (null, invalid json and etc..)
    CommonInvalidParam2 = 101,

    // Caller passed invalid value as param 3 (null, invalid json and etc..)
    CommonInvalidParam3 = 102,

    // Caller passed invalid value as param 4 (null, invalid json and etc..)
    CommonInvalidParam4 = 103,

    // Caller passed invalid value as param 5 (null, invalid json and etc..)
    CommonInvalidParam5 = 104,

    // Caller passed invalid value as param 6 (null, invalid json and etc..)
    CommonInvalidParam6 = 105,

    // Caller passed invalid value as param 7 (null, invalid json and etc..)
    CommonInvalidParam7 = 106,

    // Caller passed invalid value as param 8 (null, invalid json and etc..)
    CommonInvalidParam8 = 107,

    // Caller passed invalid value as param 9 (null, invalid json and etc..)
    CommonInvalidParam9 = 108,

    // Caller passed invalid value as param 10 (null, invalid json and etc..)
    CommonInvalidParam10 = 109,

    // Caller passed invalid value as param 11 (null, invalid json and etc..)
    CommonInvalidParam11 = 110,

    // Caller passed invalid value as param 12 (null, invalid json and etc..)
    CommonInvalidParam12 = 111,

    // Invalid library state was detected in runtime. It signals library bug
    CommonInvalidState = 112,

    // Object (json, config, key, credential and etc...) passed by library caller has invalid structure
    CommonInvalidStructure = 113,

    // IO Error
    CommonIOError = 114,

    // Caller passed invalid value as param 13 (null, invalid json and etc..)
    CommonInvalidParam13 = 115,

    // Caller passed invalid value as param 14 (null, invalid json and etc..)
    CommonInvalidParam14 = 116,

    // Wallet errors
    // Caller passed invalid wallet handle
    WalletInvalidHandle = 200,

    // Unknown type of wallet was passed on create_wallet
    WalletUnknownTypeError = 201,

    // Attempt to register already existing wallet type
    WalletTypeAlreadyRegisteredError = 202,

    // Attempt to create wallet with name used for another exists wallet
    WalletAlreadyExistsError = 203,

    // Requested entity id isn't present in wallet
    WalletNotFoundError = 204,

    // Trying to use wallet with pool that has different name
    WalletIncompatiblePoolError = 205,

    // Trying to open wallet that was opened already
    WalletAlreadyOpenedError = 206,

    // Attempt to open encrypted wallet with invalid credentials
    WalletAccessFailed = 207,

    // Input provided to wallet operations is considered not valid
    WalletInputError = 208,

    // Decoding of wallet data during input/output failed
    WalletDecodingError = 209,

    // Storage error occurred during wallet operation
    WalletStorageError = 210,

    // Error during encryption-related operations
    WalletEncryptonError = 211,

    // Requested wallet item not found
    WalletItemNotFound = 212,

    // Returned if wallet's add_record operation is used with record name that already exists
    WalletItemAlreadyExists = 213,

    // Returned if provided wallet query is invalid
    WalletQueryError = 214,

    // Returned if I/O error occurred during wallet operation
    WalletIOError = 215,

    // Returned if wallet input has invalid structure (currently used in wallet import)
    WalletStructureError = 216,

    // Returned if the wallet is not empty, but it is required (currently only when importing)
    WalletNotEmpty = 217,

    // Returned if path provided to wallet export already exists
    WalletExportPathExists = 218,

    // Returned if path provided to wallet import does not exist
    WalletImportPathDoesNotExist = 219,

    // Ledger errors
    // Trying to open pool ledger that wasn't created before
    PoolLedgerNotCreatedError = 300,

    // Caller passed invalid pool ledger handle
    PoolLedgerInvalidPoolHandle = 301,

    // Pool ledger terminated
    PoolLedgerTerminated = 302,

    // No concensus during ledger operation
    LedgerNoConsensusError = 303,

    // Attempt to parse invalid transaction response
    LedgerInvalidTransaction = 304,

    // Attempt to send transaction without the necessary privileges
    LedgerSecurityError = 305,

    // Attempt to create pool ledger config with name used for another existing pool
    PoolLedgerConfigAlreadyExistsError = 306,

    // Timeout for action
    PoolLedgerTimeout = 307,

    // Revocation registry is full and creation of new registry is necessary
    AnoncredsRevocationRegistryFullError = 400,

    AnoncredsInvalidUserRevocId = 401,

    // Attempt to generate master secret with duplicated name
    AnoncredsMasterSecretDuplicateNameError = 404,

    AnoncredsProofRejected = 405,

    AnoncredsCredentialRevoked = 406,

    // Attempt to create credential definition with duplicated id
    AnoncredsCredDefAlreadyExistsError = 407,

    // Crypto errors
    // Unknown format of DID entity keys
    UnknownCryptoTypeError = 500,

    // Attempt to create duplicate did
    DidAlreadyExistsError = 600,

    // Unknown payment method was given
    PaymentUnknownMethodError = 700,

    //No method were scraped from inputs/outputs or more than one were scraped
    PaymentIncompatibleMethodsError = 701,

    // Insufficient funds on inputs
    PaymentInsufficientFundsError = 702,
}
<commit_msg>Remove WalletIOError from API<commit_after>extern crate libc;

pub mod anoncreds;
pub mod crypto;
pub mod ledger;
pub mod pairwise;
pub mod pool;
pub mod did;
pub mod wallet;
pub mod blob_storage;
pub mod non_secrets;
pub mod payments;

#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(i32)]
pub enum ErrorCode
{
    Success = 0,

    // Common errors

    // Caller passed invalid value as param 1 (null, invalid json and etc..)
    CommonInvalidParam1 = 100,

    // Caller passed invalid value as param 2 (null, invalid json and etc..)
    CommonInvalidParam2 = 101,

    // Caller passed invalid value as param 3 (null, invalid json and etc..)
    CommonInvalidParam3 = 102,

    // Caller passed invalid value as param 4 (null, invalid json and etc..)
    CommonInvalidParam4 = 103,

    // Caller passed invalid value as param 5 (null, invalid json and etc..)
    CommonInvalidParam5 = 104,

    // Caller passed invalid value as param 6 (null, invalid json and etc..)
    CommonInvalidParam6 = 105,

    // Caller passed invalid value as param 7 (null, invalid json and etc..)
    CommonInvalidParam7 = 106,

    // Caller passed invalid value as param 8 (null, invalid json and etc..)
    CommonInvalidParam8 = 107,

    // Caller passed invalid value as param 9 (null, invalid json and etc..)
    CommonInvalidParam9 = 108,

    // Caller passed invalid value as param 10 (null, invalid json and etc..)
    CommonInvalidParam10 = 109,

    // Caller passed invalid value as param 11 (null, invalid json and etc..)
    CommonInvalidParam11 = 110,

    // Caller passed invalid value as param 12 (null, invalid json and etc..)
    CommonInvalidParam12 = 111,

    // Invalid library state was detected in runtime. It signals library bug
    CommonInvalidState = 112,

    // Object (json, config, key, credential and etc...) passed by library caller has invalid structure
    CommonInvalidStructure = 113,

    // IO Error
    CommonIOError = 114,

    // Caller passed invalid value as param 13 (null, invalid json and etc..)
    CommonInvalidParam13 = 115,

    // Caller passed invalid value as param 14 (null, invalid json and etc..)
    CommonInvalidParam14 = 116,

    // Wallet errors
    // Caller passed invalid wallet handle
    WalletInvalidHandle = 200,

    // Unknown type of wallet was passed on create_wallet
    WalletUnknownTypeError = 201,

    // Attempt to register already existing wallet type
    WalletTypeAlreadyRegisteredError = 202,

    // Attempt to create wallet with name used for another exists wallet
    WalletAlreadyExistsError = 203,

    // Requested entity id isn't present in wallet
    WalletNotFoundError = 204,

    // Trying to use wallet with pool that has different name
    WalletIncompatiblePoolError = 205,

    // Trying to open wallet that was opened already
    WalletAlreadyOpenedError = 206,

    // Attempt to open encrypted wallet with invalid credentials
    WalletAccessFailed = 207,

    // Input provided to wallet operations is considered not valid
    WalletInputError = 208,

    // Decoding of wallet data during input/output failed
    WalletDecodingError = 209,

    // Storage error occurred during wallet operation
    WalletStorageError = 210,

    // Error during encryption-related operations
    WalletEncryptonError = 211,

    // Requested wallet item not found
    WalletItemNotFound = 212,

    // Returned if wallet's add_record operation is used with record name that already exists
    WalletItemAlreadyExists = 213,

    // Returned if provided wallet query is invalid
    WalletQueryError = 214,

    // Returned if wallet input has invalid structure (currently used in wallet import)
    WalletStructureError = 215,

    // Returned if the wallet is not empty, but it is required (currently only when importing)
    WalletNotEmpty = 216,

    // Returned if path provided to wallet export already exists
    WalletExportPathExists = 217,

    // Returned if path provided to wallet import does not exist
    WalletImportPathDoesNotExist = 218,

    // Ledger errors
    // Trying to open pool ledger that wasn't created before
    PoolLedgerNotCreatedError = 300,

    // Caller passed invalid pool ledger handle
    PoolLedgerInvalidPoolHandle = 301,

    // Pool ledger terminated
    PoolLedgerTerminated = 302,

    // No concensus during ledger operation
    LedgerNoConsensusError = 303,

    // Attempt to parse invalid transaction response
    LedgerInvalidTransaction = 304,

    // Attempt to send transaction without the necessary privileges
    LedgerSecurityError = 305,

    // Attempt to create pool ledger config with name used for another existing pool
    PoolLedgerConfigAlreadyExistsError = 306,

    // Timeout for action
    PoolLedgerTimeout = 307,

    // Revocation registry is full and creation of new registry is necessary
    AnoncredsRevocationRegistryFullError = 400,

    AnoncredsInvalidUserRevocId = 401,

    // Attempt to generate master secret with duplicated name
    AnoncredsMasterSecretDuplicateNameError = 404,

    AnoncredsProofRejected = 405,

    AnoncredsCredentialRevoked = 406,

    // Attempt to create credential definition with duplicated id
    AnoncredsCredDefAlreadyExistsError = 407,

    // Crypto errors
    // Unknown format of DID entity keys
    UnknownCryptoTypeError = 500,

    // Attempt to create duplicate did
    DidAlreadyExistsError = 600,

    // Unknown payment method was given
    PaymentUnknownMethodError = 700,

    //No method were scraped from inputs/outputs or more than one were scraped
    PaymentIncompatibleMethodsError = 701,

    // Insufficient funds on inputs
    PaymentInsufficientFundsError = 702,
}
<|endoftext|>


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

use dom::bindings::codegen::EventBinding;
use dom::bindings::codegen::EventBinding::EventConstants;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::Fallible;
use dom::eventtarget::EventTarget;
use dom::window::Window;
use servo_util::str::DOMString;

use geom::point::Point2D;

pub enum Event_ {
    ResizeEvent(uint, uint),
    ReflowEvent,
    ClickEvent(uint, Point2D<f32>),
    MouseDownEvent(uint, Point2D<f32>),
    MouseUpEvent(uint, Point2D<f32>),
    MouseMoveEvent(Point2D<f32>)
}

#[deriving(Encodable)]
pub enum EventPhase {
    PhaseNone      = EventConstants::NONE,
    PhaseCapturing = EventConstants::CAPTURING_PHASE,
    PhaseAtTarget  = EventConstants::AT_TARGET,
    PhaseBubbling  = EventConstants::BUBBLING_PHASE,
}

#[deriving(Eq, Encodable)]
pub enum EventTypeId {
    HTMLEventTypeId,
    UIEventTypeId,
    MouseEventTypeId,
    KeyEventTypeId
}

#[deriving(Encodable)]
pub struct Event {
    pub type_id: EventTypeId,
    pub reflector_: Reflector,
    pub current_target: Option<JS<EventTarget>>,
    pub target: Option<JS<EventTarget>>,
    pub type_: DOMString,
    pub phase: EventPhase,
    pub canceled: bool,
    pub stop_propagation: bool,
    pub stop_immediate: bool,
    pub cancelable: bool,
    pub bubbles: bool,
    pub trusted: bool,
    pub dispatching: bool,
    pub initialized: bool,
}

impl Event {
    pub fn new_inherited(type_id: EventTypeId) -> Event {
        Event {
            type_id: type_id,
            reflector_: Reflector::new(),
            current_target: None,
            target: None,
            phase: PhaseNone,
            type_: ~"",
            canceled: false,
            cancelable: true,
            bubbles: false,
            trusted: false,
            dispatching: false,
            stop_propagation: false,
            stop_immediate: false,
            initialized: false,
        }
    }

    pub fn new(window: &JS<Window>) -> JS<Event> {
        reflect_dom_object(~Event::new_inherited(HTMLEventTypeId),
                           window,
                           EventBinding::Wrap)
    }

    pub fn EventPhase(&self) -> u16 {
        self.phase as u16
    }

    pub fn Type(&self) -> DOMString {
        self.type_.clone()
    }

    pub fn GetTarget(&self) -> Option<JS<EventTarget>> {
        self.target.clone()
    }

    pub fn GetCurrentTarget(&self) -> Option<JS<EventTarget>> {
        self.current_target.clone()
    }

    pub fn DefaultPrevented(&self) -> bool {
        self.canceled
    }

    pub fn PreventDefault(&mut self) {
        if self.cancelable {
            self.canceled = true
        }
    }

    pub fn StopPropagation(&mut self) {
        self.stop_propagation = true;
    }

    pub fn StopImmediatePropagation(&mut self) {
        self.stop_immediate = true;
        self.stop_propagation = true;
    }

    pub fn Bubbles(&self) -> bool {
        self.bubbles
    }

    pub fn Cancelable(&self) -> bool {
        self.cancelable
    }

    pub fn TimeStamp(&self) -> u64 {
        0
    }

    pub fn InitEvent(&mut self,
                     type_: DOMString,
                     bubbles: bool,
                     cancelable: bool) {
        self.initialized = true;
        if self.dispatching {
            return;
        }
        self.stop_propagation = false;
        self.stop_immediate = false;
        self.canceled = false;
        self.trusted = false;
        self.target = None;
        self.type_ = type_;
        self.bubbles = bubbles;
        self.cancelable = cancelable;
    }

    pub fn IsTrusted(&self) -> bool {
        self.trusted
    }

    pub fn Constructor(global: &JS<Window>,
                       type_: DOMString,
                       init: &EventBinding::EventInit) -> Fallible<JS<Event>> {
        let mut ev = Event::new(global);
        ev.get_mut().InitEvent(type_, init.bubbles, init.cancelable);
        Ok(ev)
    }
}

impl Reflectable for Event {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        &mut self.reflector_
    }
}
<commit_msg>Make TimeStamp in event.rs return the actual timestamp<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate time;

use dom::bindings::codegen::EventBinding;
use dom::bindings::codegen::EventBinding::EventConstants;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::Fallible;
use dom::eventtarget::EventTarget;
use dom::window::Window;
use servo_util::str::DOMString;

use geom::point::Point2D;

pub enum Event_ {
    ResizeEvent(uint, uint),
    ReflowEvent,
    ClickEvent(uint, Point2D<f32>),
    MouseDownEvent(uint, Point2D<f32>),
    MouseUpEvent(uint, Point2D<f32>),
    MouseMoveEvent(Point2D<f32>)
}

#[deriving(Encodable)]
pub enum EventPhase {
    PhaseNone      = EventConstants::NONE,
    PhaseCapturing = EventConstants::CAPTURING_PHASE,
    PhaseAtTarget  = EventConstants::AT_TARGET,
    PhaseBubbling  = EventConstants::BUBBLING_PHASE,
}

#[deriving(Eq, Encodable)]
pub enum EventTypeId {
    HTMLEventTypeId,
    UIEventTypeId,
    MouseEventTypeId,
    KeyEventTypeId
}

#[deriving(Encodable)]
pub struct Event {
    pub type_id: EventTypeId,
    pub reflector_: Reflector,
    pub current_target: Option<JS<EventTarget>>,
    pub target: Option<JS<EventTarget>>,
    pub type_: DOMString,
    pub phase: EventPhase,
    pub canceled: bool,
    pub stop_propagation: bool,
    pub stop_immediate: bool,
    pub cancelable: bool,
    pub bubbles: bool,
    pub trusted: bool,
    pub dispatching: bool,
    pub initialized: bool,
    pub timestamp: u64,
}

impl Event {
    pub fn new_inherited(type_id: EventTypeId) -> Event {
        Event {
            type_id: type_id,
            reflector_: Reflector::new(),
            current_target: None,
            target: None,
            phase: PhaseNone,
            type_: ~"",
            canceled: false,
            cancelable: true,
            bubbles: false,
            trusted: false,
            dispatching: false,
            stop_propagation: false,
            stop_immediate: false,
            initialized: false,
            timestamp: time::get_time().sec as u64,
        }
    }

    pub fn new(window: &JS<Window>) -> JS<Event> {
        reflect_dom_object(~Event::new_inherited(HTMLEventTypeId),
                           window,
                           EventBinding::Wrap)
    }

    pub fn EventPhase(&self) -> u16 {
        self.phase as u16
    }

    pub fn Type(&self) -> DOMString {
        self.type_.clone()
    }

    pub fn GetTarget(&self) -> Option<JS<EventTarget>> {
        self.target.clone()
    }

    pub fn GetCurrentTarget(&self) -> Option<JS<EventTarget>> {
        self.current_target.clone()
    }

    pub fn DefaultPrevented(&self) -> bool {
        self.canceled
    }

    pub fn PreventDefault(&mut self) {
        if self.cancelable {
            self.canceled = true
        }
    }

    pub fn StopPropagation(&mut self) {
        self.stop_propagation = true;
    }

    pub fn StopImmediatePropagation(&mut self) {
        self.stop_immediate = true;
        self.stop_propagation = true;
    }

    pub fn Bubbles(&self) -> bool {
        self.bubbles
    }

    pub fn Cancelable(&self) -> bool {
        self.cancelable
    }

    pub fn TimeStamp(&self) -> u64 {
        return self.timestamp;
    }

    pub fn InitEvent(&mut self,
                     type_: DOMString,
                     bubbles: bool,
                     cancelable: bool) {
        self.initialized = true;
        if self.dispatching {
            return;
        }
        self.stop_propagation = false;
        self.stop_immediate = false;
        self.canceled = false;
        self.trusted = false;
        self.target = None;
        self.type_ = type_;
        self.bubbles = bubbles;
        self.cancelable = cancelable;
    }

    pub fn IsTrusted(&self) -> bool {
        self.trusted
    }

    pub fn Constructor(global: &JS<Window>,
                       type_: DOMString,
                       init: &EventBinding::EventInit) -> Fallible<JS<Event>> {
        let mut ev = Event::new(global);
        ev.get_mut().InitEvent(type_, init.bubbles, init.cancelable);
        Ok(ev)
    }
}

impl Reflectable for Event {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        &mut self.reflector_
    }
}
<|endoftext|>


<commit_before>///! Mainly pages to be delivered and triggered from webui.
///! There are some static pages and few dynamical pages.
use super::{
    super::super::{config, net::peer_representation::PeerRepresentation},
    WebServerState,
};
use actix_files as fs;
use actix_web::{
    http::StatusCode,
    web::{self, HttpResponse},
    Responder,
};
use std::{
    ffi::OsString,
    string::String,
    sync::{Arc, Mutex},
};

/// dynamic development files
//#[get("/app.js")]
//fn app_js() -> Result<fs::NamedFile> {
//Ok(fs::NamedFile::open("src/ctrl/webui/js/app.js")?)
//}

#[allow(dead_code)]
pub async fn dyn_devel_html() -> impl Responder {
    fs::NamedFile::open("src/ctrl/webui/html/main_page.html")
}

#[allow(dead_code)]
pub async fn dyn_devel_js() -> impl Responder {
    fs::NamedFile::open("src/ctrl/webui/js/app.js")
}

pub async fn single_page(state: web::Data<Arc<Mutex<WebServerState>>>) -> impl Responder {
    // change state
    let mut data = state.lock().unwrap();
    let id = data.id;
    *(data.nr_connections.lock().unwrap()) += 1;
    let port = data.web_port;

    let id_page = replace_static_content(*config::webui::HTML_PAGE, &id, port);

    HttpResponse::build(StatusCode::OK)
        .content_type("text/html; charset=utf-8")
        .body(id_page)
}

pub async fn bootstrap_css(path: web::Path<(String,)>) -> impl Responder {
    let css = &*path.0;
    let output = match css {
        "bootstrap.css" => Some(*config::webui::bootstrap::CSS),
        "bootstrap.css.map" => Some(*config::webui::bootstrap::CSS_MAP),
        "bootstrap.min.css" => Some(*config::webui::bootstrap::CSS_MIN),
        "bootstrap.min.css.map" => Some(*config::webui::bootstrap::CSS_MIN_MAP),
        "bootstrap-grid.css" => Some(*config::webui::bootstrap::CSS_GRID),
        "bootstrap-grid.css.map" => Some(*config::webui::bootstrap::CSS_GRID_MAP),
        "bootstrap-grid.min.css" => Some(*config::webui::bootstrap::CSS_GRID_MIN),
        "bootstrap-grid.min.css.map" => Some(*config::webui::bootstrap::CSS_GRID_MIN_MAP),
        "bootstrap-reboot.css" => Some(*config::webui::bootstrap::CSS_REBOOT),
        "bootstrap-reboot.css.map" => Some(*config::webui::bootstrap::CSS_REBOOT_MAP),
        "bootstrap-reboot.min.css" => Some(*config::webui::bootstrap::CSS_REBOOT_MIN),
        "bootstrap-reboot.min.css.map" => Some(*config::webui::bootstrap::CSS_REBOOT_MIN_MAP),
        _ => {
            error!("CSS: not found {}", css);
            None
        }
    };
    if let Some(content) = output {
        HttpResponse::build(StatusCode::OK)
            .content_type("text/css; charset=utf-8")
            .body(content)
    } else {
        HttpResponse::build(StatusCode::NOT_FOUND)
            .content_type("text/css; charset=utf-8")
            .body("")
    }
}

pub async fn bootstrap_js(path: web::Path<(String,)>) -> impl Responder {
    let js = &*path.0;
    let output = match js {
        "bootstrap.js" => Some(*config::webui::bootstrap::JS),
        "bootstrap.js.map" => Some(*config::webui::bootstrap::JS_MAP),
        "bootstrap.min.js" => Some(*config::webui::bootstrap::JS_MIN),
        "bootstrap.min.js.map" => Some(*config::webui::bootstrap::JS_MIN_MAP),
        "bootstrap.bundle.js" => Some(*config::webui::bootstrap::JS_BUNDLE),
        "bootstrap.bundle.js.map" => Some(*config::webui::bootstrap::JS_BUNDLE_MAP),
        "bootstrap.bundle.min.js" => Some(*config::webui::bootstrap::JS_BUNDLE_MIN),
        "bootstrap.bundle.min.js.map" => Some(*config::webui::bootstrap::JS_BUNDLE_MIN_MAP),
        _ => {
            error!("JS: not found {}", js);
            None
        }
    };
    if let Some(content) = output {
        HttpResponse::build(StatusCode::OK)
            .content_type("application/javascript; charset=utf-8")
            .body(content)
    } else {
        HttpResponse::build(StatusCode::NOT_FOUND)
            .content_type("application/javascript; charset=utf-8")
            .body("")
    }
}

pub async fn js_app(state: web::Data<Arc<Mutex<WebServerState>>>) -> impl Responder {
    let data = state.lock().unwrap();
    let id = data.id;
    let port = data.web_port;

    let output = replace_static_content(*config::webui::JS_APP, &id, port);
    HttpResponse::build(StatusCode::OK)
        .content_type("application/javascript; charset=utf-8")
        .body(output)
}

fn replace_static_content(html_in: &str, id: &PeerRepresentation, port: u16) -> String {
    // short inline struct

    let id_string = std::format!("{:x?}", id);
    let hostname = hostname::get()
        .unwrap_or(OsString::from("undefined"))
        .into_string()
        .unwrap_or(String::from("undefined"));

    let changers: [ReplaceStatic; 8] = [
        ReplaceStatic {
            r: config::net::HTML_REPLACE_STATIC_URL_SOURCE,
            c: config::net::HTML_URL_SOURCE.to_string(),
        },
        ReplaceStatic {
            r: config::net::HTML_REPLACE_STATIC_WEB_ADDR,
            c: config::net::WEB_ADDR.to_string(),
        },
        ReplaceStatic {
            r: config::net::HTML_REPLACE_STATIC_WEB_PORT,
            c: port.to_string(),
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_WEBSOCKET,
            c: config::net::WEB_ADDR.to_string(),
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_PEER_HASH,
            c: id_string,
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_HOSTNAME,
            c: hostname,
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_PEER_PAGE,
            c: config::webui::PEER_PAGE.to_string(),
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_PATHS_MAX,
            c: config::data::PATHS_MAX.to_string(),
        },
    ];
    linear_LUT_replacer(html_in, &changers)
}

struct ReplaceStatic<'a> {
    r: &'a str,
    c: String,
}

#[allow(non_snake_case)]
fn linear_LUT_replacer(replace_this: &str, changers: &[ReplaceStatic]) -> String {
    let left_bracket = config::webui::HTML_REPLACER_BEGIN;
    let right_bracket = config::webui::HTML_REPLACER_END;

    let mut replace_this = replace_this.to_string();

    let mut begin = 0;
    while let Some(found_pattern_begin) = replace_this[begin..].find(left_bracket) {
        match &replace_this[found_pattern_begin..].find(right_bracket) {
            None => break,
            Some(pattern_end) => {
                let mrange = std::ops::Range {
                    start: begin + found_pattern_begin + left_bracket.len(),
                    end: found_pattern_begin + pattern_end,
                };
                let part = &replace_this[mrange];
                if let Some(good) = changers.iter().find(|el| el.r == part) {
                    let erange = std::ops::Range {
                        start: begin + found_pattern_begin,
                        end: found_pattern_begin + pattern_end + right_bracket.len(),
                    };
                    replace_this.replace_range(erange, &good.c);
                    begin += &good.c.len() + found_pattern_begin;
                } else {
                    begin += pattern_end;
                }
            }
        }
    }
    replace_this
}

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

    #[test]
    #[allow(non_snake_case)]
    fn quick_replace_LUT_tests() {
        let changers: [ReplaceStatic; 5] = [
            ReplaceStatic {
                r: config::net::HTML_REPLACE_STATIC_URL_SOURCE,
                c: config::net::HTML_URL_SOURCE.to_string(),
            },
            ReplaceStatic {
                r: "CAT",
                c: "cat".to_string(),
            },
            ReplaceStatic {
                r: "JUMP",
                c: "jumped".to_string(),
            },
            ReplaceStatic {
                r: "ON",
                c: " on ".to_string(),
            },
            ReplaceStatic {
                r: "TABLE",
                c: "table".to_string(),
            },
        ];
        let replace_this = "The <!---CAT---> <!---JUMP---><!---ON--->the <!---TABLE--->.";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "The cat jumped on the table.";
        assert_eq!(return_value, expect);

        let replace_this = "<!---JUMP---> <!---CAT---> <!---ON---> <!---CAT--->.";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "jumped cat  on  cat.";
        assert_eq!(return_value, expect);

        let replace_this = "<!---JUMP---><!---CAT--->";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "jumpedcat";
        assert_eq!(return_value, expect);

        let replace_this = "<!--JUMP--><!---CAT---><!--- -->";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "<!--JUMP-->cat<!--- -->";
        assert_eq!(return_value, expect);
    }
}
<commit_msg>[clean-up] basic updates after new compiler version warnings<commit_after>///! Mainly pages to be delivered and triggered from webui.
///! There are some static pages and few dynamical pages.
use super::{
    super::super::{config, net::peer_representation::PeerRepresentation},
    WebServerState,
};
use actix_files as fs;
use actix_web::{
    http::StatusCode,
    web::{self, HttpResponse},
    Responder,
};
use std::{
    ffi::OsString,
    string::String,
    sync::{Arc, Mutex},
};

/// dynamic development files
#[allow(dead_code)]
pub async fn dyn_devel_html() -> impl Responder {
    fs::NamedFile::open("src/ctrl/webui/html/main_page.html")
}

#[allow(dead_code)]
pub async fn dyn_devel_js() -> impl Responder {
    fs::NamedFile::open("src/ctrl/webui/js/app.js")
}

pub async fn single_page(state: web::Data<Arc<Mutex<WebServerState>>>) -> impl Responder {
    // change state
    let data = state.lock().unwrap();
    let id = data.id;
    *(data.nr_connections.lock().unwrap()) += 1;
    let port = data.web_port;

    let id_page = replace_static_content(*config::webui::HTML_PAGE, &id, port);

    HttpResponse::build(StatusCode::OK)
        .content_type("text/html; charset=utf-8")
        .body(id_page)
}

pub async fn bootstrap_css(path: web::Path<(String,)>) -> impl Responder {
    let css = &*path.0;
    let output = match css {
        "bootstrap.css" => Some(*config::webui::bootstrap::CSS),
        "bootstrap.css.map" => Some(*config::webui::bootstrap::CSS_MAP),
        "bootstrap.min.css" => Some(*config::webui::bootstrap::CSS_MIN),
        "bootstrap.min.css.map" => Some(*config::webui::bootstrap::CSS_MIN_MAP),
        "bootstrap-grid.css" => Some(*config::webui::bootstrap::CSS_GRID),
        "bootstrap-grid.css.map" => Some(*config::webui::bootstrap::CSS_GRID_MAP),
        "bootstrap-grid.min.css" => Some(*config::webui::bootstrap::CSS_GRID_MIN),
        "bootstrap-grid.min.css.map" => Some(*config::webui::bootstrap::CSS_GRID_MIN_MAP),
        "bootstrap-reboot.css" => Some(*config::webui::bootstrap::CSS_REBOOT),
        "bootstrap-reboot.css.map" => Some(*config::webui::bootstrap::CSS_REBOOT_MAP),
        "bootstrap-reboot.min.css" => Some(*config::webui::bootstrap::CSS_REBOOT_MIN),
        "bootstrap-reboot.min.css.map" => Some(*config::webui::bootstrap::CSS_REBOOT_MIN_MAP),
        _ => {
            error!("CSS: not found {}", css);
            None
        }
    };
    if let Some(content) = output {
        HttpResponse::build(StatusCode::OK)
            .content_type("text/css; charset=utf-8")
            .body(content)
    } else {
        HttpResponse::build(StatusCode::NOT_FOUND)
            .content_type("text/css; charset=utf-8")
            .body("")
    }
}

pub async fn bootstrap_js(path: web::Path<(String,)>) -> impl Responder {
    let js = &*path.0;
    let output = match js {
        "bootstrap.js" => Some(*config::webui::bootstrap::JS),
        "bootstrap.js.map" => Some(*config::webui::bootstrap::JS_MAP),
        "bootstrap.min.js" => Some(*config::webui::bootstrap::JS_MIN),
        "bootstrap.min.js.map" => Some(*config::webui::bootstrap::JS_MIN_MAP),
        "bootstrap.bundle.js" => Some(*config::webui::bootstrap::JS_BUNDLE),
        "bootstrap.bundle.js.map" => Some(*config::webui::bootstrap::JS_BUNDLE_MAP),
        "bootstrap.bundle.min.js" => Some(*config::webui::bootstrap::JS_BUNDLE_MIN),
        "bootstrap.bundle.min.js.map" => Some(*config::webui::bootstrap::JS_BUNDLE_MIN_MAP),
        _ => {
            error!("JS: not found {}", js);
            None
        }
    };
    if let Some(content) = output {
        HttpResponse::build(StatusCode::OK)
            .content_type("application/javascript; charset=utf-8")
            .body(content)
    } else {
        HttpResponse::build(StatusCode::NOT_FOUND)
            .content_type("application/javascript; charset=utf-8")
            .body("")
    }
}

pub async fn js_app(state: web::Data<Arc<Mutex<WebServerState>>>) -> impl Responder {
    let data = state.lock().unwrap();
    let id = data.id;
    let port = data.web_port;

    let output = replace_static_content(*config::webui::JS_APP, &id, port);
    HttpResponse::build(StatusCode::OK)
        .content_type("application/javascript; charset=utf-8")
        .body(output)
}

fn replace_static_content(html_in: &str, id: &PeerRepresentation, port: u16) -> String {
    // short inline struct

    let id_string = std::format!("{:x?}", id);
    let hostname = hostname::get()
        .unwrap_or(OsString::from("undefined"))
        .into_string()
        .unwrap_or(String::from("undefined"));

    let changers: [ReplaceStatic; 8] = [
        ReplaceStatic {
            r: config::net::HTML_REPLACE_STATIC_URL_SOURCE,
            c: config::net::HTML_URL_SOURCE.to_string(),
        },
        ReplaceStatic {
            r: config::net::HTML_REPLACE_STATIC_WEB_ADDR,
            c: config::net::WEB_ADDR.to_string(),
        },
        ReplaceStatic {
            r: config::net::HTML_REPLACE_STATIC_WEB_PORT,
            c: port.to_string(),
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_WEBSOCKET,
            c: config::net::WEB_ADDR.to_string(),
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_PEER_HASH,
            c: id_string,
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_HOSTNAME,
            c: hostname,
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_PEER_PAGE,
            c: config::webui::PEER_PAGE.to_string(),
        },
        ReplaceStatic {
            r: config::webui::HTML_REPLACE_PATHS_MAX,
            c: config::data::PATHS_MAX.to_string(),
        },
    ];
    linear_LUT_replacer(html_in, &changers)
}

struct ReplaceStatic<'a> {
    r: &'a str,
    c: String,
}

#[allow(non_snake_case)]
fn linear_LUT_replacer(replace_this: &str, changers: &[ReplaceStatic]) -> String {
    let left_bracket = config::webui::HTML_REPLACER_BEGIN;
    let right_bracket = config::webui::HTML_REPLACER_END;

    let mut replace_this = replace_this.to_string();

    let mut begin = 0;
    while let Some(found_pattern_begin) = replace_this[begin..].find(left_bracket) {
        match &replace_this[found_pattern_begin..].find(right_bracket) {
            None => break,
            Some(pattern_end) => {
                let mrange = std::ops::Range {
                    start: begin + found_pattern_begin + left_bracket.len(),
                    end: found_pattern_begin + pattern_end,
                };
                let part = &replace_this[mrange];
                if let Some(good) = changers.iter().find(|el| el.r == part) {
                    let erange = std::ops::Range {
                        start: begin + found_pattern_begin,
                        end: found_pattern_begin + pattern_end + right_bracket.len(),
                    };
                    replace_this.replace_range(erange, &good.c);
                    begin += &good.c.len() + found_pattern_begin;
                } else {
                    begin += pattern_end;
                }
            }
        }
    }
    replace_this
}

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

    #[test]
    #[allow(non_snake_case)]
    fn quick_replace_LUT_tests() {
        let changers: [ReplaceStatic; 5] = [
            ReplaceStatic {
                r: config::net::HTML_REPLACE_STATIC_URL_SOURCE,
                c: config::net::HTML_URL_SOURCE.to_string(),
            },
            ReplaceStatic {
                r: "CAT",
                c: "cat".to_string(),
            },
            ReplaceStatic {
                r: "JUMP",
                c: "jumped".to_string(),
            },
            ReplaceStatic {
                r: "ON",
                c: " on ".to_string(),
            },
            ReplaceStatic {
                r: "TABLE",
                c: "table".to_string(),
            },
        ];
        let replace_this = "The <!---CAT---> <!---JUMP---><!---ON--->the <!---TABLE--->.";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "The cat jumped on the table.";
        assert_eq!(return_value, expect);

        let replace_this = "<!---JUMP---> <!---CAT---> <!---ON---> <!---CAT--->.";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "jumped cat  on  cat.";
        assert_eq!(return_value, expect);

        let replace_this = "<!---JUMP---><!---CAT--->";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "jumpedcat";
        assert_eq!(return_value, expect);

        let replace_this = "<!--JUMP--><!---CAT---><!--- -->";
        let return_value = linear_LUT_replacer(replace_this, &changers);
        let expect = "<!--JUMP-->cat<!--- -->";
        assert_eq!(return_value, expect);
    }
}
<|endoftext|>