simple_ping 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88ca1bd08781db9e2ba867c8599767be9163b272b0045adb5fd612a2f79d4ab9
4
- data.tar.gz: db299c8b1bedca36d463a483c37ddc5799411461910296e940f520938d0a9e1d
3
+ metadata.gz: c99b16f604de38384de5e722a9493406a59ccf56891d68a6abc99e91b42673c9
4
+ data.tar.gz: b06fd1a5ffaeaec507a8236ff475e78def4af9c5e6ad32e17831bfcac8af58eb
5
5
  SHA512:
6
- metadata.gz: 2433fe0679a8de4a99d90ecda60446590f4eb0dacb590f91efba668ea1e1631da652bd99d47a8abf39508406a770c7b680d87cd90874b53da4c21393e78ee2c0
7
- data.tar.gz: 06dd89c9f9026672e3439e0d59e66304714aa3ada3803681a6ed7c279885faa2fff13492e79f41f454d6996c91b040b455c707563bf1cb3a88e55aa24c6e8d5c
6
+ metadata.gz: 73fec53bfc6bc75af1a583726413ec13f9d135f9d7e7e43f9ea9c5987bbf8e39a1a0f266d2d89f1326f5a8bf46dec9c361aa56fc66431b212a75b424f6c62043
7
+ data.tar.gz: ec5f43516e4ce018ca5e5228ed56380ffbe120e636f789ddbe39146a05095062676d660a5632e5c2653f0ffd7fd4415a07beca0b71aa0abc7a878e3c58152330
data/.gitignore CHANGED
@@ -13,3 +13,7 @@
13
13
  test2.rb
14
14
  test.rb
15
15
  Gemfile.lock
16
+ simple_ping.code-workspace
17
+ sample_run.rb
18
+ Steepfile
19
+ .gitignore
@@ -0,0 +1 @@
1
+ 3.0.0
data/README.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # Overview
2
- A Simpe Ping Client for Ruby.
2
+ A Simpe Ping(ICMP) Client for Ruby.
3
+ https://rubygems.org/gems/simple_ping
3
4
 
4
5
  # How to use
5
6
  ※ Need root privileges to run.
6
7
 
7
- ```
8
+ ```ruby
9
+ require "simple_ping"
10
+
8
11
  ping_client = SimplePing::Client.new(src_ip_addr: "192.168.1.100")
9
12
  ping_client.exec(dest_ip_addr: "192.168.1.101")
