/
peer_storage.erl
164 lines (147 loc) · 6.11 KB
/
peer_storage.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
%%%---------------------------------------------------------------------
%%% Created by: Eva-Lisa Kedborn, Jing Liu
%%% Creation date: 2011-11-08
%%%---------------------------------------------------------------------
%%% Description module peer_storage
%%%---------------------------------------------------------------------
%%% The peer storage is for storing peers and information about them.
%% It only stores peers that we are currently connected to.
%%%---------------------------------------------------------------------
%%% Exports
%%%---------------------------------------------------------------------
%%% start()
%%% spawns a new process running the init method
%%% returns a pid
%%%---------------------------------------------------------------------
%%% init()
%%% creates an ets table to store the pieces being downloaded
%%%---------------------------------------------------------------------
-module(peer_storage).
-export([start/0, init/0]).
%%---------------------------------------------------------------------
%% Record definition
%% Data Type: peer
%% where:
%% peerid: A process id (default is undefined).
%% interested: An integer (default is 0).
%% choke: An integer (default is 1).
%% ip: An ip address (default is undefined).
%% socket: An integer (default is undefined).
%% port: An integer (default is undefined).
%% request: A string (default is undefined).
%%----------------------------------------------------------------------
-record(peer, {peerid = undefined, interested = 0, choke = 1,
ip = undefined, socket = undefined,
port = undefined, request = undefined}).
start() ->
spawn(?MODULE, init, []).
init() ->
Tid = ets:new(peer_table, [{keypos, #peer.peerid}]),
loop(Tid).
%%--------------------------------------------------------------------
%% Function:loop/1
%% Purpose: receive requests from peer mutex about what functions to
%% execute
%% Args: TableID of peer table
%% Returns: the requested information
%%--------------------------------------------------------------------
loop(Tid) ->
receive
{request, Function, Args, From}->
case Function of
insert_new_peer ->
[Ip, Peer_id, Socket, Port, Request] = Args,
Reply = insert_new_peer(Tid, Ip, Peer_id, Socket,
Port, Request);
update_peer ->
[Peer_id, Field, Value] = Args,
Reply = update_peer(Tid, Peer_id, Field, Value);
delete_peer ->
[Peer_id] = Args,
Reply = delete_peer(Tid, Peer_id);
read_field ->
[Peer_id, Field] = Args,
Reply = read_field(Tid, Peer_id, Field)
end,
From ! {reply, Reply},
loop(Tid);
{lookup, Data, From} ->
Result = ets:lookup(Tid, Data),
From ! {reply, Result},
loop(Tid);
stop -> ok
end.
%%--------------------------------------------------------------------
%% Function: insert_new_peer/6
%% Purpose: insert peer for the first time.
%% Args: TableId of peer table, Ip, PeerId, Socket, Port and Request
%%--------------------------------------------------------------------
insert_new_peer(Tid, Ip, Peer_id, Socket, Port, Request) ->
ets:insert(Tid, #peer{peerid = Peer_id, interested = 0, choke = 1,
ip = Ip, socket = Socket, port = Port,
request = Request}).
%%--------------------------------------------------------------------
%% Function: update_peer/4
%% Purpose: update certain peer fields
%% Args: TableId of peer table, PeerId,the field to be updated, the new value
%%--------------------------------------------------------------------
update_peer(Tid, Peer_id, Field, Value) ->
case Field of
interested ->
[#peer{peerid = Peer_id, interested = _Int, choke = Ch,
ip = Ip, socket = Soc, port = Port, request = Req}] =
ets:lookup(Tid, Peer_id),
ets:insert(Tid, #peer{peerid = Peer_id, interested = Value,
choke = Ch, ip = Ip, socket = Soc,
port = Port, request = Req});
choke ->
[#peer{peerid = Peer_id, interested = Int, choke = _Ch,
ip = Ip, socket = Soc, port = Port, request = Req}] =
ets:lookup(Tid, Peer_id),
ets:insert(Tid, #peer{peerid = Peer_id, interested = Int,
choke = Value, ip = Ip, socket = Soc,
port = Port, request = Req});
socket ->
[#peer{peerid = Peer_id, interested = Int, choke = Ch,
ip = Ip, socket = _Soc, port = Port, request = Req}] =
ets:lookup(Tid, Peer_id),
ets:insert(Tid, #peer{peerid = Peer_id, interested = Int,
choke = Ch, ip = Ip, socket = Value,
port = Port, request = Req});
port ->
[#peer{peerid = Peer_id, interested = Int, choke = Ch,
ip = Ip, socket = Soc, port = _Port, request = Req}] =
ets:lookup(Tid, Peer_id),
ets:insert(Tid, #peer{peerid = Peer_id, interested = Int,
choke = Ch, ip = Ip, socket = Soc,
port = Value, request = Req});
request ->
[#peer{peerid = Peer_id, interested = Int, choke = Ch,
ip = Ip, socket = Soc, port = Port, request = _Req}] =
ets:lookup(Tid, Peer_id),
ets:insert(Tid, #peer{peerid = Peer_id, interested = Int,
choke = Ch, ip = Ip, socket = Soc,
port = Port, request = Value})
end.
%%--------------------------------------------------------------------
%% Function: delete_peer/2
%% Purpose: delete a peer from the peer table
%% Args: tableId of the peer table, PeerId
%%--------------------------------------------------------------------
delete_peer(Tid, Peer_id)->
ets:delete(Tid, Peer_id).
%%--------------------------------------------------------------------
%% Function: read_field/3
%% Purpose: read certain peer fields and return their value
%% Args: tableId of the peer table, PeerId,the field to be read
%% Returns: the value of the requested field
%%--------------------------------------------------------------------
read_field(Tid, Peer_id, Field) ->
[Peer] = ets:lookup(Tid, Peer_id),
case Field of
interested -> Peer#peer.interested;
choke -> Peer#peer.choke;
socket -> Peer#peer.socket;
port -> Peer#peer.port;
request -> Peer#peer.request
end.