commit 1ae083644216cb17310f5b1b56846fa7dd9bf934
Author: ygrek <ygrek@autistici.org>
Date:   Sun Sep 5 23:36:46 2010 +0300

    GUI protocol: add opcode to retrieve servers list
    
    currently implemented for DC

diff --git a/src/daemon/common/commonNetwork.ml b/src/daemon/common/commonNetwork.ml
index 2090af6..bf69c49 100644
--- a/src/daemon/common/commonNetwork.ml
+++ b/src/daemon/common/commonNetwork.ml
@@ -114,6 +114,8 @@ let check_network_implementations () =
         lprintf_nl "op_network_porttest_result";
       if c.op_network_check_upload_slots == cc.op_network_check_upload_slots then 
         lprintf_nl "op_network_check_upload_slots";
+      if c.op_network_all_servers == cc.op_network_all_servers then 
+        lprintf_nl "op_network_all_servers";
   ) !networks_ops;
   lprint_newline ()
 
@@ -256,6 +258,7 @@ let network_display_stats n o = n.op_network_display_stats o
 let network_info n = n.op_network_info ()
 let network_stat_info_list n = n.op_network_stat_info_list ()
 let network_gui_message n s u = n.op_network_gui_message s u
+let network_all_servers n = n.op_network_all_servers ()
 
 let new_network shortname name ?comment flags = 
   let manager = TcpBufferedSocket.create_connection_manager name in
@@ -301,6 +304,7 @@ let new_network shortname name ?comment flags =
       op_network_porttest_start = (fun _ -> ni_ok name "porttest_start");
       op_network_porttest_result = (fun _ -> fni name "porttest_result");
       op_network_check_upload_slots = (fun _ -> ni_ok name "check_upload_slots");
+      op_network_all_servers = (fun () -> ni_ok name "all_servers"; []);
     }
   in
   (* attempt: what is this cast for ? *)
diff --git a/src/daemon/common/commonNetwork.mli b/src/daemon/common/commonNetwork.mli
index d68185d..8dcd408 100644
--- a/src/daemon/common/commonNetwork.mli
+++ b/src/daemon/common/commonNetwork.mli
@@ -228,6 +228,11 @@ val network_info : CommonTypes.network -> CommonTypes.network_info
 val network_stat_info_list : CommonTypes.network -> 
   (string * int * CommonTypes.network_stat_info list) list
 
