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
// Copyright (c) 2021 Open Community Project Association https://ocpa.ch
// This software is published under the AGPLv3 license.

//! Qaul Community Router
//!
//! This module implements all the tables and logic of the
//! qaul router.

use prost::Message;
use state::Storage;
use std::sync::RwLock;

pub mod connections;
pub mod feed_requester;
pub mod flooder;
pub mod info;
pub mod neighbours;
pub mod table;
pub mod user_requester;
pub mod users;

use crate::storage::configuration::{Configuration, RoutingOptions};
use connections::ConnectionTable;
use feed_requester::{FeedRequester, FeedResponser};
use flooder::Flooder;
use info::RouterInfo;
use neighbours::Neighbours;
use table::RoutingTable;
use user_requester::{UserRequester, UserResponser};
use users::Users;

/// Import protobuf message definition generated by
/// the rust module prost-build.
pub mod proto {
    include!("qaul.rpc.router.rs");
}
pub mod router_net_proto {
    include!("qaul.net.router_net_info.rs");
}

/// mutable state of router,
/// used for storing the router configuration
static ROUTER: Storage<RwLock<Router>> = Storage::new();

/// qaul community router access
#[derive(Clone)]
pub struct Router {
    pub configuration: RoutingOptions,
}

impl Router {
    /// Initialize the qaul router
    pub fn init() {
        let config = Configuration::get();
        let router = Router {
            configuration: config.routing.clone(),
        };
        // set configuration to state
        ROUTER.set(RwLock::new(router));

        // initialize direct neighbours table
        Neighbours::init();

        // initialize users table
        Users::init();

        // initialize flooder queue
        Flooder::init();

        // initialize feed_requester queue
        FeedRequester::init();

        // initialize feed_response queue
        FeedResponser::init();

        // initialize user_requester queue
        UserRequester::init();

        // initialize user_response queue
        UserResponser::init();

        // initialize the global routing table
        RoutingTable::init();

        // initialize the routing information collection
        // tables per connection module
        ConnectionTable::init();

        // initialize RouterInfo submodule that
        // schedules the sending of the routing information
        // to the neighbouring nodes.
        RouterInfo::init(config.routing.sending_table_period);
    }

    /// Get router configuration from state
    pub fn get_configuration() -> RoutingOptions {
        let router = ROUTER.get().read().unwrap();
        router.configuration.clone()
    }

    /// Process incoming RPC request messages and send them to
    /// the submodules
    pub fn rpc(data: Vec<u8>) {
        match proto::Router::decode(&data[..]) {
            Ok(router) => {
                match router.message {
                    Some(proto::router::Message::RoutingTableRequest(_request)) => {
                        // send routing table list
                        RoutingTable::rpc_send_routing_table();
                    }
                    Some(proto::router::Message::ConnectionsRequest(_request)) => {
                        // send connections list
                        ConnectionTable::rpc_send_connections_list();
                    }
                    Some(proto::router::Message::NeighboursRequest(_request)) => {
                        // send neighbours list
                        Neighbours::rpc_send_neighbours_list();
                    }
                    _ => {}
                }
            }
            Err(error) => {
                log::error!("{:?}", error);
            }
        }
    }
}