1
//! Define a response type for directory requests.
2

            
3
use tor_proto::circuit::UniqId;
4

            
5
use crate::Error;
6

            
7
/// A successful (or at any rate, well-formed) response to a directory
8
/// request.
9
#[derive(Debug)]
10
pub struct DirResponse {
11
    /// An HTTP status code.
12
    status: u16,
13
    /// The decompressed output that we got from the directory cache.
14
    output: Vec<u8>,
15
    /// The error, if any, that caused us to stop getting this response early.
16
    error: Option<Error>,
17
    /// Information about the directory cache we used.
18
    source: Option<SourceInfo>,
19
}
20

            
21
/// Information about the source of a directory response.
22
///
23
/// We use this to remember when a request has failed, so we can
24
/// abandon the circuit.
25
///
26
/// (In the future, we will probably want to use this structure to
27
/// remember that the cache isn't working.)
28
#[derive(Debug, Clone)]
29
pub struct SourceInfo {
30
    /// Unique identifier for the circuit we're using
31
    circuit: UniqId,
32
}
33

            
34
impl DirResponse {
35
    /// Construct a new DirResponse from its parts
36
14
    pub(crate) fn new(
37
14
        status: u16,
38
14
        error: Option<Error>,
39
14
        output: Vec<u8>,
40
14
        source: Option<SourceInfo>,
41
14
    ) -> Self {
42
14
        DirResponse {
43
14
            status,
44
14
            output,
45
14
            error,
46
14
            source,
47
14
        }
48
14
    }
49

            
50
    /// Construct a new successful DirResponse from its body.
51
1
    pub fn from_body(body: impl AsRef<[u8]>) -> Self {
52
1
        Self::new(200, None, body.as_ref().to_vec(), None)
53
1
    }
54

            
55
    /// Return the HTTP status code for this response.
56
14
    pub fn status_code(&self) -> u16 {
57
14
        self.status
58
14
    }
59

            
60
    /// Return true if this is in incomplete response.
61
2
    pub fn is_partial(&self) -> bool {
62
2
        self.error.is_some()
63
2
    }
64

            
65
    /// Return the error from this response, if any.
66
3
    pub fn error(&self) -> Option<&Error> {
67
3
        self.error.as_ref()
68
3
    }
69

            
70
    /// Return the output from this response.
71
3
    pub fn output(&self) -> &[u8] {
72
3
        &self.output
73
3
    }
74

            
75
    /// Consume this DirResponse and return the output in it.
76
12
    pub fn into_output(self) -> Vec<u8> {
77
12
        self.output
78
12
    }
79

            
80
    /// Return the source information about this response.
81
1
    pub fn source(&self) -> Option<&SourceInfo> {
82
1
        self.source.as_ref()
83
1
    }
84
}
85

            
86
impl SourceInfo {
87
    /// Construct a new SourceInfo
88
    pub(crate) fn new(circuit: UniqId) -> Self {
89
        SourceInfo { circuit }
90
    }
91
    /// Return the unique circuit identifier for the circuit on which
92
    /// we received this info.
93
    pub fn unique_circ_id(&self) -> &UniqId {
94
        &self.circuit
95
    }
96
}