[Top][All Lists]
[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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Mldonkey-commits] mldonkey distrib/ChangeLog src/daemon/common/co...,
mldonkey-commits <=