net-snmp 0.1.7 → 0.2.0
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.
- data/Gemfile +2 -0
- data/README.rdoc +41 -20
- data/lib/net-snmp.rb +6 -2
- data/lib/net/snmp.rb +7 -4
- data/lib/net/snmp/constants.rb +73 -56
- data/lib/net/snmp/debug.rb +17 -0
- data/lib/net/snmp/dispatcher.rb +43 -65
- data/lib/net/snmp/error.rb +18 -10
- data/lib/net/snmp/inline.rb +4 -14
- data/lib/net/snmp/oid.rb +6 -2
- data/lib/net/snmp/pdu.rb +58 -19
- data/lib/net/snmp/session.rb +275 -195
- data/lib/net/snmp/trap_session.rb +64 -0
- data/lib/net/snmp/varbind.rb +28 -6
- data/lib/net/snmp/version.rb +1 -1
- data/lib/net/snmp/wrapper.rb +33 -8
- data/spec/async_spec.rb +78 -30
- data/spec/em_spec.rb +1 -1
- data/spec/error_spec.rb +36 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/sync_spec.rb +9 -1
- data/spec/thread_spec.rb +3 -1
- data/spec/trap_spec.rb +12 -10
- data/spec/wrapper_spec.rb +2 -2
- metadata +8 -4
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -9,6 +9,7 @@ It provides classes for sessions, pdus, varbinds, and more.
|
|
9
9
|
|
10
10
|
* Supports SNMP versions 1, 2c, and 3
|
11
11
|
* Supports both synchronous and asynchronous calls
|
12
|
+
* Supports sending of snmpv1 traps and snmpv2 traps/informs using TrapSession
|
12
13
|
* Integrates well with eventmachine, or can be used standalone.
|
13
14
|
* In Ruby 1.9, uses fibers behind the scenes to emulate synchronous calls asynchronously
|
14
15
|
|
@@ -44,31 +45,48 @@ functions are defined in Net::SNMP::Wrapper. You can call them like so:
|
|
44
45
|
== NOTES
|
45
46
|
You must call Session.close when you're done with a session to avoid leaking memory
|
46
47
|
|
47
|
-
==
|
48
|
+
== ERROR HANDLING
|
49
|
+
In the synchronous versions, all session methods raise Net::SNMP:Error on any error. Timeouts raise Net::SNMP::TimeoutError.
|
50
|
+
In the asynchronous versions, the first argument to your callback will be the return status. Possible values include :success, :timeout, and :send_error.
|
51
|
+
If you need the underlying net-snmp session errors, you can call session.errno, session.snmp_err, and session.error_message.
|
52
|
+
|
48
53
|
|
54
|
+
== EXAMPLES
|
49
55
|
|
50
56
|
A simple synchronous SNMP-GET
|
51
57
|
|
52
58
|
session = Net::SNMP::Session.open(:peername => "test.net-snmp.org", :community => "demopublic" )
|
53
|
-
|
54
|
-
|
59
|
+
begin
|
60
|
+
pdu = session.get("sysDescr.0")
|
61
|
+
puts pdu.varbinds.first.value
|
62
|
+
rescue Net::SNMP::Error => e
|
63
|
+
puts e.message
|
64
|
+
end
|
55
65
|
session.close
|
56
66
|
|
57
67
|
An asynchronous SNMP-GET
|
58
68
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
59
|
-
session.get(["sysDescr.0", "sysContact.0"]) do |
|
60
|
-
|
69
|
+
session.get(["sysDescr.0", "sysContact.0"]) do |status, pdu|
|
70
|
+
if status == :success
|
71
|
+
puts pdu.varbinds[0].value
|
72
|
+
else
|
73
|
+
puts "something went wrong. status is #{status}"
|
74
|
+
end
|
61
75
|
end
|
62
76
|
end
|
63
|
-
Net::SNMP::Dispatcher.
|
77
|
+
Net::SNMP::Dispatcher.select(false) #Setting timeout to false causes dispatcher to block until data is ready
|
64
78
|
session.close
|
65
79
|
|
66
80
|
Running the dispatcher from eventmachine
|
67
81
|
EM.run do
|
68
82
|
Net::SNMP::Dispatcher.em_loop
|
69
83
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic') do |session|
|
70
|
-
session.get("sysDescr.0") do |
|
71
|
-
|
84
|
+
session.get("sysDescr.0") do |status, pdu|
|
85
|
+
if status == :success
|
86
|
+
puts pdu.varbinds[0].value
|
87
|
+
else
|
88
|
+
puts "something went wrong. status is #{status}"
|
89
|
+
end
|
72
90
|
end
|
73
91
|
end
|
74
92
|
EM.add_timer(2) do
|
@@ -82,8 +100,12 @@ Using synchronous style with eventmachine in ruby 1.9
|
|
82
100
|
Net::SNMP::Dispatcher.fiber_loop
|
83
101
|
Fiber.new {
|
84
102
|
session = Net::SNMP::Session.open(:peername => 'test.net-snmp.org', :community => 'demopublic')
|
85
|
-
|
86
|
-
|
103
|
+
begin
|
104
|
+
pdu = session.get("sysDescr.0")
|
105
|
+
puts pdu.varbinds[0].value
|
106
|
+
rescue Net::SNMP::Error => e
|
107
|
+
puts e.message
|
108
|
+
end
|
87
109
|
session.close
|
88
110
|
EM.stop
|
89
111
|
}.resume
|
@@ -105,14 +127,15 @@ You can also explicitly add MIBs using the MIB api. For example:
|
|
105
127
|
Net::SNMP::MIB.add_mibdir("/usr/local/share/mibs")
|
106
128
|
Net::SNMP::MIB.read_mib("RFC1213-MIB.txt")
|
107
129
|
|
108
|
-
Having the appropriate MIBs loaded will allow you to pass names instead of numeric oids to net-snmp methods.
|
109
|
-
|
110
|
-
|
130
|
+
Having the appropriate MIBs loaded will allow you to pass names instead of numeric oids to net-snmp methods. You can also pass
|
131
|
+
Net::SNMP::OID objects. For example
|
111
132
|
|
112
|
-
|
113
|
-
|
114
|
-
|
133
|
+
oid = Net::SNMP::OID.new('sysDescr.0') # or Net::SNMP::OID.new("1.3.6.1.2.1.1.1.0")
|
134
|
+
puts oid.to_s --> '1.3.6.1.2.1.1.1.0'
|
135
|
+
puts oid.label --> 'sysDescr.0'
|
136
|
+
pdu = session.get([oid])
|
115
137
|
|
138
|
+
For more complex MIB parsing needs, see smi-ffi[http://github.com/mixtli/smi-ffi]
|
116
139
|
|
117
140
|
== CAVEATS/DISCLAIMER
|
118
141
|
|
@@ -128,13 +151,11 @@ break this gem. Please let me know if you find bugs or missing features. Or be
|
|
128
151
|
|
129
152
|
|
130
153
|
== TODO
|
131
|
-
|
132
|
-
* Better error handling.
|
154
|
+
* Implement walk and get_table convenience methods.
|
133
155
|
* SNMPv3 support needs testing for various security models
|
134
156
|
* Better documentation
|
135
157
|
* More tests
|
136
|
-
|
137
|
-
* Implement SNMP traps/informs?
|
158
|
+
|
138
159
|
|
139
160
|
== Note on Patches/Pull Requests
|
140
161
|
|
data/lib/net-snmp.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'nice-ffi'
|
3
3
|
require 'fiber'
|
4
|
-
|
5
|
-
|
4
|
+
require 'ffi-inliner'
|
5
|
+
#require 'ffi/libc'
|
6
|
+
%w( snmp snmp/debug snmp/wrapper snmp/version snmp/inline snmp/constants snmp/utility snmp/oid snmp/error snmp/pdu snmp/session snmp/trap_session snmp/varbind snmp/mib snmp/mib/node snmp/dispatcher).each do |f|
|
6
7
|
require "#{File.dirname(__FILE__)}/net/#{f}"
|
7
8
|
end
|
9
|
+
|
10
|
+
|
11
|
+
|
8
12
|
Net::SNMP::MIB.init
|
9
13
|
Net::SNMP::MIB.read_all_mibs
|
10
14
|
Net::SNMP.init
|
data/lib/net/snmp.rb
CHANGED
@@ -2,15 +2,18 @@ require 'net/snmp/constants'
|
|
2
2
|
module Net
|
3
3
|
module SNMP
|
4
4
|
include Net::SNMP::Constants
|
5
|
-
|
6
|
-
|
5
|
+
@thread_safe = false
|
7
6
|
def self.init(tag="snmp")
|
8
7
|
Wrapper.init_snmp(tag)
|
9
8
|
end
|
10
9
|
|
10
|
+
def self.thread_safe=(val)
|
11
|
+
@thread_safe = val
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
def self.thread_safe
|
15
|
+
@thread_safe
|
16
|
+
end
|
14
17
|
|
15
18
|
end
|
16
19
|
end
|
data/lib/net/snmp/constants.rb
CHANGED
@@ -2,10 +2,18 @@ module Net
|
|
2
2
|
module SNMP
|
3
3
|
module Constants
|
4
4
|
MAX_OID_LEN = 128
|
5
|
+
|
6
|
+
# Return values of various send functions
|
7
|
+
STAT_SUCCESS = 0
|
8
|
+
STAT_ERROR = 1
|
9
|
+
STAT_TIMEOUT = 2
|
10
|
+
|
11
|
+
# SNMP versions
|
5
12
|
SNMP_VERSION_1 = 0
|
6
13
|
SNMP_VERSION_2c = 1
|
7
14
|
SNMP_VERSION_3 = 3
|
8
15
|
|
16
|
+
# PDU variable types
|
9
17
|
ASN_BOOLEAN = 0x01
|
10
18
|
ASN_INTEGER = 0x02
|
11
19
|
ASN_BIT_STR = 0x03
|
@@ -34,13 +42,17 @@ module Net
|
|
34
42
|
ASN_UNSIGNED = (ASN_APPLICATION | 2) # RFC 1902 - same as GAUGE
|
35
43
|
ASN_TIMETICKS = (ASN_APPLICATION | 3)
|
36
44
|
ASN_OPAQUE = (ASN_APPLICATION | 4)
|
45
|
+
ASN_NSAP = (ASN_APPLICATION | 5) # historic - don't use
|
46
|
+
ASN_COUNTER64 = (ASN_APPLICATION | 6)
|
47
|
+
ASN_UINTEGER = (ASN_APPLICATION | 7) # historic - don't use
|
37
48
|
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
49
|
+
# Exception values for SNMPv2 and SNMPv3
|
50
|
+
SNMP_NOSUCHOBJECT = (ASN_CONTEXT | ASN_PRIMITIVE | 0x0)
|
51
|
+
SNMP_NOSUCHINSTANCE = (ASN_CONTEXT | ASN_PRIMITIVE | 0x1)
|
52
|
+
SNMP_ENDOFVIEW = (ASN_CONTEXT | ASN_PRIMITIVE | 0x2)
|
42
53
|
|
43
54
|
|
55
|
+
# PDU types
|
44
56
|
SNMP_MSG_GET = (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x0)
|
45
57
|
SNMP_MSG_GETNEXT = (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x1)
|
46
58
|
SNMP_MSG_RESPONSE = (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x2)
|
@@ -51,64 +63,15 @@ module Net
|
|
51
63
|
SNMP_MSG_TRAP2 = (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x7)
|
52
64
|
SNMP_MSG_REPORT = (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x8)
|
53
65
|
|
66
|
+
|
67
|
+
# Callback status codes
|
54
68
|
NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE = 1
|
55
69
|
NETSNMP_CALLBACK_OP_TIMED_OUT = 2
|
56
70
|
NETSNMP_CALLBACK_OP_SEND_FAILED = 3
|
57
71
|
NETSNMP_CALLBACK_OP_CONNECT = 4
|
58
72
|
NETSNMP_CALLBACK_OP_DISCONNECT = 5
|
59
73
|
|
60
|
-
|
61
|
-
|
62
|
-
USM_AUTH_KU_LEN = 32
|
63
|
-
USM_PRIV_KU_LEN = 32
|
64
|
-
|
65
|
-
SNMP_SEC_LEVEL_NOAUTH = 1
|
66
|
-
SNMP_SEC_LEVEL_AUTHNOPRIV = 2
|
67
|
-
SNMP_SEC_LEVEL_AUTHPRIV = 3
|
68
|
-
|
69
|
-
SNMP_DEFAULT_COMMUNITY_LEN = 0
|
70
|
-
SNMP_DEFAULT_RETRIES = -1
|
71
|
-
SNMP_DEFAULT_TIMEOUT = -1
|
72
|
-
SNMP_DEFAULT_REMPORT = 0
|
73
|
-
SNMP_DEFAULT_REQID = -1
|
74
|
-
SNMP_DEFAULT_MSGID = -1
|
75
|
-
SNMP_DEFAULT_ERRSTAT = -1
|
76
|
-
SNMP_DEFAULT_ERRINDEX = -1
|
77
|
-
SNMP_DEFAULT_ADDRESS = 0
|
78
|
-
SNMP_DEFAULT_ENTERPRISE_LENGTH = 0
|
79
|
-
SNMP_DEFAULT_TIME = 0
|
80
|
-
SNMP_DEFAULT_VERSION = -1
|
81
|
-
SNMP_DEFAULT_SECMODEL = -1
|
82
|
-
SNMP_DEFAULT_CONTEXT =
|
83
|
-
|
84
|
-
SNMP_MAX_MSG_SIZE = 1472
|
85
|
-
SNMP_MAX_MSG_V3_HDRS = (4+3+4+7+7+3+7+16)
|
86
|
-
SNMP_MAX_ENG_SIZE = 32
|
87
|
-
SNMP_MAX_SEC_NAME_SIZE = 256
|
88
|
-
SNMP_MAX_CONTEXT_SIZE = 256
|
89
|
-
SNMP_SEC_PARAM_BUF_SIZE = 256
|
90
|
-
SNMPV3_IGNORE_UNAUTH_REPORTS = 0
|
91
|
-
SNMP_SESS_NONAUTHORITATIVE = 0
|
92
|
-
SNMP_SESS_AUTHORITATIVE = 1
|
93
|
-
SNMP_SESS_UNKNOWNAUTH = 2
|
94
|
-
REPORT_STATS_LEN = 9
|
95
|
-
REPORT_snmpUnknownSecurityModels_NUM = 1
|
96
|
-
REPORT_snmpInvalidMsgs_NUM = 2
|
97
|
-
REPORT_usmStatsUnsupportedSecLevels_NUM = 1
|
98
|
-
REPORT_usmStatsNotInTimeWindows_NUM = 2
|
99
|
-
REPORT_usmStatsUnknownUserNames_NUM = 3
|
100
|
-
REPORT_usmStatsUnknownEngineIDs_NUM = 4
|
101
|
-
REPORT_usmStatsWrongDigests_NUM = 5
|
102
|
-
REPORT_usmStatsDecryptionErrors_NUM = 6
|
103
|
-
SNMP_DETAIL_SIZE = 512
|
104
|
-
SNMP_FLAGS_RESP_CALLBACK = 0x400
|
105
|
-
SNMP_FLAGS_USER_CREATED = 0x200
|
106
|
-
SNMP_FLAGS_DONT_PROBE = 0x100
|
107
|
-
SNMP_FLAGS_STREAM_SOCKET = 0x80
|
108
|
-
SNMP_FLAGS_LISTENING = 0x40
|
109
|
-
SNMP_FLAGS_SUBSESSION = 0x20
|
110
|
-
SNMP_FLAGS_STRIKE2 = 0x02
|
111
|
-
SNMP_FLAGS_STRIKE1 = 0x01
|
74
|
+
# SNMP Errors
|
112
75
|
SNMPERR_SUCCESS = (0)
|
113
76
|
SNMPERR_GENERR = (-1)
|
114
77
|
SNMPERR_BAD_LOCPORT = (-2)
|
@@ -178,6 +141,60 @@ module Net
|
|
178
141
|
SNMPERR_MAX = (-65)
|
179
142
|
|
180
143
|
|
144
|
+
|
145
|
+
USM_AUTH_KU_LEN = 32
|
146
|
+
USM_PRIV_KU_LEN = 32
|
147
|
+
|
148
|
+
# SNMPv3 Security Levels
|
149
|
+
SNMP_SEC_LEVEL_NOAUTH = 1
|
150
|
+
SNMP_SEC_LEVEL_AUTHNOPRIV = 2
|
151
|
+
SNMP_SEC_LEVEL_AUTHPRIV = 3
|
152
|
+
|
153
|
+
SNMP_DEFAULT_COMMUNITY_LEN = 0
|
154
|
+
SNMP_DEFAULT_RETRIES = -1
|
155
|
+
SNMP_DEFAULT_TIMEOUT = -1
|
156
|
+
SNMP_DEFAULT_REMPORT = 0
|
157
|
+
SNMP_DEFAULT_REQID = -1
|
158
|
+
SNMP_DEFAULT_MSGID = -1
|
159
|
+
SNMP_DEFAULT_ERRSTAT = -1
|
160
|
+
SNMP_DEFAULT_ERRINDEX = -1
|
161
|
+
SNMP_DEFAULT_ADDRESS = 0
|
162
|
+
SNMP_DEFAULT_ENTERPRISE_LENGTH = 0
|
163
|
+
SNMP_DEFAULT_TIME = 0
|
164
|
+
SNMP_DEFAULT_VERSION = -1
|
165
|
+
SNMP_DEFAULT_SECMODEL = -1
|
166
|
+
SNMP_DEFAULT_CONTEXT =
|
167
|
+
|
168
|
+
SNMP_MAX_MSG_SIZE = 1472
|
169
|
+
SNMP_MAX_MSG_V3_HDRS = (4+3+4+7+7+3+7+16)
|
170
|
+
SNMP_MAX_ENG_SIZE = 32
|
171
|
+
SNMP_MAX_SEC_NAME_SIZE = 256
|
172
|
+
SNMP_MAX_CONTEXT_SIZE = 256
|
173
|
+
SNMP_SEC_PARAM_BUF_SIZE = 256
|
174
|
+
SNMPV3_IGNORE_UNAUTH_REPORTS = 0
|
175
|
+
SNMP_SESS_NONAUTHORITATIVE = 0
|
176
|
+
SNMP_SESS_AUTHORITATIVE = 1
|
177
|
+
SNMP_SESS_UNKNOWNAUTH = 2
|
178
|
+
REPORT_STATS_LEN = 9
|
179
|
+
REPORT_snmpUnknownSecurityModels_NUM = 1
|
180
|
+
REPORT_snmpInvalidMsgs_NUM = 2
|
181
|
+
REPORT_usmStatsUnsupportedSecLevels_NUM = 1
|
182
|
+
REPORT_usmStatsNotInTimeWindows_NUM = 2
|
183
|
+
REPORT_usmStatsUnknownUserNames_NUM = 3
|
184
|
+
REPORT_usmStatsUnknownEngineIDs_NUM = 4
|
185
|
+
REPORT_usmStatsWrongDigests_NUM = 5
|
186
|
+
REPORT_usmStatsDecryptionErrors_NUM = 6
|
187
|
+
SNMP_DETAIL_SIZE = 512
|
188
|
+
SNMP_FLAGS_RESP_CALLBACK = 0x400
|
189
|
+
SNMP_FLAGS_USER_CREATED = 0x200
|
190
|
+
SNMP_FLAGS_DONT_PROBE = 0x100
|
191
|
+
SNMP_FLAGS_STREAM_SOCKET = 0x80
|
192
|
+
SNMP_FLAGS_LISTENING = 0x40
|
193
|
+
SNMP_FLAGS_SUBSESSION = 0x20
|
194
|
+
SNMP_FLAGS_STRIKE2 = 0x02
|
195
|
+
SNMP_FLAGS_STRIKE1 = 0x01
|
196
|
+
|
197
|
+
|
181
198
|
STAT_SNMPUNKNOWNSECURITYMODELS = 0
|
182
199
|
STAT_SNMPINVALIDMSGS = 1
|
183
200
|
STAT_SNMPUNKNOWNPDUHANDLERS = 2
|
data/lib/net/snmp/dispatcher.rb
CHANGED
@@ -1,89 +1,62 @@
|
|
1
1
|
class Net::SNMP::Dispatcher
|
2
|
+
# A class with convenience methods for polling multiple open sessions
|
2
3
|
class << self
|
3
|
-
|
4
|
-
|
5
|
-
# def poll(timeout = nil)
|
6
|
-
# fdset = Net::SNMP::Wrapper.get_fd_set
|
7
|
-
# num_fds = FFI::MemoryPointer.new(:int)
|
8
|
-
# tv_sec = timeout ? timeout.round : 0
|
9
|
-
# tv_usec = timeout ? (timeout - timeout.round) * 1000000 : 0
|
10
|
-
# tval = Net::SNMP::Wrapper::TimeVal.new(:tv_sec => tv_sec, :tv_usec => tv_usec)
|
11
|
-
# block = FFI::MemoryPointer.new(:int)
|
12
|
-
#
|
13
|
-
# if timeout.nil?
|
14
|
-
# block.write_int(0)
|
15
|
-
# else
|
16
|
-
# block.write_int(1)
|
17
|
-
# end
|
18
|
-
# #puts "calling snmp_select_info"
|
19
|
-
# Net::SNMP::Wrapper.snmp_select_info(num_fds, fdset, tval.pointer, block )
|
20
|
-
# #puts "done snmp_select_info."
|
21
|
-
# num_ready = 0
|
22
|
-
# #puts "block = #{block.read_int}"
|
23
|
-
#
|
24
|
-
# #puts "numready = #{num_fds.read_int}"
|
25
|
-
# #puts "tv = #{tval[:tv_sec]} #{tval[:tv_usec]}"
|
26
|
-
# #puts "timeout = #{timeout}"
|
27
|
-
# tv = (timeout == false ? nil : tval)
|
28
|
-
# #puts "calling select"
|
29
|
-
# #puts "tv = #{tv.inspect}"
|
30
|
-
# #puts "calling select with #{num_fds.read_int}"
|
31
|
-
# #num_ready = RubyWrapper.rb_thread_select(num_fds.read_int, fdset, nil, nil, tv)
|
32
|
-
# num_ready = Net::SNMP::Wrapper.select(num_fds.read_int, fdset, nil, nil, tv)
|
33
|
-
# #puts "done select. num_ready = #{num_ready}"
|
34
|
-
# if num_ready > 0
|
35
|
-
# Net::SNMP::Wrapper.snmp_read(fdset)
|
36
|
-
# elsif num_ready == 0
|
37
|
-
# # timeout. do something here? or just return 0?
|
38
|
-
# elsif num_ready == -1
|
39
|
-
# # error. check snmp_error?
|
40
|
-
# else
|
41
|
-
# # uhhh
|
42
|
-
# end
|
43
|
-
# #puts "done snmp_read"
|
44
|
-
# num_ready
|
45
|
-
# end
|
46
|
-
|
47
|
-
|
48
|
-
def poll(timeout = nil)
|
49
|
-
#puts "Dispatcher.poll #{Net::SNMP::Session.sessions.size}"
|
4
|
+
# Loop through all sessions, calling select on each.
|
5
|
+
def select(timeout = nil)
|
50
6
|
total = 0
|
51
7
|
t = timeout
|
52
8
|
t = nil if t == false
|
53
9
|
catch :got_data do
|
54
10
|
loop do
|
55
|
-
Net::SNMP
|
56
|
-
Net::SNMP::Session.
|
57
|
-
|
58
|
-
|
11
|
+
if Net::SNMP.thread_safe
|
12
|
+
Net::SNMP::Session.lock.synchronize {
|
13
|
+
Net::SNMP::Session.sessions.each do |k, sess|
|
14
|
+
total += sess.select(t)
|
15
|
+
end
|
16
|
+
}
|
17
|
+
else
|
18
|
+
Net::SNMP::Session.sessions.each do |k, sess|
|
19
|
+
total += sess.select(t)
|
59
20
|
end
|
60
|
-
|
21
|
+
end
|
22
|
+
|
61
23
|
throw :got_data if total > 0
|
62
24
|
throw :got_data unless timeout == false
|
63
25
|
end
|
64
26
|
end
|
65
|
-
#puts "Done Dispatcher.poll"
|
66
27
|
total
|
67
28
|
end
|
29
|
+
alias :poll :select
|
68
30
|
|
31
|
+
# Start a poller loop. Behavior depends upon whether
|
32
|
+
# you are running under eventmachine and whether fibers
|
33
|
+
# are available.
|
34
|
+
# +options+
|
35
|
+
# * :timeout Number of seconds to block on select. nil effects a poll. false blocks forever (probably not what you want).
|
36
|
+
# * :sleep Number of seconds to sleep if no data is available. Gives other fibers/threads a chance to run.
|
69
37
|
def run_loop(options = {})
|
70
38
|
if defined?(EM) && EM.reactor_running?
|
71
|
-
|
39
|
+
if defined?(Fiber)
|
40
|
+
fiber_loop(options)
|
41
|
+
else
|
42
|
+
em_loop(options)
|
43
|
+
end
|
72
44
|
else
|
73
45
|
thread_loop(options)
|
74
46
|
end
|
75
47
|
end
|
76
48
|
|
77
|
-
#
|
49
|
+
# Start a poller loop in a seperate thread. You
|
50
|
+
# should first call Net::SNMP.thread_safe = true.
|
51
|
+
# +options+
|
52
|
+
# * :timeout Number of seconds to block on select. Will not block other threads.
|
53
|
+
# * :sleep Number of seconds to sleep if no data is available. Allows other threads to run. Default 0.2
|
78
54
|
def thread_loop(options = {})
|
79
|
-
|
80
|
-
|
81
|
-
sleep_time = options[:sleep] || 0.1
|
55
|
+
timeout = options[:timeout] || 0.2
|
56
|
+
sleep_time = options[:sleep] || 0.2
|
82
57
|
Thread.new do
|
83
58
|
loop do
|
84
|
-
|
85
|
-
num_ready = poll(timeout)
|
86
|
-
#puts "num_ready = #{num_ready}"
|
59
|
+
num_ready = select(timeout)
|
87
60
|
if num_ready == 0
|
88
61
|
sleep(sleep_time) if sleep_time
|
89
62
|
end
|
@@ -91,14 +64,16 @@ class Net::SNMP::Dispatcher
|
|
91
64
|
end
|
92
65
|
end
|
93
66
|
|
94
|
-
|
67
|
+
# Start a loop in eventmachine (no fibers)
|
68
|
+
# +options+
|
69
|
+
# * :sleep Number of seconds to sleep if no data available. So we don't peg the reactor. Default 0.2
|
95
70
|
def em_loop(options = {})
|
96
71
|
timeout = options[:timeout]
|
97
|
-
sleep_time = options[:
|
72
|
+
sleep_time = options[:sleep] || 0.2
|
98
73
|
myproc = Proc.new do
|
99
74
|
EM.next_tick do
|
100
75
|
while(true) do
|
101
|
-
num_ready =
|
76
|
+
num_ready = select(timeout)
|
102
77
|
break if num_ready == 0
|
103
78
|
end
|
104
79
|
EM.add_timer(sleep_time) do
|
@@ -109,9 +84,12 @@ class Net::SNMP::Dispatcher
|
|
109
84
|
myproc.call
|
110
85
|
end
|
111
86
|
|
87
|
+
# Start a loop using eventmachine and fibers
|
88
|
+
# +options+
|
89
|
+
# * :sleep Number of seconds to sleep if no data available, so we don't peg the reactor. Default 0.2
|
112
90
|
def fiber_loop(options = {})
|
113
91
|
timeout = options[:timeout]
|
114
|
-
sleep_time = options[:sleep] || 0.
|
92
|
+
sleep_time = options[:sleep] || 0.2
|
115
93
|
Fiber.new {
|
116
94
|
loop do
|
117
95
|
num_handled = poll(timeout)
|