commit f94d64b1dcfe6f1dfa8f92cf0c53f1068b92c497
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Sat Aug 14 18:46:19 2010 +0200

    [evol] work on cyborg server protocol and API #2 (refs #31)

diff --git a/bin/mapmaker b/bin/mapmaker
index d90f449..032a6e0 100755
--- a/bin/mapmaker
+++ b/bin/mapmaker
@@ -54,10 +54,10 @@ module CyborgHood
 
     class MapMakerInterface < CyborgServerDefaultInterface
       class DNS < CyborgServerInterface
-        def api_zone_exists?
+        def api_zone_exists?(data)
+pp data
           "coucou"
         end
-        split_mode_command :api_zone_exists?
       end
     end
   end
diff --git a/lib/cyborghood/cyborg/interface.rb b/lib/cyborghood/cyborg/interface.rb
index e9472c5..c9f3241 100644
--- a/lib/cyborghood/cyborg/interface.rb
+++ b/lib/cyborghood/cyborg/interface.rb
@@ -23,22 +23,6 @@ module CyborgHood
   class CyborgServerInterface
     include Singleton
 
-    @split_mode_commands = []
-
-    class << self
-      attr_reader :split_mode_commands
-    end
-
-    def self.split_mode_command(*syms)
-      new_split_mode_commands = self.split_mode_commands || []
-      syms.each do |sym|
-        raise CyberError.new(:unrecoverable, "programmation", "not a symbol") unless sym.is_a? Symbol
-        raise CyberError.new(:unrecoverable, "programmation", "not an API method") unless api_method_name?(sym.to_s)
-        new_split_mode_commands << sym
-      end
-      instance_variable_set(:@split_mode_commands, new_split_mode_commands)
-    end
-
     def self.decompose_command(cmd)
       object, method = cmd.split('.', 2)
 
@@ -60,13 +44,6 @@ module CyborgHood
       [klass, method]
     end
 
-    def self.is_split_mode_command?(cmd)
-      klass, method = decompose_command(cmd)
-      return false if klass.nil?
-
-      (klass.split_mode_commands || []).include? api_method_to_class_method_name(method)
-    end
-
     def self.api_method_name?(method)
       method =~ /^api_(.+)$/
       $1
@@ -91,8 +68,17 @@ module CyborgHood
       @methods ||= self.methods.collect{|m| self.class.api_method_name?(m) }.compact
     end
 
+    def self.has_node?(cmd)
+      klass, method = self.decompose_command(cmd)
+      return false if klass.nil?
+      return true if method.nil?
+
+      inst = klass.instance
+      inst.api_methods.include?(method)
+    end
+
     # preliminary incoming message handling
-    def call(cmd, args, data)
+    def call(cmd, data)
       klass, method = self.class.decompose_command(cmd)
       return "551 unknown object" if klass.nil?
 
@@ -103,15 +89,22 @@ module CyborgHood
       end
 
       begin
-        formated_data = data.to_yaml
+        formated_data = YAML.load(data) unless data.nil?
       rescue
-        return "552 wrong format for extra data"
+        return "552 unreadable data for arguments"
       end
 
+      return "552 wrong format for arguments" unless formated_data.is_a? Array
+
       begin
         # preliminary outgoing message handling
         real_method = self.class.api_method_to_class_method_name(method)
-        r = inst.send(real_method, *args) { formated_data }
+        #if inst.method(real_method).arity > 0
+          r = inst.send(real_method, *formated_data)
+        #else
+        #  return "552 method does not take any argument" if formated_data
+        #  r = inst.send(real_method)
+        #end
 
         r.to_yaml
       rescue
diff --git a/lib/cyborghood/cyborg/server.rb b/lib/cyborghood/cyborg/server.rb
index 3d3ef11..281d981 100644
--- a/lib/cyborghood/cyborg/server.rb
+++ b/lib/cyborghood/cyborg/server.rb
@@ -81,6 +81,7 @@ module CyborgHood
     MaxLineLength = 16*1024
 
     EOD = "\033[0J"
+    NODE_PATTERN = /^([a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*[?=]?)(?: ([+?]+))?$/
 
     def initialize(interface)
       @interface = interface
@@ -90,7 +91,6 @@ module CyborgHood
       @config = Config.instance
       @split_data_mode = false
       @split_data_cmd = nil
-      @split_data_cmd_args = []
       @split_data = []
     end
 
@@ -119,28 +119,32 @@ module CyborgHood
         else
           logger.debug "Received data [#{identifier}]: #{data}"
 
-          begin
-            cmd_parts = Shellwords.shellsplit(data)
-          rescue
+          unless data =~ NODE_PATTERN
             logger.error "Error [#{identifier}]: syntax error"
-            send_line "552 syntax error"
+            send_line "552 syntax error in command"
             return
           end
-          cmd = cmd_parts.shift
-          args = cmd_parts
+          cmd = $1
+          flags = $2 || ""
 
-          if @interface.is_split_mode_command? cmd
-            enter_split_mode(cmd, args)
+          if flags.index '?'
+            send_line "250+ ok"
+            send_line({'exists?' => @interface.has_node?(cmd)}.to_yaml)
+            return
+          end
+
+          if flags.index '+'
+            enter_split_mode(cmd)
           else
-            receive_command(cmd, args)
+            receive_command(cmd)
           end
         end
       end
     end
 
-    def receive_command(cmd, args, data = nil)
+    def receive_command(cmd, data = nil)
       logger.debug "Executing command '#{cmd}' [#{identifier}]"
-      send_line @interface.instance.call(cmd, args, data)
+      send_line @interface.instance.call(cmd, data)
     end
 
     def receive_error(msg)
@@ -153,18 +157,16 @@ module CyborgHood
 
     protected
 
-    def enter_split_mode(cmd, args)
+    def enter_split_mode(cmd)
       if @split_data_mode
         logger.error "Error [#{identifier}]: already in split mode"
         send_line "551 protocol error"
         @split_data_mode = false
         @split_data_cmd = nil
-        @split_data_cmd_args = []
       else
         logger.debug "Entered split mode for command '#{cmd}' [#{identifier}]"
         @split_data_mode = true
         @split_data_cmd = cmd
-        @split_data_cmd_args = args
       end
       @split_data = []
     end
@@ -172,14 +174,13 @@ module CyborgHood
     def exit_split_mode
       if @split_data_mode
         logger.debug "Quit split mode for command '#{@split_data_cmd}' [#{identifier}]"
-        receive_command(@split_data_cmd, @split_data_cmd_args, @split_data.join("\n"))
+        receive_command(@split_data_cmd, @split_data.join("\n"))
       else
         logger.error "Error [#{identifier}]: not in split mode"
         send_line "551 protocol error"
       end
       @split_data_mode = false
       @split_data_cmd = nil
-      @split_data_cmd_args = []
       @split_data = []
     end
   end
