@@ -7,7 +7,7 @@ use tokio::net::UnixStream;
7
7
8
8
use crate :: {
9
9
Error , Interface , InterfaceAddress , InterfaceProperties , InterfaceSummary , Message , Protocol ,
10
- Result , ShowInterfacesMessage ,
10
+ ProtocolDetail , Result , ShowInterfacesMessage , ShowProtocolDetailsMessage ,
11
11
} ;
12
12
13
13
/// An active connection, on which requests can be executed, and responses
@@ -195,7 +195,7 @@ impl Connection {
195
195
}
196
196
197
197
/// Sends a `show protocols [<pattern>]` request and returns the parsed response as a
198
- /// list of [InterfaceSummary] entries, one each for an interface .
198
+ /// list of [InterfaceSummary] entries, one for each protocol .
199
199
///
200
200
/// If `pattern` is specified, results of only those protocols is returned, which
201
201
/// match the pattern.
@@ -223,6 +223,74 @@ impl Connection {
223
223
Err ( Error :: ParseError ( messages) )
224
224
}
225
225
226
+ /// Sends a `show protocols all [<pattern>]` request and returns the parsed response as a
227
+ /// list of [ShowProtocolDetailsMessage] entries, one for each protocol instance.
228
+ ///
229
+ /// If `pattern` is specified, results of only those protocols is returned, which
230
+ /// match the pattern.
231
+ pub async fn show_protocols_details (
232
+ & mut self ,
233
+ pattern : Option < & str > ,
234
+ ) -> Result < Vec < ShowProtocolDetailsMessage > > {
235
+ let cmd = if let Some ( pattern) = pattern {
236
+ format ! ( "show protocols all \" {}\" " , pattern)
237
+ } else {
238
+ "show protocols all" . into ( )
239
+ } ;
240
+ let mut result = vec ! [ ] ;
241
+ let messages = self . send_request ( & cmd) . await ?;
242
+
243
+ // we expect messages to show up as a series of doublets: 1002 and 1006
244
+ if let Some ( mut idx) = messages
245
+ . iter ( )
246
+ . position ( |x| matches ! ( x, Message :: ProtocolList ( _) ) )
247
+ {
248
+ while idx < messages. len ( ) {
249
+ // each iteration here means fully going through the pair of 1002 and 1006
250
+
251
+ if let Some ( protocol) = Protocol :: from_enum ( & messages[ idx] ) {
252
+ // move index to the next message
253
+ idx += 1 ;
254
+ // if we have a valid 1002 ...
255
+ if let Some ( protocol) = protocol. first ( ) {
256
+ // ... check for 1006
257
+ if idx == messages. len ( )
258
+ || !matches ! ( messages[ idx] , Message :: ProtocolDetails ( _) )
259
+ {
260
+ // if we're already at the end, or if there's no 1006 after the 1002 we saw
261
+ // just a step before, we push the current 1002 without any 1006, and continue
262
+ result. push ( ShowProtocolDetailsMessage {
263
+ protocol : protocol. clone ( ) ,
264
+ detail : None ,
265
+ } ) ;
266
+ continue ;
267
+ }
268
+ // looks like we have a valid 1006, so let's process it
269
+ if let Some ( detail) = ProtocolDetail :: from_enum ( & messages[ idx] ) {
270
+ // looks like we got a valid 1006
271
+ idx += 1 ;
272
+ result. push ( ShowProtocolDetailsMessage {
273
+ protocol : protocol. clone ( ) ,
274
+ detail : Some ( detail) ,
275
+ } ) ;
276
+ } else {
277
+ log:: error!( "conn: failed to parse 1006 message" ) ;
278
+ return Err ( Error :: ParseError ( messages) ) ;
279
+ }
280
+ }
281
+ } else {
282
+ log:: error!( "conn: failed to parse 1002 message: {:?}" , messages[ idx] ) ;
283
+ return Err ( Error :: ParseError ( messages) ) ;
284
+ }
285
+ }
286
+
287
+ Ok ( result)
288
+ } else {
289
+ // No 1002 entries, so empty result
290
+ Ok ( Vec :: new ( ) )
291
+ }
292
+ }
293
+
226
294
/// Reads a full [Message] from the server, and returns it
227
295
async fn next_message ( & mut self ) -> Result < Message > {
228
296
// if we have pending messages, return the first one
0 commit comments