+(** call the op_network_all_servers method of a network.
+    Get the list of all possible servers known for this network.
+    @return list of lists of key-value pairs (network dependent) describing servers *)
+val network_all_servers : CommonTypes.network -> (string * string) list list
+
 (** call the op_network_gui_message method of a network.
     Handle a message received from a GUI.
     @param network instance
diff --git a/src/daemon/common/commonTypes.ml b/src/daemon/common/commonTypes.ml
index a6c0e83..e280df4 100644
--- a/src/daemon/common/commonTypes.ml
+++ b/src/daemon/common/commonTypes.ml
@@ -594,6 +594,7 @@ and network = {
     mutable op_network_porttest_start : (unit -> unit);
     mutable op_network_porttest_result : (unit -> network_porttest);
     mutable op_network_check_upload_slots : (unit -> unit);
+    mutable op_network_all_servers : (unit -> (string*string) list list);
   }
 
 and ui_user = {
diff --git a/src/daemon/common/guiDecoding.ml b/src/daemon/common/guiDecoding.ml
index 8967060..7c91874 100644
--- a/src/daemon/common/guiDecoding.ml
+++ b/src/daemon/common/guiDecoding.ml
@@ -1042,7 +1042,6 @@ let get_shared_info_version_10 proto s pos =
 
 let from_gui (proto : int array) opcode s =
   try
-
     let proto = if opcode > from_gui_last_opcode then 0 else proto.(opcode) in
     if !verbose_gui_decoding then
       lprintf_nl "[gDe] FROM_GUI: Opcode %d %s" opcode (String.escaped s);
@@ -1328,6 +1327,10 @@ let from_gui (proto : int array) opcode s =
          let num = get_int s 2 in
          GetStats num
 
+    | 69 ->
+         let num = get_int s 2 in
+         GetServersList num
+
     | _ -> 
         lprintf_nl "FROM GUI:Unknown message %d" opcode; 
         raise FromGuiMessageNotImplemented
@@ -1790,7 +1793,28 @@ let to_gui (proto : int array)  opcode s =
     | 58 ->
         let s, pos = get_string s 2 in 
         Version s
-        
+
+(*
+    | 59 ->
+    Stats (num, l) ->
+        let proto = proto.(59) in
+        let num = get_int s 2 in
+        let l = get_list (fun s pos ->
+          get_st
+          let (s1,pos) = get_string s pos in
+          let (s2,pos) = get_string s pos in
+          (s1,s2))
+        buf_int buf num;
+        buf_list2 proto buf buf_stat_info_list l
+*)
+
+    | 60 ->
+        let (l,_) = get_list (get_list (fun s pos ->
+            let (s1,pos) = get_string s pos in
+            let (s2,pos) = get_string s pos in
+            (s1,s2),pos)) s 2 in
+        ServersList l
+
     | _ -> 
         lprintf_nl "TO GUI:Unknown message %d" opcode; 
         raise Not_found
diff --git a/src/daemon/common/guiEncoding.ml b/src/daemon/common/guiEncoding.ml
index 49c1b66..6994cbd 100644
--- a/src/daemon/common/guiEncoding.ml
+++ b/src/daemon/common/guiEncoding.ml
@@ -139,7 +139,11 @@ let buf_int64_28 proto buf i =
     buf_int64 buf i
   else
     buf_int64_32 buf i
-  
+
+let buf_pair f1 f2 buf (x,y) =
+  f1 buf x;
+  f2 buf y
+
 let rec buf_query buf q =
   match q with
     Q_AND list ->
@@ -1050,6 +1054,11 @@ let rec to_gui (proto : int array) buf t =
         buf_int buf num;
         buf_list2 proto buf buf_stat_info_list l
 
+    | ServersList l ->
+(*         let proto = proto.(60) in *)
+        buf_opcode buf 60;
+        buf_list buf (fun buf l -> buf_list buf (buf_pair buf_string buf_string) l) l
+
   with e ->
       lprintf "GuiEncoding.to_gui: Exception %s\n"
         (Printexc2.to_string e)
@@ -1266,6 +1275,9 @@ protocol version. Do not send them ? *)
     | GetStats n ->
         buf_opcode buf 68;
         buf_int buf n
+    | GetServersList n ->
+        buf_opcode buf 69;
+        buf_int buf n
 
   with e ->
       lprintf "GuiEncoding.from_gui: Exception %s\n"
@@ -1336,11 +1348,14 @@ let _ =
     assert (check_to_gui (Room_remove_user (5,6)));
     assert (check_to_gui (Shared_file_upload (1, Int64.zero, 32)));
     assert (check_to_gui (Shared_file_unshared 2));
+    assert (check_to_gui (ServersList [["name","server1"];["name","server2"]]));
 (* Shared_file_info ??? *)
 (*
   assert (check_to_gui (Add_section_option ("section", "message", "option", StringEntry )));
   assert (check_to_gui (Add_plugin_option ("section", "message", "option", StringEntry )));
-*)  
+*)
+    (* proto arrays from_gui and to_gui have different length! *)
+    let proto = Array.create (from_gui_last_opcode+1) best_gui_version in
     let check_from_gui = 
       check (from_gui proto)  (GuiDecoding.from_gui proto) in
     assert (check_from_gui (MessageToClient (33, "Bye")));
@@ -1352,5 +1367,6 @@ let _ =
     assert (check_from_gui RefreshUploadStats) ; 
     assert (check_from_gui (SetFilePriority (5,6)));
     assert (check_from_gui (Password ("mldonkey", "toto")));
+    assert (check_from_gui (GetServersList 2));
   done
-  
+
diff --git a/src/daemon/common/guiProto.ml b/src/daemon/common/guiProto.ml
index 4cd44f6..304c412 100644
--- a/src/daemon/common/guiProto.ml
+++ b/src/daemon/common/guiProto.ml
@@ -29,9 +29,9 @@ type gift_command =
   
 let gui_extension_poll = 1
   
-let to_gui_last_opcode = 59
-let from_gui_last_opcode = 68
-let best_gui_version = 41
+let to_gui_last_opcode = 60
+let from_gui_last_opcode = 69
+let best_gui_version = 42
   
 (* I will try to report all changes to the protocol here: send me patches
 if I don't !
@@ -66,11 +66,15 @@ Version 32:
 Version 33:
   CORE -> GUI: message 15 [CLIENT_INFO] encoding and decoding of the field client_release 
 
+Version 42:
+  GUI -> CORE: message 69 [GET_SERVERS_LIST]
+  CORE -> GUI: message 60 [SERVERS_LIST]
+
   *)
