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
//! This crate is a Bitmessage node implementation as a library for Koibumi, an experimental Bitmessage client.
//!
//! See [`koibumi`](https://crates.io/crates/koibumi) for more about the application.
//! See [Bitmessage](https://bitmessage.org/) for more about the protocol.
//!
//! # Examples
//!
//! ```no_run
//! use std::str::FromStr;
//!
//! use async_std::task;
//! use futures::{sink::SinkExt, stream::StreamExt};
//!
//! use koibumi_node::{self as node, db, Command, Config, Event, Response};
//!
//! let (command_sender, mut response_receiver, handle) = node::spawn();
//!
//! let config = Config::builder()
//!     .server(Some("127.0.0.1:8444".parse().unwrap()))
//!     .socks(Some("127.0.0.1:9050".parse().unwrap()))
//!     .connect_to_onion(true)
//!     .connect_to_ip(true)
//!     .seeds(vec!["quzwelsuziwqgpt2.onion:8444".parse().unwrap()])
//!     .build();
//!
//! let mut sender = command_sender;
//! let response = task::block_on(async {
//!     let pool = db::SqlitePool::connect_with(
//!         sqlx::sqlite::SqliteConnectOptions::from_str("sqlite::memory:").unwrap()
//!     ).await;
//!     if let Err(err) = pool {
//!         eprintln!("{}", err);
//!         return None;
//!     }
//!     let pool = pool.unwrap();
//!
//!     if let Err(err) = sender.send(Command::Start(config.into(), pool, Vec::new())).await {
//!         eprintln!("{}", err);
//!         return None;
//!     }
//!     response_receiver.next().await
//! });
//! let Response::Started(mut receiver) = response.unwrap();
//!
//! task::block_on(async {
//!     while let Some(event) = receiver.next().await {
//!         match event {
//!             Event::ConnectionCounts { .. } => (),
//!             Event::AddrCount(_count) => (),
//!             Event::Established { addr, user_agent, rating } => {
//!                 println!("established: {} {} rating:{}", addr, user_agent, rating);
//!             }
//!             Event::Disconnected { addr } => {
//!                 println!("disconnected: {}", addr);
//!             }
//!             Event::Objects { .. } => (),
//!             Event::Stopped => {
//!                 break;
//!             }
//!             Event::Broadcast {
//!                 user_id,
//!                 address,
//!                 object,
//!             } => {
//!                 println!("broadcast received from {}", address);
//!             }
//!             Event::Msg {
//!                 user_id,
//!                 address,
//!                 object,
//!             } => {
//!                 println!("received msg for {}", address);
//!             }
//!         }
//!     }
//!
//!     handle.await;
//! });
//! ```

#![deny(unsafe_code)]
#![warn(missing_docs)]
#![recursion_limit = "2048"]

mod config;
mod connection;
mod connection_loop;
mod constant;
pub mod db;
mod inv_manager;
mod manager;
mod message_handler;
mod net;
mod node_manager;
mod object_processor;
mod pow_manager;
mod user_manager;

pub use config::{Builder as ConfigBuilder, Config, SocksAuth};
pub use manager::{run, Command, Event, Response};
pub use net::SocketAddrNode;
pub use node_manager::Rating;
pub use user_manager::User;

use async_std::task;
use futures::channel::mpsc::{self, Receiver, Sender};

/// Spawns a task that manage a Bitmessage node.
pub fn spawn() -> (Sender<Command>, Receiver<Response>, task::JoinHandle<()>) {
    const COMMAND_BUFFER: usize = 0x10000;
    const RESPONSE_BUFFER: usize = 0x10000;
    let (command_sender, command_receiver) = mpsc::channel(COMMAND_BUFFER);
    let (response_sender, response_receiver) = mpsc::channel(RESPONSE_BUFFER);
    let handle = task::spawn(manager::run(command_receiver, response_sender));
    (command_sender, response_receiver, handle)
}