i2p 0.1.4

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