Project

General

Profile

« Previous | Next » 

Revision 69a12fdb

Added by Marc Dequènes about 14 years ago

  • ID 69a12fdbdbd27a5673fa8b848b4a03c2aa671004

[evol] conversation/bot protocol rework §6 (refs #30)

View differences:

lib/cyborghood/cyborg/conversation.rb
module BotProtocol
VERSION = "0.1"
CAPABILITIES = []
@@request_callback = proc{|result| process_request_result(result) }
# TODO:
# - check for request/reply couples (reply to wrong of non-existent request)
......
end
end
def process_request_result(result)
if result[:error]
send_error_action(result[:reply_message], result[:error])
else
send_reply_result(result[:reply_message], result[:action_result])
end
end
def receive_announce_helo(message)
unless message.conv_thread.id == 0
return send_quit_decline "bad negociation"
......
@negociation_ok = true
end
def receive_request_capabilities(message)
send_reply_result(message, @conversation.capabilities + CAPABILITIES)
end
def receive_request_call(message)
unless @conversation.bot.interface.is_node? message.parameters[:node]
return send_error_action(message, "bad node")
end
send_reply_ack(message)
@conversation.bot.schedule_task(@@request_callback) do
result = {
:reply_message => message
}
begin
result[:action_result] = @conversation.bot.interface.call(message.conv_thread.session,
message.parameters[:node],
message.parameters[:data])
rescue
result[:error] = $!
end
end
end
def receive_request_exists(message)
unless @conversation.bot.interface.is_node? message.parameters[:node]
return send_error_action(message, "bad node")
end
send_reply_ack(message)
@conversation.bot.schedule_task(@@request_callback) do
{
:reply_message => message,
:action_result => @conversation.bot.interface.has_node? message.parameters[:node]
}
end
end
def receive_request_describe(message)
# TODO: implement when ready in the interface
send_quit_decline(message, "not implemented")
end
def send_announce_helo(recv_message = nil)
action_code = "ANNOUNCE HELO"
message = (recv_message.nil? ? @conversation.thread('system').new_message(action_code) :
......
recv_message.create_reply("ANNOUNCE OK").send
end
def send_request_capabilities
@conversation.thread('system').new_message("REQUEST EXISTS", { :node => node }).send
end
def send_request_call(conv_thread, node)
conv_thread.new_message("REQUEST CALL", { :node => node }).send
end
def send_request_exists(conv_thread, node)
conv_thread.new_message("REQUEST EXISTS", { :node => node }).send
end
def send_request_describe(conv_thread, node)
conv_thread.new_message("REQUEST DESCRIBE", { :node => node }).send
end
def send_error_protocol(error, fatal = false)
@conversation.thread('system').new_message("ERROR PROTOCOL", { :error => error }).send
@conversation.set_error_status(fatal)
end
def send_error_action(recv_message, message)
recv_message.create_reply("ERROR ACTION", { :error => message }).send
def send_error_action(recv_message, error)
recv_message.create_reply("ERROR ACTION", { :error => error }).send
end
def send_reply_ack(recv_message)
......
@protocol = BotProtocol.new(self)
end
def clear_receive_info
@receive_error = false
@receive_fatal_error = false
end
def send_line(msg)
send_data "#{msg}\n"
logger.debug "Sent data [#{identifier}]: #{msg}"
def capabilities
[]
end
def post_init
......
check_errors
end
def check_errors
@error_count += 1 if @receive_error
msg_quit = nil
if @error_count >= MAXIMUM_ERROR_COUNT
msg_quit = "too much errors, terminating"
elsif @fatal_error
msg_quit = "previous fatal error"
end
unless msg_quit.nil?
send_quit_decline msg_quit
close_connection_after_writing
end
end
def receive_message(message)
logger.debug "Received message '#{action}' [#{identifier}]"
......
protected
def clear_receive_info
@receive_error = false
@receive_fatal_error = false
end
def send_line(msg)
logger.debug "Sending data [#{identifier}]: #{msg}"
send_data "#{msg}\n"
end
def check_errors
@error_count += 1 if @receive_error
msg_quit = nil
if @error_count >= MAXIMUM_ERROR_COUNT
msg_quit = "too much errors, terminating"
elsif @fatal_error
msg_quit = "previous fatal error"
end
unless msg_quit.nil?
send_quit_decline msg_quit
close_connection_after_writing
end
end
def new_thread(name, id = nil)
id ||= @next_thread_id
th = ConversationThread.new(self, id, name)
......
def identifier
"unix_socket/#{@signature}"
end
def capabilities
super + []
end
end
end
lib/cyborghood/cyborg/interface.rb
def export_parent_methods
self.export_method *self.superclass.public_instance_methods(false)
end
def is_node?(node)
(node =~ NODE_PATTERN) ? true : false
end
end
def initialize(*args)
......
self.class.auto_export_public_instance_methods = true
end
# convenience method
def is_node?(node)
self.class.is_node?(node)
end
def api_klasses
list = self.class.constants.collect do |c|
cc = self.class.const_get(c)
......
# preliminary incoming message handling
def call(session, cmd, data)
action = find_node_action(session, cmd)
return "551 unknown node" if action.nil?
raise "unknown node" if action.nil?
if data.nil?
formated_data = []
else
begin
formated_data = YAML.load(data) unless data.nil?
rescue
return "552 unreadable YAML data for arguments"
end
return "552 wrong format for arguments" unless formated_data.is_a? Array
end
raise "wrong format for arguments" unless data.is_a? Array
begin
# preliminary outgoing message handling
action.call(*formated_data).to_yaml
action.call(*data)
rescue
logger.debug "node action error message: " + $!
logger.debug "node action error backtrace: " + $!.backtrace.join("\n")
return "550 method call failed: " + $!
raise "method call failed: " + $!
end
end
end
lib/cyborghood/cyborg/server.rb
def unregister_communication(peer)
@comm_list.delete(peer)
end
def schedule_task(callback, &task)
EventMachine.defer(task, callback)
end
end
class BotServerUNIXSocket < BotServer

Also available in: Unified diff