Project

General

Profile

« Previous | Next » 

Revision 21a7eaf9

Added by Marc Dequènes about 14 years ago

  • ID 21a7eaf9331ab26b1c1d5ff7173c4b248f6a2967

[evol] conversation/bot protocol rework §8 (refs #30): preliminary client-side protocol handling

View differences:

bin/mapmaker_client
contact_peer("MapMaker") do |conv|
if conv
logger.info "Yo ! Conversation ready with MapMaker (#{conv.peer_name}) !"
conv_thread = conv.thread("plop")
conv.protocol.send_request_call(conv_thread, "/") do |reply|
pp reply
end
else
logger.error "Could not connect to MapMaker"
stop
lib/cyborghood/cyborg/conversation.rb
@action_id = @conv_thread.next_action_id if @action_id.nil?
@conv_thread.conversation.send_message(self)
@sent = true
# return message (convenience)
self
end
def create_reply(action_code, parameters = nil)
......
MAXIMUM_ERROR_COUNT = 3
MAXIMUM_LINES = 1024
attr_reader :bot, :peer_name, :peer_capabilities
attr_reader :bot, :peer_name, :peer_capabilities, :protocol
def initialize(bot, block = nil)
@bot = bot
lib/cyborghood/cyborg/protocol.rb
VERSION = "0.1"
CAPABILITIES = []
@@request_callback = proc{|result| process_request_result(result) }
@@request_callback = proc do |result|
protocol = result[:reply_message].conv_thread.conversation.protocol
protocol.process_request_result(result)
end
# TODO:
# - check for request/reply couples (reply to wrong of non-existent request)
......
@negociation_received = false
@negociation_sent = false
@negociation_ok = false
end
def self.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
@action_followup = {}
end
def negociation_ok?
......
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"
......
message.action_parameters[:node],
message.action_parameters[:data])
rescue
result[:error] = $!
result[:error] = $!.to_s
end
result
end
end
......
def receive_request_describe(message)
# TODO: implement when ready in the interface
send_quit_decline(message, "not implemented")
send_reply_decline(message, "not implemented")
end
def receive_error_protocol(message)
logger.error "received protocol error notification from '#{@conversation.peer_name}': #{message.action_parameters[:error]}"
end
def receive_error_action(message)
cb = pop_callback(message)
if cb
cb.call({:reply => :error, :reason => message.action_parameters[:error]})
else
send_error_protocol("received reply for unknown action")
end
end
def receive_reply_ack(message)
# TODO
end
def receive_reply_decline(message)
cb = pop_callback(message)
if cb
cb.call({:reply => :decline, :reason => message.action_parameters[:reason]})
else
send_error_protocol("received reply for unknown action")
end
end
def receive_reply_result(message)
cb = pop_callback(message)
if cb
cb.call({:reply => :ok, :result => message.action_parameters[:result]})
else
send_error_protocol("received reply for unknown action")
end
end
def receive_quit_decline(message)
logger.warning "peer '#{@conversation.peer_name}' refused more conversation: #{message.action_parameters[:reason]}"
@conversation.set_comm_stop(true)
# TODO: notify client
end
def receive_quit_leaving(message)
logger.info "peer '#{@conversation.peer_name}' is leaving"
@conversation.set_comm_stop(true)
# TODO: notify client
end
......
@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
def send_request_call(conv_thread, node, &callback)
message = conv_thread.new_message("REQUEST CALL", { :node => node }).send
register_callback(message, callback)
end
def send_request_exists(conv_thread, node)
conv_thread.new_message("REQUEST EXISTS", { :node => node }).send
message = conv_thread.new_message("REQUEST EXISTS", { :node => node }).send
register_callback(message, callback)
end
def send_request_describe(conv_thread, node)
conv_thread.new_message("REQUEST DESCRIBE", { :node => node }).send
message = conv_thread.new_message("REQUEST DESCRIBE", { :node => node }).send
register_callback(message, callback)
end
def send_error_protocol(error, fatal = false)
......
end
def send_reply_result(recv_message, result)
recv_message.create_reply("REPLY ACK", { :result => result }).send
recv_message.create_reply("REPLY RESULT", { :result => result }).send
end
def send_quit_decline(reason)
......
@conversation.thread('system').new_message("QUIT LEAVING").send
end
end
protected
def register_callback(message, callback)
@action_followup[message.conv_thread.id] ||= {}
@action_followup[message.conv_thread.id][message.action_id] = callback
end
def pop_callback(message)
return nil unless @action_followup.has_key? message.conv_thread.id
return nil unless @action_followup[message.conv_thread.id].has_key? message.action_id
cb = @action_followup[message.conv_thread.id][message.action_id]
@action_followup[message.conv_thread.id].delete message.action_id
@action_followup.delete message.conv_thread.id if @action_followup[message.conv_thread.id].empty?
cb
end
end
end

Also available in: Unified diff