mldonkey-commits
[Top][All Lists]
Advanced

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

[Mldonkey-commits] mldonkey distrib/ChangeLog src/daemon/common/co...


From: mldonkey-commits
Subject: [Mldonkey-commits] mldonkey distrib/ChangeLog src/daemon/common/co...
Date: Fri, 27 Jul 2012 17:46:38 +0000

CVSROOT:        /sources/mldonkey
Module name:    mldonkey
Changes by:     spiralvoice <spiralvoice>       12/07/27 17:46:38

Modified files:
        distrib        : ChangeLog 
        src/daemon/common: commonTypes.ml 
        src/networks/bittorrent: bTClients.ml bTGlobals.ml 
                                 bTInteractive.ml bTProtocol.ml 
                                 bTTypes.ml 

Log message:
        patch #7756

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/mldonkey/distrib/ChangeLog?cvsroot=mldonkey&r1=1.1564&r2=1.1565
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonTypes.ml?cvsroot=mldonkey&r1=1.80&r2=1.81
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/bittorrent/bTClients.ml?cvsroot=mldonkey&r1=1.108&r2=1.109
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/bittorrent/bTGlobals.ml?cvsroot=mldonkey&r1=1.91&r2=1.92
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/bittorrent/bTInteractive.ml?cvsroot=mldonkey&r1=1.167&r2=1.168
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/bittorrent/bTProtocol.ml?cvsroot=mldonkey&r1=1.29&r2=1.30
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/networks/bittorrent/bTTypes.ml?cvsroot=mldonkey&r1=1.49&r2=1.50

Patches:
Index: distrib/ChangeLog
===================================================================
RCS file: /sources/mldonkey/mldonkey/distrib/ChangeLog,v
retrieving revision 1.1564
retrieving revision 1.1565
diff -u -b -r1.1564 -r1.1565
--- distrib/ChangeLog   1 Jul 2012 20:02:50 -0000       1.1564
+++ distrib/ChangeLog   27 Jul 2012 17:46:38 -0000      1.1565
@@ -14,6 +14,9 @@
 ChangeLog
 =========
 
+2012/07/27
+7756: BT: Add support for magnet links (ygrek, jave)
+
 2012/07/01
 7813: Fix segfault on Solaris/OpenIndiana in md4 code written in C (dcoppa)
 7812: FreeBSD: proper version identification (lioux)

Index: src/daemon/common/commonTypes.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonTypes.ml,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -b -r1.80 -r1.81
--- src/daemon/common/commonTypes.ml    23 Jan 2011 15:20:26 -0000      1.80
+++ src/daemon/common/commonTypes.ml    27 Jul 2012 17:46:38 -0000      1.81
@@ -116,8 +116,9 @@
   | "ttr" -> TigerTree (TigerTree.of_string rem)
   | "md5" ->  Md5 (Md5.of_string rem)
   | "sig2dat" -> Md5Ext (Md5Ext.of_base32 rem)
-  | "bt" | "bittorrent" | "btih" -> 
-      BTUrl (Sha1.of_string rem)
+  | "bt" | "btih" ->
+    (* accept both base32 (32 chars) and base16 (40 chars) *)
+    BTUrl (if String.length rem = 40 then Sha1.of_hexa rem else Sha1.of_string 
rem)
   | "filetp" -> FileTP (Md4.of_string rem)
   | _ -> raise (Illegal_urn (s ^ " at " ^ sign ^ " is not known"))
 
@@ -211,6 +212,7 @@
     let uids = ref [] in
     let name = ref "" in
     let size = ref None in
+    let trackers = ref [] in
     let each k v =
       match String2.split k '.' with
       | "xt"::_ -> uids := Uid.of_string v :: !uids
