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,226 @@
|
|
1
|
+
module I2P; module SAM
|
2
|
+
##
|
3
|
+
# **I2P Simple Anonymous Messaging (SAM) V3 client.**
|
4
|
+
#
|
5
|
+
# @example Connecting to the I2P SAM bridge (1)
|
6
|
+
# sam = I2P::SAM::Client.new(:port => 7656)
|
7
|
+
#
|
8
|
+
# @example Connecting to the I2P SAM bridge (2)
|
9
|
+
# I2P::SAM::Client.open(:port => 7656) do |sam|
|
10
|
+
# ...
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @see http://www.i2p2.de/applications.html
|
14
|
+
# @see http://www.i2p2.de/samv3.html
|
15
|
+
class Client
|
16
|
+
##
|
17
|
+
# Establishes a connection to the SAM bridge.
|
18
|
+
#
|
19
|
+
# @example Connecting to the default port
|
20
|
+
# sam = I2P::SAM::Client.open
|
21
|
+
#
|
22
|
+
# @example Connecting to the given port
|
23
|
+
# sam = I2P::SAM::Client.open(:port => 7656)
|
24
|
+
#
|
25
|
+
# @param [Hash{Symbol => Object}] options
|
26
|
+
# @option options [String, #to_s] :host (DEFAULT_HOST)
|
27
|
+
# @option options [Integer, #to_i] :port (DEFAULT_PORT)
|
28
|
+
# @option options [Integer, #to_i] :version (PROTOCOL_VERSION)
|
29
|
+
# @yield [client]
|
30
|
+
# @yieldparam [Client] client
|
31
|
+
# @return [void]
|
32
|
+
def self.open(options = {}, &block)
|
33
|
+
client = self.new(options)
|
34
|
+
client.connect.hello # handshake
|
35
|
+
|
36
|
+
unless block_given?
|
37
|
+
client
|
38
|
+
else
|
39
|
+
begin
|
40
|
+
result = block.call(client)
|
41
|
+
ensure
|
42
|
+
client.disconnect
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Returns the socket connection to the SAM bridge.
|
50
|
+
#
|
51
|
+
# @return [TCPSocket]
|
52
|
+
attr_reader :socket
|
53
|
+
|
54
|
+
##
|
55
|
+
# Initializes a new client instance.
|
56
|
+
#
|
57
|
+
# @param [Hash{Symbol => Object}] options
|
58
|
+
# @option options [String, #to_s] :host (DEFAULT_HOST)
|
59
|
+
# @option options [Integer, #to_i] :port (DEFAULT_PORT)
|
60
|
+
# @option options [Integer, #to_i] :version (PROTOCOL_VERSION)
|
61
|
+
# @yield [client]
|
62
|
+
# @yieldparam [Client] client
|
63
|
+
def initialize(options = {}, &block)
|
64
|
+
@options = options.dup
|
65
|
+
@host = (@options.delete(:host) || DEFAULT_HOST).to_s
|
66
|
+
@port = (@options.delete(:port) || DEFAULT_PORT).to_i
|
67
|
+
@version = (@options.delete(:version) || PROTOCOL_VERSION).to_i
|
68
|
+
|
69
|
+
block.call(self) if block_given?
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Returns `true` if a connection to the SAM bridge has been established
|
74
|
+
# and is active.
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# sam.connected? #=> true
|
78
|
+
# sam.disconnect
|
79
|
+
# sam.connected? #=> false
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
def connected?
|
83
|
+
!!@socket
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Establishes a connection to the SAM bridge.
|
88
|
+
#
|
89
|
+
# If called after the connection has already been established,
|
90
|
+
# disconnects and then reconnects to the bridge.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# sam.connect
|
94
|
+
#
|
95
|
+
# @return [void]
|
96
|
+
def connect
|
97
|
+
disconnect if connected?
|
98
|
+
@socket = TCPSocket.new(@host, @port)
|
99
|
+
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
100
|
+
self
|
101
|
+
end
|
102
|
+
alias_method :reconnect, :connect
|
103
|
+
|
104
|
+
##
|
105
|
+
# Closes the connection to the SAM bridge.
|
106
|
+
#
|
107
|
+
# If called after the connection has already been closed, does nothing.
|
108
|
+
#
|
109
|
+
# @example
|
110
|
+
# sam.disconnect
|
111
|
+
#
|
112
|
+
# @return [void]
|
113
|
+
def disconnect
|
114
|
+
@socket.close if @socket && !@socket.closed?
|
115
|
+
@socket = nil
|
116
|
+
self
|
117
|
+
end
|
118
|
+
alias_method :close, :disconnect
|
119
|
+
|
120
|
+
##
|
121
|
+
# Performs the SAM protocol handshake and returns the autonegotiated
|
122
|
+
# protocol version.
|
123
|
+
#
|
124
|
+
# @example
|
125
|
+
# sam.hello #=> 3.0
|
126
|
+
#
|
127
|
+
# @example
|
128
|
+
# sam.hello(:min => 3.0, :max => 4.0) #=> 3.0
|
129
|
+
#
|
130
|
+
# @param [Hash{Symbol => Object}] options
|
131
|
+
# @option options [Float, #to_f] :min (PROTOCOL_VERSION)
|
132
|
+
# @option options [Float, #to_f] :max (PROTOCOL_VERSION)
|
133
|
+
# @return [Float]
|
134
|
+
# @raise [ProtocolNotSupported] if the handshake failed
|
135
|
+
def hello(options = {})
|
136
|
+
send_msg(:hello, :version, {
|
137
|
+
:min => '%.1f' % (options[:min] || @version).to_f,
|
138
|
+
:max => '%.1f' % (options[:max] || @version).to_f,
|
139
|
+
})
|
140
|
+
read_reply[:version].to_f
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Returns the I2P destination corresponding to `name`.
|
145
|
+
#
|
146
|
+
# @example
|
147
|
+
# sam.lookup_name("forum.i2p") #=> #<I2P::Destination:...>
|
148
|
+
#
|
149
|
+
# @param [String, #to_s] name
|
150
|
+
# @return [Destination]
|
151
|
+
# @raise [Error::KeyNotFound] if `name` was not found
|
152
|
+
def lookup_name(name)
|
153
|
+
send_msg(:naming, :lookup, :name => name.to_s)
|
154
|
+
Destination.parse(read_reply[:value])
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Generates a new I2P destination and returns the key pair for it.
|
159
|
+
#
|
160
|
+
# @example
|
161
|
+
# key_pair = sam.generate_dest
|
162
|
+
#
|
163
|
+
# @return [KeyPair]
|
164
|
+
def generate_dest
|
165
|
+
send_msg(:dest, :generate)
|
166
|
+
KeyPair.parse(read_reply[:priv])
|
167
|
+
end
|
168
|
+
alias_method :generate_destination, :generate_dest
|
169
|
+
|
170
|
+
protected
|
171
|
+
|
172
|
+
##
|
173
|
+
# Sends a message to the SAM bridge.
|
174
|
+
#
|
175
|
+
# @param [Symbol, #to_s] noun
|
176
|
+
# @param [Symbol, #to_s] verb
|
177
|
+
# @param [Hash{Symbol => Object}] options
|
178
|
+
# @return [void]
|
179
|
+
def send_msg(noun, verb, options = {})
|
180
|
+
msg = [noun.to_s.upcase, verb.to_s.upcase]
|
181
|
+
msg += options.map { |k, v| "#{k.to_s.upcase}=#{v}" } unless options.empty?
|
182
|
+
send_line(msg.join(' '))
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Sends a text line over the SAM bridge socket.
|
188
|
+
#
|
189
|
+
# @param [String, #to_s] line
|
190
|
+
# @return [void]
|
191
|
+
def send_line(line)
|
192
|
+
connect unless connected?
|
193
|
+
warn "-> #{line}" if @options[:debug]
|
194
|
+
@socket.write(line.to_s + "\n")
|
195
|
+
@socket.flush
|
196
|
+
self
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Reads a reply line from the SAM bridge socket.
|
201
|
+
#
|
202
|
+
# @return [String]
|
203
|
+
def read_reply
|
204
|
+
reply = @socket.readline.chomp
|
205
|
+
warn "<- #{reply}" if @options[:debug]
|
206
|
+
case reply
|
207
|
+
when /^HELLO REPLY RESULT=OK VERSION=(\S*)/
|
208
|
+
{:version => $1}
|
209
|
+
when /^HELLO REPLY RESULT=NOVERSION/
|
210
|
+
raise Error::ProtocolNotSupported.new("SAM bridge does not support the requested protocol version")
|
211
|
+
when /^HELLO REPLY RESULT=I2P_ERROR MESSAGE="([^"]+)"/
|
212
|
+
raise Error.new($1.strip)
|
213
|
+
when /^NAMING REPLY RESULT=OK NAME=(\S+) VALUE=(\S+)/
|
214
|
+
{:name => $1, :value => $2}
|
215
|
+
when /^NAMING REPLY RESULT=INVALID_KEY NAME=(\S+)/
|
216
|
+
raise Error::KeyNotValid.new($1)
|
217
|
+
when /^NAMING REPLY RESULT=KEY_NOT_FOUND NAME=(\S+)/
|
218
|
+
raise Error::KeyNotFound.new($1)
|
219
|
+
when /^DEST REPLY PUB=(\S+) PRIV=(\S+)/
|
220
|
+
{:pub => $1, :priv => $2}
|
221
|
+
else
|
222
|
+
raise Error.new(reply)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end; end
|
data/lib/i2p/sdk.jar
ADDED
Binary file
|
data/lib/i2p/sdk.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'i2p'
|
3
|
+
require 'i2p.jar'
|
4
|
+
|
5
|
+
module I2P
|
6
|
+
##
|
7
|
+
# @since 0.1.3
|
8
|
+
module SDK
|
9
|
+
import 'net.i2p'
|
10
|
+
import 'net.i2p.client'
|
11
|
+
import 'net.i2p.client.datagram'
|
12
|
+
import 'net.i2p.client.naming'
|
13
|
+
import 'net.i2p.crypto'
|
14
|
+
import 'net.i2p.data'
|
15
|
+
import 'net.i2p.data.i2cp'
|
16
|
+
import 'net.i2p.stat'
|
17
|
+
import 'net.i2p.time'
|
18
|
+
import 'net.i2p.util'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class I2P::Certificate
|
23
|
+
##
|
24
|
+
# Returns an instance of the Java class `net.i2p.data.Certificate`.
|
25
|
+
#
|
26
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
27
|
+
#
|
28
|
+
# @return [Object]
|
29
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/Certificate.html
|
30
|
+
def to_java
|
31
|
+
I2P::SDK::Certificate.new(type.to_i, payload.to_s.to_java_bytes)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class I2P::PrivateKey
|
36
|
+
##
|
37
|
+
# Returns an instance of the Java class `net.i2p.data.PrivateKey`.
|
38
|
+
#
|
39
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
40
|
+
#
|
41
|
+
# @return [Object]
|
42
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/PrivateKey.html
|
43
|
+
def to_java
|
44
|
+
I2P::SDK::PrivateKey.new(to_s.to_java_bytes)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class I2P::SigningPrivateKey
|
49
|
+
##
|
50
|
+
# Returns an instance of the Java class `net.i2p.data.SigningPrivateKey`.
|
51
|
+
#
|
52
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
53
|
+
#
|
54
|
+
# @return [Object]
|
55
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/SigningPrivateKey.html
|
56
|
+
def to_java
|
57
|
+
I2P::SDK::SigningPrivateKey.new(to_s.to_java_bytes)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class I2P::PublicKey
|
62
|
+
##
|
63
|
+
# Returns an instance of the Java class `net.i2p.data.PublicKey`.
|
64
|
+
#
|
65
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
66
|
+
#
|
67
|
+
# @return [Object]
|
68
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/PublicKey.html
|
69
|
+
def to_java
|
70
|
+
I2P::SDK::PublicKey.new(to_s.to_java_bytes)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class I2P::SigningPublicKey
|
75
|
+
##
|
76
|
+
# Returns an instance of the Java class `net.i2p.data.SigningPublicKey`.
|
77
|
+
#
|
78
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
79
|
+
#
|
80
|
+
# @return [Object]
|
81
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/SigningPublicKey.html
|
82
|
+
def to_java
|
83
|
+
I2P::SDK::SigningPublicKey.new(to_s.to_java_bytes)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class I2P::Destination
|
88
|
+
##
|
89
|
+
# Returns an instance of the Java class `net.i2p.data.Destination`.
|
90
|
+
#
|
91
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
92
|
+
#
|
93
|
+
# @return [Object]
|
94
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/Destination.html
|
95
|
+
def to_java
|
96
|
+
I2P::SDK::Destination.new(to_base64)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class I2P::KeyPair
|
101
|
+
##
|
102
|
+
# Returns an instance of the Java class `net.i2p.data.PrivateKeyFile`.
|
103
|
+
#
|
104
|
+
# **This method only works with JRuby, not with MRI or YARV.**
|
105
|
+
#
|
106
|
+
# @return [Object]
|
107
|
+
# @see http://docs.i2p2.de/core/net/i2p/data/PrivateKeyFile.html
|
108
|
+
def to_java
|
109
|
+
raise NotImplementedError.new("#{self.class}#to_java") # TODO
|
110
|
+
end
|
111
|
+
end
|
Binary file
|
data/lib/i2p/version.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module I2P
|
2
|
+
module VERSION
|
3
|
+
MAJOR = 0
|
4
|
+
MINOR = 1
|
5
|
+
TINY = 4
|
6
|
+
EXTRA = nil
|
7
|
+
|
8
|
+
STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
|
9
|
+
|
10
|
+
##
|
11
|
+
# @return [String]
|
12
|
+
def self.to_s() STRING end
|
13
|
+
|
14
|
+
##
|
15
|
+
# @return [String]
|
16
|
+
def self.to_str() STRING end
|
17
|
+
|
18
|
+
##
|
19
|
+
# @return [Array(Integer, Integer, Integer)]
|
20
|
+
def self.to_a() [MAJOR, MINOR, TINY] end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: i2p
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 4
|
9
|
+
version: 0.1.4
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Arto Bendiken
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-08-07 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: yard
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 5
|
30
|
+
- 8
|
31
|
+
version: 0.5.8
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rspec
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 1
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
version: 1.3.0
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
|
+
description: I2P.rb is a Ruby library for interacting with the I2P anonymity network.
|
49
|
+
email: i2p@i2p.net
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files: []
|
55
|
+
|
56
|
+
files:
|
57
|
+
- AUTHORS
|
58
|
+
- CONTRIBUTORS
|
59
|
+
- README
|
60
|
+
- UNLICENSE
|
61
|
+
- VERSION
|
62
|
+
- lib/i2p/bob/client.rb
|
63
|
+
- lib/i2p/bob/tunnel.rb
|
64
|
+
- lib/i2p/bob.rb
|
65
|
+
- lib/i2p/data/certificate.rb
|
66
|
+
- lib/i2p/data/destination.rb
|
67
|
+
- lib/i2p/data/key.rb
|
68
|
+
- lib/i2p/data/key_pair.rb
|
69
|
+
- lib/i2p/data/private_key.rb
|
70
|
+
- lib/i2p/data/public_key.rb
|
71
|
+
- lib/i2p/data/signing_private_key.rb
|
72
|
+
- lib/i2p/data/signing_public_key.rb
|
73
|
+
- lib/i2p/data/structure.rb
|
74
|
+
- lib/i2p/hosts.rb
|
75
|
+
- lib/i2p/sam/client.rb
|
76
|
+
- lib/i2p/sam.rb
|
77
|
+
- lib/i2p/sdk.rb
|
78
|
+
- lib/i2p/streaming.rb
|
79
|
+
- lib/i2p/version.rb
|
80
|
+
- lib/i2p.rb
|
81
|
+
- lib/i2p/sdk.jar
|
82
|
+
- lib/i2p/streaming.jar
|
83
|
+
has_rdoc: false
|
84
|
+
homepage: http://cypherpunk.rubyforge.org/i2p/
|
85
|
+
licenses:
|
86
|
+
- Public Domain
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 1
|
98
|
+
- 8
|
99
|
+
- 1
|
100
|
+
version: 1.8.1
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
version: "0"
|
108
|
+
requirements:
|
109
|
+
- I2P (>= 0.8)
|
110
|
+
rubyforge_project: cypherpunk
|
111
|
+
rubygems_version: 1.3.6
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Anonymous networking for Ruby.
|
115
|
+
test_files: []
|
116
|
+
|