2
2
// License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
5
- use crate :: db:: { Db , PeerInfo , TunnelRoute } ;
5
+ use crate :: db:: { Db , PeerInfo , PeerStatus , RouterKind , TunnelRoute } ;
6
6
use crate :: exchange:: PathVector ;
7
7
use crate :: sm:: { AdminEvent , Event , PrefixSet , SmContext } ;
8
8
use dropshot:: endpoint;
@@ -27,6 +27,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
27
27
use std:: sync:: mpsc:: Sender ;
28
28
use std:: sync:: Arc ;
29
29
use std:: sync:: Mutex ;
30
+ use std:: time:: { Duration , Instant } ;
30
31
use tokio:: spawn;
31
32
use tokio:: task:: JoinHandle ;
32
33
use uuid:: Uuid ;
@@ -103,12 +104,71 @@ pub fn handler(
103
104
Ok ( ( ) )
104
105
}
105
106
107
+ /// Status of a DDM peer with state expressed as durations.
108
+ #[ derive(
109
+ Debug , Copy , Clone , PartialEq , Eq , Deserialize , Serialize , JsonSchema ,
110
+ ) ]
111
+ #[ serde( tag = "type" , content = "value" ) ]
112
+ pub enum ApiPeerStatus {
113
+ NoContact ,
114
+ Init ( Duration ) ,
115
+ Solicit ( Duration ) ,
116
+ Exchange ( Duration ) ,
117
+ Expired ( Duration ) ,
118
+ }
119
+
120
+ // Translate internal peer status which is based on instants, to API
121
+ // representation which is based on durations.
122
+ impl From < PeerStatus > for ApiPeerStatus {
123
+ fn from ( value : PeerStatus ) -> Self {
124
+ match value {
125
+ PeerStatus :: NoContact => Self :: NoContact ,
126
+ PeerStatus :: Init ( t) => Self :: Init ( Instant :: now ( ) . duration_since ( t) ) ,
127
+ PeerStatus :: Solicit ( t) => {
128
+ Self :: Solicit ( Instant :: now ( ) . duration_since ( t) )
129
+ }
130
+ PeerStatus :: Exchange ( t) => {
131
+ Self :: Exchange ( Instant :: now ( ) . duration_since ( t) )
132
+ }
133
+ PeerStatus :: Expired ( t) => {
134
+ Self :: Expired ( Instant :: now ( ) . duration_since ( t) )
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ /// Information about a DDM peer.
141
+ #[ derive( Debug , Clone , PartialEq , Eq , Deserialize , Serialize , JsonSchema ) ]
142
+ pub struct ApiPeerInfo {
143
+ pub status : ApiPeerStatus ,
144
+ pub addr : Ipv6Addr ,
145
+ pub host : String ,
146
+ pub kind : RouterKind ,
147
+ }
148
+
149
+ impl From < PeerInfo > for ApiPeerInfo {
150
+ fn from ( value : PeerInfo ) -> Self {
151
+ Self {
152
+ status : value. status . into ( ) ,
153
+ addr : value. addr ,
154
+ host : value. host ,
155
+ kind : value. kind ,
156
+ }
157
+ }
158
+ }
159
+
106
160
#[ endpoint { method = GET , path = "/peers" } ]
107
161
async fn get_peers (
108
162
ctx : RequestContext < Arc < Mutex < HandlerContext > > > ,
109
- ) -> Result < HttpResponseOk < HashMap < u32 , PeerInfo > > , HttpError > {
163
+ ) -> Result < HttpResponseOk < HashMap < u32 , ApiPeerInfo > > , HttpError > {
110
164
let ctx = ctx. context ( ) . lock ( ) . unwrap ( ) ;
111
- Ok ( HttpResponseOk ( ctx. db . peers ( ) ) )
165
+ let peers = ctx
166
+ . db
167
+ . peers ( )
168
+ . into_iter ( )
169
+ . map ( |( k, v) | ( k, v. into ( ) ) )
170
+ . collect ( ) ;
171
+ Ok ( HttpResponseOk ( peers) )
112
172
}
113
173
114
174
#[ derive( Debug , Clone , Deserialize , Serialize , JsonSchema ) ]
0 commit comments