wping 0.1.0-mswin32

Sign up to get free protection for your applications and to get access to all the features.
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
+