Lines 63-70
Link Here
|
63 |
open BTComplexOptions |
63 |
open BTComplexOptions |
64 |
open BTChooser |
64 |
open BTChooser |
65 |
open BTStats |
65 |
open BTStats |
66 |
open TcpMessages |
|
|
67 |
|
66 |
|
|
|
67 |
|
68 |
open TcpMessages |
69 |
open Bencode |
70 |
open Str |
68 |
module VB = VerificationBitmap |
71 |
module VB = VerificationBitmap |
69 |
|
72 |
|
70 |
let http_ok = "HTTP 200 OK" |
73 |
let http_ok = "HTTP 200 OK" |
Lines 100-105
Link Here
|
100 |
open BTUdpTracker |
103 |
open BTUdpTracker |
101 |
open UdpSocket |
104 |
open UdpSocket |
102 |
|
105 |
|
|
|
106 |
|
107 |
(* some stupid temporary copypasta because i couldnt figure out how to import from btinteractive *) |
108 |
(* let hack_op_file_cancel file = *) |
109 |
(* CommonSwarming.remove_swarmer file.file_swarmer; *) |
110 |
(* file.file_swarmer <- None; *) |
111 |
(* (\* forward declarations turned out difficult. wtf?*\) *) |
112 |
(* (\* file_stop file;*\) *) |
113 |
(* remove_file file; *) |
114 |
(* (\*disconnect_clients file;*\) *) |
115 |
(* (\*remove_all_clients file;*\) *) |
116 |
(* if Sys.file_exists file.file_torrent_diskname then Sys.remove file.file_torrent_diskname *) |
117 |
|
118 |
let load_torrent_string s user group = |
119 |
if !verbose then lprintf_nl "load_torrent_string"; |
120 |
let file_id, torrent = BTTorrent.decode_torrent s in |
121 |
|
122 |
(* Save the torrent, because we later want to put |
123 |
it in the seeded directory. *) |
124 |
let torrent_diskname = CommonFile.concat_file downloads_directory (torrent.torrent_name ^ ".torrent") in |
125 |
if Sys.file_exists torrent_diskname then |
126 |
begin |
127 |
if !verbose then lprintf_nl "load_torrent_string: %s already exists, ignoring" torrent_diskname; |
128 |
raise (Torrent_already_exists torrent.torrent_name) |
129 |
end; |
130 |
File.from_string torrent_diskname s; |
131 |
|
132 |
if !verbose then |
133 |
lprintf_nl "Starting torrent download with diskname: %s" |
134 |
torrent_diskname; |
135 |
let file = new_download file_id torrent torrent_diskname user group in |
136 |
(* talk_to_tracker file true; TODO stupid fwd declaration issue. OTOH bep9 torrents arent tracker based anyway*) |
137 |
CommonInteractive.start_download (file_find (file_num file)); |
138 |
file |
139 |
|
140 |
let load_torrent_file filename user group = |
141 |
if !verbose then |
142 |
lprintf_nl "load_torrent_file %s" filename; |
143 |
let s = File.to_string filename in |
144 |
(* Delete the torrent if it is in the downloads dir. because it gets saved |
145 |
again under the torrent name and we don't want to clutter up this dir. .*) |
146 |
if Sys.file_exists filename |
147 |
&& (Filename.dirname filename) = downloads_directory then |
148 |
Sys.remove filename; |
149 |
ignore (load_torrent_string s user group) |
150 |
(* end copypasta *) |
151 |
|
152 |
|
153 |
|
103 |
let string_of_event = function |
154 |
let string_of_event = function |
104 |
| READ_DONE -> "READ_DONE" |
155 |
| READ_DONE -> "READ_DONE" |
105 |
| WRITE_DONE -> "WRITE_DONE" |
156 |
| WRITE_DONE -> "WRITE_DONE" |
Lines 540-545
Link Here
|
540 |
let reserved () = |
591 |
let reserved () = |
541 |
let s = String.make 8 '\x00' in |
592 |
let s = String.make 8 '\x00' in |
542 |
s.[7] <- (match !bt_dht with None -> '\x00' | Some _ -> '\x01'); |
593 |
s.[7] <- (match !bt_dht with None -> '\x00' | Some _ -> '\x01'); |
|
|
594 |
s.[5] <- '\x10'; (* TODO bep9, bep10, notify clients about extended*) |
543 |
s |
595 |
s |
544 |
|
596 |
|
545 |
(** handshake *) |
597 |
(** handshake *) |
Lines 569-574
Link Here
|
569 |
*) |
621 |
*) |
570 |
|
622 |
|
571 |
let send_bitfield c = |
623 |
let send_bitfield c = |
|
|
624 |
if c.client_file.file_metadata_downloading then |
625 |
lprintf_nl "dont send bitmap, we are in metadata state" |
626 |
else |
572 |
send_client c (BitField |
627 |
send_client c (BitField |
573 |
( |
628 |
( |
574 |
match c.client_file.file_swarmer with |
629 |
match c.client_file.file_swarmer with |
Lines 607-612
Link Here
|
607 |
|
662 |
|
608 |
c.client_azureus_messaging_protocol <- has_bit 0 0x80 |
663 |
c.client_azureus_messaging_protocol <- has_bit 0 0x80 |
609 |
|
664 |
|
|
|
665 |
let send_extended_handshake c file = |
666 |
let module B = Bencode in |
667 |
let msg = (B.encode (B.Dictionary [(* "e",B.Int 0L; *) |
668 |
"m", (B.Dictionary ["ut_metadata", B.Int 1L]); |
669 |
(* "metadata_size", B.Int (-1L) *)])) in begin |
670 |
lprintf_file_nl (as_file file) "send extended handshake msg %s" msg; |
671 |
send_client c (Extended (Int64.to_int 0L, msg)); |
672 |
end |
673 |
|
674 |
let send_extended_piece_request c piece file = |
675 |
let module B = Bencode in |
676 |
let msg = (B.encode (B.Dictionary ["msg_type", B.Int 0L; (* 0 is request subtype*) |
677 |
"piece", B.Int piece; ])) in begin |
678 |
lprintf_file_nl (as_file file) "send extended request for piece:%Ld msgid:%Ld msg:%s" piece c.client_ut_metadata_msg msg; |
679 |
send_client c (Extended (Int64.to_int c.client_ut_metadata_msg, msg)); |
680 |
end |
681 |
|
682 |
|
610 |
let show_client c = |
683 |
let show_client c = |
611 |
let (ip,port) = c.client_host in |
684 |
let (ip,port) = c.client_host in |
612 |
Printf.sprintf "%s:%d %S" (Ip.to_string ip) port (brand_to_string c.client_brand) |
685 |
Printf.sprintf "%s:%d %S" (Ip.to_string ip) port (brand_to_string c.client_brand) |
Lines 705-710
Link Here
|
705 |
begin |
778 |
begin |
706 |
c.client_incoming <- true; |
779 |
c.client_incoming <- true; |
707 |
send_init !!client_uid file_id sock; |
780 |
send_init !!client_uid file_id sock; |
|
|
781 |
|
782 |
send_extended_handshake c file; |
708 |
end; |
783 |
end; |
709 |
connection_ok c.client_connection_control; |
784 |
connection_ok c.client_connection_control; |
710 |
if !verbose_msg_clients then |
785 |
if !verbose_msg_clients then |
Lines 968-974
Link Here
|
968 |
@param msg The message sent by the client |
1043 |
@param msg The message sent by the client |
969 |
*) |
1044 |
*) |
970 |
and client_to_client c sock msg = |
1045 |
and client_to_client c sock msg = |
971 |
if !verbose_msg_clients then begin |
1046 |
(* if !verbose_msg_clients then begin *) |
972 |
let (ip,port) = (TcpBufferedSocket.peer_addr sock) in |
1047 |
let (ip,port) = (TcpBufferedSocket.peer_addr sock) in |
973 |
let (timeout, next) = get_rtimeout sock in |
1048 |
let (timeout, next) = get_rtimeout sock in |
974 |
lprintf_nl "CLIENT %d(%s:%d): (%d, %d,%d) Received %s" |
1049 |
lprintf_nl "CLIENT %d(%s:%d): (%d, %d,%d) Received %s" |
Lines 977-983
Link Here
|
977 |
(int_of_float timeout) |
1052 |
(int_of_float timeout) |
978 |
(int_of_float next) |
1053 |
(int_of_float next) |
979 |
(TcpMessages.to_string msg); |
1054 |
(TcpMessages.to_string msg); |
980 |
end; |
1055 |
(* end; *) |
981 |
|
1056 |
|
982 |
let file = c.client_file in |
1057 |
let file = c.client_file in |
983 |
|
1058 |
|
Lines 1079-1084
Link Here
|
1079 |
|
1154 |
|
1080 |
| BitField p -> |
1155 |
| BitField p -> |
1081 |
(*A bitfield is a summary of what a client have*) |
1156 |
(*A bitfield is a summary of what a client have*) |
|
|
1157 |
lprintf_file_nl (as_file file) "Bitfield message, metadata state %B" c.client_file.file_metadata_downloading ; |
1158 |
if c.client_file.file_metadata_downloading then |
1159 |
lprintf_file_nl (as_file file) "ignoring Bitfield message, we are in metadata state" |
1160 |
else |
1161 |
|
1082 |
begin |
1162 |
begin |
1083 |
match c.client_file.file_swarmer with |
1163 |
match c.client_file.file_swarmer with |
1084 |
None -> () |
1164 |
None -> () |
Lines 1125-1130
Link Here
|
1125 |
|
1205 |
|
1126 |
| Have n -> |
1206 |
| Have n -> |
1127 |
(* A client can send a "Have" without sending a Bitfield *) |
1207 |
(* A client can send a "Have" without sending a Bitfield *) |
|
|
1208 |
if c.client_file.file_metadata_downloading then |
1209 |
lprintf_file_nl (as_file file) "ignoring Have message, we are in metadata state" |
1210 |
else |
1128 |
begin |
1211 |
begin |
1129 |
match c.client_file.file_swarmer with |
1212 |
match c.client_file.file_swarmer with |
1130 |
None -> () |
1213 |
None -> () |
Lines 1247-1252
Link Here
|
1247 |
if !verbose_msg_clients then |
1330 |
if !verbose_msg_clients then |
1248 |
lprintf_file_nl (as_file file) "Error: received cancel request but client has no slot" |
1331 |
lprintf_file_nl (as_file file) "Error: received cancel request but client has no slot" |
1249 |
|
1332 |
|
|
|
1333 |
| Extended (extmsg, payload) -> |
1334 |
|
1335 |
(* extmsg: 0 handshake, N other message previously declared in handshake. |
1336 |
atm ignore extended messages if were not currently in metadata state. |
1337 |
TODO when were not in metadata state we should be friendly and answer metadata requests |
1338 |
*) |
1339 |
if file.file_metadata_downloading then begin |
1340 |
(* since we got at least one extended handshake from the peer, it should be okay to |
1341 |
send a handshake back now. we need to send it so the remote client knows how |
1342 |
to send us messages back. |
1343 |
this should of course be moved but I dont know where yet. |
1344 |
also we shouldnt send more than one handshake of course... |
1345 |
*) |
1346 |
lprintf_file_nl (as_file file) "Got extended msg: %d %s" extmsg payload; |
1347 |
|
1348 |
match extmsg with |
1349 |
0x0 -> |
1350 |
lprintf_file_nl (as_file file) "Got extended handshake "; |
1351 |
let dict = Bencode.decode payload in begin |
1352 |
match dict with |
1353 |
Dictionary list -> |
1354 |
List.iter (fun (key,value) -> |
1355 |
match key, value with |
1356 |
"metadata_size", Int n -> |
1357 |
lprintf_file_nl (as_file file) "Got metadata size %Ld" n; |
1358 |
c.client_file.file_metadata_size <- n; |
1359 |
| "m", Dictionary mdict -> |
1360 |
lprintf_file_nl (as_file file) "Got meta dict "; |
1361 |
List.iter (fun (key,value) -> |
1362 |
match key, value with |
1363 |
"ut_metadata", Int n -> |
1364 |
lprintf_file_nl (as_file file) "ut_metadata is %Ld " n; |
1365 |
c.client_ut_metadata_msg <- n; |
1366 |
| _ -> (); |
1367 |
) mdict; |
1368 |
|
1369 |
| _ -> () ; |
1370 |
) list; |
1371 |
(* okay so now we know what to ask for, so ask for metadata now |
1372 |
since metadata can be larger than 16k which is the limit, the transfer needs to be chunked, so |
1373 |
it is not really right to make the query here. but its a start. |
1374 |
also im just asking for piece 0. |
1375 |
(we should also check that we actually got the metadata info before proceeding) |
1376 |
*) |
1377 |
|
1378 |
|
1379 |
send_extended_handshake c file; |
1380 |
send_extended_piece_request c c.client_file.file_metadata_piece file; |
1381 |
|_ -> () ; |
1382 |
end; |
1383 |
| 0x01 -> (* ut_metadata is 1 because we asked it to be 1 in the handshake |
1384 |
the msg_type is probably |
1385 |
1 for data, |
1386 |
but could be 0 for request(unlikely since we didnt advertise we had the meta) |
1387 |
2 for reject, also unlikely since peers shouldnt advertise if they dont have(but will need handling in the end) |
1388 |
|
1389 |
{'msg_type': 1, 'piece': 0, 'total_size': 3425} |
1390 |
after the dict comes the actual piece |
1391 |
|
1392 |
*) |
1393 |
lprintf_file_nl (as_file file) "Got extended ut_metadata message "; |
1394 |
let dict = Bencode.decode payload in |
1395 |
let msgtype = ref 0L in begin |
1396 |
begin |
1397 |
match dict with |
1398 |
Dictionary list -> |
1399 |
List.iter (fun (key,value) -> |
1400 |
match key, value with |
1401 |
"msg_type", Int n -> |
1402 |
lprintf_file_nl (as_file file) "msg_type %Ld" n; |
1403 |
msgtype := n; |
1404 |
| "piece", Int n -> |
1405 |
lprintf_file_nl (as_file file) "piece %Ld" n; |
1406 |
file.file_metadata_piece <- n; |
1407 |
| "total_size", Int n -> |
1408 |
lprintf_file_nl (as_file file) "total_size %Ld" n; (* should always be the same as received in the initial handshake i suppose *) |
1409 |
|_ -> () ; |
1410 |
) list; |
1411 |
|_ -> () ; |
1412 |
end; |
1413 |
match !msgtype with |
1414 |
1L -> |
1415 |
let last_piece_index = (Int64.div file.file_metadata_size 16384L) in |
1416 |
lprintf_file_nl (as_file file) "handling metadata piece %Ld of %Ld" |
1417 |
file.file_metadata_piece |
1418 |
last_piece_index; |
1419 |
(* store the metadata piece in memory *) |
1420 |
file.file_metadata_chunks.(1 + (Int64.to_int file.file_metadata_piece)) <- payload; |
1421 |
(* possibly write metadata to disk *) |
1422 |
if file.file_metadata_piece >= |
1423 |
(Int64.div file.file_metadata_size 16384L) then begin |
1424 |
lprintf_file_nl (as_file file) "this was the last piece "; |
1425 |
(* here we should simply delete the current download, and wait for mld to pick up the new torrent file *) |
1426 |
(* the entire payload is currently in the array, TODO *) |
1427 |
let newtorrentfile = (Printf.sprintf "/tmp/BT-%s.torrent" |
1428 |
(Sha1.to_string file.file_id)) in |
1429 |
let fd = Unix32.create_rw newtorrentfile in |
1430 |
let fileindex = ref 0L in |
1431 |
begin |
1432 |
(* the ee is so we can use the same method to find the |
1433 |
start of the payload for the real payloads as well as the synthetic ones |
1434 |
*) |
1435 |
file.file_metadata_chunks.(0) <- "eed4:info"; |
1436 |
file.file_metadata_chunks.(2 + Int64.to_int last_piece_index) <- "eee"; |
1437 |
try |
1438 |
Array.iteri (fun index chunk -> |
1439 |
(* regexp ee is a fugly way to find the end of the 1st dict before the real payload *) |
1440 |
let metaindex = (2 + (Str.search_forward (Str.regexp_string "ee") chunk 0 )) in |
1441 |
let chunklength = ((String.length chunk) - metaindex) in |
1442 |
Unix32.write fd !fileindex chunk |
1443 |
metaindex |
1444 |
chunklength; |
1445 |
fileindex := Int64.add !fileindex (Int64.of_int chunklength); |
1446 |
(); |
1447 |
) file.file_metadata_chunks; |
1448 |
with e -> begin |
1449 |
(* TODO ignoring errors for now, the array isnt really set up right anyway yet *) |
1450 |
lprintf_file_nl (as_file file) "Error %s saving metadata" |
1451 |
(Printexc2.to_string e) |
1452 |
end; |
1453 |
(* Yay, now the new torrent is on disk! amazing! However, now we need to kill the dummy torrent |
1454 |
and restart it with the fresh real torrent *) |
1455 |
|
1456 |
(* it seems we need to use the dynamic interface... *) |
1457 |
lprintf_file_nl (as_file file) "cancelling metadata download "; |
1458 |
let owner = file.file_file.impl_file_owner in |
1459 |
let group = file.file_file.impl_file_group in begin |
1460 |
CommonInteractive.file_cancel (as_file file) owner ; |
1461 |
(* hack_op_file_cancel c.client_file; *) |
1462 |
lprintf_file_nl (as_file file) "starting download from metadata torrent %s" newtorrentfile ; |
1463 |
load_torrent_file newtorrentfile owner group; |
1464 |
end; |
1465 |
end; |
1466 |
|
1467 |
end |
1468 |
else begin |
1469 |
(* now ask for the next metadata piece, if any *) |
1470 |
let module B = Bencode in |
1471 |
let nextpiece = (Int64.succ file.file_metadata_piece) in begin |
1472 |
lprintf_file_nl (as_file file) "asking for the next piece %Ld" nextpiece; |
1473 |
send_extended_piece_request c nextpiece file; |
1474 |
end; |
1475 |
end; |
1476 |
|_ -> |
1477 |
lprintf_file_nl (as_file file) "unmatched extended subtype" ; |
1478 |
end; |
1479 |
|
1480 |
|
1481 |
| _ -> |
1482 |
lprintf_file_nl (as_file file) "Got extended other msg "; |
1483 |
end; |
1484 |
|
1250 |
| DHT_Port port -> |
1485 |
| DHT_Port port -> |
1251 |
match !bt_dht with |
1486 |
match !bt_dht with |
1252 |
| None -> |
1487 |
| None -> |
Lines 1261-1266
Link Here
|
1261 |
BT_DHT.update dht Kademlia.Good id addr |
1496 |
BT_DHT.update dht Kademlia.Good id addr |
1262 |
end |
1497 |
end |
1263 |
|
1498 |
|
|
|
1499 |
|
1264 |
with e -> |
1500 |
with e -> |
1265 |
lprintf_file_nl (as_file file) "Error %s while handling MESSAGE: %s" (Printexc2.to_string e) (TcpMessages.to_string msg) |
1501 |
lprintf_file_nl (as_file file) "Error %s while handling MESSAGE: %s" (Printexc2.to_string e) (TcpMessages.to_string msg) |
1266 |
|
1502 |
|
Lines 1332-1337
Link Here
|
1332 |
lprintf_file_nl (as_file file) "READY TO DOWNLOAD FILE"; |
1568 |
lprintf_file_nl (as_file file) "READY TO DOWNLOAD FILE"; |
1333 |
|
1569 |
|
1334 |
send_init !!client_uid file.file_id sock; |
1570 |
send_init !!client_uid file.file_id sock; |
|
|
1571 |
send_extended_handshake c file; |
1572 |
|
1335 |
(* Fabrice: Initialize the client bitmap and uploader fields to <> None *) |
1573 |
(* Fabrice: Initialize the client bitmap and uploader fields to <> None *) |
1336 |
update_client_bitmap c; |
1574 |
update_client_bitmap c; |
1337 |
(* (try get_from_client sock c with _ -> ());*) |
1575 |
(* (try get_from_client sock c with _ -> ());*) |