Browse Source

protections on net protocol

Prevent double calls with a critical object and minimize limits
PascalCoin 6 years ago
parent
commit
f3d45d56ca
1 changed files with 20 additions and 13 deletions
  1. 20 13
      src/core/UNetProtocol.pas

+ 20 - 13
src/core/UNetProtocol.pas

@@ -264,7 +264,7 @@ Type
     FOnProcessReservedAreaMessage: TProcessReservedAreaMessage;
     FOnProcessReservedAreaMessage: TProcessReservedAreaMessage;
     FRegisteredRequests : TPCThreadList;
     FRegisteredRequests : TPCThreadList;
     FIsDiscoveringServers : Boolean;
     FIsDiscoveringServers : Boolean;
-    FIsGettingNewBlockChainFromClient : Boolean;
+    FLockGettingNewBlockChainFromClient : TPCCriticalSection;
     FNewBlockChainFromClientStatus : String;
     FNewBlockChainFromClientStatus : String;
     FOnConnectivityChanged : TNotifyManyEvent;
     FOnConnectivityChanged : TNotifyManyEvent;
     FOnNetConnectionsUpdated: TNotifyEvent;
     FOnNetConnectionsUpdated: TNotifyEvent;
@@ -1173,7 +1173,7 @@ begin
   FNodeServersAddresses := TOrderedServerAddressListTS.Create(Self);
   FNodeServersAddresses := TOrderedServerAddressListTS.Create(Self);
   FLastRequestId := 0;
   FLastRequestId := 0;
   FNetConnections := TPCThreadList.Create('TNetData_NetConnections');
   FNetConnections := TPCThreadList.Create('TNetData_NetConnections');
-  FIsGettingNewBlockChainFromClient := false;
+  FLockGettingNewBlockChainFromClient := TPCCriticalSection.Create('LockGettingNewBlockChainFromClient');
   FNewBlockChainFromClientStatus := '';
   FNewBlockChainFromClientStatus := '';
   FNodePrivateKey := TECPrivateKey.Create;
   FNodePrivateKey := TECPrivateKey.Create;
   FNodePrivateKey.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
   FNodePrivateKey.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
@@ -1248,6 +1248,7 @@ begin
   FreeAndNil(FRegisteredRequests);
   FreeAndNil(FRegisteredRequests);
   FreeAndNil(FNetworkAdjustedTime);
   FreeAndNil(FNetworkAdjustedTime);
   FreeAndNil(FIpInfos);
   FreeAndNil(FIpInfos);
+  FreeAndNil(FLockGettingNewBlockChainFromClient);
   inherited;
   inherited;
   if (_NetData=Self) then _NetData := Nil;
   if (_NetData=Self) then _NetData := Nil;
   TLog.NewLog(ltInfo,ClassName,'TNetData.Destroy END');
   TLog.NewLog(ltInfo,ClassName,'TNetData.Destroy END');
@@ -1921,12 +1922,12 @@ begin
 
 
   if (Not Assigned(TNode.Node.Bank.StorageClass)) then Exit;
   if (Not Assigned(TNode.Node.Bank.StorageClass)) then Exit;
   //
   //
-  If FIsGettingNewBlockChainFromClient then begin
+  if Not FLockGettingNewBlockChainFromClient.TryEnter then begin
     TLog.NewLog(ltdebug,CT_LogSender,'Is getting new blockchain from client...');
     TLog.NewLog(ltdebug,CT_LogSender,'Is getting new blockchain from client...');
     exit;
     exit;
-  end else TLog.NewLog(ltdebug,CT_LogSender,'Starting receiving: '+why);
+  end;
   Try
   Try
-    FIsGettingNewBlockChainFromClient := true;
+    TLog.NewLog(ltdebug,CT_LogSender,'Starting receiving: '+why);
     FNewBlockChainFromClientStatus := Format('Downloading block %d from %s',[Connection.RemoteOperationBlock.block,Connection.ClientRemoteAddr]);
     FNewBlockChainFromClientStatus := Format('Downloading block %d from %s',[Connection.RemoteOperationBlock.block,Connection.ClientRemoteAddr]);
     FMaxRemoteOperationBlock := Connection.FRemoteOperationBlock;
     FMaxRemoteOperationBlock := Connection.FRemoteOperationBlock;
     if TNode.Node.Bank.BlocksCount=0 then begin
     if TNode.Node.Bank.BlocksCount=0 then begin
