/
etorrent_peer_pool.erl
76 lines (64 loc) · 2.89 KB
/
etorrent_peer_pool.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
%% @author Jesper Louis Andersen <jesper.louis.andersen@gmail.com>
%% @doc Supervise a pool of peers.
%% <p>This module is a simple supervisor of Peers</p>
%% @end
-module(etorrent_peer_pool).
-behaviour(supervisor).
%% API
-export([start_link/1, start_child/7, start_child/8]).
%% Supervisor callbacks
-export([init/1]).
-define(SERVER, ?MODULE).
-type ipaddr() :: etorrent_types:ipaddr().
-type portnum() :: etorrent_types:portnum().
-type capabilities() :: etorrent_types:capabilities().
%% ====================================================================
%% @doc Start the pool supervisor
%% @end
-spec start_link(integer()) -> {ok, pid()} | ignore | {error, term()}.
start_link(Id) -> supervisor:start_link(?MODULE, [Id]).
%% @doc Add a peer to the supervisor pool.
%% <p>Post-factum, when new peers arrives, or we deplete the number of connected
%% peer below a certain threshold, we add new peers. When this happens, we call
%% the add_peer/7 function given here. It sets up a peer and adds it to the
%% supervisor.</p>
%% @end
-spec start_child(binary(), binary(), binary(), integer(),
{ipaddr(), portnum()}, [capabilities()], port()) ->
{ok, pid(), pid()} | {error, term()}.
start_child(LocalPeerId, RemotePeerId, InfoHash, TorrentId,
{IP, Port}, Capabilities, Socket) ->
start_child("no_tracker_url", LocalPeerId, RemotePeerId, InfoHash,
TorrentId, {IP, Port}, Capabilities, Socket).
-spec start_child(string(), binary(), binary(), binary(), integer(),
{ipaddr(), portnum()}, [capabilities()], port()) ->
{ok, pid(), pid()} | {error, term()}.
start_child(TrackerUrl, LocalPeerId, RemotePeerId, InfoHash, TorrentId,
{IP, Port}, Capabilities, Socket)
when is_integer(TorrentId) ->
Params = [TrackerUrl, LocalPeerId, RemotePeerId, InfoHash,
TorrentId, {IP, Port}, Capabilities, Socket],
GroupPid = group_pid(TorrentId),
case supervisor:start_child(GroupPid, Params) of
{ok, _Pid} ->
RecvPid = etorrent_peer_recv:await_server(Socket),
ControlPid = etorrent_peer_control:await_server(Socket),
{ok, RecvPid, ControlPid};
{error, Reason} ->
lager:warning("Error starting child: ~p", [Reason]),
{error, Reason}
end.
%% ====================================================================
%% @private
init([Id]) ->
gproc:add_local_name({torrent, Id, peer_pool_sup}),
ChildSpec = {child,
{etorrent_peer_control, start_link, []},
temporary, 10*1000, worker, [etorrent_peer_control]},
{ok, {{simple_one_for_one, 50, 3600}, [ChildSpec]}}.
%% --------------------------------------------------
group_pid(Id) ->
case gproc:lookup_local_name({torrent, Id, peer_pool_sup}) of
Pid when is_pid(Pid) -> Pid;
Otherwise -> error({dead_pool, Otherwise, Id})
end.