Преглед изворни кода

book/ dchat: EDIT1- clarified language and fixed errors

lunar-mining пре 4 година
родитељ
комит
cb7702dd82

+ 2 - 1
doc/src/SUMMARY.md

@@ -30,7 +30,8 @@
     - [Deployment](learn/dchat/local-deployment/local-deployment.md)
     - [Deployment](learn/dchat/local-deployment/local-deployment.md)
       - [Getting started](learn/dchat/local-deployment/getting-started.md)
       - [Getting started](learn/dchat/local-deployment/getting-started.md)
       - [Writing a daemon](learn/dchat/local-deployment/writing-a-daemon.md)
       - [Writing a daemon](learn/dchat/local-deployment/writing-a-daemon.md)
-      - [Inbound and outbound](learn/dchat/local-deployment/inbound-and-outbound.md)
+      - [Sessions](learn/dchat/local-deployment/sessions.md)
+      - [Settings](learn/dchat/local-deployment/settings.md)
       - [Error handling](learn/dchat/local-deployment/error-handling.md)
       - [Error handling](learn/dchat/local-deployment/error-handling.md)
       - [Running the network](learn/dchat/local-deployment/creating-and-running.md)
       - [Running the network](learn/dchat/local-deployment/creating-and-running.md)
       - [Seed node](learn/dchat/local-deployment/seed-node.md)
       - [Seed node](learn/dchat/local-deployment/seed-node.md)

+ 16 - 12
doc/src/learn/dchat/creating-dchat/protocols.md

@@ -28,32 +28,36 @@ our custom protocol. In particular:
 
 
 1. The Message Subsystem
 1. The Message Subsystem
 
 
-MessageSubsystem is a generic publish/subscribe class that can
-dispatch any kind of message to a list of dispatchers. This is how we
-can send and receive custom messages on the p2p network.
+MessageSubsystem is a generic publish/subscribe class that contains
+a list of Message dispatchers. A new dispatcher is created for every
+Message type. These Message-specific dispatchers maintain a list of
+susbscribers that are subscribed to a particular message.
 
 
 2. Message Subscription
 2. Message Subscription
 
 
-A subscription to a message type. 
+A subscription to a specific Message type. Handles receiving messages
+on a subscription.
 
 
 3. Channel
 3. Channel
 
 
 A channel is an async connection for communication between nodes. It is
 A channel is an async connection for communication between nodes. It is
 also a powerful interface that exposes methods to the Message Subsystem
 also a powerful interface that exposes methods to the Message Subsystem
-and implements message subscriptions.  Channel also contains a weak
-pointer to its parent, Session.
+and implements message subscriptions.
 
 
 4. The Protocol Registry 
 4. The Protocol Registry 
 
 
-ProtocolRegistry takes any kind of generic protocol and initializes it. We
-use it through the method register() which passes a protocol constructor
-and a session bitflag which determines which sessions (outbound, inbound,
-or seed) will run our protocol.
+ProtocolRegistry is a registry of all protocols. We use it through the
+method register() which passes a protocol constructor and a session
+bitflag. The bitflag specifies which sessions the protocol is created
+for. The ProtocolRegistry then spawns new protocols for different channels
+depending on the session.
 
 
 5. ProtocolJobsManager
 5. ProtocolJobsManager
 
 
-An asynchronous job manager that spawns and stops tasks created by
-protocols across the network.
+An asynchronous job manager that spawns and stops tasks. Its main
+purpose is so a protocol can cleanly close all started jobs, through
+the function close_all_tasks().  This way if the connection between
+nodes is dropped and the channel closes, all protocols are also shutdown.
 
 
 6. ProtocolBase
 6. ProtocolBase
 
 

+ 21 - 7
doc/src/learn/dchat/creating-dchat/register-protocol.md

@@ -8,8 +8,6 @@ register_protocol(). It will invoke the protocol_registry using the
 handle to the p2p network contained in the Dchat struct. It will then
 handle to the p2p network contained in the Dchat struct. It will then
 call register() on the registry and pass the ProtocolDchat constructor.
 call register() on the registry and pass the ProtocolDchat constructor.
 
 
