torchat 0.0.1.rc.1

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.
Files changed (43) hide show
  1. data/README.md +43 -0
  2. data/bin/torchatd +537 -0
  3. data/doc/protocol/broadcast.md +26 -0
  4. data/doc/protocol/groupchat.md +140 -0
  5. data/doc/protocol/latency.md +30 -0
  6. data/doc/protocol/standard.md +279 -0
  7. data/doc/protocol/typing.md +41 -0
  8. data/etc/torchat.yml +12 -0
  9. data/lib/torchat.rb +239 -0
  10. data/lib/torchat/protocol.rb +256 -0
  11. data/lib/torchat/protocol/broadcast.rb +40 -0
  12. data/lib/torchat/protocol/groupchat.rb +197 -0
  13. data/lib/torchat/protocol/latency.rb +44 -0
  14. data/lib/torchat/protocol/standard.rb +367 -0
  15. data/lib/torchat/protocol/typing.rb +36 -0
  16. data/lib/torchat/session.rb +603 -0
  17. data/lib/torchat/session/broadcast/message.rb +50 -0
  18. data/lib/torchat/session/broadcasts.rb +72 -0
  19. data/lib/torchat/session/buddies.rb +152 -0
  20. data/lib/torchat/session/buddy.rb +343 -0
  21. data/lib/torchat/session/buddy/joined_group_chat.rb +42 -0
  22. data/lib/torchat/session/buddy/joined_group_chats.rb +46 -0
  23. data/lib/torchat/session/buddy/latency.rb +54 -0
  24. data/lib/torchat/session/event.rb +79 -0
  25. data/lib/torchat/session/file_transfer.rb +173 -0
  26. data/lib/torchat/session/file_transfer/block.rb +51 -0
  27. data/lib/torchat/session/file_transfers.rb +89 -0
  28. data/lib/torchat/session/group_chat.rb +123 -0
  29. data/lib/torchat/session/group_chat/participant.rb +38 -0
  30. data/lib/torchat/session/group_chat/participants.rb +52 -0
  31. data/lib/torchat/session/group_chats.rb +74 -0
  32. data/lib/torchat/session/incoming.rb +187 -0
  33. data/lib/torchat/session/outgoing.rb +102 -0
  34. data/lib/torchat/tor.rb +107 -0
  35. data/lib/torchat/utils.rb +87 -0
  36. data/lib/torchat/version.rb +24 -0
  37. data/test/file_transfer/receiver.rb +41 -0
  38. data/test/file_transfer/sender.rb +45 -0
  39. data/test/group_chat/a.rb +37 -0
  40. data/test/group_chat/b.rb +37 -0
  41. data/test/group_chat/c.rb +57 -0
  42. data/torchat.gemspec +21 -0
  43. metadata +140 -0
