Browse files

Merge remote branch 'tim/master'

  • Loading branch information...
2 parents 8e7646a + b88c813 commit 41d097d46aa2059a49e89e93b5e9a91b0655fdb5 @monkeydom monkeydom committed Mar 12, 2011
Showing with 78 additions and 28 deletions.
  1. +1 −0 src/servtorrent.erl
  2. +1 −1 src/servtorrent_sup.erl
  3. +38 −27 src/tracker_web.erl
  4. +38 −0 src/trackerdb.erl
View
1 src/servtorrent.erl
@@ -13,4 +13,5 @@ start(_, _) ->
torrentdb:init(),
piecesdb:init(),
peerdb:init(),
+ trackerdb:init(),
servtorrent_sup:start_link().
View
2 src/servtorrent_sup.erl
@@ -37,7 +37,7 @@ init([]) ->
{peer_sup, start_link, []},
permanent, 2000, supervisor, [peer_sup]},
Tracker = {tracker_web,
- {tracker_web, start, [[{ip, "::"}, {port, 6969}]]},
+ {tracker_web, start, [[{ip, "0.0.0.0"}, {port, 6969}]]},
permanent, 2000, worker, [tracker_web]},
SeedList = {seedlist,
{seedlist, start_link, []},
View
65 src/tracker_web.erl
@@ -17,39 +17,50 @@ stop() ->
mochiweb_http:stop(?MODULE).
loop(Req) ->
- "/" ++ Path = Req:get(path),
- try
- case Req:get(method) of
- Method when Method =:= 'GET'; Method =:= 'HEAD' ->
- case Path of
- _ ->
- Req:ok({"text/plain", "Hello, world!"})
- end;
- 'POST' ->
- case Path of
- _ ->
- Req:not_found()
- end;
- _ ->
- Req:respond({501, [], []})
- end
- catch
- Type:What ->
- Report = ["web request failed",
- {path, Path},
- {type, Type}, {what, What},
- {trace, erlang:get_stacktrace()}],
- error_logger:error_report(Report),
- %% NOTE: mustache templates need \\ because they are not awesome.
- Req:respond({500, [{"Content-Type", "text/plain"}],
- "request failed, sorry\\n"})
- end.
+ case {Req:get(method), Req:get(path)} of
+ { 'GET', "/announce" } ->
+ Query = Req:parse_qs(),
+ io:format("~p~n", [Query]),
+ {ok, Ip} = inet_parse:address(Req:get(peer)),
+ InfoHash = list_to_binary(proplists:get_value("info_hash", Query)),
+ PeerId = list_to_binary(proplists:get_value("peer_id", Query)),
+ Port = list_to_integer(proplists:get_value("port", Query)),
+ Uploaded = list_to_integer(proplists:get_value("uploaded", Query, "0")),
+ Downloaded = list_to_integer(proplists:get_value("downloaded", Query, "0")),
+ Left = list_to_integer(proplists:get_value("left", Query, "0")),
+ _Compact = list_to_integer(proplists:get_value("compact", Query, "0")),
+ _Crypto = list_to_integer(proplists:get_value("supportcrypto", Query, "0")),
+ _Key = list_to_binary(proplists:get_value("key", Query, "")),
+
+ { ok, AvailablePeers, Complete, Incomplete } = trackerdb:announce(InfoHash, Ip, Port, PeerId, Uploaded, Downloaded, Left),
+
+ Payload = << <<A,B,C,D,P:16/big>> || { _, {A,B,C,D}, P } <- AvailablePeers >>,
+ Response = benc:to_binary([{<<"peers">>, Payload}]),
+
+ io:format("~s~n", [Response]),
+ Req:ok({"text/plain", Response});
+ _ ->
+ Req:respond({501, [{"Content-Type", "text/plain"}], "Malformed request."})
+ end.
%% Internal API
get_option(Option, Options) ->
{proplists:get_value(Option, Options), proplists:delete(Option, Options)}.
+
+get_remote_addr_(Addr) ->
+%%io:format("get_remote_addr_(~p)~n", [Addr]),
+ case inet_parse:ipv6_address(Addr) of
+ {ok, {0, 0, 0, 0, 0, 16#ffff, AB, CD}} ->
+ {AB bsr 8, AB band 16#ff, CD bsr 8, CD band 16#ff};
+ {ok, Addr6} ->
+ Addr6
+ end.
+-define(GET_REMOTE_ADDR, get_remote_addr_(Req:get(peer))).
+
+
+
%%
%% Tests
%%
View
38 src/trackerdb.erl
@@ -0,0 +1,38 @@
+-module(trackerdb).
+
+-export([init/0, announce/7]).
+
+-record(pirate, { id, info_hash, ip, port, peer_id,
+ uploaded, downloaded, left,
+ first_seen, last_seen}).
+
+
+init() ->
+ mnesia:create_table(pirate,
+ [{attributes, record_info(fields, pirate)}, {type, set}, {index, [info_hash]}]).
+
+announce(InfoHash, Ip, Port, PeerId, Uploaded, Downloaded, Left) ->
+ {atomic, Result} = mnesia:transaction(fun() ->
+ AllPeers = mnesia:index_read(pirate, InfoHash, #pirate.info_hash),
+ Now = make_timestamp(now),
+ PeerUpdate = case mnesia:read(pirate, { InfoHash, Ip, Port }) of
+ [Peer = #pirate{ }] -> Peer#pirate { peer_id = PeerId, uploaded = Uploaded,
+ downloaded = Downloaded, left = Left, last_seen = Now };
+ [] -> #pirate{ id = {InfoHash, Ip, Port},
+ info_hash = InfoHash, ip = Ip, port = Port, peer_id = PeerId,
+ uploaded = Uploaded, downloaded = Downloaded, left = Left,
+ first_seen = Now, last_seen = Now }
+ end,
+ mnesia:write(PeerUpdate),
+
+ AvailablePeers = [ { TmpPeerId, TmpIp, TmpPort } ||
+ #pirate{ peer_id = TmpPeerId, ip = TmpIp, port = TmpPort } <- AllPeers],
+ Complete = 0, Incomplete = 0,
+ { ok, AvailablePeers, Complete, Incomplete }
+ end),
+ Result.
+
+
+make_timestamp(now) ->
+ { MegaSeconds, Seconds, MicroSeconds} = erlang:now(),
+ (MegaSeconds * 1000000 + Seconds) * 1000000 + MicroSeconds.

0 comments on commit 41d097d

Please sign in to comment.