Revision d9694ad7
Added by Marc Dequènes almost 14 years ago
- ID d9694ad7d8ecf4074becfbe41455a7d2535962ca
lib/cyborghood/cyborg/conversation.rb | ||
---|---|---|
MAXIMUM_ERROR_COUNT = 3
|
||
MAXIMUM_LINES = 1024
|
||
|
||
attr_reader :bot, :peer_name, :peer_capabilities, :protocol
|
||
attr_reader :bot, :peer_name, :peer_capabilities, :protocol, :auto_close_threads
|
||
|
||
def initialize(bot, block = nil)
|
||
@bot = bot
|
||
... | ... | |
@comm_stop = false
|
||
|
||
# associated conversation threads
|
||
@auto_close_threads = 60 # max idle time before closing (nil => never close threads)
|
||
@conv_threads = {}
|
||
@conv_threads_index = {}
|
||
@conv_threads_timers = {}
|
||
@conv_threads_closing = []
|
||
# thread 0 is reserved
|
||
@next_thread_id = 0
|
||
@system_thread = self.thread('system')
|
||
... | ... | |
def receive_message(message)
|
||
logger.debug "Received message '#{message.action_code}' [#{identifier}]"
|
||
|
||
reset_idle_thread_check(message.conv_thread)
|
||
|
||
@protocol.process_received_message(message)
|
||
|
||
check_idle_thread(message.conv_thread)
|
||
end
|
||
|
||
def receive_error(msg)
|
||
... | ... | |
# ignore mistakes
|
||
return unless @conv_threads.has_key? name
|
||
|
||
@conv_threads_closing << name
|
||
|
||
@conv_threads[name].close
|
||
|
||
# if only the system thread remains, notify idleness
|
||
... | ... | |
@conv_threads_index.delete(th.id)
|
||
@conv_threads.delete(th.name)
|
||
@pending_thread_close.delete(th.name)
|
||
@conv_threads_closing.delete(th.name)
|
||
end
|
||
|
||
def send_message(message)
|
||
raise CyberError.new(:unrecoverable, "bot/conversation", "Cannot send message without action id") if message.action_id.nil?
|
||
|
||
reset_idle_thread_check(message.conv_thread)
|
||
|
||
flags = ""
|
||
flags += "+" unless message.action_parameters.nil?
|
||
|
||
... | ... | |
message.action_parameters.to_yaml.each_line {|l| send_line l }
|
||
send_line EOD
|
||
end
|
||
|
||
check_idle_thread(message.conv_thread)
|
||
end
|
||
|
||
def identifier
|
||
... | ... | |
th_name = msg[:thread]
|
||
close_thread(th_name) if @pending_thread_close.include? th_name
|
||
end
|
||
|
||
def reset_idle_thread_check(conv_thread)
|
||
return if @auto_close_threads.nil?
|
||
return if @conv_threads_closing.include? conv_thread.name
|
||
|
||
# ignore system thread
|
||
return if conv_thread.name == "system"
|
||
|
||
logger.debug "Thread '#{conv_thread.name}@#{@peer_name}' is working, canceling idle check"
|
||
|
||
# cancel time if exists
|
||
timer = @conv_threads_timers[conv_thread.id]
|
||
EventMachine.cancel_timer(timer) unless timer.nil?
|
||
@conv_threads_timers[conv_thread.id] = nil
|
||
end
|
||
|
||
def check_idle_thread(conv_thread)
|
||
return if @auto_close_threads.nil?
|
||
return if @conv_threads_closing.include? conv_thread.name
|
||
|
||
# ignore system thread
|
||
return if conv_thread.name == "system"
|
||
|
||
# if a timer is running, do nothing
|
||
return unless @conv_threads_timers[conv_thread.id].nil?
|
||
|
||
# test for idleness
|
||
return unless conv_thread.idle?
|
||
logger.debug "Thread '#{conv_thread.name}@#{@peer_name}' is currently idle, doing another check in #{@auto_close_threads}s"
|
||
|
||
# set timer for closing
|
||
@conv_threads_timers[conv_thread.id] = EventMachine.add_timer(@auto_close_threads) do
|
||
@conv_threads_timers[conv_thread.id] = nil
|
||
# if it is not idle, then do nothing, wait for another call to check_idle_thread
|
||
if conv_thread.idle?
|
||
logger.debug "Thread '#{conv_thread.name}@#{@peer_name}' is still idle, closing"
|
||
close_thread(conv_thread.name)
|
||
else
|
||
logger.debug "Thread '#{conv_thread.name}@#{@peer_name}' is no more idle"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
Also available in: Unified diff
[evol] Botnet Conversation: created a new idle threads check (old method is pending for removal)