1 module snmp.pdu;
2 
3 import c.net_snmp;
4 import snmp.types;
5 import snmp.oid;
6 
7 private alias size_t = object.size_t;
8 import snmp.varbind;
9 
10 /// Owns the response PDU from a synchronous SNMP request.
11 struct SNMPResponse
12 {
13     netsnmp_pdu* handle;
14     int          status;
15 
16     @disable this(this);
17 
18     bool ok() const @trusted @nogc nothrow
19     {
20         return status == STAT_SUCCESS
21             && handle !is null
22             && handle.errstat == SNMP_ERR_NOERROR;
23     }
24 
25     SNMPError errStatus() const @trusted @nogc nothrow
26     {
27         return handle
28             ? cast(SNMPError) handle.errstat
29             : SNMPError.genErr;
30     }
31 
32     VarBind variables() const @trusted @nogc nothrow
33     {
34         return VarBind(handle ? cast(netsnmp_variable_list*) handle.variables : null);
35     }
36 
37     size_t length() const @trusted @nogc nothrow
38     {
39         size_t n;
40         for (auto v = cast(netsnmp_variable_list*) (handle ? handle.variables : null);
41              v; v = v.next_variable)
42             ++n;
43         return n;
44     }
45 
46     int opApply(scope int delegate(VarBind) dg) @trusted
47     {
48         for (auto v = variables; v.isValid; v = v.next)
49             if (auto r = dg(v))
50                 return r;
51         return 0;
52     }
53 
54     ~this() @trusted @nogc nothrow { free_(); }
55 
56     void free_() @trusted @nogc nothrow
57     {
58         if (handle)
59         {
60             snmp_free_pdu(handle);
61             handle = null;
62         }
63     }
64 }
65 
66 unittest
67 {
68     auto r = SNMPResponse(null, STAT_ERROR);
69     assert(!r.ok);
70     assert(!r.variables.isValid);
71     assert(r.length == 0);
72     r.free_();
73 
74     auto t = SNMPResponse(null, STAT_TIMEOUT);
75     assert(!t.ok);
76 
77     assert(r.errStatus == SNMPError.genErr);
78 
79     int count;
80     foreach (v; r)
81         ++count;
82     assert(count == 0);
83 }