@@ -220,7 +222,7 @@
       | "xs"::_ -> () (* eXtra source *)
       | "mt"::_ -> () (* manifest topic: url or urn, see 
http://rakjar.de/gnuticles/MAGMA-Specsv22.txt *)
       | "kt"::_ -> () (* keywords topic *)
-      | "tr"::_ -> () (* BT tracker *)
+      | "tr"::_ -> trackers := Url.decode v :: !trackers
       | "x"::_ -> () (* extensions *)
 (*
       | _ when v = "" ->
@@ -234,7 +236,12 @@
       try each k v
       with exn -> lprintf_nl "MAGNET: field %S=%S, exn %s" k v 
(Printexc2.to_string exn)
     ) url.Url.args;
-    object method name = !name method size = !size method uids = List.map 
Uid.to_uid (Uid.expand !uids) end
+    object
+      method name = !name
+      method size = !size
+      method uids = List.map Uid.to_uid (Uid.expand !uids)
+      method trackers = !trackers
+    end
   else 
     raise Not_found
 

Index: src/networks/bittorrent/bTClients.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTClients.ml,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -b -r1.108 -r1.109
--- src/networks/bittorrent/bTClients.ml        16 Jul 2011 08:59:27 -0000      
1.108
+++ src/networks/bittorrent/bTClients.ml        27 Jul 2012 17:46:38 -0000      
1.109
@@ -540,6 +540,7 @@
 let reserved () =
   let s = String.make 8 '\x00' in
   s.[7] <- (match !bt_dht with None -> '\x00' | Some _ -> '\x01');
+  s.[5] <- '\x10'; (* TODO bep9, bep10, notify clients about extended*)
   s
 
 (** handshake *)
@@ -569,6 +570,7 @@
 *)
 
 let send_bitfield c =
