SourceForge: gazzera/gazzera: changeset 73:10fe8d9bf6f6
minor work
authorMsx <msx80@users.sourceforge.net>
Fri Oct 16 19:34:00 2009 +0200 (5 weeks ago)
changeset 7310fe8d9bf6f6
parent 72d6680cbcf304
child 746dcac058c123
minor work
src/gazzera.lpi
src/node/plugins/friendpluginunit.pas
     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.