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,102 @@
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 'em-socksify'
21
+
22
+ class Torchat; class Session
23
+
24
+ class Outgoing < EventMachine::Protocols::LineAndTextProtocol
25
+ include EM::Socksify
26
+
27
+ attr_accessor :owner
28
+
29
+ def post_init
30
+ @delayed = []
31
+ end
32
+
33
+ def connection_completed
34
+ old, new = comm_inactivity_timeout, @session.connection_timeout
35
+
36
+ set_comm_inactivity_timeout new
37
+
38
+ @session.fire :connect_to, address: @owner.address, port: @owner.port
39
+
40
+ socksify(@owner.address, @owner.port).callback {
41
+ set_comm_inactivity_timeout old
42
+
43
+ @owner.connected
44
+ }.errback {|exc|
45
+ Torchat.debug exc, level: 3
46
+
47
+ @owner.disconnect
48
+ }
49
+ end
50
+
51
+ def verification_completed
52
+ @delayed.each {|packet|
53
+ send_packet! packet
54
+ }
55
+
56
+ @delayed = nil
57
+ end
58
+
59
+ def receive_line (line)
60
+ packet = Protocol.unpack(line.chomp, @owner)
61
+
62
+ return unless packet.type.to_s.start_with 'file'
63
+
64
+ @owner.session.received_packet packet
65
+ end
66
+
67
+ def send_packet (*args)
68
+ packet = Protocol.packet(*args)
69
+
70
+ if @delayed
71
+ @delayed << packet
72
+ else
73
+ send_packet! packet
74
+ end
75
+
76
+ packet
77
+ end
78
+
79
+ def send_packet! (*args)
80
+ packet = Protocol.packet(*args)
81
+
82
+ Torchat.debug ">> #{@owner ? @owner.id : 'unknown'} #{packet.inspect}", level: 2
83
+
84
+ send_data packet.pack
85
+
86
+ packet
87
+ end
88
+
89
+ def unbind
90
+ if error?
91
+ Torchat.debug "errno #{EM.report_connection_error_status(@signature)}", level: 2
92
+ end
93
+
94
+ if @owner.connecting?
95
+ @owner.failed!
96
+ else
97
+ @owner.disconnect
98
+ end
99
+ end
100
+ end
101
+
102
+ end; end
@@ -0,0 +1,107 @@
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
21
+
22
+ class Tor
23
+ class Instance < EM::Connection
24
+ def receive_data (data)
25
+ return unless ENV['DEBUG'] && ENV['DEBUG'].to_i >= 5
26
+
27
+ print data.gsub(/^/, 'tor] ')
28
+ end
29
+
30
+ alias stop close_connection
31
+
32
+ def unbind
33
+ @owner.error unless get_status.success?
34
+ end
35
+ end
36
+
37
+ attr_reader :config
38
+ attr_accessor :file
39
+
40
+ def initialize (config)
41
+ @config = config
42
+
43
+ @file = 'torrc'
44
+ end
45
+
46
+ def start (path, *args, &block)
47
+ return if @instance
48
+
49
+ if block
50
+ @error = args.shift
51
+ end
52
+
53
+ block = args.shift
54
+ @error ||= args.shift
55
+
56
+ File.expand_path(path).tap {|path|
57
+ FileUtils.mkpath path
58
+
59
+ Dir.chdir path do
60
+ unless File.exists?(@file)
61
+ File.open(@file, 'w') { |f| f.print rc }
62
+ end
63
+
64
+ EM.popen "tor -f '#@file'", Instance do |t|
65
+ @instance = t
66
+
67
+ t.instance_variable_set :@owner, self
68
+ end
69
+
70
+ block.arity.zero? ? block.call : block.call(path) if block
71
+ end
72
+ }
73
+ end
74
+
75
+ def stop
76
+ return unless @instance
77
+
78
+ @instance.close_connection
79
+ end
80
+
81
+ def error
82
+ @error.call if @error
83
+ end
84
+
85
+ def rc
86
+ <<-EOF.gsub /^\t+/, ''
87
+ SocksPort #{config['connection']['outgoing']['port']}
88
+
89
+ HiddenServiceDir hidden_service
90
+ HiddenServicePort 11009 #{
91
+ config['connection']['incoming']['host']
92
+ }:#{
93
+ config['connection']['incoming']['port']
94
+ }
95
+
96
+ DataDirectory tor_data
97
+
98
+ AvoidDiskWrites 1
99
+ LongLivedPorts 11009
100
+ FetchDirInfoEarly 1
101
+ CircuitBuildTimeout 30
102
+ NumEntryGuards 6
103
+ EOF
104
+ end
105
+ end
106
+
107
+ end
@@ -0,0 +1,87 @@
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 'securerandom'
21
+
22
+ class Torchat
23
+ def self.debug?
24
+ return false unless env = ENV['DEBUG'] || ENV['TORCHAT_DEBUG']
25
+
26
+ env.to_i.zero? ? 1 : env.to_i
27
+ end
28
+
29
+ if debug?
30
+ require 'ap'
31
+ end
32
+
33
+ def self.debug (argument, options = {})
34
+ return if !debug? && !options[:force]
35
+
36
+ return if debug? < (options[:level] || 1) && !options[:force]
37
+
38
+ output = options[:prefix] ? options[:prefix] : "[#{Time.new}] "
39
+
40
+ if argument.is_a?(Exception)
41
+ output << "From: #{caller[0, options[:deep] || 1].join("\n")}\n"
42
+ output << "#{argument.class}: #{argument.message}\n"
43
+ output << argument.backtrace.collect {|stack|
44
+ stack
45
+ }.join("\n")
46
+ output << "\n\n"
47
+ elsif argument.is_a?(String)
48
+ output << "#{argument}\n"
49
+ else
50
+ output << "#{argument.inspect}\n"
51
+ end
52
+
53
+ if options[:separator]
54
+ output << options[:separator]
55
+ end
56
+
57
+ $stderr.puts output
58
+ end
59
+
60
+ def self.valid_address? (address)
61
+ !!address.match(/^[234567abcdefghijklmnopqrstuvwxyz]{16}\.onion$/i)
62
+ end
63
+
64
+ def self.valid_id? (id)
65
+ !!id.match(/^[234567abcdefghijklmnopqrstuvwxyz]{16}$/i)
66
+ end
67
+
68
+ def self.new_cookie
69
+ SecureRandom.uuid
70
+ end
71
+
72
+ def self.normalize_id (value, return_nil = false)
73
+ if value.respond_to? :id
74
+ value = value.id
75
+ end
76
+
77
+ value = value.to_s[/^(.*?)(\.onion)?$/, 1]
78
+
79
+ unless valid_id?(value)
80
+ return if return_nil
81
+
82
+ raise ArgumentError, 'the given ID is invalid'
83
+ end
84
+
85
+ value
86
+ end
87
+ end
@@ -0,0 +1,24 @@
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
21
+ def self.version
22
+ '0.0.1.rc.1'
23
+ end
24
+ end
@@ -0,0 +1,41 @@
1
+ #! /usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'torchat'
4
+
5
+ options = {}
6
+
7
+ OptionParser.new do |o|
8
+ o.on '-p', '--profile PROFILE', 'the profile name' do |name|
9
+ options[:profile] = name
10
+ end
11
+ end.parse!
12
+
13
+ EM.run {
14
+ Torchat.profile(options[:profile]).start {|s|
15
+ s.when :connect_to do |e|
16
+ Torchat.debug "connecting to #{e.address}:#{e.port}"
17
+ end
18
+
19
+ s.on :connect_failure do |e|
20
+ Torchat.debug "#{e.buddy.id} failed to connect"
21
+ end
22
+
23
+ s.on :connect do |e|
24
+ Torchat.debug "#{e.buddy.id} connected"
25
+ end
26
+
27
+ s.on :verify do |e|
28
+ Torchat.debug "#{e.buddy.id} has been verified"
29
+ end
30
+
31
+ s.on :disconnect do |e|
32
+ Torchat.debug "#{e.buddy.id} disconnected"
33
+ end
34
+
35
+ s.on :file_transfer_activity do |e|
36
+ puts e.file_transfer.inspect
37
+ end
38
+
39
+ s.online!
40
+ }
41
+ }
@@ -0,0 +1,45 @@
1
+ #! /usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'torchat'
4
+
5
+ options = {}
6
+
7
+ OptionParser.new do |o|
8
+ o.on '-p', '--profile PROFILE', 'the profile name' do |name|
9
+ options[:profile] = name
10
+ end
11
+
12
+ o.on '-s', '--send-to NAME', 'the name of the receiver' do |name|
13
+ options[:send_to] = name
14
+ end
15
+ end.parse!
16
+
17
+ EM.run {
18
+ Torchat.profile(options[:profile]).start {|s|
19
+ s.when :connect_to do |e|
20
+ Torchat.debug "connecting to #{e.address}:#{e.port}"
21
+ end
22
+
23
+ s.on :connect_failure do |e|
24
+ Torchat.debug "#{e.buddy.id} failed to connect"
25
+ end
26
+
27
+ s.on :connect do |e|
28
+ Torchat.debug "#{e.buddy.id} connected"
29
+ end
30
+
31
+ s.on :verify do |e|
32
+ Torchat.debug "#{e.buddy.id} has been verified"
33
+ end
34
+
35
+ s.on :disconnect do |e|
36
+ Torchat.debug "#{e.buddy.id} disconnected"
37
+ end
38
+
39
+ s.buddies.add_temporary(options[:send_to]).on :ready do |e|
40
+ e.buddy.send_file ARGV.first
41
+ end
42
+
43
+ s.online!
44
+ }
45
+ }
@@ -0,0 +1,37 @@
1
+ #! /usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'torchat'
4
+
5
+ options = {}
6
+
7
+ OptionParser.new do |o|
8
+ o.on '-p', '--profile PROFILE', 'the profile name' do |name|
9
+ options[:profile] = name
10
+ end
11
+ end.parse!
12
+
13
+ EM.run {
14
+ Torchat.profile(options[:profile]).start {|s|
15
+ s.when :connect_to do |e|
16
+ Torchat.debug "connecting to #{e.address}:#{e.port}"
17
+ end
18
+
19
+ s.on :connect_failure do |e|
20
+ Torchat.debug "#{e.buddy.id} failed to connect"
21
+ end
22
+
23
+ s.on :connect do |e|
24
+ Torchat.debug "#{e.buddy.id} connected"
25
+ end
26
+
27
+ s.on :verify do |e|
28
+ Torchat.debug "#{e.buddy.id} has been verified"
29
+ end
30
+
31
+ s.on :disconnect do |e|
32
+ Torchat.debug "#{e.buddy.id} disconnected"
33
+ end
34
+
35
+ s.online!
36
+ }
37
+ }