+  if not c.client_file.file_metadata_downloading then
   send_client c (BitField
       (
       match c.client_file.file_swarmer with
@@ -607,6 +609,21 @@
 
   c.client_azureus_messaging_protocol <- has_bit 0 0x80
 
+let send_extended_handshake c file =
+  let module B = Bencode in
+  let msg = (B.encode (B.Dictionary [(* "e",B.Int 0L; *)
+                                     "m", (B.Dictionary ["ut_metadata", B.Int 
1L]);
+                                     (* "metadata_size", B.Int (-1L) *)])) in 
begin
+    send_client c (Extended (Int64.to_int 0L, msg));
+  end
+
+let send_extended_piece_request c piece file =
+  let module B = Bencode in
+  let msg = (B.encode (B.Dictionary ["msg_type", B.Int 0L; (* 0 is request 
subtype*)
+                                     "piece", B.Int piece; ])) in begin
+    send_client c (Extended (Int64.to_int c.client_ut_metadata_msg, msg));
+  end
+
 let show_client c =
   let (ip,port) = c.client_host in
   Printf.sprintf "%s:%d %S" (Ip.to_string ip) port (brand_to_string 
c.client_brand)
@@ -705,6 +722,7 @@
       begin
         c.client_incoming <- true;
         send_init !!client_uid file_id sock;
+        send_extended_handshake c file;
       end;
     connection_ok c.client_connection_control;
     if !verbose_msg_clients then
@@ -1079,6 +1097,9 @@
 
     | BitField p ->
         (*A bitfield is a summary of what a client have*)
+      if !verbose_msg_clients then
+        lprintf_file_nl (as_file file) "Bitfield message,  metadata state %B" 
c.client_file.file_metadata_downloading;
+      if not c.client_file.file_metadata_downloading then
         begin
           match c.client_file.file_swarmer with
             None -> ()
@@ -1125,6 +1146,7 @@
 
     | Have n ->
         (* A client can send a "Have" without sending a Bitfield *)
+        if not c.client_file.file_metadata_downloading then
         begin
           match c.client_file.file_swarmer with
             None -> ()
@@ -1247,6 +1269,172 @@
           if !verbose_msg_clients then
             lprintf_file_nl (as_file file) "Error: received cancel request but 
client has no slot"
 
+    | Extended (extmsg, payload) ->
+      (* extmsg: 0 handshake, N other message previously declared in handshake.
+         atm ignore extended messages if were not currently in metadata state.
+         TODO when were not in metadata state we should be friendly and answer 
metadata requests
+      *)
+      let module B = Bencode in
+      if file.file_metadata_downloading then begin
+        (* since we got at least one extended handshake from the peer, it 
should be okay to
+           send a handshake back now. we need to send it so the remote client 
knows how
+           to send us messages back.
+           this should of course be moved but I dont know where yet.
+           also we shouldnt send more than one handshake of course...
+        *)
+        if !verbose_msg_clients then
+          lprintf_file_nl (as_file file) "Got extended msg: %d %s" extmsg 
(String.escaped payload);
+
+        match extmsg with
+            0x0 ->
+            if !verbose_msg_clients then
+              lprintf_file_nl (as_file file) "Got extended handshake";
+            let dict = Bencode.decode payload in begin
+              match dict with
+                  B.Dictionary list ->
+                    List.iter (fun (key,value) ->
+                      match key, value with
+                        | "metadata_size", B.Int n ->
+                            if !verbose_msg_clients then
+                              lprintf_file_nl (as_file file) "Got metadata 
size %Ld" n;
+                            c.client_file.file_metadata_size <- n;
+                        | "m", B.Dictionary  mdict ->
+                          if !verbose_msg_clients then
+                            lprintf_file_nl (as_file file) "Got meta dict";
+                          List.iter (fun (key,value) ->
+                            match key, value with
+                                "ut_metadata", B.Int n ->
+                                  if !verbose_msg_clients then
+                                    lprintf_file_nl (as_file file) 
"ut_metadata is %Ld " n;
+                                  c.client_ut_metadata_msg <- n;
+                              | _ -> ();
+                          ) mdict;
+
+                        | _ -> () ;
+                    ) list;
+                    (* okay so now we know what to ask for, so ask for 
metadata now
+                       since metadata can be larger than 16k which is the 
limit, the transfer needs to be chunked, so
+                       it is not really right to make the query here. but its 
a start.
+                       also im just asking for piece 0.
+                       (we should also check that we actually got the metadata 
info before proceeding)
+                    *)
+                    send_extended_handshake c file;
+                    send_extended_piece_request c 
c.client_file.file_metadata_piece file;
+                  |_ -> () ;
+            end;
+          | 0x01 -> (* ut_metadata is 1 because we asked it to be 1 in the 
handshake
+                       the msg_type is probably
+                       1 for data,
+                       but could be 0 for request(unlikely since we didnt 
advertise we had the meta)
+                       2 for reject, also unlikely since peers shouldnt 
advertise if they dont have(but will need handling in the end)
+
+                       {'msg_type': 1, 'piece': 0, 'total_size': 3425}
+                       after the dict comes the actual piece
+                    *)
+            if !verbose_msg_clients then
+              lprintf_file_nl (as_file file) "Got extended ut_metadata 
message";
+            let msgtype = ref 0L in begin
+              begin
+                match B.decode payload with
+                    B.Dictionary list ->
+                      List.iter (fun (key,value) ->
+                        match key, value with
+                            "msg_type", B.Int n ->
+                              if !verbose_msg_clients then
+                                lprintf_file_nl (as_file file) "msg_type %Ld" 
n;
+                              msgtype := n;
+                          | "piece", B.Int n ->
+                            if !verbose_msg_clients then
+                              lprintf_file_nl (as_file file) "piece %Ld" n;
+                            file.file_metadata_piece <- n;
+                          | "total_size", B.Int n ->
+                             if !verbose_msg_clients then
+                              lprintf_file_nl (as_file file) "total_size %Ld" 
n; (* should always be the same as received in the initial handshake i suppose 
*)
+                          |_ -> () ;
+                      ) list;
+                  |_ -> () ;
+              end;
+              match !msgtype with
+                  1L ->
+                    let last_piece_index = (Int64.div file.file_metadata_size 
16384L) in
+                    if !verbose_msg_clients then
+                      lprintf_file_nl (as_file file) "handling metadata piece 
%Ld of %Ld"
+                        file.file_metadata_piece
+                        last_piece_index;
+                        (* store the metadata piece in memory *)
+                    file.file_metadata_chunks.(1 + (Int64.to_int 
file.file_metadata_piece)) <- payload;
+                        (* possibly write metadata to disk *)
+                    if file.file_metadata_piece >=
+                      (Int64.div file.file_metadata_size 16384L) then begin
+                        if !verbose_msg_clients then
+                          lprintf_file_nl (as_file file) "this was the last 
piece";
+                            (* here we should simply delete the current 
download, and wait for mld to pick up the new torrent file *)
+                            (* the entire payload is currently in the array, 
TODO *)
+                        let newtorrentfile = (Printf.sprintf "%s/BT-%s.torrent"
+                                                      (Filename2.temp_dir_name 
())
+                                                      (Sha1.to_string 
file.file_id)) in
+                        let fd = Unix32.create_rw  newtorrentfile  in
+                        let fileindex = ref 0L in
+                        begin
+                          (* the ee is so we can use the same method to find 
the
+                             start of the payload for the real payloads as 
well as the synthetic ones
+                             *)
+                          file.file_metadata_chunks.(0) <- "eed4:info";
+                          file.file_metadata_chunks.(2 + Int64.to_int 
last_piece_index) <- "eee";
+                          try
+                            Array.iteri (fun index chunk ->
+                            (* regexp ee is a fugly way to find the end of the 
1st dict before the real payload *)
+                              let metaindex = (2 + (Str.search_forward  
(Str.regexp_string "ee") chunk 0 )) in
+                              let chunklength = ((String.length chunk) - 
metaindex) in
+                              Unix32.write fd !fileindex chunk
+                                metaindex
+                                chunklength;
+                              fileindex := Int64.add !fileindex  (Int64.of_int 
chunklength);
+                              ();
+                            ) file.file_metadata_chunks;
+                          with e -> begin
+                            (* TODO ignoring errors for now, the array isnt 
really set up right anyway yet *)
+                            (*
+                            lprintf_file_nl (as_file file) "Error %s saving 
metadata"
+                              (Printexc2.to_string e)
+                            *) ()
+                          end;
+                          (* Yay, now the new torrent is on disk! amazing! 
However, now we need to kill the dummy torrent
+                             and restart it with the fresh real torrent *)
+
+                          (* it seems we need to use the dynamic interface... 
*)
+                          if !verbose then
+                            lprintf_file_nl (as_file file) "cancelling 
metadata download ";
+                          let owner = file.file_file.impl_file_owner in
+                          let group = file.file_file.impl_file_group in begin
+                            CommonInteractive.file_cancel (as_file file) owner 
;
+                            (* hack_op_file_cancel c.client_file;   *)
+                            if !verbose then
+                              lprintf_file_nl (as_file file) "starting 
download from metadata torrent %s" newtorrentfile  ;
+                            ignore(CommonNetwork.network_parse_url 
BTGlobals.network newtorrentfile owner group);
+                          end;
+                          (try Sys.remove newtorrentfile with _ -> ())
+                        end;
+
+                      end
+                    else begin
+                          (* now ask for the next metadata piece, if any *)
+                      let nextpiece = (Int64.succ file.file_metadata_piece) in 
begin
+                        if !verbose_msg_clients then
+                          lprintf_file_nl (as_file file) "asking for the next 
piece %Ld" nextpiece;
+                        send_extended_piece_request c nextpiece file;
+                      end;
+                    end;
+                |_ ->
+                  if !verbose_msg_clients then
+                    lprintf_file_nl (as_file file) "unmatched extended 
subtype" ;
+            end;
+
+          | _ ->
+            if !verbose_msg_clients then
+              lprintf_file_nl (as_file file) "Got extended other msg ";
+      end;
+
     | DHT_Port port ->
         match !bt_dht with
         | None ->
@@ -1332,6 +1520,8 @@
                     lprintf_file_nl (as_file file) "READY TO DOWNLOAD FILE";
 
                   send_init !!client_uid file.file_id sock;
+                  send_extended_handshake c file;
+
 (* Fabrice: Initialize the client bitmap and uploader fields to <> None *)
                   update_client_bitmap c;
 (*              (try get_from_client sock c with _ -> ());*)

Index: src/networks/bittorrent/bTGlobals.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTGlobals.ml,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -b -r1.91 -r1.92
--- src/networks/bittorrent/bTGlobals.ml        25 Oct 2011 17:33:21 -0000      
1.91
+++ src/networks/bittorrent/bTGlobals.ml        27 Jul 2012 17:46:38 -0000      
1.92
@@ -272,7 +272,7 @@
           file.file_trackers <-  t :: file.file_trackers)
   file_trackers
 
-let new_file file_id t torrent_diskname file_temp file_state user group =
+let new_file ?(metadata=false) file_id t torrent_diskname file_temp file_state 
user group =
   try
     Hashtbl.find files_by_uid file_id
   with Not_found ->
@@ -302,6 +302,10 @@
           file_session_uploaded = Int64.zero;
           file_session_downloaded = Int64.zero;
           file_last_dht_announce = 0;
+          file_metadata_size = 0L;
+          file_metadata_piece = 0L;
+          file_metadata_downloading = metadata;
+          file_metadata_chunks = Array.make 20 "";
           file_private = t.torrent_private;
         } and file_impl =  {
           (dummy_file_impl ()) with
@@ -354,10 +358,10 @@
       must_share_file file;
       file
 
-let new_download file_id t torrent_diskname user =
+let new_download ?(metadata=false) file_id t torrent_diskname user =
   let file_temp = Filename.concat !!DO.temp_directory
       (Printf.sprintf "BT-%s" (Sha1.to_string file_id)) in
-  new_file file_id t torrent_diskname file_temp FileDownloading user
+  new_file ~metadata file_id t torrent_diskname file_temp FileDownloading user
 
 let ft_by_num = Hashtbl.create 13
 let ft_counter = ref 0
@@ -866,6 +870,7 @@
           client_cache_extension = false;
           client_fast_extension = false;
           client_utorrent_extension = false;
+          client_ut_metadata_msg = -1L;
           client_azureus_messaging_protocol = false;
         } and impl = {
           dummy_client_impl with

Index: src/networks/bittorrent/bTInteractive.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTInteractive.ml,v
retrieving revision 1.167
retrieving revision 1.168
diff -u -b -r1.167 -r1.168
--- src/networks/bittorrent/bTInteractive.ml    16 Jul 2011 08:59:27 -0000      
1.167
+++ src/networks/bittorrent/bTInteractive.ml    27 Jul 2012 17:46:38 -0000      
1.168
@@ -322,6 +322,7 @@
   if !bt_dht <> None then
     emit (_s"Last DHT announce") ~desc:(_s"Last time this torrent was 
announced in DHT")
       (string_of_date file.file_last_dht_announce);
+  emit (_s"Metadata downloading") (if file.file_metadata_downloading then _s 
"yes" else _s "no");
 
   let rec print_first_tracker l =
     match l with
@@ -837,7 +838,8 @@
   List.iter (fun file ->
       (* if !verbose_share then lprintf_nl "Checking torrent share for %s" 
file.file_torrent_diskname; *)
       if not (Sys.file_exists file.file_torrent_diskname) &&
-        file_state file = FileShared then
+        file_state file = FileShared &&
+        not (file.file_metadata_downloading) then
         begin
           if !verbose_share then lprintf_nl "Removing torrent share for %s" 
file.file_torrent_diskname;
           BTClients.file_stop file;
@@ -898,6 +900,46 @@
   String.sub text a (b - a)
 
 let op_network_parse_url url user group =
+        let exn_catch f x = try `Ok (f x) with exn -> `Exn exn in
+        match exn_catch parse_magnet_url url with
+          | `Ok magnet ->
+            (
+            if !verbose then begin
+              lprintf_nl "Got magnet url %S" url;
+              List.iter (fun(v) -> lprintf_nl "magnet %s" (string_of_uid v)) 
magnet#uids;
+              List.iter (fun(v) -> lprintf_nl "magnet trackers %s" v) 
magnet#trackers;
+            end;
+            match List2.filter_map (function BTUrl btih -> Some btih | _ -> 
None) magnet#uids with
+              | [] -> "No btih found in magnet url", false;
+              | btih::_ ->
+                if !verbose then
+                  lprintf_nl "Got btih %S" (Sha1.to_string btih);
+                let hashstr = (Sha1.to_string btih) in 
+                let torrent = {
+                  torrent_name = hashstr; (*magnet#name*)
+                  torrent_filename = hashstr;
+                  torrent_name_utf8 = hashstr;
+                  torrent_comment = "";
+                  torrent_pieces = Array.of_list [];  
+                  torrent_piece_size = 1L;  
+                  torrent_files = []; 
+                  torrent_length = 1L;
+                  torrent_created_by = ""; 
+                  torrent_creation_date = 1000000L;
+                  torrent_modified_by = ""; 
+                  torrent_encoding = ""; 
+                  torrent_private = false; 
+                  torrent_announce =
+                    (match magnet#trackers with
+                     | h::q -> h
+                     | [] -> "");
+                  torrent_announce_list = magnet#trackers;
+                }  in
+                ignore(new_download ~metadata:true btih torrent "" user group);
+                magnet#name, true; 
+              )
+          | `Exn _ ->
+  (
   let location_regexp = "Location: \\(.*\\)" in
   try
     let real_url = get_regexp_string url (Str.regexp location_regexp) in
@@ -964,6 +1006,7 @@
        let s = Printf.sprintf "Can not load load torrent file: %s"
          (Printexc2.to_string e) in
        s, false
+  )
 
 let op_client_info c =
   check_client_country_code c;

Index: src/networks/bittorrent/bTProtocol.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTProtocol.ml,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- src/networks/bittorrent/bTProtocol.ml       23 Jan 2011 15:20:26 -0000      
1.29
+++ src/networks/bittorrent/bTProtocol.ml       27 Jul 2012 17:46:38 -0000      
1.30
@@ -216,7 +216,8 @@
           int: length (power of 2, 2 ^ 15)
     * 9 - DHT port announcement
           int16: UDP port
-
+    * 20 - extended
+          byte: extended message ID (0 = handshake)
 Choke/unchoke every 10 seconds
 *)
 
@@ -266,6 +267,7 @@
     | Ping
     | PeerID of string
     | DHT_Port of int
+    | Extended of int * string
 
     let to_string msg =
       match msg with
@@ -284,6 +286,7 @@
       | Ping -> "Ping"
       | PeerID s ->  Printf.sprintf  "PeerID [%s]" (String.escaped s)
       | DHT_Port n -> Printf.sprintf "DHT_Port %d" n
+      | Extended (n, s) -> Printf.sprintf  "Extended [%d %s]" n 
(String.escaped s)
 
     let parsing opcode m =
         match opcode with
@@ -297,6 +300,7 @@
         | 7 -> Piece (get_int m 0, get_uint64_32 m 4, m, 8, String.length m - 
8)
         | 8 -> Cancel (get_int m 0, get_uint64_32 m 4, get_uint64_32 m 8)
         | 9 -> DHT_Port (get_int16 m 0)
+        | 20 -> Extended (get_int8 m 0, String.sub m 1 (String.length m - 1))
         | -1 -> PeerID m
         | _ -> raise Not_found
 
@@ -325,6 +329,7 @@
         | PeerID _ -> ()
         | Ping -> ()
         | DHT_Port n -> buf_int8 buf 9; buf_int16 buf n
+        | Extended (n,msg) -> buf_int8 buf 20; buf_int8 buf n; 
Buffer.add_string buf msg
       end;
       let s = Buffer.contents buf in
       str_int s 0 (String.length s - 4);

Index: src/networks/bittorrent/bTTypes.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTTypes.ml,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- src/networks/bittorrent/bTTypes.ml  23 Jan 2011 15:20:26 -0000      1.49
+++ src/networks/bittorrent/bTTypes.ml  27 Jul 2012 17:46:38 -0000      1.50
@@ -289,6 +289,7 @@
     mutable client_utorrent_extension : bool;
     mutable client_azureus_messaging_protocol : bool;
 
+    mutable client_ut_metadata_msg : int64;
   }
 
 and tracker_info = {
@@ -335,6 +336,12 @@
     mutable file_session_downloaded : int64;
     (** DHT specific *)
     mutable file_last_dht_announce : int;
+
+    mutable file_metadata_size : int64;
+    mutable file_metadata_piece : int64;
+    mutable file_metadata_downloading : bool;
+    mutable file_metadata_chunks : string array;
+
     file_private : bool;
   }
 



reply via email to

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