net-snmp2 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +18 -1
- data/examples/agent.rb +1 -0
- data/examples/inform.rb +23 -0
- data/examples/trap_handler.rb +15 -0
- data/examples/{v1_trap_session.rb → v1_trap.rb} +2 -7
- data/examples/{v2_trap_session.rb → v2_trap.rb} +2 -7
- data/history.md +17 -0
- data/lib/net-snmp2.rb +1 -1
- data/lib/net/snmp/agent/agent.rb +44 -13
- data/lib/net/snmp/agent/provider.rb +56 -1
- data/lib/net/snmp/agent/provider_dsl.rb +11 -0
- data/lib/net/snmp/debug.rb +10 -19
- data/lib/net/snmp/error.rb +13 -6
- data/lib/net/snmp/listener.rb +2 -4
- data/lib/net/snmp/message.rb +52 -25
- data/lib/net/snmp/mib/mib.rb +2 -1
- data/lib/net/snmp/mib/node.rb +1 -1
- data/lib/net/snmp/oid.rb +5 -2
- data/lib/net/snmp/pdu.rb +15 -10
- data/lib/net/snmp/repl/manager_repl.rb +20 -7
- data/lib/net/snmp/session.rb +78 -45
- data/lib/net/snmp/trap_handler/trap_handler.rb +13 -9
- data/lib/net/snmp/trap_handler/v2_inform_dsl.rb +16 -0
- data/lib/net/snmp/trap_session.rb +64 -42
- data/lib/net/snmp/version.rb +1 -1
- data/lib/net/snmp/wrapper.rb +2 -8
- data/net-snmp2.gemspec +1 -1
- data/spec/README.md +36 -40
- data/spec/async_spec.rb +92 -87
- data/spec/em_spec.rb +3 -3
- data/spec/error_spec.rb +2 -2
- data/spec/fiber_spec.rb +8 -7
- data/spec/mib_spec.rb +8 -8
- data/spec/net-snmp_spec.rb +3 -3
- data/spec/oid_spec.rb +5 -5
- data/spec/spec_helper.rb +5 -0
- data/spec/sync_spec.rb +50 -56
- data/spec/test_agent.rb +150 -0
- data/spec/test_mib.rb +6 -0
- data/spec/thread_spec.rb +4 -4
- data/spec/trap_spec.rb +3 -12
- data/spec/utility_spec.rb +4 -4
- data/spec/wrapper_spec.rb +6 -6
- metadata +11 -6
- data/lib/net/snmp/agent/request_dispatcher.rb +0 -38
data/lib/net/snmp/message.rb
CHANGED
@@ -7,18 +7,13 @@ class Message
|
|
7
7
|
Message.new(packet)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
response_pdu.community = message.pdu.community
|
18
|
-
response_pdu
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_accessor :version, :community, :pdu, :version_ptr, :community_ptr
|
10
|
+
attr_accessor :version,
|
11
|
+
:community,
|
12
|
+
:pdu,
|
13
|
+
:version_ptr,
|
14
|
+
:community_ptr,
|
15
|
+
:source_address,
|
16
|
+
:source_port
|
22
17
|
|
23
18
|
def version_name
|
24
19
|
case @version
|
@@ -33,14 +28,6 @@ class Message
|
|
33
28
|
end
|
34
29
|
end
|
35
30
|
|
36
|
-
private
|
37
|
-
|
38
|
-
attr_accessor :type,
|
39
|
-
:length,
|
40
|
-
:data,
|
41
|
-
:cursor,
|
42
|
-
:bytes_remaining
|
43
|
-
|
44
31
|
def initialize(packet)
|
45
32
|
@version = nil
|
46
33
|
@version_ptr = FFI::MemoryPointer.new(:long, 1)
|
@@ -53,10 +40,50 @@ class Message
|
|
53
40
|
@cursor_ptr = @data_ptr
|
54
41
|
@bytes_remaining_ptr = FFI::MemoryPointer.new(:int, 1)
|
55
42
|
@bytes_remaining_ptr.write_bytes([@packet_length].pack("L"))
|
56
|
-
|
43
|
+
@source_address = @packet[1][3]
|
44
|
+
@source_port = @packet[1][1]
|
45
|
+
#debug "MESSAGE INITIALIZED\n#{self}"
|
57
46
|
parse
|
58
47
|
end
|
59
48
|
|
49
|
+
# Sends the given PDU back to the origin of this message.
|
50
|
+
# The origin is the same address and port that the message was
|
51
|
+
# received from.
|
52
|
+
def respond(response_pdu)
|
53
|
+
Session.open(peername: source_address, port: source_port, version: version_name) do |sess|
|
54
|
+
sess.send_pdu(response_pdu)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sends a response PDU to the source of the message with all of the same
|
59
|
+
# varbinds. (Useful for sets & informs, where this is how you indicate success)
|
60
|
+
def echo
|
61
|
+
response_pdu = make_response_pdu
|
62
|
+
pdu.varbinds.each do |vb|
|
63
|
+
response_pdu.add_varbind(oid: vb.oid, type: vb.type, value: vb.value)
|
64
|
+
end
|
65
|
+
respond(response_pdu)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Constructs a PDU for responding to this message.
|
69
|
+
# This makes sure the PDU has the right request ID, version,
|
70
|
+
# and community set.
|
71
|
+
def make_response_pdu
|
72
|
+
response_pdu = PDU.new(Constants::SNMP_MSG_RESPONSE)
|
73
|
+
response_pdu.reqid = pdu.reqid
|
74
|
+
response_pdu.version = version
|
75
|
+
response_pdu.community = pdu.community
|
76
|
+
response_pdu
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
attr_accessor :type,
|
82
|
+
:length,
|
83
|
+
:data,
|
84
|
+
:cursor,
|
85
|
+
:bytes_remaining
|
86
|
+
|
60
87
|
def parse
|
61
88
|
parse_length
|
62
89
|
parse_version
|
@@ -70,7 +97,7 @@ class Message
|
|
70
97
|
unless @type_ptr.read_int == 48
|
71
98
|
raise "Invalid SNMP packet. Message should start with a sequence declaration"
|
72
99
|
end
|
73
|
-
debug "MESSAGE SEQUENCE HEADER PARSED\n#{self}"
|
100
|
+
#debug "MESSAGE SEQUENCE HEADER PARSED\n#{self}"
|
74
101
|
end
|
75
102
|
|
76
103
|
def parse_version
|
@@ -82,7 +109,7 @@ class Message
|
|
82
109
|
@version_ptr.total)
|
83
110
|
|
84
111
|
@version = @version_ptr.read_long
|
85
|
-
debug "VERSION NUMBER PARSED\n#{self}"
|
112
|
+
#debug "VERSION NUMBER PARSED\n#{self}"
|
86
113
|
end
|
87
114
|
|
88
115
|
def parse_community
|
@@ -96,7 +123,7 @@ class Message
|
|
96
123
|
community_length_ptr)
|
97
124
|
|
98
125
|
@community = @community_ptr.read_string
|
99
|
-
debug "COMMUNITY PARSED\n#{self}"
|
126
|
+
#debug "COMMUNITY PARSED\n#{self}"
|
100
127
|
end
|
101
128
|
|
102
129
|
def parse_pdu
|
@@ -118,7 +145,7 @@ class Message
|
|
118
145
|
|
119
146
|
Net::SNMP::Wrapper.snmp_pdu_parse(pdu_struct_ptr, @cursor_ptr, @bytes_remaining_ptr)
|
120
147
|
@pdu = Net::SNMP::PDU.new(pdu_struct_ptr.pointer)
|
121
|
-
debug "PDU PARSED\n#{self}"
|
148
|
+
#debug "PDU PARSED\n#{self}"
|
122
149
|
end
|
123
150
|
|
124
151
|
def to_s
|
data/lib/net/snmp/mib/mib.rb
CHANGED
@@ -35,7 +35,8 @@ module Net
|
|
35
35
|
"#{node.label}#{oid.sub(node.oid.to_s, "")}"
|
36
36
|
else
|
37
37
|
# Node OID + instance indexes from argument
|
38
|
-
|
38
|
+
# (Regex ensures the module qualifier is also removed, if present)
|
39
|
+
"#{node.oid.to_s}#{oid.sub(%r[.*#{node.label.to_s}], "")}"
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
data/lib/net/snmp/mib/node.rb
CHANGED
data/lib/net/snmp/oid.rb
CHANGED
@@ -26,7 +26,9 @@ module Net
|
|
26
26
|
length_ptr.write_int(oid_ptr.total)
|
27
27
|
|
28
28
|
Wrapper.read_objid('1.1', oid_ptr, length_ptr)
|
29
|
-
oid_str = oid_ptr.read_array_of_uint8(oid_ptr.total).map{|byte|
|
29
|
+
oid_str = oid_ptr.read_array_of_uint8(oid_ptr.total).map { |byte|
|
30
|
+
byte.to_s(2).rjust(8, '0')
|
31
|
+
}.join('')
|
30
32
|
|
31
33
|
@oid_size = (oid_str[/10*1/].length - 1) / 8
|
32
34
|
else
|
@@ -50,7 +52,8 @@ module Net
|
|
50
52
|
unless @sub_id_bit_width
|
51
53
|
@sub_id_bit_width = OID.oid_size * 8
|
52
54
|
end
|
53
|
-
|
55
|
+
subids = self.to_s.split('.').map{ |subid| subid.to_i }
|
56
|
+
buffer.send("write_array_of_uint#{@sub_id_bit_width}", subids)
|
54
57
|
end
|
55
58
|
|
56
59
|
def initialize(oid)
|
data/lib/net/snmp/pdu.rb
CHANGED
@@ -57,7 +57,9 @@ module Net
|
|
57
57
|
def enterprise=(oid)
|
58
58
|
@i_own_enterprise = true
|
59
59
|
oid = OID.new(oid) if oid.kind_of?(String)
|
60
|
-
|
60
|
+
# save own reference to enterprise in case we need to free it
|
61
|
+
@enterprise_ptr = FFI::LibC.calloc(oid.length, OID.oid_size)
|
62
|
+
@struct.enterprise = @enterprise_ptr
|
61
63
|
oid.write_to_buffer(@struct.enterprise)
|
62
64
|
@struct.enterprise_length = oid.length
|
63
65
|
end
|
@@ -201,22 +203,25 @@ module Net
|
|
201
203
|
end
|
202
204
|
|
203
205
|
# Free the pdu
|
204
|
-
# Segfaults at the moment - most of the time, anyway.
|
205
|
-
# This is troublesome...
|
206
206
|
def free
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
207
|
+
free_own_memory
|
208
|
+
Wrapper.snmp_free_pdu(@struct.pointer) unless @struct.pointer.null?
|
209
|
+
end
|
210
|
+
|
211
|
+
# malloc'ing memory on one side of the FFI barrier and freeing it
|
212
|
+
# on the other side is unreliable (causing intermittent segfaults).
|
213
|
+
# So, this function free's any memory allocated on the ruby side
|
214
|
+
# for this PDU.
|
215
|
+
def free_own_memory
|
211
216
|
if @i_own_enterprise
|
212
|
-
FFI::LibC.free(@
|
217
|
+
FFI::LibC.free(@enterprise_ptr) unless @enterprise_ptr.null?
|
213
218
|
@struct.enterprise = FFI::Pointer::NULL
|
214
219
|
end
|
215
|
-
Wrapper.snmp_free_pdu(@struct.pointer)
|
216
220
|
end
|
217
221
|
|
218
222
|
def print
|
219
|
-
puts "PDU"
|
223
|
+
puts "== PDU =="
|
224
|
+
puts "Command: #{command}"
|
220
225
|
if command == Constants::SNMP_MSG_TRAP
|
221
226
|
puts " - Enterprise: #{enterprise}"
|
222
227
|
puts " - Trap Type: #{trap_type}"
|
@@ -28,11 +28,13 @@ EOF
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# Adds a session for managing options[:peername] to the sessions list.
|
31
|
+
#
|
31
32
|
# - Note that all requests are sent to all active sessions, and their
|
32
33
|
# responses are all displayed under their peername.
|
33
34
|
# - You may close a session by calling `close(peername)`
|
34
35
|
#
|
35
36
|
# Arguments
|
37
|
+
#
|
36
38
|
# - options: A Hash or String object
|
37
39
|
# + As a Hash, accepts the following keys
|
38
40
|
# - peername: ADDRESS_OF_AGENT
|
@@ -40,11 +42,12 @@ EOF
|
|
40
42
|
# - version: '1'|'2c'|'3' (defaults to '2c')
|
41
43
|
# + As a string, implies the peername, with the version defaulting to '2c'
|
42
44
|
#
|
43
|
-
# Examples
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
45
|
+
# Examples
|
46
|
+
#
|
47
|
+
# manage('192.168.1.5')
|
48
|
+
# manage('192.168.1.5:162')
|
49
|
+
# manage(peername: '192.168.1.5', port: 161, version '2c')
|
50
|
+
# manage(peername: '192.168.1.5:161', version '2c')
|
48
51
|
def manage(options)
|
49
52
|
options = {:peername => options} if options.kind_of?(String)
|
50
53
|
sessions << Session.open(options)
|
@@ -54,11 +57,13 @@ EOF
|
|
54
57
|
# Close the session with the given `peername`
|
55
58
|
#
|
56
59
|
# Arguments
|
60
|
+
#
|
57
61
|
# - peername: May be a string, matching the peername, or an index.
|
58
62
|
# Run the `peer` command to see indexes & peernames for
|
59
63
|
# all active sessions
|
60
64
|
#
|
61
|
-
# Example
|
65
|
+
# Example
|
66
|
+
#
|
62
67
|
# [7] net-snmp2> peers
|
63
68
|
#
|
64
69
|
# Currently Managing
|
@@ -117,6 +122,7 @@ EOF
|
|
117
122
|
# Translates a numerical oid to it's MIB name, or a name to numerical oid
|
118
123
|
#
|
119
124
|
# Arguments
|
125
|
+
#
|
120
126
|
# - oid: Either a string, as the numerical OID or MIB variable name,
|
121
127
|
# or an OID object
|
122
128
|
def translate(oid)
|
@@ -126,6 +132,7 @@ EOF
|
|
126
132
|
# Prints a description of a MIB variable
|
127
133
|
#
|
128
134
|
# Arguments
|
135
|
+
#
|
129
136
|
# - oid: May be either a numeric OID, or MIB variable name
|
130
137
|
def describe(oid)
|
131
138
|
nodes = [MIB[oid]]
|
@@ -135,6 +142,7 @@ EOF
|
|
135
142
|
# Prints a description of a the MIB subtree starting at root `oid`
|
136
143
|
#
|
137
144
|
# Arguments
|
145
|
+
#
|
138
146
|
# - oid: May be either a numeric OID, or MIB variable name
|
139
147
|
def describe_tree(oid)
|
140
148
|
root = MIB[oid]
|
@@ -145,6 +153,7 @@ EOF
|
|
145
153
|
# Issue an SNMP GET Request to all active peers
|
146
154
|
#
|
147
155
|
# Arguments
|
156
|
+
#
|
148
157
|
# - oids: A single oid, or an array of oids
|
149
158
|
def get(oids, options = {})
|
150
159
|
each_session do |session|
|
@@ -158,6 +167,7 @@ EOF
|
|
158
167
|
# Issue an SNMP GETNEXT Request to all active peers
|
159
168
|
#
|
160
169
|
# Arguments
|
170
|
+
#
|
161
171
|
# - oids: A single oid, or an array of oids
|
162
172
|
def get_next(oids, options = {})
|
163
173
|
each_session do |session|
|
@@ -171,6 +181,7 @@ EOF
|
|
171
181
|
# Issue an SNMP GETBULK Request to all active peers
|
172
182
|
#
|
173
183
|
# Arguments
|
184
|
+
#
|
174
185
|
# - oids: A single oid, or an array of oids
|
175
186
|
# - options: A Hash accepting the typical options keys for a request, plus
|
176
187
|
# + non_repeaters: The number of non-repeated oids in the request
|
@@ -188,6 +199,7 @@ EOF
|
|
188
199
|
# Performs a walk on all active peers for each oid provided
|
189
200
|
#
|
190
201
|
# Arguments
|
202
|
+
#
|
191
203
|
# - oids: A single oid, or an array of oids
|
192
204
|
def walk(oids, options = {})
|
193
205
|
each_session do |session|
|
@@ -201,10 +213,11 @@ EOF
|
|
201
213
|
# Issue an SNMP Set Request to all active peers
|
202
214
|
#
|
203
215
|
# Arguments
|
216
|
+
#
|
204
217
|
# - varbinds: An single varbind, or an array of varbinds, each of which may be
|
205
218
|
# + An Array of length 3 `[oid, type, value]`
|
206
219
|
# + An Array of length 2 `[oid, value]`
|
207
|
-
# +
|
220
|
+
# + A Hash `{oid: oid, type: type, value: value}`
|
208
221
|
# * Hash syntax is the same as supported by PDU.add_varbind
|
209
222
|
# * If type is not supplied, it is infered by the value
|
210
223
|
def set(varbinds, options = {})
|
data/lib/net/snmp/session.rb
CHANGED
@@ -88,7 +88,6 @@ module Net
|
|
88
88
|
else
|
89
89
|
Constants::SNMP_VERSION_1
|
90
90
|
end
|
91
|
-
debug "setting timeout = #{@timeout} retries = #{@retries}"
|
92
91
|
@sess.timeout = @timeout * 1000000
|
93
92
|
@sess.retries = @retries
|
94
93
|
|
@@ -164,7 +163,6 @@ module Net
|
|
164
163
|
end
|
165
164
|
end
|
166
165
|
end
|
167
|
-
# General callback just takes the pdu, calls the session callback if any, then the request specific callback.
|
168
166
|
|
169
167
|
@struct = Wrapper.snmp_sess_open(@sess.pointer)
|
170
168
|
end
|
@@ -172,13 +170,13 @@ module Net
|
|
172
170
|
# Close the snmp session and free associated resources.
|
173
171
|
def close
|
174
172
|
if Net::SNMP.thread_safe
|
175
|
-
|
173
|
+
Session.lock.synchronize {
|
176
174
|
Wrapper.snmp_sess_close(@struct)
|
177
|
-
|
175
|
+
Session.sessions.delete(self.sessid)
|
178
176
|
}
|
179
177
|
else
|
180
178
|
Wrapper.snmp_sess_close(@struct)
|
181
|
-
|
179
|
+
Session.sessions.delete(self.sessid)
|
182
180
|
end
|
183
181
|
end
|
184
182
|
|
@@ -281,42 +279,38 @@ module Net
|
|
281
279
|
# the number of seconds to block.
|
282
280
|
# Returns the number of file descriptors handled.
|
283
281
|
def select(timeout = nil)
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
else
|
289
|
-
# 8K should be plenty of space
|
290
|
-
@fdset = FFI::MemoryPointer.new(1024 * 8)
|
291
|
-
end
|
282
|
+
unless @fdset
|
283
|
+
# 8K should be plenty of space
|
284
|
+
@fdset = FFI::MemoryPointer.new(1024 * 8)
|
285
|
+
end
|
292
286
|
|
293
|
-
|
294
|
-
tv_sec = timeout ? timeout.round : 0
|
295
|
-
tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
296
|
-
tval = Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
297
|
-
block = FFI::MemoryPointer.new(:int)
|
298
|
-
if timeout.nil?
|
299
|
-
block.write_int(0)
|
300
|
-
else
|
301
|
-
block.write_int(1)
|
302
|
-
end
|
287
|
+
@fdset.clear
|
303
288
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
289
|
+
num_fds = FFI::MemoryPointer.new(:int)
|
290
|
+
tv_sec = timeout ? timeout.round : 0
|
291
|
+
tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
292
|
+
tval = Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
293
|
+
block = FFI::MemoryPointer.new(:int)
|
294
|
+
if timeout.nil?
|
295
|
+
block.write_int(0)
|
296
|
+
else
|
297
|
+
block.write_int(1)
|
298
|
+
end
|
299
|
+
|
300
|
+
Wrapper.snmp_sess_select_info(@struct, num_fds, @fdset, tval.pointer, block )
|
301
|
+
tv = (timeout == false ? nil : tval)
|
302
|
+
num_ready = FFI::LibC.select(num_fds.read_int, @fdset, nil, nil, tv)
|
303
|
+
if num_ready > 0
|
304
|
+
Wrapper.snmp_sess_read(@struct, @fdset)
|
305
|
+
elsif num_ready == 0
|
306
|
+
Wrapper.snmp_sess_timeout(@struct)
|
307
|
+
elsif num_ready == -1
|
308
|
+
# error. check snmp_error?
|
309
|
+
error("select")
|
310
|
+
else
|
311
|
+
error("wtf is wrong with select?")
|
312
|
+
end
|
313
|
+
num_ready
|
320
314
|
end
|
321
315
|
|
322
316
|
alias :poll :select
|
@@ -352,7 +346,7 @@ module Net
|
|
352
346
|
# So we remove it and resend all the rest
|
353
347
|
if pdu.error? && pdu.errindex == i + 1
|
354
348
|
oidlist.pop # remove the bad oid
|
355
|
-
debug "
|
349
|
+
debug "Error on: #{pdu.varbinds[pdu.errindex - 1].oid}"
|
356
350
|
if pdu.varbinds.size > i+1
|
357
351
|
# recram rest of oids on list
|
358
352
|
((i+1)..pdu.varbinds.size).each do |j|
|
@@ -373,7 +367,6 @@ module Net
|
|
373
367
|
all_results
|
374
368
|
end
|
375
369
|
|
376
|
-
|
377
370
|
# Given a list of columns (e.g ['ifIndex', 'ifDescr'], will return a hash with
|
378
371
|
# the indexes as keys and hashes as values.
|
379
372
|
# puts sess.get_columns(['ifIndex', 'ifDescr']).inspect
|
@@ -435,13 +428,19 @@ module Net
|
|
435
428
|
# rescue Net::SNMP::Error => e
|
436
429
|
# puts e.message
|
437
430
|
# end
|
438
|
-
def send_pdu(pdu, options = {},
|
431
|
+
def send_pdu(pdu, options = {}, &callback)
|
439
432
|
if options[:blocking]
|
440
433
|
return send_pdu_blocking(pdu)
|
441
434
|
end
|
435
|
+
|
436
|
+
debug "Sending: " do
|
437
|
+
pdu.print
|
438
|
+
end
|
439
|
+
|
442
440
|
if block_given?
|
441
|
+
debug "Setting callback for reqid #{pdu.reqid}"
|
443
442
|
@requests[pdu.reqid] = callback
|
444
|
-
debug "
|
443
|
+
debug "Calling snmp_sess_async_send"
|
445
444
|
if Wrapper.snmp_sess_async_send(@struct, pdu.pointer, sess_callback, nil) == 0
|
446
445
|
error("snmp_get async failed")
|
447
446
|
end
|
@@ -469,6 +468,36 @@ module Net
|
|
469
468
|
send_pdu_blocking(pdu)
|
470
469
|
end
|
471
470
|
end
|
471
|
+
|
472
|
+
# if block_given?
|
473
|
+
# debug "Setting callback for reqid #{pdu.reqid}"
|
474
|
+
# @requests[pdu.reqid] = callback
|
475
|
+
# debug "Calling snmp_sess_async_send"
|
476
|
+
# if Wrapper.snmp_sess_async_send(@struct, pdu.pointer, sess_callback, nil) == 0
|
477
|
+
# error("snmp_get async failed")
|
478
|
+
# end
|
479
|
+
# nil
|
480
|
+
# elsif defined?(EM) && EM.reactor_running? && defined?(Fiber)
|
481
|
+
# f = Fiber.current
|
482
|
+
# send_pdu pdu do | op, response_pdu |
|
483
|
+
# f.resume([op, response_pdu])
|
484
|
+
# end
|
485
|
+
# op, result = Fiber.yield
|
486
|
+
# case op
|
487
|
+
# when :timeout
|
488
|
+
# raise TimeoutError.new, "timeout"
|
489
|
+
# when :send_failed
|
490
|
+
# error "send failed"
|
491
|
+
# when :success
|
492
|
+
# result
|
493
|
+
# when :connect, :disconnect
|
494
|
+
# nil #does this ever happen?
|
495
|
+
# else
|
496
|
+
# error "unknown operation #{op}"
|
497
|
+
# end
|
498
|
+
# else
|
499
|
+
# send_pdu_blocking(pdu)
|
500
|
+
# end
|
472
501
|
end
|
473
502
|
|
474
503
|
def send_pdu_blocking(pdu)
|
@@ -477,7 +506,8 @@ module Net
|
|
477
506
|
# Since we don't expect a response, the native net-snmp lib is going to free this
|
478
507
|
# pdu for us. Polite, though this may be, it causes intermittent segfaults when freeing
|
479
508
|
# memory malloc'ed by ruby. So, clone the pdu into a new memory buffer,
|
480
|
-
# and pass that along.
|
509
|
+
# and pass that along. The clone is then freed by the native lib. The sent
|
510
|
+
# pdu must be freed by the caller.
|
481
511
|
clone = Wrapper.snmp_clone_pdu(pdu.struct)
|
482
512
|
status = Wrapper.snmp_sess_send(@struct, clone)
|
483
513
|
if status == 0
|
@@ -518,7 +548,7 @@ module Net
|
|
518
548
|
|
519
549
|
def sess_callback
|
520
550
|
@sess_callback ||= FFI::Function.new(:int, [:int, :pointer, :int, :pointer, :pointer]) do |operation, session, reqid, pdu_ptr, magic|
|
521
|
-
debug "in
|
551
|
+
debug "in sess_callback #{operation.inspect} #{session.inspect}"
|
522
552
|
op = case operation
|
523
553
|
when Constants::NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE
|
524
554
|
:success
|
@@ -536,6 +566,9 @@ module Net
|
|
536
566
|
|
537
567
|
if @requests[reqid]
|
538
568
|
pdu = PDU.new(pdu_ptr)
|
569
|
+
debug "Received:" do
|
570
|
+
pdu.print
|
571
|
+
end
|
539
572
|
callback_return = @requests[reqid].call(op, pdu)
|
540
573
|
@requests.delete(reqid)
|
541
574
|
callback_return == false ? 0 : 1 #if callback returns false (failure), pass it on. otherwise return 1 (success)
|