wping 0.1.0-mswin32

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.
Files changed (3) hide show
  1. data/bin/ping.rb +51 -0
  2. data/lib/win32/ping.rb +149 -0
  3. metadata +47 -0
@@ -0,0 +1,51 @@
1
+ $: << File.join( File.dirname( __FILE__ ), '../lib' )
2
+ require 'win32/ping'
3
+ require 'resolv'
4
+
5
+ include Win32
6
+
7
+ size = 32
8
+ count = 4
9
+ forever = false
10
+
11
+ while arg = ARGV.shift
12
+ case arg
13
+ when /-t/
14
+ forever = true
15
+ else
16
+ host = arg
17
+ end
18
+ end
19
+
20
+ pinger = Win32::PingICMP.new
21
+
22
+ real_host = Resolv.new.getaddress( host )
23
+ host = "#{host} [#{real_host}]" unless host == real_host
24
+ puts "\nPinging #{host} with #{size} bytes of data:\n\n"
25
+ i = count
26
+ total = max = received = lost = 0
27
+ min = nil
28
+
29
+ while forever == true or i > 0
30
+ i -= 1
31
+ r = pinger.ping( real_host, 1, size ).first
32
+ if r.successful
33
+ puts "Reply from #{real_host}: bytes=#{size} time=#{r.round_trip_time} TTL=#{r.ttl}"
34
+ received += 1
35
+ min ||= r.round_trip_time
36
+ min = [min, r.round_trip_time].min
37
+ max = [max, r.round_trip_time].max
38
+ total += r.round_trip_time
39
+ else
40
+ puts "Ping failed"
41
+ lost += 1
42
+ end
43
+ sleep 1
44
+ end
45
+
46
+ avg = total.to_f / count
47
+ puts "\nPing statistics for #{real_host}:"
48
+ puts " Packets: Sent = #{count}, Received = #{received}, Lost = #{lost} (#{'%d'%[lost/count*100]}% loss),"
49
+ puts "Approximate round trip times in milli-seconds:"
50
+ puts " Minimum = #{min}ms, Maximum = #{max}ms, Average = #{avg}ms\n"
51
+
@@ -0,0 +1,149 @@
1
+ require 'Win32API'
2
+ require 'ipaddr'
3
+ require 'resolv'
4
+ require 'enumerator'
5
+ require 'ostruct'
6
+
7
+ class Integer
8
+ def to_ip
9
+ ip = []
10
+ self.to_s( 2 ).rjust( 32, "0" ).split(//).each_slice( 8 ) do |p|
11
+ ip << p.join.to_i( 2 )
12
+ end
13
+ ip.join '.'
14
+ end
15
+
16
+ def to_w32ip
17
+ [self].pack( 'N' ).unpack( 'L' ).first
18
+ end
19
+ end
20
+
21
+ class IPAddr
22
+ def to_w32ip
23
+ self.to_i.to_w32ip
24
+ end
25
+ end
26
+
27
+ module Win32; end
28
+ class Win32::PingICMP
29
+ @@icmp_create_file = Win32API.new( 'icmp', 'IcmpCreateFile', '', 'N' )
30
+ @@icmp_send_echo = Win32API.new( 'icmp', 'IcmpSendEcho', 'NNPIPPNN', 'N' )
31
+ @@icmp_close_handle = Win32API.new( 'icmp', 'IcmpCloseHandle', 'N', 'I' )
32
+ @@resolv = Resolv.new
33
+
34
+ IPFLAG_DONT_FRAGMENT = 0x02
35
+ REPLY_BUFFER_SIZE = 1024
36
+ ICMP_ECHO_REPLY_SIZE = 28
37
+
38
+ # Low level, you probably shouldn't be using it
39
+ def self.icmp_create_file
40
+ handle = @@icmp_create_file.call
41
+ if block_given?
42
+ begin
43
+ yield handle
44
+ ensure
45
+ icmp_close_handle handle
46
+ handle = nil
47
+ end
48
+ end
49
+ handle
50
+ end
51
+
52
+ # This is pretty low level and probably shouldn't be used, but since
53
+ # I believe in freedom, I have left it public just in case.
54
+ # I left out the data size and buffer size args because ruby can
55
+ # figure that out. int_ip is the int form of the ip address.
56
+ def self.icmp_send_echo handle, int_ip, request_data, request_options,
57
+ reply_buffer, timeout
58
+ @@icmp_send_echo.call( handle, int_ip, request_data, request_data.size,
59
+ request_options, reply_buffer, reply_buffer.size,
60
+ timeout )
61
+ end
62
+
63
+ # Low level. Are you sure you need this?
64
+ def self.icmp_close_handle handle
65
+ @@icmp_close_handle.call( handle )
66
+ end
67
+
68
+ # Low level.
69
+ def self.resolv hostname
70
+ @@resolv.getaddress hostname
71
+ end
72
+
73
+ # Some algorythm I found on line.
74
+ # This generates the buffer to ping with
75
+ def self.create_buffer size
76
+ b = []
77
+ 1.upto size do |i|
78
+ # readable characters
79
+ b << i % 94 + 32
80
+ end
81
+
82
+ ("%c"*size)%b
83
+ end
84
+
85
+ # heres what you want
86
+ def ping host, count = 1, size = 32, no_frag = false, ttl = 64, timeout = 4000
87
+ ip = nil
88
+ nresolv = false
89
+ begin
90
+ if nresolv
91
+ host = self.class.resolv host
92
+ end
93
+ ip = IPAddr.new( host )
94
+ rescue
95
+ unless nresolv
96
+ nresolv = true
97
+ retry
98
+ end
99
+ raise $!
100
+ end
101
+
102
+ reply_buffer = "0" * ( size + ICMP_ECHO_REPLY_SIZE )
103
+ req_data = self.class.create_buffer size
104
+ replies = []
105
+ no_frag = no_frag ? IPFLAG_DONT_FRAGMENT : 0
106
+ # struct options
107
+ # u_char ttl
108
+ # u_char tos
109
+ # u_char flags
110
+ # u_char options_size
111
+ options = ("%c"*4)%[ttl,0,no_frag,0]
112
+ self.class.icmp_create_file do |handle|
113
+ count.times do
114
+ reply = OpenStruct.new
115
+ reply.reply_count = self.class.icmp_send_echo( handle, ip.to_w32ip,
116
+ req_data, options,
117
+ reply_buffer, timeout )
118
+ reply.request_data = req_data
119
+ reply.reply_data = reply_buffer[28..-1]
120
+ header = reply_buffer.unpack( 'NLLSSLCCCCL' )
121
+ reply.ip = header[0].to_ip
122
+ reply.status, reply.round_trip_time = header[1..2]
123
+ reply.data_size, reply.reserved = header[3..4]
124
+ # this is a pointer to the actual reply data. We assume
125
+ # that it is a 28 so we don't need it, maybe future versions
126
+ # will
127
+ #reply.pdata = header[5]
128
+ reply.time_to_live = reply.ttl = header[6]
129
+ reply.type_of_service = reply.tos = header[7]
130
+ reply.flags = header[8]
131
+ reply.options_size = header[9]
132
+ # this is a pointer to the optiondata, we don't need it
133
+ # but maybe future versions will
134
+ #reply.poptions_data = header[10]
135
+ # I was using this one for testing
136
+ #reply.reply_buffer = reply_buffer
137
+ reply.successful = ( reply.status == 0 )
138
+ replies << reply
139
+ end
140
+ end
141
+ def replies.all_successful?
142
+ self.find {|r| !r.successful }.nil?
143
+ end
144
+ def replies.one_successful?
145
+ !self.find {|r| r.successful}.nil?
146
+ end
147
+ replies
148
+ end
149
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: wping
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-11-20 00:00:00 -05:00
8
+ summary: ruby wrapper for win32api icmp.dll
9
+ require_paths:
10
+ - lib
11
+ email: rcorsaro@gmail.com
12
+ homepage:
13
+ rubyforge_project:
14
+ description: ruby wrapper for win32api icmp.dll
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: mswin32
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - rcorsaro
30
+ files:
31
+ - bin/ping.rb
32
+ - lib/win32
33
+ - lib/win32/ping.rb
34
+ test_files: []
35
+
36
+ rdoc_options: []
37
+
38
+ extra_rdoc_files: []
39
+
40
+ executables:
41
+ - ping.rb
42
+ extensions: []
43
+
44
+ requirements:
45
+ - none
46
+ dependencies: []
47
+