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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
pub use super::Error;
use paste::paste;

use std::collections::HashMap;
pub type Response<T> = Result<T, Error>;
pub type Sender<T> = futures::channel::oneshot::Sender<Result<CommandResponse<T>, Error>>;
pub type RequestSender = futures::channel::mpsc::Sender<RequestMessage>;

#[derive(Debug)]
pub struct CommandExtraValue {
    pub value: String,
    pub reason: String,
}

#[derive(Debug)]
pub struct CommandTransactionID {
    pub client: String,
    pub server: String,
}

#[derive(Debug)]
pub struct CommandResponse<T> {
    pub response: T,
    pub extra_values: Vec<CommandExtraValue>,
    pub transaction_id: Option<CommandTransactionID>,
}

macro_rules! router {
    ($($n:ident, $req:ty, $res:ty);*) => {
        #[derive(Debug)]
        pub enum RequestMessage {
            $($n(Box<$req>),)*
        }

        #[allow(non_snake_case)]
        #[derive(Default, Debug)]
        pub struct Router<I: InnerRouter<T>, T> {
            _marker: std::marker::PhantomData<T>,
            pub inner: Box<I>,
            $($n: HashMap<uuid::Uuid, Sender<$res>>,)*
        }

        paste! {
            $(pub type [<$n Request>] = $req;)*
            $(pub type [<$n Response>] = $res;)*
        }

        paste! {
            #[allow(non_snake_case)]
            pub trait InnerRouter<T> {
                type Request;
                type Response;

                $(fn [<$n _request>](&mut self, client: &T, req: &$req, command_id: uuid::Uuid) -> Result<Self::Request, Response<$res>>;)*
                $(fn [<$n _response>](&mut self, return_path: Sender<$res>, response: Self::Response);)*
            }
        }

        impl<T, I: InnerRouter<T>> Router<I, T> {
            pub fn reject_request(req: RequestMessage) {
                match req {
                    $(RequestMessage::$n(req) => {let _ = req.return_path.send(Err(Error::NotReady));},)*
                };
            }

            pub fn drain(&mut self) {
                $(for r in self.$n.drain() {
                    let _ = r.1.send(Err(Error::NotReady));
                })*
            }

            pub fn handle_request(&mut self, client: &T, req: RequestMessage) ->
             Option<(I::Request, uuid::Uuid)> {
                match req {
                    $(RequestMessage::$n(req) => {
                        let command_id = uuid::Uuid::new_v4();
                        paste! {
                            let res = match I::[<$n _request>](&mut self.inner, client, &req, command_id.clone()) {
                                Ok(c) => c,
                                Err(e) => {
                                    let _ = req.return_path.send(match e {
                                        Ok(r) => Ok(CommandResponse {
                                            response: r,
                                            extra_values: vec![],
                                            transaction_id: None
                                        }),
                                        Err(e) => Err(e)
                                    });
                                    return None
                                }
                            };
                        }
                        self.$n.insert(command_id, req.return_path);
                        Some((res, command_id))
                    },)*
                }
            }

            pub fn handle_response(&mut self, transaction_id: &uuid::Uuid, response: I::Response) {
                $(if let Some(return_path) = self.$n.remove(transaction_id) {
                    paste! {
                        I::[<$n _response>](&mut self.inner, return_path, response);
                    }
                } else)* {}
            }
        }
    }
}

