torchat 0.0.1.rc.1

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