-Be sure to import Dchatmsg and ProtocolDchat so we can access their data.
-
 ```
 ```
 use crate::{dchatmsg::DchatmsgsBuffer, protocol_dchat::ProtocolDchat};
 use crate::{dchatmsg::DchatmsgsBuffer, protocol_dchat::ProtocolDchat};
 
 
@@ -28,12 +26,28 @@ async fn register_protocol(&self, msgs: DchatmsgsBuffer) -> Result<()> {
 }
 }
 ```
 ```
 
 
-We set the bitflag to SESSION_ALL to specify that this protocol should
-be performed by every session. We also use a closure to capture a pointer
-to Channel, which we pass into the ProtocolDchat constructor. This gives
-us access to the message subscriber methods.
+There's a lot going on here. register() takes a closure with two
+arguments, `channel` and `p2p`. We use `move` to capture these values. We
+then create an async closure that captures these values and the value
+`msgs` and use them to call ProtocolDchat::init() in the async block.
+
+The code would be expressed more simply as:
+
+```
+registry.register(net::SESSION_ALL, async move |channel, _p2p| {
+        ProtocolDchat::init(channel, msgs).await
+    })
+    .await;
+```
+
+However we cannot do this due to limitation with async closures. So
+instead we wrap the `async move` in a `move` in order to capture the
+variables needed by ProtocolDchat::init().
+
+Notice the use of a bitflag. We use SESSION_ALL to specify that this
+protocol should be performed by every session. 
 
 
-Notice that register_protocol() requires a DchatmsgsBuffer that we send
+Also notice that register_protocol() requires a DchatmsgsBuffer that we send
 to the ProtocolDchat constructor. We'll create the DchatmsgsBuffer in
 to the ProtocolDchat constructor. We'll create the DchatmsgsBuffer in
 main() and pass it to Dchat::new(). Let's add DchatmsgsBuffer to the
 main() and pass it to Dchat::new(). Let's add DchatmsgsBuffer to the
 Dchat struct definition first.
 Dchat struct definition first.

+ 0 - 2
doc/src/learn/dchat/local-deployment/creating-and-running.md

@@ -14,8 +14,6 @@ let p2p = net::P2p::new(settings?.into()).await;
 We will next create a Dchat struct that will store all the data required
 We will next create a Dchat struct that will store all the data required
 by dchat. For now, it will just hold a pointer to the p2p network.
 by dchat. For now, it will just hold a pointer to the p2p network.
 
 
-To accesss this we will need to add net to our imports, like so:
-
 ```
 ```
 use darkfi::net;
 use darkfi::net;
 
 

+ 21 - 110
doc/src/learn/dchat/local-deployment/inbound-and-outbound.md

@@ -1,120 +1,31 @@
-# Inbound and Outbound nodes
+# Sessions
 
 
-To create an instance of the p2p network, we must configure our p2p
-network settings into a type called net::Settings. These settings
-determine whether our node will be an outbound, inbound, manual or
-seed node.
-
-Inbound, outbound and seed nodes perform different roles on the p2p
+To deploy the p2p network, we need to configure two types of nodes:
+inbound and outbound. These nodes perform different roles on the p2p
 network. An inbound node receives connections. An outbound node makes
 network. An inbound node receives connections. An outbound node makes
