mldonkey-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Mldonkey-users] Overnet support - patch number 1.1


From: Norbert LATAILLE
Subject: Re: [Mldonkey-users] Overnet support - patch number 1.1
Date: 08 Dec 2002 21:14:47 +0100

Here is the complete patch, with the lastest fix.

sorry for the bad submition.

Norbert

Le dim 08/12/2002 à 21:07, Norbert LATAILLE a écrit :
> Oups,
> 
> forgot one line, please apply this patch too to load correctly
> servers.ini :
> 
> diff -u -r mldonkey/donkey/donkeyOvernet.ml
> mldonkey-ov1/donkey/donkeyOvernet.ml
> --- mldonkey/donkey/donkeyOvernet.ml    2002-12-08 20:59:21.000000000
> +0100
> +++ mldonkey-ov1/donkey/donkeyOvernet.ml        2002-12-08
> 19:18:21.000000000 +0100
> @@ -92,7 +92,7 @@
>           global_peers_size.(t_md4)<-global_peers_size.(t_md4)+1;
>            (t_md4,v_md4, {
>              peer_md4 = v_md4;
> -            peer_ip = Ip.value_to_ip ip;
> +            peer_ip = Ip.value_to_ip port;
>              peer_port = value_to_int port;
>              peer_kind = value_to_int kind;
>              peer_last_msg = last_time ();
> 
> 
> Le dim 08/12/2002 à 20:21, Norbert LATAILLE a écrit :
> > Hi,
> > 
> > Here is the first patch for a more complete overnet support in mldonkey.
> > It is diffed against mldonkey-pango-20021201a sources, found on
> > http://concept.free.free.fr/mldonkey/.
> > 
> > Please keep in mind that this is the first version of this overnet
> > update, it does not expose much configuration options. I am looking for
> > feedback, tell me if it works !
> > 
> > This overnet patch is still in developpement, next steps are :
> > - better search
> > - complete network insertion : answer Queries from other Overnet peers
> > (keyword and files)
> > 
> > Norbert
> > 
> > DONE
> > ----
> > 
> > - Fix: PUBLISH works
> > - Fix: Never add ourself in the peer list
> > - Fix: never add 0.0.0.0 or a local address for a distant peer
> > - Fix: Search and Publish fixes
> > - Fix: Removed BCP type2 support for now
> > - Add opcode 12/13/27/28/29 support
> > - Remove fixed overnet_md4 address
> > - Advertize every 20 minutes the network AND close peers that we are up
> > - New peer storage system : there is now only one peer list (Hashtbl
> > array) in the core which replaces all peer lists.
> >    - it enables powerful functions like get_uniform_distribution() and
> > get_local_distribution(md4)
> >    - gives an efficient way to answer searches
> > - Remove the "connected network" schema : we only send Connect if
> > necessary, we no longer try to check a "connected peers subset" every x
> > minutes. Moreover, we try to keep an uniform peer table (to have a good
> > view of the network) : try ovstats command.
> > 
> > 
> > TODO:
> > - Add new opcode support 30/21/22
> > - Add BCP type2 support again
> > - Answer Search and FileSearch requests
> > - Make the search more efficient/less aggressive
> > 
> > - Update get_local_distrib for more accurate responses
> > - Wait before sending 29 (is there a way to flush the udp_sock buffer ?)
> > 
> > 
> > 
> > ----
> > 
> 
> > diff -u -r mldonkey-pango-20021201a/donkey/donkeyOvernet.ml 
> > mldonkey/donkey/donkeyOvernet.ml
> > --- mldonkey-pango-20021201a/donkey/donkeyOvernet.ml        2002-12-01 
> > 17:27:42.000000000 +0100
> > +++ mldonkey/donkey/donkeyOvernet.ml        2002-12-08 19:18:21.000000000 
> > +0100
> > @@ -36,32 +36,80 @@
> >  open DonkeyMftp
> >  open DonkeyProtoOvernet
> >  
> > -let publish_implemented = false
> > -  
> > +(*
> > +DONE
> > +----
> > +Fix: Never add ourself in the peer list
> > +Fix: never add 0.0.0.0 or a local address for a distant peer
> > +Fix: Search and Publish fixes
> > +Fix: Removed BCP type2 support for now
> > +Add packets type 12/13/27/28/29 support
> > +Remove fixed overnet_md4 address
> > +advertize every 20 minutes the network AND close peers that we are up
> > +new peer storage system : there is now only one peer list (Hashtbl array) 
> > in the core
> > +   enables powerful get_uniform_distrib() and get_local_distrib(md4) 
> > functions
> > +   gives an efficient way to answer seaches
> > +Remove the "connected network" schema : we only send Connect if necessary, 
> > we no longer 
> > +   try to check a "connected peers subset" every x minutes.
> > +*)
> > +
> > +(*
> > +TODO:
> > +Add new opcode support 30/21/22
> > +Readd BCP type2 support
> > +Answer Search and FileSearch requests
> > +Make the search more efficient/less aggressive
> > +--
> > +Update get_local_distrib for more accurate responses
> > +Wait before sending 29 (is there a way to flush the udp_sock buffer ?)
> > +*)
> > +
> > +module XorSet = Set.Make (
> > +  struct
> > +    type t = Md4.t * peer
> > +    let compare (m1,p1) (m2,p2) = 
> > +      compare (m1,p1.peer_md4, p1.peer_ip) (m2,p2.peer_md4, p2.peer_ip)
> > +  end
> > +)
> > +
> > +let publish_implemented = true
> > +
> > +let global_peers_size = Array.make 256 0
> > +
> > +(* overnet_md4 should be different from client_md4 for protocol safety 
> > reasons *)
> > +let overnet_md4 = Md4.random()
> > +
> > +let max_peer_by_peerblock = 64
> > +
> >  module PeerOption = struct
> >      
> >      let value_to_peer v = 
> >        match v with
> >          SmallList [md4; ip; port; kind]
> >        | List [md4; ip; port; kind] ->
> > -          {
> > -            peer_md4 = Md4.value_to_md4 md4; 
> > -            peer_ip = Ip.value_to_ip ip; 
> > +     let v_md4 = Md4.value_to_md4 md4 in
> > +     let t_md4 = Md4.up v_md4 in
> > +     global_peers_size.(t_md4)<-global_peers_size.(t_md4)+1;
> > +          (t_md4,v_md4, {
> > +            peer_md4 = v_md4; 
> > +            peer_ip = Ip.value_to_ip port; 
> >              peer_port = value_to_int port; 
> >              peer_kind = value_to_int kind; 
> >              peer_last_msg = last_time ();
> > -          }
> > +          });
> >        | _ -> assert false
> >            
> > -    let peer_to_value p = 
> > -      SmallList [
> > -        Md4.md4_to_value p.peer_md4; 
> > -        Ip.ip_to_value p.peer_ip;
> > -        int_to_value p.peer_port;
> > -        int_to_value p.peer_kind]
> > -      
> > -    let t = define_option_class "Peer" value_to_peer peer_to_value      
> > +    let peer_to_value v = 
> > +      match v with 
> > +   (_,_,p) ->
> > +     SmallList [
> > +          Md4.md4_to_value p.peer_md4;
> > +          Ip.ip_to_value p.peer_ip;
> > +          int_to_value p.peer_port;
> > +          int_to_value p.peer_kind
> > +   ]
> >        
> > +    let t = define_option_class "Peer" value_to_peer peer_to_value
> >    end
> >    
> >  let overnet_port = 
> > @@ -86,11 +134,10 @@
> >    "maximal number of peers mldonkey should connect at beginning" 
> >      int_option 50
> >  
> > -let overnet_peers = define_option servers_ini 
> > +let global_peers : (Md4.t, peer) Hashtbl.t array Options.option_record = 
> > define_option servers_ini 
> >      ["overnet_peers"] "List of overnet peers"
> > -    (list_option PeerOption.t)
> > -  []
> > -      
> > +    (list_option2 Md4.null PeerOption.t) (Array.init 256 (fun _ -> 
> > Hashtbl.create 10))
> > +
> >  let overnet_search_timeout = 
> >    define_option downloads_ini ["overnet_search_timeout"] 
> >    "How long shoud a search on Overnet wait for the last reply before 
> > terminating"
> > @@ -100,7 +147,6 @@
> >    define_option downloads_ini ["overnet_query_peer_period"] 
> >    "Period between two queries in the overnet tree (should not be set under 
> > 5)"
> >      float_option 5. 
> > -
> >        
> >  let overnet_max_search_hits = 
> >    define_option downloads_ini ["overnet_max_search_hits"] 
> > @@ -111,7 +157,6 @@
> >    define_option downloads_ini ["overnet_max_waiting_peers"] 
> >    "Max number of peers waiting in a search on Overnet"
> >      int_option 50 
> > -
> >        
> >  let gui_overnet_options_panel = 
> >    define_option downloads_ini ["gui_overnet_options_panel"]
> > @@ -130,7 +175,6 @@
> >      "Search Max Waiting Peers", shortname overnet_max_waiting_peers, "T";
> >    ]
> >    
> > -  
> >  let udp_sock = ref None  
> >  
> >  let buf = Buffer.create 2000
> > @@ -148,8 +192,7 @@
> >          if !!verbose_overnet then begin            
> >              Printf.printf "Sending UDP to %s:%d" (Ip.to_string ip) port;
> >              print_newline ();
> > -            dump s;
> > -            print_newline ();
> > +            (*dump s; print_newline ();*)
> >            end;
> >          let len = String.length s in
> >          UdpSocket.write sock s 0 (String.length s) addr
> > @@ -157,30 +200,134 @@
> >            Printf.printf "Exception %s in udp_send" (Printexc.to_string e);
> >            print_newline () 
> >              
> > -let (peers_queue : (Ip.t * int) Fifo.t) = Fifo.create ()
> > -  
> > -let peers_by_md4 = Hashtbl.create 1000
> > -
> >  let search_hits = ref 0
> >  let source_hits = ref 0
> > -  
> > -let add_peer peer =
> > -  if not (Hashtbl.mem peers_by_md4 peer.peer_md4) &&
> > -     not ( is_black_address peer.peer_ip peer.peer_port ) then
> > +
> > +let remove_old_global_peers () =
> > +  for i=0 to 255 do 
> > +    Hashtbl.iter ( fun a b -> 
> > +      if (b.peer_last_msg < last_time () -. 14400.) && 
> > (global_peers_size.(i)>2) then 
> > +   begin
> > +     (*Printf.printf "REM global_peers %s\n" (Md4.to_string a);*)
> > +     Hashtbl.remove !!global_peers.(i) a;
> > +     global_peers_size.(i) <- global_peers_size.(i)-1;
> > +   end
> > +    ) !!global_peers.(i)
> > +  done
> > +
> > +let get_local_distribution md4 = 
> > +  let start_pos=(Md4.up md4) and peers = ref [] and size = ref 0 in
> > +  (*FIXME we should use a XorSet for the first test*)
> > +  Hashtbl.iter 
> > +    ( fun a b -> if !size<16 then begin peers := b :: !peers; incr size; 
> > end) 
> > +    !!global_peers.(start_pos);
> > +  for i=1 to 127 do
> > +    if !size<16 then
> > +      Hashtbl.iter 
> > +   ( fun a b -> if !size<16 then begin peers := b :: !peers; incr size; 
> > end) 
> > +   !!global_peers.((start_pos+i) mod 256);
> > +    if !size<16 then
> > +      Hashtbl.iter 
> > +   ( fun a b -> if !size<16 then begin peers := b :: !peers; incr size; 
> > end) 
> > +   !!global_peers.((start_pos-i+256) mod 256);
> > +  done;
> > +  !peers
> > +
> > +let get_uniform_distribution () =
> > +  let peers = ref [] in
> > +  for i=0 to 15 do
> > +    let size = ref 0 in
> > +    for j=0 to 15 do
> > +      size:=!size+global_peers_size.(16*i+j);
> > +    done;
> > +    if !size <> 0 then
> > +      let pos=ref (Random.int !size) in
> > +      for j=0 to 15 do
> > +   if global_peers_size.(16*i+j) < !pos || !pos < 0 then pos := !pos - 
> > global_peers_size.(16*i+j)
> > +   else Hashtbl.iter ( fun a b -> if !pos=0 then peers := b :: !peers; 
> > decr pos ) 
> > +       !!global_peers.(16*i+j);
> > +      done;    
> > +  done; 
> > +  !peers
> > +
> > +let find_oldest_peer hashtbl =
> > +  let md4 = ref Md4.null and time = ref (last_time () ) in 
> > +  Hashtbl.iter ( fun a b -> 
> > +    if b.peer_last_msg < !time then 
> > +      begin
> > +   md4 := a;
> > +   time := b.peer_last_msg;
> > +      end
> > +  ) hashtbl;
> > +  !md4
> > +
> > +let add_global_peer peer =
> > +  if (peer.peer_ip <> !!donkey_bind_addr) && (peer.peer_md4 <> overnet_md4)
> > +  then
> >      begin
> > -      overnet_peers =:= peer :: !!overnet_peers;
> > -      Hashtbl.add peers_by_md4 peer.peer_md4 peer;
> > -      Fifo.put peers_queue (peer.peer_ip, peer.peer_port)
> > +      let i=Md4.up peer.peer_md4 in
> > +      if Hashtbl.mem !!global_peers.(i) peer.peer_md4 then
> > +   begin
> > +     (*Printf.printf "UPD global_peers: %s\n" (Md4.to_string 
> > peer.peer_md4);*)
> > +     (Hashtbl.find !!global_peers.(i) peer.peer_md4).peer_last_msg <- 
> > last_time();
> > +   end
> > +      else
> > +   begin
> > +     if global_peers_size.(i) >= max_peer_by_peerblock then
> > +       begin
> > +         let p = find_oldest_peer !!global_peers.(i) in
> > +         (*Printf.printf "REM global_peers: %s\n" (Md4.to_string p);*)
> > +         Hashtbl.remove !!global_peers.(i) p;
> > +         global_peers_size.(i) <- global_peers_size.(i)-1;
> > +       end;
> > +     (*Printf.printf "ADD global_peers: %s\n" (Md4.to_string 
> > peer.peer_md4);*)
> > +     peer.peer_last_msg <- last_time();
> > +          Hashtbl.add !!global_peers.(i) peer.peer_md4 peer;
> > +     global_peers_size.(i) <- global_peers_size.(i)+1;
> > +   end
> >      end
> > -    
> > -let connected_peers = ref []
> > -let nconnected_peers = ref 0
> > +  else
> > +    if !!verbose then
> > +      begin
> > +   Printf.printf "Tried to add myself as a peer: %s/%s %s/%s\n" 
> > +     (Ip.to_string peer.peer_ip) (Ip.to_string !!donkey_bind_addr)
> > +     (Md4.to_string peer.peer_md4) (Md4.to_string overnet_md4);        
> > +      end
> >  
> > -module XorSet = Set.Make (struct
> > -      type t = Md4.t * peer
> > -      let compare (m1,p1) (m2,p2) = 
> > -        compare (m1,p1.peer_md4, p1.peer_ip) (m2,p2.peer_md4, p2.peer_ip)
> > -    end)
> > +  
> > +(* Replace private IP by public IPs in peer list *)
> > +let change_private_address ip public_ip =
> > +  if Ip.matches ip [(Ip.of_string "0.0.0.0"); (Ip.of_string 
> > "127.0.0.255"); 
> > +               (Ip.of_string "10.255.255.255"); (Ip.of_string 
> > "192.168.255.255") ] 
> > +  then public_ip
> > +  else ip
> > +
> > +(*advertize an uniform distribution then a local distribution (around our 
> > MD4) that we are UP*)
> > +let publicize_peers () =
> > +  if (!!overnet_search_sources || !!overnet_search_keyword) then
> > +      begin
> > +   let global_dist = get_uniform_distribution () and local_dist = 
> > get_local_distribution overnet_md4 in
> > +   (*List.iter (fun a -> Printf.printf "UNIFORM DIST: %s" (Md4.to_string 
> > a.peer_md4); print_newline () ) global_dist; *)
> > +   List.iter (fun a -> udp_send a.peer_ip a.peer_port 
> > (OvernetPublicize(overnet_md4,!!donkey_bind_addr,!!overnet_port, 0) ) ) 
> > global_dist;
> > +   (*List.iter (fun a -> Printf.printf "LOCAL DIST: %s" (Md4.to_string 
> > a.peer_md4); print_newline () ) local_dist;*)
> > +   List.iter (fun a -> udp_send a.peer_ip a.peer_port 
> > (OvernetPublicize(overnet_md4,!!donkey_bind_addr,!!overnet_port, 0) ) ) 
> > local_dist
> > +      end
> > +     
> > +(* If one peer block is running low, try to get new peers using Connect *)
> > +let find_new_peers () =
> > +  if !!overnet_search_sources || !!overnet_search_keyword then
> > +      begin
> > +   Printf.printf "FINDING NEW PEERS\n";
> > +   try 
> > +     for i=0 to 255 do 
> > +       if global_peers_size.(i) <= 4 then raise Not_found;
> > +     done
> > +   with _ -> 
> > +     begin
> > +       let global_dist = get_uniform_distribution () in
> > +       List.iter (fun a -> udp_send a.peer_ip a.peer_port 
> > (OvernetConnect(overnet_md4,!!donkey_bind_addr,!!overnet_port, 0) ) ) 
> > global_dist;
> > +     end
> > +      end
> >  
> >  type search_for =
> >    FileSearch of file
> > @@ -211,18 +358,15 @@
> >  let overnet_searches = Hashtbl.create 13
> >  
> >  let add_search_peer s p = 
> > -  if not (Hashtbl.mem s.search_known_peers (p.peer_ip, p.peer_port)) &&
> > -     not ( is_black_address p.peer_ip p.peer_port ) then
> > +  if not (Hashtbl.mem s.search_known_peers (p.peer_ip, p.peer_port)) then
> >      begin
> >        Hashtbl.add s.search_known_peers (p.peer_ip, p.peer_port) p;
> >        let distance = Md4.xor s.search_md4 p.peer_md4 in
> >        if s.search_waiting_peers > !!overnet_max_waiting_peers then begin
> >            let (dd,pp) as e = XorSet.max_elt s.search_next_peers in
> >            if dd>distance then begin
> > -              s.search_next_peers <- 
> > -                XorSet.remove (dd, pp) s.search_next_peers;     
> > -              s.search_next_peers <- 
> > -                XorSet.add (distance, p) s.search_next_peers;   
> > +              s.search_next_peers <- XorSet.remove (dd, pp) 
> > s.search_next_peers;     
> > +              s.search_next_peers <- XorSet.add (distance, p) 
> > s.search_next_peers;   
> >              end        
> >          end
> >        else begin
> > @@ -231,17 +375,6 @@
> >          end
> >      end
> >      
> > -    
> > -let try_connect () =
> > -  if (!!overnet_search_sources || !!overnet_search_keyword) &&
> > -    !nconnected_peers < !!overnet_max_connected_peers && 
> > -    not (Fifo.empty peers_queue) then begin
> > -      let (ip, port) = Fifo.take peers_queue in
> > -      if not ( is_black_address ip port ) then
> > -      udp_send ip port  (OvernetConnect (!!client_md4, Ip.null, 
> > -          !!overnet_port, 0))
> > -    end
> > -
> >  let create_simple_search kind md4 =   
> >    let search = {
> >        search_last_packet = last_time ();
> > @@ -267,9 +400,7 @@
> >  
> >  let create_search kind md4 =   
> >    let search = create_simple_search kind md4 in
> > -  List.iter (fun (peer, _) ->
> > -      add_search_peer search peer;
> > -  ) !connected_peers;
> > +  List.iter (fun peer -> add_search_peer search peer;) 
> > (get_local_distribution md4) ;
> >    search
> >  
> >  let create_keyword_search w =   
> > @@ -287,7 +418,7 @@
> >            search_waiting_peers = 0;
> >            search_publish_files = [];
> >            search_publish_file = false;
> > -(*          search_query_files = true;  *)
> > +(*        search_query_files = true;  *)
> >            search_results = Hashtbl.create 13;
> >            search_nreplies = 0;
> >            search_nqueries = 0;
> > @@ -297,9 +428,7 @@
> >          } in
> >  (*   Printf.printf "STARTED SEARCH FOR %s" (Md4.to_string md4); 
> > print_newline (); *)
> >        Hashtbl.add overnet_searches md4 search;
> > -      List.iter (fun (peer, _) ->
> > -          add_search_peer search peer;
> > -      ) !connected_peers;
> > +      List.iter (fun peer -> add_search_peer search peer;) 
> > (get_local_distribution md4);
> >        search
> >        
> >    
> > @@ -348,6 +477,11 @@
> >        Ip.of_inet_addr inet
> >    | _ -> assert false
> >      
> > +let port_of_udp_packet p =
> > +  match p.UdpSocket.addr with
> > +    Unix.ADDR_INET (inet, port) -> port
> > +  | _ -> assert false
> > + 
> >  let udp_client_handler t p =
> >    match t with
> >    | OvernetConnectReply peers ->
> > @@ -357,54 +491,58 @@
> >            peer :: tail ->
> >              
> >              let other_ip = ip_of_udp_packet p in
> > -            
> > -            if !!verbose then begin
> > -                let rec iteri i list =
> > -                  match list with
> > -                    [] -> 
> > -                      Printf.printf "NO OWN IP ADDRESS IN PACKET"; 
> > -                      print_newline ();
> > -                  | p :: tail ->
> > -                      if p.peer_ip = other_ip then begin
> > -                          Printf.printf "PEER ADDRESS IS %d" i; 
> > print_newline ();
> > -                        end
> > -                      else 
> > -                        iteri (i+1) tail
> > -                in
> > -                iteri 0 peers;
> > -              end;            
> > -            
> > -            
> > -            if Ip.valid peer.peer_ip then 
> > -              peer.peer_ip <- other_ip;
> > -            
> > -            add_peer peer;
> > +       if !!verbose then begin
> > +              Printf.printf "sender IP was %s" (Ip.to_string 
> > peer.peer_ip); print_newline ();          
> > +       end;
> > +       peer.peer_ip <- (change_private_address peer.peer_ip other_ip);
> > +
> >              peer.peer_last_msg <- last_time ();
> > -            connected_peers := (peer, last_time ()) :: !connected_peers;
> > -            if !!verbose_overnet then begin                
> > -                Printf.printf "Connected %d to %s:%d" 
> > !nconnected_peers(Ip.to_string peer.peer_ip)
> > -                peer.peer_port; print_newline ();
> > +       add_global_peer peer;
> > +            if !!verbose_overnet then 
> > +         begin                
> > +                Printf.printf "Connected to %s:%d" (Ip.to_string 
> > peer.peer_ip) peer.peer_port; 
> > +           print_newline ();
> >                end;
> > -            incr nconnected_peers;
> > -            List.iter add_peer tail;
> > -            Hashtbl.iter (fun _ search ->
> > -                add_search_peer search peer) 
> > +
> > +       (* everything else sould be added *)
> > +            List.iter add_global_peer tail;
> > +
> > +            Hashtbl.iter (fun _ search ->add_search_peer search peer) 
> >              overnet_searches;
> >              List.iter (fun file ->
> >                  if file_state file = FileDownloading           
> >                     && not (file_enough_sources file)
> > -                    && !!overnet_search_sources &&
> > +                   && !!overnet_search_sources &&
> >                    not (Hashtbl.mem overnet_searches file.file_md4) then
> > -                  let search = create_simple_search 
> > -                      (FileSearch file) file.file_md4 in
> > -                  ()
> > +                  let search = create_simple_search (FileSearch file) 
> > file.file_md4 in ()
> >              ) !DonkeyGlobals.current_files;
> > -            Hashtbl.iter (fun _ s ->
> > -                add_search_peer s peer
> > -            ) overnet_searches;
> > +            Hashtbl.iter (fun _ s -> add_search_peer s peer) 
> > overnet_searches;
> >          | _ -> ()
> >        end
> > +
> > +  | OvernetPublicize (md4, ip, port, kind ) ->
> > +      begin
> > +        let other_ip = ip_of_udp_packet p in
> > +   if !!verbose then
> > +     begin
> > +       Printf.printf "sender IP was %s - packet was from %s" 
> > +         (Ip.to_string ip) (Ip.to_string other_ip); 
> > +       print_newline ();       
> > +     end;
> > +   add_global_peer {
> > +     peer_md4=md4;
> > +     peer_ip=(change_private_address ip other_ip);
> > +     peer_port=port;
> > +     peer_kind=kind;
> > +     peer_last_msg=last_time();
> > +   };
> > +
> > +   (* send the PUBLICIZED message *)
> > +   udp_send other_ip port OvernetPublicized
> > +     end
> >        
> > +  | OvernetPublicized -> ()      
> > +  | OvernetPublished (md4) -> ()      
> >    | OvernetSearchReply (md4, peers) ->
> >        begin
> >          try
> > @@ -426,31 +564,24 @@
> >                    KeywordSearch sss ->
> >  (* Here, we could check whether the searches are finished *)
> >                      if sss <> [] then
> > -                      udp_send s_ip s_port 
> > -                        (OvernetGetSearchResults (md4,0,0,100));
> > -(* PUBLISH FILE FOR A GIVEN KEYWORD 
> > -                    if s.search_publish_file then
> > -udp_send s_ip s_port 
> > -*)
> > +                 udp_send s_ip s_port (OvernetGetSearchResults 
> > (md4,0,0,100));
> > +
> >                      List.iter (fun file ->
> >                          Printf.printf "TRY TO PUBLISH FILE FOR KEYWORD";
> >                          print_newline ();
> >                          udp_send s_ip s_port 
> > -                          (OvernetPublish (md4, file.file_md4,
> > -                            DonkeyProtoCom.tag_file file))
> > +                          (OvernetPublish (md4, file.file_md4, 
> > DonkeyProtoCom.tag_file file))
> >                      ) s.search_publish_files
> >                  | FileSearch file ->
> >                      if file_state file = FileDownloading then
> > -                      udp_send s_ip s_port 
> > -                        (OvernetGetSearchResults (md4,0,0,100));
> > +                      udp_send s_ip s_port (OvernetGetSearchResults 
> > (md4,0,0,100));
> >                      if s.search_publish_file then
> >                        udp_send s_ip s_port 
> > -                        (OvernetPublish (md4, !!client_md4,
> > +                        (OvernetPublish (md4, overnet_md4,
> >                            [{
> >                                tag_name = "loc";
> >                                tag_value = String (
> > -                                Printf.sprintf "bcp://%s:%s:%d"
> > -                                  (Md4.to_string !!client_md4)
> > +                                Printf.sprintf "bcp://%s:%d"
> >                                    (Ip.to_string (client_ip None))
> >                                  !!port
> >                                  
> > @@ -464,17 +595,17 @@
> >                    (Md4.to_string sender.peer_md4)
> >                    ; print_newline ();
> >                  end;
> > -            with _ ->
> > -                Printf.printf "Sender firewalled ?"; print_newline ();
> > +            with _ -> Printf.printf "Sender firewalled ?"; print_newline 
> > ();
> >            end;
> >            List.iter (fun p ->
> >                if !!verbose_overnet then begin
> > -                  Printf.printf "DISTANCES: peer   %s from %s" 
> > (Md4.to_string
> > +                  Printf.printf "DISTANCES: peer %s from %s" (Md4.to_string
> >                        (Md4.xor p.peer_md4 md4))
> >                    (Md4.to_string p.peer_md4)
> >                    ; print_newline ();
> >                  end;
> > -              add_search_peer s p
> > +              add_search_peer s p;
> > +         add_global_peer p
> >            ) peers
> >          with _ ->
> >              Printf.printf "NO SUCH SEARCH ??"; print_newline ();
> > @@ -520,7 +651,12 @@
> >                                  let bcp2 = String.sub bcp 6 (String.length 
> > bcp - 6) 
> >                                  in
> >                                  match String2.split_simplify bcp2 ':' with
> > -                                | [_ ;ip;port]
> > +                                | [_;ip;port] ->
> > +                               if !!verbose_overnet then begin
> > +                                      Printf.printf "FIXME: Received a BCP 
> > type 2 %s for MD4 %s/%s" bcp
> > +                                   (Md4.to_string md4) (Md4.to_string 
> > r_md4);
> > +                                      print_newline ();
> > +                                    end   
> >                                  | [ip;port] ->
> >                                      incr source_hits;
> >                                      let ip = Ip.of_string ip in
> > @@ -541,7 +677,7 @@
> >                                      Printf.printf "Ill formed bcp: %s" bcp;
> >                                      print_newline ();
> >                                else begin
> > -                                  Printf.printf "Not a bcp!!!"; 
> > print_newline ();
> > +                                  Printf.printf "Not a bcp !!!"; 
> > print_newline ();
> >                                  end
> >                            | _ -> 
> >                                Printf.printf "NOot a string location ??"; 
> > @@ -566,16 +702,28 @@
> >              with _ -> 
> >                  Printf.printf "No info on sender"; print_newline ();
> >            end;
> > -          if !!verbose_overnet then begin
> > +          if !!verbose_overnet then 
> > +       begin
> >                Printf.printf "RESULT:"; print_newline ();
> >                print_tags r_tags; print_newline ();
> >              end;
> > -        
> > +
> >          with _ ->
> >              Printf.printf "NO SUCH SEARCH ??"; print_newline ();
> >        end
> >        
> > -      
> > +  | OvernetGetMyIP ->
> > +      begin
> > +        let other_ip = ip_of_udp_packet p in
> > +   let other_port = port_of_udp_packet p in
> > +   (* send the answer *)
> > +   (* FIXME : should be able to flush the UDP buffer*)
> > +   udp_send other_ip other_port (OvernetGetMyIPResult other_ip);
> > +   udp_send other_ip other_port OvernetGetMyIPDone;
> > +     end
> > +
> > +  | OvernetGetMyIPResult(ip) -> ()
> > +  | OvernetGetMyIPDone -> ()
> >    | _ -> 
> >        if !!verbose_overnet then begin
> >            Printf.printf "UNUSED MESSAGE"; print_newline ()
> > @@ -615,51 +763,29 @@
> >          end
> >    ) overnet_searches
> >  
> > -let remove_old_connected_peers () =
> > -  let connected_peers = ref [] in
> > -  List.iter (fun (peer, ctime) ->
> > -      if ctime < last_time () -. 1200. then begin
> > -          decr nconnected_peers;
> > -          Fifo.put peers_queue (peer.peer_ip, peer.peer_port);
> > -        end else begin
> > -          connected_peers := (peer, ctime) :: !connected_peers
> > -        end) !connected_peers
> > -  
> >  let publish_shared_files () = 
> >    if !!overnet_search_sources || !!overnet_search_keyword then begin
> >        let files = DonkeyShare.all_shared () in
> >        List.iter publish_file files
> >      end
> >    
> > -let purge_peer_list () =
> > -  let list = Sort.list (fun p1 p2 ->
> > -        p2.peer_last_msg > p1.peer_last_msg
> > -    ) !!overnet_peers in
> > -  let recent_peers, old = 
> > -    List2.cut !!overnet_max_known_peers list
> > -  in
> > -  overnet_peers =:= recent_peers
> > -  
> >  let enable enabler = 
> > -
> > -  let peers = !!overnet_peers in
> > -  overnet_peers =:= [];
> > -  List.iter add_peer peers;
> > -  
> > -  let sock =   (UdpSocket.create (Ip.to_inet_addr !!donkey_bind_addr)
> > -    (!!overnet_port) 
> > -      (udp_handler udp_client_handler)) in
> > +  let sock = (UdpSocket.create (Ip.to_inet_addr !!donkey_bind_addr)
> > +    (!!overnet_port) (udp_handler udp_client_handler)) in
> >    udp_sock := Some sock;
> >    UdpSocket.set_write_controler sock udp_write_controler;
> > -  add_session_timer enabler 1. try_connect;
> > +  add_session_timer enabler 120. find_new_peers;
> >    add_session_option_timer enabler overnet_query_peer_period 
> > query_next_peers;
> >    add_session_timer enabler 1200. (fun _ ->
> >        recover_all_files ();
> > -      remove_old_connected_peers ();
> > -      purge_peer_list ();
> > +      remove_old_global_peers ();
> > +      publicize_peers ();
> >        publish_shared_files ()
> >    );
> > -  add_timer 30. (fun timer -> publish_shared_files ())
> > +  add_timer 30. (fun timer -> publicize_peers ());
> > +  add_timer 50. (fun timer -> publish_shared_files ());
> > +  add_timer 10. (fun timer -> find_new_peers ())
> > +
> >    
> >  let _ =
> >    option_hook overnet_query_peer_period (fun _ ->
> > @@ -671,9 +797,7 @@
> >      None -> ()
> >    | Some sock -> 
> >        udp_sock := None;
> > -      UdpSocket.close sock "disabled";
> > -      Hashtbl.clear peers_by_md4;
> > -      Fifo.clear peers_queue
> > +      UdpSocket.close sock "disabled"
> >  
> >  let parse_overnet_url url =
> >    match String2.split (String.escaped url) '|' with
> > @@ -681,8 +805,7 @@
> >    | "boot" :: name :: port :: _ ->
> >        let ip = Ip.from_name name in
> >        let port = int_of_string port in
> > -      Fifo.put peers_queue (ip, port);
> > -      try_connect ();
> > +      udp_send ip port 
> > (OvernetConnect(overnet_md4,!!donkey_bind_addr,!!overnet_port, 0));
> >        true
> >    | _ -> false
> >        
> > @@ -693,8 +816,7 @@
> >      "boot", Arg_two (fun hostname port o ->
> >     let ip = Ip.from_name hostname in
> >     let port = int_of_string port in
> > -        Fifo.put peers_queue (ip, port);
> > -        try_connect ();
> > +   udp_send ip port 
> > (OvernetConnect(overnet_md4,!!donkey_bind_addr,!!overnet_port, 0));
> >          "peer added"
> >      ), " <hostname> <port> : add an Overnet peer";
> >      
> > @@ -708,15 +830,20 @@
> >      ), " <fhalink> : download fha:// link";
> >      
> >      "ovstats", Arg_none (fun o ->
> > -        let buf = o.conn_buf in
> > +        let buf = o.conn_buf and sum = ref 0 in
> >          Printf.bprintf buf "Overnet statistics:\n"; 
> > -        Printf.bprintf buf "  Connected Peers: %d\n" !nconnected_peers;
> > -        List.iter (fun (p,_) ->
> > -            Printf.bprintf buf "      %s:%d\n" (Ip.to_string p.peer_ip) 
> > -            p.peer_port;
> > -        ) !connected_peers;
> >          Printf.bprintf buf "  Search hits: %d\n" !search_hits;
> >          Printf.bprintf buf "  Source hits: %d\n" !source_hits;
> > +   Printf.bprintf buf "  peers blocks :\n";
> > +   for i=0 to 15 do          
> > +     Printf.bprintf buf "    ";
> > +     for j=0 to 15 do
> > +       Printf.bprintf buf "%3d: %3d " (i*16+j) global_peers_size.(i*16+j);
> > +       sum := !sum + global_peers_size.(i*16+j);
> > +     done;
> > +     Printf.bprintf buf "\n";
> > +   done;
> > +   Printf.bprintf buf "  Number of overnet peers = %d\n" !sum;
> >  
> >          Hashtbl.iter (fun _ s ->
> >              Printf.bprintf buf 
> > @@ -753,6 +880,37 @@
> >                "web boot started"
> >          end;
> >      ), " <urls>: download .ocl URLS (no arg load default)";
> > +
> > +    "ovmd4", Arg_none (fun o -> "MD4 is " ^ (Md4.to_string overnet_md4);
> > +     ), " get client MD4 address on the overnet network";
> > +
> > +    "ovdump", Arg_none (fun o -> 
> > +      let buf = o.conn_buf in
> > +      begin
> > +   Printf.bprintf buf "overnet dump\n";
> > +   for i=0 to 255 do 
> > +     if global_peers_size.(i) <> 0 then
> > +       Printf.bprintf buf "global_peers n°%d : %d elements\n" i 
> > global_peers_size.(i);
> > +     Hashtbl.iter ( fun a b -> Printf.bprintf buf "global_peers n°%d %s 
> > %f\n" 
> > +         i (Md4.to_string a) b.peer_last_msg) !!global_peers.(i);
> > +   done;
> > +      end;
> > +      ""), "dump overnet global_peer table";
> > +
> > +    "ovtst", Arg_none (fun o -> 
> > +      for i=1 to 92 do
> > +   add_global_peer {
> > +   peer_md4=Md4.random();
> > +   peer_ip=Ip.of_string "10.10.10.10";
> > +   peer_port=1;
> > +   peer_kind=0;
> > +   peer_last_msg=1.;
> > +      };
> > +      done;
> > +      ""), "dump overnet global_peer table";
> > +
> > +    "ovadv", Arg_none (fun o -> publicize_peers (); ""), "dump overnet 
> > global_peer table";
> > +
> >    ];
> >    add_web_kind "ocl" (fun filename ->
> >        let s = File.to_string filename in
> > @@ -763,8 +921,7 @@
> >              name :: port :: _ ->
> >                let ip = Ip.from_name name in
> >                let port = int_of_string port in
> > -              Fifo.put peers_queue (ip, port);
> > -              try_connect ();              
> > +         udp_send ip port 
> > (OvernetConnect(overnet_md4,!!donkey_bind_addr,!!overnet_port, 0));
> >            | _ -> 
> >                Printf.printf "BAD LINE ocl: %s" s;
> >                print_newline ();
> > diff -u -r mldonkey-pango-20021201a/donkey/donkeyProtoOvernet.ml 
> > mldonkey/donkey/donkeyProtoOvernet.ml
> > --- mldonkey-pango-20021201a/donkey/donkeyProtoOvernet.ml   2002-10-15 
> > 22:23:21.000000000 +0200
> > +++ mldonkey/donkey/donkeyProtoOvernet.ml   2002-12-08 11:50:32.000000000 
> > +0100
> > @@ -43,9 +43,6 @@
> >    let md4 = get_md4 s pos in
> >    let ip = get_ip s (pos+16) in
> >    let port = get_int16 s (pos+20) in
> > -  if !!verbose_overnet then begin
> > -      Printf.printf "PEER %s:%d" (Ip.to_string ip) port; print_newline ();
> > -    end;
> >    let kind = get_int8 s (pos+22) in
> >    {
> >      peer_md4 = md4;
> > @@ -70,6 +67,14 @@
> >  (* ?? 2 is OK for most searches, number of replies ? *) int * 
> >  (* searched file or keyword *) Md4.t
> >  
> > +| OvernetPublicize of
> > +(* client md4 *) Md4.t *
> > +(* IP address *) Ip.t *
> > +(* port *)       int *
> > +(* kind *)       int
> > +
> > +| OvernetPublicized
> > +
> >  | OvernetSearchReply of 
> >    Md4.t *
> >    peer list (* the two closest peers in the binary tree of md4s *)
> > @@ -218,6 +223,12 @@
> >  
> >  | OvernetUnknown of int * string
> >  
> > +| OvernetGetMyIP
> > +
> > +| OvernetGetMyIPResult of Ip.t
> > +
> > +| OvernetGetMyIPDone
> > +
> >  let names_of_tag =
> >    [
> >      1, "filename";
> > @@ -239,6 +250,16 @@
> >        buf_int8 buf 11;
> >        buf_list16 buf_peer buf peers      
> >    
> > +  | OvernetPublicize (md4, ip, port, kind) ->
> > +      buf_int8 buf 12;
> > +      buf_md4 buf md4;
> > +      buf_ip buf ip;
> > +      buf_int16 buf port;
> > +      buf_int8 buf kind
> > +
> > +  | OvernetPublicized ->
> > +      buf_int8 buf 13
> > +
> >    | OvernetSearch (kind, md4) ->
> >        buf_int8 buf 14;
> >        buf_int8 buf kind;
> > @@ -259,6 +280,7 @@
> >        buf_int8 buf 17;
> >        buf_md4 buf md4;
> >        buf_md4 buf r_md4;
> > +      buf_int32 buf (Int32.of_int (List.length r_tags));
> >        buf_tags buf r_tags names_of_tag
> >  
> >    | OvernetNoResult md4 ->
> > @@ -269,11 +291,24 @@
> >        buf_int8 buf 19;
> >        buf_md4 buf md4;
> >        buf_md4 buf r_md4;
> > +      buf_int32 buf (Int32.of_int (List.length r_tags));
> >        buf_tags buf r_tags names_of_tag
> >        
> >    | OvernetPublished md4 ->
> >        buf_int8 buf 20;
> >        buf_md4 buf md4
> > +
> > +  | OvernetGetMyIP ->
> > +      buf_int8 buf 27;
> > +      buf_int8 buf 54;
> > +      buf_int8 buf 18
> > +
> > +  | OvernetGetMyIPResult (ip) ->
> > +      buf_int8 buf 28;
> > +      buf_ip buf ip
> > +
> > +  | OvernetGetMyIPDone ->
> > +      buf_int8 buf 29
> >        
> >    | OvernetUnknown (opcode, s) ->
> >        buf_int8 buf opcode;
> > @@ -297,6 +332,20 @@
> >            end;
> >          let peers, pos = get_list16 get_peer s 0 in
> >          OvernetConnectReply peers
> > +    | 12 -> 
> > +        if !!verbose_overnet then begin
> > +            Printf.printf "OK: PUBLICIZE"; print_newline ();
> > +          end;
> > +        let md4 = get_md4 s 0 in
> > +        let ip = get_ip s 16 in
> > +        let port = get_int16 s 20 in
> > +        let kind = get_int8 s 22 in
> > +        OvernetPublicize (md4,ip,port,kind)
> > +    | 13 ->
> > +        if !!verbose_overnet then begin
> > +            Printf.printf "OK: PUBLICIZED"; print_newline ();
> > +          end; 
> > +   OvernetPublicized
> >      | 14 -> 
> >          if !!verbose_overnet then begin
> >              Printf.printf "OK: SEARCH MESSAGE"; print_newline ();
> > @@ -321,8 +370,7 @@
> >          let kind = get_int8 s 16 in
> >          let min = get_int16 s 17 in
> >          let max = get_int16 s 19 in
> > -        OvernetGetSearchResults (md4, kind, min, max)
> > -    
> > +        OvernetGetSearchResults (md4, kind, min, max)  
> >      
> >      | 17 ->
> >          if !!verbose_overnet then begin
> > @@ -357,7 +405,41 @@
> >            end;
> >          let md4 = get_md4 s 0 in
> >          OvernetPublished md4
> > -        
> > +
> > +    | 27 ->
> > +        let opcode1 = get_int8 s 0 in
> > +   let opcode2 = get_int8 s 1 in   
> > +   if opcode1 = 54 && opcode2 = 18 then 
> > +     begin
> > +       if !!verbose_overnet then 
> > +         begin
> > +           Printf.printf "OK: GETMYIP"; 
> > +           print_newline ();
> > +         end;
> > +       OvernetGetMyIP
> > +     end
> > +   else
> > +     begin
> > +       if !!verbose_overnet then 
> > +         begin
> > +           Printf.printf "UNKNOWN: opcode %d, opcode1 %d, opcode2 %d " 
> > opcode opcode1 opcode2; 
> > +           print_newline ();
> > +         end;
> > +       dump s;
> > +            print_newline ();
> > +            OvernetUnknown (opcode, s)
> > +     end
> > +    | 28 -> 
> > +   if !!verbose_overnet then begin
> > +            Printf.printf "OK: GETMYIPRESULT MESSAGE"; print_newline ();
> > +          end;
> > +        let ip = get_ip s 0 in
> > +        OvernetGetMyIPResult (ip)
> > +    | 29 -> 
> > +   if !!verbose_overnet then begin
> > +            Printf.printf "OK: GETMYIPDONE MESSAGE"; print_newline ();
> > +          end;
> > +        OvernetGetMyIPDone
> >      | _ ->
> >          Printf.printf "UNKNOWN: opcode %d" opcode; print_newline ();
> >          dump s;
> > @@ -378,12 +460,14 @@
> >              let pbuf = p.UdpSocket.content in
> >              let len = String.length pbuf in
> >              if len < 2 || 
> > -              int_of_char pbuf.[0] <> 227 then begin
> > +              int_of_char pbuf.[0] <> 227 then 
> > +         begin
> >                  Printf.printf "Received unknown UDP packet"; print_newline 
> > ();
> >                  dump pbuf;
> > -              end else begin
> > -                let t = parse (int_of_char pbuf.[1]) 
> > -                  (String.sub pbuf 2 (len-2)) in
> > +              end 
> > +       else 
> > +         begin
> > +                let t = parse (int_of_char pbuf.[1]) (String.sub pbuf 2 
> > (len-2)) in
> >  (*              M.print t; *)
> >                  f t p
> >                end
> > @@ -392,4 +476,4 @@
> >                  (Printexc.to_string e); print_newline () 
> >        );
> >    | _ -> ()
> > -      
> > \ No newline at end of file
> > +      
> > diff -u -r mldonkey-pango-20021201a/lib/md4.ml mldonkey/lib/md4.ml
> > --- mldonkey-pango-20021201a/lib/md4.ml     2002-12-01 17:27:42.000000000 
> > +0100
> > +++ mldonkey/lib/md4.ml     2002-12-08 19:33:26.000000000 +0100
> > @@ -101,9 +101,14 @@
> >    done;
> >    s
> >    
> > +
> > +let up s = int_of_char s.[0]
> > +let up2 s = (int_of_char s.[0])*256+(int_of_char s.[1])
> > +let up3 s = (int_of_char s.[0])*65536+(int_of_char s.[1])*256+(int_of_char 
> > s.[2])
> > +  
> >  open Options
> >  
> > -let value_to_md4 v = (*
> > +let value_to_md4 v = (* 
> >        match v with
> >          Options.Module assocs ->
> >            let get_value name conv = conv (List.assoc name assocs) in
> > @@ -124,4 +129,4 @@
> >    
> >  let option =
> >    define_option_class "Md4" value_to_md4 md4_to_value
> > -  
> > \ No newline at end of file
> > +  
> > diff -u -r mldonkey-pango-20021201a/lib/md4.mli mldonkey/lib/md4.mli
> > --- mldonkey-pango-20021201a/lib/md4.mli    2002-12-01 17:27:42.000000000 
> > +0100
> > +++ mldonkey/lib/md4.mli    2002-12-08 18:10:29.000000000 +0100
> > @@ -31,6 +31,9 @@
> >  val direct_of_string : string -> t
> >  val direct_to_string : t -> string
> >  val random : unit -> t
> > +val up : t -> int
> > +val up2 : t -> int
> > +val up3 : t -> int
> >  
> >  val digest_subfile : Unix32.t -> int32 -> int32 -> t
> >  
> > @@ -39,4 +42,4 @@
> >  val xor : t -> t -> t
> >  val value_to_md4 : Options.option_value -> t
> >  val md4_to_value : t -> Options.option_value
> > -  
> > \ No newline at end of file
> > +  
> > diff -u -r mldonkey-pango-20021201a/lib/options.ml mldonkey/lib/options.ml
> > --- mldonkey-pango-20021201a/lib/options.ml 2002-10-23 11:54:58.000000000 
> > +0200
> > +++ mldonkey/lib/options.ml 2002-12-08 18:47:12.000000000 +0100
> > @@ -30,7 +30,7 @@
> >  both approaches in a latter release.
> >    
> >      *)
> > -  
> > +
> >  type option_value =
> >      Module of option_module
> >    | StringValue of string
> > @@ -421,6 +421,17 @@
> >    | Module _ -> failwith "Options: not a list option (Module)"
> >  ;;
> >  
> > +let value_to_list2 v2c v =
> > +  match v with
> > +    List l ->  
> > +      begin
> > +   let hash=Array.init 256 (fun _ -> Hashtbl.create 10) in
> > +   List.iter ( fun a -> let (num,md4,peer) = v2c a in Hashtbl.add 
> > hash.(num) md4 peer) (List.rev l);
> > +   hash
> > +      end
> > +  | _ -> failwith (Printf.sprintf "Options: not a list option for list2")
> > +;;
> > +
> >  let value_to_safelist v2c v =
> >    match v with
> >      List l | SmallList l -> 
> > @@ -481,6 +492,13 @@
> >  let list_to_value name c2v l =
> >    List (convert_list name c2v l [])
> >    
> > +let list_to_value2 x c2v l =
> > +  let res = ref [] in
> > +  for i=0 to 255 do   
> > +    Hashtbl.iter (fun a b -> res := (c2v (0,x,b) ) :: !res ) l.(i);
> > +  done;
> > +  List !res
> > +
> >  let smalllist_to_value name c2v l =
> >    SmallList (convert_list name c2v l [])
> >  
> > @@ -533,6 +551,11 @@
> >      (list_to_value cl.class_name cl.to_value)
> >  ;;
> >  
> > +let list_option2 x cl =
> > +  define_option_class "Hashtable array" (value_to_list2 cl.from_value) 
> > +    (list_to_value2 x cl.to_value)
> > +;;
> > +
> >  let safelist_option cl =
> >    define_option_class (cl.class_name ^ " List") 
> >    (value_to_safelist cl.from_value)
> > @@ -950,4 +973,4 @@
> >    ) (simple_args file)
> >  
> >  let option_type o =
> > -  (get_class o).class_name
> > \ No newline at end of file
> > +  (get_class o).class_name
> > diff -u -r mldonkey-pango-20021201a/lib/options.mli mldonkey/lib/options.mli
> > --- mldonkey-pango-20021201a/lib/options.mli        2002-10-15 
> > 00:21:48.000000000 +0200
> > +++ mldonkey/lib/options.mli        2002-12-08 18:41:43.000000000 +0100
> > @@ -34,7 +34,7 @@
> >  type options_file
> >  
> >  exception SideEffectOption
> > -  
> > +
> >  val create_options_file : string -> options_file
> >  val options_file_name : options_file -> string
> >  val set_options_file : options_file -> string -> unit
> > @@ -73,6 +73,7 @@
> >    
> >    (* parameterized options *)
> >  val list_option : 'a option_class -> 'a list option_class
> > +val list_option2 : 'a -> (int * 'a * 'b) option_class -> ('a, 'b) 
> > Hashtbl.t array option_class
> >  val safelist_option : 'a option_class -> 'a list option_class
> >  val listiter_option : 'a option_class -> 'a list option_class
> >  val option_option : 'a option_class -> 'a option option_class
> > ----
> > 
> 
> > _______________________________________________
> > Mldonkey-users mailing list
> > address@hidden
> > http://mail.nongnu.org/mailman/listinfo/mldonkey-users
> 
> 
> 
> _____________________________________________________________________
> GRAND JEU SMS : Pour gagner un NOKIA 7650, envoyez le mot IF au 61321
> (prix d'un SMS + 0.35 euro). Un SMS vous dira si vous avez gagné.
> Règlement : http://www.ifrance.com/_reloc/sign.sms

Attachment: overnet-patch1
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]