i2p 0.1.4
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/AUTHORS +1 -0
- data/CONTRIBUTORS +0 -0
- data/README +155 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/lib/i2p.rb +177 -0
- data/lib/i2p/bob.rb +27 -0
- data/lib/i2p/bob/client.rb +489 -0
- data/lib/i2p/bob/tunnel.rb +303 -0
- data/lib/i2p/data/certificate.rb +75 -0
- data/lib/i2p/data/destination.rb +68 -0
- data/lib/i2p/data/key.rb +40 -0
- data/lib/i2p/data/key_pair.rb +65 -0
- data/lib/i2p/data/private_key.rb +14 -0
- data/lib/i2p/data/public_key.rb +14 -0
- data/lib/i2p/data/signing_private_key.rb +10 -0
- data/lib/i2p/data/signing_public_key.rb +10 -0
- data/lib/i2p/data/structure.rb +84 -0
- data/lib/i2p/hosts.rb +207 -0
- data/lib/i2p/sam.rb +40 -0
- data/lib/i2p/sam/client.rb +226 -0
- data/lib/i2p/sdk.jar +0 -0
- data/lib/i2p/sdk.rb +111 -0
- data/lib/i2p/streaming.jar +0 -0
- data/lib/i2p/streaming.rb +10 -0
- data/lib/i2p/version.rb +22 -0
- metadata +116 -0
@@ -0,0 +1,303 @@
|
|
1
|
+
module I2P; module BOB
|
2
|
+
##
|
3
|
+
# **I2P Basic Open Bridge (BOB) tunnel manager.**
|
4
|
+
#
|
5
|
+
# @example Creating and controlling a new tunnel
|
6
|
+
# I2P::BOB::Tunnel.new(...) do |tunnel|
|
7
|
+
# tunnel.start
|
8
|
+
# sleep 0.1 until tunnel.running?
|
9
|
+
# # ... code that uses the tunnel goes here ...
|
10
|
+
# tunnel.stop
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @example Starting a new inbound I2P tunnel in one go
|
14
|
+
# I2P::BOB::Tunnel.start({
|
15
|
+
# :nickname => :inproxy,
|
16
|
+
# :inhost => "127.0.0.1"
|
17
|
+
# :inport => 12345, # unused port
|
18
|
+
# })
|
19
|
+
#
|
20
|
+
# @example Starting a new outbound I2P tunnel in one go
|
21
|
+
# I2P::BOB::Tunnel.start({
|
22
|
+
# :nickname => :myssh,
|
23
|
+
# :outhost => "127.0.0.1",
|
24
|
+
# :outport => 22, # SSH port
|
25
|
+
# })
|
26
|
+
#
|
27
|
+
# @example Starting an existing tunnel
|
28
|
+
# I2P::BOB::Tunnel.start(:myssh)
|
29
|
+
#
|
30
|
+
# @example Obtaining the I2P destination for a tunnel
|
31
|
+
# tunnel = I2P::BOB::Tunnel.start(:mytunnel)
|
32
|
+
# tunnel.destination #=> #<I2P::Destination:...>
|
33
|
+
#
|
34
|
+
# @example Stopping an existing tunnel
|
35
|
+
# I2P::BOB::Tunnel.stop(:myssh)
|
36
|
+
#
|
37
|
+
# @see http://www.i2p2.de/applications.html
|
38
|
+
# @see http://bob.i2p.to/bridge.html
|
39
|
+
# @since 0.1.4
|
40
|
+
class Tunnel
|
41
|
+
##
|
42
|
+
# Starts up a new tunnel.
|
43
|
+
#
|
44
|
+
# @param [Hash{Symbol => Object}] options
|
45
|
+
# @option options [String, #to_s] :nickname (Time.now.to_i)
|
46
|
+
# @option options [KeyPair, #to_s] :keys (nil)
|
47
|
+
# @option options [Boolean] :quiet (false)
|
48
|
+
# @option options [String, #to_s] :inhost ("localhost")
|
49
|
+
# @option options [Integer, #to_i] :inport (nil)
|
50
|
+
# @option options [String, #to_s] :outhost ("localhost")
|
51
|
+
# @option options [Integer, #to_i] :outport (nil)
|
52
|
+
# @return [Tunnel]
|
53
|
+
def self.start(options = {}, &block)
|
54
|
+
tunnel = self.new(options).start
|
55
|
+
|
56
|
+
if block_given?
|
57
|
+
begin
|
58
|
+
result = block.call(tunnel)
|
59
|
+
ensure
|
60
|
+
tunnel.stop
|
61
|
+
end
|
62
|
+
result
|
63
|
+
else
|
64
|
+
tunnel
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Shuts down an existing tunnel of the given `nickname`.
|
70
|
+
#
|
71
|
+
# @param [String, #to_s]
|
72
|
+
# @return [void]
|
73
|
+
def self.stop(nickname)
|
74
|
+
self.new(nickname).stop
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Initializes a new tunnel instance.
|
79
|
+
#
|
80
|
+
# @overload initialize(options = {})
|
81
|
+
# @param [Hash{Symbol => Object}] options
|
82
|
+
# @option options [String, #to_s] :nickname (Time.now.to_i)
|
83
|
+
# @option options [KeyPair, #to_s] :keys (nil)
|
84
|
+
# @option options [Boolean] :quiet (false)
|
85
|
+
# @option options [String, #to_s] :inhost ("localhost")
|
86
|
+
# @option options [Integer, #to_i] :inport (nil)
|
87
|
+
# @option options [String, #to_s] :outhost ("localhost")
|
88
|
+
# @option options [Integer, #to_i] :outport (nil)
|
89
|
+
#
|
90
|
+
# @overload initialize(nickname)
|
91
|
+
# @param [String, #to_s] nickname
|
92
|
+
#
|
93
|
+
def initialize(options = {})
|
94
|
+
case options
|
95
|
+
when Hash
|
96
|
+
# Create a new tunnel
|
97
|
+
@nickname = options[:nickname] || Time.now.to_i.to_s
|
98
|
+
@debug = options[:debug]
|
99
|
+
setup(options)
|
100
|
+
else
|
101
|
+
# Access an existing tunnel
|
102
|
+
@nickname = options.to_s
|
103
|
+
Client.open { |client| client.getnick(@nickname) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Returns the nickname for this tunnel.
|
109
|
+
#
|
110
|
+
# @return [String]
|
111
|
+
# @see Client#getnick
|
112
|
+
attr_reader :nickname
|
113
|
+
|
114
|
+
##
|
115
|
+
# Returns the I2P {I2P::Destination destination} for this tunnel.
|
116
|
+
#
|
117
|
+
# @return [Destination]
|
118
|
+
# @see Client#getdest
|
119
|
+
attr_reader :destination
|
120
|
+
def destination
|
121
|
+
@destination ||= client { getdest }
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Returns the I2P {I2P::KeyPair key pair} for this tunnel.
|
126
|
+
#
|
127
|
+
# @return [KeyPair]
|
128
|
+
# @see Client#getkeys
|
129
|
+
attr_reader :keys
|
130
|
+
def keys
|
131
|
+
@keys ||= client { getkeys }
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# Returns `true` if this is an inbound tunnel.
|
136
|
+
#
|
137
|
+
# @return [Boolean]
|
138
|
+
def inbound?
|
139
|
+
!!inport
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Returns the inbound host name or IP address for this tunnel.
|
144
|
+
#
|
145
|
+
# @return [String]
|
146
|
+
# @see Client#inhost
|
147
|
+
attr_reader :inhost
|
148
|
+
def inhost
|
149
|
+
@inhost ||= begin
|
150
|
+
nil # TODO
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# Returns the inbound port number for this tunnel.
|
156
|
+
#
|
157
|
+
# @return [Integer]
|
158
|
+
# @see Client#inport
|
159
|
+
attr_reader :inport
|
160
|
+
def inport
|
161
|
+
@inport ||= begin
|
162
|
+
nil # TODO
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Returns `true` if this is an outbound tunnel.
|
168
|
+
#
|
169
|
+
# @return [Boolean]
|
170
|
+
def outbound?
|
171
|
+
!!outport
|
172
|
+
end
|
173
|
+
|
174
|
+
##
|
175
|
+
# Returns the outbound host name or IP address for this tunnel.
|
176
|
+
#
|
177
|
+
# @return [String]
|
178
|
+
# @see Client#outhost
|
179
|
+
attr_reader :outhost
|
180
|
+
def outhost
|
181
|
+
@outhost ||= begin
|
182
|
+
nil # TODO
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Returns the outbound port number for this tunnel.
|
188
|
+
#
|
189
|
+
# @return [Integer]
|
190
|
+
# @see Client#outport
|
191
|
+
attr_reader :outport
|
192
|
+
def outport
|
193
|
+
@outport ||= begin
|
194
|
+
nil # TODO
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Returns `true` if quiet mode is enabled for this tunnel.
|
200
|
+
#
|
201
|
+
# This only applies to outbound tunnels and has no effect on inbound
|
202
|
+
# tunnels.
|
203
|
+
#
|
204
|
+
# @return [Boolean]
|
205
|
+
# @see Client#quiet
|
206
|
+
def quiet?
|
207
|
+
@quiet ||= begin
|
208
|
+
nil # TODO
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
##
|
213
|
+
# Registers the given tunnel `options` with the BOB bridge.
|
214
|
+
#
|
215
|
+
# @param [Hash{Symbol => Object}] options
|
216
|
+
# @return [void]
|
217
|
+
def setup(options = {})
|
218
|
+
client do |client|
|
219
|
+
if options[:keys]
|
220
|
+
client.setkeys(options[:keys])
|
221
|
+
else
|
222
|
+
begin
|
223
|
+
client.getkeys
|
224
|
+
rescue Error => e
|
225
|
+
client.newkeys
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
client.quiet(options[:quiet]) if options[:quiet]
|
230
|
+
client.inhost(options[:inhost]) if options[:inhost]
|
231
|
+
client.inport(options[:inport]) if options[:inport]
|
232
|
+
client.outhost(options[:outhost]) if options[:outhost]
|
233
|
+
client.outport(options[:outport]) if options[:outport]
|
234
|
+
end
|
235
|
+
self
|
236
|
+
end
|
237
|
+
alias_method :setup!, :setup
|
238
|
+
|
239
|
+
##
|
240
|
+
# Returns `true` if this tunnel is currently active.
|
241
|
+
#
|
242
|
+
# @return [Boolean]
|
243
|
+
def running?
|
244
|
+
true # FIXME
|
245
|
+
end
|
246
|
+
alias_method :active?, :running?
|
247
|
+
|
248
|
+
##
|
249
|
+
# Starts up this tunnel.
|
250
|
+
#
|
251
|
+
# @return [void]
|
252
|
+
# @see Client#start
|
253
|
+
def start
|
254
|
+
client { start }
|
255
|
+
self
|
256
|
+
end
|
257
|
+
alias_method :start!, :start
|
258
|
+
|
259
|
+
##
|
260
|
+
# Returns `true` if this tunnel is currently in the process of starting
|
261
|
+
# up.
|
262
|
+
#
|
263
|
+
# @return [Boolean]
|
264
|
+
def starting?
|
265
|
+
# TODO
|
266
|
+
end
|
267
|
+
|
268
|
+
##
|
269
|
+
# Shuts down this tunnel.
|
270
|
+
#
|
271
|
+
# @return [void]
|
272
|
+
# @see Client#stop
|
273
|
+
def stop
|
274
|
+
client { stop }
|
275
|
+
self
|
276
|
+
end
|
277
|
+
alias_method :stop!, :stop
|
278
|
+
|
279
|
+
##
|
280
|
+
# Returns `true` if this tunnel is currently in the process of shutting
|
281
|
+
# down.
|
282
|
+
#
|
283
|
+
# @return [Boolean]
|
284
|
+
def stopping?
|
285
|
+
# TODO
|
286
|
+
end
|
287
|
+
|
288
|
+
def socket
|
289
|
+
client.socket
|
290
|
+
end
|
291
|
+
|
292
|
+
##
|
293
|
+
# Returns a {I2P::BOB::Client} instance for accessing low-level
|
294
|
+
# information about this tunnel.
|
295
|
+
#
|
296
|
+
# @yield [client]
|
297
|
+
# @yieldparam [Client] client
|
298
|
+
# @return [Client]
|
299
|
+
def client(&block)
|
300
|
+
Client.open(:nickname => nickname, :debug => @debug, &block)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end; end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module I2P
|
2
|
+
##
|
3
|
+
# **I2P certificate data structure.**
|
4
|
+
#
|
5
|
+
# Defines a certificate that can be attached to various I2P structures,
|
6
|
+
# such as `RouterIdentity` and `Destination`, allowing routers and clients
|
7
|
+
# to help manage denial of service attacks and the network utilization.
|
8
|
+
#
|
9
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/Certificate.html
|
10
|
+
# @since 0.1.3
|
11
|
+
class Certificate < Structure
|
12
|
+
TYPE_NULL = 0 # Null certificate
|
13
|
+
TYPE_HASHCASH = 1 # Hashcash certificate
|
14
|
+
TYPE_HIDDEN = 2 # Hidden certificate
|
15
|
+
TYPE_SIGNED = 3 # Signed certificate
|
16
|
+
TYPE_MULTIPLE = 4
|
17
|
+
|
18
|
+
LENGTH_SIGNED_WITH_HASH = nil # TODO
|
19
|
+
|
20
|
+
##
|
21
|
+
# Reads a certificate from the given `input` stream.
|
22
|
+
#
|
23
|
+
# @param [IO, StringIO] input
|
24
|
+
# @return [Certificate]
|
25
|
+
def self.read(input)
|
26
|
+
type = input.read(1).unpack('c').first
|
27
|
+
length = input.read(2).unpack('n').first
|
28
|
+
payload = length.zero? ? String.new : input.read(length)
|
29
|
+
self.new(type, payload)
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# @return [Integer]
|
34
|
+
attr_accessor :type
|
35
|
+
|
36
|
+
##
|
37
|
+
# @return [String]
|
38
|
+
attr_accessor :payload
|
39
|
+
|
40
|
+
##
|
41
|
+
# Initializes a new certificate instance.
|
42
|
+
#
|
43
|
+
# @param [Integer, #to_i] type
|
44
|
+
# @param [String, #to_s] payload
|
45
|
+
def initialize(type = TYPE_NULL, payload = String.new)
|
46
|
+
@type, @payload = type.to_i, payload
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Returns the byte size of this certificate.
|
51
|
+
#
|
52
|
+
# @return [Integer]
|
53
|
+
def size
|
54
|
+
1 + 2 + (payload ? payload.size : 0)
|
55
|
+
end
|
56
|
+
alias_method :bytesize, :size
|
57
|
+
|
58
|
+
##
|
59
|
+
# Returns the binary string representation of this certificate.
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
def to_s
|
63
|
+
StringIO.open do |buffer|
|
64
|
+
buffer.write([type].pack('c'))
|
65
|
+
if payload && !payload.empty?
|
66
|
+
buffer.write([payload.size].pack('n'))
|
67
|
+
buffer.write(payload.to_s)
|
68
|
+
else
|
69
|
+
buffer.write([0].pack('n'))
|
70
|
+
end
|
71
|
+
buffer.string
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module I2P
|
2
|
+
##
|
3
|
+
# **I2P destination data structure.**
|
4
|
+
#
|
5
|
+
# Defines an endpoint in the I2P network. The destination may move around
|
6
|
+
# in the network, but messages sent to the destination will reach it.
|
7
|
+
#
|
8
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/Destination.html
|
9
|
+
# @since 0.1.3
|
10
|
+
class Destination < Structure
|
11
|
+
BYTESIZE = 387 # minimum
|
12
|
+
|
13
|
+
##
|
14
|
+
# Reads a destination from the given `input` stream.
|
15
|
+
#
|
16
|
+
# @param [IO, StringIO] input
|
17
|
+
# @return [Destination]
|
18
|
+
def self.read(input)
|
19
|
+
self.new(PublicKey.read(input), SigningPublicKey.read(input), Certificate.read(input))
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Initializes a new destination instance.
|
24
|
+
#
|
25
|
+
# @param [PublicKey] public_key
|
26
|
+
# @param [SigningPublicKey] signing_key
|
27
|
+
# @param [Certificate] certificate
|
28
|
+
def initialize(public_key, signing_key, certificate = Certificate.new)
|
29
|
+
@public_key = public_key
|
30
|
+
@signing_key = signing_key
|
31
|
+
@certificate = certificate
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# @return [PublicKey]
|
36
|
+
attr_accessor :public_key
|
37
|
+
|
38
|
+
##
|
39
|
+
# @return [SigningPublicKey]
|
40
|
+
attr_accessor :signing_key
|
41
|
+
|
42
|
+
##
|
43
|
+
# @return [Certificate]
|
44
|
+
attr_accessor :certificate
|
45
|
+
|
46
|
+
##
|
47
|
+
# Returns the byte size of this data structure.
|
48
|
+
#
|
49
|
+
# @return [Integer]
|
50
|
+
def size
|
51
|
+
public_key.size + signing_key.size + certificate.size
|
52
|
+
end
|
53
|
+
alias_method :bytesize, :size
|
54
|
+
|
55
|
+
##
|
56
|
+
# Returns the binary string representation of this destination.
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
def to_s
|
60
|
+
StringIO.open do |buffer|
|
61
|
+
buffer.write(public_key.to_s)
|
62
|
+
buffer.write(signing_key.to_s)
|
63
|
+
buffer.write(certificate.to_s)
|
64
|
+
buffer.string
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/i2p/data/key.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module I2P
|
2
|
+
##
|
3
|
+
class Key < Structure
|
4
|
+
##
|
5
|
+
# Reads a key data structure from the given `input` stream.
|
6
|
+
#
|
7
|
+
# @param [IO, StringIO] input
|
8
|
+
# @return [Key]
|
9
|
+
def self.read(input)
|
10
|
+
self.new(input.read(const_get(:BYTESIZE)))
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :data
|
16
|
+
|
17
|
+
##
|
18
|
+
# @param [String] data
|
19
|
+
def initialize(data)
|
20
|
+
@data = data.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Returns `true` if this key is of the correct size.
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
# @since 0.1.3
|
28
|
+
def valid?
|
29
|
+
@data.size.eql?(self.class.const_get(:BYTESIZE))
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Returns the binary string representation of this key.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
def to_s
|
37
|
+
@data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|