pub trait MibHandler:
Send
+ Sync
+ 'static {
// Required methods
fn get<'a>(
&'a self,
ctx: &'a RequestContext,
oid: &'a Oid,
) -> BoxFuture<'a, GetResult>;
fn get_next<'a>(
&'a self,
ctx: &'a RequestContext,
oid: &'a Oid,
) -> BoxFuture<'a, GetNextResult>;
// Provided methods
fn test_set<'a>(
&'a self,
_ctx: &'a RequestContext,
_oid: &'a Oid,
_value: &'a Value,
) -> BoxFuture<'a, SetResult> { ... }
fn commit_set<'a>(
&'a self,
_ctx: &'a RequestContext,
_oid: &'a Oid,
_value: &'a Value,
) -> BoxFuture<'a, SetResult> { ... }
fn undo_set<'a>(
&'a self,
_ctx: &'a RequestContext,
_oid: &'a Oid,
_value: &'a Value,
) -> BoxFuture<'a, ()> { ... }
fn handles(&self, registered_prefix: &Oid, oid: &Oid) -> bool { ... }
}Expand description
Handler for SNMP MIB operations.
Implement this trait to provide values for a subtree of OIDs.
Register handlers with AgentBuilder::handler()
using a prefix OID.
§SET Operations
SET operations use a two-phase commit protocol for RFC 3416 atomicity:
-
Test phase:
test_setis called for ALL varbinds before any commits. If any test fails, no changes are made. -
Commit phase:
commit_setis called for each varbind in order. If a commit fails,undo_setis called for all previously committed varbinds (in reverse order).
§Bounds
The 'static bound is required because handlers are stored as
Arc<dyn MibHandler> within the agent. This allows the agent to
hold handlers for its entire lifetime without lifetime annotations.
In practice, most handlers naturally satisfy this bound.
§Thread Safety
Handlers must be Send + Sync because the agent may process
requests concurrently from multiple tasks.
§Example
use async_snmp::handler::{MibHandler, RequestContext, GetResult, GetNextResult, BoxFuture};
use async_snmp::{Oid, Value, VarBind, oid};
struct MyHandler;
impl MibHandler for MyHandler {
fn get<'a>(&'a self, ctx: &'a RequestContext, oid: &'a Oid) -> BoxFuture<'a, GetResult> {
Box::pin(async move {
if oid == &oid!(1, 3, 6, 1, 4, 1, 99999, 1, 0) {
return GetResult::Value(Value::Integer(42));
}
GetResult::NoSuchObject
})
}
fn get_next<'a>(&'a self, ctx: &'a RequestContext, oid: &'a Oid) -> BoxFuture<'a, GetNextResult> {
Box::pin(async move {
let my_oid = oid!(1, 3, 6, 1, 4, 1, 99999, 1, 0);
if oid < &my_oid {
return GetNextResult::Value(VarBind::new(my_oid, Value::Integer(42)));
}
GetNextResult::EndOfMibView
})
}
}Required Methods§
Sourcefn get<'a>(
&'a self,
ctx: &'a RequestContext,
oid: &'a Oid,
) -> BoxFuture<'a, GetResult>
fn get<'a>( &'a self, ctx: &'a RequestContext, oid: &'a Oid, ) -> BoxFuture<'a, GetResult>
Handle a GET request for a specific OID.
Return GetResult::Value if the OID exists, GetResult::NoSuchObject
if the object type is not implemented, or GetResult::NoSuchInstance
if the object type exists but this specific instance doesn’t.
See GetResult documentation for details on when to use each variant.
Sourcefn get_next<'a>(
&'a self,
ctx: &'a RequestContext,
oid: &'a Oid,
) -> BoxFuture<'a, GetNextResult>
fn get_next<'a>( &'a self, ctx: &'a RequestContext, oid: &'a Oid, ) -> BoxFuture<'a, GetNextResult>
Handle a GETNEXT request.
Return GetNextResult::Value with the lexicographically next OID and value
after oid, or GetNextResult::EndOfMibView if there are no more OIDs
in this handler’s subtree.
Provided Methods§
Sourcefn test_set<'a>(
&'a self,
_ctx: &'a RequestContext,
_oid: &'a Oid,
_value: &'a Value,
) -> BoxFuture<'a, SetResult>
fn test_set<'a>( &'a self, _ctx: &'a RequestContext, _oid: &'a Oid, _value: &'a Value, ) -> BoxFuture<'a, SetResult>
Test if a SET operation would succeed (phase 1 of two-phase commit).
Called for ALL varbinds before any commits. Must NOT modify state.
Return SetResult::Ok if the SET would succeed, or an appropriate
error otherwise.
Default implementation returns NotWritable (read-only handler).
Sourcefn commit_set<'a>(
&'a self,
_ctx: &'a RequestContext,
_oid: &'a Oid,
_value: &'a Value,
) -> BoxFuture<'a, SetResult>
fn commit_set<'a>( &'a self, _ctx: &'a RequestContext, _oid: &'a Oid, _value: &'a Value, ) -> BoxFuture<'a, SetResult>
Commit a SET operation (phase 2 of two-phase commit).
Only called after ALL test_set calls succeed. Should apply the change.
If this fails, undo_set will be called for all previously committed
varbinds in this request.
Default implementation returns NotWritable (read-only handler).
Sourcefn undo_set<'a>(
&'a self,
_ctx: &'a RequestContext,
_oid: &'a Oid,
_value: &'a Value,
) -> BoxFuture<'a, ()>
fn undo_set<'a>( &'a self, _ctx: &'a RequestContext, _oid: &'a Oid, _value: &'a Value, ) -> BoxFuture<'a, ()>
Undo a committed SET operation (rollback on partial failure).
Called if a later commit_set fails. Should restore the previous value.
This is best-effort: if undo fails, log a warning but continue.
Default implementation does nothing (no rollback support).