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.
- data/README.md +43 -0
- data/bin/torchatd +537 -0
- data/doc/protocol/broadcast.md +26 -0
- data/doc/protocol/groupchat.md +140 -0
- data/doc/protocol/latency.md +30 -0
- data/doc/protocol/standard.md +279 -0
- data/doc/protocol/typing.md +41 -0
- data/etc/torchat.yml +12 -0
- data/lib/torchat.rb +239 -0
- data/lib/torchat/protocol.rb +256 -0
- data/lib/torchat/protocol/broadcast.rb +40 -0
- data/lib/torchat/protocol/groupchat.rb +197 -0
- data/lib/torchat/protocol/latency.rb +44 -0
- data/lib/torchat/protocol/standard.rb +367 -0
- data/lib/torchat/protocol/typing.rb +36 -0
- data/lib/torchat/session.rb +603 -0
- data/lib/torchat/session/broadcast/message.rb +50 -0
- data/lib/torchat/session/broadcasts.rb +72 -0
- data/lib/torchat/session/buddies.rb +152 -0
- data/lib/torchat/session/buddy.rb +343 -0
- data/lib/torchat/session/buddy/joined_group_chat.rb +42 -0
- data/lib/torchat/session/buddy/joined_group_chats.rb +46 -0
- data/lib/torchat/session/buddy/latency.rb +54 -0
- data/lib/torchat/session/event.rb +79 -0
- data/lib/torchat/session/file_transfer.rb +173 -0
- data/lib/torchat/session/file_transfer/block.rb +51 -0
- data/lib/torchat/session/file_transfers.rb +89 -0
- data/lib/torchat/session/group_chat.rb +123 -0
- data/lib/torchat/session/group_chat/participant.rb +38 -0
- data/lib/torchat/session/group_chat/participants.rb +52 -0
- data/lib/torchat/session/group_chats.rb +74 -0
- data/lib/torchat/session/incoming.rb +187 -0
- data/lib/torchat/session/outgoing.rb +102 -0
- data/lib/torchat/tor.rb +107 -0
- data/lib/torchat/utils.rb +87 -0
- data/lib/torchat/version.rb +24 -0
- data/test/file_transfer/receiver.rb +41 -0
- data/test/file_transfer/sender.rb +45 -0
- data/test/group_chat/a.rb +37 -0
- data/test/group_chat/b.rb +37 -0
- data/test/group_chat/c.rb +57 -0
- data/torchat.gemspec +21 -0
- metadata +140 -0
@@ -0,0 +1,50 @@
|
|
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; class Session; module Broadcast
|
21
|
+
|
22
|
+
class Message
|
23
|
+
def self.parse (text)
|
24
|
+
new text, text.scan(/#([^ ]+)/)
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :at, :tags
|
28
|
+
|
29
|
+
def initialize (message, *tags)
|
30
|
+
@at = Time.new
|
31
|
+
@internal = message
|
32
|
+
@tags = tags.flatten.compact.uniq.map(&:to_sym)
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
@internal
|
37
|
+
end
|
38
|
+
|
39
|
+
alias to_str to_s
|
40
|
+
|
41
|
+
def == (other)
|
42
|
+
to_s == other
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
"#<Torchat::Broadcast::Message(#{tags.join ' '}): #{to_s}>"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end; end; end
|
@@ -0,0 +1,72 @@
|
|
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 'torchat/session/broadcast/message'
|
21
|
+
|
22
|
+
class Torchat; class Session
|
23
|
+
|
24
|
+
class Broadcasts < Array
|
25
|
+
attr_reader :session
|
26
|
+
attr_accessor :cooldown
|
27
|
+
|
28
|
+
def initialize (session)
|
29
|
+
@session = session
|
30
|
+
|
31
|
+
@cooldown = 360
|
32
|
+
end
|
33
|
+
|
34
|
+
def disable!; @disabled = true; end
|
35
|
+
def enable!; @disabled = false; end
|
36
|
+
def disabled?; @disabled; end
|
37
|
+
def enabled?; !disabled?; end
|
38
|
+
|
39
|
+
def send_message (message)
|
40
|
+
received(message, true)
|
41
|
+
end
|
42
|
+
|
43
|
+
def received? (message)
|
44
|
+
flush!
|
45
|
+
|
46
|
+
any? { |m| m == message }
|
47
|
+
end
|
48
|
+
|
49
|
+
def received (message, no_event = false)
|
50
|
+
return if disabled? or received? message
|
51
|
+
|
52
|
+
Broadcast::Message.parse(message).tap {|message|
|
53
|
+
push message
|
54
|
+
|
55
|
+
session.buddies.each_online {|id, buddy|
|
56
|
+
if buddy.supports? :broadcast
|
57
|
+
buddy.send_packet [:broadcast, :message], message.to_s
|
58
|
+
end
|
59
|
+
}
|
60
|
+
|
61
|
+
session.fire :broadcast, message: message unless no_event
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def flush!
|
66
|
+
delete_if {|message|
|
67
|
+
(Time.now.to_i - message.at.to_i) > cooldown
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end; end
|
@@ -0,0 +1,152 @@
|
|
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 'torchat/session/buddy'
|
21
|
+
|
22
|
+
class Torchat; class Session
|
23
|
+
|
24
|
+
class Buddies < Hash
|
25
|
+
attr_reader :session
|
26
|
+
|
27
|
+
def initialize (session)
|
28
|
+
@session = session
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_key? (name)
|
32
|
+
name = name.id if name.is_a? Buddy
|
33
|
+
|
34
|
+
!!self[name]
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete (name)
|
38
|
+
super(self[name].id) rescue nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def [] (name)
|
42
|
+
begin
|
43
|
+
super(Torchat.normalize_id(name))
|
44
|
+
rescue ArgumentError
|
45
|
+
find { |a, b| name === b.name }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def []= (name, buddy)
|
50
|
+
name = begin
|
51
|
+
Torchat.normalize_id(name)
|
52
|
+
rescue ArgumentError
|
53
|
+
find { |a, b| name === b.name }.id
|
54
|
+
end
|
55
|
+
|
56
|
+
super(name, buddy)
|
57
|
+
end
|
58
|
+
|
59
|
+
def << (buddy)
|
60
|
+
self[buddy.id] = buddy
|
61
|
+
end
|
62
|
+
|
63
|
+
def each_online (&block)
|
64
|
+
each {|id, buddy|
|
65
|
+
block.call id, buddy if buddy.online?
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def each_offline (&block)
|
70
|
+
each {|id, buddy|
|
71
|
+
block.call id, buddy if buddy.offline?
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def add (id, ali = nil)
|
76
|
+
if buddy = self[id]
|
77
|
+
buddy.permanent!
|
78
|
+
|
79
|
+
return buddy
|
80
|
+
end
|
81
|
+
|
82
|
+
buddy = id.is_a?(Buddy) ? id : Buddy.new(session, id)
|
83
|
+
|
84
|
+
raise ArgumentError, 'you cannot add yourself' if session.id == buddy.id
|
85
|
+
|
86
|
+
buddy.permanent!
|
87
|
+
buddy.alias = ali
|
88
|
+
|
89
|
+
self << buddy
|
90
|
+
|
91
|
+
session.fire :buddy_add, buddy: buddy
|
92
|
+
|
93
|
+
buddy.connect if session.online?
|
94
|
+
|
95
|
+
buddy
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_temporary (id, ali = nil)
|
99
|
+
if buddy = self[id]
|
100
|
+
return buddy
|
101
|
+
end
|
102
|
+
|
103
|
+
buddy = id.is_a?(Buddy) ? id : Buddy.new(session, id)
|
104
|
+
|
105
|
+
raise ArgumentError, 'you cannot add yourself' if session.id == buddy.id
|
106
|
+
|
107
|
+
buddy.temporary!
|
108
|
+
buddy.alias = ali
|
109
|
+
|
110
|
+
self << buddy
|
111
|
+
|
112
|
+
session.fire :add_buddy, buddy: buddy
|
113
|
+
|
114
|
+
buddy.connect if session.online?
|
115
|
+
|
116
|
+
buddy
|
117
|
+
end
|
118
|
+
|
119
|
+
def remove (id)
|
120
|
+
return unless has_key? id
|
121
|
+
|
122
|
+
buddy = if id.is_a? Buddy
|
123
|
+
delete(key(id))
|
124
|
+
else
|
125
|
+
delete(id)
|
126
|
+
end
|
127
|
+
|
128
|
+
buddy.remove!
|
129
|
+
|
130
|
+
session.fire :remove_buddy, buddy: buddy
|
131
|
+
|
132
|
+
buddy.remove_callbacks
|
133
|
+
|
134
|
+
if buddy.permanent? && buddy.online?
|
135
|
+
buddy.send_packet :remove_me
|
136
|
+
|
137
|
+
session.set_timeout 10 do
|
138
|
+
buddy.disconnect
|
139
|
+
end
|
140
|
+
else
|
141
|
+
buddy.disconnect
|
142
|
+
end
|
143
|
+
|
144
|
+
if buddy.blocked?
|
145
|
+
add_temporary(buddy.id).block!
|
146
|
+
end
|
147
|
+
|
148
|
+
buddy
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end; end
|
@@ -0,0 +1,343 @@
|
|
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 'eventmachine'
|
21
|
+
|
22
|
+
require 'torchat/session/incoming'
|
23
|
+
require 'torchat/session/outgoing'
|
24
|
+
|
25
|
+
class Torchat; class Session
|
26
|
+
|
27
|
+
class Buddy
|
28
|
+
class Avatar
|
29
|
+
attr_writer :rgb, :alpha
|
30
|
+
|
31
|
+
def to_image
|
32
|
+
return unless @rgb
|
33
|
+
|
34
|
+
require 'chunky_png'
|
35
|
+
|
36
|
+
ChunkyPNG::Image.new(64, 64, ChunkyPNG::Color::TRANSPARENT).tap {|image|
|
37
|
+
@rgb.bytes.each_slice(3).with_index {|(r, g, b), index|
|
38
|
+
x, y = index % 64, index / 64
|
39
|
+
|
40
|
+
image[x, y] = if @alpha
|
41
|
+
ChunkyPNG::Color.rgba(r, g, b, @alpha[index])
|
42
|
+
else
|
43
|
+
ChunkyPNG::Color.rgb(r, g, b)
|
44
|
+
end
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Client = Struct.new(:name, :version)
|
51
|
+
|
52
|
+
attr_reader :session, :id, :address, :avatar, :client, :tries, :last_try, :messages, :group_chats, :latency
|
53
|
+
attr_writer :status
|
54
|
+
attr_accessor :name, :description, :alias, :last_received
|
55
|
+
|
56
|
+
def port; 11009; end
|
57
|
+
|
58
|
+
def initialize (session, id, incoming = nil, outgoing = nil)
|
59
|
+
unless Torchat.valid_id?(id)
|
60
|
+
raise ArgumentError, "#{id} is an invalid onion id"
|
61
|
+
end
|
62
|
+
|
63
|
+
@session = session
|
64
|
+
@id = id[/^(.*?)(\.onion)?$/, 1]
|
65
|
+
@address = "#{@id}.onion"
|
66
|
+
@callbacks = []
|
67
|
+
@avatar = Avatar.new
|
68
|
+
@client = Client.new
|
69
|
+
@supports = []
|
70
|
+
@messages = []
|
71
|
+
@group_chats = JoinedGroupChats.new(self)
|
72
|
+
@latency = Latency.new(self)
|
73
|
+
@tries = 0
|
74
|
+
@last_try = nil
|
75
|
+
@typing = :stop
|
76
|
+
|
77
|
+
own! incoming
|
78
|
+
own! outgoing
|
79
|
+
end
|
80
|
+
|
81
|
+
def supports (*what)
|
82
|
+
@supports.concat(what).uniq!
|
83
|
+
end
|
84
|
+
|
85
|
+
def supports? (what)
|
86
|
+
@supports.include?(what.to_sym.downcase)
|
87
|
+
end
|
88
|
+
|
89
|
+
def status
|
90
|
+
online? ? @status : :offline
|
91
|
+
end
|
92
|
+
|
93
|
+
def on (what, &block)
|
94
|
+
removable = session.on what do |e|
|
95
|
+
block.call e if e.buddy == self
|
96
|
+
end
|
97
|
+
|
98
|
+
@callbacks << removable
|
99
|
+
|
100
|
+
removable
|
101
|
+
end
|
102
|
+
|
103
|
+
def on_packet (name = nil)
|
104
|
+
removable = if name
|
105
|
+
on :packet do |e|
|
106
|
+
block.call e if e.packet.type == name
|
107
|
+
end
|
108
|
+
else
|
109
|
+
on :packet, &block
|
110
|
+
end
|
111
|
+
|
112
|
+
@callbacks << removable
|
113
|
+
|
114
|
+
removable
|
115
|
+
end
|
116
|
+
|
117
|
+
def remove_callbacks
|
118
|
+
@callbacks.each(&:remove!).clear
|
119
|
+
end
|
120
|
+
|
121
|
+
def has_incoming?
|
122
|
+
!!@incoming
|
123
|
+
end
|
124
|
+
|
125
|
+
def has_outgoing?
|
126
|
+
!!@outgoing
|
127
|
+
end
|
128
|
+
|
129
|
+
def own! (what)
|
130
|
+
if what.is_a? Incoming
|
131
|
+
@incoming = what
|
132
|
+
elsif what.is_a? Outgoing
|
133
|
+
@outgoing = what
|
134
|
+
end
|
135
|
+
|
136
|
+
@incoming.owner = self if has_incoming?
|
137
|
+
@outgoing.owner = self if has_outgoing?
|
138
|
+
end
|
139
|
+
|
140
|
+
def pinged?; @pinged; end
|
141
|
+
def ping!(c); @pinged = c; end
|
142
|
+
def pong!; @pinged = false; end
|
143
|
+
|
144
|
+
def removed?; @removed; end
|
145
|
+
def remove!; @removed = true; end
|
146
|
+
|
147
|
+
def blocked?; @blocked; end
|
148
|
+
def allowed?; !@blocked; end
|
149
|
+
|
150
|
+
def block!
|
151
|
+
@blocked = true
|
152
|
+
|
153
|
+
disconnect
|
154
|
+
end
|
155
|
+
|
156
|
+
def allow!
|
157
|
+
@blocked = false
|
158
|
+
|
159
|
+
connect
|
160
|
+
end
|
161
|
+
|
162
|
+
def temporary?; @temporary; end
|
163
|
+
def permanent?; !@temporary; end
|
164
|
+
def temporary!; @temporary = true; end
|
165
|
+
def permanent!; @temporary = false; end
|
166
|
+
|
167
|
+
def typing?; @typing == :start; end
|
168
|
+
def thinking?; @typing == :thinking; end
|
169
|
+
def not_typing?; @typing == :stop; end
|
170
|
+
|
171
|
+
def typing!
|
172
|
+
return if typing?
|
173
|
+
|
174
|
+
@typing = :start
|
175
|
+
|
176
|
+
session.fire :typing, buddy: self, mode: :start
|
177
|
+
end
|
178
|
+
|
179
|
+
def thinking!
|
180
|
+
return if thinking?
|
181
|
+
|
182
|
+
@typing = :thinking
|
183
|
+
|
184
|
+
session.fire :typing, buddy: self, mode: :thinking
|
185
|
+
end
|
186
|
+
|
187
|
+
def not_typing!
|
188
|
+
return if not_typing?
|
189
|
+
|
190
|
+
@typing = :stop
|
191
|
+
|
192
|
+
session.fire :typing, buddy: self, mode: :stop
|
193
|
+
end
|
194
|
+
|
195
|
+
def send_packet (*args)
|
196
|
+
raise 'you cannot send packets yet' unless has_outgoing?
|
197
|
+
|
198
|
+
@outgoing.send_packet *args
|
199
|
+
end
|
200
|
+
|
201
|
+
def send_packet! (*args)
|
202
|
+
raise 'you cannot send packets yet' unless has_outgoing?
|
203
|
+
|
204
|
+
@outgoing.send_packet! *args
|
205
|
+
end
|
206
|
+
|
207
|
+
def send_message (text)
|
208
|
+
if offline?
|
209
|
+
@messages << text
|
210
|
+
|
211
|
+
unless @messages.empty?
|
212
|
+
on :ready do |e|
|
213
|
+
until @messages.empty?
|
214
|
+
break if offline?
|
215
|
+
|
216
|
+
send_message "[delayed] #{@messages.shift}"
|
217
|
+
end
|
218
|
+
|
219
|
+
if @messages.empty?
|
220
|
+
e.remove!
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
else
|
225
|
+
send_packet :message, text
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def send_file (path)
|
230
|
+
session.file_transfers.send_file(self, path)
|
231
|
+
end
|
232
|
+
|
233
|
+
def send_blob (data)
|
234
|
+
session.file_transfers.send_blob(self, data)
|
235
|
+
end
|
236
|
+
|
237
|
+
def send_typing (mode)
|
238
|
+
return unless supports? :typing
|
239
|
+
|
240
|
+
send_packet "typing_#{mode}"
|
241
|
+
end
|
242
|
+
|
243
|
+
def online?; connected?; end
|
244
|
+
def offline?; !online?; end
|
245
|
+
|
246
|
+
def ready?; @ready; end
|
247
|
+
def ready!; @ready = true; end
|
248
|
+
|
249
|
+
def failed!
|
250
|
+
@connecting = false
|
251
|
+
|
252
|
+
session.fire :connect_failure, buddy: self
|
253
|
+
end
|
254
|
+
|
255
|
+
def connecting?; @connecting; end
|
256
|
+
|
257
|
+
def connect
|
258
|
+
return if connecting? || connected? || blocked?
|
259
|
+
|
260
|
+
@connecting = true
|
261
|
+
@tries += 1
|
262
|
+
@last_try = Time.new
|
263
|
+
|
264
|
+
EM.connect session.tor.host, session.tor.port, Outgoing do |outgoing|
|
265
|
+
outgoing.instance_variable_set :@session, session
|
266
|
+
|
267
|
+
own! outgoing
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def connected?; @connected; end
|
272
|
+
|
273
|
+
def connected
|
274
|
+
return if connected?
|
275
|
+
|
276
|
+
@last_received = Protocol.packet :status, :available
|
277
|
+
|
278
|
+
@connecting = false
|
279
|
+
@connected = true
|
280
|
+
|
281
|
+
@tries = 0
|
282
|
+
@last_try = nil
|
283
|
+
|
284
|
+
ping! send_packet!(:ping, session.address).cookie
|
285
|
+
|
286
|
+
session.fire :connect, buddy: self
|
287
|
+
end
|
288
|
+
|
289
|
+
def verified?; @verified; end
|
290
|
+
|
291
|
+
def verified (incoming)
|
292
|
+
return if verified?
|
293
|
+
|
294
|
+
@verified = true
|
295
|
+
|
296
|
+
own! incoming
|
297
|
+
|
298
|
+
session.fire :verify, buddy: self
|
299
|
+
|
300
|
+
@outgoing.verification_completed
|
301
|
+
@incoming.verification_completed
|
302
|
+
end
|
303
|
+
|
304
|
+
def disconnect
|
305
|
+
return if disconnected?
|
306
|
+
|
307
|
+
@incoming.close_connection_after_writing if @incoming
|
308
|
+
@outgoing.close_connection_after_writing if @outgoing
|
309
|
+
|
310
|
+
@outgoing = nil
|
311
|
+
@incoming = nil
|
312
|
+
|
313
|
+
disconnected
|
314
|
+
end
|
315
|
+
|
316
|
+
def disconnected?; !@connected; end
|
317
|
+
|
318
|
+
def disconnected
|
319
|
+
return if disconnected?
|
320
|
+
|
321
|
+
session.fire :disconnect, buddy: self
|
322
|
+
|
323
|
+
@verified = false
|
324
|
+
@ready = false
|
325
|
+
@connecting = false
|
326
|
+
@connected = false
|
327
|
+
@tries = 0
|
328
|
+
@last_received = nil
|
329
|
+
|
330
|
+
@group_chats.clear
|
331
|
+
|
332
|
+
disconnect
|
333
|
+
end
|
334
|
+
|
335
|
+
def inspect
|
336
|
+
"#<Torchat::Buddy(#{id})#{": #{name}#{", #{description}" if description}" if name}>"
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
end; end
|
341
|
+
|
342
|
+
require 'torchat/session/buddy/joined_group_chats'
|
343
|
+
require 'torchat/session/buddy/latency'
|