@@ -1980,7 +1981,7 @@ begin
     end;
     end;
   Finally
   Finally
     TLog.NewLog(ltdebug,CT_LogSender,'Finalizing');
     TLog.NewLog(ltdebug,CT_LogSender,'Finalizing');
-    FIsGettingNewBlockChainFromClient := false;
+    FLockGettingNewBlockChainFromClient.Release;
   end;
   end;
 end;
 end;
 
 
@@ -2020,9 +2021,17 @@ end;
 
 
 function TNetData.IsGettingNewBlockChainFromClient(var status: AnsiString): Boolean;
 function TNetData.IsGettingNewBlockChainFromClient(var status: AnsiString): Boolean;
 begin
 begin
-  Result := FIsGettingNewBlockChainFromClient;
-  if (Result) then  status := FNewBlockChainFromClientStatus
-  else status := '';
+  if FLockGettingNewBlockChainFromClient.TryEnter then begin
+    try
+      Result := False;
+      status := '';
+    finally
+      FLockGettingNewBlockChainFromClient.Release;
+    end;
+  end else begin
+    status := FNewBlockChainFromClientStatus;
+    Result := True;
+  end;
 end;
 end;
 
 
 procedure TNetData.SetMaxNodeServersAddressesBuffer(AValue: Integer);
 procedure TNetData.SetMaxNodeServersAddressesBuffer(AValue: Integer);
@@ -3738,14 +3747,12 @@ begin
                     end else TLog.NewLog(ltdebug,Classname,'Received old response of: '+TNetData.HeaderDataToText(HeaderData));
                     end else TLog.NewLog(ltdebug,Classname,'Received old response of: '+TNetData.HeaderDataToText(HeaderData));
                   End;
                   End;
                   CT_NetOp_AddOperations : Begin
                   CT_NetOp_AddOperations : Begin
-                    if TNetData.NetData.IpInfos.ReachesLimits(Client.RemoteHost,CT_NetTransferType[HeaderData.header_type],TNetData.OperationToText(HeaderData.operation),HeaderData.buffer_data_length,
-                      TArray<TLimitLifetime>.Create(TLimitLifetime.Create(20,20,0))) then DisconnectInvalidClient(False,Format('Reached limit %s',[TNetData.OperationToText(HeaderData.operation)]))
-                    else DoProcess_AddOperations(HeaderData,ReceiveDataBuffer);
+                    DoProcess_AddOperations(HeaderData,ReceiveDataBuffer);
                   End;
                   End;
                   CT_NetOp_GetSafeBox : Begin
                   CT_NetOp_GetSafeBox : Begin
                     if HeaderData.header_type=ntp_request then begin
                     if HeaderData.header_type=ntp_request then begin
                       if TNetData.NetData.IpInfos.ReachesLimits(Client.RemoteHost,CT_NetTransferType[HeaderData.header_type],TNetData.OperationToText(HeaderData.operation),HeaderData.buffer_data_length,
                       if TNetData.NetData.IpInfos.ReachesLimits(Client.RemoteHost,CT_NetTransferType[HeaderData.header_type],TNetData.OperationToText(HeaderData.operation),HeaderData.buffer_data_length,
-                        TArray<TLimitLifetime>.Create(TLimitLifetime.Create(3600,100,0))) then DisconnectInvalidClient(False,Format('Reached limit %s',[TNetData.OperationToText(HeaderData.operation)]))
+                        TArray<TLimitLifetime>.Create(TLimitLifetime.Create(3600,100,0),TLimitLifetime.Create(30,30,0))) then DisconnectInvalidClient(False,Format('Reached limit %s',[TNetData.OperationToText(HeaderData.operation)]))
                       else DoProcess_GetSafeBox_Request(HeaderData,ReceiveDataBuffer)
                       else DoProcess_GetSafeBox_Request(HeaderData,ReceiveDataBuffer)
                     end else DisconnectInvalidClient(false,'Received '+TNetData.HeaderDataToText(HeaderData));
                     end else DisconnectInvalidClient(false,'Received '+TNetData.HeaderDataToText(HeaderData));
                   end;
                   end;