router!(
    Hello,                       super::BlankRequest,                               ();
    Logout,                      super::BlankRequest,                               ();
    Poll,                        super::poll::PollRequest,                          Option<super::poll::PollResponse>;
    PollAck,                     super::poll::PollAckRequest,                       super::poll::PollAckResponse;
    DomainCheck,                 super::domain::CheckRequest,                       super::domain::CheckResponse;
    DomainClaimsCheck,           super::domain::ClaimsCheckRequest,                 super::domain::ClaimsCheckResponse;
    DomainTrademarkCheck,        super::domain::TrademarkCheckRequest,              super::domain::ClaimsCheckResponse;
    DomainInfo,                  super::domain::InfoRequest,                        super::domain::InfoResponse;
    DomainCreate,                super::domain::CreateRequest,                      super::domain::CreateResponse;
    DomainDelete,                super::domain::DeleteRequest,                      super::domain::DeleteResponse;
    DomainUpdate,                super::domain::UpdateRequest,                      super::domain::UpdateResponse;
    DomainRenew,                 super::domain::RenewRequest,                       super::domain::RenewResponse;
    DomainTransferQuery,         super::domain::TransferQueryRequest,               super::domain::TransferResponse;
    DomainTransferRequest,       super::domain::TransferRequestRequest,             super::domain::TransferResponse;
    DomainTransferCancel,        super::domain::TransferAcceptRejectRequest,        super::domain::TransferResponse;
    DomainTransferAccept,        super::domain::TransferAcceptRejectRequest,        super::domain::TransferResponse;
    DomainTransferReject,        super::domain::TransferAcceptRejectRequest,        super::domain::TransferResponse;
    VerisignSync,                super::domain::VerisignSyncRequest,                super::domain::UpdateResponse;
    EmailForwardCheck,           super::email_forward::CheckRequest,                super::email_forward::CheckResponse;
    EmailForwardInfo,            super::email_forward::InfoRequest,                 super::email_forward::InfoResponse;
    EmailForwardCreate,          super::email_forward::CreateRequest,               super::email_forward::CreateResponse;
    EmailForwardDelete,          super::email_forward::DeleteRequest,               super::email_forward::DeleteResponse;
    EmailForwardUpdate,          super::email_forward::UpdateRequest,               super::email_forward::UpdateResponse;
    EmailForwardRenew,           super::email_forward::RenewRequest,                super::email_forward::RenewResponse;
    EmailForwardTransferQuery,   super::email_forward::TransferQueryRequest,        super::email_forward::TransferResponse;
    EmailForwardTransferRequest, super::email_forward::TransferRequestRequest,      super::email_forward::TransferResponse;
    EmailForwardTransferCancel,  super::email_forward::TransferAcceptRejectRequest, super::email_forward::TransferResponse;
    EmailForwardTransferAccept,  super::email_forward::TransferAcceptRejectRequest, super::email_forward::TransferResponse;
    EmailForwardTransferReject,  super::email_forward::TransferAcceptRejectRequest, super::email_forward::TransferResponse;
    RestoreRequest,              super::rgp::RestoreRequest,                        super::rgp::RestoreResponse;
    HostCheck,                   super::host::CheckRequest,                         super::host::CheckResponse;
    HostInfo,                    super::host::InfoRequest,                          super::host::InfoResponse;
    HostCreate,                  super::host::CreateRequest,                        super::host::CreateResponse;
    HostDelete,                  super::host::DeleteRequest,                        super::host::DeleteResponse;
    HostUpdate,                  super::host::UpdateRequest,                        super::host::UpdateResponse;
    ContactCheck,                super::contact::CheckRequest,                      super::contact::CheckResponse;
    ContactInfo,                 super::contact::InfoRequest,                       super::contact::InfoResponse;
    ContactCreate,               super::contact::CreateRequest,                     super::contact::CreateResponse;
    ContactDelete,               super::contact::DeleteRequest,                     super::contact::DeleteResponse;
    ContactUpdate,               super::contact::UpdateRequest,                     super::contact::UpdateResponse;
    ContactTransferQuery,        super::contact::TransferQueryRequest,              super::contact::TransferResponse;
    ContactTransferRequest,      super::contact::TransferRequestRequest,            super::contact::TransferResponse;
    ContactTransferAccept,       super::contact::TransferRequestRequest,            super::contact::TransferResponse;
    ContactTransferReject,       super::contact::TransferRequestRequest,            super::contact::TransferResponse;
    NominetTagList,              super::nominet::TagListRequest,                    super::nominet::TagListResponse;
    NominetAccept,               super::nominet::HandshakeAcceptRequest,            super::nominet::HandshakeResponse;
    NominetReject,               super::nominet::HandshakeRejectRequest,            super::nominet::HandshakeResponse;
    NominetRelease,              super::nominet::ReleaseRequest,                    super::nominet::ReleaseResponse;
    NominetContactValidate,      super::nominet::ContactValidateRequest,            super::nominet::ContactValidateResponse;
    NominetLock,                 super::nominet::LockRequest,                       super::nominet::LockResponse;
    NominetUnlock,               super::nominet::LockRequest,                       super::nominet::LockResponse;
    Balance,                     super::balance::BalanceRequest,                    super::balance::BalanceResponse;
    MaintenanceList,             super::maintenance::ListRequest,                   super::maintenance::ListResponse;
    MaintenanceInfo,             super::maintenance::InfoRequest,                   super::maintenance::InfoResponse;
    EURIDHitPoints,              super::eurid::HitPointsRequest,                    super::eurid::HitPointsResponse;
    EURIDRegistrationLimit,      super::eurid::RegistrationLimitRequest,            super::eurid::RegistrationLimitResponse;
    EURIDDNSSECEligibility,      super::eurid::DNSSECEligibilityRequest,            super::eurid::DNSSECEligibilityResponse;
    EURIDDNSQuality,             super::eurid::DNSQualityRequest,                   super::eurid::DNSQualityResponse;
    TMCHCheck,                   super::tmch::CheckRequest,                         super::tmch::CheckResponse;
    TMCHCreate,                  super::tmch::CreateRequest,                        super::tmch::CreateResponse;
    TMCHMarkInfo,                super::tmch::MarkInfoRequest,                      super::tmch::MarkInfoResponse;
    TMCHMarkSMDInfo,             super::tmch::MarkSMDInfoRequest,                   super::tmch::MarkSMDInfoResponse;
    TMCHMarkEncodedSMDInfo,      super::tmch::MarkSMDInfoRequest,                   super::tmch::MarkSMDInfoResponse;
    TMCHMarkFileInfo,            super::tmch::MarkSMDInfoRequest,                   super::tmch::MarkSMDInfoResponse;
    TMCHUpdate,                  super::tmch::UpdateRequest,                        super::tmch::UpdateResponse;
    TMCHRenew,                   super::tmch::RenewRequest,                         super::tmch::RenewResponse;
    TMCHTransferInitiate,        super::tmch::TransferInitiateRequest,              super::tmch::TransferInitiateResponse;
    TMCHTransfer,                super::tmch::TransferRequest,                      super::tmch::TransferResponse;
    TMCHTrexActivate,            super::tmch::TrexActivateRequest,                  super::tmch::TrexActivateResponse;
    TMCHTrexRenew,               super::tmch::TrexRenewRequest,                     super::tmch::TrexRenewResponse;
    DACDomain,                   super::dac::DACDomainRequest,                      super::dac::DACDomainResponse;
    DACUsage,                    super::dac::DACUsageRequest,                       super::dac::DACUsageResponse;
    DACLimits,                   super::dac::DACUsageRequest,                       super::dac::DACUsageResponse
);