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,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
+ }