1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Netidx is like DNS for values. With netidx you can name individual
//! values in your program, and other programs can find and subscribe
//! to those values securely over the network.
//!
//! Like DNS netidx maintains a hierarchical namespace in a resolver
//! server. Publishers tell the resolver about values they
//! have. Subscribers ask the resolver for values they want. Once a
//! subscriber knows where to find a value it is looking for, it
//! connects directly to the publisher, and the resolver is no longer
//! involved.
//!
//! # Publisher
//! ```no_run
//! # fn get_cpu_temp() -> f32 { 42. }
//! use netidx::{
//!     publisher::{Publisher, Value, BindCfg},
//!     config::Config,
//!     resolver::Auth,
//!     path::Path,
//! };
//! use tokio::time;
//! use std::time::Duration;
//!
//! # use anyhow::Result;
//! # async fn run() -> Result<()> {
//! // load the site cluster config. You can also just use a file.
//! let cfg = Config::load_default()?;
//!
//! // no authentication (kerberos v5 is the other option)
//! // listen on any unique address matching 192.168.0.0/16
//! let publisher = Publisher::new(cfg, Auth::Anonymous, "192.168.0.0/16".parse()?).await?;
//!
//! let temp = publisher.publish(
//!     Path::from("/hw/washu-chan/cpu-temp"),
//!     Value::F32(get_cpu_temp())
//! )?;
//! publisher.flush(None).await;
//!
//! loop {
//!     time::sleep(Duration::from_millis(500)).await;
//!     temp.update(Value::F32(get_cpu_temp()));
//!     publisher.flush(None).await;
//! }
//! # Ok(())
//! # };
//! ```
//!
//! # Subscriber
//! ```no_run
//! use netidx::{
//!     subscriber::{Subscriber, UpdatesFlags},
//!     config::Config,
//!     resolver::Auth,
//!     path::Path,
//! };
//! use futures::{prelude::*, channel::mpsc};
//! # use anyhow::Result;
//!
//! # async fn run() -> Result<()> {
//! let cfg = Config::load_default()?;
//! let subscriber = Subscriber::new(cfg, Auth::Anonymous)?;
//! let path = Path::from("/hw/washu-chan/cpu-temp");
//! let temp = subscriber.subscribe_one(path, None).await?;
//! println!("washu-chan cpu temp is: {:?}", temp.last());
//!
//! let (tx, mut rx) = mpsc::channel(10);
//! temp.updates(UpdatesFlags::empty(), tx);
//! while let Some(mut batch) = rx.next().await {
//!     for (_, v) in batch.drain(..) {
//!         println!("washu-chan cpu temp is: {:?}", v);
//!     }
//! }
//! # Ok(())
//! # };
//! ```
//!
//! Published values always have a value, and new subscribers receive
//! the most recent published value initially. Thereafter a
//! subscription is a lossless ordered stream, just like a tcp
//! connection, except that instead of bytes `publisher::Value` is the
//! unit of transmission. Since the subscriber can write values back
//! to the publisher, the connection is bidirectional, also like a Tcp
//! stream.
//!
//! Values include many useful primitives, including zero copy bytes
//! buffers (using the awesome bytes crate), so you can easily use
//! netidx to efficiently send any kind of message you like. However
//! it's advised to stick to primitives and express structure with
//! muliple published values in a hierarchy, since this makes your
//! system more discoverable, and is also quite efficient.
//!
//! In many environments security is a requirement, whereas in others
//! it's not necessary. To handle both of these cases netidx includes
//! optional support for kerberos v5 (including Active Directory). If
//! enabled, all components will do mutual authentication between the
//! resolver, subscriber, and publisher as well as encryption of all
//! data on the wire. In addition to authentication, the resolver
//! server in krb5 mode maintains and enforces authorization
//! permissions for the entire namespace, so the resolvers can
//! centrally enforce who can publish where, and who can subscribe to
//! what.
//!
//! * Publish with a [`Publisher`](publisher/struct.Publisher.html)
//! * Subscribe with a [`Subscriber`](subscriber/struct.Subscriber.html)
#![recursion_limit = "1024"]
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate anyhow;
#[macro_use] extern crate netidx_core;

pub use netidx_core::{chars, pack, pool, path, utils};
pub use netidx_netproto as protocol;

mod batch_channel;
mod auth;
mod channel;
pub mod config;
mod os;
pub mod publisher;
pub mod resolver;
pub mod resolver_server;
mod resolver_single;
mod shard_resolver_store;
mod resolver_store;
mod secstore;
pub mod subscriber;
#[cfg(test)]
mod test;