apply rustffmt on proxy, remove rustfmt.toml for now
This commit is contained in:
parent
d2c54b65de
commit
3f87213602
|
@ -1,84 +0,0 @@
|
||||||
# https://github.com/rust-lang-nursery/rustfmt/blob/master/Configurations.md
|
|
||||||
verbose = false
|
|
||||||
disable_all_formatting = false
|
|
||||||
skip_children = false
|
|
||||||
max_width = 100
|
|
||||||
error_on_line_overflow = false
|
|
||||||
error_on_line_overflow_comments = false
|
|
||||||
tab_spaces = 4
|
|
||||||
fn_call_width = 60
|
|
||||||
struct_lit_width = 18
|
|
||||||
struct_variant_width = 35
|
|
||||||
force_explicit_abi = true
|
|
||||||
newline_style = "Unix"
|
|
||||||
fn_brace_style = "SameLineWhere"
|
|
||||||
item_brace_style = "SameLineWhere"
|
|
||||||
control_style = "Rfc"
|
|
||||||
control_brace_style = "AlwaysSameLine"
|
|
||||||
impl_empty_single_line = true
|
|
||||||
trailing_comma = "Vertical"
|
|
||||||
trailing_semicolon = true
|
|
||||||
fn_empty_single_line = true
|
|
||||||
fn_single_line = false
|
|
||||||
fn_return_indent = "WithArgs"
|
|
||||||
fn_args_paren_newline = false
|
|
||||||
fn_args_density = "Tall"
|
|
||||||
fn_args_layout = "Block"
|
|
||||||
array_layout = "Block"
|
|
||||||
array_width = 60
|
|
||||||
array_horizontal_layout_threshold = 0
|
|
||||||
type_punctuation_density = "Wide"
|
|
||||||
where_style = "Rfc"
|
|
||||||
where_density = "CompressedIfEmpty"
|
|
||||||
where_layout = "Vertical"
|
|
||||||
where_pred_indent = "Visual"
|
|
||||||
generics_indent = "Block"
|
|
||||||
struct_lit_style = "Block"
|
|
||||||
struct_lit_multiline_style = "ForceMulti"
|
|
||||||
fn_call_style = "Block"
|
|
||||||
report_todo = "Never"
|
|
||||||
report_fixme = "Never"
|
|
||||||
chain_indent = "Block"
|
|
||||||
chain_one_line_max = 60
|
|
||||||
chain_split_single_child = false
|
|
||||||
imports_indent = "Block"
|
|
||||||
imports_layout = "HorizontalVertical"
|
|
||||||
reorder_extern_crates = true
|
|
||||||
reorder_extern_crates_in_group = true
|
|
||||||
reorder_imports = true
|
|
||||||
reorder_imports_in_group = true
|
|
||||||
reorder_imported_names = true
|
|
||||||
single_line_if_else_max_width = 50
|
|
||||||
format_strings = true
|
|
||||||
force_format_strings = false
|
|
||||||
take_source_hints = false
|
|
||||||
hard_tabs = false
|
|
||||||
wrap_comments = false
|
|
||||||
comment_width = 80
|
|
||||||
normalize_comments = false
|
|
||||||
wrap_match_arms = true
|
|
||||||
match_block_trailing_comma = true
|
|
||||||
indent_match_arms = true
|
|
||||||
match_pattern_separator_break_point = "Back"
|
|
||||||
closure_block_indent_threshold = 0
|
|
||||||
space_before_type_annotation = false
|
|
||||||
space_after_type_annotation_colon = true
|
|
||||||
space_before_struct_lit_field_colon = false
|
|
||||||
space_after_struct_lit_field_colon = true
|
|
||||||
space_before_bound = false
|
|
||||||
space_after_bound_colon = true
|
|
||||||
spaces_around_ranges = false
|
|
||||||
spaces_within_angle_brackets = false
|
|
||||||
spaces_within_square_brackets = false
|
|
||||||
spaces_within_parens = false
|
|
||||||
use_try_shorthand = true
|
|
||||||
write_mode = "Overwrite"
|
|
||||||
condense_wildcard_suffixes = false
|
|
||||||
combine_control_expr = true
|
|
||||||
struct_field_align_threshold = 0
|
|
||||||
remove_blank_lines_at_start_or_end_of_block = true
|
|
||||||
attributes_on_same_line_as_field = true
|
|
||||||
attributes_on_same_line_as_variant = true
|
|
||||||
multiline_closure_forces_block = false
|
|
||||||
multiline_match_arm_forces_block = false
|
|
||||||
merge_derives = true
|
|
|
@ -92,7 +92,8 @@ impl<T> Sender<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tx.unbounded_send(v)
|
self.tx
|
||||||
|
.unbounded_send(v)
|
||||||
.map_err(|se| SendError::NoReceiver(se.into_inner()))
|
.map_err(|se| SendError::NoReceiver(se.into_inner()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,8 +104,7 @@ impl<T> Sink for Sender<T> {
|
||||||
type SinkError = SendError<T>;
|
type SinkError = SendError<T>;
|
||||||
|
|
||||||
fn start_send(&mut self, item: T) -> StartSend<Self::SinkItem, Self::SinkError> {
|
fn start_send(&mut self, item: T) -> StartSend<Self::SinkItem, Self::SinkError> {
|
||||||
self.lossy_send(item)
|
self.lossy_send(item).map(|_| AsyncSink::Ready)
|
||||||
.map(|_| AsyncSink::Ready)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
|
fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
|
||||||
|
@ -136,8 +136,7 @@ impl<T> fmt::Debug for Sender<T> {
|
||||||
impl<T> SendError<T> {
|
impl<T> SendError<T> {
|
||||||
pub fn into_inner(self) -> T {
|
pub fn into_inner(self) -> T {
|
||||||
match self {
|
match self {
|
||||||
SendError::NoReceiver(v) |
|
SendError::NoReceiver(v) | SendError::Rejected(v) => v,
|
||||||
SendError::Rejected(v) => v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,8 @@ fn build_control() {
|
||||||
"../proto/proxy/destination/destination.proto",
|
"../proto/proxy/destination/destination.proto",
|
||||||
"../proto/proxy/telemetry/telemetry.proto",
|
"../proto/proxy/telemetry/telemetry.proto",
|
||||||
];
|
];
|
||||||
let server_files = &[
|
let server_files = &["../proto/proxy/tap/tap.proto"];
|
||||||
"../proto/proxy/tap/tap.proto",
|
let dirs = &["../proto"];
|
||||||
];
|
|
||||||
let dirs = &[
|
|
||||||
"../proto",
|
|
||||||
];
|
|
||||||
|
|
||||||
tower_grpc_build::Config::new()
|
tower_grpc_build::Config::new()
|
||||||
.enable_client(true)
|
.enable_client(true)
|
||||||
|
|
|
@ -5,4 +5,3 @@ pub fn init() -> Result<Config, config::Error> {
|
||||||
logging::init();
|
logging::init();
|
||||||
Config::load_from_env()
|
Config::load_from_env()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -65,14 +65,14 @@ impl<B> Bind<(), B> {
|
||||||
pub fn with_connect_timeout(self, connect_timeout: Duration) -> Self {
|
pub fn with_connect_timeout(self, connect_timeout: Duration) -> Self {
|
||||||
Self {
|
Self {
|
||||||
connect_timeout,
|
connect_timeout,
|
||||||
.. self
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_sensors(self, sensors: telemetry::Sensors) -> Self {
|
pub fn with_sensors(self, sensors: telemetry::Sensors) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sensors,
|
sensors,
|
||||||
.. self
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,6 @@ impl<B> Bind<(), B> {
|
||||||
_p: PhantomData,
|
_p: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Clone, B> Clone for Bind<C, B> {
|
impl<C: Clone, B> Clone for Bind<C, B> {
|
||||||
|
@ -139,14 +138,14 @@ where
|
||||||
&self.executor,
|
&self.executor,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.sensors.connect(c, &client_ctx )
|
self.sensors.connect(c, &client_ctx)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Establishes an HTTP/2.0 connection
|
// Establishes an HTTP/2.0 connection
|
||||||
let client = tower_h2::client::Client::new(
|
let client = tower_h2::client::Client::new(
|
||||||
connect,
|
connect,
|
||||||
self.h2_builder.clone(),
|
self.h2_builder.clone(),
|
||||||
::logging::context_executor(("client", *addr), self.executor.clone())
|
::logging::context_executor(("client", *addr), self.executor.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let h2_proxy = self.sensors.http(self.req_ids.clone(), client, &client_ctx);
|
let h2_proxy = self.sensors.http(self.req_ids.clone(), client, &client_ctx);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use url::{Host, HostAndPort, Url};
|
use url::{Host, HostAndPort, Url};
|
||||||
|
@ -123,16 +123,16 @@ impl Config {
|
||||||
None => DEFAULT_EVENT_BUFFER_CAPACITY,
|
None => DEFAULT_EVENT_BUFFER_CAPACITY,
|
||||||
Some(c) => match c.parse() {
|
Some(c) => match c.parse() {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(_) => return Err(Error::NotANumber(c))
|
Err(_) => return Err(Error::NotANumber(c)),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let metrics_flush_interval = match env::var(ENV_METRICS_FLUSH_INTERVAL_SECS).ok() {
|
let metrics_flush_interval = match env::var(ENV_METRICS_FLUSH_INTERVAL_SECS).ok() {
|
||||||
None => Duration::from_secs(DEFAULT_METRICS_FLUSH_INTERVAL_SECS),
|
None => Duration::from_secs(DEFAULT_METRICS_FLUSH_INTERVAL_SECS),
|
||||||
Some(c) => match c.parse() {
|
Some(c) => match c.parse() {
|
||||||
Ok(c) => Duration::from_secs(c),
|
Ok(c) => Duration::from_secs(c),
|
||||||
Err(_) => return Err(Error::NotANumber(c))
|
Err(_) => return Err(Error::NotANumber(c)),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
|
@ -147,11 +147,13 @@ impl Config {
|
||||||
},
|
},
|
||||||
private_forward: Addr::from_env_opt(ENV_PRIVATE_FORWARD)?,
|
private_forward: Addr::from_env_opt(ENV_PRIVATE_FORWARD)?,
|
||||||
|
|
||||||
public_connect_timeout: env::var(ENV_PUBLIC_CONNECT_TIMEOUT).ok()
|
public_connect_timeout: env::var(ENV_PUBLIC_CONNECT_TIMEOUT)
|
||||||
|
.ok()
|
||||||
.and_then(|c| c.parse().ok())
|
.and_then(|c| c.parse().ok())
|
||||||
.map(Duration::from_millis),
|
.map(Duration::from_millis),
|
||||||
|
|
||||||
private_connect_timeout: env::var(ENV_PRIVATE_CONNECT_TIMEOUT).ok()
|
private_connect_timeout: env::var(ENV_PRIVATE_CONNECT_TIMEOUT)
|
||||||
|
.ok()
|
||||||
.and_then(|c| c.parse().ok())
|
.and_then(|c| c.parse().ok())
|
||||||
.map(Duration::from_millis),
|
.map(Duration::from_millis),
|
||||||
|
|
||||||
|
@ -159,7 +161,10 @@ impl Config {
|
||||||
.unwrap_or_else(|_| DEFAULT_RESOLV_CONF.into())
|
.unwrap_or_else(|_| DEFAULT_RESOLV_CONF.into())
|
||||||
.into(),
|
.into(),
|
||||||
|
|
||||||
control_host_and_port: control_host_and_port_from_env(ENV_CONTROL_URL, DEFAULT_CONTROL_URL)?,
|
control_host_and_port: control_host_and_port_from_env(
|
||||||
|
ENV_CONTROL_URL,
|
||||||
|
DEFAULT_CONTROL_URL,
|
||||||
|
)?,
|
||||||
event_buffer_capacity,
|
event_buffer_capacity,
|
||||||
metrics_flush_interval,
|
metrics_flush_interval,
|
||||||
})
|
})
|
||||||
|
@ -177,8 +182,7 @@ impl Addr {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_env_or(key: &str, default: &str) -> Result<Addr, Error> {
|
fn from_env_or(key: &str, default: &str) -> Result<Addr, Error> {
|
||||||
let s = env::var(key)
|
let s = env::var(key).unwrap_or_else(|_| default.into());
|
||||||
.unwrap_or_else(|_| default.into());
|
|
||||||
|
|
||||||
s.parse()
|
s.parse()
|
||||||
}
|
}
|
||||||
|
@ -190,16 +194,20 @@ impl FromStr for Addr {
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match Url::parse(s) {
|
match Url::parse(s) {
|
||||||
Err(_) => Err(Error::InvalidAddr),
|
Err(_) => Err(Error::InvalidAddr),
|
||||||
Ok(u) => {
|
Ok(u) => match u.scheme() {
|
||||||
match u.scheme() {
|
|
||||||
"tcp" => match u.with_default_port(|_| Err(())) {
|
"tcp" => match u.with_default_port(|_| Err(())) {
|
||||||
Ok(HostAndPort { host: Host::Ipv4(ip), port }) => Ok(Addr(SocketAddr::new(ip.into(), port))),
|
Ok(HostAndPort {
|
||||||
Ok(HostAndPort { host: Host::Ipv6(ip), port }) => Ok(Addr(SocketAddr::new(ip.into(), port))),
|
host: Host::Ipv4(ip),
|
||||||
|
port,
|
||||||
|
}) => Ok(Addr(SocketAddr::new(ip.into(), port))),
|
||||||
|
Ok(HostAndPort {
|
||||||
|
host: Host::Ipv6(ip),
|
||||||
|
port,
|
||||||
|
}) => Ok(Addr(SocketAddr::new(ip.into(), port))),
|
||||||
_ => Err(Error::InvalidAddr),
|
_ => Err(Error::InvalidAddr),
|
||||||
},
|
},
|
||||||
_ => Err(Error::InvalidAddr),
|
_ => Err(Error::InvalidAddr),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,21 +220,37 @@ impl From<Addr> for SocketAddr {
|
||||||
|
|
||||||
fn control_host_and_port_from_env(key: &str, default: &str) -> Result<HostAndPort, Error> {
|
fn control_host_and_port_from_env(key: &str, default: &str) -> Result<HostAndPort, Error> {
|
||||||
let s = env::var(key).unwrap_or_else(|_| default.into());
|
let s = env::var(key).unwrap_or_else(|_| default.into());
|
||||||
let url = Url::parse(&s).map_err(|_| Error::ControlPlaneConfigError(s.clone(), UrlError::SyntaxError))?;
|
let url = Url::parse(&s).map_err(|_| {
|
||||||
let host = url.host().ok_or_else(|| Error::ControlPlaneConfigError(s.clone(), UrlError::MissingHost))?
|
Error::ControlPlaneConfigError(s.clone(), UrlError::SyntaxError)
|
||||||
|
})?;
|
||||||
|
let host = url.host()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::ControlPlaneConfigError(s.clone(), UrlError::MissingHost)
|
||||||
|
})?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
if url.scheme() != "tcp" {
|
if url.scheme() != "tcp" {
|
||||||
return Err(Error::ControlPlaneConfigError(s.clone(), UrlError::UnsupportedScheme));
|
return Err(Error::ControlPlaneConfigError(
|
||||||
|
s.clone(),
|
||||||
|
UrlError::UnsupportedScheme,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let port = url.port().ok_or_else(|| Error::ControlPlaneConfigError(s.clone(), UrlError::MissingPort))?;
|
let port = url.port().ok_or_else(|| {
|
||||||
|
Error::ControlPlaneConfigError(s.clone(), UrlError::MissingPort)
|
||||||
|
})?;
|
||||||
if url.path() != "/" {
|
if url.path() != "/" {
|
||||||
return Err(Error::ControlPlaneConfigError(s.clone(), UrlError::PathNotAllowed));
|
return Err(Error::ControlPlaneConfigError(
|
||||||
|
s.clone(),
|
||||||
|
UrlError::PathNotAllowed,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if url.fragment().is_some() {
|
if url.fragment().is_some() {
|
||||||
return Err(Error::ControlPlaneConfigError(s.clone(), UrlError::FragmentNotAllowed));
|
return Err(Error::ControlPlaneConfigError(
|
||||||
|
s.clone(),
|
||||||
|
UrlError::FragmentNotAllowed,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Ok(HostAndPort {
|
Ok(HostAndPort {
|
||||||
host,
|
host,
|
||||||
port
|
port,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,9 @@ pub struct Handshake {
|
||||||
impl Connection {
|
impl Connection {
|
||||||
/// Establish a connection backed by the provided `io`.
|
/// Establish a connection backed by the provided `io`.
|
||||||
pub fn handshake(io: PlaintextSocket) -> Handshake {
|
pub fn handshake(io: PlaintextSocket) -> Handshake {
|
||||||
Handshake { plaintext_socket: Some(io) }
|
Handshake {
|
||||||
|
plaintext_socket: Some(io),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,13 +50,11 @@ impl<T: Message, U: Message + Default> Codec for Protobuf<T, U> {
|
||||||
trace!("decode; bytes={}", buf.remaining());
|
trace!("decode; bytes={}", buf.remaining());
|
||||||
|
|
||||||
match Message::decode(buf) {
|
match Message::decode(buf) {
|
||||||
Ok(msg) => {
|
Ok(msg) => Ok(msg),
|
||||||
Ok(msg)
|
|
||||||
},
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
debug!("decode error: {:?}", err);
|
debug!("decode error: {:?}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,20 @@
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
|
||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::{HashSet, VecDeque};
|
||||||
|
use std::collections::hash_map::{Entry, HashMap};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use futures::{Async, Future, Poll, Stream};
|
use futures::{Async, Future, Poll, Stream};
|
||||||
use futures::sync::mpsc;
|
use futures::sync::mpsc;
|
||||||
use http::uri::Authority;
|
use http::uri::Authority;
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
use tower_discover::{Discover, Change};
|
use tower_discover::{Change, Discover};
|
||||||
use tower_grpc;
|
use tower_grpc;
|
||||||
|
|
||||||
use super::codec::Protobuf;
|
use super::codec::Protobuf;
|
||||||
use super::pb::common::{Destination, TcpAddress};
|
use super::pb::common::{Destination, TcpAddress};
|
||||||
use super::pb::proxy::destination::Update as PbUpdate;
|
use super::pb::proxy::destination::Update as PbUpdate;
|
||||||
|
use super::pb::proxy::destination::client::Destination as DestinationSvc;
|
||||||
|
use super::pb::proxy::destination::client::destination_methods::Get as GetRpc;
|
||||||
use super::pb::proxy::destination::update::Update as PbUpdate2;
|
use super::pb::proxy::destination::update::Update as PbUpdate2;
|
||||||
use super::pb::proxy::destination::client::{
|
|
||||||
Destination as DestinationSvc
|
|
||||||
};
|
|
||||||
use super::pb::proxy::destination::client::destination_methods::{
|
|
||||||
Get as GetRpc
|
|
||||||
};
|
|
||||||
|
|
||||||
pub type ClientBody = ::tower_grpc::client::codec::EncodingBody<
|
pub type ClientBody = ::tower_grpc::client::codec::EncodingBody<
|
||||||
Protobuf<Destination, PbUpdate>,
|
Protobuf<Destination, PbUpdate>,
|
||||||
|
@ -44,16 +40,12 @@ pub struct Background {
|
||||||
rx: mpsc::UnboundedReceiver<(Authority, mpsc::UnboundedSender<Update>)>,
|
rx: mpsc::UnboundedReceiver<(Authority, mpsc::UnboundedSender<Update>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiscoveryWatch<F> =
|
type DiscoveryWatch<F> = DestinationSet<
|
||||||
DestinationSet<
|
|
||||||
tower_grpc::client::Streaming<
|
tower_grpc::client::Streaming<
|
||||||
tower_grpc::client::ResponseFuture<
|
tower_grpc::client::ResponseFuture<Protobuf<Destination, PbUpdate>, F>,
|
||||||
Protobuf<Destination, PbUpdate>,
|
|
||||||
F,
|
|
||||||
>,
|
|
||||||
tower_grpc::client::codec::DecodingBody<Protobuf<Destination, PbUpdate>>,
|
tower_grpc::client::codec::DecodingBody<Protobuf<Destination, PbUpdate>>,
|
||||||
>
|
>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/// A future returned from `Background::work()`, doing the work of talking to
|
/// A future returned from `Background::work()`, doing the work of talking to
|
||||||
/// the controller destination API.
|
/// the controller destination API.
|
||||||
|
@ -97,9 +89,7 @@ pub trait Bind {
|
||||||
type BindError;
|
type BindError;
|
||||||
|
|
||||||
/// The discovered `Service` instance.
|
/// The discovered `Service` instance.
|
||||||
type Service: Service<Request = Self::Request,
|
type Service: Service<Request = Self::Request, Response = Self::Response, Error = Self::Error>;
|
||||||
Response = Self::Response,
|
|
||||||
Error = Self::Error>;
|
|
||||||
|
|
||||||
/// Bind a socket address with a service.
|
/// Bind a socket address with a service.
|
||||||
fn bind(&self, addr: &SocketAddr) -> Result<Self::Service, Self::BindError>;
|
fn bind(&self, addr: &SocketAddr) -> Result<Self::Service, Self::BindError>;
|
||||||
|
@ -111,11 +101,14 @@ pub trait Bind {
|
||||||
/// on the controller thread.
|
/// on the controller thread.
|
||||||
pub fn new() -> (Discovery, Background) {
|
pub fn new() -> (Discovery, Background) {
|
||||||
let (tx, rx) = mpsc::unbounded();
|
let (tx, rx) = mpsc::unbounded();
|
||||||
(Discovery {
|
(
|
||||||
|
Discovery {
|
||||||
tx,
|
tx,
|
||||||
}, Background {
|
},
|
||||||
|
Background {
|
||||||
rx,
|
rx,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==== impl Discovery =====
|
// ==== impl Discovery =====
|
||||||
|
@ -125,7 +118,9 @@ impl Discovery {
|
||||||
pub fn resolve<B>(&self, authority: &Authority, bind: B) -> Watch<B> {
|
pub fn resolve<B>(&self, authority: &Authority, bind: B) -> Watch<B> {
|
||||||
trace!("resolve; authority={:?}", authority);
|
trace!("resolve; authority={:?}", authority);
|
||||||
let (tx, rx) = mpsc::unbounded();
|
let (tx, rx) = mpsc::unbounded();
|
||||||
self.tx.unbounded_send((authority.clone(), tx)).expect("unbounded can't fail");
|
self.tx
|
||||||
|
.unbounded_send((authority.clone(), tx))
|
||||||
|
.expect("unbounded can't fail");
|
||||||
|
|
||||||
Watch {
|
Watch {
|
||||||
rx,
|
rx,
|
||||||
|
@ -137,7 +132,8 @@ impl Discovery {
|
||||||
// ==== impl Watch =====
|
// ==== impl Watch =====
|
||||||
|
|
||||||
impl<B> Discover for Watch<B>
|
impl<B> Discover for Watch<B>
|
||||||
where B: Bind,
|
where
|
||||||
|
B: Bind,
|
||||||
{
|
{
|
||||||
type Key = SocketAddr;
|
type Key = SocketAddr;
|
||||||
type Request = B::Request;
|
type Request = B::Request;
|
||||||
|
@ -158,8 +154,7 @@ where B: Bind,
|
||||||
|
|
||||||
match update {
|
match update {
|
||||||
Update::Insert(addr) => {
|
Update::Insert(addr) => {
|
||||||
let service = self.bind.bind(&addr)
|
let service = self.bind.bind(&addr).map_err(|_| ())?;
|
||||||
.map_err(|_| ())?;
|
|
||||||
|
|
||||||
Ok(Async::Ready(Change::Insert(addr, service)))
|
Ok(Async::Ready(Change::Insert(addr, service)))
|
||||||
}
|
}
|
||||||
|
@ -186,16 +181,16 @@ impl Background {
|
||||||
|
|
||||||
impl<F> DiscoveryWork<F>
|
impl<F> DiscoveryWork<F>
|
||||||
where
|
where
|
||||||
F: Future<Item=::http::Response<::tower_h2::RecvBody>>,
|
F: Future<Item = ::http::Response<::tower_h2::RecvBody>>,
|
||||||
F::Error: ::std::fmt::Debug,
|
F::Error: ::std::fmt::Debug,
|
||||||
{
|
{
|
||||||
pub fn poll_rpc<S>(&mut self, client: &mut S)
|
pub fn poll_rpc<S>(&mut self, client: &mut S)
|
||||||
where
|
where
|
||||||
S: Service<
|
S: Service<
|
||||||
Request=::http::Request<ClientBody>,
|
Request = ::http::Request<ClientBody>,
|
||||||
Response=F::Item,
|
Response = F::Item,
|
||||||
Error=F::Error,
|
Error = F::Error,
|
||||||
Future=F,
|
Future = F,
|
||||||
>,
|
>,
|
||||||
{
|
{
|
||||||
// This loop is make sure any streams that were found disconnected
|
// This loop is make sure any streams that were found disconnected
|
||||||
|
@ -215,10 +210,10 @@ where
|
||||||
fn poll_new_watches<S>(&mut self, mut client: &mut S)
|
fn poll_new_watches<S>(&mut self, mut client: &mut S)
|
||||||
where
|
where
|
||||||
S: Service<
|
S: Service<
|
||||||
Request=::http::Request<ClientBody>,
|
Request = ::http::Request<ClientBody>,
|
||||||
Response=F::Item,
|
Response = F::Item,
|
||||||
Error=F::Error,
|
Error = F::Error,
|
||||||
Future=F,
|
Future = F,
|
||||||
>,
|
>,
|
||||||
{
|
{
|
||||||
loop {
|
loop {
|
||||||
|
@ -226,11 +221,11 @@ where
|
||||||
match client.poll_ready() {
|
match client.poll_ready() {
|
||||||
Ok(Async::Ready(())) => {
|
Ok(Async::Ready(())) => {
|
||||||
self.rpc_ready = true;
|
self.rpc_ready = true;
|
||||||
},
|
}
|
||||||
Ok(Async::NotReady) => {
|
Ok(Async::NotReady) => {
|
||||||
self.rpc_ready = false;
|
self.rpc_ready = false;
|
||||||
break;
|
break;
|
||||||
},
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("Destination.Get poll_ready error: {:?}", err);
|
warn!("Destination.Get poll_ready error: {:?}", err);
|
||||||
self.rpc_ready = false;
|
self.rpc_ready = false;
|
||||||
|
@ -252,7 +247,7 @@ where
|
||||||
match self.destinations.entry(auth) {
|
match self.destinations.entry(auth) {
|
||||||
Entry::Occupied(mut occ) => {
|
Entry::Occupied(mut occ) => {
|
||||||
occ.get_mut().tx = tx;
|
occ.get_mut().tx = tx;
|
||||||
},
|
}
|
||||||
Entry::Vacant(vac) => {
|
Entry::Vacant(vac) => {
|
||||||
let req = Destination {
|
let req = Destination {
|
||||||
scheme: "k8s".into(),
|
scheme: "k8s".into(),
|
||||||
|
@ -267,11 +262,11 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Ok(Async::Ready(None)) => {
|
Ok(Async::Ready(None)) => {
|
||||||
trace!("Discover tx is dropped, shutdown?");
|
trace!("Discover tx is dropped, shutdown?");
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
Ok(Async::NotReady) => break,
|
Ok(Async::NotReady) => break,
|
||||||
Err(_) => unreachable!("unbounded receiver doesn't error"),
|
Err(_) => unreachable!("unbounded receiver doesn't error"),
|
||||||
}
|
}
|
||||||
|
@ -282,10 +277,10 @@ where
|
||||||
fn poll_reconnect<S>(&mut self, client: &mut S) -> bool
|
fn poll_reconnect<S>(&mut self, client: &mut S) -> bool
|
||||||
where
|
where
|
||||||
S: Service<
|
S: Service<
|
||||||
Request=::http::Request<ClientBody>,
|
Request = ::http::Request<ClientBody>,
|
||||||
Response=F::Item,
|
Response = F::Item,
|
||||||
Error=F::Error,
|
Error = F::Error,
|
||||||
Future=F,
|
Future = F,
|
||||||
>,
|
>,
|
||||||
{
|
{
|
||||||
debug_assert!(self.rpc_ready);
|
debug_assert!(self.rpc_ready);
|
||||||
|
@ -316,40 +311,37 @@ where
|
||||||
}
|
}
|
||||||
let needs_reconnect = 'set: loop {
|
let needs_reconnect = 'set: loop {
|
||||||
match set.rx.poll() {
|
match set.rx.poll() {
|
||||||
Ok(Async::Ready(Some(update))) => {
|
Ok(Async::Ready(Some(update))) => match update.update {
|
||||||
match update.update {
|
Some(PbUpdate2::Add(a_set)) => for addr in a_set.addrs {
|
||||||
Some(PbUpdate2::Add(a_set)) => {
|
|
||||||
for addr in a_set.addrs {
|
|
||||||
if let Some(addr) = addr.addr.and_then(pb_to_sock_addr) {
|
if let Some(addr) = addr.addr.and_then(pb_to_sock_addr) {
|
||||||
if set.addrs.insert(addr) {
|
if set.addrs.insert(addr) {
|
||||||
trace!("update {:?} for {:?}", addr, auth);
|
trace!("update {:?} for {:?}", addr, auth);
|
||||||
let _ = set.tx.unbounded_send(Update::Insert(addr));
|
let _ = set.tx.unbounded_send(Update::Insert(addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Some(PbUpdate2::Remove(r_set)) => {
|
Some(PbUpdate2::Remove(r_set)) => for addr in r_set.addrs {
|
||||||
for addr in r_set.addrs {
|
|
||||||
if let Some(addr) = pb_to_sock_addr(addr) {
|
if let Some(addr) = pb_to_sock_addr(addr) {
|
||||||
if set.addrs.remove(&addr) {
|
if set.addrs.remove(&addr) {
|
||||||
trace!("remove {:?} for {:?}", addr, auth);
|
trace!("remove {:?} for {:?}", addr, auth);
|
||||||
let _ = set.tx.unbounded_send(Update::Remove(addr));
|
let _ = set.tx.unbounded_send(Update::Remove(addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
None => (),
|
None => (),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Ok(Async::Ready(None)) => {
|
Ok(Async::Ready(None)) => {
|
||||||
trace!("Destination.Get stream ended for {:?}, must reconnect", auth);
|
trace!(
|
||||||
|
"Destination.Get stream ended for {:?}, must reconnect",
|
||||||
|
auth
|
||||||
|
);
|
||||||
break 'set true;
|
break 'set true;
|
||||||
},
|
}
|
||||||
Ok(Async::NotReady) => break 'set false,
|
Ok(Async::NotReady) => break 'set false,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("Destination.Get stream errored for {:?}: {:?}", auth, err);
|
warn!("Destination.Get stream errored for {:?}: {:?}", auth, err);
|
||||||
break 'set true;
|
break 'set true;
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if needs_reconnect {
|
if needs_reconnect {
|
||||||
|
@ -363,7 +355,8 @@ where
|
||||||
// ===== impl Bind =====
|
// ===== impl Bind =====
|
||||||
|
|
||||||
impl<F, S, E> Bind for F
|
impl<F, S, E> Bind for F
|
||||||
where F: Fn(&SocketAddr) -> Result<S, E>,
|
where
|
||||||
|
F: Fn(&SocketAddr) -> Result<S, E>,
|
||||||
S: Service,
|
S: Service,
|
||||||
{
|
{
|
||||||
type Request = S::Request;
|
type Request = S::Request;
|
||||||
|
@ -378,8 +371,8 @@ where F: Fn(&SocketAddr) -> Result<S, E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pb_to_sock_addr(pb: TcpAddress) -> Option<SocketAddr> {
|
fn pb_to_sock_addr(pb: TcpAddress) -> Option<SocketAddr> {
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
|
||||||
use super::pb::common::ip_address::Ip;
|
use super::pb::common::ip_address::Ip;
|
||||||
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
/*
|
/*
|
||||||
current structure is:
|
current structure is:
|
||||||
TcpAddress {
|
TcpAddress {
|
||||||
|
@ -401,7 +394,7 @@ fn pb_to_sock_addr(pb: TcpAddress) -> Option<SocketAddr> {
|
||||||
Some(Ip::Ipv4(octets)) => {
|
Some(Ip::Ipv4(octets)) => {
|
||||||
let ipv4 = Ipv4Addr::from(octets);
|
let ipv4 = Ipv4Addr::from(octets);
|
||||||
Some(SocketAddr::from((ipv4, pb.port as u16)))
|
Some(SocketAddr::from((ipv4, pb.port as u16)))
|
||||||
},
|
}
|
||||||
Some(Ip::Ipv6(v6)) => {
|
Some(Ip::Ipv6(v6)) => {
|
||||||
let octets = [
|
let octets = [
|
||||||
(v6.first >> 56) as u8,
|
(v6.first >> 56) as u8,
|
||||||
|
@ -423,7 +416,7 @@ fn pb_to_sock_addr(pb: TcpAddress) -> Option<SocketAddr> {
|
||||||
];
|
];
|
||||||
let ipv6 = Ipv6Addr::from(octets);
|
let ipv6 = Ipv6Addr::from(octets);
|
||||||
Some(SocketAddr::from((ipv6, pb.port as u16)))
|
Some(SocketAddr::from((ipv6, pb.port as u16)))
|
||||||
},
|
}
|
||||||
None => None,
|
None => None,
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::marker::PhantomData;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::{Async, Future, future, Poll, Stream};
|
use futures::{future, Async, Future, Poll, Stream};
|
||||||
use h2;
|
use h2;
|
||||||
use http;
|
use http;
|
||||||
use tokio_core::reactor::{Handle, Timeout};
|
use tokio_core::reactor::{Handle, Timeout};
|
||||||
|
@ -59,15 +59,22 @@ impl Control {
|
||||||
// ===== impl Background =====
|
// ===== impl Background =====
|
||||||
|
|
||||||
impl Background {
|
impl Background {
|
||||||
pub fn bind<S>(self, events: S, host_and_port: HostAndPort, dns_config: dns::Config, executor: &Handle) -> Box<Future<Item=(), Error=()>>
|
pub fn bind<S>(
|
||||||
|
self,
|
||||||
|
events: S,
|
||||||
|
host_and_port: HostAndPort,
|
||||||
|
dns_config: dns::Config,
|
||||||
|
executor: &Handle,
|
||||||
|
) -> Box<Future<Item = (), Error = ()>>
|
||||||
where
|
where
|
||||||
S: Stream<Item=ReportRequest, Error=()> + 'static,
|
S: Stream<Item = ReportRequest, Error = ()> + 'static,
|
||||||
{
|
{
|
||||||
// Build up the Controller Client Stack
|
// Build up the Controller Client Stack
|
||||||
let mut client = {
|
let mut client = {
|
||||||
let ctx = ("controller-client", format!("{}", host_and_port));
|
let ctx = ("controller-client", format!("{}", host_and_port));
|
||||||
let scheme = http::uri::Scheme::from_shared(Bytes::from_static(b"http")).unwrap();
|
let scheme = http::uri::Scheme::from_shared(Bytes::from_static(b"http")).unwrap();
|
||||||
let authority = http::uri::Authority::from_shared(format!("{}", host_and_port).into()).unwrap();
|
let authority =
|
||||||
|
http::uri::Authority::from_shared(format!("{}", host_and_port).into()).unwrap();
|
||||||
|
|
||||||
let dns_resolver = dns::Resolver::new(dns_config, executor);
|
let dns_resolver = dns::Resolver::new(dns_config, executor);
|
||||||
let connect = TimeoutConnect::new(
|
let connect = TimeoutConnect::new(
|
||||||
|
@ -78,7 +85,7 @@ impl Background {
|
||||||
let h2_client = tower_h2::client::Client::new(
|
let h2_client = tower_h2::client::Client::new(
|
||||||
connect,
|
connect,
|
||||||
h2::client::Builder::default(),
|
h2::client::Builder::default(),
|
||||||
::logging::context_executor(ctx, executor.clone())
|
::logging::context_executor(ctx, executor.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,7 +155,7 @@ where
|
||||||
self.waiting = true;
|
self.waiting = true;
|
||||||
self.timer.reset(Instant::now() + self.wait_dur);
|
self.timer.reset(Instant::now() + self.wait_dur);
|
||||||
Ok(Async::NotReady)
|
Ok(Async::NotReady)
|
||||||
},
|
}
|
||||||
ok => ok,
|
ok => ok,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +184,7 @@ impl<S> AddOrigin<S> {
|
||||||
|
|
||||||
impl<S, B> Service for AddOrigin<S>
|
impl<S, B> Service for AddOrigin<S>
|
||||||
where
|
where
|
||||||
S: Service<Request=http::Request<B>>,
|
S: Service<Request = http::Request<B>>,
|
||||||
{
|
{
|
||||||
type Request = http::Request<B>;
|
type Request = http::Request<B>;
|
||||||
type Response = S::Response;
|
type Response = S::Response;
|
||||||
|
@ -205,7 +212,7 @@ struct EnumService<S, B>(S, PhantomData<B>);
|
||||||
|
|
||||||
impl<S, B> Service for EnumService<S, B>
|
impl<S, B> Service for EnumService<S, B>
|
||||||
where
|
where
|
||||||
S: Service<Request=http::Request<GrpcEncodingBody>>,
|
S: Service<Request = http::Request<GrpcEncodingBody>>,
|
||||||
B: Into<GrpcEncodingBody>,
|
B: Into<GrpcEncodingBody>,
|
||||||
{
|
{
|
||||||
type Request = http::Request<B>;
|
type Request = http::Request<B>;
|
||||||
|
@ -256,7 +263,6 @@ impl tower_h2::Body for GrpcEncodingBody {
|
||||||
GrpcEncodingBody::DestinationGet(ref mut b) => b.poll_trailers(),
|
GrpcEncodingBody::DestinationGet(ref mut b) => b.poll_trailers(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<self::telemetry::ClientBody> for GrpcEncodingBody {
|
impl From<self::telemetry::ClientBody> for GrpcEncodingBody {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use futures::{future, Stream, Poll};
|
use futures::{future, Poll, Stream};
|
||||||
use futures_mpsc_lossy;
|
use futures_mpsc_lossy;
|
||||||
use ordermap::OrderMap;
|
use ordermap::OrderMap;
|
||||||
use tower_grpc::{self, Request, Response};
|
use tower_grpc::{self, Request, Response};
|
||||||
use tower_grpc::codegen::server::grpc::ServerStreamingService;
|
use tower_grpc::codegen::server::grpc::ServerStreamingService;
|
||||||
|
|
||||||
use control::pb::common::TapEvent;
|
use control::pb::common::TapEvent;
|
||||||
use control::pb::proxy::tap::{ObserveRequest};
|
use control::pb::proxy::tap::ObserveRequest;
|
||||||
|
use convert::*;
|
||||||
use ctx;
|
use ctx;
|
||||||
use telemetry::Event;
|
use telemetry::Event;
|
||||||
use telemetry::tap::{Tap, Taps};
|
use telemetry::tap::{Tap, Taps};
|
||||||
use convert::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Observe {
|
pub struct Observe {
|
||||||
|
@ -58,10 +58,14 @@ impl ServerStreamingService for Observe {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, req) = req.into_http().into_parts();
|
let (_, req) = req.into_http().into_parts();
|
||||||
let (tap, rx) = match req.match_.and_then(|m| Tap::new(&m, self.tap_capacity).ok()) {
|
let (tap, rx) = match req.match_
|
||||||
|
.and_then(|m| Tap::new(&m, self.tap_capacity).ok())
|
||||||
|
{
|
||||||
Some(m) => m,
|
Some(m) => m,
|
||||||
None => {
|
None => {
|
||||||
return future::err(tower_grpc::Error::Grpc(tower_grpc::Status::INVALID_ARGUMENT));
|
return future::err(tower_grpc::Error::Grpc(
|
||||||
|
tower_grpc::Status::INVALID_ARGUMENT,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use http;
|
use http;
|
||||||
|
|
||||||
|
use convert::*;
|
||||||
use ctx;
|
use ctx;
|
||||||
use telemetry::Event;
|
use telemetry::Event;
|
||||||
use convert::*;
|
|
||||||
|
|
||||||
// re-export proxy here since we dont care about the other dirs
|
// re-export proxy here since we dont care about the other dirs
|
||||||
pub use self::proxy::*;
|
pub use self::proxy::*;
|
||||||
|
@ -57,7 +57,7 @@ fn pb_response_end(
|
||||||
source: Some((&ctx.server.remote).into()),
|
source: Some((&ctx.server.remote).into()),
|
||||||
target: Some((&ctx.client.remote).into()),
|
target: Some((&ctx.client.remote).into()),
|
||||||
event: Some(tap_event::Event::Http(tap_event::Http {
|
event: Some(tap_event::Event::Http(tap_event::Http {
|
||||||
event: Some(tap_event::http::Event::ResponseEnd(end))
|
event: Some(tap_event::http::Event::ResponseEnd(end)),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,8 @@ impl fmt::Display for InvalidMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for InvalidMethod {
|
impl Error for InvalidMethod {
|
||||||
#[inline] fn description(&self) -> &str {
|
#[inline]
|
||||||
|
fn description(&self) -> &str {
|
||||||
"invalid http method"
|
"invalid http method"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +89,8 @@ impl fmt::Display for InvalidScheme {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for InvalidScheme {
|
impl Error for InvalidScheme {
|
||||||
#[inline] fn description(&self) -> &str {
|
#[inline]
|
||||||
|
fn description(&self) -> &str {
|
||||||
"invalid http scheme"
|
"invalid http scheme"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +105,8 @@ impl fmt::Display for UnknownEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for UnknownEvent {
|
impl Error for UnknownEvent {
|
||||||
#[inline] fn description(&self) -> &str {
|
#[inline]
|
||||||
|
fn description(&self) -> &str {
|
||||||
"unknown tap event"
|
"unknown tap event"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +127,8 @@ impl<'a> TryFrom<&'a Event> for common::TapEvent {
|
||||||
}),
|
}),
|
||||||
method: Some((&ctx.method).into()),
|
method: Some((&ctx.method).into()),
|
||||||
scheme: ctx.uri.scheme().map(|s| s.into()),
|
scheme: ctx.uri.scheme().map(|s| s.into()),
|
||||||
authority: ctx.uri.authority_part()
|
authority: ctx.uri
|
||||||
|
.authority_part()
|
||||||
.map(|a| a.as_str())
|
.map(|a| a.as_str())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -135,10 +139,10 @@ impl<'a> TryFrom<&'a Event> for common::TapEvent {
|
||||||
source: Some((&ctx.server.remote).into()),
|
source: Some((&ctx.server.remote).into()),
|
||||||
target: Some((&ctx.client.remote).into()),
|
target: Some((&ctx.client.remote).into()),
|
||||||
event: Some(tap_event::Event::Http(tap_event::Http {
|
event: Some(tap_event::Event::Http(tap_event::Http {
|
||||||
event: Some(tap_event::http::Event::RequestInit(init))
|
event: Some(tap_event::http::Event::RequestInit(init)),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
Event::StreamResponseOpen(ref ctx, ref rsp) => {
|
Event::StreamResponseOpen(ref ctx, ref rsp) => {
|
||||||
let init = tap_event::http::ResponseInit {
|
let init = tap_event::http::ResponseInit {
|
||||||
|
@ -155,40 +159,30 @@ impl<'a> TryFrom<&'a Event> for common::TapEvent {
|
||||||
source: Some((&ctx.request.server.remote).into()),
|
source: Some((&ctx.request.server.remote).into()),
|
||||||
target: Some((&ctx.request.client.remote).into()),
|
target: Some((&ctx.request.client.remote).into()),
|
||||||
event: Some(tap_event::Event::Http(tap_event::Http {
|
event: Some(tap_event::Event::Http(tap_event::Http {
|
||||||
event: Some(tap_event::http::Event::ResponseInit(init))
|
event: Some(tap_event::http::Event::ResponseInit(init)),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::StreamRequestFail(ref ctx, ref fail) => {
|
Event::StreamRequestFail(ref ctx, ref fail) => {
|
||||||
pb_response_end(
|
pb_response_end(ctx, fail.since_request_open, None, 0, 0)
|
||||||
ctx,
|
|
||||||
fail.since_request_open,
|
|
||||||
None,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::StreamResponseEnd(ref ctx, ref end) => {
|
Event::StreamResponseEnd(ref ctx, ref end) => pb_response_end(
|
||||||
pb_response_end(
|
|
||||||
&ctx.request,
|
&ctx.request,
|
||||||
end.since_request_open,
|
end.since_request_open,
|
||||||
Some(end.since_response_open),
|
Some(end.since_response_open),
|
||||||
end.bytes_sent,
|
end.bytes_sent,
|
||||||
end.grpc_status.unwrap_or(0),
|
end.grpc_status.unwrap_or(0),
|
||||||
)
|
),
|
||||||
}
|
|
||||||
|
|
||||||
Event::StreamResponseFail(ref ctx, ref fail) => {
|
Event::StreamResponseFail(ref ctx, ref fail) => pb_response_end(
|
||||||
pb_response_end(
|
|
||||||
&ctx.request,
|
&ctx.request,
|
||||||
fail.since_request_open,
|
fail.since_request_open,
|
||||||
Some(fail.since_response_open),
|
Some(fail.since_response_open),
|
||||||
fail.bytes_sent,
|
fail.bytes_sent,
|
||||||
0,
|
0,
|
||||||
)
|
),
|
||||||
}
|
|
||||||
|
|
||||||
_ => return Err(UnknownEvent),
|
_ => return Err(UnknownEvent),
|
||||||
};
|
};
|
||||||
|
@ -200,12 +194,11 @@ impl<'a> TryFrom<&'a Event> for common::TapEvent {
|
||||||
impl<'a> TryFrom<&'a common::http_method::Type> for http::Method {
|
impl<'a> TryFrom<&'a common::http_method::Type> for http::Method {
|
||||||
type Err = InvalidMethod;
|
type Err = InvalidMethod;
|
||||||
fn try_from(m: &'a common::http_method::Type) -> Result<Self, Self::Err> {
|
fn try_from(m: &'a common::http_method::Type) -> Result<Self, Self::Err> {
|
||||||
use http::HttpTryFrom;
|
|
||||||
use self::common::http_method::*;
|
use self::common::http_method::*;
|
||||||
|
use http::HttpTryFrom;
|
||||||
|
|
||||||
match *m {
|
match *m {
|
||||||
Type::Registered(reg) => {
|
Type::Registered(reg) => if reg == Registered::Get.into() {
|
||||||
if reg == Registered::Get.into() {
|
|
||||||
Ok(http::Method::GET)
|
Ok(http::Method::GET)
|
||||||
} else if reg == Registered::Post.into() {
|
} else if reg == Registered::Post.into() {
|
||||||
Ok(http::Method::POST)
|
Ok(http::Method::POST)
|
||||||
|
@ -225,12 +218,11 @@ impl<'a> TryFrom<&'a common::http_method::Type> for http::Method {
|
||||||
Ok(http::Method::TRACE)
|
Ok(http::Method::TRACE)
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidMethod)
|
Err(InvalidMethod)
|
||||||
|
},
|
||||||
|
Type::Unregistered(ref m) => {
|
||||||
|
HttpTryFrom::try_from(m.as_str()).map_err(|_| InvalidMethod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Unregistered(ref m) =>
|
|
||||||
HttpTryFrom::try_from(m.as_str())
|
|
||||||
.map_err(|_| InvalidMethod),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,15 +232,13 @@ impl<'a> TryInto<String> for &'a common::scheme::Type {
|
||||||
use self::common::scheme::*;
|
use self::common::scheme::*;
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Type::Registered(reg) => {
|
Type::Registered(reg) => if reg == Registered::Http.into() {
|
||||||
if reg == Registered::Http.into() {
|
|
||||||
Ok("http".into())
|
Ok("http".into())
|
||||||
} else if reg == Registered::Https.into() {
|
} else if reg == Registered::Https.into() {
|
||||||
Ok("https".into())
|
Ok("https".into())
|
||||||
} else {
|
} else {
|
||||||
Err(InvalidScheme)
|
Err(InvalidScheme)
|
||||||
}
|
},
|
||||||
}
|
|
||||||
Type::Unregistered(ref s) => Ok(s.clone()),
|
Type::Unregistered(ref s) => Ok(s.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,7 +265,7 @@ impl<'a> From<&'a http::Method> for common::http_method::Type {
|
||||||
impl<'a> From<&'a http::Method> for common::HttpMethod {
|
impl<'a> From<&'a http::Method> for common::HttpMethod {
|
||||||
fn from(m: &'a http::Method) -> Self {
|
fn from(m: &'a http::Method) -> Self {
|
||||||
common::HttpMethod {
|
common::HttpMethod {
|
||||||
type_: Some(m.into())
|
type_: Some(m.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +285,7 @@ impl<'a> From<&'a str> for common::scheme::Type {
|
||||||
impl<'a> From<&'a str> for common::Scheme {
|
impl<'a> From<&'a str> for common::Scheme {
|
||||||
fn from(s: &'a str) -> Self {
|
fn from(s: &'a str) -> Self {
|
||||||
common::Scheme {
|
common::Scheme {
|
||||||
type_: Some(s.into())
|
type_: Some(s.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,7 +294,7 @@ impl<'a> From<&'a str> for common::Scheme {
|
||||||
|
|
||||||
impl<T> From<T> for common::IpAddress
|
impl<T> From<T> for common::IpAddress
|
||||||
where
|
where
|
||||||
common::ip_address::Ip: From<T>
|
common::ip_address::Ip: From<T>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(ip: T) -> Self {
|
fn from(ip: T) -> Self {
|
||||||
|
@ -317,12 +307,10 @@ where
|
||||||
impl From<::std::net::IpAddr> for common::IpAddress {
|
impl From<::std::net::IpAddr> for common::IpAddress {
|
||||||
fn from(ip: ::std::net::IpAddr) -> Self {
|
fn from(ip: ::std::net::IpAddr) -> Self {
|
||||||
match ip {
|
match ip {
|
||||||
::std::net::IpAddr::V4(v4) =>
|
::std::net::IpAddr::V4(v4) => Self {
|
||||||
Self {
|
|
||||||
ip: Some(v4.into()),
|
ip: Some(v4.into()),
|
||||||
},
|
},
|
||||||
::std::net::IpAddr::V6(v6) =>
|
::std::net::IpAddr::V6(v6) => Self {
|
||||||
Self {
|
|
||||||
ip: Some(v6.into()),
|
ip: Some(v6.into()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -333,22 +321,14 @@ impl From<::std::net::IpAddr> for common::IpAddress {
|
||||||
|
|
||||||
impl From<[u8; 16]> for common::IPv6 {
|
impl From<[u8; 16]> for common::IPv6 {
|
||||||
fn from(octets: [u8; 16]) -> Self {
|
fn from(octets: [u8; 16]) -> Self {
|
||||||
let first = (u64::from(octets[0]) << 56)
|
let first = (u64::from(octets[0]) << 56) + (u64::from(octets[1]) << 48)
|
||||||
+ (u64::from(octets[1]) << 48)
|
+ (u64::from(octets[2]) << 40) + (u64::from(octets[3]) << 32)
|
||||||
+ (u64::from(octets[2]) << 40)
|
+ (u64::from(octets[4]) << 24) + (u64::from(octets[5]) << 16)
|
||||||
+ (u64::from(octets[3]) << 32)
|
+ (u64::from(octets[6]) << 8) + u64::from(octets[7]);
|
||||||
+ (u64::from(octets[4]) << 24)
|
let last = (u64::from(octets[8]) << 56) + (u64::from(octets[9]) << 48)
|
||||||
+ (u64::from(octets[5]) << 16)
|
+ (u64::from(octets[10]) << 40) + (u64::from(octets[11]) << 32)
|
||||||
+ (u64::from(octets[6]) << 8)
|
+ (u64::from(octets[12]) << 24) + (u64::from(octets[13]) << 16)
|
||||||
+ u64::from(octets[7]);
|
+ (u64::from(octets[14]) << 8) + u64::from(octets[15]);
|
||||||
let last = (u64::from(octets[8]) << 56)
|
|
||||||
+ (u64::from(octets[9]) << 48)
|
|
||||||
+ (u64::from(octets[10]) << 40)
|
|
||||||
+ (u64::from(octets[11]) << 32)
|
|
||||||
+ (u64::from(octets[12]) << 24)
|
|
||||||
+ (u64::from(octets[13]) << 16)
|
|
||||||
+ (u64::from(octets[14]) << 8)
|
|
||||||
+ u64::from(octets[15]);
|
|
||||||
Self {
|
Self {
|
||||||
first,
|
first,
|
||||||
last,
|
last,
|
||||||
|
@ -357,7 +337,8 @@ impl From<[u8; 16]> for common::IPv6 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<::std::net::Ipv6Addr> for common::IPv6 {
|
impl From<::std::net::Ipv6Addr> for common::IPv6 {
|
||||||
#[inline] fn from(v6: ::std::net::Ipv6Addr) -> Self {
|
#[inline]
|
||||||
|
fn from(v6: ::std::net::Ipv6Addr) -> Self {
|
||||||
Self::from(v6.octets())
|
Self::from(v6.octets())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,25 +363,25 @@ impl<'a> From<&'a common::IPv6> for ::std::net::Ipv6Addr {
|
||||||
impl From<[u8; 4]> for common::ip_address::Ip {
|
impl From<[u8; 4]> for common::ip_address::Ip {
|
||||||
fn from(octets: [u8; 4]) -> Self {
|
fn from(octets: [u8; 4]) -> Self {
|
||||||
common::ip_address::Ip::Ipv4(
|
common::ip_address::Ip::Ipv4(
|
||||||
u32::from(octets[0]) << 24 |
|
u32::from(octets[0]) << 24 | u32::from(octets[1]) << 16 | u32::from(octets[2]) << 8
|
||||||
u32::from(octets[1]) << 16 |
|
| u32::from(octets[3]),
|
||||||
u32::from(octets[2]) << 8 |
|
|
||||||
u32::from(octets[3])
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<::std::net::Ipv4Addr> for common::ip_address::Ip {
|
impl From<::std::net::Ipv4Addr> for common::ip_address::Ip {
|
||||||
#[inline] fn from(v4: ::std::net::Ipv4Addr) -> Self {
|
#[inline]
|
||||||
|
fn from(v4: ::std::net::Ipv4Addr) -> Self {
|
||||||
Self::from(v4.octets())
|
Self::from(v4.octets())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<T> for common::ip_address::Ip
|
impl<T> From<T> for common::ip_address::Ip
|
||||||
where
|
where
|
||||||
common::IPv6: From<T>
|
common::IPv6: From<T>,
|
||||||
{
|
{
|
||||||
#[inline] fn from(t: T) -> Self {
|
#[inline]
|
||||||
|
fn from(t: T) -> Self {
|
||||||
common::ip_address::Ip::Ipv6(common::IPv6::from(t))
|
common::ip_address::Ip::Ipv6(common::IPv6::from(t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,5 +410,8 @@ fn pb_duration(d: &::std::time::Duration) -> ::prost_types::Duration {
|
||||||
d.subsec_nanos() as i32
|
d.subsec_nanos() as i32
|
||||||
};
|
};
|
||||||
|
|
||||||
::prost_types::Duration { seconds, nanos }
|
::prost_types::Duration {
|
||||||
|
seconds,
|
||||||
|
nanos,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,8 @@ use tower_grpc;
|
||||||
|
|
||||||
use super::codec::Protobuf;
|
use super::codec::Protobuf;
|
||||||
use super::pb::proxy::telemetry::{ReportRequest, ReportResponse};
|
use super::pb::proxy::telemetry::{ReportRequest, ReportResponse};
|
||||||
use super::pb::proxy::telemetry::client::{
|
use super::pb::proxy::telemetry::client::Telemetry as TelemetrySvc;
|
||||||
Telemetry as TelemetrySvc,
|
use super::pb::proxy::telemetry::client::telemetry_methods::Report as ReportRpc;
|
||||||
};
|
|
||||||
use super::pb::proxy::telemetry::client::telemetry_methods::{
|
|
||||||
Report as ReportRpc,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub type ClientBody = tower_grpc::client::codec::EncodingBody<
|
pub type ClientBody = tower_grpc::client::codec::EncodingBody<
|
||||||
Protobuf<ReportRequest, ReportResponse>,
|
Protobuf<ReportRequest, ReportResponse>,
|
||||||
|
@ -20,12 +16,9 @@ pub type ClientBody = tower_grpc::client::codec::EncodingBody<
|
||||||
|
|
||||||
type TelemetryStream<F> = tower_grpc::client::BodyFuture<
|
type TelemetryStream<F> = tower_grpc::client::BodyFuture<
|
||||||
tower_grpc::client::Unary<
|
tower_grpc::client::Unary<
|
||||||
tower_grpc::client::ResponseFuture<
|
tower_grpc::client::ResponseFuture<Protobuf<ReportRequest, ReportResponse>, F>,
|
||||||
Protobuf<ReportRequest, ReportResponse>,
|
Protobuf<ReportRequest, ReportResponse>,
|
||||||
F
|
|
||||||
>,
|
>,
|
||||||
Protobuf<ReportRequest, ReportResponse>,
|
|
||||||
>
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -36,9 +29,9 @@ pub struct Telemetry<T, F> {
|
||||||
|
|
||||||
impl<T, F> Telemetry<T, F>
|
impl<T, F> Telemetry<T, F>
|
||||||
where
|
where
|
||||||
T: Stream<Item=ReportRequest>,
|
T: Stream<Item = ReportRequest>,
|
||||||
T::Error: ::std::fmt::Debug,
|
T::Error: ::std::fmt::Debug,
|
||||||
F: Future<Item=::http::Response<::tower_h2::RecvBody>>,
|
F: Future<Item = ::http::Response<::tower_h2::RecvBody>>,
|
||||||
F::Error: ::std::fmt::Debug,
|
F::Error: ::std::fmt::Debug,
|
||||||
{
|
{
|
||||||
pub fn new(reports: T) -> Self {
|
pub fn new(reports: T) -> Self {
|
||||||
|
@ -51,10 +44,10 @@ where
|
||||||
pub fn poll_rpc<S>(&mut self, client: &mut S)
|
pub fn poll_rpc<S>(&mut self, client: &mut S)
|
||||||
where
|
where
|
||||||
S: Service<
|
S: Service<
|
||||||
Request=::http::Request<ClientBody>,
|
Request = ::http::Request<ClientBody>,
|
||||||
Response=F::Item,
|
Response = F::Item,
|
||||||
Error=F::Error,
|
Error = F::Error,
|
||||||
Future=F,
|
Future = F,
|
||||||
>,
|
>,
|
||||||
{
|
{
|
||||||
let grpc = tower_grpc::Client::new(Protobuf::new(), client);
|
let grpc = tower_grpc::Client::new(Protobuf::new(), client);
|
||||||
|
@ -70,14 +63,15 @@ where
|
||||||
trace!("report in flight to controller for {:?}", t0.elapsed());
|
trace!("report in flight to controller for {:?}", t0.elapsed());
|
||||||
self.in_flight = Some((t0, fut));
|
self.in_flight = Some((t0, fut));
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(_)) => trace!("report sent to controller in {:?}", t0.elapsed()),
|
Ok(Async::Ready(_)) => {
|
||||||
|
trace!("report sent to controller in {:?}", t0.elapsed())
|
||||||
|
}
|
||||||
Err(err) => warn!("controller error: {:?}", err),
|
Err(err) => warn!("controller error: {:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let controller_ready = self.in_flight.is_none() &&
|
let controller_ready = self.in_flight.is_none() && match rpc.poll_ready() {
|
||||||
match rpc.poll_ready() {
|
|
||||||
Ok(Async::Ready(_)) => true,
|
Ok(Async::Ready(_)) => true,
|
||||||
Ok(Async::NotReady) => {
|
Ok(Async::NotReady) => {
|
||||||
trace!("controller unavailable");
|
trace!("controller unavailable");
|
||||||
|
@ -92,14 +86,14 @@ where
|
||||||
match self.reports.poll() {
|
match self.reports.poll() {
|
||||||
Ok(Async::NotReady) => {
|
Ok(Async::NotReady) => {
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
Ok(Async::Ready(None)) => {
|
Ok(Async::Ready(None)) => {
|
||||||
error!("report stream complete");
|
error!("report stream complete");
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("report stream error: {:?}", err);
|
warn!("report stream error: {:?}", err);
|
||||||
},
|
}
|
||||||
Ok(Async::Ready(Some(report))) => {
|
Ok(Async::Ready(Some(report))) => {
|
||||||
// Attempt to send the report. Continue looping so that `reports` is
|
// Attempt to send the report. Continue looping so that `reports` is
|
||||||
// polled until it's not ready.
|
// polled until it's not ready.
|
||||||
|
@ -120,7 +114,7 @@ where
|
||||||
let rep = TelemetrySvc::new(&mut rpc).report(report);
|
let rep = TelemetrySvc::new(&mut rpc).report(report);
|
||||||
self.in_flight = Some((Instant::now(), rep));
|
self.in_flight = Some((Instant::now(), rep));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
//! As a rule, context types should implement `Clone + Send + Sync`. This allows them to
|
//! As a rule, context types should implement `Clone + Send + Sync`. This allows them to
|
||||||
//! be stored in `http::Extensions`, for instance. Furthermore, because these contexts
|
//! be stored in `http::Extensions`, for instance. Furthermore, because these contexts
|
||||||
//! will be sent to a telemetry processing thread, we want to avoid excessive cloning.
|
//! will be sent to a telemetry processing thread, we want to avoid excessive cloning.
|
||||||
|
use control::pb::proxy::telemetry as proto;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use control::pb::proxy::telemetry as proto;
|
|
||||||
pub mod http;
|
pub mod http;
|
||||||
pub mod transport;
|
pub mod transport;
|
||||||
|
|
||||||
|
@ -51,15 +51,14 @@ impl Process {
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
node: node.into(),
|
node: node.into(),
|
||||||
scheduled_instance: instance.into(),
|
scheduled_instance: instance.into(),
|
||||||
scheduled_namespace: ns.into()
|
scheduled_namespace: ns.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new `Process` from environment variables.
|
/// Construct a new `Process` from environment variables.
|
||||||
pub fn from_env() -> Arc<Self> {
|
pub fn from_env() -> Arc<Self> {
|
||||||
fn get_var(key: &str) -> String {
|
fn get_var(key: &str) -> String {
|
||||||
env::var(key)
|
env::var(key).unwrap_or_else(|why| {
|
||||||
.unwrap_or_else(|why| {
|
|
||||||
warn!(
|
warn!(
|
||||||
"Process::from_env(): Failed to get value of {} environment variable: {:?}",
|
"Process::from_env(): Failed to get value of {} environment variable: {:?}",
|
||||||
key,
|
key,
|
||||||
|
@ -103,7 +102,7 @@ impl Proxy {
|
||||||
pub fn is_inbound(&self) -> bool {
|
pub fn is_inbound(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Proxy::Inbound(_) => true,
|
Proxy::Inbound(_) => true,
|
||||||
Proxy::Outbound(_) => false
|
Proxy::Outbound(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use futures::prelude::*;
|
|
||||||
use std::net::IpAddr;
|
|
||||||
use domain;
|
|
||||||
use ns_dns_tokio;
|
|
||||||
use abstract_ns;
|
use abstract_ns;
|
||||||
use abstract_ns::HostResolve;
|
use abstract_ns::HostResolve;
|
||||||
|
use domain;
|
||||||
|
use futures::prelude::*;
|
||||||
|
use ns_dns_tokio;
|
||||||
|
use std::net::IpAddr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tokio_core::reactor::Handle;
|
use tokio_core::reactor::Handle;
|
||||||
|
@ -40,7 +40,9 @@ impl Config {
|
||||||
|
|
||||||
impl Resolver {
|
impl Resolver {
|
||||||
pub fn new(config: Config, executor: &Handle) -> Self {
|
pub fn new(config: Config, executor: &Handle) -> Self {
|
||||||
Resolver(ns_dns_tokio::DnsResolver::new_from_resolver(domain::resolv::Resolver::from_conf(executor, config.0)))
|
Resolver(ns_dns_tokio::DnsResolver::new_from_resolver(
|
||||||
|
domain::resolv::Resolver::from_conf(executor, config.0),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_host(&self, host: &url::Host) -> IpAddrFuture {
|
pub fn resolve_host(&self, host: &url::Host) -> IpAddrFuture {
|
||||||
|
@ -65,15 +67,12 @@ impl Future for IpAddrFuture {
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
IpAddrFuture::DNS(ref mut inner) => {
|
IpAddrFuture::DNS(ref mut inner) => match inner.poll() {
|
||||||
match inner.poll() {
|
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||||
Ok(Async::Ready(ips)) =>
|
Ok(Async::Ready(ips)) => ips.pick_one()
|
||||||
ips.pick_one()
|
|
||||||
.map(Async::Ready)
|
.map(Async::Ready)
|
||||||
.ok_or(Error::NoAddressesFound),
|
.ok_or(Error::NoAddressesFound),
|
||||||
Err(e) => Err(Error::ResolutionFailed(e)),
|
Err(e) => Err(Error::ResolutionFailed(e)),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
IpAddrFuture::Fixed(addr) => Ok(Async::Ready(addr)),
|
IpAddrFuture::Fixed(addr) => Ok(Async::Ready(addr)),
|
||||||
IpAddrFuture::InvalidDNSName(ref name) => Err(Error::InvalidDNSName(name.clone())),
|
IpAddrFuture::InvalidDNSName(ref name) => Err(Error::InvalidDNSName(name.clone())),
|
||||||
|
|
|
@ -32,29 +32,25 @@ type CtxtExec = ::logging::ContextualExecutor<(&'static str, SocketAddr), Handle
|
||||||
// ===== impl Inbound =====
|
// ===== impl Inbound =====
|
||||||
|
|
||||||
impl<B> Inbound<B> {
|
impl<B> Inbound<B> {
|
||||||
pub fn new(
|
pub fn new(default_addr: Option<SocketAddr>, bind: Bind<B>) -> Self {
|
||||||
default_addr: Option<SocketAddr>,
|
|
||||||
bind: Bind<B>
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
default_addr,
|
default_addr,
|
||||||
bind
|
bind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn same_addr(a0: &SocketAddr, a1: &SocketAddr) -> bool {
|
fn same_addr(a0: &SocketAddr, a1: &SocketAddr) -> bool {
|
||||||
(a0.port() == a1.port()) &&
|
(a0.port() == a1.port()) && match (a0.ip(), a1.ip()) {
|
||||||
match (a0.ip(), a1.ip()) {
|
|
||||||
(IpAddr::V6(a0), IpAddr::V4(a1)) => a0.to_ipv4() == Some(a1),
|
(IpAddr::V6(a0), IpAddr::V4(a1)) => a0.to_ipv4() == Some(a1),
|
||||||
(IpAddr::V4(a0), IpAddr::V6(a1)) => Some(a0) == a1.to_ipv4(),
|
(IpAddr::V4(a0), IpAddr::V6(a1)) => Some(a0) == a1.to_ipv4(),
|
||||||
(a0, a1) => (a0 == a1)
|
(a0, a1) => (a0 == a1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> Recognize for Inbound<B>
|
impl<B> Recognize for Inbound<B>
|
||||||
where
|
where
|
||||||
B: tower_h2::Body + 'static
|
B: tower_h2::Body + 'static,
|
||||||
{
|
{
|
||||||
type Request = http::Request<B>;
|
type Request = http::Request<B>;
|
||||||
type Response = http::Response<telemetry::sensor::http::ResponseBody<tower_h2::RecvBody>>;
|
type Response = http::Response<telemetry::sensor::http::ResponseBody<tower_h2::RecvBody>>;
|
||||||
|
@ -66,11 +62,7 @@ where
|
||||||
>;
|
>;
|
||||||
type Key = SocketAddr;
|
type Key = SocketAddr;
|
||||||
type RouteError = ();
|
type RouteError = ();
|
||||||
type Service = Buffer<Reconnect<telemetry::sensor::NewHttp<
|
type Service = Buffer<Reconnect<telemetry::sensor::NewHttp<Client<B>, B, tower_h2::RecvBody>>>;
|
||||||
Client<B>,
|
|
||||||
B,
|
|
||||||
tower_h2::RecvBody
|
|
||||||
>>>;
|
|
||||||
|
|
||||||
fn recognize(&self, req: &Self::Request) -> Option<Self::Key> {
|
fn recognize(&self, req: &Self::Request) -> Option<Self::Key> {
|
||||||
let key = req.extensions()
|
let key = req.extensions()
|
||||||
|
@ -82,8 +74,11 @@ where
|
||||||
Some(orig_dst) => {
|
Some(orig_dst) => {
|
||||||
// If the original destination is actually the listening socket,
|
// If the original destination is actually the listening socket,
|
||||||
// we don't want to create a loop.
|
// we don't want to create a loop.
|
||||||
if Self::same_addr(&orig_dst, &ctx.local) { None }
|
if Self::same_addr(&orig_dst, &ctx.local) {
|
||||||
else { Some(orig_dst) }
|
None
|
||||||
|
} else {
|
||||||
|
Some(orig_dst)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -107,8 +102,7 @@ where
|
||||||
// is not ideal.
|
// is not ideal.
|
||||||
//
|
//
|
||||||
// TODO: Don't use unbounded buffering.
|
// TODO: Don't use unbounded buffering.
|
||||||
Buffer::new(self.bind.bind_service(addr), self.bind.executor())
|
Buffer::new(self.bind.bind_service(addr), self.bind.executor()).map_err(|_| {})
|
||||||
.map_err(|_| {})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,9 +116,9 @@ mod tests {
|
||||||
use tokio_core::reactor::Core;
|
use tokio_core::reactor::Core;
|
||||||
use tower_router::Recognize;
|
use tower_router::Recognize;
|
||||||
|
|
||||||
|
use super::Inbound;
|
||||||
use bind::Bind;
|
use bind::Bind;
|
||||||
use ctx;
|
use ctx;
|
||||||
use super::Inbound;
|
|
||||||
|
|
||||||
fn new_inbound(default: Option<net::SocketAddr>, ctx: &Arc<ctx::Proxy>) -> Inbound<()> {
|
fn new_inbound(default: Option<net::SocketAddr>, ctx: &Arc<ctx::Proxy>) -> Inbound<()> {
|
||||||
let core = Core::new().unwrap();
|
let core = Core::new().unwrap();
|
||||||
|
|
|
@ -74,8 +74,8 @@ mod tower_fn; // TODO: move to tower-fn
|
||||||
use bind::Bind;
|
use bind::Bind;
|
||||||
use control::pb::proxy::tap;
|
use control::pb::proxy::tap;
|
||||||
use inbound::Inbound;
|
use inbound::Inbound;
|
||||||
use outbound::Outbound;
|
|
||||||
use map_err::MapErr;
|
use map_err::MapErr;
|
||||||
|
use outbound::Outbound;
|
||||||
|
|
||||||
/// Runs a sidecar proxy.
|
/// Runs a sidecar proxy.
|
||||||
///
|
///
|
||||||
|
@ -99,13 +99,13 @@ pub struct Main {
|
||||||
|
|
||||||
impl Main {
|
impl Main {
|
||||||
pub fn new(config: config::Config) -> Self {
|
pub fn new(config: config::Config) -> Self {
|
||||||
|
|
||||||
let control_listener = StdTcpListener::bind(SocketAddr::from(config.control_listener.addr))
|
let control_listener = StdTcpListener::bind(SocketAddr::from(config.control_listener.addr))
|
||||||
.expect("controller listener bind");
|
.expect("controller listener bind");
|
||||||
let inbound_listener = StdTcpListener::bind(SocketAddr::from(config.public_listener.addr))
|
let inbound_listener = StdTcpListener::bind(SocketAddr::from(config.public_listener.addr))
|
||||||
.expect("public listener bind");
|
.expect("public listener bind");
|
||||||
let outbound_listener = StdTcpListener::bind(SocketAddr::from(config.private_listener.addr))
|
let outbound_listener = StdTcpListener::bind(
|
||||||
.expect("private listener bind");
|
SocketAddr::from(config.private_listener.addr),
|
||||||
|
).expect("private listener bind");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
|
@ -134,7 +134,7 @@ impl Main {
|
||||||
|
|
||||||
pub fn run_until<F>(self, shutdown_signal: F)
|
pub fn run_until<F>(self, shutdown_signal: F)
|
||||||
where
|
where
|
||||||
F: Future<Item=(), Error=()>,
|
F: Future<Item = (), Error = ()>,
|
||||||
{
|
{
|
||||||
let Main {
|
let Main {
|
||||||
config,
|
config,
|
||||||
|
@ -146,10 +146,7 @@ impl Main {
|
||||||
let control_host_and_port = config.control_host_and_port.clone();
|
let control_host_and_port = config.control_host_and_port.clone();
|
||||||
|
|
||||||
info!("using controller at {:?}", control_host_and_port);
|
info!("using controller at {:?}", control_host_and_port);
|
||||||
info!(
|
info!("routing on {:?}", outbound_listener.local_addr().unwrap(),);
|
||||||
"routing on {:?}",
|
|
||||||
outbound_listener.local_addr().unwrap(),
|
|
||||||
);
|
|
||||||
info!(
|
info!(
|
||||||
"proxying on {:?} to {:?}",
|
"proxying on {:?} to {:?}",
|
||||||
inbound_listener.local_addr().unwrap(),
|
inbound_listener.local_addr().unwrap(),
|
||||||
|
@ -170,8 +167,7 @@ impl Main {
|
||||||
|
|
||||||
let dns_config = dns::Config::from_file(&config.resolv_conf_path);
|
let dns_config = dns::Config::from_file(&config.resolv_conf_path);
|
||||||
|
|
||||||
let bind = Bind::new(executor.clone())
|
let bind = Bind::new(executor.clone()).with_sensors(sensors.clone());
|
||||||
.with_sensors(sensors.clone());
|
|
||||||
|
|
||||||
// Setup the public listener. This will listen on a publicly accessible
|
// Setup the public listener. This will listen on a publicly accessible
|
||||||
// address and listen for inbound connections that should be forwarded
|
// address and listen for inbound connections that should be forwarded
|
||||||
|
@ -179,7 +175,9 @@ impl Main {
|
||||||
let inbound = {
|
let inbound = {
|
||||||
let ctx = ctx::Proxy::inbound(&process_ctx);
|
let ctx = ctx::Proxy::inbound(&process_ctx);
|
||||||
|
|
||||||
let timeout = config.private_connect_timeout.unwrap_or_else(|| Duration::from_millis(20));
|
let timeout = config
|
||||||
|
.private_connect_timeout
|
||||||
|
.unwrap_or_else(|| Duration::from_millis(20));
|
||||||
let bind = bind.clone()
|
let bind = bind.clone()
|
||||||
.with_connect_timeout(timeout)
|
.with_connect_timeout(timeout)
|
||||||
.with_ctx(ctx.clone());
|
.with_ctx(ctx.clone());
|
||||||
|
@ -203,11 +201,9 @@ impl Main {
|
||||||
let outbound = {
|
let outbound = {
|
||||||
let ctx = ctx::Proxy::outbound(&process_ctx);
|
let ctx = ctx::Proxy::outbound(&process_ctx);
|
||||||
|
|
||||||
let bind = config.public_connect_timeout
|
let bind = config
|
||||||
.map_or_else(
|
.public_connect_timeout
|
||||||
|| bind.clone(),
|
.map_or_else(|| bind.clone(), |t| bind.clone().with_connect_timeout(t))
|
||||||
|t| bind.clone().with_connect_timeout(t),
|
|
||||||
)
|
|
||||||
.with_ctx(ctx.clone());
|
.with_ctx(ctx.clone());
|
||||||
|
|
||||||
let fut = serve(
|
let fut = serve(
|
||||||
|
@ -233,36 +229,33 @@ impl Main {
|
||||||
|
|
||||||
let (taps, observe) = control::Observe::new(100);
|
let (taps, observe) = control::Observe::new(100);
|
||||||
|
|
||||||
let new_service = tap::server::Tap::new_service()
|
let new_service = tap::server::Tap::new_service().observe(observe);
|
||||||
.observe(observe);
|
|
||||||
|
|
||||||
let server = serve_control(
|
let server = serve_control(
|
||||||
control_listener,
|
control_listener,
|
||||||
h2::server::Builder::default(),
|
h2::server::Builder::default(),
|
||||||
new_service,
|
new_service,
|
||||||
&executor
|
&executor,
|
||||||
);
|
);
|
||||||
|
|
||||||
let telemetry = telemetry
|
let telemetry = telemetry
|
||||||
.make_control(&taps, &executor)
|
.make_control(&taps, &executor)
|
||||||
.expect("bad news in telemetry town");
|
.expect("bad news in telemetry town");
|
||||||
|
|
||||||
let client = control_bg.bind(
|
let client =
|
||||||
telemetry,
|
control_bg.bind(telemetry, control_host_and_port, dns_config, &executor);
|
||||||
control_host_and_port,
|
|
||||||
dns_config,
|
|
||||||
&executor
|
|
||||||
);
|
|
||||||
|
|
||||||
let fut = client.join(server.map_err(|_| {})).map(|_| {});
|
let fut = client.join(server.map_err(|_| {})).map(|_| {});
|
||||||
executor.spawn(::logging::context_future("controller-client", fut));
|
executor.spawn(::logging::context_future("controller-client", fut));
|
||||||
|
|
||||||
let shutdown = controller_shutdown_signal.then(|_| Ok::<(), ()>(()));
|
let shutdown = controller_shutdown_signal.then(|_| Ok::<(), ()>(()));
|
||||||
core.run(shutdown).expect("controller api");
|
core.run(shutdown).expect("controller api");
|
||||||
}).expect("initialize controller api thread");
|
})
|
||||||
|
.expect("initialize controller api thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
let fut = inbound.join(outbound)
|
let fut = inbound
|
||||||
|
.join(outbound)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|err| error!("main error: {:?}", err));
|
.map_err(|err| error!("main error: {:?}", err));
|
||||||
|
|
||||||
|
@ -288,12 +281,12 @@ where
|
||||||
Response = http::Response<telemetry::sensor::http::ResponseBody<B>>,
|
Response = http::Response<telemetry::sensor::http::ResponseBody<B>>,
|
||||||
Error = E,
|
Error = E,
|
||||||
RouteError = F,
|
RouteError = F,
|
||||||
> + 'static,
|
>
|
||||||
|
+ 'static,
|
||||||
{
|
{
|
||||||
let listen_addr = listen.local_addr().expect("local addr");
|
let listen_addr = listen.local_addr().expect("local addr");
|
||||||
|
|
||||||
let bind = TcpListener::from_listener(listen, &listen_addr, &executor)
|
let bind = TcpListener::from_listener(listen, &listen_addr, &executor).expect("bind");
|
||||||
.expect("bind");
|
|
||||||
|
|
||||||
let router = Router::new(recognize);
|
let router = Router::new(recognize);
|
||||||
let stack = NewServiceFn::new(move || {
|
let stack = NewServiceFn::new(move || {
|
||||||
|
@ -304,19 +297,28 @@ where
|
||||||
MapErr::new(router)
|
MapErr::new(router)
|
||||||
});
|
});
|
||||||
|
|
||||||
let server = Server::new(stack, h2_builder, ::logging::context_executor(("serve", listen_addr) , executor.clone()));
|
let server = Server::new(
|
||||||
|
stack,
|
||||||
|
h2_builder,
|
||||||
|
::logging::context_executor(("serve", listen_addr), executor.clone()),
|
||||||
|
);
|
||||||
let f = bind.incoming().fold(
|
let f = bind.incoming().fold(
|
||||||
(server, proxy_ctx, sensors, executor),
|
(server, proxy_ctx, sensors, executor),
|
||||||
move |(server, proxy_ctx, sensors, executor), (socket, remote_addr)| {
|
move |(server, proxy_ctx, sensors, executor), (socket, remote_addr)| {
|
||||||
if let Err(e) = socket.set_nodelay(true) {
|
if let Err(e) = socket.set_nodelay(true) {
|
||||||
warn!("could not set TCP_NODELAY on {:?}/{:?}: {}",
|
warn!(
|
||||||
socket.local_addr(), socket.peer_addr(), e);
|
"could not set TCP_NODELAY on {:?}/{:?}: {}",
|
||||||
|
socket.local_addr(),
|
||||||
|
socket.peer_addr(),
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let opened_at = Instant::now();
|
let opened_at = Instant::now();
|
||||||
let orig_dst = transport::get_original_dst(&socket);
|
let orig_dst = transport::get_original_dst(&socket);
|
||||||
let local_addr = socket.local_addr().unwrap_or(listen_addr);
|
let local_addr = socket.local_addr().unwrap_or(listen_addr);
|
||||||
let srv_ctx = ctx::transport::Server::new(&proxy_ctx, &local_addr, &remote_addr, &orig_dst);
|
let srv_ctx =
|
||||||
|
ctx::transport::Server::new(&proxy_ctx, &local_addr, &remote_addr, &orig_dst);
|
||||||
|
|
||||||
connection::Connection::handshake(socket).map(move |session| {
|
connection::Connection::handshake(socket).map(move |session| {
|
||||||
let io = sensors.accept(session, opened_at, &srv_ctx);
|
let io = sensors.accept(session, opened_at, &srv_ctx);
|
||||||
|
@ -345,22 +347,22 @@ fn serve_control<N, B>(
|
||||||
) -> Box<Future<Item = (), Error = io::Error> + 'static>
|
) -> Box<Future<Item = (), Error = io::Error> + 'static>
|
||||||
where
|
where
|
||||||
B: Body + 'static,
|
B: Body + 'static,
|
||||||
N: NewService<
|
N: NewService<Request = http::Request<RecvBody>, Response = http::Response<B>> + 'static,
|
||||||
Request = http::Request<RecvBody>,
|
|
||||||
Response = http::Response<B>,
|
|
||||||
> + 'static,
|
|
||||||
{
|
{
|
||||||
let listen_addr = listen.local_addr().expect("local addr");
|
let listen_addr = listen.local_addr().expect("local addr");
|
||||||
let bind = TcpListener::from_listener(listen, &listen_addr, executor)
|
let bind = TcpListener::from_listener(listen, &listen_addr, executor).expect("bind");
|
||||||
.expect("bind");
|
|
||||||
|
|
||||||
let server = Server::new(new_service, h2_builder, executor.clone());
|
let server = Server::new(new_service, h2_builder, executor.clone());
|
||||||
let f = bind.incoming().fold(
|
let f = bind.incoming().fold(
|
||||||
(server, executor.clone()),
|
(server, executor.clone()),
|
||||||
move |(server, executor), (socket, _)| {
|
move |(server, executor), (socket, _)| {
|
||||||
if let Err(e) = socket.set_nodelay(true) {
|
if let Err(e) = socket.set_nodelay(true) {
|
||||||
warn!("could not set TCP_NODELAY on {:?}/{:?}: {}",
|
warn!(
|
||||||
socket.local_addr(), socket.peer_addr(), e);
|
"could not set TCP_NODELAY on {:?}/{:?}: {}",
|
||||||
|
socket.local_addr(),
|
||||||
|
socket.peer_addr(),
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
connection::Connection::handshake(socket).map(move |session| {
|
connection::Connection::handshake(socket).map(move |session| {
|
||||||
|
|
|
@ -4,9 +4,9 @@ use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use futures::{Future, Poll};
|
|
||||||
use futures::future::{Executor, ExecuteError};
|
|
||||||
use env_logger::LogBuilder;
|
use env_logger::LogBuilder;
|
||||||
|
use futures::{Future, Poll};
|
||||||
|
use futures::future::{ExecuteError, Executor};
|
||||||
use log::LogLevel;
|
use log::LogLevel;
|
||||||
|
|
||||||
const ENV_LOG: &str = "CONDUIT_PROXY_LOG";
|
const ENV_LOG: &str = "CONDUIT_PROXY_LOG";
|
||||||
|
@ -39,7 +39,6 @@ pub fn init() {
|
||||||
.parse(&env::var(ENV_LOG).unwrap_or_default())
|
.parse(&env::var(ENV_LOG).unwrap_or_default())
|
||||||
.init()
|
.init()
|
||||||
.expect("logger");
|
.expect("logger");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute a closure with a `Debug` item attached to allow log messages.
|
/// Execute a closure with a `Debug` item attached to allow log messages.
|
||||||
|
@ -112,7 +111,7 @@ impl<T, E, F> Executor<F> for ContextualExecutor<T, E>
|
||||||
where
|
where
|
||||||
T: ::std::fmt::Debug + 'static,
|
T: ::std::fmt::Debug + 'static,
|
||||||
E: Executor<ContextualFuture<Rc<T>, F>>,
|
E: Executor<ContextualFuture<Rc<T>, F>>,
|
||||||
F: Future<Item=(), Error=()>,
|
F: Future<Item = (), Error = ()>,
|
||||||
{
|
{
|
||||||
fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
|
fn execute(&self, future: F) -> Result<(), ExecuteError<F>> {
|
||||||
let fut = context_future(self.context.clone(), future);
|
let fut = context_future(self.context.clone(), future);
|
||||||
|
|
|
@ -11,8 +11,7 @@ fn main() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("configuration error: {:#?}", e);
|
eprintln!("configuration error: {:#?}", e);
|
||||||
process::exit(64)
|
process::exit(64)
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
conduit_proxy::Main::new(config)
|
conduit_proxy::Main::new(config).run();
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,17 +21,22 @@ pub struct ResponseFuture<T, E> {
|
||||||
// ===== impl MapErr =====
|
// ===== impl MapErr =====
|
||||||
|
|
||||||
impl<T, E> MapErr<T, E>
|
impl<T, E> MapErr<T, E>
|
||||||
where T: Service<Error = E>,
|
where
|
||||||
|
T: Service<Error = E>,
|
||||||
E: Debug,
|
E: Debug,
|
||||||
{
|
{
|
||||||
/// Crete a new `MapErr`
|
/// Crete a new `MapErr`
|
||||||
pub fn new(inner: T) -> Self {
|
pub fn new(inner: T) -> Self {
|
||||||
MapErr { inner, _p: PhantomData }
|
MapErr {
|
||||||
|
inner,
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, B, E> Service for MapErr<T, E>
|
impl<T, B, E> Service for MapErr<T, E>
|
||||||
where T: Service<Response = http::Response<B>, Error = E>,
|
where
|
||||||
|
T: Service<Response = http::Response<B>, Error = E>,
|
||||||
B: Default,
|
B: Default,
|
||||||
E: Debug,
|
E: Debug,
|
||||||
{
|
{
|
||||||
|
@ -48,14 +53,18 @@ where T: Service<Response = http::Response<B>, Error = E>,
|
||||||
|
|
||||||
fn call(&mut self, request: Self::Request) -> Self::Future {
|
fn call(&mut self, request: Self::Request) -> Self::Future {
|
||||||
let inner = self.inner.call(request);
|
let inner = self.inner.call(request);
|
||||||
ResponseFuture { inner, _p: PhantomData }
|
ResponseFuture {
|
||||||
|
inner,
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== impl ResponseFuture =====
|
// ===== impl ResponseFuture =====
|
||||||
|
|
||||||
impl<T, B, E> Future for ResponseFuture<T, E>
|
impl<T, B, E> Future for ResponseFuture<T, E>
|
||||||
where T: Future<Item = http::Response<B>, Error = E>,
|
where
|
||||||
|
T: Future<Item = http::Response<B>, Error = E>,
|
||||||
B: Default,
|
B: Default,
|
||||||
E: Debug,
|
E: Debug,
|
||||||
{
|
{
|
||||||
|
@ -63,8 +72,7 @@ where T: Future<Item = http::Response<B>, Error = E>,
|
||||||
type Error = h2::Error;
|
type Error = h2::Error;
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
self.inner.poll()
|
self.inner.poll().or_else(|e| {
|
||||||
.or_else(|e| {
|
|
||||||
error!("turning h2 error into 500: {:?}", e);
|
error!("turning h2 error into 500: {:?}", e);
|
||||||
let response = http::Response::builder()
|
let response = http::Response::builder()
|
||||||
.status(500)
|
.status(500)
|
||||||
|
|
|
@ -20,10 +20,10 @@ type Error = tower_buffer::Error<
|
||||||
tower_balance::Error<
|
tower_balance::Error<
|
||||||
tower_reconnect::Error<
|
tower_reconnect::Error<
|
||||||
tower_h2::client::Error,
|
tower_h2::client::Error,
|
||||||
tower_h2::client::ConnectError<transport::TimeoutError<io::Error>>
|
tower_h2::client::ConnectError<transport::TimeoutError<io::Error>>,
|
||||||
>,
|
>,
|
||||||
(),
|
(),
|
||||||
>
|
>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub struct Outbound<B> {
|
pub struct Outbound<B> {
|
||||||
|
@ -44,7 +44,7 @@ impl<B> Outbound<B> {
|
||||||
|
|
||||||
impl<B> Recognize for Outbound<B>
|
impl<B> Recognize for Outbound<B>
|
||||||
where
|
where
|
||||||
B: tower_h2::Body + 'static
|
B: tower_h2::Body + 'static,
|
||||||
{
|
{
|
||||||
type Request = http::Request<B>;
|
type Request = http::Request<B>;
|
||||||
type Response = http::Response<telemetry::sensor::http::ResponseBody<tower_h2::RecvBody>>;
|
type Response = http::Response<telemetry::sensor::http::ResponseBody<tower_h2::RecvBody>>;
|
||||||
|
@ -66,9 +66,10 @@ where
|
||||||
///
|
///
|
||||||
/// Buffering is currently unbounded and does not apply timeouts. This must be
|
/// Buffering is currently unbounded and does not apply timeouts. This must be
|
||||||
/// changed.
|
/// changed.
|
||||||
fn bind_service(&mut self, authority: &http::uri::Authority)
|
fn bind_service(
|
||||||
-> Result<Self::Service, Self::RouteError>
|
&mut self,
|
||||||
{
|
authority: &http::uri::Authority,
|
||||||
|
) -> Result<Self::Service, Self::RouteError> {
|
||||||
debug!("building outbound client to {:?}", authority);
|
debug!("building outbound client to {:?}", authority);
|
||||||
|
|
||||||
let resolve = self.discovery.resolve(authority, self.bind.clone());
|
let resolve = self.discovery.resolve(authority, self.bind.clone());
|
||||||
|
@ -79,7 +80,6 @@ where
|
||||||
// which is not ideal.
|
// which is not ideal.
|
||||||
//
|
//
|
||||||
// TODO: Don't use unbounded buffering.
|
// TODO: Don't use unbounded buffering.
|
||||||
Buffer::new(balance, self.bind.executor())
|
Buffer::new(balance, self.bind.executor()).map_err(|_| {})
|
||||||
.map_err(|_| {})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
use std::{fmt, io};
|
use std::{fmt, io};
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use futures::{Async, Future, Poll, Stream};
|
use futures::{Async, Future, Poll, Stream};
|
||||||
use futures_mpsc_lossy::Receiver;
|
use futures_mpsc_lossy::Receiver;
|
||||||
use tokio_core::reactor::{Handle, Timeout};
|
use tokio_core::reactor::{Handle, Timeout};
|
||||||
|
|
||||||
use ctx;
|
|
||||||
use super::event::Event;
|
use super::event::Event;
|
||||||
use super::tap::Taps;
|
|
||||||
use super::metrics::Metrics;
|
use super::metrics::Metrics;
|
||||||
|
use super::tap::Taps;
|
||||||
use control::pb::telemetry::ReportRequest;
|
use control::pb::telemetry::ReportRequest;
|
||||||
|
use ctx;
|
||||||
|
|
||||||
/// A `Control` which has been configured but not initialized.
|
/// A `Control` which has been configured but not initialized.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -64,7 +64,7 @@ impl MakeControl {
|
||||||
/// - `rx`: the `Receiver` side of the channel on which events are sent.
|
/// - `rx`: the `Receiver` side of the channel on which events are sent.
|
||||||
/// - `flush_interval`: the maximum amount of time between sending reports to the
|
/// - `flush_interval`: the maximum amount of time between sending reports to the
|
||||||
/// controller.
|
/// controller.
|
||||||
pub (super) fn new(
|
pub(super) fn new(
|
||||||
rx: Receiver<Event>,
|
rx: Receiver<Event>,
|
||||||
flush_interval: Duration,
|
flush_interval: Duration,
|
||||||
process_ctx: &Arc<ctx::Process>,
|
process_ctx: &Arc<ctx::Process>,
|
||||||
|
@ -138,7 +138,8 @@ impl Control {
|
||||||
/// Reset the flush timeout.
|
/// Reset the flush timeout.
|
||||||
fn reset_timeout(&mut self) {
|
fn reset_timeout(&mut self) {
|
||||||
trace!("flushing in {:?}", self.flush_interval);
|
trace!("flushing in {:?}", self.flush_interval);
|
||||||
self.flush_timeout.reset(Instant::now() + self.flush_interval);
|
self.flush_timeout
|
||||||
|
.reset(Instant::now() + self.flush_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv(&mut self) -> Async<Option<Event>> {
|
fn recv(&mut self) -> Async<Option<Event>> {
|
||||||
|
@ -185,7 +186,9 @@ impl Stream for Control {
|
||||||
}
|
}
|
||||||
Async::Ready(None) => {
|
Async::Ready(None) => {
|
||||||
warn!("events finished");
|
warn!("events finished");
|
||||||
let report = self.metrics.take().map(|mut m| Self::generate_report(&mut m));
|
let report = self.metrics
|
||||||
|
.take()
|
||||||
|
.map(|mut m| Self::generate_report(&mut m));
|
||||||
if report.is_none() {
|
if report.is_none() {
|
||||||
return Ok(Async::Ready(None));
|
return Ok(Async::Ready(None));
|
||||||
}
|
}
|
||||||
|
@ -226,7 +229,10 @@ impl fmt::Debug for Control {
|
||||||
.field("rx", &self.rx)
|
.field("rx", &self.rx)
|
||||||
.field("taps", &self.taps)
|
.field("taps", &self.taps)
|
||||||
.field("flush_interval", &self.flush_interval)
|
.field("flush_interval", &self.flush_interval)
|
||||||
.field("flush_timeout", &format!("Timeout({:?})", &self.flush_interval))
|
.field(
|
||||||
|
"flush_timeout",
|
||||||
|
&format!("Timeout({:?})", &self.flush_interval),
|
||||||
|
)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,18 +76,17 @@ impl Event {
|
||||||
|
|
||||||
pub fn is_transport(&self) -> bool {
|
pub fn is_transport(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Event::TransportOpen(_) |
|
Event::TransportOpen(_) | Event::TransportClose(_, _) => true,
|
||||||
Event::TransportClose(_, _) => true,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proxy(&self) -> &Arc<ctx::Proxy> {
|
pub fn proxy(&self) -> &Arc<ctx::Proxy> {
|
||||||
match *self {
|
match *self {
|
||||||
Event::TransportOpen(ref ctx) |
|
Event::TransportOpen(ref ctx) | Event::TransportClose(ref ctx, _) => ctx.proxy(),
|
||||||
Event::TransportClose(ref ctx, _) => ctx.proxy(),
|
Event::StreamRequestOpen(ref req) | Event::StreamRequestFail(ref req, _) => {
|
||||||
Event::StreamRequestOpen(ref req) |
|
&req.server.proxy
|
||||||
Event::StreamRequestFail(ref req, _) => &req.server.proxy,
|
}
|
||||||
Event::StreamResponseOpen(ref rsp, _) |
|
Event::StreamResponseOpen(ref rsp, _) |
|
||||||
Event::StreamResponseFail(ref rsp, _) |
|
Event::StreamResponseFail(ref rsp, _) |
|
||||||
Event::StreamResponseEnd(ref rsp, _) => &rsp.request.server.proxy,
|
Event::StreamResponseEnd(ref rsp, _) => &rsp.request.server.proxy,
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
|
use std::{u32, u64};
|
||||||
use std::net;
|
use std::net;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{u32, u64};
|
|
||||||
|
|
||||||
use http;
|
use http;
|
||||||
use ordermap::OrderMap;
|
use ordermap::OrderMap;
|
||||||
|
|
||||||
use ctx;
|
use control::pb::common::{HttpMethod, TcpAddress};
|
||||||
use control::pb::common::{
|
|
||||||
TcpAddress,
|
|
||||||
HttpMethod,
|
|
||||||
};
|
|
||||||
use control::pb::proxy::telemetry::{
|
use control::pb::proxy::telemetry::{
|
||||||
eos_ctx,
|
eos_ctx,
|
||||||
ClientTransport,
|
ClientTransport,
|
||||||
EosCtx,
|
EosCtx,
|
||||||
EosScope,
|
EosScope,
|
||||||
|
Latency as PbLatency,
|
||||||
ReportRequest,
|
ReportRequest,
|
||||||
RequestCtx,
|
RequestCtx,
|
||||||
RequestScope,
|
RequestScope,
|
||||||
|
@ -24,9 +21,9 @@ use control::pb::proxy::telemetry::{
|
||||||
ServerTransport,
|
ServerTransport,
|
||||||
StreamSummary,
|
StreamSummary,
|
||||||
TransportSummary,
|
TransportSummary,
|
||||||
Latency as PbLatency,
|
|
||||||
};
|
};
|
||||||
use telemetry::event::{Event};
|
use ctx;
|
||||||
|
use telemetry::event::Event;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Metrics {
|
pub struct Metrics {
|
||||||
|
@ -113,24 +110,27 @@ impl Metrics {
|
||||||
match *event {
|
match *event {
|
||||||
Event::TransportOpen(ref transport) => {
|
Event::TransportOpen(ref transport) => {
|
||||||
self.transport(transport).connects += 1;
|
self.transport(transport).connects += 1;
|
||||||
},
|
}
|
||||||
Event::TransportClose(ref transport, ref close) => {
|
Event::TransportClose(ref transport, ref close) => {
|
||||||
self.transport(transport).disconnects.push(TransportSummary {
|
self.transport(transport)
|
||||||
|
.disconnects
|
||||||
|
.push(TransportSummary {
|
||||||
duration_ms: dur_to_ms(close.duration),
|
duration_ms: dur_to_ms(close.duration),
|
||||||
bytes_sent: 0,
|
bytes_sent: 0,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
Event::StreamRequestOpen(ref req) => {
|
Event::StreamRequestOpen(ref req) => {
|
||||||
self.request(req).count += 1;
|
self.request(req).count += 1;
|
||||||
},
|
}
|
||||||
Event::StreamRequestFail(ref req, ref fail) => {
|
Event::StreamRequestFail(ref req, ref fail) => {
|
||||||
let stats = self.request(req)
|
let stats = self.request(req)
|
||||||
.responses
|
.responses
|
||||||
.entry(None)
|
.entry(None)
|
||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default);
|
||||||
|
|
||||||
let ends = stats.ends
|
let ends = stats
|
||||||
|
.ends
|
||||||
.entry(End::Reset(fail.error.into()))
|
.entry(End::Reset(fail.error.into()))
|
||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default);
|
||||||
|
|
||||||
|
@ -145,11 +145,11 @@ impl Metrics {
|
||||||
bytes_sent: 0,
|
bytes_sent: 0,
|
||||||
frames_sent: 0,
|
frames_sent: 0,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
Event::StreamResponseOpen(ref res, ref open) => {
|
Event::StreamResponseOpen(ref res, ref open) => {
|
||||||
self.response(res).latencies.add(open.since_request_open);
|
self.response(res).latencies.add(open.since_request_open);
|
||||||
},
|
}
|
||||||
Event::StreamResponseFail(ref res, ref fail) => {
|
Event::StreamResponseFail(ref res, ref fail) => {
|
||||||
self.response_end(res, End::Reset(fail.error.into()))
|
self.response_end(res, End::Reset(fail.error.into()))
|
||||||
.push(EndStats {
|
.push(EndStats {
|
||||||
|
@ -157,7 +157,7 @@ impl Metrics {
|
||||||
bytes_sent: fail.bytes_sent,
|
bytes_sent: fail.bytes_sent,
|
||||||
frames_sent: fail.frames_sent,
|
frames_sent: fail.frames_sent,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
Event::StreamResponseEnd(ref res, ref end) => {
|
Event::StreamResponseEnd(ref res, ref end) => {
|
||||||
let e = end.grpc_status.map(End::Grpc).unwrap_or(End::Other);
|
let e = end.grpc_status.map(End::Grpc).unwrap_or(End::Other);
|
||||||
self.response_end(res, e).push(EndStats {
|
self.response_end(res, e).push(EndStats {
|
||||||
|
@ -165,7 +165,7 @@ impl Metrics {
|
||||||
bytes_sent: end.bytes_sent,
|
bytes_sent: end.bytes_sent,
|
||||||
frames_sent: end.frames_sent,
|
frames_sent: end.frames_sent,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,11 +177,20 @@ impl Metrics {
|
||||||
|
|
||||||
fn response<'a>(&mut self, res: &'a Arc<ctx::http::Response>) -> &mut ResponseStats {
|
fn response<'a>(&mut self, res: &'a Arc<ctx::http::Response>) -> &mut ResponseStats {
|
||||||
let req = self.request(&res.request);
|
let req = self.request(&res.request);
|
||||||
req.responses.entry(Some(res.status)).or_insert_with(Default::default)
|
req.responses
|
||||||
|
.entry(Some(res.status))
|
||||||
|
.or_insert_with(Default::default)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn response_end<'a>(&mut self, res: &'a Arc<ctx::http::Response>, end: End) -> &mut Vec<EndStats> {
|
fn response_end<'a>(
|
||||||
self.response(res).ends.entry(end).or_insert_with(Default::default)
|
&mut self,
|
||||||
|
res: &'a Arc<ctx::http::Response>,
|
||||||
|
end: End,
|
||||||
|
) -> &mut Vec<EndStats> {
|
||||||
|
self.response(res)
|
||||||
|
.ends
|
||||||
|
.entry(end)
|
||||||
|
.or_insert_with(Default::default)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transport<'a>(&mut self, transport: &'a ctx::transport::Ctx) -> &mut TransportStats {
|
fn transport<'a>(&mut self, transport: &'a ctx::transport::Ctx) -> &mut TransportStats {
|
||||||
|
@ -192,11 +201,9 @@ impl Metrics {
|
||||||
.entry(source)
|
.entry(source)
|
||||||
.or_insert_with(TransportStats::default)
|
.or_insert_with(TransportStats::default)
|
||||||
}
|
}
|
||||||
ctx::transport::Ctx::Client(ref c) => {
|
ctx::transport::Ctx::Client(ref c) => self.destinations
|
||||||
self.destinations
|
|
||||||
.entry(c.remote)
|
.entry(c.remote)
|
||||||
.or_insert_with(TransportStats::default)
|
.or_insert_with(TransportStats::default),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +239,6 @@ impl Metrics {
|
||||||
let mut ends = Vec::with_capacity(res_stats.ends.len());
|
let mut ends = Vec::with_capacity(res_stats.ends.len());
|
||||||
|
|
||||||
for (end, end_stats) in res_stats.ends {
|
for (end, end_stats) in res_stats.ends {
|
||||||
|
|
||||||
let mut streams = Vec::with_capacity(end_stats.len());
|
let mut streams = Vec::with_capacity(end_stats.len());
|
||||||
|
|
||||||
for stats in end_stats {
|
for stats in end_stats {
|
||||||
|
@ -257,8 +263,10 @@ impl Metrics {
|
||||||
|
|
||||||
|
|
||||||
responses.push(ResponseScope {
|
responses.push(ResponseScope {
|
||||||
ctx: status_code.map(|code| ResponseCtx {
|
ctx: status_code.map(|code| {
|
||||||
|
ResponseCtx {
|
||||||
http_status_code: u32::from(code.as_u16()),
|
http_status_code: u32::from(code.as_u16()),
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
ends: ends,
|
ends: ends,
|
||||||
response_latencies: res_stats.latencies.into(),
|
response_latencies: res_stats.latencies.into(),
|
||||||
|
@ -269,7 +277,8 @@ impl Metrics {
|
||||||
ctx: Some(RequestCtx {
|
ctx: Some(RequestCtx {
|
||||||
method: Some(HttpMethod::from(&req.method)),
|
method: Some(HttpMethod::from(&req.method)),
|
||||||
path: req.uri.path().to_string(),
|
path: req.uri.path().to_string(),
|
||||||
authority: req.uri.authority_part()
|
authority: req.uri
|
||||||
|
.authority_part()
|
||||||
.map(|a| a.to_string())
|
.map(|a| a.to_string())
|
||||||
.unwrap_or_else(String::new),
|
.unwrap_or_else(String::new),
|
||||||
source_ip: Some(req.source.into()),
|
source_ip: Some(req.source.into()),
|
||||||
|
@ -311,9 +320,7 @@ impl From<Duration> for Latency {
|
||||||
};
|
};
|
||||||
|
|
||||||
// divide the duration as ms by ten to get the value in tenths of a ms.
|
// divide the duration as ms by ten to get the value in tenths of a ms.
|
||||||
let as_tenths = as_ms
|
let as_tenths = as_ms.and_then(|ms| ms.checked_div(10)).unwrap_or_else(|| {
|
||||||
.and_then(|ms| ms.checked_div(10))
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
debug!("{:?} too large to convert to tenths of a millisecond!", dur);
|
debug!("{:?} too large to convert to tenths of a millisecond!", dur);
|
||||||
u32::MAX
|
u32::MAX
|
||||||
});
|
});
|
||||||
|
@ -337,11 +344,13 @@ impl Into<Vec<PbLatency>> for Latencies {
|
||||||
fn into(mut self) -> Vec<PbLatency> {
|
fn into(mut self) -> Vec<PbLatency> {
|
||||||
// NOTE: `OrderMap.drain` means we can reuse the allocated memory --- can we
|
// NOTE: `OrderMap.drain` means we can reuse the allocated memory --- can we
|
||||||
// ensure we're not allocating a new OrderMap after covnerting to pb?
|
// ensure we're not allocating a new OrderMap after covnerting to pb?
|
||||||
self.0.drain(..)
|
self.0
|
||||||
.map(|(Latency(latency), count)|
|
.drain(..)
|
||||||
|
.map(|(Latency(latency), count)| {
|
||||||
PbLatency {
|
PbLatency {
|
||||||
latency,
|
latency,
|
||||||
count,
|
count,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -372,14 +381,29 @@ mod tests {
|
||||||
assert!(latencies.0.is_empty());
|
assert!(latencies.0.is_empty());
|
||||||
|
|
||||||
latencies.add(Duration::from_secs(10));
|
latencies.add(Duration::from_secs(10));
|
||||||
assert_eq!(latencies.0.get(&Latency::from(Duration::from_secs(10))), Some(&1));
|
assert_eq!(
|
||||||
|
latencies.0.get(&Latency::from(Duration::from_secs(10))),
|
||||||
|
Some(&1)
|
||||||
|
);
|
||||||
|
|
||||||
latencies.add(Duration::from_secs(15));
|
latencies.add(Duration::from_secs(15));
|
||||||
assert_eq!(latencies.0.get(&Latency::from(Duration::from_secs(10))), Some(&1));
|
assert_eq!(
|
||||||
assert_eq!(latencies.0.get(&Latency::from(Duration::from_secs(15))), Some(&1));
|
latencies.0.get(&Latency::from(Duration::from_secs(10))),
|
||||||
|
Some(&1)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
latencies.0.get(&Latency::from(Duration::from_secs(15))),
|
||||||
|
Some(&1)
|
||||||
|
);
|
||||||
|
|
||||||
latencies.add(Duration::from_secs(10));
|
latencies.add(Duration::from_secs(10));
|
||||||
assert_eq!(latencies.0.get(&Latency::from(Duration::from_secs(10))), Some(&2));
|
assert_eq!(
|
||||||
assert_eq!(latencies.0.get(&Latency::from(Duration::from_secs(15))), Some(&1));
|
latencies.0.get(&Latency::from(Duration::from_secs(10))),
|
||||||
|
Some(&2)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
latencies.0.get(&Latency::from(Duration::from_secs(15))),
|
||||||
|
Some(&1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ mod metrics;
|
||||||
pub mod sensor;
|
pub mod sensor;
|
||||||
pub mod tap;
|
pub mod tap;
|
||||||
|
|
||||||
pub use self::control::{MakeControl, Control};
|
pub use self::control::{Control, MakeControl};
|
||||||
pub use self::event::Event;
|
pub use self::event::Event;
|
||||||
pub use self::sensor::Sensors;
|
pub use self::sensor::Sensors;
|
||||||
|
|
||||||
|
@ -39,10 +39,6 @@ pub fn new(
|
||||||
) -> (Sensors, MakeControl) {
|
) -> (Sensors, MakeControl) {
|
||||||
let (tx, rx) = futures_mpsc_lossy::channel(capacity);
|
let (tx, rx) = futures_mpsc_lossy::channel(capacity);
|
||||||
let s = Sensors::new(tx);
|
let s = Sensors::new(tx);
|
||||||
let c = MakeControl::new(
|
let c = MakeControl::new(rx, flush_interval, process);
|
||||||
rx,
|
|
||||||
flush_interval,
|
|
||||||
process,
|
|
||||||
);
|
|
||||||
(s, c)
|
(s, c)
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,17 +77,14 @@ impl<N, A, B> NewHttp<N, A, B>
|
||||||
where
|
where
|
||||||
A: Body + 'static,
|
A: Body + 'static,
|
||||||
B: Body + 'static,
|
B: Body + 'static,
|
||||||
N: NewService<
|
N: NewService<Request = http::Request<A>, Response = http::Response<B>, Error = client::Error>
|
||||||
Request = http::Request<A>,
|
+ 'static,
|
||||||
Response = http::Response<B>,
|
|
||||||
Error = client::Error>
|
|
||||||
+ 'static
|
|
||||||
{
|
{
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
next_id: Arc<AtomicUsize>,
|
next_id: Arc<AtomicUsize>,
|
||||||
new_service: N,
|
new_service: N,
|
||||||
handle: &super::Handle,
|
handle: &super::Handle,
|
||||||
client_ctx: &Arc<ctx::transport::Client>
|
client_ctx: &Arc<ctx::transport::Client>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
next_id,
|
next_id,
|
||||||
|
@ -103,11 +100,8 @@ impl<N, A, B> NewService for NewHttp<N, A, B>
|
||||||
where
|
where
|
||||||
A: Body + 'static,
|
A: Body + 'static,
|
||||||
B: Body + 'static,
|
B: Body + 'static,
|
||||||
N: NewService<
|
N: NewService<Request = http::Request<A>, Response = http::Response<B>, Error = client::Error>
|
||||||
Request = http::Request<A>,
|
+ 'static,
|
||||||
Response = http::Response<B>,
|
|
||||||
Error = client::Error>
|
|
||||||
+ 'static
|
|
||||||
{
|
{
|
||||||
type Request = N::Request;
|
type Request = N::Request;
|
||||||
type Response = http::Response<ResponseBody<B>>;
|
type Response = http::Response<ResponseBody<B>>;
|
||||||
|
@ -158,11 +152,8 @@ impl<S, A, B> Service for Http<S, A, B>
|
||||||
where
|
where
|
||||||
A: Body + 'static,
|
A: Body + 'static,
|
||||||
B: Body + 'static,
|
B: Body + 'static,
|
||||||
S: Service<
|
S: Service<Request = http::Request<A>, Response = http::Response<B>, Error = client::Error>
|
||||||
Request = http::Request<A>,
|
+ 'static,
|
||||||
Response = http::Response<B>,
|
|
||||||
Error = client::Error>
|
|
||||||
+ 'static
|
|
||||||
{
|
{
|
||||||
type Request = S::Request;
|
type Request = S::Request;
|
||||||
type Response = http::Response<ResponseBody<B>>;
|
type Response = http::Response<ResponseBody<B>>;
|
||||||
|
@ -180,7 +171,8 @@ where
|
||||||
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
|
||||||
let ctx = ctx::http::Request::new(&req, &ctx, &self.client_ctx, id);
|
let ctx = ctx::http::Request::new(&req, &ctx, &self.client_ctx, id);
|
||||||
|
|
||||||
self.handle.send(|| Event::StreamRequestOpen(Arc::clone(&ctx)));
|
self.handle
|
||||||
|
.send(|| Event::StreamRequestOpen(Arc::clone(&ctx)));
|
||||||
|
|
||||||
Some(RespondInner {
|
Some(RespondInner {
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -196,7 +188,7 @@ where
|
||||||
Respond {
|
Respond {
|
||||||
future,
|
future,
|
||||||
inner,
|
inner,
|
||||||
_p: PhantomData
|
_p: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +198,7 @@ where
|
||||||
impl<F, B> Future for Respond<F, B>
|
impl<F, B> Future for Respond<F, B>
|
||||||
where
|
where
|
||||||
F: Future<Item = http::Response<B>, Error = client::Error>,
|
F: Future<Item = http::Response<B>, Error = client::Error>,
|
||||||
B: Body + 'static
|
B: Body + 'static,
|
||||||
{
|
{
|
||||||
type Item = http::Response<ResponseBody<B>>;
|
type Item = http::Response<ResponseBody<B>>;
|
||||||
type Error = F::Error;
|
type Error = F::Error;
|
||||||
|
@ -230,7 +222,7 @@ where
|
||||||
Arc::clone(&ctx),
|
Arc::clone(&ctx),
|
||||||
event::StreamResponseOpen {
|
event::StreamResponseOpen {
|
||||||
since_request_open: request_open.elapsed(),
|
since_request_open: request_open.elapsed(),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -249,7 +241,7 @@ where
|
||||||
since_response_open: Duration::default(),
|
since_response_open: Duration::default(),
|
||||||
bytes_sent: 0,
|
bytes_sent: 0,
|
||||||
frames_sent: 0,
|
frames_sent: 0,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -294,7 +286,7 @@ where
|
||||||
event::StreamRequestFail {
|
event::StreamRequestFail {
|
||||||
error,
|
error,
|
||||||
since_request_open: request_open.elapsed(),
|
since_request_open: request_open.elapsed(),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -341,21 +333,21 @@ impl<B> ResponseBody<B> {
|
||||||
since_response_open: response_open.elapsed(),
|
since_response_open: response_open.elapsed(),
|
||||||
bytes_sent,
|
bytes_sent,
|
||||||
frames_sent,
|
frames_sent,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e)
|
Err(e)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> Body for ResponseBody<B>
|
impl<B> Body for ResponseBody<B>
|
||||||
where
|
where
|
||||||
B: Body + 'static
|
B: Body + 'static,
|
||||||
{
|
{
|
||||||
/// The body chunk type
|
/// The body chunk type
|
||||||
type Data = <B::Data as IntoBuf>::Buf;
|
type Data = <B::Data as IntoBuf>::Buf;
|
||||||
|
@ -406,7 +398,7 @@ where
|
||||||
since_response_open: response_open.elapsed(),
|
since_response_open: response_open.elapsed(),
|
||||||
bytes_sent,
|
bytes_sent,
|
||||||
frames_sent,
|
frames_sent,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use telemetry::event;
|
||||||
pub mod http;
|
pub mod http;
|
||||||
mod transport;
|
mod transport;
|
||||||
|
|
||||||
pub use self::http::{NewHttp, Http};
|
pub use self::http::{Http, NewHttp};
|
||||||
pub use self::transport::{Connect, Transport};
|
pub use self::transport::{Connect, Transport};
|
||||||
|
|
||||||
/// Accepts events from sensors.
|
/// Accepts events from sensors.
|
||||||
|
@ -27,7 +27,10 @@ struct Handle(Option<Sender<event::Event>>);
|
||||||
pub struct Sensors(Handle);
|
pub struct Sensors(Handle);
|
||||||
|
|
||||||
impl Handle {
|
impl Handle {
|
||||||
fn send<F>(&mut self, mk: F) where F: FnOnce()-> event::Event {
|
fn send<F>(&mut self, mk: F)
|
||||||
|
where
|
||||||
|
F: FnOnce() -> event::Event,
|
||||||
|
{
|
||||||
if let Some(tx) = self.0.as_mut() {
|
if let Some(tx) = self.0.as_mut() {
|
||||||
// We may want to capture timestamps here instead of on the consumer-side... That
|
// We may want to capture timestamps here instead of on the consumer-side... That
|
||||||
// level of precision doesn't necessarily seem worth it yet.
|
// level of precision doesn't necessarily seem worth it yet.
|
||||||
|
@ -51,8 +54,14 @@ impl Sensors {
|
||||||
Sensors(Handle(None))
|
Sensors(Handle(None))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn accept<T>(&self, io: T, opened_at: Instant, ctx: &Arc<ctx::transport::Server>) -> Transport<T>
|
pub fn accept<T>(
|
||||||
where T: AsyncRead + AsyncWrite
|
&self,
|
||||||
|
io: T,
|
||||||
|
opened_at: Instant,
|
||||||
|
ctx: &Arc<ctx::transport::Server>,
|
||||||
|
) -> Transport<T>
|
||||||
|
where
|
||||||
|
T: AsyncRead + AsyncWrite,
|
||||||
{
|
{
|
||||||
debug!("server connection open");
|
debug!("server connection open");
|
||||||
let ctx = Arc::new(ctx::transport::Ctx::Server(Arc::clone(ctx)));
|
let ctx = Arc::new(ctx::transport::Ctx::Server(Arc::clone(ctx)));
|
||||||
|
@ -60,7 +69,8 @@ impl Sensors {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect<C>(&self, connect: C, ctx: &Arc<ctx::transport::Client>) -> Connect<C>
|
pub fn connect<C>(&self, connect: C, ctx: &Arc<ctx::transport::Client>) -> Connect<C>
|
||||||
where C: tokio_connect::Connect
|
where
|
||||||
|
C: tokio_connect::Connect,
|
||||||
{
|
{
|
||||||
Connect::new(connect, &self.0, ctx)
|
Connect::new(connect, &self.0, ctx)
|
||||||
}
|
}
|
||||||
|
@ -69,15 +79,13 @@ impl Sensors {
|
||||||
&self,
|
&self,
|
||||||
next_id: Arc<AtomicUsize>,
|
next_id: Arc<AtomicUsize>,
|
||||||
new_service: N,
|
new_service: N,
|
||||||
client_ctx: &Arc<ctx::transport::Client>
|
client_ctx: &Arc<ctx::transport::Client>,
|
||||||
) -> NewHttp<N, A, B>
|
) -> NewHttp<N, A, B>
|
||||||
where
|
where
|
||||||
A: Body + 'static,
|
A: Body + 'static,
|
||||||
B: Body + 'static,
|
B: Body + 'static,
|
||||||
N: NewService<
|
N: NewService<Request = Request<A>, Response = Response<B>, Error = client::Error>
|
||||||
Request = Request<A>,
|
+ 'static,
|
||||||
Response = Response<B>,
|
|
||||||
Error = client::Error> + 'static
|
|
||||||
{
|
{
|
||||||
NewHttp::new(next_id, new_service, &self.0, client_ctx)
|
NewHttp::new(next_id, new_service, &self.0, client_ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,12 @@ pub struct Connecting<C: tokio_connect::Connect> {
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite> Transport<T> {
|
impl<T: AsyncRead + AsyncWrite> Transport<T> {
|
||||||
/// Wraps a transport with telemetry and emits a transport open event.
|
/// Wraps a transport with telemetry and emits a transport open event.
|
||||||
pub(super) fn open(io: T, opened_at: Instant, handle: &super::Handle, ctx: Arc<ctx::transport::Ctx>) -> Self {
|
pub(super) fn open(
|
||||||
|
io: T,
|
||||||
|
opened_at: Instant,
|
||||||
|
handle: &super::Handle,
|
||||||
|
ctx: Arc<ctx::transport::Ctx>,
|
||||||
|
) -> Self {
|
||||||
let mut handle = handle.clone();
|
let mut handle = handle.clone();
|
||||||
|
|
||||||
handle.send(|| event::Event::TransportOpen(Arc::clone(&ctx)));
|
handle.send(|| event::Event::TransportOpen(Arc::clone(&ctx)));
|
||||||
|
@ -70,27 +75,43 @@ impl<T: AsyncRead + AsyncWrite> Transport<T> {
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.kind() != io::ErrorKind::WouldBlock {
|
if e.kind() != io::ErrorKind::WouldBlock {
|
||||||
if let Some(Inner { mut handle, ctx, opened_at }) = self.1.take() {
|
if let Some(Inner {
|
||||||
|
mut handle,
|
||||||
|
ctx,
|
||||||
|
opened_at,
|
||||||
|
}) = self.1.take()
|
||||||
|
{
|
||||||
handle.send(move || {
|
handle.send(move || {
|
||||||
let duration = opened_at.elapsed();
|
let duration = opened_at.elapsed();
|
||||||
let ev = event::TransportClose { duration, clean: false };
|
let ev = event::TransportClose {
|
||||||
|
duration,
|
||||||
|
clean: false,
|
||||||
|
};
|
||||||
event::Event::TransportClose(ctx, ev)
|
event::Event::TransportClose(ctx, ev)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e)
|
Err(e)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Drop for Transport<T> {
|
impl<T> Drop for Transport<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(Inner { mut handle, ctx, opened_at }) = self.1.take() {
|
if let Some(Inner {
|
||||||
|
mut handle,
|
||||||
|
ctx,
|
||||||
|
opened_at,
|
||||||
|
}) = self.1.take()
|
||||||
|
{
|
||||||
handle.send(move || {
|
handle.send(move || {
|
||||||
let duration = opened_at.elapsed();
|
let duration = opened_at.elapsed();
|
||||||
let ev = event::TransportClose { clean: true, duration };
|
let ev = event::TransportClose {
|
||||||
|
clean: true,
|
||||||
|
duration,
|
||||||
|
};
|
||||||
event::Event::TransportClose(ctx, ev)
|
event::Event::TransportClose(ctx, ev)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::net;
|
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
use std::net;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use http;
|
use http;
|
||||||
|
@ -8,8 +8,8 @@ use ipnet::{Contains, Ipv4Net, Ipv6Net};
|
||||||
use super::Event;
|
use super::Event;
|
||||||
use control::pb::common::ip_address;
|
use control::pb::common::ip_address;
|
||||||
use control::pb::tap::observe_request;
|
use control::pb::tap::observe_request;
|
||||||
use ctx;
|
|
||||||
use convert::*;
|
use convert::*;
|
||||||
|
use ctx;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(super) enum Match {
|
pub(super) enum Match {
|
||||||
|
@ -40,7 +40,7 @@ pub(super) enum TcpMatch {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(super) enum NetMatch {
|
pub(super) enum NetMatch {
|
||||||
Net4(Ipv4Net),
|
Net4(Ipv4Net),
|
||||||
Net6(Ipv6Net) ,
|
Net6(Ipv6Net),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -76,55 +76,44 @@ impl Match {
|
||||||
|
|
||||||
Match::Not(ref not) => !not.matches(ev),
|
Match::Not(ref not) => !not.matches(ev),
|
||||||
|
|
||||||
Match::Source(ref src) => {
|
Match::Source(ref src) => match *ev {
|
||||||
match *ev {
|
|
||||||
Event::StreamRequestOpen(ref req) | Event::StreamRequestFail(ref req, _) => {
|
Event::StreamRequestOpen(ref req) | Event::StreamRequestFail(ref req, _) => {
|
||||||
src.matches(&req.server.remote)
|
src.matches(&req.server.remote)
|
||||||
},
|
}
|
||||||
Event::StreamResponseOpen(ref rsp, _) |
|
Event::StreamResponseOpen(ref rsp, _) |
|
||||||
Event::StreamResponseFail(ref rsp, _) |
|
Event::StreamResponseFail(ref rsp, _) |
|
||||||
Event::StreamResponseEnd(ref rsp, _) => {
|
Event::StreamResponseEnd(ref rsp, _) => src.matches(&rsp.request.server.remote),
|
||||||
src.matches(&rsp.request.server.remote)
|
|
||||||
},
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
Match::Destination(ref dst) => {
|
Match::Destination(ref dst) => match *ev {
|
||||||
match *ev {
|
|
||||||
Event::StreamRequestOpen(ref req) | Event::StreamRequestFail(ref req, _) => {
|
Event::StreamRequestOpen(ref req) | Event::StreamRequestFail(ref req, _) => {
|
||||||
dst.matches(&req.client.remote)
|
dst.matches(&req.client.remote)
|
||||||
}
|
}
|
||||||
Event::StreamResponseOpen(ref rsp, _) |
|
Event::StreamResponseOpen(ref rsp, _) |
|
||||||
Event::StreamResponseFail(ref rsp, _) |
|
Event::StreamResponseFail(ref rsp, _) |
|
||||||
Event::StreamResponseEnd(ref rsp, _) => {
|
Event::StreamResponseEnd(ref rsp, _) => dst.matches(&rsp.request.client.remote),
|
||||||
dst.matches(&rsp.request.client.remote)
|
|
||||||
}
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
Match::Http(ref http) => {
|
Match::Http(ref http) => match *ev {
|
||||||
match *ev {
|
Event::StreamRequestOpen(ref req) | Event::StreamRequestFail(ref req, _) => {
|
||||||
Event::StreamRequestOpen(ref req) |
|
|
||||||
Event::StreamRequestFail(ref req, _) => {
|
|
||||||
http.matches(req)
|
http.matches(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::StreamResponseOpen(ref rsp, _) |
|
Event::StreamResponseOpen(ref rsp, _) |
|
||||||
Event::StreamResponseFail(ref rsp, _) |
|
Event::StreamResponseFail(ref rsp, _) |
|
||||||
Event::StreamResponseEnd(ref rsp, _) => {
|
Event::StreamResponseEnd(ref rsp, _) => http.matches(&rsp.request),
|
||||||
http.matches(&rsp.request)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn new(match_: &observe_request::Match) -> Result<Match, InvalidMatch> {
|
pub(super) fn new(match_: &observe_request::Match) -> Result<Match, InvalidMatch> {
|
||||||
match_.match_.as_ref()
|
match_
|
||||||
|
.match_
|
||||||
|
.as_ref()
|
||||||
.map(Match::try_from)
|
.map(Match::try_from)
|
||||||
.unwrap_or_else(|| Err(InvalidMatch::Empty))
|
.unwrap_or_else(|| Err(InvalidMatch::Empty))
|
||||||
}
|
}
|
||||||
|
@ -154,12 +143,10 @@ impl<'a> TryFrom<&'a observe_request::match_::Match> for Match {
|
||||||
|
|
||||||
match_::Match::Any(ref seq) => Match::Any(Self::from_seq(seq)?),
|
match_::Match::Any(ref seq) => Match::Any(Self::from_seq(seq)?),
|
||||||
|
|
||||||
match_::Match::Not(ref m) => {
|
match_::Match::Not(ref m) => match m.match_.as_ref() {
|
||||||
match m.match_.as_ref() {
|
|
||||||
Some(m) => Match::Not(Box::new(Self::try_from(m)?)),
|
Some(m) => Match::Not(Box::new(Self::try_from(m)?)),
|
||||||
None => return Err(InvalidMatch::Empty),
|
None => return Err(InvalidMatch::Empty),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
match_::Match::Source(ref src) => Match::Source(TcpMatch::try_from(src)?),
|
match_::Match::Source(ref src) => Match::Source(TcpMatch::try_from(src)?),
|
||||||
|
|
||||||
|
@ -179,13 +166,9 @@ impl TcpMatch {
|
||||||
match *self {
|
match *self {
|
||||||
// If either a minimum or maximum is not specified, the range is considered to
|
// If either a minimum or maximum is not specified, the range is considered to
|
||||||
// be over a discrete value.
|
// be over a discrete value.
|
||||||
TcpMatch::PortRange(min, max) => {
|
TcpMatch::PortRange(min, max) => min <= addr.port() && addr.port() <= max,
|
||||||
min <= addr.port() && addr.port() <= max
|
|
||||||
}
|
|
||||||
|
|
||||||
TcpMatch::Net(ref net) => {
|
TcpMatch::Net(ref net) => net.matches(&addr.ip()),
|
||||||
net.matches(&addr.ip())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,21 +211,16 @@ impl<'a> TryFrom<&'a observe_request::match_::Tcp> for TcpMatch {
|
||||||
impl NetMatch {
|
impl NetMatch {
|
||||||
fn matches(&self, addr: &net::IpAddr) -> bool {
|
fn matches(&self, addr: &net::IpAddr) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
NetMatch::Net4(ref net) => {
|
NetMatch::Net4(ref net) => match *addr {
|
||||||
match *addr {
|
|
||||||
net::IpAddr::V6(_) => false,
|
net::IpAddr::V6(_) => false,
|
||||||
net::IpAddr::V4(ref addr) => net.contains(addr),
|
net::IpAddr::V4(ref addr) => net.contains(addr),
|
||||||
}
|
},
|
||||||
}
|
NetMatch::Net6(ref net) => match *addr {
|
||||||
NetMatch::Net6(ref net) => {
|
|
||||||
match *addr {
|
|
||||||
net::IpAddr::V4(_) => false,
|
net::IpAddr::V4(_) => false,
|
||||||
net::IpAddr::V6(ref addr) => net.contains(addr),
|
net::IpAddr::V6(ref addr) => net.contains(addr),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TryFrom<&'a observe_request::match_::tcp::Netmask> for NetMatch {
|
impl<'a> TryFrom<&'a observe_request::match_::tcp::Netmask> for NetMatch {
|
||||||
|
@ -263,7 +241,8 @@ impl<'a> TryFrom<&'a observe_request::match_::tcp::Netmask> for NetMatch {
|
||||||
|
|
||||||
let net = match *ip {
|
let net = match *ip {
|
||||||
ip_address::Ip::Ipv4(ref n) => {
|
ip_address::Ip::Ipv4(ref n) => {
|
||||||
let net = Ipv4Net::new((*n).into(), mask).map_err(|_| InvalidMatch::InvalidNetwork)?;
|
let net =
|
||||||
|
Ipv4Net::new((*n).into(), mask).map_err(|_| InvalidMatch::InvalidNetwork)?;
|
||||||
NetMatch::Net4(net)
|
NetMatch::Net4(net)
|
||||||
}
|
}
|
||||||
ip_address::Ip::Ipv6(ref ip6) => {
|
ip_address::Ip::Ipv6(ref ip6) => {
|
||||||
|
@ -281,21 +260,14 @@ impl<'a> TryFrom<&'a observe_request::match_::tcp::Netmask> for NetMatch {
|
||||||
impl HttpMatch {
|
impl HttpMatch {
|
||||||
fn matches(&self, req: &Arc<ctx::http::Request>) -> bool {
|
fn matches(&self, req: &Arc<ctx::http::Request>) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
HttpMatch::Scheme(ref m) => {
|
HttpMatch::Scheme(ref m) => req.uri.scheme().map(|s| *m == s).unwrap_or(false),
|
||||||
req.uri.scheme()
|
|
||||||
.map(|s| *m == s)
|
|
||||||
.unwrap_or(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpMatch::Method(ref m) => {
|
HttpMatch::Method(ref m) => *m == req.method,
|
||||||
*m == req.method
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpMatch::Authority(ref m) => {
|
HttpMatch::Authority(ref m) => req.uri
|
||||||
req.uri.authority_part()
|
.authority_part()
|
||||||
.map(|a| Self::matches_string(m, a.as_str()))
|
.map(|a| Self::matches_string(m, a.as_str()))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false),
|
||||||
}
|
|
||||||
|
|
||||||
HttpMatch::Path(ref m) => Self::matches_string(m, req.uri.path()),
|
HttpMatch::Path(ref m) => Self::matches_string(m, req.uri.path()),
|
||||||
}
|
}
|
||||||
|
@ -303,7 +275,7 @@ impl HttpMatch {
|
||||||
|
|
||||||
fn matches_string(
|
fn matches_string(
|
||||||
string_match: &observe_request::match_::http::string_match::Match,
|
string_match: &observe_request::match_::http::string_match::Match,
|
||||||
value: &str
|
value: &str,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
use control::pb::proxy::tap::observe_request::match_::http::string_match::Match::*;
|
use control::pb::proxy::tap::observe_request::match_::http::string_match::Match::*;
|
||||||
|
|
||||||
|
@ -312,7 +284,6 @@ impl HttpMatch {
|
||||||
Prefix(ref prefix) => value.starts_with(prefix),
|
Prefix(ref prefix) => value.starts_with(prefix),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TryFrom<&'a observe_request::match_::Http> for HttpMatch {
|
impl<'a> TryFrom<&'a observe_request::match_::Http> for HttpMatch {
|
||||||
|
@ -320,51 +291,45 @@ impl<'a> TryFrom<&'a observe_request::match_::Http> for HttpMatch {
|
||||||
fn try_from(m: &'a observe_request::match_::Http) -> Result<Self, InvalidMatch> {
|
fn try_from(m: &'a observe_request::match_::Http) -> Result<Self, InvalidMatch> {
|
||||||
use control::pb::proxy::tap::observe_request::match_::http::Match as Pb;
|
use control::pb::proxy::tap::observe_request::match_::http::Match as Pb;
|
||||||
|
|
||||||
m.match_.as_ref()
|
m.match_
|
||||||
|
.as_ref()
|
||||||
.ok_or_else(|| InvalidMatch::Empty)
|
.ok_or_else(|| InvalidMatch::Empty)
|
||||||
.and_then(|m| {
|
.and_then(|m| match *m {
|
||||||
match *m {
|
Pb::Scheme(ref s) => s.type_
|
||||||
Pb::Scheme(ref s) => {
|
.as_ref()
|
||||||
s.type_.as_ref()
|
|
||||||
.ok_or_else(|| InvalidMatch::Empty)
|
.ok_or_else(|| InvalidMatch::Empty)
|
||||||
.and_then(|s| {
|
.and_then(|s| {
|
||||||
s.try_into()
|
s.try_into()
|
||||||
.map(HttpMatch::Scheme)
|
.map(HttpMatch::Scheme)
|
||||||
.map_err(|_|InvalidMatch::InvalidScheme)
|
.map_err(|_| InvalidMatch::InvalidScheme)
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
|
|
||||||
Pb::Method(ref m) => {
|
Pb::Method(ref m) => m.type_
|
||||||
m.type_.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| InvalidMatch::Empty)
|
.ok_or_else(|| InvalidMatch::Empty)
|
||||||
.and_then(|m| {
|
.and_then(|m| {
|
||||||
m.try_into()
|
m.try_into()
|
||||||
.map(HttpMatch::Method)
|
.map(HttpMatch::Method)
|
||||||
.map_err(|_| InvalidMatch::InvalidHttpMethod)
|
.map_err(|_| InvalidMatch::InvalidHttpMethod)
|
||||||
})
|
}),
|
||||||
|
|
||||||
}
|
Pb::Authority(ref a) => a.match_
|
||||||
|
.as_ref()
|
||||||
Pb::Authority(ref a) => {
|
|
||||||
a.match_.as_ref()
|
|
||||||
.ok_or_else(|| InvalidMatch::Empty)
|
.ok_or_else(|| InvalidMatch::Empty)
|
||||||
.map(|a|HttpMatch::Authority(a.clone()))
|
.map(|a| HttpMatch::Authority(a.clone())),
|
||||||
}
|
|
||||||
|
|
||||||
Pb::Path(ref p) => {
|
Pb::Path(ref p) => p.match_
|
||||||
p.match_.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| InvalidMatch::Empty)
|
.ok_or_else(|| InvalidMatch::Empty)
|
||||||
.map(|p| HttpMatch::Path(p.clone()))
|
.map(|p| HttpMatch::Path(p.clone())),
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::net;
|
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
|
use std::net;
|
||||||
|
|
||||||
use ipnet::{Contains, Ipv4Net, Ipv6Net};
|
use ipnet::{Contains, Ipv4Net, Ipv6Net};
|
||||||
use quickcheck::*;
|
use quickcheck::*;
|
||||||
|
@ -377,7 +342,7 @@ mod tests {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
ObserveRequest {
|
ObserveRequest {
|
||||||
limit: g.gen(),
|
limit: g.gen(),
|
||||||
match_: Arbitrary::arbitrary(g)
|
match_: Arbitrary::arbitrary(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +350,7 @@ mod tests {
|
||||||
impl Arbitrary for observe_request::Match {
|
impl Arbitrary for observe_request::Match {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
observe_request::Match {
|
observe_request::Match {
|
||||||
match_: Arbitrary::arbitrary(g)
|
match_: Arbitrary::arbitrary(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,7 +364,7 @@ mod tests {
|
||||||
3 => observe_request::match_::Match::Source(Arbitrary::arbitrary(g)),
|
3 => observe_request::match_::Match::Source(Arbitrary::arbitrary(g)),
|
||||||
4 => observe_request::match_::Match::Destination(Arbitrary::arbitrary(g)),
|
4 => observe_request::match_::Match::Destination(Arbitrary::arbitrary(g)),
|
||||||
5 => observe_request::match_::Match::Http(Arbitrary::arbitrary(g)),
|
5 => observe_request::match_::Match::Http(Arbitrary::arbitrary(g)),
|
||||||
_ => unreachable!()
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,9 +376,12 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shrink(&self) -> Box<Iterator<Item=Self>> {
|
fn shrink(&self) -> Box<Iterator<Item = Self>> {
|
||||||
Box::new(self.matches.shrink()
|
Box::new(self.matches.shrink().map(|matches| {
|
||||||
.map(|matches| observe_request::match_::Seq { matches }))
|
observe_request::match_::Seq {
|
||||||
|
matches,
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +422,10 @@ mod tests {
|
||||||
Some(&ip_address::Ip::Ipv6(_)) => g.gen::<u32>() % 128 + 1,
|
Some(&ip_address::Ip::Ipv6(_)) => g.gen::<u32>() % 128 + 1,
|
||||||
None => 0u32,
|
None => 0u32,
|
||||||
};
|
};
|
||||||
observe_request::match_::tcp::Netmask { ip, mask }
|
observe_request::match_::tcp::Netmask {
|
||||||
|
ip,
|
||||||
|
mask,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +446,7 @@ mod tests {
|
||||||
1 => http::Match::Method(HttpMethod::arbitrary(g)),
|
1 => http::Match::Method(HttpMethod::arbitrary(g)),
|
||||||
2 => http::Match::Authority(http::StringMatch::arbitrary(g)),
|
2 => http::Match::Authority(http::StringMatch::arbitrary(g)),
|
||||||
3 => http::Match::Path(http::StringMatch::arbitrary(g)),
|
3 => http::Match::Path(http::StringMatch::arbitrary(g)),
|
||||||
_ => unreachable!()
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,7 +454,7 @@ mod tests {
|
||||||
impl Arbitrary for observe_request::match_::http::StringMatch {
|
impl Arbitrary for observe_request::match_::http::StringMatch {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
observe_request::match_::http::StringMatch {
|
observe_request::match_::http::StringMatch {
|
||||||
match_: Arbitrary::arbitrary(g)
|
match_: Arbitrary::arbitrary(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,7 +466,7 @@ mod tests {
|
||||||
match g.gen::<u32>() % 2 {
|
match g.gen::<u32>() % 2 {
|
||||||
0 => string_match::Match::Exact(String::arbitrary(g)),
|
0 => string_match::Match::Exact(String::arbitrary(g)),
|
||||||
1 => string_match::Match::Prefix(String::arbitrary(g)),
|
1 => string_match::Match::Prefix(String::arbitrary(g)),
|
||||||
_ => unreachable!()
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,7 +474,7 @@ mod tests {
|
||||||
impl Arbitrary for IpAddress {
|
impl Arbitrary for IpAddress {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
IpAddress {
|
IpAddress {
|
||||||
ip: Arbitrary::arbitrary(g)
|
ip: Arbitrary::arbitrary(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -530,7 +501,7 @@ mod tests {
|
||||||
impl Arbitrary for HttpMethod {
|
impl Arbitrary for HttpMethod {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
HttpMethod {
|
HttpMethod {
|
||||||
type_: Arbitrary::arbitrary(g)
|
type_: Arbitrary::arbitrary(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,7 +518,7 @@ mod tests {
|
||||||
impl Arbitrary for Scheme {
|
impl Arbitrary for Scheme {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||||
Scheme {
|
Scheme {
|
||||||
type_: Arbitrary::arbitrary(g)
|
type_: Arbitrary::arbitrary(g),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,12 +62,16 @@ impl Taps {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tap {
|
impl Tap {
|
||||||
pub fn new(match_: &observe_request::Match, capacity: usize)
|
pub fn new(
|
||||||
-> Result<(Tap, futures_mpsc_lossy::Receiver<Event>), InvalidMatch>
|
match_: &observe_request::Match,
|
||||||
{
|
capacity: usize,
|
||||||
|
) -> Result<(Tap, futures_mpsc_lossy::Receiver<Event>), InvalidMatch> {
|
||||||
let (tx, rx) = futures_mpsc_lossy::channel(capacity);
|
let (tx, rx) = futures_mpsc_lossy::channel(capacity);
|
||||||
let match_ = Match::new(match_)?;
|
let match_ = Match::new(match_)?;
|
||||||
let tap = Tap { match_, tx };
|
let tap = Tap {
|
||||||
|
match_,
|
||||||
|
tx,
|
||||||
|
};
|
||||||
Ok((tap, rx))
|
Ok((tap, rx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,25 @@
|
||||||
use futures::future::{self, FutureResult};
|
use futures::future::{self, FutureResult};
|
||||||
use tower::{Service, NewService};
|
use tower::{NewService, Service};
|
||||||
|
|
||||||
pub struct NewServiceFn<T> {
|
pub struct NewServiceFn<T> {
|
||||||
f: T,
|
f: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, N> NewServiceFn<T>
|
impl<T, N> NewServiceFn<T>
|
||||||
where T: Fn() -> N,
|
where
|
||||||
|
T: Fn() -> N,
|
||||||
N: Service,
|
N: Service,
|
||||||
{
|
{
|
||||||
pub fn new(f: T) -> Self {
|
pub fn new(f: T) -> Self {
|
||||||
NewServiceFn { f }
|
NewServiceFn {
|
||||||
|
f,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, N> NewService for NewServiceFn<T>
|
impl<T, N> NewService for NewServiceFn<T>
|
||||||
where T: Fn() -> N,
|
where
|
||||||
|
T: Fn() -> N,
|
||||||
N: Service,
|
N: Service,
|
||||||
{
|
{
|
||||||
type Request = N::Request;
|
type Request = N::Request;
|
||||||
|
|
|
@ -54,8 +54,12 @@ impl Future for TcpStreamNewNoDelay {
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
let tcp = try_ready!(self.0.poll());
|
let tcp = try_ready!(self.0.poll());
|
||||||
if let Err(e) = tcp.set_nodelay(true) {
|
if let Err(e) = tcp.set_nodelay(true) {
|
||||||
warn!("could not set TCP_NODELAY on {:?}/{:?}: {}",
|
warn!(
|
||||||
tcp.local_addr(), tcp.peer_addr(), e);
|
"could not set TCP_NODELAY on {:?}/{:?}: {}",
|
||||||
|
tcp.local_addr(),
|
||||||
|
tcp.peer_addr(),
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(Async::Ready(tcp))
|
Ok(Async::Ready(tcp))
|
||||||
}
|
}
|
||||||
|
@ -90,7 +94,7 @@ impl LookupAddressAndConnect {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
host_and_port: url::HostAndPort,
|
host_and_port: url::HostAndPort,
|
||||||
dns_resolver: dns::Resolver,
|
dns_resolver: dns::Resolver,
|
||||||
handle: &Handle
|
handle: &Handle,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
host_and_port,
|
host_and_port,
|
||||||
|
@ -109,8 +113,11 @@ impl tokio_connect::Connect for LookupAddressAndConnect {
|
||||||
let port = self.host_and_port.port;
|
let port = self.host_and_port.port;
|
||||||
let handle = self.handle.clone();
|
let handle = self.handle.clone();
|
||||||
let host = self.host_and_port.host.clone();
|
let host = self.host_and_port.host.clone();
|
||||||
let c = self.dns_resolver.resolve_host(&self.host_and_port.host)
|
let c = self.dns_resolver
|
||||||
.map_err(|_| io::Error::new(io::ErrorKind::NotFound, "DNS resolution failed"))
|
.resolve_host(&self.host_and_port.host)
|
||||||
|
.map_err(|_| {
|
||||||
|
io::Error::new(io::ErrorKind::NotFound, "DNS resolution failed")
|
||||||
|
})
|
||||||
.and_then(move |ip_addr: IpAddr| {
|
.and_then(move |ip_addr: IpAddr| {
|
||||||
info!("DNS resolved {} to {}", host, ip_addr);
|
info!("DNS resolved {} to {}", host, ip_addr);
|
||||||
let addr = SocketAddr::from((ip_addr, port));
|
let addr = SocketAddr::from((ip_addr, port));
|
||||||
|
@ -143,7 +150,11 @@ impl<C: tokio_connect::Connect> tokio_connect::Connect for TimeoutConnect<C> {
|
||||||
let connect = self.connect.connect();
|
let connect = self.connect.connect();
|
||||||
let duration = self.timeout;
|
let duration = self.timeout;
|
||||||
let timeout = Timeout::new(duration, &self.handle).unwrap();
|
let timeout = Timeout::new(duration, &self.handle).unwrap();
|
||||||
TimeoutConnectFuture { connect, duration, timeout }
|
TimeoutConnectFuture {
|
||||||
|
connect,
|
||||||
|
duration,
|
||||||
|
timeout,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ mod linux {
|
||||||
);
|
);
|
||||||
let port = sa.sin_port;
|
let port = sa.sin_port;
|
||||||
Ok(SocketAddr::V4(SocketAddrV4::new(ip, ntoh16(port))))
|
Ok(SocketAddr::V4(SocketAddrV4::new(ip, ntoh16(port))))
|
||||||
},
|
}
|
||||||
libc::AF_INET6 => {
|
libc::AF_INET6 => {
|
||||||
assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>());
|
assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>());
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ mod linux {
|
||||||
Ok(SocketAddr::V6(
|
Ok(SocketAddr::V6(
|
||||||
SocketAddrV6::new(ip, ntoh16(port), flowinfo, scope_id),
|
SocketAddrV6::new(ip, ntoh16(port), flowinfo, scope_id),
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
_ => Err(io::Error::new(
|
_ => Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
"invalid argument",
|
"invalid argument",
|
||||||
|
|
|
@ -8,17 +8,11 @@ use self::support::*;
|
||||||
fn outbound_asks_controller_api() {
|
fn outbound_asks_controller_api() {
|
||||||
let _ = env_logger::init();
|
let _ = env_logger::init();
|
||||||
|
|
||||||
let srv = server::new()
|
let srv = server::new().route("/", "hello").route("/bye", "bye").run();
|
||||||
.route("/", "hello")
|
|
||||||
.route("/bye", "bye")
|
|
||||||
.run();
|
|
||||||
let ctrl = controller::new()
|
let ctrl = controller::new()
|
||||||
.destination("test.conduit.local", srv.addr)
|
.destination("test.conduit.local", srv.addr)
|
||||||
.run();
|
.run();
|
||||||
let proxy = proxy::new()
|
let proxy = proxy::new().controller(ctrl).outbound(srv).run();
|
||||||
.controller(ctrl)
|
|
||||||
.outbound(srv)
|
|
||||||
.run();
|
|
||||||
let client = client::new(proxy.outbound, "test.conduit.local");
|
let client = client::new(proxy.outbound, "test.conduit.local");
|
||||||
|
|
||||||
assert_eq!(client.get("/"), "hello");
|
assert_eq!(client.get("/"), "hello");
|
||||||
|
@ -29,17 +23,12 @@ fn outbound_asks_controller_api() {
|
||||||
fn outbound_reconnects_if_controller_stream_ends() {
|
fn outbound_reconnects_if_controller_stream_ends() {
|
||||||
let _ = env_logger::init();
|
let _ = env_logger::init();
|
||||||
|
|
||||||
let srv = server::new()
|
let srv = server::new().route("/recon", "nect").run();
|
||||||
.route("/recon", "nect")
|
|
||||||
.run();
|
|
||||||
let ctrl = controller::new()
|
let ctrl = controller::new()
|
||||||
.destination_close("test.conduit.local")
|
.destination_close("test.conduit.local")
|
||||||
.destination("test.conduit.local", srv.addr)
|
.destination("test.conduit.local", srv.addr)
|
||||||
.run();
|
.run();
|
||||||
let proxy = proxy::new()
|
let proxy = proxy::new().controller(ctrl).outbound(srv).run();
|
||||||
.controller(ctrl)
|
|
||||||
.outbound(srv)
|
|
||||||
.run();
|
|
||||||
let client = client::new(proxy.outbound, "test.conduit.local");
|
let client = client::new(proxy.outbound, "test.conduit.local");
|
||||||
|
|
||||||
assert_eq!(client.get("/recon"), "nect");
|
assert_eq!(client.get("/recon"), "nect");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use support::*;
|
use support::*;
|
||||||
|
|
||||||
use self::futures::sync::{oneshot, mpsc};
|
use self::futures::sync::{mpsc, oneshot};
|
||||||
use self::tokio_core::net::TcpStream;
|
use self::tokio_core::net::TcpStream;
|
||||||
use self::tower_h2::client::Error;
|
use self::tower_h2::client::Error;
|
||||||
|
|
||||||
|
@ -35,14 +35,14 @@ impl Client {
|
||||||
.body(())
|
.body(())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let _ = self.tx.unbounded_send((req, tx));
|
let _ = self.tx.unbounded_send((req, tx));
|
||||||
rx
|
rx.map_err(|_| panic!("client request dropped"))
|
||||||
.map_err(|_| panic!("client request dropped"))
|
|
||||||
.and_then(|res| {
|
.and_then(|res| {
|
||||||
let stream = RecvBodyStream(res.unwrap().into_parts().1);
|
let stream = RecvBodyStream(res.unwrap().into_parts().1);
|
||||||
stream.concat2()
|
stream.concat2()
|
||||||
}).map(|body| {
|
})
|
||||||
::std::str::from_utf8(&body).unwrap().to_string()
|
.map(|body| ::std::str::from_utf8(&body).unwrap().to_string())
|
||||||
}).wait().unwrap()
|
.wait()
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +56,17 @@ fn run(addr: SocketAddr) -> Sender {
|
||||||
let reactor = core.handle();
|
let reactor = core.handle();
|
||||||
|
|
||||||
let conn = Conn(addr, reactor.clone());
|
let conn = Conn(addr, reactor.clone());
|
||||||
let h2 = tower_h2::Client::<Conn, Handle, ()>::new(conn, Default::default(), reactor.clone());
|
let h2 = tower_h2::Client::<Conn, Handle, ()>::new(
|
||||||
|
conn,
|
||||||
|
Default::default(),
|
||||||
|
reactor.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let done = h2.new_service()
|
let done = h2.new_service()
|
||||||
.map_err(move |err| println!("connect error ({:?}): {:?}", addr, err))
|
.map_err(move |err| println!("connect error ({:?}): {:?}", addr, err))
|
||||||
.and_then(move |mut h2| {
|
.and_then(move |mut h2| {
|
||||||
rx.for_each(move |(req, cb)| {
|
rx.for_each(move |(req, cb)| {
|
||||||
let fut = h2.call(req)
|
let fut = h2.call(req).then(|result| {
|
||||||
.then(|result| {
|
|
||||||
let _ = cb.send(result);
|
let _ = cb.send(result);
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,7 +35,8 @@ impl Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destination(mut self, dest: &str, addr: SocketAddr) -> Self {
|
pub fn destination(mut self, dest: &str, addr: SocketAddr) -> Self {
|
||||||
self.destinations.push((dest.into(), Some(destination_update(addr))));
|
self.destinations
|
||||||
|
.push((dest.into(), Some(destination_update(addr))));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +69,11 @@ struct Svc {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Svc {
|
impl Svc {
|
||||||
fn route(&self, path: &str, body: RecvBodyStream) -> Box<Future<Item=Response, Error=h2::Error>> {
|
fn route(
|
||||||
|
&self,
|
||||||
|
path: &str,
|
||||||
|
body: RecvBodyStream,
|
||||||
|
) -> Box<Future<Item = Response, Error = h2::Error>> {
|
||||||
let mut rsp = http::Response::builder();
|
let mut rsp = http::Response::builder();
|
||||||
rsp.version(http::Version::HTTP_2);
|
rsp.version(http::Version::HTTP_2);
|
||||||
|
|
||||||
|
@ -94,7 +99,7 @@ impl Svc {
|
||||||
let rsp = rsp.body(body).unwrap();
|
let rsp = rsp.body(body).unwrap();
|
||||||
Ok(rsp)
|
Ok(rsp)
|
||||||
}))
|
}))
|
||||||
},
|
}
|
||||||
TELEMETRY_REPORT => {
|
TELEMETRY_REPORT => {
|
||||||
let mut reports = self.reports.clone();
|
let mut reports = self.reports.clone();
|
||||||
Box::new(body.concat2().and_then(move |mut bytes| {
|
Box::new(body.concat2().and_then(move |mut bytes| {
|
||||||
|
@ -121,7 +126,7 @@ impl Service for Svc {
|
||||||
type Request = Request<RecvBody>;
|
type Request = Request<RecvBody>;
|
||||||
type Response = Response;
|
type Response = Response;
|
||||||
type Error = h2::Error;
|
type Error = h2::Error;
|
||||||
type Future = Box<Future<Item=Response, Error=h2::Error>>;
|
type Future = Box<Future<Item = Response, Error = h2::Error>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
Ok(Async::Ready(()))
|
Ok(Async::Ready(()))
|
||||||
|
@ -160,11 +165,7 @@ impl Body for GrpcBody {
|
||||||
|
|
||||||
fn poll_data(&mut self) -> Poll<Option<Bytes>, self::h2::Error> {
|
fn poll_data(&mut self) -> Poll<Option<Bytes>, self::h2::Error> {
|
||||||
let data = self.message.split_off(0);
|
let data = self.message.split_off(0);
|
||||||
let data = if data.is_empty() {
|
let data = if data.is_empty() { None } else { Some(data) };
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(data)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Async::Ready(data))
|
Ok(Async::Ready(data))
|
||||||
}
|
}
|
||||||
|
@ -231,11 +232,10 @@ fn run(controller: Controller) -> Listening {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
core.handle()
|
core.handle().spawn(
|
||||||
.spawn(
|
|
||||||
serve
|
serve
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|e| println!("controller error: {}", e))
|
.map_err(|e| println!("controller error: {}", e)),
|
||||||
);
|
);
|
||||||
|
|
||||||
core.run(rx).unwrap();
|
core.run(rx).unwrap();
|
||||||
|
@ -251,32 +251,26 @@ fn run(controller: Controller) -> Listening {
|
||||||
|
|
||||||
fn destination_update(addr: SocketAddr) -> pb::destination::Update {
|
fn destination_update(addr: SocketAddr) -> pb::destination::Update {
|
||||||
pb::destination::Update {
|
pb::destination::Update {
|
||||||
update: Some(
|
update: Some(pb::destination::update::Update::Add(
|
||||||
pb::destination::update::Update::Add(
|
|
||||||
pb::destination::WeightedAddrSet {
|
pb::destination::WeightedAddrSet {
|
||||||
addrs: vec![
|
addrs: vec![
|
||||||
pb::destination::WeightedAddr {
|
pb::destination::WeightedAddr {
|
||||||
addr: Some(
|
addr: Some(pb::common::TcpAddress {
|
||||||
pb::common::TcpAddress {
|
|
||||||
ip: Some(ip_conv(addr.ip())),
|
ip: Some(ip_conv(addr.ip())),
|
||||||
port: u32::from(addr.port()),
|
port: u32::from(addr.port()),
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
weight: 0,
|
weight: 0,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
)
|
)),
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ip_conv(ip: IpAddr) -> pb::common::IpAddress {
|
fn ip_conv(ip: IpAddr) -> pb::common::IpAddress {
|
||||||
match ip {
|
match ip {
|
||||||
IpAddr::V4(v4) => {
|
IpAddr::V4(v4) => pb::common::IpAddress {
|
||||||
pb::common::IpAddress {
|
|
||||||
ip: Some(pb::common::ip_address::Ip::Ipv4(v4.into())),
|
ip: Some(pb::common::ip_address::Ip::Ipv4(v4.into())),
|
||||||
}
|
|
||||||
},
|
},
|
||||||
IpAddr::V6(v6) => {
|
IpAddr::V6(v6) => {
|
||||||
let (first, last) = octets_to_u64s(v6.octets());
|
let (first, last) = octets_to_u64s(v6.octets());
|
||||||
|
@ -291,21 +285,13 @@ fn ip_conv(ip: IpAddr) -> pb::common::IpAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn octets_to_u64s(octets: [u8; 16]) -> (u64, u64) {
|
fn octets_to_u64s(octets: [u8; 16]) -> (u64, u64) {
|
||||||
let first = (u64::from(octets[0]) << 56)
|
let first = (u64::from(octets[0]) << 56) + (u64::from(octets[1]) << 48)
|
||||||
+ (u64::from(octets[1]) << 48)
|
+ (u64::from(octets[2]) << 40) + (u64::from(octets[3]) << 32)
|
||||||
+ (u64::from(octets[2]) << 40)
|
+ (u64::from(octets[4]) << 24) + (u64::from(octets[5]) << 16)
|
||||||
+ (u64::from(octets[3]) << 32)
|
+ (u64::from(octets[6]) << 8) + u64::from(octets[7]);
|
||||||
+ (u64::from(octets[4]) << 24)
|
let last = (u64::from(octets[8]) << 56) + (u64::from(octets[9]) << 48)
|
||||||
+ (u64::from(octets[5]) << 16)
|
+ (u64::from(octets[10]) << 40) + (u64::from(octets[11]) << 32)
|
||||||
+ (u64::from(octets[6]) << 8)
|
+ (u64::from(octets[12]) << 24) + (u64::from(octets[13]) << 16)
|
||||||
+ u64::from(octets[7]);
|
+ (u64::from(octets[14]) << 8) + u64::from(octets[15]);
|
||||||
let last = (u64::from(octets[8]) << 56)
|
|
||||||
+ (u64::from(octets[9]) << 48)
|
|
||||||
+ (u64::from(octets[10]) << 40)
|
|
||||||
+ (u64::from(octets[11]) << 32)
|
|
||||||
+ (u64::from(octets[12]) << 24)
|
|
||||||
+ (u64::from(octets[13]) << 16)
|
|
||||||
+ (u64::from(octets[14]) << 8)
|
|
||||||
+ u64::from(octets[15]);
|
|
||||||
(first, last)
|
(first, last)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,29 +2,29 @@
|
||||||
|
|
||||||
extern crate bytes;
|
extern crate bytes;
|
||||||
extern crate conduit_proxy;
|
extern crate conduit_proxy;
|
||||||
pub extern crate env_logger;
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate h2;
|
extern crate h2;
|
||||||
extern crate http;
|
extern crate http;
|
||||||
extern crate prost;
|
extern crate prost;
|
||||||
extern crate tokio_core;
|
|
||||||
extern crate tokio_connect;
|
extern crate tokio_connect;
|
||||||
|
extern crate tokio_core;
|
||||||
extern crate tower;
|
extern crate tower;
|
||||||
extern crate tower_h2;
|
extern crate tower_h2;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
pub extern crate env_logger;
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
pub use std::time::Duration;
|
|
||||||
use self::bytes::{BigEndian, Bytes, BytesMut};
|
use self::bytes::{BigEndian, Bytes, BytesMut};
|
||||||
pub use self::futures::*;
|
pub use self::futures::*;
|
||||||
use self::futures::sync::oneshot;
|
use self::futures::sync::oneshot;
|
||||||
use self::http::{Request, HeaderMap};
|
use self::http::{HeaderMap, Request};
|
||||||
use self::http::header::HeaderValue;
|
use self::http::header::HeaderValue;
|
||||||
use self::tokio_connect::Connect;
|
use self::tokio_connect::Connect;
|
||||||
use self::tokio_core::net::TcpListener;
|
use self::tokio_core::net::TcpListener;
|
||||||
use self::tokio_core::reactor::{Core, Handle};
|
use self::tokio_core::reactor::{Core, Handle};
|
||||||
use self::tower::{NewService, Service};
|
use self::tower::{NewService, Service};
|
||||||
use self::tower_h2::{Body, RecvBody};
|
use self::tower_h2::{Body, RecvBody};
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
pub use std::time::Duration;
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod controller;
|
pub mod controller;
|
||||||
|
@ -32,7 +32,11 @@ pub mod proxy;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
pub type Shutdown = oneshot::Sender<()>;
|
pub type Shutdown = oneshot::Sender<()>;
|
||||||
pub type ShutdownRx = future::Then<oneshot::Receiver<()>, Result<(), ()>, fn(Result<(), oneshot::Canceled>) -> Result<(), ()>>;
|
pub type ShutdownRx = future::Then<
|
||||||
|
oneshot::Receiver<()>,
|
||||||
|
Result<(), ()>,
|
||||||
|
fn(Result<(), oneshot::Canceled>) -> Result<(), ()>,
|
||||||
|
>;
|
||||||
|
|
||||||
pub fn shutdown_signal() -> (oneshot::Sender<()>, ShutdownRx) {
|
pub fn shutdown_signal() -> (oneshot::Sender<()>, ShutdownRx) {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
|
@ -39,7 +39,11 @@ impl Server {
|
||||||
let mut core = Core::new().unwrap();
|
let mut core = Core::new().unwrap();
|
||||||
let reactor = core.handle();
|
let reactor = core.handle();
|
||||||
|
|
||||||
let h2 = tower_h2::Server::new(NewSvc(Arc::new(self.routes)), Default::default(), reactor.clone());
|
let h2 = tower_h2::Server::new(
|
||||||
|
NewSvc(Arc::new(self.routes)),
|
||||||
|
Default::default(),
|
||||||
|
reactor.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
let addr = ([127, 0, 0, 1], 0).into();
|
let addr = ([127, 0, 0, 1], 0).into();
|
||||||
let bind = TcpListener::bind(&addr, &reactor).expect("bind");
|
let bind = TcpListener::bind(&addr, &reactor).expect("bind");
|
||||||
|
@ -60,11 +64,10 @@ impl Server {
|
||||||
Ok((h2, reactor))
|
Ok((h2, reactor))
|
||||||
});
|
});
|
||||||
|
|
||||||
core.handle()
|
core.handle().spawn(
|
||||||
.spawn(
|
|
||||||
serve
|
serve
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|e| println!("server error: {}", e))
|
.map_err(|e| println!("server error: {}", e)),
|
||||||
);
|
);
|
||||||
|
|
||||||
info!("running");
|
info!("running");
|
||||||
|
|
|
@ -9,9 +9,7 @@ fn inbound_sends_telemetry() {
|
||||||
let _ = env_logger::init();
|
let _ = env_logger::init();
|
||||||
|
|
||||||
info!("running test server");
|
info!("running test server");
|
||||||
let srv = server::new()
|
let srv = server::new().route("/hey", "hello").run();
|
||||||
.route("/hey", "hello")
|
|
||||||
.run();
|
|
||||||
|
|
||||||
let mut ctrl = controller::new();
|
let mut ctrl = controller::new();
|
||||||
let reports = ctrl.reports();
|
let reports = ctrl.reports();
|
||||||
|
|
Loading…
Reference in New Issue