10
13
  ```
@@ -16,5 +19,18 @@ ping_client.exec(dest_ip_addr: "192.168.1.101")
16
19
  - Does not support retries
17
20
  - Confirmed the operation with Ruby 2.7.1
18
21
 
22
+
23
+ # What you can do
24
+
25
+ - Return the success or failure of the ping (ICMP) result with true/false
26
+ - Destination is IP address
27
+
28
+ # What you can not do now
29
+
30
+ - Addressing by FQDN
31
+ - Retry
32
+ - Customized transmission data (ID specification, data section specification, etc.)
33
+ - Etc., etc
34
+
19
35
  # License
20
36
  MIT
@@ -40,19 +40,17 @@ class SimplePing::Client
40
40
  # Receive
41
41
  begin
42
42
  Timeout.timeout(TIMEOUT_TIME) do
43
- loop do
44
- mesg, _ = socket.recvfrom(1500)
45
- icmp_reply = SimplePing::RecvMessage.new(mesg).to_icmp
43
+ mesg, _ = socket.recvfrom(1500)
44
+ icmp_reply = SimplePing::RecvMessage.new(mesg).to_icmp
46
45
 
47
- if icmp.successful_reply?(icmp_reply)
48
- return true
49
- elsif icmp_reply.is_type_destination_unreachable?
50
- logger.warn { "Destination Unreachable!!" }
51
- return false
52
- elsif icmp_reply.is_type_redirect?
53
- logger.warn { "Redirect Required!!" }
54
- return false
55
- end
46
+ if icmp.successful_reply?(icmp_reply)
47
+ true
48
+ elsif icmp_reply.is_type_destination_unreachable?
49
+ logger.warn { "Destination Unreachable!!" }
50
+ false
51
+ elsif icmp_reply.is_type_redirect?
52
+ logger.warn { "Redirect Required!!" }
53
+ false
56
54
  end
57
55
  end
58
56
  rescue Timeout::Error => e
@@ -64,7 +64,7 @@ class SimplePing::ICMP
64
64
  @seq_number.to_s(2).rjust(16, "0")
65
65
 
66
66
  data_byte_arr = bynary_data.scan(/.{1,8}/)
67
- data_byte_arr.map! { |byte| byte.to_i(2).chr }
67
+ data_byte_arr.map! { |byte| byte.to_i(2).chr } # TO ASCII
68
68
  data_byte_arr.join + @data
69
69
  end
70
70
 
@@ -1,3 +1,3 @@
1
1
  module SimplePing
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,94 @@
1
+ module SimplePing
2
+ end
3
+
4
+ class SimplePing::Client
5
+ public
6
+
7
+ def exec: (dest_ip_addr: untyped, ?data: untyped) -> untyped
8
+
9
+ private
10
+
11
+ def initialize: (src_ip_addr: String, ?log_level: Integer) -> void
12
+
13
+ def logger: () -> untyped
14
+
15
+ def socket: () -> untyped
16
+ end
17
+
18
+ SimplePing::Client::TIMEOUT_TIME: Integer
19
+
20
+ class SimplePing::ICMP
21
+ public
22
+
23
+ def data: () -> untyped
24
+
25
+ def data=: (untyped) -> untyped
26
+
27
+ def id: () -> untyped
28
+
29
+ def id=: (untyped) -> untyped
30
+
31
+ def is_type_destination_unreachable?: () -> untyped
32
+
33
+ def is_type_echo?: () -> untyped
34
+
35
+ def is_type_echo_reply?: () -> untyped
36
+
37
+ def is_type_redirect?: () -> untyped
38
+
39
+ def seq_number: () -> untyped
40
+
41
+ def seq_number=: (untyped) -> untyped
42
+
43
+ def successful_reply?: (untyped icmp) -> untyped
44
+
45
+ def to_trans_data: () -> untyped
46
+
47
+ def type: () -> untyped
48
+
49
+ def type=: (untyped) -> untyped
50
+
51
+ private
52
+
53
+ def carry_up: (untyped num) -> untyped
54
+
55
+ def checksum: () -> untyped
56
+
57
+ def gen_data: () -> untyped
58
+
59
+ def gen_id: () -> untyped
60
+
61
+ def gen_seq_number: () -> untyped
62
+
63
+ def initialize: (type: untyped, ?code: untyped, ?id: untyped, ?seq_number: untyped, ?data: untyped) -> untyped
64
+ end
65
+
66
+ SimplePing::ICMP::TYPE_ICMP_DESTINATION_UNREACHABLE: Integer
67
+
68
+ SimplePing::ICMP::TYPE_ICMP_ECHO_REPLY: Integer
69
+
70
+ SimplePing::ICMP::TYPE_ICMP_ECHO_REQUEST: Integer
71
+
72
+ SimplePing::ICMP::TYPE_ICMP_REDIRECT: Integer
73
+
74
+ class SimplePing::RecvMessage
75
+ public
76
+
77
+ def code: () -> untyped
78
+
79
+ def data: () -> untyped
80
+
81
+ def id: () -> untyped
82
+
83
+ def seq_number: () -> untyped
84
+
85
+ def to_icmp: () -> untyped
86
+
87
+ def type: () -> untyped
88
+
89
+ private
90
+
91
+ def initialize: (untyped mesg) -> untyped
92
+ end
93
+
94
+ SimplePing::VERSION: String
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_ping
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akira Kure
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-26 00:00:00.000000000 Z
11
+ date: 2021-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -61,6 +61,7 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - ".gitignore"
63
63
  - ".rspec"
64
+ - ".ruby-version"
64
65
  - ".travis.yml"
65
66
  - CODE_OF_CONDUCT.md
66
67
  - Gemfile
@@ -69,14 +70,12 @@ files:
69
70
  - Rakefile
70
71
  - bin/console
71
72
  - bin/setup
72
- - client.rb
73
- - icmp.rb
74
73
  - lib/simple_ping.rb
75
74
  - lib/simple_ping/client.rb
76
75
  - lib/simple_ping/icmp.rb
77
76
  - lib/simple_ping/recv_message.rb
78
77
  - lib/simple_ping/version.rb
79
- - recv_message.rb
78
+ - sig/simple_ping.rbs
80
79
  - simple_ping.gemspec
81
80
  homepage: https://github.com/kuredev/simple_ping
82
81
  licenses:
@@ -84,7 +83,7 @@ licenses:
84
83
  metadata:
85
84
  homepage_uri: https://github.com/kuredev/simple_ping
86
85
  source_code_uri: https://github.com/kuredev/simple_ping
87
- post_install_message:
86
+ post_install_message:
88
87
  rdoc_options: []
89
88
  require_paths:
90
89
  - lib
@@ -99,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
98
  - !ruby/object:Gem::Version
100
99
  version: '0'
101
100
  requirements: []
102
- rubygems_version: 3.0.3
103
- signing_key:
101
+ rubygems_version: 3.2.3
102
+ signing_key:
104
103
  specification_version: 4
105
104
  summary: A Simpe Ping Client for Ruby.
106
105
  test_files: []
data/client.rb DELETED
@@ -1,91 +0,0 @@
1
- require "logger"
2
- require "socket"
3
- require "timeout"
4
- require_relative "recv_message"
5
- require_relative "icmp"
6
-
7
- # Simple Ping (ICMP) client
8
- # Root privilege required to run
9
- # ex)
10
- # require_relative "./simple_ping/client"
11
- #
12
- # client = SimplePing::Client.new(src_ip_addr: "192.168.1.100")
13
- # client.exec(dest_ip_addr: "192.168.1.101") # => true or false
14
- module SimplePing
15
- class Client
16
- # Wait time for ICMP Reply
17
- TIMEOUT_TIME = 10
18
-
19
- # constructor
20
- #
21
- # @param src_ip_addr [String] IP address of the interface to send ping, ex: "192.168.1.100"
22
- def initialize(src_ip_addr:, log_level: Logger::INFO)
23
- @src_ip_addr = src_ip_addr
24
- @log_level = log_level
25
- end
26
-
27
- # Execute ping(ICMP).
28
- # Basically, it returns Boolean depending on the result.
29
- # Exception may be thrown due to unexpected error etc.
30
- #
31
- # @param dest_ip_addr [String] IP address of destination to send ping, ex: "192.168.1.101"
32
- # @param data [String] ICMP Datagram, ex: "abc"
33
- # @return [Boolean]
34
- def exec(dest_ip_addr:, data: nil)
35
- # Transmission
36
- icmp = ICMP.new(type: ICMP::TYPE_ICMP_ECHO_REQUEST, data: data)
37
- sockaddr = Socket.sockaddr_in(nil, dest_ip_addr)
38
- trans_data = icmp.to_trans_data
39
- socket.send(trans_data, 0, sockaddr)
40
-
41
- # Receive
42
- begin
43
- Timeout.timeout(TIMEOUT_TIME) do
44
- loop do
45
- mesg, _ = socket.recvfrom(1500)
46
- icmp_reply = RecvMessage.new(mesg).to_icmp
47
-
48
- if icmp.successful_reply?(icmp_reply)
49
- return true
50
- elsif icmp_reply.is_type_destination_unreachable?
51
- logger.warn { "Destination Unreachable!!" }
52
- return false
53
- elsif icmp_reply.is_type_redirect?
54
- logger.warn { "Redirect Required!!" }
55
- return false
56
- end
57
- end
58
- end
59
- rescue Timeout::Error => e
60
- logger.warn { "Timeout Occurred! #{e}" }
61
- false
62
- end
63
- end
64
-
65
- private
66
-
67
- # @return [Logger]
68
- def logger
69
- @logger ||= begin
70
- logger = Logger.new(STDOUT)
71
- logger.level = @log_level
72
- logger
73
- end
74
- end
75
-
76
- # Socket instance
77
- #
78
- # @return [Socket]
79
- def socket
80
- @socket ||= begin
81
- socket = Socket.open(
82
- Socket::AF_INET, # IPv4
83
- Socket::SOCK_RAW, # RAW Socket
84
- Socket::IPPROTO_ICMP # ICMP
85
- )
86
- socket.bind(Socket.sockaddr_in(nil, @src_ip_addr))
87
- socket
88
- end
89
- end
90
- end
91
- end
data/icmp.rb DELETED
@@ -1,132 +0,0 @@
1
- module SimplePing
2
- class ICMP
3
- attr_accessor :id, :seq_number, :data, :type
4
-
5
- # ICMP TYPES
6
- TYPE_ICMP_ECHO_REPLY = 0x00
7
- TYPE_ICMP_DESTINATION_UNREACHABLE = 0x03
8
- TYPE_ICMP_REDIRECT = 0x05
9
- TYPE_ICMP_ECHO_REQUEST = 0x08
10
-
11
- # constructor
12
- #
13
- # @param code [Integer] 0x01
14
- # @param type [Integer] 0x01
15
- # @param id [Integer] 0x01
16
- # @param seq_number [Integer] 0x01
17
- # @param data [String] 0x01
18
- def initialize(type:, code: 0, id: nil, seq_number: nil, data: nil)
19
- @type = type
20
- @code = code
21
- @id = id || gen_id
22
- @seq_number = seq_number || gen_seq_number
23
- @data = data || gen_data
24
- @checksum = checksum
25
- end
26
-
27
- # @return [Boolean]
28
- def is_type_redirect?
29
- @type == TYPE_ICMP_REDIRECT
30
- end
31
-
32
- # @return [Boolean]
33
- def is_type_echo?
34
- @type == TYPE_ICMP_ECHO_REPLY || @type == TYPE_ICMP_ECHO_REQUEST
35
- end
36
-
37
- # @return [Boolean]
38
- def is_type_echo_reply?
39
- @type == TYPE_ICMP_ECHO_REPLY
40
- end
41
-
42
- # @return [Boolean]
43
- def is_type_destination_unreachable?
44
- @type == TYPE_ICMP_DESTINATION_UNREACHABLE
45
- end
46
-
47
- # Whether the argument ICMP is a reply of this ICMP
48
- #
49
- # @param [ICMP]
50
- # @return [Boolean]
51
- def successful_reply?(icmp)
52
- icmp.id == @id && icmp.seq_number == @seq_number && icmp.is_type_echo_reply?
53
- end
54
-
55
- # Return the data format for sending with the Socket::send method
56
- #
57
- # @return [String]
58
- def to_trans_data
59
- bynary_data =
60
- @type.to_s(2).rjust(8, "0") +
61
- @code.to_s(2).rjust(8, "0") +
62
- @checksum.to_s(2).rjust(16, "0") +
63
- @id.to_s(2).rjust(16, "0") +
64
- @seq_number.to_s(2).rjust(16, "0")
65
-
66
- data_byte_arr = bynary_data.scan(/.{1,8}/)
67
- data_byte_arr.map! { |byte| byte.to_i(2).chr }
68
- data_byte_arr.join + @data
69
- end
70
-
71
- private
72
-
73
- # Calculate carry in 16bit
74
- # memo: https://qiita.com/kure/items/fa7e665c2259375d9a81
75
- #
76
- # @param num [String] ex: "11001100110100011"
77
- # @return [Integer]
78
- def carry_up(num)
79
- carry_up_num = num.length - 16
80
- original_value = num[carry_up_num, 16]
81
- carry_up_value = num[0, carry_up_num]
82
- sum = original_value.to_i(2) + carry_up_value&.to_i(2)
83
- sum ^ 0xffff
84
- end
85
-
86
- # return checksum value
87
- # Calculate 1's complement sum for each 16 bits
88
- # memo: https://qiita.com/kure/items/fa7e665c2259375d9a81
89
- #
90
- # @return [Integer]
91
- def checksum
92
- # Divide into 16 bits
93
- # ex: ["pi", "ng"]
94
- data_arr = @data.scan(/.{1,2}/)
95
- # Calculate each ASCII code
96
- # ex: [28777, 28263]
97
- data_arr_int = data_arr.map do |data|
98
- (data.bytes[0] << 8) + (data.bytes[1].nil? ? 0 : data.bytes[1])
99
- end
100
- data_sum = data_arr_int.sum
101
-
102
- sum_with_16bit = (@type << 8 + @code) + @id + @seq_number + data_sum
103
-
104
- # calculate carry
105
- carry_up(sum_with_16bit.to_s(2).rjust(16, "0"))
106
- end
107
-
108
- # generate data
109
- #
110
- # TODO: random
111
- # @return [String]
112
- def gen_data
113
- "abcd"
114
- end
115
-
116
- # generate ID
117
- #
118
- # TODO: random
119
- # @return [Integer]
120
- def gen_id
121
- 0x01
122
- end
123
-
124
- # generate sequence number
125
- #
126
- # TODO: random
127
- # @return [Integer]
128
- def gen_seq_number
129
- 0x00af
130
- end
131
- end
132
- end
@@ -1,60 +0,0 @@
1
- module SimplePing
2
- # Class that stores the received message
3
- # Implements a method to retrieve the ICMP header
4
- class RecvMessage
5
- # Code
6
- #
7
- # @return [Integer]
8
- def code
9
- @mesg[21].bytes[0]
10
- end
11
-
12
- # ID
13
- #
14
- # @return [Integer]
15
- def id
16
- (@mesg[24].bytes[0] << 8) + @mesg[25].bytes[0]
17
- end
18
-
19
- # constructor
20
- #
21
- # @param [String] mesg
22
- def initialize(mesg)
23
- @mesg = mesg
24
- end
25
-
26
- # Data
27
- #
28
- # @return [String]
29
- def data
30
- @mesg[28, @mesg.length.to_i - 28]
31
- end
32
-
33
- # sequence numebr
34
- #
35
- # @return [Integer]
36
- def seq_number
37
- (@mesg[26].bytes[0] << 8) + @mesg[27].bytes[0]
38
- end
39
-
40
- # create icmp object
41
- #
42
- # @return [SimplePing::ICMP]
43
- def to_icmp
44
- icmp = ICMP.new(code: code, type: type)
45
- if icmp.is_type_echo?
46
- icmp.id = id
47
- icmp.seq_number = seq_number
48
- icmp.data = data
49
- end
50
- icmp
51
- end
52
-
53
- # Type
54
- #
55
- # @return [Integer]
56
- def type
57
- @mesg[20].bytes[0]
58
- end
59
- end
60
- end