-  
-  
+
+
 type from_gui =
-(* These two messages are protocol independant: they MUST be sent to
+(* These two messages are protocol independent: they MUST be sent to
   establish the connection. *)
 | GuiProtocol of int
 | Password of string * string
@@ -168,6 +172,9 @@ the messages (it will use the version specified in CoreProtocol instead
 | ServerSetPreferred of (int * bool)
 | GetStats of int
 
+(* proto 42 *)
+| GetServersList of int (* get all servers for specified network *)
+
 type to_gui =
 (* This message is the first message sent by the core *)
 | CoreProtocol of int * int * int
@@ -235,7 +242,11 @@ type to_gui =
 | GiftServerAttach of string * string
 | GiftServerStats of (string * string * string * string) list
 | Stats of int * (string * int * network_stat_info list) list  
-  
+
+(* proto 42 *)
+| ServersList of (string * string) list list 
+  (** list of servers, each server represented as list of network-specific attributes *)
+
   
 let string_of_from_gui t = 
   match t with
@@ -315,6 +326,8 @@ let string_of_from_gui t =
   | ServerSetPreferred _ -> "ServerSetPreferred"
   | GetStats _ -> "GetStats"
 
+  | GetServersList _ -> "GetServersList"
+
 let string_of_to_gui t =
   match t with
   
@@ -380,11 +393,13 @@ let string_of_to_gui t =
   | Pending _ -> "Pending"
   | Search _ -> "Search"
   | Version _ -> "Version"
-      
+
   | GiftServerAttach _ -> "GiftServerAttach"
   | GiftServerStats _ -> "GiftServerStats"
   | Stats _ -> "Stats"
-      
+
+  | ServersList _ -> "ServersList"
+
 type gui_record = {
     mutable gui_num : int;
     mutable gui_search_nums : int list;
diff --git a/src/daemon/driver/driverInterface.ml b/src/daemon/driver/driverInterface.ml
index 5f4373b..c7e5ac4 100644
--- a/src/daemon/driver/driverInterface.ml
+++ b/src/daemon/driver/driverInterface.ml
@@ -1110,10 +1110,10 @@ let gui_reader (gui: gui_record) t _ =
               let s = server_find num in
               server_rename s name
           | P.ServerSetPreferred (num, preferred) ->
-	      if user2_is_admin gui.gui_conn.conn_user.ui_user then
+              if user2_is_admin gui.gui_conn.conn_user.ui_user then
                 server_set_preferred (server_find num) preferred
-	      else
-	        begin
+              else
+                begin
                   let o = gui.gui_conn in
                   let buf = o.conn_buf in
                   Buffer.reset buf; 
@@ -1121,7 +1121,11 @@ let gui_reader (gui: gui_record) t _ =
                   gui_send gui (P.Console (
                       DriverControlers.dollar_escape o false
                         (Buffer.contents buf)))
-		end
+                end
+          | P.GetServersList num ->
+              let n = network_find_by_num num in
+              let l = network_all_servers n in
+              gui_send gui (P.ServersList l)
 
   with 
     Failure s ->
diff --git a/src/networks/direct_connect/dcMain.ml b/src/networks/direct_connect/dcMain.ml
index 9449d5d..89afa55 100644
--- a/src/networks/direct_connect/dcMain.ml
+++ b/src/networks/direct_connect/dcMain.ml
@@ -242,6 +242,13 @@ let _ =
   network.op_network_reset <- (fun _ -> ());
   network.op_network_porttest_result <- (fun _ -> PorttestNotAvailable);
   network.op_network_check_upload_slots <- (fun _ -> ());
+  network.op_network_all_servers <- (fun () ->
+    List.map (fun h -> [
+      "name",h.dc_name; 
+      "host",Ip.string_of_addr h.dc_ip;
+      "port",string_of_int h.dc_port;
+      "info",h.dc_info;
+      "users",string_of_int h.dc_nusers]) !dc_hublist);
 
   CommonInteractive.register_gui_options_panel "DC" gui_dc_options_panel; 
   