-connections. A seed node is used when connecting to the network: it is
-a special kind of inbound node that gets connected to, sends over a list
-of addresses and disconnects again.
+connections.
 
 
-The behavior of the different
-kinds of nodes is defined in what is called a
+The behavior of these nodes is defined in what is called a
 [Session](https://github.com/darkrenaissance/darkfi/blob/master/src/net/session/mod.rs#L93).
 [Session](https://github.com/darkrenaissance/darkfi/blob/master/src/net/session/mod.rs#L93).
-Session is a trait that outbound, inbound, manual and seed nodes all
-implement. Session implementations expose methods such as stopping and
-starting a channel, accepting connections (inbound nodes) or making
-connections (outbound nodes).
-
-On production-ready software, you would usually configure your node
-using a config file or command line inputs. On dchat we are keeping
-things ultra simple. We pass a command line flag that is either `a` or
-`b`. If we pass `a` we will initialize an inbound node. If we pass `b`
-we will initialize an outbound node.
-
-Here's how that works. We define two methods called alice() and
-bob(). alice() returns the Settings that will create an inbound
-node. bob() return the Settings for an outbound node.
-
-We also implement logging that outputs to /tmp/alice.log and /tmp/bob.log
-so we can access the debug output of our nodes. We store this info in a
-log file because we don't want it interfering with our terminal UI when
-we eventually build it.
-
-This is a function that returns the settings to create Alice, an
-inbound node:
-
-```
-use simplelog::WriteLogger;
-use std::fs::File;
-
-use darkfi::{net::Settings, Result};
-use url::Url;
-
-fn alice() -> Result<Settings> {
-    let log_level = simplelog::LevelFilter::Debug;
-    let log_config = simplelog::Config::default();
-
-    let log_path = "/tmp/alice.log";
-    let file = File::create(log_path).unwrap();
-    WriteLogger::init(log_level, log_config, file)?;
-
-    let seed = Url::parse("tcp://127.0.0.1:55555").unwrap();
-    let inbound = Url::parse("tcp://127.0.0.1:55554").unwrap();
-    let ext_addr = Url::parse("tcp://127.0.0.1:55554").unwrap();
-
-    let settings = Settings {
-        inbound: Some(inbound),
-        outbound_connections: 0,
-        manual_attempt_limit: 0,
-        seed_query_timeout_seconds: 8,
-        connect_timeout_seconds: 10,
-        channel_handshake_seconds: 4,
-        channel_heartbeat_seconds: 10,
-        outbound_retry_seconds: 1200,
-        external_addr: Some(ext_addr),
-        peers: Vec::new(),
-        seeds: vec![seed],
-        node_id: String::new(),
-    };
-
-    Ok(settings)
-}
-
-```
-
-This is a function that returns the settings to create Bob, an
-outbound node:
-
-```
-fn bob() -> Result<Settings> {
-    let log_level = simplelog::LevelFilter::Debug;
-    let log_config = simplelog::Config::default();
+There are four types of sessions: Manual, Inbound, Outbound and SeedSync.
 
 
-    let log_path = "/tmp/bob.log";
-    let file = File::create(log_path).unwrap();
-    WriteLogger::init(log_level, log_config, file)?;
-    let seed = Url::parse("tcp://127.0.0.1:55555").unwrap();
-    let oc = 5;
+There behavior is as follows: 
 
 
-    let settings = Settings {
-        inbound: None,
-        outbound_connections: oc,
-        manual_attempt_limit: 0,
-        seed_query_timeout_seconds: 8,
-        connect_timeout_seconds: 10,
-        channel_handshake_seconds: 4,
-        channel_heartbeat_seconds: 10,
-        outbound_retry_seconds: 1200,
-        external_addr: None,
-        peers: Vec::new(),
-        seeds: vec![seed],
-        node_id: String::new(),
-    };
+1. Inbound: Uses an Acceptor to accept connections on the inbound connect
+address configured in settings.
 
 
-    Ok(settings)
-}
-```
+2. Outbound: Starts a connect loop for every connect slot configured in
+settings. Establishes a connection using Connector.connect(): a method
+that takes an address returns a Channel.
 
 
-Both outbound and inbound nodes specify a seed address to connect to. The
-inbound node also specifies an external address and an inbound address:
-this is where it will receive connections. The outbound node specifies
-the number of outbound connection slots, which is the number of outbound
-connections the node will try to make.
+3. Manual: Uses a Connector to connect to a single address that is passed
+to ManualSession::connect(). Used to create an explicit connection to
+an address.
 
 
-These are the only settings we need to think about. For the rest, we
-use the network defaults.
+4. SeedSync: Creates a connection to the seed nodes specified in settings.
+Loops through all the configured seeds and tries to connect to them
+using a Connector. Either connects successfully, fails with an error or
+times out.
 
 
+To create an inbound and outbound node, we will need to configure them
+using a type called net::Settings.

+ 9 - 2
doc/src/learn/dchat/local-deployment/seed-node.md

@@ -49,8 +49,15 @@ It should output the following error:
 Error: NetworkOperationFailed
 Error: NetworkOperationFailed
 ```
 ```
 
 
-That's because there is no seed node online for our nodes to connect
-to. Let's remedy that.
+That's because there is no seed node online for our nodes to connect to. A
+seed node is used when connecting to the network: it is a special kind
+of inbound node that gets connected to, sends over a list of addresses
+and disconnects again.  This behavior is defined in the ProtocolSeed.
+
+Everytime we run `p2p.start()` we attempt to connect to a seed using a
+SeedSyncSession.  If the SeedSyncSession fails, p2p.start() will fail,
+so without a seed node, our inbound and outbound nodes cannot establish
+a connection to the network. Let's remedy that.
 
 
 We have two options here. First, we could implement our own seed node.
 We have two options here. First, we could implement our own seed node.
 Alternatively, DarkFi maintains a master seed node called lilith that
 Alternatively, DarkFi maintains a master seed node called lilith that

+ 101 - 0
doc/src/learn/dchat/local-deployment/settings.md

@@ -0,0 +1,101 @@
+# Settings
+
+On production-ready software, you would usually configure your node
+using a config file or command line inputs. On dchat we are keeping
+things ultra simple. We pass a command line flag that is either `a` or
+`b`. If we pass `a` we will initialize an inbound node. If we pass `b`
+we will initialize an outbound node.
+
+Here's how that works. We define two methods called alice() and
+bob(). alice() returns the Settings that will create an inbound
+node. bob() return the Settings for an outbound node.
+
+We also implement logging that outputs to /tmp/alice.log and /tmp/bob.log
+so we can access the debug output of our nodes. We store this info in a
+log file because we don't want it interfering with our terminal UI when
+we eventually build it.
+
+This is a function that returns the settings to create Alice, an
+inbound node:
+
+```
+use simplelog::WriteLogger;
+use std::fs::File;
+
+use darkfi::{net::Settings, Result};
+use url::Url;
+
+fn alice() -> Result<Settings> {
+    let log_level = simplelog::LevelFilter::Debug;
+    let log_config = simplelog::Config::default();
+
+    let log_path = "/tmp/alice.log";
+    let file = File::create(log_path).unwrap();
+    WriteLogger::init(log_level, log_config, file)?;
+
+    let seed = Url::parse("tcp://127.0.0.1:55555").unwrap();
+    let inbound = Url::parse("tcp://127.0.0.1:55554").unwrap();
+    let ext_addr = Url::parse("tcp://127.0.0.1:55554").unwrap();
+
+    let settings = Settings {
+        inbound: Some(inbound),
+        outbound_connections: 0,
+        manual_attempt_limit: 0,
+        seed_query_timeout_seconds: 8,
+        connect_timeout_seconds: 10,
+        channel_handshake_seconds: 4,
+        channel_heartbeat_seconds: 10,
+        outbound_retry_seconds: 1200,
+        external_addr: Some(ext_addr),
+        peers: Vec::new(),
+        seeds: vec![seed],
+        node_id: String::new(),
+    };
+
+    Ok(settings)
+}
+
+```
+
+This is a function that returns the settings to create Bob, an
+outbound node:
+
+```
+fn bob() -> Result<Settings> {
+    let log_level = simplelog::LevelFilter::Debug;
+    let log_config = simplelog::Config::default();
+
+    let log_path = "/tmp/bob.log";
+    let file = File::create(log_path).unwrap();
+    WriteLogger::init(log_level, log_config, file)?;
+    let seed = Url::parse("tcp://127.0.0.1:55555").unwrap();
+    let oc = 5;
+
+    let settings = Settings {
+        inbound: None,
+        outbound_connections: oc,
+        manual_attempt_limit: 0,
+        seed_query_timeout_seconds: 8,
+        connect_timeout_seconds: 10,
+        channel_handshake_seconds: 4,
+        channel_heartbeat_seconds: 10,
+        outbound_retry_seconds: 1200,
+        external_addr: None,
+        peers: Vec::new(),
+        seeds: vec![seed],
+        node_id: String::new(),
+    };
+
+    Ok(settings)
+}
+```
+
+Both outbound and inbound nodes specify a seed address to connect to. The
+inbound node also specifies an external address and an inbound address:
+this is where it will receive connections. The outbound node specifies
+the number of outbound connection slots, which is the number of outbound
+connections the node will try to make.
+
+These are the only settings we need to think about. For the rest, we
+use the network defaults.
+