@@ -0,0 +1,40 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of torchat for ruby.
5
+ #
6
+ # torchat for ruby is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # torchat for ruby is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with torchat for ruby. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ class Torchat; module Protocol
21
+
22
+ define_extension :broadcast do
23
+ define_packet :message do
24
+ define_unpacker_for 1 do |data|
25
+ data.force_encoding('UTF-8')
26
+ end
27
+
28
+ def pack
29
+ super(@internal.encode('UTF-8'))
30
+ end
31
+
32
+ def to_s
33
+ @internal
34
+ end
35
+
36
+ alias to_str to_s
37
+ end
38
+ end
39
+
40
+ end; end
@@ -0,0 +1,197 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of torchat for ruby.
5
+ #
6
+ # torchat for ruby is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # torchat for ruby is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with torchat for ruby. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ class Torchat; module Protocol
21
+
22
+ define_extension :groupchat do
23
+ define_packet :invite do
24
+ define_unpacker_for 1 .. -1
25
+
26
+ attr_reader :id, :modes
27
+
28
+ def initialize (id = nil, *modes)
29
+ @id = id || Torchat.new_cookie
30
+ @modes = modes.flatten.compact.uniq.map(&:to_sym)
31
+ end
32
+
33
+ def pack
34
+ super("#{id}#{" #{modes.join ' '}" unless modes.empty?}")
35
+ end
36
+
37
+ def inspect
38
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})#{": #{modes.join ' '}" unless modes.empty?}>"
39
+ end
40
+ end
41
+
42
+ define_packet :participants do
43
+ define_unpacker_for 1 .. -1
44
+
45
+ attr_accessor :id
46
+
47
+ def initialize (id, *participants)
48
+ @id = id
49
+ @internal = participants.flatten.compact.uniq
50
+ end
51
+
52
+ def method_missing (id, *args, &block)
53
+ return @internal.__send__ id, *args, &block if @internal.respond_to? id
54
+
55
+ super
56
+ end
57
+
58
+ def respond_to_missing? (id, include_private = false)
59
+ @internal.respond_to? id, include_private
60
+ end
61
+
62
+ def pack
63
+ super("#{id}#{" #{join ' '}" unless empty?}")
64
+ end
65
+
66
+ def inspect
67
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})#{": #{join ' '}" unless empty?}>"
68
+ end
69
+ end
70
+
71
+ define_packet :is_participanting do
72
+ define_unpacker_for 1
73
+
74
+ def id
75
+ @internal
76
+ end
77
+
78
+ def inspect
79
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})>"
80
+ end
81
+ end
82
+
83
+ define_packet :participating do
84
+ define_unpacker_for 1
85
+
86
+ def id
87
+ @internal
88
+ end
89
+
90
+ def inspect
91
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})>"
92
+ end
93
+ end
94
+
95
+ define_packet :not_participating do
96
+ define_unpacker_for 1
97
+
98
+ def id
99
+ @internal
100
+ end
101
+
102
+ def inspect
103
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})>"
104
+ end
105
+ end
106
+
107
+ define_packet :join do
108
+ define_unpacker_for 1
109
+
110
+ def id
111
+ @internal
112
+ end
113
+
114
+ def inspect
115
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})>"
116
+ end
117
+ end
118
+
119
+ define_packet :leave do
120
+ define_unpacker_for 1 .. 2 do |data|
121
+ id, data = data.split ' ', 2
122
+
123
+ [id, data && !data.empty? ? data.force_encoding('UTF-8') : nil]
124
+ end
125
+
126
+ attr_accessor :id, :reason
127
+
128
+ def initialize (id, reason = nil)
129
+ @id = id
130
+ @reason = reason
131
+ end
132
+
133
+ def pack
134
+ super("#{id}#{" #{reason.encode('UTF-8')}" if reason}")
135
+ end
136
+
137
+ def inspect
138
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id})#{": #{reason.inspect}" if reason}>"
139
+ end
140
+ end
141
+
142
+ define_packet :invited do
143
+ define_unpacker_for 2
144
+
145
+ attr_accessor :id, :buddy
146
+
147
+ def initialize (id, buddy)
148
+ @id = id
149
+ @buddy = buddy
150
+ end
151
+
152
+ def pack
153
+ super("#{id} #{to_s}")
154
+ end
155
+
156
+ def to_s
157
+ @buddy
158
+ end
159
+
160
+ alias to_str to_s
161
+
162
+ def inspect
163
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id}): #{to_s}>"
164
+ end
165
+ end
166
+
167
+ define_packet :message do
168
+ define_unpacker_for 2 do |data|
169
+ id, data = data.split ' ', 2
170
+
171
+ [id, data.force_encoding('UTF-8')]
172
+ end
173
+
174
+ attr_accessor :id, :content
175
+
176
+ def initialize (id, content)
177
+ @id = id
178
+ @content = content
179
+ end
180
+
181
+ def pack
182
+ super("#{id} #{to_s.encode('UTF-8')}")
183
+ end
184
+
185
+ def to_s
186
+ @content
187
+ end
188
+
189
+ alias to_str to_s
190
+
191
+ def inspect
192
+ "#<Torchat::Packet[#{"#{extension}_" if extension}#{type}](#{id}): #{to_s.inspect}>"
193
+ end
194
+ end
195
+ end
196
+
197
+ end; end
@@ -0,0 +1,44 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of torchat for ruby.
5
+ #
6
+ # torchat for ruby is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # torchat for ruby is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with torchat for ruby. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ class Torchat; module Protocol
21
+
22
+ define_extension :latency do
23
+ define_packet :ping do
24
+ define_unpacker_for 1
25
+
26
+ def initialize (id = Torchat.new_cookie)
27
+ @internal = id
28
+ end
29
+
30
+ def id
31
+ @internal
32
+ end
33
+ end
34
+
35
+ define_packet :pong do
36
+ define_unpacker_for 1
37
+
38
+ def id
39
+ @internal
40
+ end
41
+ end
42
+ end
43
+
44
+ end; end
@@ -0,0 +1,367 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.paranoid.pk | meh@paranoici.org]
3
+ #
4
+ # This file is part of torchat for ruby.
5
+ #
6
+ # torchat for ruby is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # torchat for ruby is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with torchat for ruby. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'digest/md5'
21
+
22
+ class Torchat; module Protocol
23
+
24
+ define_packet :not_implemented do
25
+ define_unpacker_for 0 .. 1
26
+
27
+ def command
28
+ @internal
29
+ end
30
+ end
31
+
32
+ define_packet :ping do
33
+ define_unpacker_for 2
34
+
35
+ attr_reader :id, :address
36
+ attr_accessor :cookie
37
+
38
+ def initialize (address, cookie = nil)
39
+ self.address = address
40
+ self.cookie = cookie || Torchat.new_cookie
41
+ end
42
+
43
+ def id= (value)
44
+ @id = value[/^(.*?)(\.onion)?$/, 1]
45
+ @address = "#{@id}.onion"
46
+ end
47
+
48
+ alias address= id=
49
+
50
+ def valid?
51
+ Torchat.valid_id? @id
52
+ end
53
+
54
+ def pack
55
+ super("#{id} #{cookie}")
56
+ end
57
+
58
+ def inspect
59
+ "#<Torchat::Packet[#{type}]#{"(#{from.inspect})" if from}: #{id} #{cookie}>"
60
+ end
61
+ end
62
+
63
+ define_packet :pong do
64
+ define_unpacker_for 1
65
+
66
+ def cookie
67
+ @internal
68
+ end
69
+ end
70
+
71
+ define_packet :client do
72
+ define_unpacker_for 0 .. 1
73
+
74
+ def nil?
75
+ @internal.nil?
76
+ end
77
+
78
+ def name
79
+ @internal
80
+ end
81
+
82
+ alias to_s name
83
+ alias to_str name
84
+ end
85
+
86
+ define_packet :version do
87
+ define_unpacker_for 0 .. 1
88
+
89
+ def nil?
90
+ @internal.nil?
91
+ end
92
+
93
+ def to_s
94
+ @internal
95
+ end
96
+
97
+ alias to_str to_s
98
+ end
99
+
100
+ define_packet :supports do
101
+ define_unpacker_for 0 .. -1
102
+
103
+ def initialize (*supports)
104
+ @internal = supports.flatten.compact.map(&:downcase).map(&:to_sym).uniq
105
+ end
106
+
107
+ def method_missing (id, *args, &block)
108
+ return @internal.__send__ id, *args, &block if @internal.respond_to? id
109
+
110
+ super
111
+ end
112
+
113
+ def pack
114
+ super(join ' ')
115
+ end
116
+ end
117
+
118
+ define_packet :status do
119
+ def self.valid? (name)
120
+ %w(available away xa).include?(name.to_s.downcase)
121
+ end
122
+
123
+ define_unpacker_for 1
124
+
125
+ def initialize (name)
126
+ unless Protocol[:status].valid?(name)
127
+ raise ArgumentError, "#{name} is not a valid status"
128
+ end
129
+
130
+ @internal = name.to_sym.downcase
131
+ end
132
+
133
+ def available?
134
+ @internal == :available
135
+ end
136
+
137
+ def away?
138
+ @internal == :away
139
+ end
140
+
141
+ def extended_away?
142
+ @internal == :xa
143
+ end
144
+
145
+ def to_sym
146
+ @internal
147
+ end
148
+
149
+ def to_s
150
+ to_sym.to_s
151
+ end
152
+ end
153
+
154
+ define_packet :profile_name do
155
+ define_unpacker_for 0 .. 1 do |data|
156
+ data.force_encoding('UTF-8') if data
157
+ end
158
+
159
+ def pack
160
+ super(@internal ? @internal.encode('UTF-8') : nil)
161
+ end
162
+
163
+ def to_s
164
+ @internal
165
+ end
166
+
167
+ alias to_str to_s
168
+ end
169
+
170
+ define_packet :profile_text do
171
+ define_unpacker_for 0 .. 1 do |data|
172
+ data.force_encoding('UTF-8') if data
173
+ end
174
+
175
+ def pack
176
+ super(@internal ? @internal.encode('UTF-8') : nil)
177
+ end
178
+
179
+ def to_s
180
+ @internal
181
+ end
182
+
183
+ alias to_str to_s
184
+ end
185
+
186
+ define_packet :profile_avatar_alpha do
187
+ define_unpacker_for 0 .. 1 do |data|
188
+ data if data && (data.empty? || data.bytesize != 4096)
189
+ end
190
+
191
+ def data
192
+ @internal
193
+ end
194
+
195
+ def inspect
196
+ "#<Torchat::Packet[#{type}]>"
197
+ end
198
+ end
199
+
200
+ define_packet :profile_avatar do
201
+ define_unpacker_for 0 .. 1 do |data|
202
+ data if data && (data.empty? || data.bytesize == 12288)
203
+ end
204
+
205
+ def data
206
+ @internal
207
+ end
208
+
209
+ def inspect
210
+ "#<Torchat::Packet[#{type}]>"
211
+ end
212
+ end
213
+
214
+ define_packet :add_me do
215
+ define_unpacker_for 0
216
+ end
217
+
218
+ define_packet :remove_me do
219
+ define_unpacker_for 0
220
+ end
221
+
222
+ define_packet :message do
223
+ define_unpacker_for 1 do |data|
224
+ data.force_encoding('UTF-8')
225
+ end
226
+
227
+ def pack
228
+ super(@internal.encode('UTF-8'))
229
+ end
230
+
231
+ def to_s
232
+ @internal
233
+ end
234
+
235
+ alias to_str to_s
236
+ end
237
+
238
+ define_packet :filename do
239
+ define_unpacker do |data|
240
+ id, size, block_size, name = data.split ' ', 4
241
+
242
+ [name, size, block_size, id]
243
+ end
244
+
245
+ attr_accessor :id, :name, :size, :block_size
246
+
247
+ def initialize (name, size, block_size = 4096, id = nil)
248
+ @name = name
249
+ @size = size.to_i
250
+ @block_size = block_size.to_i
251
+ @id = id || Torchat.new_cookie
252
+ end
253
+
254
+ alias length size
255
+ alias bytesize size
256
+
257
+ def pack
258
+ super("#{id} #{size} #{block_size} #{name}")
259
+ end
260
+
261
+ def inspect
262
+ "#<Torchat::Packet[#{type}](#{id}): #{name} #{size} #{block_size}>"
263
+ end
264
+ end
265
+
266
+ define_packet :filedata do
267
+ define_unpacker do |data|
268
+ id, offset, md5, data = data.split ' ', 4
269
+
270
+ [id, offset, data, md5]
271
+ end
272
+
273
+ attr_reader :data, :md5
274
+ attr_accessor :id, :offset
275
+
276
+ def initialize (id, offset, data, md5 = nil)
277
+ @id = id
278
+ @offset = offset.to_i
279
+ @data = data.force_encoding('BINARY')
280
+ @md5 = md5 || Digest::MD5.hexdigest(@data)
281
+ end
282
+
283
+ def data= (value)
284
+ @data = value.to_s.force_encoding('BINARY')
285
+ @md5 = Digest::MD5.hexdigest(@data)
286
+ end
287
+
288
+ def valid?
289
+ Digest::MD5.hexdigest(data) == md5
290
+ end
291
+
292
+ def pack
293
+ super("#{id} #{offset} #{md5} #{data}")
294
+ end
295
+
296
+ def inspect
297
+ "#<Torchat::Packet[#{type}](#{id}): #{offset} #{data.size}>"
298
+ end
299
+ end
300
+
301
+ define_packet :filedata_ok do
302
+ define_unpacker do |data|
303
+ data.split ' '
304
+ end
305
+
306
+ attr_accessor :id, :offset
307
+
308
+ def initialize (id, offset)
309
+ @id = id
310
+ @offset = offset.to_i
311
+ end
312
+
313
+ def pack
314
+ super("#{id} #{offset}")
315
+ end
316
+
317
+ def inspect
318
+ "#<Torchat::Packet[#{type}](#{id}): #{offset}>"
319
+ end
320
+ end
321
+
322
+ define_packet :filedata_error do
323
+ define_unpacker do |data|
324
+ data.split ' '
325
+ end
326
+
327
+ attr_accessor :id, :offset
328
+
329
+ def initialize (id, offset)
330
+ @id = id
331
+ @offset = offset.to_i
332
+ end
333
+
334
+ def pack
335
+ super("#{id} #{offset}")
336
+ end
337
+
338
+ def inspect
339
+ "#<Torchat::Packet[#{type}](#{id}): #{offset}>"
340
+ end
341
+ end
342
+
343
+ define_packet :file_stop_sending do
344
+ define_unpacker_for 1
345
+
346
+ def id
347
+ @internal
348
+ end
349
+
350
+ def inspect
351
+ "#<Torchat::Packet[#{type}](#{id})>"
352
+ end
353
+ end
354
+
355
+ define_packet :file_stop_receiving do
356
+ define_unpacker_for 1
357
+
358
+ def id
359
+ @internal
360
+ end
361
+
362
+ def inspect
363
+ "#<Torchat::Packet[#{type}](#{id})>"
364
+ end
365
+ end
366
+
367
+ end; end