drop md4 i?86 specific asm implementations
[mldonkey.git] / src / networks / donkey / donkeyThieves.ml
blob5a6293d3e8a513405bd432f38b0ba4f68a39e10d
1 (* Copyright 2003 pango *)
2 (*
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 Detect clients switching to another client_hash, already is use by
22 someone else (almost certainly a theft).
25 open Printf2
27 open BasicSocket
28 open CommonOptions
29 open Md4
32 let log_prefix = "[eDThieves]"
34 let lprintf_nl fmt =
35 lprintf_nl2 log_prefix fmt
37 type hash_history = Ip.t * Md4.t * int
39 (* index by client IP *)
40 let (client_hashes : (Ip.t, hash_history ref) Hashtbl.t) = Hashtbl.create 1023
42 (* index by client hash *)
43 let hash_of_md4 md4 = Hashtbl.hash (Md4.direct_to_string md4)
45 module Md4HashType =
46 struct type t = Md4.t
47 let equal = Md4.equal
48 let hash = hash_of_md4
49 end
51 module Md4_hashtbl = Hashtbl.Make ( Md4HashType )
53 let hashes_usage = Md4_hashtbl.create 1023
56 let register_client_hash ip hash =
57 let find_by_ip ip =
58 try
59 Hashtbl.find client_hashes ip
60 with Not_found ->
61 let new_record = ref (ip, Md4.null, 0) in
62 Hashtbl.add client_hashes ip new_record;
63 new_record in
65 let find_by_hash hash =
66 try
67 Md4_hashtbl.find hashes_usage hash
68 with Not_found ->
69 let new_record = ref (Ip.null, hash, 0) in
70 Md4_hashtbl.add hashes_usage hash new_record;
71 new_record in
73 let by_ip = find_by_ip ip in
74 let by_hash = find_by_hash hash in
75 let new_record = (ip, hash, last_time ()) in
76 match !by_ip with
77 _, _, 0 ->
78 (* no hash was previously known for that IP. We do not check if the
79 hash was previously used somewhere else, as it could be legitimate
80 (client switching IP address). *)
81 by_ip := new_record;
82 by_hash := new_record;
83 true
84 | _, previous_hash, _ ->
85 if Md4.equal previous_hash hash then begin
86 (* no change, all is fine; just update timestamps *)
87 by_ip := new_record;
88 by_hash := new_record;
89 true
90 end else
91 (* peer changed in hash, what's happening ? *)
92 match !by_hash with
93 _, _, 0 ->
94 (* that hash is original, all is fine *)
95 (* forget old hash *)
96 Md4_hashtbl.remove hashes_usage previous_hash;
97 by_ip := new_record;
98 by_hash := new_record;
99 true
100 | _, _, _ ->
101 (* it switched to a hash that's used somewhere else,
102 that's certainly a theft. *)
103 if !verbose then
104 lprintf_nl "client_md4 %s (ip:%s) was already used somewhere else, that's certainly a theft!"
105 (Md4.to_string hash) (Ip.to_string ip);
106 false
108 let clean_thieves () =
109 let timelimit = last_time () - 3 * 3600 in
110 let obsolete_ips = Hashtbl.fold (fun ip r l ->
111 match !r with _, _, time ->
112 if time < timelimit then
113 ip :: l
114 else l) client_hashes [] in
115 List.iter (fun ip -> Hashtbl.remove client_hashes ip) obsolete_ips;
116 let obsolete_hashes = Md4_hashtbl.fold (fun hash r l ->
117 match !r with _, _, time ->
118 if time < timelimit then
119 hash :: l
120 else l) hashes_usage [] in
121 List.iter (fun hash -> Md4_hashtbl.remove hashes_usage hash) obsolete_hashes
123 module Marshal = struct
125 let to_string v _ =
126 let v = Marshal.to_string v [] in
127 (* The header depends on OCaml version. Remove it. *)
128 let v = String.sub v (Marshal.header_size)
129 (String.length v - Marshal.header_size) in
134 (* test code *)
136 let dump () =
137 lprintf "Hashes history by IP:\n";
138 Hashtbl.iter (fun ip r -> match !r with (ip, md4, time) -> lprintf "%s: %s (%d)\n" (Ip.to_string ip) (Md4.to_string md4) time) client_hashes;
139 lprintf "Hashes history by hash:\n";
140 Md4_hashtbl.iter (fun md4 r -> match !r with (ip, md4, time) -> lprintf "%s: %s (%d)\n" (Md4.to_string md4) (Ip.to_string ip) time) hashes_usage;
141 lprintf "\n"
143 let testcode () =
144 let peer1 = Ip.of_string "1.2.3.4" in
145 let peer2 = Ip.of_string "5.6.7.8" in
146 let peer3 = Ip.of_string "9.10.11.12" in
147 lprintf "Add a peer...\n";
148 assert(register_client_hash peer1 (Md4.of_string "11111111111111111111111111111111"));
149 dump ();
150 lprintf "Another peer...\n";
151 assert(register_client_hash peer2 (Md4.of_string "22222222222222222222222222222222"));
152 dump ();
153 lprintf "First peer changes of hash, ok...\n";
154 assert(register_client_hash peer1 (Md4.of_string "33333333333333333333333333333333"));
155 dump ();
156 lprintf "A third peer appears with the same hash as the first, ok (could be in fact first one switching IP)...\n";
157 assert(register_client_hash peer3 (Md4.of_string "33333333333333333333333333333333"));
158 dump ();
159 lprintf "Second peer takes the hash of the first, wrong!...\n";
160 assert(not (register_client_hash peer2 (Md4.of_string "33333333333333333333333333333333")));
161 dump ();
162 lprintf "Third peer takes a hash that *was* first's hash, ok (?)...\n";
163 assert(register_client_hash peer3 (Md4.of_string "11111111111111111111111111111111"));
164 dump ();
166 exit 2
168 let _ =
169 testcode ()