1.1 --- a/src/gazzera.lpi Thu Oct 15 19:12:00 2009 +0200
1.2 +++ b/src/gazzera.lpi Fri Oct 16 19:34:00 2009 +0200
1.3 @@ -12,7 +12,7 @@
1.4 </Flags>
1.5 <MainUnit Value="0"/>
1.6 <TargetFileExt Value=""/>
1.7 - <ActiveEditorIndexAtStart Value="1"/>
1.8 + <ActiveEditorIndexAtStart Value="3"/>
1.9 </General>
1.10 <PublishOptions>
1.11 <Version Value="2"/>
1.12 @@ -185,7 +185,7 @@
1.13 <UnitName Value="nodedatabaseunit"/>
1.14 <CursorPos X="31" Y="103"/>
1.15 <TopLine Value="92"/>
1.16 - <EditorIndex Value="3"/>
1.17 + <EditorIndex Value="9"/>
1.18 <UsageCount Value="63"/>
1.19 <Loaded Value="True"/>
1.20 <SyntaxHighlighter Value="Delphi"/>
1.21 @@ -225,9 +225,11 @@
1.22 <Unit24>
1.23 <Filename Value="database\sqliteunit.pas"/>
1.24 <UnitName Value="sqliteunit"/>
1.25 - <CursorPos X="39" Y="69"/>
1.26 - <TopLine Value="53"/>
1.27 + <CursorPos X="26" Y="185"/>
1.28 + <TopLine Value="176"/>
1.29 + <EditorIndex Value="1"/>
1.30 <UsageCount Value="43"/>
1.31 + <Loaded Value="True"/>
1.32 <SyntaxHighlighter Value="Delphi"/>
1.33 </Unit24>
1.34 <Unit25>
1.35 @@ -484,7 +486,7 @@
1.36 <UnitName Value="browsepluginunit"/>
1.37 <CursorPos X="112" Y="123"/>
1.38 <TopLine Value="111"/>
1.39 - <EditorIndex Value="2"/>
1.40 + <EditorIndex Value="8"/>
1.41 <UsageCount Value="32"/>
1.42 <Loaded Value="True"/>
1.43 <SyntaxHighlighter Value="Delphi"/>
1.44 @@ -492,9 +494,11 @@
1.45 <Unit60>
1.46 <Filename Value="ultimatesockets\normalsocketunit.pas"/>
1.47 <UnitName Value="normalsocketunit"/>
1.48 - <CursorPos X="29" Y="39"/>
1.49 - <TopLine Value="35"/>
1.50 + <CursorPos X="62" Y="63"/>
1.51 + <TopLine Value="37"/>
1.52 + <EditorIndex Value="6"/>
1.53 <UsageCount Value="67"/>
1.54 + <Loaded Value="True"/>
1.55 <SyntaxHighlighter Value="Delphi"/>
1.56 </Unit60>
1.57 <Unit61>
1.58 @@ -616,9 +620,11 @@
1.59 <Unit77>
1.60 <Filename Value="ultimatesockets\socketunit.pas"/>
1.61 <UnitName Value="socketunit"/>
1.62 - <CursorPos X="61" Y="373"/>
1.63 + <CursorPos X="63" Y="374"/>
1.64 <TopLine Value="349"/>
1.65 + <EditorIndex Value="5"/>
1.66 <UsageCount Value="44"/>
1.67 + <Loaded Value="True"/>
1.68 <SyntaxHighlighter Value="Delphi"/>
1.69 </Unit77>
1.70 <Unit78>
1.71 @@ -671,9 +677,11 @@
1.72 <Unit84>
1.73 <Filename Value="node\plugins\friendpluginunit.pas"/>
1.74 <UnitName Value="friendpluginunit"/>
1.75 - <CursorPos X="1" Y="232"/>
1.76 - <TopLine Value="217"/>
1.77 + <CursorPos X="13" Y="491"/>
1.78 + <TopLine Value="454"/>
1.79 + <EditorIndex Value="3"/>
1.80 <UsageCount Value="40"/>
1.81 + <Loaded Value="True"/>
1.82 <SyntaxHighlighter Value="Delphi"/>
1.83 </Unit84>
1.84 <Unit85>
1.85 @@ -719,9 +727,11 @@
1.86 <Unit90>
1.87 <Filename Value="node\pluginmanagerunit.pas"/>
1.88 <UnitName Value="pluginmanagerunit"/>
1.89 - <CursorPos X="90" Y="113"/>
1.90 + <CursorPos X="1" Y="130"/>
1.91 <TopLine Value="104"/>
1.92 + <EditorIndex Value="4"/>
1.93 <UsageCount Value="52"/>
1.94 + <Loaded Value="True"/>
1.95 <SyntaxHighlighter Value="Delphi"/>
1.96 </Unit90>
1.97 <Unit91>
1.98 @@ -823,9 +833,11 @@
1.99 <Unit104>
1.100 <Filename Value="database\databaseunit.pas"/>
1.101 <UnitName Value="databaseunit"/>
1.102 - <CursorPos X="13" Y="25"/>
1.103 - <TopLine Value="4"/>
1.104 + <CursorPos X="22" Y="24"/>
1.105 + <TopLine Value="3"/>
1.106 + <EditorIndex Value="7"/>
1.107 <UsageCount Value="18"/>
1.108 + <Loaded Value="True"/>
1.109 <SyntaxHighlighter Value="Delphi"/>
1.110 </Unit104>
1.111 <Unit105>
1.112 @@ -910,9 +922,9 @@
1.113 <Unit117>
1.114 <Filename Value="node\plugins\searchpluginunit.pas"/>
1.115 <UnitName Value="searchpluginunit"/>
1.116 - <CursorPos X="1" Y="154"/>
1.117 + <CursorPos X="27" Y="151"/>
1.118 <TopLine Value="132"/>
1.119 - <EditorIndex Value="1"/>
1.120 + <EditorIndex Value="2"/>
1.121 <UsageCount Value="22"/>
1.122 <Loaded Value="True"/>
1.123 <SyntaxHighlighter Value="Delphi"/>
1.124 @@ -1872,11 +1884,127 @@
1.125 <SyntaxHighlighter Value="Delphi"/>
1.126 </Unit250>
1.127 </Units>
1.128 - <JumpHistory Count="1" HistoryIndex="0">
1.129 + <JumpHistory Count="30" HistoryIndex="29">
1.130 <Position1>
1.131 - <Filename Value="gazzera.pas"/>
1.132 - <Caret Line="93" Column="12" TopLine="58"/>
1.133 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.134 + <Caret Line="469" Column="1" TopLine="448"/>
1.135 </Position1>
1.136 + <Position2>
1.137 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.138 + <Caret Line="470" Column="1" TopLine="449"/>
1.139 + </Position2>
1.140 + <Position3>
1.141 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.142 + <Caret Line="474" Column="1" TopLine="453"/>
1.143 + </Position3>
1.144 + <Position4>
1.145 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.146 + <Caret Line="475" Column="1" TopLine="463"/>
1.147 + </Position4>
1.148 + <Position5>
1.149 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.150 + <Caret Line="457" Column="31" TopLine="436"/>
1.151 + </Position5>
1.152 + <Position6>
1.153 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.154 + <Caret Line="458" Column="1" TopLine="437"/>
1.155 + </Position6>
1.156 + <Position7>
1.157 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.158 + <Caret Line="459" Column="1" TopLine="438"/>
1.159 + </Position7>
1.160 + <Position8>
1.161 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.162 + <Caret Line="461" Column="1" TopLine="440"/>
1.163 + </Position8>
1.164 + <Position9>
1.165 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.166 + <Caret Line="462" Column="1" TopLine="441"/>
1.167 + </Position9>
1.168 + <Position10>
1.169 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.170 + <Caret Line="464" Column="1" TopLine="443"/>
1.171 + </Position10>
1.172 + <Position11>
1.173 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.174 + <Caret Line="465" Column="1" TopLine="444"/>
1.175 + </Position11>
1.176 + <Position12>
1.177 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.178 + <Caret Line="466" Column="1" TopLine="445"/>
1.179 + </Position12>
1.180 + <Position13>
1.181 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.182 + <Caret Line="467" Column="1" TopLine="446"/>
1.183 + </Position13>
1.184 + <Position14>
1.185 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.186 + <Caret Line="469" Column="1" TopLine="448"/>
1.187 + </Position14>
1.188 + <Position15>
1.189 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.190 + <Caret Line="470" Column="1" TopLine="449"/>
1.191 + </Position15>
1.192 + <Position16>
1.193 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.194 + <Caret Line="474" Column="1" TopLine="453"/>
1.195 + </Position16>
1.196 + <Position17>
1.197 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.198 + <Caret Line="484" Column="1" TopLine="463"/>
1.199 + </Position17>
1.200 + <Position18>
1.201 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.202 + <Caret Line="478" Column="33" TopLine="454"/>
1.203 + </Position18>
1.204 + <Position19>
1.205 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.206 + <Caret Line="477" Column="1" TopLine="456"/>
1.207 + </Position19>
1.208 + <Position20>
1.209 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.210 + <Caret Line="478" Column="1" TopLine="457"/>
1.211 + </Position20>
1.212 + <Position21>
1.213 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.214 + <Caret Line="479" Column="1" TopLine="458"/>
1.215 + </Position21>
1.216 + <Position22>
1.217 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.218 + <Caret Line="484" Column="1" TopLine="463"/>
1.219 + </Position22>
1.220 + <Position23>
1.221 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.222 + <Caret Line="487" Column="1" TopLine="466"/>
1.223 + </Position23>
1.224 + <Position24>
1.225 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.226 + <Caret Line="488" Column="1" TopLine="467"/>
1.227 + </Position24>
1.228 + <Position25>
1.229 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.230 + <Caret Line="490" Column="1" TopLine="469"/>
1.231 + </Position25>
1.232 + <Position26>
1.233 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.234 + <Caret Line="509" Column="1" TopLine="478"/>
1.235 + </Position26>
1.236 + <Position27>
1.237 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.238 + <Caret Line="238" Column="1" TopLine="217"/>
1.239 + </Position27>
1.240 + <Position28>
1.241 + <Filename Value="node\pluginmanagerunit.pas"/>
1.242 + <Caret Line="130" Column="1" TopLine="104"/>
1.243 + </Position28>
1.244 + <Position29>
1.245 + <Filename Value="ultimatesockets\socketunit.pas"/>
1.246 + <Caret Line="374" Column="63" TopLine="349"/>
1.247 + </Position29>
1.248 + <Position30>
1.249 + <Filename Value="node\plugins\friendpluginunit.pas"/>
1.250 + <Caret Line="238" Column="1" TopLine="241"/>
1.251 + </Position30>
1.252 </JumpHistory>
1.253 </ProjectOptions>
1.254 <CompilerOptions>
1.255 @@ -1902,7 +2030,7 @@
1.256 </Other>
1.257 </CompilerOptions>
1.258 <Debugging>
1.259 - <BreakPoints Count="8">
1.260 + <BreakPoints Count="9">
1.261 <Item1>
1.262 <Source Value="node\plugins\uploadpluginunit.pas"/>
1.263 <Line Value="440"/>
1.264 @@ -1935,6 +2063,10 @@
1.265 <Source Value="node\nodedatabaseunit.pas"/>
1.266 <Line Value="105"/>
1.267 </Item8>
1.268 + <Item9>
1.269 + <Source Value="node\plugins\friendpluginunit.pas"/>
1.270 + <Line Value="475"/>
1.271 + </Item9>
1.272 </BreakPoints>
1.273 <Watches Count="5">
1.274 <Item1>
2.1 --- a/src/node/plugins/friendpluginunit.pas Thu Oct 15 19:12:00 2009 +0200
2.2 +++ b/src/node/plugins/friendpluginunit.pas Fri Oct 16 19:34:00 2009 +0200
2.3 @@ -1,512 +1,521 @@
2.4 -unit friendpluginunit;
2.5 -{$H+}
2.6 -
2.7 -interface
2.8 -uses Classes, SysUtils, pluginunit, peerunit, messagesunit, logunit,
2.9 - directoryscannerunit, controllercommandsunit, propertiesunit, personunit,
2.10 - statusunit, socketunit, stringdictionaryunit, databaseunit, nodedatabaseunit,
2.11 - validatorsunit, newnodeserverunit, stringutilunit, dateutils, dateunit;
2.12 -
2.13 -type
2.14 -TFriendPlugin = class(TPlugin)
2.15 - private
2.16 - checking: TStringDictionary; // these are peers we are connecting directly.
2.17 - // After a while, if connection failed, we use the peerfinder to try again.
2.18 - procedure commandAddFriend(m:TMsgCommandAddFriend);
2.19 - procedure commandBan(m:TMsgCommandBan);
2.20 - procedure commandRemoveFriend(m:TMsgCommandRemoveFriend);
2.21 - procedure commandConnectToPeer(m:TMsgCommandConnectToPeer);
2.22 - procedure commandConnectToAddress(m:TMsgCommandConnectToAddress);
2.23 - procedure commandCloseNode(m:TMsgCommandCloseNode);
2.24 - procedure commandHello;
2.25 - procedure everyFiveSeconds;
2.26 - procedure everyMinute;
2.27 - procedure readHello(m:TMsgHelloFirst);
2.28 - procedure readMetaSharedFoldersRefreshed(m:TMsgMetaSharedFoldersRefreshed);
2.29 - procedure readSharedInfo(m:TMsgSharedInfo);
2.30 - protected
2.31 - function getName: string; override;
2.32 - public
2.33 - procedure Initialize; override;
2.34 - procedure Finalize; override;
2.35 - procedure OnMessage(m:TMessage); override;
2.36 -end;
2.37 -
2.38 -procedure NotifyPeerInfo(pe:TPerson);
2.39 -
2.40 -
2.41 -implementation
2.42 -uses peerfinderpluginunit, trustpluginunit, objectsunit;
2.43 -
2.44 -
2.45 -procedure NotifyPeerInfo(pe:TPerson);
2.46 -var s:string;
2.47 - rs:TResultSet;
2.48 -begin
2.49 - s:='';
2.50 - rs:=Database.executeQuery('select groupName from peopleGroups where gid = ?', [pe.gid]);
2.51 - try
2.52 - while rs.next do
2.53 - begin
2.54 - if s<>'' then s:=s+', ';
2.55 - s:=s+rs[0];
2.56 - end;
2.57 - finally
2.58 - rs.Free;
2.59 - end;
2.60 - Notifier.postToController(TMsgCommandPeerAdd.Create(pe.nickname, pe.gid,
2.61 - StatusStr[pe.status], PluginManager.PeerList.containsGid(pe.gid),
2.62 - pe.sharedbytes, pe.sharedfiles, pe.dynhost, pe.lastAddr, pe.lastPort, s));
2.63 -end;
2.64 -
2.65 -function TFriendPlugin.getName: string;
2.66 -begin
2.67 - result := 'Friend Plugin';
2.68 -end;
2.69 -
2.70 -procedure TFriendPlugin.Finalize;
2.71 -begin
2.72 - log(llInfo, 'Finalize');
2.73 - checking.free;
2.74 -end;
2.75 -
2.76 -procedure TFriendPlugin.Initialize;
2.77 -var
2.78 - rs: TResultSet;
2.79 - a, p, gid: string;
2.80 -begin
2.81 - log(llInfo, 'Initialize');
2.82 - registerMessageType(mtHelloFirst);
2.83 - registerMessageType(mtSharedInfo);
2.84 - registerMessageType(mtCommandAddFriend);
2.85 - registerMessageType(mtCommandHello);
2.86 - registerMessageType(mtCommandRemoveFriend);
2.87 - registerMessageType(mtCommandBan);
2.88 - registerMessageType(mtCommandConnectToAddress);
2.89 - registerMessageType(mtCommandConnectToPeer);
2.90 - registerMessageType(mtMetaFiveSeconds);
2.91 - registerMessageType(mtMetaOneMinute);
2.92 - registerMessageType(mtMetaSharedFoldersRefreshed);
2.93 - registerMessageType(mtCommandCloseNode);
2.94 - checking := TStringDictionary.create;
2.95 - rs := Database.executeQuery('select lastAddr, lastPort, gid, dynhost from people where status in (''FRIEND'',''TRUSTED'')');
2.96 - while rs.next do
2.97 - begin
2.98 - a := rs[3];
2.99 - gid := rs[2];
2.100 - if a='' then a:=rs[0];
2.101 - p := rs[1];
2.102 - if (a <> '') and (p <> '') then
2.103 - begin
2.104 - Database.executeUpdate('update people set lastConnAttempt = ? where gid = ?', [dtos(now), gid]);
2.105 - Core.startConnectTo(a, strtoint(p));
2.106 - checking.put(gid, dtos(now));
2.107 - end;
2.108 - end;
2.109 - rs.free;
2.110 -end;
2.111 -
2.112 -procedure TFriendPlugin.readMetaSharedFoldersRefreshed(m:TMsgMetaSharedFoldersRefreshed);
2.113 -var
2.114 - i64: int64;
2.115 - i: integer;
2.116 -begin
2.117 - ShareManager.getSharedInfo(i64, i);
2.118 - for i:=0 to PluginManager.PeerList.Count-1 do
2.119 - PluginManager.PeerList.get(i).enqueue(TMsgSharedInfo.Create(i64, i));
2.120 -end;
2.121 -
2.122 -procedure TFriendPlugin.readSharedInfo(m:TMsgSharedInfo);
2.123 -var person: TPerson;
2.124 -begin
2.125 - person := TPerson.load(m.peer.gid);
2.126 - try
2.127 - person.sharedBytes:=m.sharedbytes;
2.128 - person.sharedFiles:=m.sharedfiles;
2.129 - person.save();
2.130 - NotifyPeerInfo(person);
2.131 - //Notifier.postToController(TMsgCommandPeerAddReplaceMe.create(person.nickname,
2.132 - //person.gid, StatusStr[person.status], PluginManager.PeerList.containsGid(person.gid),
2.133 - //person.sharedBytes, person.sharedFiles));
2.134 - finally
2.135 - person.free;
2.136 - end;
2.137 -end;
2.138 -
2.139 -procedure TFriendPlugin.readHello(m:TMsgHelloFirst);
2.140 -var pe: TPerson;
2.141 -begin
2.142 - log(llInfo, 'Received Hello ');
2.143 - if m.majorVersion <> LAST_MAJOR_VERSION then
2.144 - begin
2.145 - log(llError, 'version not valid: ' + inttostr(m.majorVersion));
2.146 - if m.majorVersion > LAST_MAJOR_VERSION
2.147 - then Notifier.postToController(TMsgCommandNewVersion.Create());
2.148 - m.peer.Socket.close;
2.149 - exit;
2.150 - end;
2.151 -
2.152 - if m.minorVersion > LAST_MINOR_VERSION then
2.153 - Notifier.postToController(TMsgCommandNewVersion.Create());
2.154 -
2.155 - if not nicknameRegex.exec(m.nickname) then
2.156 - begin
2.157 - log(llError, 'Nickname not validated: ' + m.nickname + ' ' + m.peer.gid);
2.158 - m.peer.Socket.close;
2.159 - exit;
2.160 - end;
2.161 - pe := m.peer.Person;
2.162 -
2.163 - // handle dynamic host hint
2.164 -(*
2.165 - // TODO review this part
2.166 - if dynhost <> '' then
2.167 - if validateHost(dynhost, peer.socket.getAddress.sin_addr) then
2.168 - pe.addKarma(1, 'Valid dynamic host')
2.169 - else
2.170 - begin
2.171 - pe.addKarma(-5, 'Invalid dynamic host');
2.172 - dynhost := pe.dynhost; // keep current
2.173 - end;
2.174 -*)
2.175 - pe.nickname := m.nickname;
2.176 - pe.dynhost := m.nodeSuggestedHost;
2.177 - pe.lastAddr := InAddrToIp(m.peer.Address);
2.178 - pe.lastPort := m.nodePort;
2.179 - pe.lastSeen := now();
2.180 - pe.sharedFiles := m.sharedFiles;
2.181 - pe.sharedBytes := m.sharedbytes;
2.182 - pe.save();
2.183 - // send again with correct info
2.184 - NotifyPeerInfo(pe);
2.185 -end;
2.186 -
2.187 -procedure TFriendPlugin.commandHello;
2.188 -var
2.189 - rs: TResultSet;
2.190 - online: boolean;
2.191 - p: TPerson;
2.192 -begin
2.193 - // i also send the node info to the controller, as the controller could be just connected
2.194 - core.updateNodeInfo;
2.195 -
2.196 - // the controller connected, send the list of all friends
2.197 - rs := Database.executeQuery('select gid from people');
2.198 - try
2.199 - while rs.next do
2.200 - begin
2.201 - p:=TPerson.load(rs[0]);
2.202 - //online := PluginManager.PeerList.containsGid(p.gid);
2.203 - //Notifier.postToController(TMsgCommandPeerAddReplaceMe.Create(p.nickname,
2.204 - // p.gid, StatusStr[p.status], online, p.sharedBytes, p.sharedFiles));
2.205 - NotifyPeerInfo(p);
2.206 - p.free;
2.207 - end;
2.208 - finally
2.209 - rs.free;
2.210 - end;
2.211 -end;
2.212 -
2.213 -procedure TFriendPlugin.OnMessage(m:TMessage);
2.214 -begin
2.215 - case m.msgType of
2.216 - mtHelloFirst: readHello(TMsgHelloFirst(m));
2.217 - mtSharedInfo: readSharedInfo(TMsgSharedInfo(m));
2.218 - mtCommandAddFriend: commandAddFriend(TMsgCommandAddFriend(m));
2.219 - mtCommandRemoveFriend: commandRemoveFriend(TMsgCommandRemoveFriend(m));
2.220 - mtCommandHello: commandHello;
2.221 - mtCommandBan: commandBan(TMsgCommandBan(m));
2.222 - mtCommandConnectToAddress: commandConnectToAddress(TMsgCommandConnectToAddress(m));
2.223 - mtCommandConnectToPeer: commandConnectToPeer(TMsgCommandConnectToPeer(m));
2.224 - mtMetaFiveSeconds: everyFiveSeconds;
2.225 - mtMetaOneMinute: everyMinute;
2.226 - mtMetaSharedFoldersRefreshed: readMetaSharedFoldersRefreshed(TMsgMetaSharedFoldersRefreshed(m));
2.227 - mtCommandCloseNode: commandCloseNode(TMsgCommandCloseNode(m));
2.228 - end;
2.229 -(*
2.230 - if msg[0] = BAN then
2.231 - commandBan(msg[1]);
2.232 - if msg[0] = REMOVEFRIEND then
2.233 - commandRemoveFriend(msg[1]);
2.234 - if msg[0] = CONNECTTO then
2.235 - commandConnectTo(msg[1]);
2.236 - if msg[0] = CONNECTTOADDRESS then
2.237 - commandConnectToAddress(msg[1]);
2.238 - if msg[0] = HELLO then
2.239 - commandHello;
2.240 -*)
2.241 -end;
2.242 -
2.243 -procedure TFriendPlugin.commandConnectToAddress(m:TMsgCommandConnectToAddress);
2.244 -var
2.245 - addr: string;
2.246 - port: word;
2.247 -begin
2.248 - if (m.address <> '') and addrRegex.Exec(m.address) then
2.249 - begin
2.250 - addr := addrRegex.Results[1];
2.251 - port := strtoint(addrRegex.Results[2]);
2.252 - Core.startConnectTo(addr, port);
2.253 - exit;
2.254 - end;
2.255 - Notifier.postToController(TMsgCommandError.create('Invalid address. Format is: host:port'));
2.256 -end;
2.257 -
2.258 -procedure TFriendPlugin.commandAddFriend(m:TMsgCommandAddFriend);
2.259 -var
2.260 - person: TPerson;
2.261 - addr: string;
2.262 - port: word;
2.263 -begin
2.264 - log(llInfo, 'Adding friend: '+ m.fullid);
2.265 -
2.266 - if gidRegex.exec(m.fullid) then
2.267 - begin
2.268 - if gidRegex.Results.Count > 4 then
2.269 - begin
2.270 - addr := gidRegex.results[4];
2.271 - port := strtoint(gidRegex.results[5]);
2.272 - end
2.273 - else
2.274 - begin
2.275 - addr := '';
2.276 - port := 0;
2.277 - end;
2.278 -
2.279 -
2.280 - person := TPerson.Load(gidRegex.results[2]);
2.281 - if person <> nil then
2.282 - try
2.283 - if person.status in [sFriend, sTrusted] then
2.284 - begin
2.285 - // if he specified the address, we connect and say nothing, else we give a warning
2.286 - if addr <> '' then
2.287 - Core.startConnectTo(addr, port)
2.288 - else
2.289 - Notifier.postToController(TMsgCommandError.Create('Already friend :)'));
2.290 - // either way, we exit
2.291 - exit;
2.292 - end;
2.293 - finally
2.294 - person.free;
2.295 - end;
2.296 -
2.297 - if gidRegex.results[2] <> SSLBrundle.OurGid then
2.298 - begin
2.299 - person := TPerson.create(gidRegex.results[2], gidRegex.results[1], sFriend);
2.300 - person.lastAddr := addr;
2.301 - person.lastPort := port;
2.302 - person.save();
2.303 - NotifyPeerInfo(person);
2.304 -
2.305 - if m.trusted then
2.306 - TTrustPlugin(PluginManager.getPlugin(TTrustPlugin)).SetTrusted(person.gid, true);
2.307 - //Notifier.postToController(TMsgCommandPeerAddReplaceMe.Create(person.nickname,
2.308 - //person.gid, StatusStr[person.status], PluginManager.PeerList.containsGid(person.gid),
2.309 - //person.sharedBytes, person.sharedFiles));
2.310 - end
2.311 - else
2.312 - begin
2.313 - Notifier.postToController(TMsgCommandError.Create('Cannot add yourself!'));
2.314 - exit;
2.315 - end;
2.316 -
2.317 - if not PluginManager.PeerList.containsGid(gidRegex.results[2]) then
2.318 - // it could be already connected if i.e. we are adding someone connected as a group friend
2.319 - begin
2.320 - if addr <> '' then
2.321 - begin
2.322 - // if we have address, connect immediately
2.323 - Core.startConnectTo(addr, port);
2.324 - checking.put(gidRegex.results[2], dtos(now));
2.325 - end
2.326 - else
2.327 - begin
2.328 - // if we don't, start an address search
2.329 - log(llInfo, 'Starting address search for ' + m.fullid);
2.330 - TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(person.gid);
2.331 - end;
2.332 - end;
2.333 - end
2.334 - else
2.335 - begin
2.336 - Notifier.postToController(TMsgCommandError.Create('Invalid GID!'));
2.337 - exit;
2.338 - end;
2.339 -
2.340 -
2.341 -end;
2.342 -
2.343 -procedure TFriendPlugin.commandRemoveFriend(m:TMsgCommandRemoveFriend);
2.344 -var
2.345 - person: TPerson;
2.346 - p: TPeer;
2.347 -begin
2.348 - if m.gid <> SSLBrundle.ourGid then
2.349 - begin
2.350 - p := PluginManager.PeerList[m.gid];
2.351 - if p <> nil then p.socket.close;
2.352 - person := TPerson.load(m.gid);
2.353 - if person = nil then
2.354 - Notifier.postToController(TMsgCommandError.Create('Cannot remove: unknown gid'))
2.355 - else
2.356 - begin
2.357 - person.delete();
2.358 - Notifier.postToController(TMsgCommandPeerRemove.Create(m.gid));
2.359 - person.free;
2.360 - end;
2.361 - end
2.362 - else
2.363 - Notifier.postToController(TMsgCommandError.Create('Cannot remove yourself!'));
2.364 -end;
2.365 -
2.366 -procedure TFriendPlugin.commandConnectToPeer(m:TMsgCommandConnectToPeer);
2.367 -var person: TPerson;
2.368 - addr:string;
2.369 -begin
2.370 - if m.gid <> SSLBrundle.ourGid then
2.371 - begin
2.372 - if PluginManager.PeerList.containsGid(m.gid) then
2.373 - begin
2.374 - Notifier.postToController(TMsgCommandError.Create('Already connected'));
2.375 - exit;
2.376 - end;
2.377 - person := TPerson.load(m.gid);
2.378 - if person = nil then
2.379 - Notifier.postToController(TMsgCommandError.Create('Cannot connect: unknown gid'))
2.380 - else
2.381 - try
2.382 - if person.dynhost<>'' then addr := person.dynhost else addr := person.lastAddr;
2.383 - if (Addr = '') or (person.lastPort = 0) then
2.384 - TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(person.gid)
2.385 - else
2.386 - begin
2.387 - Database.executeUpdate('update people set lastConnAttempt = ? where gid = ?', [dtos(now), person.gid]);
2.388 - Core.startConnectTo(Addr, person.lastPort);
2.389 - checking.put(m.gid, dtos(now));
2.390 - end;
2.391 - finally
2.392 - person.free;
2.393 - end;
2.394 - end
2.395 - else
2.396 - Notifier.postToController(TMsgCommandError.Create('Cannot connect yourself!'));
2.397 -end;
2.398 -
2.399 -procedure TFriendPlugin.commandBan(m:TMsgCommandBan);
2.400 -var
2.401 - person: TPerson;
2.402 - p: TPeer;
2.403 -begin
2.404 - if m.gid <> SSLBrundle.ourGid then
2.405 - begin
2.406 - p := PluginManager.PeerList[m.gid];
2.407 - if p <> nil then p.socket.close;
2.408 - person := TPerson.load(m.gid);
2.409 - if person = nil then
2.410 - Notifier.postToController(TMsgCommandError.Create('Cannot ban: unknown gid'))
2.411 - else
2.412 - try
2.413 - person.status := sBanned;
2.414 - person.save();
2.415 - NotifyPeerInfo(person);
2.416 - //Notifier.postToController(TMsgCommandPeerAddReplaceMe.create(person.nickname, person.gid, StatusStr[person.status], false, person.sharedBytes, person.sharedFiles));
2.417 - finally
2.418 - person.free;
2.419 - end;
2.420 - end
2.421 - else
2.422 - Notifier.postToController(TMsgCommandError.Create('Cannot ban yourself!'));
2.423 -end;
2.424 -
2.425 -procedure TFriendPlugin.everyFiveSeconds;
2.426 -var
2.427 - i: integer;
2.428 - gid: string;
2.429 - p: TPeer;
2.430 -begin
2.431 - if checking.count = 0 then exit;
2.432 - gid := checking.key(0);
2.433 - p := PluginManager.PeerList[gid];
2.434 - if p = nil then
2.435 - begin
2.436 - if stod(checking[gid]) + (OneSecond*15) < now then
2.437 - begin
2.438 - log(llInfo, 'Peer not directly connected after a while, trying with peerfinder ' + gid);
2.439 - TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(gid);
2.440 - checking.remove(gid);
2.441 - end;
2.442 - end
2.443 - else
2.444 - // peer connected by some other way, no more checking
2.445 - checking.remove(gid);
2.446 -end;
2.447 -
2.448 -procedure TFriendPlugin.everyMinute;
2.449 -var
2.450 - i, days: integer;
2.451 - gid: string;
2.452 - p, a: string;
2.453 - lastAttempt, lastSeen:Tdatetime;
2.454 - rs:TResultSet;
2.455 -begin
2.456 - if PluginManager.maxPeersConnected then exit;
2.457 -
2.458 - rs := Database.executeQuery('select lastAddr, lastPort, gid, dynhost, lastConnAttempt, lastSeen from people where lastPort <> 0 and status in (''FRIEND'',''TRUSTED'')');
2.459 - try
2.460 - while rs.next do
2.461 - begin
2.462 - gid := rs[2];
2.463 - if not PluginManager.PeerList.containsGid(gid) then
2.464 - begin
2.465 - a := rs[3];
2.466 - if a='' then a:=rs[0];
2.467 - p := rs[1];
2.468 - lastAttempt:=stod(rs[4]);
2.469 -
2.470 - lastSeen := stod(rs[5]);
2.471 - days := round((now - lastSeen) / (OneHour*24)); // oneHour * 24 should be 1
2.472 -
2.473 - // connect every 4 minutes, plus something random, plug one minute for each day we didn't see him
2.474 - // to avoid connecting many times to friends that are not coming online anymore
2.475 - if (lastAttempt + OneMinute*(4+days+random(4))) < now then
2.476 - if (a <> '') and (p <> '') then
2.477 - begin
2.478 - Database.executeUpdate('update people set lastConnAttempt = ? where gid = ?', [dtos(now), gid]);
2.479 - Core.startConnectTo(a, strtoint(p));
2.480 - checking.put(gid, dtos(now));
2.481 - end;
2.482 - end;
2.483 - end;
2.484 - finally
2.485 - rs.free;
2.486 - end;
2.487 - (*
2.488 - if checking.count = 0 then exit; zxcv
2.489 - gid := checking.key(0);
2.490 - p := PluginManager.PeerList[gid];
2.491 - if p = nil then
2.492 - begin
2.493 - if stod(checking[gid]) + (OneSecond*15) < now then
2.494 - begin
2.495 - log(llInfo, 'Peer not directly connected after a while, trying with peerfinder ' + gid);
2.496 - TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(gid);
2.497 - checking.remove(gid);
2.498 - end;
2.499 - end
2.500 - else
2.501 - // peer connected by some other way, no more checking
2.502 - checking.remove(gid);
2.503 - *)
2.504 -end;
2.505 -
2.506 -procedure TFriendPlugin.commandCloseNode(m:TMsgCommandCloseNode);
2.507 -var i: integer;
2.508 -begin
2.509 - log(llInfo, 'Closing all connections');
2.510 - for i:=0 to PluginManager.PeerList.count-1 do
2.511 - PluginManager.PeerList.get(i).Socket.close;
2.512 -end;
2.513 -
2.514 -
2.515 -end.
2.516 +unit friendpluginunit;
2.517 +{$H+}
2.518 +
2.519 +interface
2.520 +uses Classes, SysUtils, pluginunit, peerunit, messagesunit, logunit,
2.521 + directoryscannerunit, controllercommandsunit, propertiesunit, personunit,
2.522 + statusunit, socketunit, stringdictionaryunit, databaseunit, nodedatabaseunit,
2.523 + validatorsunit, newnodeserverunit, stringutilunit, dateutils, dateunit;
2.524 +
2.525 +type
2.526 +TFriendPlugin = class(TPlugin)
2.527 + private
2.528 + checking: TStringDictionary; // these are peers we are connecting directly.
2.529 + // After a while, if connection failed, we use the peerfinder to try again.
2.530 + procedure commandAddFriend(m:TMsgCommandAddFriend);
2.531 + procedure commandBan(m:TMsgCommandBan);
2.532 + procedure commandRemoveFriend(m:TMsgCommandRemoveFriend);
2.533 + procedure commandConnectToPeer(m:TMsgCommandConnectToPeer);
2.534 + procedure commandConnectToAddress(m:TMsgCommandConnectToAddress);
2.535 + procedure commandCloseNode(m:TMsgCommandCloseNode);
2.536 + procedure commandHello;
2.537 + procedure everyFiveSeconds;
2.538 + procedure everyMinute;
2.539 + procedure readHello(m:TMsgHelloFirst);
2.540 + procedure readMetaSharedFoldersRefreshed(m:TMsgMetaSharedFoldersRefreshed);
2.541 + procedure readSharedInfo(m:TMsgSharedInfo);
2.542 + protected
2.543 + function getName: string; override;
2.544 + public
2.545 + procedure Initialize; override;
2.546 + procedure Finalize; override;
2.547 + procedure OnMessage(m:TMessage); override;
2.548 +end;
2.549 +
2.550 +procedure NotifyPeerInfo(pe:TPerson);
2.551 +
2.552 +
2.553 +implementation
2.554 +uses peerfinderpluginunit, trustpluginunit, objectsunit;
2.555 +
2.556 +
2.557 +procedure NotifyPeerInfo(pe:TPerson);
2.558 +var s:string;
2.559 + rs:TResultSet;
2.560 +begin
2.561 + s:='';
2.562 + rs:=Database.executeQuery('select groupName from peopleGroups where gid = ?', [pe.gid]);
2.563 + try
2.564 + while rs.next do
2.565 + begin
2.566 + if s<>'' then s:=s+', ';
2.567 + s:=s+rs[0];
2.568 + end;
2.569 + finally
2.570 + rs.Free;
2.571 + end;
2.572 + Notifier.postToController(TMsgCommandPeerAdd.Create(pe.nickname, pe.gid,
2.573 + StatusStr[pe.status], PluginManager.PeerList.containsGid(pe.gid),
2.574 + pe.sharedbytes, pe.sharedfiles, pe.dynhost, pe.lastAddr, pe.lastPort, s));
2.575 +end;
2.576 +
2.577 +function TFriendPlugin.getName: string;
2.578 +begin
2.579 + result := 'Friend Plugin';
2.580 +end;
2.581 +
2.582 +procedure TFriendPlugin.Finalize;
2.583 +begin
2.584 + log(llInfo, 'Finalize');
2.585 + checking.free;
2.586 +end;
2.587 +
2.588 +procedure TFriendPlugin.Initialize;
2.589 +var
2.590 + rs: TResultSet;
2.591 + a, p, gid: string;
2.592 +begin
2.593 + log(llInfo, 'Initialize');
2.594 + registerMessageType(mtHelloFirst);
2.595 + registerMessageType(mtSharedInfo);
2.596 + registerMessageType(mtCommandAddFriend);
2.597 + registerMessageType(mtCommandHello);
2.598 + registerMessageType(mtCommandRemoveFriend);
2.599 + registerMessageType(mtCommandBan);
2.600 + registerMessageType(mtCommandConnectToAddress);
2.601 + registerMessageType(mtCommandConnectToPeer);
2.602 + registerMessageType(mtMetaFiveSeconds);
2.603 + registerMessageType(mtMetaOneMinute);
2.604 + registerMessageType(mtMetaSharedFoldersRefreshed);
2.605 + registerMessageType(mtCommandCloseNode);
2.606 + checking := TStringDictionary.create;
2.607 + rs := Database.executeQuery('select lastAddr, lastPort, gid, dynhost from people where status in (''FRIEND'',''TRUSTED'')');
2.608 + while rs.next do
2.609 + begin
2.610 + a := rs[3];
2.611 + gid := rs[2];
2.612 + if a='' then a:=rs[0];
2.613 + p := rs[1];
2.614 + if (a <> '') and (p <> '') then
2.615 + begin
2.616 + Database.executeUpdate('update people set lastConnAttempt = ? where gid = ?', [dtos(now), gid]);
2.617 + Core.startConnectTo(a, strtoint(p));
2.618 + checking.put(gid, dtos(now));
2.619 + end;
2.620 + end;
2.621 + rs.free;
2.622 +end;
2.623 +
2.624 +procedure TFriendPlugin.readMetaSharedFoldersRefreshed(m:TMsgMetaSharedFoldersRefreshed);
2.625 +var
2.626 + i64: int64;
2.627 + i: integer;
2.628 +begin
2.629 + ShareManager.getSharedInfo(i64, i);
2.630 + for i:=0 to PluginManager.PeerList.Count-1 do
2.631 + PluginManager.PeerList.get(i).enqueue(TMsgSharedInfo.Create(i64, i));
2.632 +end;
2.633 +
2.634 +procedure TFriendPlugin.readSharedInfo(m:TMsgSharedInfo);
2.635 +var person: TPerson;
2.636 +begin
2.637 + person := TPerson.load(m.peer.gid);
2.638 + try
2.639 + person.sharedBytes:=m.sharedbytes;
2.640 + person.sharedFiles:=m.sharedfiles;
2.641 + person.save();
2.642 + NotifyPeerInfo(person);
2.643 + //Notifier.postToController(TMsgCommandPeerAddReplaceMe.create(person.nickname,
2.644 + //person.gid, StatusStr[person.status], PluginManager.PeerList.containsGid(person.gid),
2.645 + //person.sharedBytes, person.sharedFiles));
2.646 + finally
2.647 + person.free;
2.648 + end;
2.649 +end;
2.650 +
2.651 +procedure TFriendPlugin.readHello(m:TMsgHelloFirst);
2.652 +var pe: TPerson;
2.653 +begin
2.654 + log(llInfo, 'Received Hello ');
2.655 + if m.majorVersion <> LAST_MAJOR_VERSION then
2.656 + begin
2.657 + log(llError, 'version not valid: ' + inttostr(m.majorVersion));
2.658 + if m.majorVersion > LAST_MAJOR_VERSION
2.659 + then Notifier.postToController(TMsgCommandNewVersion.Create());
2.660 + m.peer.Socket.close;
2.661 + exit;
2.662 + end;
2.663 +
2.664 + if m.minorVersion > LAST_MINOR_VERSION then
2.665 + Notifier.postToController(TMsgCommandNewVersion.Create());
2.666 +
2.667 + if not nicknameRegex.exec(m.nickname) then
2.668 + begin
2.669 + log(llError, 'Nickname not validated: ' + m.nickname + ' ' + m.peer.gid);
2.670 + m.peer.Socket.close;
2.671 + exit;
2.672 + end;
2.673 + pe := m.peer.Person;
2.674 +
2.675 + // handle dynamic host hint
2.676 +(*
2.677 + // TODO review this part
2.678 + if dynhost <> '' then
2.679 + if validateHost(dynhost, peer.socket.getAddress.sin_addr) then
2.680 + pe.addKarma(1, 'Valid dynamic host')
2.681 + else
2.682 + begin
2.683 + pe.addKarma(-5, 'Invalid dynamic host');
2.684 + dynhost := pe.dynhost; // keep current
2.685 + end;
2.686 +*)
2.687 + pe.nickname := m.nickname;
2.688 + pe.dynhost := m.nodeSuggestedHost;
2.689 + pe.lastAddr := InAddrToIp(m.peer.Address);
2.690 + pe.lastPort := m.nodePort;
2.691 + pe.lastSeen := now();
2.692 + pe.sharedFiles := m.sharedFiles;
2.693 + pe.sharedBytes := m.sharedbytes;
2.694 + pe.save();
2.695 + // send again with correct info
2.696 + NotifyPeerInfo(pe);
2.697 +end;
2.698 +
2.699 +procedure TFriendPlugin.commandHello;
2.700 +var
2.701 + rs: TResultSet;
2.702 + online: boolean;
2.703 + p: TPerson;
2.704 +begin
2.705 + // i also send the node info to the controller, as the controller could be just connected
2.706 + core.updateNodeInfo;
2.707 +
2.708 + // the controller connected, send the list of all friends
2.709 + rs := Database.executeQuery('select gid from people');
2.710 + try
2.711 + while rs.next do
2.712 + begin
2.713 + p:=TPerson.load(rs[0]);
2.714 + //online := PluginManager.PeerList.containsGid(p.gid);
2.715 + //Notifier.postToController(TMsgCommandPeerAddReplaceMe.Create(p.nickname,
2.716 + // p.gid, StatusStr[p.status], online, p.sharedBytes, p.sharedFiles));
2.717 + NotifyPeerInfo(p);
2.718 + p.free;
2.719 + end;
2.720 + finally
2.721 + rs.free;
2.722 + end;
2.723 +end;
2.724 +
2.725 +procedure TFriendPlugin.OnMessage(m:TMessage);
2.726 +begin
2.727 + case m.msgType of
2.728 + mtHelloFirst: readHello(TMsgHelloFirst(m));
2.729 + mtSharedInfo: readSharedInfo(TMsgSharedInfo(m));
2.730 + mtCommandAddFriend: commandAddFriend(TMsgCommandAddFriend(m));
2.731 + mtCommandRemoveFriend: commandRemoveFriend(TMsgCommandRemoveFriend(m));
2.732 + mtCommandHello: commandHello;
2.733 + mtCommandBan: commandBan(TMsgCommandBan(m));
2.734 + mtCommandConnectToAddress: commandConnectToAddress(TMsgCommandConnectToAddress(m));
2.735 + mtCommandConnectToPeer: commandConnectToPeer(TMsgCommandConnectToPeer(m));
2.736 + mtMetaFiveSeconds: everyFiveSeconds;
2.737 + mtMetaOneMinute: everyMinute;
2.738 + mtMetaSharedFoldersRefreshed: readMetaSharedFoldersRefreshed(TMsgMetaSharedFoldersRefreshed(m));
2.739 + mtCommandCloseNode: commandCloseNode(TMsgCommandCloseNode(m));
2.740 + end;
2.741 +(*
2.742 + if msg[0] = BAN then
2.743 + commandBan(msg[1]);
2.744 + if msg[0] = REMOVEFRIEND then
2.745 + commandRemoveFriend(msg[1]);
2.746 + if msg[0] = CONNECTTO then
2.747 + commandConnectTo(msg[1]);
2.748 + if msg[0] = CONNECTTOADDRESS then
2.749 + commandConnectToAddress(msg[1]);
2.750 + if msg[0] = HELLO then
2.751 + commandHello;
2.752 +*)
2.753 +end;
2.754 +
2.755 +procedure TFriendPlugin.commandConnectToAddress(m:TMsgCommandConnectToAddress);
2.756 +var
2.757 + addr: string;
2.758 + port: word;
2.759 +begin
2.760 + if (m.address <> '') and addrRegex.Exec(m.address) then
2.761 + begin
2.762 + addr := addrRegex.Results[1];
2.763 + port := strtoint(addrRegex.Results[2]);
2.764 + Core.startConnectTo(addr, port);
2.765 + exit;
2.766 + end;
2.767 + Notifier.postToController(TMsgCommandError.create('Invalid address. Format is: host:port'));
2.768 +end;
2.769 +
2.770 +procedure TFriendPlugin.commandAddFriend(m:TMsgCommandAddFriend);
2.771 +var
2.772 + person: TPerson;
2.773 + addr: string;
2.774 + port: word;
2.775 +begin
2.776 + log(llInfo, 'Adding friend: '+ m.fullid);
2.777 +
2.778 + if gidRegex.exec(m.fullid) then
2.779 + begin
2.780 + if gidRegex.Results.Count > 4 then
2.781 + begin
2.782 + addr := gidRegex.results[4];
2.783 + port := strtoint(gidRegex.results[5]);
2.784 + end
2.785 + else
2.786 + begin
2.787 + addr := '';
2.788 + port := 0;
2.789 + end;
2.790 +
2.791 +
2.792 + person := TPerson.Load(gidRegex.results[2]);
2.793 + if person <> nil then
2.794 + try
2.795 + if person.status in [sFriend, sTrusted] then
2.796 + begin
2.797 + // if he specified the address, we connect and say nothing, else we give a warning
2.798 + if addr <> '' then
2.799 + Core.startConnectTo(addr, port)
2.800 + else
2.801 + Notifier.postToController(TMsgCommandError.Create('Already friend :)'));
2.802 + // either way, we exit
2.803 + exit;
2.804 + end;
2.805 + finally
2.806 + person.free;
2.807 + end;
2.808 +
2.809 + if gidRegex.results[2] <> SSLBrundle.OurGid then
2.810 + begin
2.811 + person := TPerson.create(gidRegex.results[2], gidRegex.results[1], sFriend);
2.812 + person.lastAddr := addr;
2.813 + person.lastPort := port;
2.814 + person.save();
2.815 + NotifyPeerInfo(person);
2.816 +
2.817 + if m.trusted then
2.818 + TTrustPlugin(PluginManager.getPlugin(TTrustPlugin)).SetTrusted(person.gid, true);
2.819 + //Notifier.postToController(TMsgCommandPeerAddReplaceMe.Create(person.nickname,
2.820 + //person.gid, StatusStr[person.status], PluginManager.PeerList.containsGid(person.gid),
2.821 + //person.sharedBytes, person.sharedFiles));
2.822 + end
2.823 + else
2.824 + begin
2.825 + Notifier.postToController(TMsgCommandError.Create('Cannot add yourself!'));
2.826 + exit;
2.827 + end;
2.828 +
2.829 + if not PluginManager.PeerList.containsGid(gidRegex.results[2]) then
2.830 + // it could be already connected if i.e. we are adding someone connected as a group friend
2.831 + begin
2.832 + if addr <> '' then
2.833 + begin
2.834 + // if we have address, connect immediately
2.835 + Core.startConnectTo(addr, port);
2.836 + checking.put(gidRegex.results[2], dtos(now));
2.837 + end
2.838 + else
2.839 + begin
2.840 + // if we don't, start an address search
2.841 + log(llInfo, 'Starting address search for ' + m.fullid);
2.842 + TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(person.gid);
2.843 + end;
2.844 + end;
2.845 + end
2.846 + else
2.847 + begin
2.848 + Notifier.postToController(TMsgCommandError.Create('Invalid GID!'));
2.849 + exit;
2.850 + end;
2.851 +
2.852 +
2.853 +end;
2.854 +
2.855 +procedure TFriendPlugin.commandRemoveFriend(m:TMsgCommandRemoveFriend);
2.856 +var
2.857 + person: TPerson;
2.858 + p: TPeer;
2.859 +begin
2.860 + if m.gid <> SSLBrundle.ourGid then
2.861 + begin
2.862 + p := PluginManager.PeerList[m.gid];
2.863 + if p <> nil then p.socket.close;
2.864 + person := TPerson.load(m.gid);
2.865 + if person = nil then
2.866 + Notifier.postToController(TMsgCommandError.Create('Cannot remove: unknown gid'))
2.867 + else
2.868 + begin
2.869 + person.delete();
2.870 + Notifier.postToController(TMsgCommandPeerRemove.Create(m.gid));
2.871 + person.free;
2.872 + end;
2.873 + end
2.874 + else
2.875 + Notifier.postToController(TMsgCommandError.Create('Cannot remove yourself!'));
2.876 +end;
2.877 +
2.878 +procedure TFriendPlugin.commandConnectToPeer(m:TMsgCommandConnectToPeer);
2.879 +var person: TPerson;
2.880 + addr:string;
2.881 +begin
2.882 + if m.gid <> SSLBrundle.ourGid then
2.883 + begin
2.884 + if PluginManager.PeerList.containsGid(m.gid) then
2.885 + begin
2.886 + Notifier.postToController(TMsgCommandError.Create('Already connected'));
2.887 + exit;
2.888 + end;
2.889 + person := TPerson.load(m.gid);
2.890 + if person = nil then
2.891 + Notifier.postToController(TMsgCommandError.Create('Cannot connect: unknown gid'))
2.892 + else
2.893 + try
2.894 + if person.dynhost<>'' then addr := person.dynhost else addr := person.lastAddr;
2.895 + if (Addr = '') or (person.lastPort = 0) then
2.896 + TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(person.gid)
2.897 + else
2.898 + begin
2.899 + Database.executeUpdate('update people set lastConnAttempt = ? where gid = ?', [dtos(now), person.gid]);
2.900 + Core.startConnectTo(Addr, person.lastPort);
2.901 + checking.put(m.gid, dtos(now));
2.902 + end;
2.903 + finally
2.904 + person.free;
2.905 + end;
2.906 + end
2.907 + else
2.908 + Notifier.postToController(TMsgCommandError.Create('Cannot connect yourself!'));
2.909 +end;
2.910 +
2.911 +procedure TFriendPlugin.commandBan(m:TMsgCommandBan);
2.912 +var
2.913 + person: TPerson;
2.914 + p: TPeer;
2.915 +begin
2.916 + if m.gid <> SSLBrundle.ourGid then
2.917 + begin
2.918 + p := PluginManager.PeerList[m.gid];
2.919 + if p <> nil then p.socket.close;
2.920 + person := TPerson.load(m.gid);
2.921 + if person = nil then
2.922 + Notifier.postToController(TMsgCommandError.Create('Cannot ban: unknown gid'))
2.923 + else
2.924 + try
2.925 + person.status := sBanned;
2.926 + person.save();
2.927 + NotifyPeerInfo(person);
2.928 + //Notifier.postToController(TMsgCommandPeerAddReplaceMe.create(person.nickname, person.gid, StatusStr[person.status], false, person.sharedBytes, person.sharedFiles));
2.929 + finally
2.930 + person.free;
2.931 + end;
2.932 + end
2.933 + else
2.934 + Notifier.postToController(TMsgCommandError.Create('Cannot ban yourself!'));
2.935 +end;
2.936 +
2.937 +procedure TFriendPlugin.everyFiveSeconds;
2.938 +var
2.939 + i: integer;
2.940 + gid: string;
2.941 + p: TPeer;
2.942 +begin
2.943 + if checking.count = 0 then exit;
2.944 + gid := checking.key(0);
2.945 + p := PluginManager.PeerList[gid];
2.946 + if p = nil then
2.947 + begin
2.948 + if stod(checking[gid]) + (OneSecond*15) < now then
2.949 + begin
2.950 + log(llInfo, 'Peer not directly connected after a while, trying with peerfinder ' + gid);
2.951 + TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(gid);
2.952 + checking.remove(gid);
2.953 + end;
2.954 + end
2.955 + else
2.956 + // peer connected by some other way, no more checking
2.957 + checking.remove(gid);
2.958 +end;
2.959 +
2.960 +procedure TFriendPlugin.everyMinute;
2.961 +var
2.962 + i, days: integer;
2.963 + gid: string;
2.964 + p, a: string;
2.965 + lastAttempt, lastSeen:Tdatetime;
2.966 + rs:TResultSet;
2.967 + toUpdate:TStringList;
2.968 +begin
2.969 + if PluginManager.maxPeersConnected then exit;
2.970 + toUpdate:=TStringList.create;
2.971 + try
2.972 + rs := Database.executeQuery('select lastAddr, lastPort, gid, dynhost, lastConnAttempt, lastSeen from people where lastPort <> ''0'' and status in (''FRIEND'',''TRUSTED'')');
2.973 + try
2.974 + while rs.next do
2.975 + begin
2.976 + gid := rs[2];
2.977 + if not PluginManager.PeerList.containsGid(gid) then
2.978 + begin
2.979 + a := rs[3];
2.980 + if a='' then a:=rs[0];
2.981 + p := rs[1];
2.982 + lastAttempt:=stod(rs[4]);
2.983 +
2.984 + lastSeen := stod(rs[5]);
2.985 + days := round((now - lastSeen) / (OneHour*24)); // oneHour * 24 should be 1
2.986 +
2.987 + // connect every 4 minutes, plus something random, plus one minute for each day we didn't see him
2.988 + // to avoid connecting many times to friends that are not coming online anymore
2.989 + if (lastAttempt + OneMinute*(4+days+random(4))) < now then
2.990 + if (a <> '') and (p <> '') then
2.991 + begin
2.992 + log(llInfo, 'Connection attempt to '+gid+' at '+a+':'+p+' (last was '+DateTimeToStr(lastAttempt)+')');
2.993 + toUpdate.add(gid);
2.994 + Core.startConnectTo(a, strtoint(p));
2.995 + checking.put(gid, dtos(now));
2.996 + end;
2.997 + end;
2.998 + end;
2.999 + finally
2.1000 + rs.free;
2.1001 + end;
2.1002 + // update the lastConnAttempt on DB
2.1003 + for i:=0 to toUpdate.count-1 do
2.1004 + Database.executeUpdate('update people set lastConnAttempt = ? where gid = ?', [dtos(now), toUpdate[i]]);
2.1005 + finally
2.1006 + toUpdate.free;
2.1007 + end;
2.1008 + (*
2.1009 + if checking.count = 0 then exit; zxcv
2.1010 + gid := checking.key(0);
2.1011 + p := PluginManager.PeerList[gid];
2.1012 + if p = nil then
2.1013 + begin
2.1014 + if stod(checking[gid]) + (OneSecond*15) < now then
2.1015 + begin
2.1016 + log(llInfo, 'Peer not directly connected after a while, trying with peerfinder ' + gid);
2.1017 + TPeerFinderPlugin(PluginManager.getPlugin(TPeerFinderPlugin)).startSearchOfAddressAll(gid);
2.1018 + checking.remove(gid);
2.1019 + end;
2.1020 + end
2.1021 + else
2.1022 + // peer connected by some other way, no more checking
2.1023 + checking.remove(gid);
2.1024 + *)
2.1025 +end;
2.1026 +
2.1027 +procedure TFriendPlugin.commandCloseNode(m:TMsgCommandCloseNode);
2.1028 +var i: integer;
2.1029 +begin
2.1030 + log(llInfo, 'Closing all connections');
2.1031 + for i:=0 to PluginManager.PeerList.count-1 do
2.1032 + PluginManager.PeerList.get(i).Socket.close;
2.1033 +end;
2.1034 +
2.1035 +
2.1036 +end.