Browse Source

Build 1.0.6

PascalCoin 9 years ago
parent
commit
d0530a4623

+ 0 - 1
PascalCoinWallet.dpr

@@ -14,7 +14,6 @@ uses
   UThread in 'Units\PascalCoin\UThread.pas',
   ULog in 'Units\PascalCoin\ULog.pas',
   UNode in 'Units\PascalCoin\UNode.pas',
-  UFileStorage in 'Units\PascalCoin\UFileStorage.pas',
   UECIES in 'Units\PascalCoin\UECIES.pas',
   UDBStorage in 'Units\PascalCoin\UDBStorage.pas',
   UFRMWallet in 'Units\Forms\UFRMWallet.pas' {FRMWallet},

BIN
PascalCoinWallet.res


+ 7 - 0
README.md

@@ -38,6 +38,13 @@ If you like it, consider a donation using BitCoin:
 
 History:
 
+Build 1.0.6.0 - 2016-10-04
+--------------------------
+- Memory leaks corrections
+- Introducing net protocol 2-3
+- Source code modified, next build will be compiled with Lazarus and FPC
+
+
 Build 1.0.5.0 - 2016-09-21
 --------------------------
 - Massive operations, selecting multiple accounts

+ 113 - 88
Units/Forms/UFRMWallet.dfm

@@ -2,8 +2,8 @@ object FRMWallet: TFRMWallet
   Left = 360
   Top = 328
   Caption = 'Pascal Coin Wallet, Miner & Explorer'
-  ClientHeight = 558
-  ClientWidth = 899
+  ClientHeight = 545
+  ClientWidth = 903
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Color = clWindowText
@@ -20,11 +20,12 @@ object FRMWallet: TFRMWallet
   object pnlTop: TPanel
     Left = 0
     Top = 0
-    Width = 899
+    Width = 903
     Height = 91
     Align = alTop
     BevelOuter = bvNone
     TabOrder = 0
+    ExplicitWidth = 899
     object Image1: TImage
       Left = 15
       Top = 15
@@ -352,8 +353,8 @@ object FRMWallet: TFRMWallet
   end
   object StatusBar: TStatusBar
     Left = 0
-    Top = 539
-    Width = 899
+    Top = 526
+    Width = 903
     Height = 19
     Panels = <
       item
@@ -369,26 +370,28 @@ object FRMWallet: TFRMWallet
         Text = 'Blocks'
         Width = 50
       end>
+    ExplicitTop = 539
+    ExplicitWidth = 899
   end
   object PageControl: TPageControl
     Left = 0
     Top = 91
-    Width = 899
-    Height = 448
+    Width = 903
+    Height = 435
     ActivePage = tsAccountsExplorer
     Align = alClient
     TabOrder = 2
     OnChange = PageControlChange
+    ExplicitWidth = 899
+    ExplicitHeight = 448
     object tsAccountsExplorer: TTabSheet
       Caption = 'Accounts Explorer'
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       object Splitter1: TSplitter
         Left = 380
         Top = 66
-        Height = 354
+        Height = 341
         ExplicitLeft = 390
         ExplicitTop = 140
         ExplicitHeight = 100
@@ -396,10 +399,11 @@ object FRMWallet: TFRMWallet
       object pnlMyAccountsTop: TPanel
         Left = 0
         Top = 0
-        Width = 891
+        Width = 895
         Height = 66
         Align = alTop
         TabOrder = 0
+        ExplicitWidth = 891
         object Label18: TLabel
           Left = 11
           Top = 35
@@ -479,20 +483,22 @@ object FRMWallet: TFRMWallet
         Left = 0
         Top = 66
         Width = 380
-        Height = 354
+        Height = 341
         Align = alLeft
         BevelOuter = bvNone
         TabOrder = 1
+        ExplicitHeight = 354
         object dgAccounts: TDrawGrid
           Left = 0
           Top = 0
           Width = 380
-          Height = 320
+          Height = 307
           Align = alLeft
           TabOrder = 0
           OnClick = dgAccountsClick
           OnColumnMoved = dgAccountsColumnMoved
           OnFixedCellClick = dgAccountsFixedCellClick
+          ExplicitHeight = 320
           ColWidths = (
             64
             64
@@ -502,12 +508,13 @@ object FRMWallet: TFRMWallet
         end
         object pnlAccountsInfo: TPanel
           Left = 0
-          Top = 320
+          Top = 307
           Width = 380
           Height = 34
           Align = alBottom
           BevelOuter = bvNone
           TabOrder = 1
+          ExplicitTop = 320
           DesignSize = (
             380
             34)
@@ -583,25 +590,27 @@ object FRMWallet: TFRMWallet
       object pcAccountsOptions: TPageControl
         Left = 383
         Top = 66
-        Width = 508
-        Height = 354
+        Width = 512
+        Height = 341
         ActivePage = tsMultiSelectAccounts
         Align = alClient
         TabOrder = 2
+        ExplicitWidth = 508
+        ExplicitHeight = 354
         object tsAccountOperations: TTabSheet
           Caption = 'Operations of selected Account'
-          ExplicitLeft = 0
-          ExplicitTop = 0
-          ExplicitWidth = 0
-          ExplicitHeight = 0
+          ExplicitWidth = 500
+          ExplicitHeight = 326
           object dgAccountOperations: TDrawGrid
             Left = 0
             Top = 0
-            Width = 500
-            Height = 326
+            Width = 504
+            Height = 313
             Align = alClient
             TabOrder = 0
             OnDblClick = MiDecodePayloadClick
+            ExplicitWidth = 500
+            ExplicitHeight = 326
             RowHeights = (
               24
               24
@@ -613,22 +622,27 @@ object FRMWallet: TFRMWallet
         object tsMultiSelectAccounts: TTabSheet
           Caption = 'Selected accounts for massive operations'
           ImageIndex = 1
-          ExplicitLeft = 0
-          ExplicitTop = 0
-          ExplicitWidth = 0
-          ExplicitHeight = 0
+          ExplicitWidth = 500
+          ExplicitHeight = 326
           object dgSelectedAccounts: TDrawGrid
             Left = 41
             Top = 31
             Width = 320
-            Height = 269
+            Height = 256
             Align = alLeft
             TabOrder = 0
+            ExplicitHeight = 269
+            RowHeights = (
+              24
+              24
+              24
+              24
+              24)
           end
           object pnlSelectedAccountsTop: TPanel
             Left = 0
             Top = 0
-            Width = 500
+            Width = 504
             Height = 31
             Align = alTop
             BevelOuter = bvNone
@@ -639,6 +653,7 @@ object FRMWallet: TFRMWallet
             Font.Style = [fsBold]
             ParentFont = False
             TabOrder = 1
+            ExplicitWidth = 500
             object Label15: TLabel
               Left = 41
               Top = 4
@@ -649,12 +664,14 @@ object FRMWallet: TFRMWallet
           end
           object pnlSelectedAccountsBottom: TPanel
             Left = 0
-            Top = 300
-            Width = 500
+            Top = 287
+            Width = 504
             Height = 26
             Align = alBottom
             BevelOuter = bvNone
             TabOrder = 2
+            ExplicitTop = 300
+            ExplicitWidth = 500
             object Label20: TLabel
               Left = 41
               Top = 6
@@ -688,10 +705,11 @@ object FRMWallet: TFRMWallet
             Left = 0
             Top = 31
             Width = 41
-            Height = 269
+            Height = 256
             Align = alLeft
             BevelOuter = bvNone
             TabOrder = 3
+            ExplicitHeight = 269
             object sbSelectedAccountsAdd: TSpeedButton
               Left = 2
               Top = 0
@@ -800,15 +818,13 @@ object FRMWallet: TFRMWallet
     object tsPendingOperations: TTabSheet
       Caption = 'Pending Operations'
       ImageIndex = 5
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       object dgPendingOperations: TDrawGrid
         Left = 0
         Top = 86
-        Width = 891
-        Height = 334
+        Width = 895
+        Height = 321
         Align = alClient
         TabOrder = 0
         OnDblClick = MiDecodePayloadClick
@@ -816,16 +832,17 @@ object FRMWallet: TFRMWallet
       object pnlPendingOperations: TPanel
         Left = 0
         Top = 0
-        Width = 891
+        Width = 895
         Height = 86
         Align = alTop
         BevelOuter = bvNone
         BorderWidth = 10
         TabOrder = 1
+        ExplicitWidth = 891
         object Label10: TLabel
           Left = 10
           Top = 10
-          Width = 871
+          Width = 875
           Height = 66
           Align = alClient
           AutoSize = False
@@ -851,17 +868,16 @@ object FRMWallet: TFRMWallet
     object tsBlockChain: TTabSheet
       Caption = 'BlockChain Explorer'
       ImageIndex = 1
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       object Panel2: TPanel
         Left = 0
         Top = 0
-        Width = 891
+        Width = 895
         Height = 41
         Align = alTop
         TabOrder = 0
+        ExplicitWidth = 891
         object Label9: TLabel
           Left = 306
           Top = 10
@@ -922,8 +938,8 @@ object FRMWallet: TFRMWallet
       object dbGridBlockChain: TDBGrid
         Left = 0
         Top = 41
-        Width = 891
-        Height = 379
+        Width = 895
+        Height = 366
         Align = alClient
         Options = [dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit, dgTitleClick, dgTitleHotTrack]
         ReadOnly = True
@@ -938,17 +954,16 @@ object FRMWallet: TFRMWallet
     object tsOperations: TTabSheet
       Caption = 'Operations Explorer'
       ImageIndex = 1
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       object Panel1: TPanel
         Left = 0
         Top = 0
-        Width = 891
+        Width = 895
         Height = 41
         Align = alTop
         TabOrder = 0
+        ExplicitWidth = 891
         object Label1: TLabel
           Left = 11
           Top = 10
@@ -1025,8 +1040,8 @@ object FRMWallet: TFRMWallet
       object dbgridOperations: TDBGrid
         Left = 0
         Top = 41
-        Width = 891
-        Height = 379
+        Width = 895
+        Height = 366
         Align = alClient
         Options = [dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit, dgTitleClick, dgTitleHotTrack]
         ReadOnly = True
@@ -1042,17 +1057,16 @@ object FRMWallet: TFRMWallet
     object tsLogs: TTabSheet
       Caption = 'Logs'
       ImageIndex = 2
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       object pnlTopLogs: TPanel
         Left = 0
         Top = 0
-        Width = 891
+        Width = 895
         Height = 41
         Align = alTop
         TabOrder = 0
+        ExplicitWidth = 891
         object cbShowDebugLogs: TCheckBox
           Left = 15
           Top = 10
@@ -1065,23 +1079,23 @@ object FRMWallet: TFRMWallet
       object memoLogs: TMemo
         Left = 0
         Top = 41
-        Width = 891
-        Height = 379
+        Width = 895
+        Height = 366
         Align = alClient
         ScrollBars = ssBoth
         TabOrder = 1
+        ExplicitWidth = 891
+        ExplicitHeight = 379
       end
     end
     object tsNodeStats: TTabSheet
       Caption = 'Node Stats'
       ImageIndex = 3
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       DesignSize = (
-        891
-        420)
+        895
+        407)
       object Label3: TLabel
         Left = 15
         Top = 15
@@ -1091,58 +1105,67 @@ object FRMWallet: TFRMWallet
       end
       object Label6: TLabel
         Left = 15
-        Top = 236
+        Top = 253
         Width = 169
         Height = 13
+        Anchors = [akLeft, akBottom]
         Caption = 'Available or possible Node Servers:'
+        ExplicitTop = 266
       end
       object Label7: TLabel
         Left = 15
-        Top = 132
+        Top = 149
         Width = 86
         Height = 13
+        Anchors = [akLeft, akBottom]
         Caption = 'BlackList of Nodes'
+        ExplicitTop = 162
       end
       object memoNetConnections: TMemo
         Left = 15
         Top = 34
-        Width = 860
-        Height = 92
+        Width = 864
+        Height = 109
+        Anchors = [akLeft, akTop, akRight, akBottom]
         ReadOnly = True
         ScrollBars = ssVertical
         TabOrder = 0
+        ExplicitWidth = 860
+        ExplicitHeight = 122
       end
       object memoNetServers: TMemo
         Left = 15
-        Top = 255
-        Width = 860
-        Height = 146
-        Anchors = [akLeft, akTop, akRight, akBottom]
+        Top = 272
+        Width = 864
+        Height = 116
+        Anchors = [akLeft, akRight, akBottom]
         ReadOnly = True
         ScrollBars = ssVertical
         TabOrder = 1
+        ExplicitTop = 300
+        ExplicitWidth = 859
       end
       object memoNetBlackLists: TMemo
         Left = 15
-        Top = 151
-        Width = 860
+        Top = 168
+        Width = 864
         Height = 79
-        Anchors = [akLeft, akTop, akRight]
+        Anchors = [akLeft, akRight, akBottom]
         ReadOnly = True
         ScrollBars = ssVertical
         TabOrder = 2
+        ExplicitTop = 196
+        ExplicitWidth = 859
       end
     end
     object tsMessages: TTabSheet
       Caption = 'Messages'
       ImageIndex = 6
-      ExplicitLeft = 0
-      ExplicitTop = 0
-      ExplicitWidth = 0
-      ExplicitHeight = 0
+      ExplicitWidth = 891
+      ExplicitHeight = 420
       DesignSize = (
-        891
-        420)
+        895
+        407)
       object Label11: TLabel
         Left = 15
         Top = 151
@@ -1200,8 +1223,8 @@ object FRMWallet: TFRMWallet
       object memoMessages: TMemo
         Left = 15
         Top = 170
-        Width = 860
-        Height = 231
+        Width = 864
+        Height = 218
         Anchors = [akLeft, akTop, akRight, akBottom]
         Font.Charset = DEFAULT_CHARSET
         Font.Color = clWindowText
@@ -1215,6 +1238,8 @@ object FRMWallet: TFRMWallet
         ReadOnly = True
         ScrollBars = ssBoth
         TabOrder = 2
+        ExplicitWidth = 860
+        ExplicitHeight = 231
       end
       object memoMessageToSend: TMemo
         Left = 315
@@ -1368,7 +1393,7 @@ object FRMWallet: TFRMWallet
     Left = 105
     Top = 180
     Bitmap = {
-      494C010102000800080110003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      494C010102000800240110003000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
       0000000000003600000028000000400000003000000001002000000000000030
       0000000000000000000000000000000000000000000000000000000000000000
       0000000000000000002A292929D60B0B0BF4111111EE0000006B000000000000

+ 14 - 11
Units/Forms/UFRMWallet.pas

@@ -838,8 +838,10 @@ begin
   ebFilterOperationsAccount.Text := '';
   PageControl.ActivePage := tsAccountsExplorer;
   pcAccountsOptions.ActivePage := tsAccountOperations;
-  dtpFilterOperationsDateStart.Date := Now;
-  dtpFilterOperationsDateEnd.Date := Now;
+  dtpFilterOperationsDateStart.Date := Trunc(Now);
+  dtpFilterOperationsDateEnd.Date := Trunc(Now);
+  dtpBlockChainDateStart.Date := Trunc(Now);
+  dtpBlockChainDateEnd.Date := Trunc(Now);
   ebFilterOperationsAccount.Text := '';
   ebFilterOperationsStartBlock.Text := '';
   ebFilterOperationsEndBlock.Text := '';
@@ -867,6 +869,7 @@ begin
   Try
   step := 'Saving params';
   SaveAppParams;
+  FreeAndNil(FAppParams);
   //
   step := 'Assigning nil events';
   FLog.OnNewLog :=Nil;
@@ -911,6 +914,7 @@ begin
   TNode.Node.NetServer.Active := false;
   FNode := Nil;
 
+  TNetData.NetData.Free;
 
   step := 'Processing messages 1';
   Application.ProcessMessages;
@@ -929,6 +933,8 @@ begin
     end;
   End;
   TLog.NewLog(ltinfo,Classname,'Destroying form - END');
+  FreeAndNil(FLog);
+  Sleep(100);
 end;
 
 function TFRMWallet.GetAccountKeyForMiner: TAccountKey;
@@ -1638,6 +1644,8 @@ Var isMining : boolean;
   f, favg : real;
 begin
   UpdateNodeStatus;
+  mc := 0;
+  hr := 0;
   if Assigned(FNode) then begin
     if FNode.Bank.BlocksCount>0 then begin
       lblCurrentBlock.Caption :=  Inttostr(FNode.Bank.BlocksCount)+' (0..'+Inttostr(FNode.Bank.BlocksCount-1)+')'; ;
@@ -1654,8 +1662,10 @@ begin
     end else begin
       lblTimeAverage.Font.Color := clOlive;
     end;
-    lblTimeAverageAux.Caption := Format('Last %d: %s sec. - Last %d: %s sec. - Last %d: %s sec.',[
+    lblTimeAverageAux.Caption := Format('Last %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec. - %d: %s sec.',[
         CT_CalcNewTargetBlocksAverage * 2 ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage * 2)),
+        ((CT_CalcNewTargetBlocksAverage * 3) DIV 2) ,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage((CT_CalcNewTargetBlocksAverage * 3) DIV 2)),
+        ((CT_CalcNewTargetBlocksAverage DIV 4)*3),FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(((CT_CalcNewTargetBlocksAverage DIV 4)*3))),
         CT_CalcNewTargetBlocksAverage DIV 2,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 2)),
         CT_CalcNewTargetBlocksAverage DIV 4,FormatFloat('0.0',FNode.Bank.GetActualTargetSecondsAverage(CT_CalcNewTargetBlocksAverage DIV 4))]);
     mtl := FNode.MinerThreads.LockList;
@@ -1663,7 +1673,6 @@ begin
       mc := mtl.Count;
       If mc>0 then begin
         isMining := Not TMinerThread(mtl[0]).Paused;
-        hr := 0;
         for i := 0 to mtl.Count - 1 do begin
           hr := hr + TMinerThread(mtl[i]).HashRate;
         end;
@@ -1728,13 +1737,7 @@ begin
 end;
 
 procedure TFRMWallet.UpdateConnectionStatus;
-Var
-  NS : TNetStatistics;
-  errors : AnsiString;
-
-Var i : integer;
- NC : TNetConnection;
- l : TList;
+var errors : AnsiString;
 begin
   UpdateNodeStatus;
   OnNetStatisticsChanged(Nil);

+ 14 - 1
Units/PascalCoin/UAccounts.pas

@@ -1,5 +1,9 @@
 unit UAccounts;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -16,7 +20,12 @@ unit UAccounts;
 interface
 
 uses
-  Classes, UConst, Windows, UCrypto, SyncObjs;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  Classes, UConst, UCrypto, SyncObjs;
 
 Type
   TAccountKey = TECDSA_Public;
@@ -1215,7 +1224,11 @@ begin
       // Add ordered
       P^.accounts.Add(TObject(accounts[i]));
     end;
+    {$IFDEF FPC}
+    P^.accounts.Sort(SortOrdered);
+    {$ELSE}
     P^.accounts.SortList(SortOrdered);
+    {$ENDIF}
   end;
 end;
 

+ 11 - 20
Units/PascalCoin/UBlockChain.pas

@@ -1,4 +1,8 @@
-unit UBlockChain;
+unit UBlockChain;
+
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
 
 { Copyright (c) 2016 by Albert Molina
 
@@ -16,7 +20,12 @@
 interface
 
 uses
-  Classes, UCrypto, UAccounts, Windows, ULog, UThread, SyncObjs;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  Classes, UCrypto, UAccounts, ULog, UThread, SyncObjs;
 
 
 Type
@@ -142,7 +151,6 @@ Type
     function SenderAccount : Cardinal; virtual; abstract;
     Property tag : integer read Ftag Write Ftag;
     Property AuxBalance : Int64 read FAuxBalance Write FAuxBalance;
-    Class Function IsReadablePayload(const Payload : TRawBytes) : Boolean;
   End;
 
   TOperationsHashTree = Class
@@ -778,11 +786,6 @@ begin
   SafeBox.SaveToStream(Stream);
 end;
 
-{procedure TPCBank.SaveToStream(Stream: TStream);
-begin
-  SafeBox.SaveToStream(Stream);
-end;
-}
 procedure TPCBank.SetStorageClass(const Value: TStorageClass);
 begin
   if FStorageClass=Value then exit;
@@ -1806,18 +1809,6 @@ end;
 
 { TPCOperation }
 
-class function TPCOperation.IsReadablePayload(const Payload: TRawBytes): Boolean;
-Var i : Integer;
-begin
-  Result := true;
-    for i := 1 to length(Payload) do begin
-      if (ord(Payload[i])<32) Or (ord(Payload[i])>=127) then begin
-        Result := false;
-        Exit;
-      end;
-    end;
-end;
-
 initialization
   SetLength(_OperationsClass, 0);
 finalization

+ 18 - 10
Units/PascalCoin/UConst.pas

@@ -1,5 +1,9 @@
 unit UConst;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -13,6 +17,8 @@ unit UConst;
 
   }
 
+{$DEFINE TESTNET}
+
 interface
 
 Uses ssl_const;
@@ -23,13 +29,13 @@ Const
     '(c) Albert Molina - Genesis block at same time than BitCoin Block 424720 Hash 000000000000000001cc41ff7846264718ef0a15f97f532a98277bd5f6820b89';
 
   CT_Zero_Block_Proof_of_work_in_Hexa =
-    {$IFDEF PRODUCTION}'00000003A29C32E84A539ADE24397D41D30116A6FAFEC17B7D9CED68A4238C92'{$ELSE}{$IFDEF TESTNET}''{$ENDIF}{$ENDIF};
+    '00000003A29C32E84A539ADE24397D41D30116A6FAFEC17B7D9CED68A4238C92';
 
 
-  CT_NetServer_Port = {$IFDEF PRODUCTION}4004{$ELSE}{$IFDEF TESTNET}4104{$ENDIF}{$ENDIF};
+  CT_NetServer_Port = 4004;
   CT_AccountsPerBlock = 5;
 
-  CT_NewLineSecondsAvg: Cardinal = {$IFDEF PRODUCTION}300{$ELSE}{$IFDEF TESTNET}30{$ENDIF}{$ENDIF};
+  CT_NewLineSecondsAvg: Cardinal = 300;
     // 60*5=300 seconds -> 5 minutes avg
     //   -> 1 day = 86400 seconds -> 1 year = 31536000 seconds (aprox)
     //   Each year = 105120 new blocks (aprox)
@@ -37,17 +43,17 @@ Const
 
   CT_FirstReward: UInt64 = 1000000; // 4 decimals... First reward = 100,0000
   CT_MinReward: UInt64 = 10000; // 4 decimals... Min reward = 1,0000
-  CT_NewLineRewardDecrease: Cardinal = {$IFDEF PRODUCTION}420480{$ELSE}{$IFDEF TESTNET}600{$ENDIF}{$ENDIF}; // Avg 4 year
+  CT_NewLineRewardDecrease: Cardinal = 420480; // Avg 4 year
 
   CT_WaitNewBlocksBeforeTransaction = 100;
 
-  CT_RecoverFoundsWaitInactiveCount = {$IFDEF PRODUCTION}420480{$ELSE}{$IFDEF TESTNET}500{$ENDIF}{$ENDIF};  // After 4 years... if an account has no operations, money will be a reward for a miner!
+  CT_RecoverFoundsWaitInactiveCount = 420480;  // After 4 years... if an account has no operations, money will be a reward for a miner!
 
   CT_MaxTransactionAmount = 1000000000000;
   CT_MaxTransactionFee = 100000000;
   CT_MaxWalletAmount = 10000000000000;
   //
-  CT_MinCompactTarget: Cardinal = {$IFDEF PRODUCTION}$19000000{$ELSE}{$IFDEF TESTNET}$16000000{$ENDIF}{$ENDIF}; // First compact target of block 0
+  CT_MinCompactTarget: Cardinal = $19000000; // First compact target of block 0
 
   CT_CalcNewTargetBlocksAverage: Cardinal = 100;
   CT_MaxBlock : Cardinal = $FFFFFFFF;
@@ -66,11 +72,13 @@ Const
   CT_BlockChain_Protocol_Version: Word = $0001; // Version 1
   CT_BlockChain_Protocol_Available: Word = $0000;
 
+  CT_MagicNetIdentification = $0A043580; // Unix timestamp 168048000 ... It's Albert birthdate!
+
   // Build 1.0.4 - introducing NetProtocol versioning:
-  CT_NetProtocol_Version: Word = $0001;
+  CT_NetProtocol_Version: Word = $0002;
   // IMPORTANT NOTE!!!
   // NetProtocol_Available MUST BE allways >= NetProtocol_version
-  CT_NetProtocol_Available: Word = $0002;  // Remember, >= NetProtocol_version !!!
+  CT_NetProtocol_Available: Word = $0003;  // Remember, >= NetProtocol_version !!!
 
   CT_MagicIdentificator: AnsiString = 'PascalCoin'; //
 
@@ -79,9 +87,9 @@ Const
   CT_Op_Changekey = $02;
   CT_Op_Recover = $03;
 
-  CT_ClientAppVersion : AnsiString = {$IFDEF PRODUCTION}'1.0.5'{$ELSE}{$IFDEF TESTNET}'TESTNET'{$ENDIF}{$ENDIF};
+  CT_ClientAppVersion : AnsiString = '1.0.6';
 
-  CT_Discover_IPs =  {$IFDEF PRODUCTION}'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin1.ddns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us'{$ELSE}{$IFDEF TESTNET}''{$ENDIF}{$ENDIF};
+  CT_Discover_IPs =  'bpascal1.dynamic-dns.net;bpascal2.dynamic-dns.net;pascalcoin1.ddns.net;pascalcoin2.ddns.net;pascalcoin1.dynamic-dns.net;pascalcoin1.dns1.us';
 
   CT_TRUE_FALSE : Array[Boolean] Of AnsiString = ('FALSE','TRUE');
 

+ 10 - 1
Units/PascalCoin/UCrypto.pas

@@ -1,5 +1,9 @@
 unit UCrypto;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -120,7 +124,12 @@ Const
 implementation
 
 uses
-  ULog, UConst, Windows, UAccounts;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  ULog, UConst, UAccounts;
 
 Var _initialized : Boolean = false;
 

+ 18 - 1
Units/PascalCoin/UECIES.pas

@@ -1,5 +1,9 @@
 unit UECIES;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -46,7 +50,12 @@ function ECIESDecrypt(EC_OpenSSL_NID : Word; PrivateKey: PEC_KEY; logErrors : Bo
 implementation
 
 uses
-  ssl_sha, Windows, SysUtils, ssl_bn;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages, Windows,
+{$ENDIF}
+  ssl_sha, SysUtils, ssl_bn;
 
 Type
   Psecure_t = Pointer;
@@ -234,7 +243,11 @@ begin
         exit;
       end;
       // For now we use an empty initialization vector.
+      {$IFDEF FPC}
+      FillByte(iv,EVP_MAX_IV_LENGTH,0);
+      {$ELSE}
       FillMemory(@iv,EVP_MAX_IV_LENGTH,0);
+      {$ENDIF}
       // Setup the cipher context, the body length, and store a pointer to the body buffer location.
       EVP_CIPHER_CTX_init(@cipher);
       try
@@ -259,7 +272,11 @@ begin
           end;
           // Copy the remaining data into our partial block buffer. The memset() call ensures any extra bytes will be zero'ed out.
           //SetLength(block,EVP_MAX_BLOCK_LENGTH);
+          {$IFDEF FPC}
+          FillByte(block,length(block),0);
+          {$ELSE}
           FillMemory(@block,length(block),0);
+          {$ENDIF}
           CopyMemory(@block,Pointer(Integer(@MessageToEncrypt[1])+body_length),Length(MessageToEncrypt)-body_length);
           // Advance the body pointer to the location of the remaining space, and calculate just how much room is still available.
           body := Pointer(integer(body)+body_length);

+ 10 - 1
Units/PascalCoin/UFileStorage.pas

@@ -1,5 +1,9 @@
 unit UFileStorage;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -16,7 +20,12 @@ unit UFileStorage;
 interface
 
 uses
-  Classes, UBlockChain, Windows, SyncObjs;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  Classes, UBlockChain, SyncObjs;
 
 Type
   TBlockHeader = Record

+ 5 - 0
Units/PascalCoin/ULog.pas

@@ -1,5 +1,9 @@
 unit ULog;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -207,4 +211,5 @@ end;
 initialization
   _logs := Nil;
 finalization
+  FreeAndNil(_logs);
 end.

+ 11 - 1
Units/PascalCoin/UMiner.pas

@@ -1,5 +1,9 @@
 unit UMiner;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -15,7 +19,13 @@ unit UMiner;
 
 interface
 
-Uses UBlockChain, Classes, SyncObjs, Windows, UAccounts, UThread;
+Uses
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  UBlockChain, Classes, SyncObjs, UAccounts, UThread;
 
 Type
   TMinerPrivateKey = (mpk_NewEachTime, mpk_Random, mpk_Selected);

+ 216 - 86
Units/PascalCoin/UNetProtocol.pas

@@ -1,5 +1,9 @@
 unit UNetProtocol;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -15,11 +19,18 @@ unit UNetProtocol;
 
 interface
 
-Uses UBlockChain, Classes, SysUtils, UAccounts, UThread, ExtCtrls,
-  UCrypto, UTCPIP, SyncObjs, Windows;
+Uses
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  UBlockChain, Classes, SysUtils, UAccounts, UThread, ExtCtrls,
+  UCrypto, UTCPIP, SyncObjs;
+
+{$DEFINE TESTNET}
 
 Const
-  CT_MagicNetIdentification = {$IFDEF PRODUCTION}$0A043580{$ELSE}{$IFDEF TESTNET}$8035040A{$ENDIF}{$ENDIF}; // Unix timestamp 168048000 ... It's Albert birthdate!
   CT_MagicRequest = $0001;
   CT_MagicResponse = $0002;
   CT_MagicAutoSend = $0003;
@@ -100,14 +111,6 @@ Type
     SendTime : TDateTime;
   end;
 
-  TThreadCheckConnections = Class(TPCThread)
-  private
-    FLastCheckTS : Cardinal;
-  protected
-    procedure BCExecute; override;
-  public
-  End;
-
   TNetStatistics = Record
     ActiveConnections : Integer; // All connections wiht "connected" state
     ClientsConnections : Integer; // All clients connected to me like a server with "connected" state
@@ -121,7 +124,7 @@ Type
   end;
 
   TNetData = Class;
-  
+
   { TNetDataNotifyEventsThread ensures that notifications of TNetData object
     will be in main Thread calling a Synchronized method }
   TNetDataNotifyEventsThread = Class(TPCThread)
@@ -136,7 +139,28 @@ Type
     procedure SynchronizedNotify;
     procedure BCExecute; override;
   public
-    Constructor Create(ANetData : TNetData);    
+    Constructor Create(ANetData : TNetData);
+  End;
+
+  TNetClientsDestroyThread = Class(TPCThread)
+  private
+    FNetData : TNetData;
+    FTerminatedAllConnections : Boolean;
+  protected
+    procedure BCExecute; override;
+  public
+    Constructor Create(NetData : TNetData);
+    Procedure WaitForTerminatedAllConnections;
+  End;
+
+  TThreadCheckConnections = Class(TPCThread)
+  private
+    FNetData : TNetData;
+    FLastCheckTS : Cardinal;
+  protected
+    procedure BCExecute; override;
+  public
+    Constructor Create(NetData : TNetData);
   End;
 
   TNetData = Class(TComponent)
@@ -159,6 +183,7 @@ Type
     FOnStatisticsChanged: TNotifyEvent;
     FMaxRemoteOperationBlock : TOperationBlock;
     FFixedServers : TNodeServerAddressArray;
+    FNetClientsDestroyThread : TNetClientsDestroyThread;
     Procedure IncStatistics(incActiveConnections,incClientsConnections,incServersConnections,incServersConnectionsWithResponse : Integer; incBytesReceived, incBytesSend : Int64);
   protected
     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
@@ -172,6 +197,7 @@ Type
     Class Function OperationToText(operation : Word) : AnsiString;
     // Only 1 NetData
     Class Function NetData : TNetData;
+    Class Function NetDataExists : Boolean;
     //
     Constructor Create(AOwner : TComponent); override;
     Destructor Destroy; override;
@@ -298,15 +324,6 @@ Type
     Destructor Destroy; override;
   End;
 
-  TNetClientDestroyThread = Class(TPCThread)
-  private
-    FNetClient : TNetClient;
-  protected
-    procedure BCExecute; override;
-  public
-    Constructor Create(NetClient : TNetClient);
-  End;
-
   TNetServerClient = Class(TNetConnection);
 
   TNetServer = Class(TNetTcpIpServer)
@@ -315,6 +332,7 @@ Type
     Procedure OnNewIncommingConnection(Sender : TObject; Client : TNetTcpIpClient); override;
     procedure SetActive(const Value: Boolean); override;
   public
+    Constructor Create; override;
   End;
 
   TThreadDiscoverConnection = Class(TPCThread)
@@ -521,6 +539,7 @@ end;
 
 constructor TNetData.Create;
 begin
+  TLog.NewLog(ltInfo,ClassName,'TNetData.Create');
   SetLength(FFixedServers,0);
   FMaxRemoteOperationBlock := CT_OperationBlock_NUL;
   FNetStatistics := CT_TNetStatistics_NUL;
@@ -538,8 +557,10 @@ begin
   FIsGettingNewBlockChainFromClient := false;
   FNodePrivateKey := TECPrivateKey.Create;
   FNodePrivateKey.GenerateRandomPrivateKey(CT_Default_EC_OpenSSL_NID);
-  FThreadCheckConnections := TThreadCheckConnections.Create(false);
+  FThreadCheckConnections := TThreadCheckConnections.Create(Self);
   FNetDataNotifyEventsThread := TNetDataNotifyEventsThread.Create(Self);
+  FNetClientsDestroyThread := TNetClientsDestroyThread.Create(Self);
+  If Not Assigned(_NetData) then _NetData := Self;
 end;
 
 procedure TNetData.DeleteNetClient(List: TList; index: Integer);
@@ -552,14 +573,49 @@ end;
 
 destructor TNetData.Destroy;
 Var l : TList;
+  i : Integer;
+  tdc : TThreadDiscoverConnection;
 begin
+  TLog.NewLog(ltInfo,ClassName,'TNetData.Destroy START');
   FOnStatisticsChanged := Nil;
   FOnNetConnectionsUpdated := Nil;
   FOnNodeServersUpdated := Nil;
   FOnBlackListUpdated := Nil;
   FOnReceivedHelloMessage := Nil;
+
+  // First destroy ThreadCheckConnections to prevent a call to "DiscoverServers"
   FThreadCheckConnections.Terminate;
   FThreadCheckConnections.WaitFor;
+  FreeAndNil(FThreadCheckConnections);
+
+  // Now finish all DiscoverConnection threads
+  Repeat
+    tdc := TThreadDiscoverConnection( TPCThreadClass.GetThreadByClass(TThreadDiscoverConnection,nil) );
+    if Assigned(tdc) then begin
+      tdc.FreeOnTerminate := false;
+      tdc.Terminate;
+      tdc.WaitFor;
+      tdc.Free;
+    end;
+  Until Not Assigned(tdc);
+
+  // Closing connections
+  l := FNetConnections.LockList;
+  Try
+    for i := 0 to l.Count - 1 do begin
+      TNetConnection(l[i]).Connected := false;
+      TNetConnection(l[i]).FinalizeConnection;
+    end;
+  Finally
+    FNetConnections.UnlockList;
+  End;
+
+
+  FNetClientsDestroyThread.WaitForTerminatedAllConnections;
+  FNetClientsDestroyThread.Terminate;
+  FNetClientsDestroyThread.WaitFor;
+  FreeAndNil(FNetClientsDestroyThread);
+
   CleanBlackList;
   l := FNodeServers.LockList;
   try
@@ -579,8 +635,12 @@ begin
   FreeAndNil(FNodePrivateKey);
   FNetDataNotifyEventsThread.Terminate;
   FNetDataNotifyEventsThread.WaitFor;
+  FreeAndNil(FNetDataNotifyEventsThread);
   SetLength(FFixedServers,0);
+  FreeAndNil(FRegisteredRequests);
   inherited;
+  if (_NetData=Self) then _NetData := Nil;
+  TLog.NewLog(ltInfo,ClassName,'TNetData.Destroy END');
 end;
 
 procedure TNetData.DisconnectClients;
@@ -592,6 +652,7 @@ begin
     for i := l.Count - 1 downto 0 do begin
       if TObject(l[i]) is TNetClient then begin
         TNetClient(l[i]).Connected := false;
+        TNetClient(l[i]).FinalizeConnection;
       end;
     end;
   Finally
@@ -651,8 +712,8 @@ begin
       for i:=0 to lns.Count-1 do begin
         P := lns[i];
         If (Not Assigned(P.netConnection)) AND (Not IsBlackListed(P^.ip,P^.port)) AND (Not P^.its_myself) And
-          ((P^.last_attempt_to_connect=0) Or ((P^.last_attempt_to_connect+EncodeTime(0,5,0,0)<now))) And
-          ((P^.total_failed_attemps_to_connect<3) Or (P^.last_attempt_to_connect+EncodeTime(2,0,0,0)<now)) then begin
+          ((P^.last_attempt_to_connect=0) Or ((P^.last_attempt_to_connect+EncodeTime(0,3,0,0)<now))) And
+          ((P^.total_failed_attemps_to_connect<3) Or (P^.last_attempt_to_connect+EncodeTime(0,10,0,0)<now)) then begin
 
           if Length(FFixedServers)>0 then begin
             canAdd := false;
@@ -688,7 +749,7 @@ end;
 procedure TNetData.DiscoverServersTerminated(Sender: TObject);
 begin
   NotifyNodeServersUpdated;
-  if TPCThread.ThreadClassFound(TThreadDiscoverConnection,Sender)>=0 then exit;
+  if TPCThread.ThreadClassFound(TThreadDiscoverConnection,Nil)>=0 then exit;
   FIsDiscoveringServers := false;
   // If here, discover servers finished, so we can try to get/receive data
   TLog.NewLog(ltDebug,Classname,Format('Discovering servers finished. Now we have %d active connections and %d connections to other servers',
@@ -774,7 +835,7 @@ end;
 procedure TNetData.GetNewBlockChainFromClient(Connection: TNetConnection);
 Const CT_LogSender = 'GetNewBlockChainFromClient';
 
-  function Do_GetOperationsBlock(AssignToBank : TPCBank; block_start,block_end : Cardinal; OnlyOperationBlock : Boolean; BlocksList : TList) : Boolean;
+  function Do_GetOperationsBlock(AssignToBank : TPCBank; block_start,block_end, MaxWaitMilliseconds : Cardinal; OnlyOperationBlock : Boolean; BlocksList : TList) : Boolean;
   Var SendData,ReceiveData : TMemoryStream;
     headerdata : TNetHeaderData;
     op : TPCOperationsComp;
@@ -799,7 +860,7 @@ Const CT_LogSender = 'GetNewBlockChainFromClient';
       SendData.Write(block_start,4);
       SendData.Write(block_end,4);
       request_id := TNetData.NetData.NewRequestId;
-      if Connection.DoSendAndWaitForResponse(noperation,request_id,SendData,ReceiveData,5000,headerdata) then begin
+      if Connection.DoSendAndWaitForResponse(noperation,request_id,SendData,ReceiveData,MaxWaitMilliseconds,headerdata) then begin
         if HeaderData.is_error then exit;
         if ReceiveData.Read(opcount,4)<4 then exit; // Error in data
         i := 0;
@@ -825,14 +886,14 @@ Const CT_LogSender = 'GetNewBlockChainFromClient';
     end;
   end;
 
-  function Do_GetOperationBlock(block : Cardinal; var OperationBlock : TOperationBlock) : Boolean;
+  function Do_GetOperationBlock(block, MaxWaitMilliseconds : Cardinal; var OperationBlock : TOperationBlock) : Boolean;
   Var BlocksList : TList;
     i : Integer;
   begin
     OperationBlock := CT_OperationBlock_NUL;
     BlocksList := TList.Create;
     try
-      Result := Do_GetOperationsBlock(TNode.Node.Bank,block,block,false,BlocksList);
+      Result := Do_GetOperationsBlock(TNode.Node.Bank,block,block,MaxWaitMilliseconds,false,BlocksList);
       if (Result) And (BlocksList.Count=1) then begin
         OperationBlock := TPCOperationsComp(BlocksList[0]).OperationBlock;
       end;
@@ -855,7 +916,7 @@ Const CT_LogSender = 'GetNewBlockChainFromClient';
     repeat
       BlocksList := TList.Create;
       try
-        If Not Do_GetOperationsBlock(Nil,min,max,true,BlocksList) then exit;
+        If Not Do_GetOperationsBlock(Nil,min,max,5000,true,BlocksList) then exit;
         distinctmin := min;
         distinctmax := max;
         myops := TPCOperationsComp.Create(TNode.Node.Bank);
@@ -929,7 +990,7 @@ Const CT_LogSender = 'GetNewBlockChainFromClient';
       repeat
         BlocksList := TList.Create;
         try
-          finished := NOT Do_GetOperationsBlock(Bank,start,start + 50,false,BlocksList);
+          finished := NOT Do_GetOperationsBlock(Bank,start,start + 50,5000,false,BlocksList);
           i := 0;
           while (i<BlocksList.Count) And (Not finished) do begin
             OpComp := TPCOperationsComp(BlocksList[i]);
@@ -1005,9 +1066,9 @@ begin
     // NOTE: FRemoteOperationBlock.block >= TNode.Node.Bank.BlocksCount
     // First capture same block than me (TNode.Node.Bank.BlocksCount-1) to check if i'm an orphan block...
     my_op := TNode.Node.Bank.LastOperationBlock;
-    If Not Do_GetOperationBlock(my_op.block,client_op) then begin
-      TLog.NewLog(lterror,CT_LogSender,'Cannot receive information about my block ('+inttostr(my_op.block)+')... Invalid client. Disconnecting');
-      Connection.DisconnectInvalidClient(false,'Cannot receive information about my block ('+inttostr(my_op.block)+')... Invalid client. Disconnecting');
+    If Not Do_GetOperationBlock(my_op.block,10000,client_op) then begin
+      TLog.NewLog(lterror,CT_LogSender,'Cannot receive information about my block ('+inttostr(my_op.block)+')... Invalid client');
+      // Disabled at Build 1.0.6 >  Connection.DisconnectInvalidClient(false,'Cannot receive information about my block ('+inttostr(my_op.block)+')... Invalid client. Disconnecting');
       exit;
     end;
 
@@ -1024,7 +1085,7 @@ begin
     end else begin
       TLog.NewLog(ltinfo,CT_LogSender,'My blockchain is ok! Need to download new blocks starting at '+inttostr(my_op.block+1));
       // High to new value:
-      Connection.Send_GetBlocks(my_op.block+1,0,rid);
+      Connection.Send_GetBlocks(my_op.block+1,100,rid);
     end;
   Finally
     TLog.NewLog(ltdebug,CT_LogSender,'Finalizing');
@@ -1132,6 +1193,11 @@ begin
   result := _NetData;
 end;
 
+class function TNetData.NetDataExists: Boolean;
+begin
+  Result := Assigned(_NetData);
+end;
+
 function TNetData.NewRequestId: Cardinal;
 begin
   Inc(FLastRequestId);
@@ -1266,8 +1332,13 @@ end;
 
 { TNetServer }
 
+constructor TNetServer.Create;
+begin
+  inherited;
+  MaxConnections := CT_MaxClientsConnected;
+end;
+
 procedure TNetServer.OnNewIncommingConnection(Sender : TObject; Client : TNetTcpIpClient);
-//procedure TNetServer.OnTcpServerAccept(Sender: TObject; ClientSocket: TCustomIpClient);
 Var n : TNetServerClient;
   DebugStep : String;
 begin
@@ -1330,8 +1401,8 @@ begin
   end;
   inherited;
   if Active then begin
-    TNode.Node.AutoDiscoverNodes(CT_Discover_IPs);
-  end else begin
+    // TNode.Node.AutoDiscoverNodes(CT_Discover_IPs);
+  end else if TNetData.NetDataExists then begin
     TNetData.NetData.DisconnectClients;
   end;
 end;
@@ -1361,12 +1432,17 @@ begin
     TNetData.NetData.FNodeServers.UnlockList;
   end;
 
-  Client.RemoteHost := ServerIP;
-  if ServerPort<=0 then ServerPort := CT_NetServer_Port;
-  Client.RemotePort := ServerPort;
-  TLog.NewLog(ltDebug,Classname,'Trying to connect to a server at: '+ClientRemoteAddr);
-  TNetData.NetData.NotifyNetConnectionUpdated;
-  Result := Client.Connect;
+  TPCThread.ProtectEnterCriticalSection(Self,FNetLock);
+  Try
+    Client.RemoteHost := ServerIP;
+    if ServerPort<=0 then ServerPort := CT_NetServer_Port;
+    Client.RemotePort := ServerPort;
+    TLog.NewLog(ltDebug,Classname,'Trying to connect to a server at: '+ClientRemoteAddr);
+    TNetData.NetData.NotifyNetConnectionUpdated;
+    Result := Client.Connect;
+  Finally
+    FNetLock.Release;
+  End;
   if Result then begin
     TLog.NewLog(ltDebug,Classname,'Connected to a possible server at: '+ClientRemoteAddr);
     Result := Send_Hello(ntp_request,TNetData.NetData.NewRequestId);
@@ -1396,7 +1472,7 @@ begin
   FLastDataSendedTS := 0;
   FTcpIpClient := Nil;
   FRemoteOperationBlock := CT_OperationBlock_NUL;
-  SetClient( TNetTcpIpClient.Create(Nil) );
+  SetClient( TNetTcpIpClient.Create(Self) );
   TNetData.NetData.FNetConnections.Add(Self);
   TNetData.NetData.NotifyNetConnectionUpdated;
 end;
@@ -1514,11 +1590,6 @@ begin
     finally
       ms.Free;
     end;
-    // Build 1.0.3 changes:
-    // - A server only checks connection (send HELLO) if received some data from client
-    // - A client only checks connection (send HELLO) if not received OR send during last minute
-    // (Prior to 1.0.3 sends HELLO if no received data... and if was a server too)
-    //  Before: if ((FLastDataReceivedTS+(1000*60)<GetTickCount) Or (FLastDataSendedTS+(1000*60)<GetTickCount)) then begin
     If ((FLastDataReceivedTS>0) Or ( NOT (Self is TNetServerClient)))
        AND ((FLastDataReceivedTS+(1000*60)<GetTickCount) AND (FLastDataSendedTS+(1000*60)<GetTickCount)) then begin
       DebugStep := 'LastSend time old';
@@ -1572,8 +1643,12 @@ begin
       opclass := TPCOperationsComp.GetOperationClassByOpType(optype);
       if Not Assigned(opclass) then exit;
       op := opclass.Create;
-      op.LoadFromStream(DataBuffer);
-      operations.AddOperationToHashTree(op);
+      Try
+        op.LoadFromStream(DataBuffer);
+        operations.AddOperationToHashTree(op);
+      Finally
+        op.Free;
+      End;
     end;
     DoDisconnect := false;
   finally
@@ -1627,6 +1702,7 @@ begin
          posquantity := db.position;
          db.Write(c,4);
          c := 0;
+         b := b_start;
          for b := b_start to b_end do begin
            inc(c);
            If TNetData.NetData.bank.LoadOperations(op,b) then begin
@@ -1640,6 +1716,9 @@ begin
              // Stop
              db.position := posquantity;
              db.Write(c,4);
+             // BUG of Build 1.0.5 !!! Need to break bucle OH MY GOD!
+             db.Position := db.Size;
+             break;
            end;
          end;
          Send(ntp_response,HeaderData.operation,0,HeaderData.request_id,db);
@@ -1704,14 +1783,14 @@ begin
           end;
         end else begin
           // Receiving an unexpected operationblock
-          TLog.NewLog(lterror,classname,'Received a distinct block, finalizing: '+TPCOperationsComp.OperationBlockToText(op.OperationBlock));
+          TLog.NewLog(lterror,classname,'Received a distinct block, finalizing: '+TPCOperationsComp.OperationBlockToText(op.OperationBlock)+' (My block: '+TPCOperationsComp.OperationBlockToText(TNode.Node.Bank.LastOperationBlock)+')' );
           FIsDownloadingBlocks := false;
           exit;
         end;
       end;
       FIsDownloadingBlocks := false;
       if ((opcount>0) And (FRemoteOperationBlock.block>=TNode.Node.Bank.BlocksCount)) then begin
-        Send_GetBlocks(TNode.Node.Bank.BlocksCount,50,i);
+        Send_GetBlocks(TNode.Node.Bank.BlocksCount,100,i);
       end;
       TNode.Node.NotifyBlocksChanged;
     Finally
@@ -2120,6 +2199,7 @@ end;
 
 procedure TNetConnection.FinalizeConnection;
 begin
+  TLog.NewLog(ltdebug,ClassName,'Executing FinalizeConnection to '+ClientRemoteAddr);
   FDoFinalizeConnection := true;
 end;
 
@@ -2243,6 +2323,7 @@ Var l : Cardinal;
    w : Word;
   Buffer : TStream;
   s : AnsiString;
+  sendbytes : Int64;
 begin
   Buffer := TMemoryStream.Create;
   try
@@ -2298,9 +2379,11 @@ begin
         TNetData.OperationToText(operation)+' id:'+Inttostr(request_id)+' errorcode:'+InttoStr(errorcode)+
         ' Size:'+InttoStr(Buffer.Size)+'b '+s+'to '+
         ClientRemoteAddr);
-      Client.SendStream(Buffer);
-      FLastDataSendedTS := GetTickCount;
-      TNetData.NetData.IncStatistics(0,0,0,0,0,Buffer.Size);
+      sendbytes := Client.SendStream(Buffer);
+      if sendbytes>0 then begin
+        FLastDataSendedTS := GetTickCount;
+        TNetData.NetData.IncStatistics(0,0,0,0,0,Buffer.Size);
+      end;
     Finally
       FNetLock.Release;
     End;
@@ -2361,8 +2444,10 @@ begin
       if FRemoteOperationBlock.block>0 then c2 := FRemoteOperationBlock.block
       else c2 := c1+100;
     end else c2 := c1+quantity-1;
-    // Build 1.0.5 to allow download all:
-    // Deleted: if (FRemoteOperationBlock.block>0) And (c2>FRemoteOperationBlock.block) then c2 := FRemoteOperationBlock.block;
+    // Build 1.0.5 BUG - Allways query for ONLY 1 if Build is lower or equal to 1.0.5
+    if ((FClientAppVersion='') Or ( (length(FClientAppVersion)=5) And (FClientAppVersion<='1.0.5') )) then begin
+      c2 := c1;
+    end;
     data.Write(c1,4);
     data.Write(c2,4);
     request_id := TNetData.NetData.NewRequestId;
@@ -2612,6 +2697,8 @@ Var NC : TNetClient;
   i : Integer;
   Pnsa : PNodeServerAddress;
 begin
+  if Terminated then exit;
+
   TLog.NewLog(ltdebug,Classname,'Starting discovery of connection '+FNodeServerAddress.ip+':'+InttoStr(FNodeServerAddress.port));
   Pnsa := Nil;
   DebugStep := 'Locking list';
@@ -2630,25 +2717,31 @@ begin
     TNetData.NetData.FNodeServers.UnlockList;
   end;
   DebugStep := 'Synchronizing notify';
+  if Terminated then exit;
   TNetData.NetData.NotifyNodeServersUpdated;
   // Try to connect
   ok := false;
   DebugStep := 'Trying to connect';
+  if Terminated then exit;
   NC := TNetClient.Create(Nil);
   Try
     DebugStep := 'Connecting';
     If NC.ConnectTo(FNodeServerAddress.ip,FNodeServerAddress.port) then begin
+      if Terminated then exit;
       Sleep(500);
       DebugStep := 'Is connected now?';
+      if Terminated then exit;
       ok :=NC.Connected;
     end;
+    if Terminated then exit;
   Finally
     if not ok then begin
       DebugStep := 'Destroying non connected';
-      TNetClientDestroyThread.Create(NC);
+      NC.FinalizeConnection;
     end;
   End;
   DebugStep := 'Synchronizing notify final';
+  if Terminated then exit;
   TNetData.NetData.NotifyNodeServersUpdated;
 end;
 
@@ -2671,22 +2764,22 @@ Var l : TList;
 begin
   FLastCheckTS := GetTickCount;
   while (Not Terminated) do begin
-    if ((GetTickCount>(FLastCheckTS+1000)) AND (Not TNetData.NetData.FIsDiscoveringServers)) then begin
+    if ((GetTickCount>(FLastCheckTS+1000)) AND (Not FNetData.FIsDiscoveringServers)) then begin
       nactive := 0;
       ndeleted := 0;
       ntotal := 0;
       nserverclients := 0;
       netserverclientstop := Nil;
       FLastCheckTS := GetTickCount;
-      l := TNetData.NetData.FNetConnections.LockList;
+      l := FNetData.FNetConnections.LockList;
       try
         ntotal := l.Count;
         for i := l.Count-1 downto 0 do begin
           netconn := TNetConnection(l.Items[i]);
           if (netconn is TNetClient) then begin
-            if Not TNetClient(netconn).Connected then begin
+            if (Not TNetClient(netconn).Connected) And (netconn.CreatedTime+EncodeTime(0,0,1,0)<now) then begin
               // Free this!
-              TNetClientDestroyThread.Create(TNetClient(netconn));
+              TNetClient(netconn).FinalizeConnection;
               inc(ndeleted);
             end else inc(nactive);
           end else if (netconn is TNetServerClient) then begin
@@ -2704,17 +2797,23 @@ begin
           netserverclientstop.FinalizeConnection;
         end;
       finally
-        TNetData.NetData.FNetConnections.UnlockList;
+        FNetData.FNetConnections.UnlockList;
       end;
       if (nactive<=CT_MaxServersConnected) And (Not Terminated) then begin
         // Discover
-        TNetData.NetData.DiscoverServers;
+        FNetData.DiscoverServers;
       end;
     end;
     sleep(100);
   end;
 end;
 
+constructor TThreadCheckConnections.Create(NetData: TNetData);
+begin
+  FNetData := NetData;
+  inherited Create(false);
+end;
+
 { TThreadGetNewBlockChainFromClient }
 
 procedure TThreadGetNewBlockChainFromClient.BCExecute;
@@ -2765,7 +2864,7 @@ begin
   while (not Terminated) do begin
     if (FNotifyOnReceivedHelloMessage) Or
        (FNotifyOnStatisticsChanged) Or 
-       (FNotifyOnNetConnectionsUpdated) Or 
+       (FNotifyOnNetConnectionsUpdated) Or
        (FNotifyOnNodeServersUpdated) Or 
        (FNotifyOnBlackListUpdated) then begin
       Synchronize(SynchronizedNotify);
@@ -2783,12 +2882,13 @@ begin
   FNotifyOnNodeServersUpdated := false;
   FNotifyOnBlackListUpdated := false;
   inherited Create(false);
-  FreeOnTerminate := true;
 end;
 
 procedure TNetDataNotifyEventsThread.SynchronizedNotify;
 begin
   if Terminated then exit;
+  if Not Assigned(FNetData) then exit;
+
   if FNotifyOnReceivedHelloMessage then begin
     FNotifyOnReceivedHelloMessage := false;
     If Assigned(FNetData.FOnReceivedHelloMessage) then FNetData.FOnReceivedHelloMessage(FNetData);
@@ -2808,32 +2908,62 @@ begin
   if FNotifyOnBlackListUpdated then begin
     FNotifyOnBlackListUpdated := false;
     If Assigned(FNetData.FOnBlackListUpdated) then FNetData.FOnBlackListUpdated(FNetData);
-  end;  
+  end;
 end;
 
-{ TNetClientDestroyThread }
+{ TNetClientsDestroyThread }
 
-procedure TNetClientDestroyThread.BCExecute;
+procedure TNetClientsDestroyThread.BCExecute;
+Var l,l_to_del : TList;
+  i : Integer;
 begin
-  DebugStep := 'Locking NetClient if exists';
-  If TNetData.NetData.ConnectionLock(Self,FNetClient) then begin
-    try
-      DebugStep := 'Destroying NetClient '+FNetClient.ClientRemoteAddr;
-      FreeAndNil(FNetClient);
-    finally
-      // Not Necessary because on Freeing then Lock is deleted.
-      // -> TNetData.NetData.ConnectionUnlock(FNetClient);
+  l_to_del := TList.Create;
+  Try
+    while not Terminated do begin
+      l_to_del.Clear;
+      l := FNetData.ConnectionsLock;
+      try
+        FTerminatedAllConnections := l.Count=0;
+        for i := 0 to l.Count-1 do begin
+          If (TObject(l[i]) is TNetClient) And (not TNetConnection(l[i]).Connected) And (TNetConnection(l[i]).FDoFinalizeConnection) then begin
+            l_to_del.Add(l[i]);
+          end;
+        end;
+      finally
+        FNetData.ConnectionsUnlock;
+      end;
+
+      for i := 0 to l_to_del.Count - 1 do begin
+        If FNetData.ConnectionLock(Self,TNetConnection(l_to_del[i])) then begin
+          try
+            DebugStep := 'Destroying NetClient '+TNetConnection(l_to_del[i]).ClientRemoteAddr;
+            TNetConnection(l_to_del[i]).Free;
+          finally
+            // Not Necessary because on Freeing then Lock is deleted.
+            // -> TNetData.NetData.ConnectionUnlock(FNetClient);
+          end;
+        end;
+      end;
+      Sleep(100);
     end;
+  Finally
+    l_to_del.Free;
   end;
 end;
 
-constructor TNetClientDestroyThread.Create(NetClient: TNetClient);
+constructor TNetClientsDestroyThread.Create(NetData: TNetData);
 begin
-  FNetClient := NetClient;
-  TLog.NewLog(ltdebug,Classname,'Start destroying NetClient: '+NetClient.ClientRemoteAddr);
-  inherited Create(true);
-  FreeOnTerminate := true;
-  Suspended := false;
+  FNetData:=NetData;
+  FTerminatedAllConnections := true;
+  Inherited Create(false);
+end;
+
+procedure TNetClientsDestroyThread.WaitForTerminatedAllConnections;
+begin
+  while (Not FTerminatedAllConnections) do begin
+    TLog.NewLog(ltdebug,ClassName,'Waiting all connections terminated');
+    Sleep(100);
+  end;
 end;
 
 end.

+ 24 - 8
Units/PascalCoin/UNode.pas

@@ -1,5 +1,9 @@
 unit UNode;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -26,7 +30,12 @@ unit UNode;
 interface
 
 uses
-  Classes, UBlockChain, UNetProtocol, UMiner, UAccounts, UCrypto, Windows, UThread, SyncObjs;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  Classes, UBlockChain, UNetProtocol, UMiner, UAccounts, UCrypto, UThread, SyncObjs;
 
 Type
   TNode = Class(TComponent)
@@ -84,6 +93,7 @@ Type
     Procedure SynchronizedProcess;
   protected
     procedure BCExecute; override;
+    Constructor Create(ANodeNotifyEvents : TNodeNotifyEvents);
   End;
 
   TNodeMessageEvent = Procedure(NetConnection : TNetConnection; MessageData : TRawBytes) of object;
@@ -369,6 +379,7 @@ end;
 constructor TNode.Create(AOwner: TComponent);
 begin
   if Assigned(_Node) then raise Exception.Create('Duplicate nodes protection');
+  TLog.NewLog(ltInfo,ClassName,'TNode.Create');
   inherited;
   FDisabledsNewBlocksCount := 0;
   FLockNodeOperations := TCriticalSection.Create;
@@ -446,12 +457,13 @@ begin
   End;
   m.Terminate;
   m.WaitFor;
+  m.Free;
 end;
 
 destructor TNode.Destroy;
 Var step : String;
 begin
-  TLog.NewLog(ltinfo,Classname,'Destroying Node - START');
+  TLog.NewLog(ltInfo,ClassName,'TNode.Destroy START');
   Try
     step := 'Deleting critical section';
     FreeAndNil(FLockNodeOperations);
@@ -459,8 +471,6 @@ begin
     step := 'Desactivating server';
     FNetServer.Active := false;
 
-    Sleep(1000);
-
     step := 'Deleting miners';
     while (MinersCount>0) do DeleteMiner(0);
 
@@ -477,6 +487,7 @@ begin
     if _Node=Self then _Node := Nil;
 
     step := 'Destroying Bank';
+    FreeAndNil(FBCBankNotify);
     FreeAndNil(FBank);
 
     step := 'inherited';
@@ -487,7 +498,7 @@ begin
       Raise;
     end;
   End;
-  TLog.NewLog(ltinfo,Classname,'Destroying Node - END');
+  TLog.NewLog(ltInfo,ClassName,'TNode.Destroy END');
 end;
 
 procedure TNode.DisableNewBlocks;
@@ -659,9 +670,8 @@ begin
   FOnNodeMessageEvent := Nil;
   FMessages := TStringList.Create;
   FPendingNotificationsList := TPCThreadList.Create;
-  FThreadSafeNodeNotifyEvent := TThreadSafeNodeNotifyEvent.Create(false);
-  FThreadSafeNodeNotifyEvent.FNodeNotifyEvents := Self;
-  FThreadSafeNodeNotifyEvent.FreeOnTerminate := true;
+  FThreadSafeNodeNotifyEvent := TThreadSafeNodeNotifyEvent.Create(Self);
+  FThreadSafeNodeNotifyEvent.FreeOnTerminate := true; // This is to prevent locking when freeing component
   Node := _Node;
 end;
 
@@ -717,6 +727,12 @@ begin
   end;
 end;
 
+constructor TThreadSafeNodeNotifyEvent.Create(ANodeNotifyEvents: TNodeNotifyEvents);
+begin
+  FNodeNotifyEvents := ANodeNotifyEvents;
+  Inherited Create(false);
+end;
+
 procedure TThreadSafeNodeNotifyEvent.SynchronizedProcess;
 Var i : Integer;
 begin

+ 4 - 0
Units/PascalCoin/UOpTransaction.pas

@@ -1,5 +1,9 @@
 unit UOpTransaction;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE

+ 340 - 44
Units/PascalCoin/UTCPIP.pas

@@ -20,23 +20,41 @@ interface
 {$ENDIF}
 
 {$DEFINE DelphiSockets}
+{.$DEFINE Synapse}
+{$IFDEF DelphiSockets}{$IFDEF Synapse}DelphiSockets and Synapse are defined! Choose one!{$ENDIF}{$ENDIF}
+{$IFNDEF DelphiSockets}{$IFNDEF Synapse}Nor DelphiSockets nor Synapse are defined! Choose one!{$ENDIF}{$ENDIF}
 
 uses
   {$IFDEF UNIX}
- cthreads,
- {$ENDIF}
+  //cthreads,
+  {$ENDIF}
+  {$IFDEF Synapse}
+  blcksock,
+  synsock,  // synsock choose Socket by OS
+  {$ENDIF}
+  {$IFDEF DelphiSockets}
+  Sockets,
+  {$ENDIF}
   Classes, Sysutils,
-  UThread,Sockets;
+  UThread;
 
 type
+  {$IFDEF DelphiSockets}
+  TTCPBlockSocket = TCustomIpClient;
+  {$ENDIF}
+
   TNetTcpIpClient = Class(TComponent)
   private
-    {$IFDEF DelphiSockets}
-    FTcpIpClient : TCustomIpClient;
+    FTcpBlockSocket : TTCPBlockSocket;
+    {$IFDEF Synapse}
+    FConnected : Boolean;
+    FRemoteHost : AnsiString;
+    FRemotePort : Word;
+    FBytesReceived, FBytesSent : Int64;
+    {$ENDIF}
     FOnConnect: TNotifyEvent;
     FOnDisconnect: TNotifyEvent;
     FSocketError: Integer;
-    {$ENDIF}
     function GetConnected: Boolean;
     function GetRemoteHost: AnsiString;
     function GetRemotePort: Word;
@@ -69,27 +87,59 @@ type
     Property SocketError : Integer read FSocketError write SetSocketError;
   End;
 
+  {$IFDEF Synapse}
+  TNetTcpIpServer = Class;
+  TTcpIpServerListenerThread = Class;
+
+  TTcpIpSocketThread = Class(TPCThread)
+  private
+    FSock: TTCPBlockSocket;
+    FListenerThread : TTcpIpServerListenerThread;
+  protected
+    procedure BCExecute; override;
+  public
+    Constructor Create(AListenerThread : TTcpIpServerListenerThread; ASocket : TSocket);
+    Destructor Destroy; override;
+  End;
+
+  TTcpIpServerListenerThread = Class(TPCThread)
+  private
+    FNetTcpIpServerServer : TNetTcpIpServer;
+    FServerSocket: TTCPBlockSocket;
+    FTcpIpSocketsThread : TPCThreadList;
+  protected
+    procedure BCExecute; override;
+  public
+    Constructor Create(ANetTcpIpServer : TNetTcpIpServer);
+    Destructor Destroy; override;
+  End;
+  {$ENDIF}
+
   TNetTcpIpServer = Class(TObject)
   private
     {$IFDEF DelphiSockets}
     FTcpIpServer : TTcpServer;
-    FTcpIpClient : TCustomIpClient;
+    {$ENDIF}
+    {$IFDEF Synapse}
+    FTcpIpServer : TTcpIpServerListenerThread;
+    FPort : Word;
+    FActive : Boolean;
     {$ENDIF}
     FNetClients : TPCThreadList;
+    FMaxConnections : Integer;
     function GetActive: Boolean;
     procedure SetPort(const Value: Word);  // When a connection is established to a new client, a TNetConnection is created (p2p)
-    {$IFDEF DelphiSockets}
-    procedure OnTcpServerAccept(Sender: TObject; ClientSocket: TCustomIpClient);
     function GetPort: Word;
-    {$ENDIF}
+    procedure OnTcpServerAccept(Sender: TObject; ClientSocket: TTCPBlockSocket);
   protected
     Procedure OnNewIncommingConnection(Sender : TObject; Client : TNetTcpIpClient); virtual;
     procedure SetActive(const Value: Boolean); virtual;
   public
-    Constructor Create;
+    Constructor Create; virtual;
     Destructor Destroy; override;
     Property Active : Boolean read GetActive write SetActive;
     Property Port : Word read GetPort Write SetPort;
+    Property MaxConnections : Integer read FMaxConnections Write FMaxConnections;
   End;
 
 
@@ -102,22 +152,33 @@ uses UConst, ULog;
 function TNetTcpIpClient.BytesReceived: Int64;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.BytesReceived;
+  Result := FTcpBlockSocket.BytesReceived;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  Result := FBytesReceived;
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.BytesSent: Int64;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.BytesSent;
+  Result := FTcpBlockSocket.BytesSent;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  Result := FBytesSent;
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.ClientRemoteAddr: AnsiString;
 begin
-  If Assigned(FTcpIpClient) then begin
+  If Assigned(FTcpBlockSocket) then begin
     {$IFDEF DelphiSockets}
-    Result := FTcpIpClient.RemoteHost+':'+FTcpIpClient.RemotePort;
+    Result := FTcpBlockSocket.RemoteHost+':'+FTcpBlockSocket.RemotePort;
+    {$ENDIF}
+    {$IFDEF Synapse}
+    if FConnected then
+      Result := FTcpBlockSocket.GetRemoteSinIP+':'+IntToStr(FTcpBlockSocket.GetRemoteSinPort)
+    else Result := FRemoteHost+':'+inttostr(FRemotePort);
     {$ENDIF}
   end else Result := 'NIL';
 end;
@@ -125,20 +186,45 @@ end;
 function TNetTcpIpClient.Connect: Boolean;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.Connect;
+  Result := FTcpBlockSocket.Connect;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  Try
+    FTcpBlockSocket.Connect(FRemoteHost,IntToStr(FRemotePort));
+    FConnected := FTcpBlockSocket.LastError=0;
+    if (FConnected) And (Assigned(FOnConnect)) then FOnConnect(Self)
+    else TLog.NewLog(ltdebug,Classname,'Cannot connect to a server at: '+ClientRemoteAddr+' Reason: '+FTcpBlockSocket.GetErrorDescEx);
+  Except
+    On E:Exception do begin
+      FSocketError := FTcpBlockSocket.LastError;
+      TLog.NewLog(lterror,ClassName,'Error Connecting to '+ClientRemoteAddr+': '+FTcpBlockSocket.GetErrorDescEx);
+      Disconnect;
+    end;
+  End;
+  Result := FConnected;
   {$ENDIF}
 end;
 
 constructor TNetTcpIpClient.Create(AOwner : TComponent);
 begin
   inherited;
-  FTcpIpClient := Nil;
+  FTcpBlockSocket := Nil;
   FSocketError := 0;
   {$IFDEF DelphiSockets}
-  FTcpIpClient := TTcpClient.Create(Nil);
-  FTcpIpClient.OnConnect := OnConnect;
-  FTcpIpClient.OnDisconnect := OnDisconnect;
-  FTcpIpClient.OnError := TCustomIpClient_OnError;
+  FTcpBlockSocket := TTcpClient.Create(Nil);
+  FTcpBlockSocket.OnConnect := OnConnect;
+  FTcpBlockSocket.OnDisconnect := OnDisconnect;
+  FTcpBlockSocket.OnError := TCustomIpClient_OnError;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  FTcpBlockSocket := TTCPBlockSocket.Create;
+  FTcpBlockSocket.OnAfterConnect := OnConnect;
+  FTcpBlockSocket.SocksTimeout := 10000;
+  FRemoteHost := '';
+  FRemotePort  := 0;
+  FBytesReceived := 0;
+  FBytesSent := 0;
+  FConnected := False;
   {$ENDIF}
 end;
 
@@ -146,62 +232,114 @@ destructor TNetTcpIpClient.Destroy;
 begin
   Disconnect;
   inherited;
-  FreeAndNil(FTcpIpClient);
+  FreeAndNil(FTcpBlockSocket);
+  TLog.NewLog(ltdebug,ClassName,'Destroying Socket end');
 end;
 
 procedure TNetTcpIpClient.Disconnect;
 begin
   {$IFDEF DelphiSockets}
-  FTcpIpClient.Disconnect;
-  FTcpIpClient.OnConnect := Nil;
-  FTcpIpClient.OnDisconnect := Nil;
-  FTcpIpClient.OnError := Nil;
+  FTcpBlockSocket.Disconnect;
+  FTcpBlockSocket.OnConnect := Nil;
+  FTcpBlockSocket.OnDisconnect := Nil;
+  FTcpBlockSocket.OnError := Nil;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  if Not FConnected then exit;
+  FTcpBlockSocket.CloseSocket;
+  FConnected := false;
+  if Assigned(FOnDisconnect) then FOnDisconnect(Self);
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.GetConnected: Boolean;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.Connected;
+  Result := FTcpBlockSocket.Connected;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  Result := FConnected;
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.GetRemoteHost: AnsiString;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.RemoteHost;
+  Result := FTcpBlockSocket.RemoteHost;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  if FConnected then Result := FTcpBlockSocket.GetRemoteSinIP
+  else Result := FRemoteHost;
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.GetRemotePort: Word;
 begin
   {$IFDEF DelphiSockets}
-  Result := StrToIntDef(FTcpIpClient.RemotePort,0);
+  Result := StrToIntDef(FTcpBlockSocket.RemotePort,0);
+  {$ENDIF}
+  {$IFDEF Synapse}
+  if FConnected then Result := FTcpBlockSocket.GetRemoteSinPort
+  else Result := FRemotePort;
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.ReceiveBuf(var Buf; BufSize: Integer): Integer;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.ReceiveBuf(Buf,BufSize);
+  Result := FTcpBlockSocket.ReceiveBuf(Buf,BufSize);
+  {$ENDIF}
+  {$IFDEF Synapse}
+  Try
+    Result := FTcpBlockSocket.RecvBuffer(@Buf,BufSize);
+    if (Result<0) Or (FTcpBlockSocket.LastError<>0) then begin
+      TLog.NewLog(ltInfo,ClassName,'Closing connection from '+ClientRemoteAddr+' (Receiving error): '+Inttostr(FTcpBlockSocket.LastError)+' '+FTcpBlockSocket.GetErrorDescEx);
+      Disconnect;
+    end else if Result>0 then inc(FBytesReceived,Result);
+  Except
+    On E:Exception do begin
+      FSocketError := FTcpBlockSocket.LastError;
+      TLog.NewLog(lterror,ClassName,'Exception receiving buffer from '+ClientRemoteAddr+': '+FTcpBlockSocket.GetErrorDescEx);
+      Disconnect;
+    end;
+  End;
   {$ENDIF}
 end;
 
 function TNetTcpIpClient.SendStream(Stream: TStream): Int64;
 Var sp : Int64;
 begin
-  {$IFDEF DelphiSockets}
   sp := Stream.Position;
-  FTcpIpClient.SendStream(Stream);
+  {$IFDEF DelphiSockets}
+  FTcpBlockSocket.SendStream(Stream);
   Result := Stream.Position - sp;
   {$ENDIF}
+  {$IFDEF Synapse}
+  Try
+    FTcpBlockSocket.SendStreamRaw(Stream);
+    if FTcpBlockSocket.LastError<>0 then begin
+      TLog.NewLog(ltInfo,ClassName,'Closing connection from '+ClientRemoteAddr+' (Sending error): '+Inttostr(FTcpBlockSocket.LastError)+' '+FTcpBlockSocket.GetErrorDescEx);
+      Result := -1;
+      Disconnect;
+    end else begin
+      Result := Stream.Position - sp;
+      inc(FBytesSent,Result);
+    end;
+  Except
+    On E:Exception do begin
+      FSocketError := FTcpBlockSocket.LastError;
+      TLog.NewLog(lterror,ClassName,'Exception sending stream to '+ClientRemoteAddr+': '+FTcpBlockSocket.GetErrorDescEx);
+      Disconnect;
+    end;
+  End;
+  {$ENDIF}
 end;
 
 procedure TNetTcpIpClient.SetOnConnect(const Value: TNotifyEvent);
 begin
   FOnConnect := Value;
   {$IFDEF DelphiSockets}
-  FTcpIpClient.OnConnect := OnConnect;
+  FTcpBlockSocket.OnConnect := OnConnect;
   {$ENDIF}
 end;
 
@@ -209,21 +347,27 @@ procedure TNetTcpIpClient.SetOnDisconnect(const Value: TNotifyEvent);
 begin
   FOnDisconnect := Value;
   {$IFDEF DelphiSockets}
-  FTcpIpClient.OnDisconnect := OnDisconnect;
+  FTcpBlockSocket.OnDisconnect := OnDisconnect;
   {$ENDIF}
 end;
 
 procedure TNetTcpIpClient.SetRemoteHost(const Value: AnsiString);
 begin
   {$IFDEF DelphiSockets}
-  FTcpIpClient.RemoteHost := Value;
+  FTcpBlockSocket.RemoteHost := Value;
+  {$ENDIF}
+  {$IFDEF Synapse}
+  FRemoteHost := Value;
   {$ENDIF}
 end;
 
 procedure TNetTcpIpClient.SetRemotePort(const Value: Word);
 begin
   {$IFDEF DelphiSockets}
-  FTcpIpClient.RemotePort := IntToStr(Value);
+  FTcpBlockSocket.RemotePort := IntToStr(Value);
+  {$ENDIF}
+  {$IFDEF Synapse}
+  FRemotePort := Value;
   {$ENDIF}
 end;
 
@@ -244,18 +388,34 @@ end;
 function TNetTcpIpClient.WaitForData(WaitMilliseconds: Integer): Boolean;
 begin
   {$IFDEF DelphiSockets}
-  Result := FTcpIpClient.WaitForData(WaitMilliseconds);
+  Result := FTcpBlockSocket.WaitForData(WaitMilliseconds);
+  {$ENDIF}
+  {$IFDEF Synapse}
+  Try
+    Result := FTcpBlockSocket.CanRead(WaitMilliseconds);
+  Except
+    On E:Exception do begin
+      FSocketError := FTcpBlockSocket.LastError;
+      TLog.NewLog(lterror,ClassName,'Error WaitingForData from '+ClientRemoteAddr+': '+FTcpBlockSocket.GetErrorDescEx);
+      Disconnect;
+    end;
+  End;
   {$ENDIF}
 end;
 
+
 { TNetTcpIpServer }
 
 constructor TNetTcpIpServer.Create;
 begin
+  FTcpIpServer := Nil;
+  FMaxConnections := 10;
   {$IFDEF DelphiSockets}
   FTcpIpServer := TTcpServer.Create(Nil);
   FTcpIpServer.OnAccept := OnTcpServerAccept;
   FTcpIpServer.ServerSocketThread.ThreadCacheSize := CT_MaxClientsConnected;
+  {$ELSE}
+  FActive := false;
   {$ENDIF}
 end;
 
@@ -273,6 +433,8 @@ function TNetTcpIpServer.GetActive: Boolean;
 begin
   {$IFDEF DelphiSockets}
   Result := FTcpIpServer.Active;
+  {$ELSE}
+  Result := Assigned(FTcpIpServer) And (FActive);
   {$ENDIF}
 end;
 
@@ -280,6 +442,8 @@ function TNetTcpIpServer.GetPort: Word;
 begin
   {$IFDEF DelphiSockets}
   Result := StrToIntDef(FTcpIpServer.LocalPort,0);
+  {$ELSE}
+  Result := FPort;
   {$ENDIF}
 end;
 
@@ -288,27 +452,47 @@ begin
   //
 end;
 
-{$IFDEF DelphiSockets}
-procedure TNetTcpIpServer.OnTcpServerAccept(Sender: TObject; ClientSocket: TCustomIpClient);
+procedure TNetTcpIpServer.OnTcpServerAccept(Sender: TObject; ClientSocket: TTCPBlockSocket);
 Var n : TNetTcpIpClient;
-  oldSocket : TCustomIpClient;
+  oldSocket : TTCPBlockSocket;
 begin
+  {$IFDEF DelphiSockets}
+  If FTcpIpServer.ServerSocketThread.ThreadCacheSize <> MaxConnections then
+      FTcpIpServer.ServerSocketThread.ThreadCacheSize := MaxConnections;
+  {$ENDIF}
+
   n := TNetTcpIpClient.Create(Nil);
   Try
-    oldSocket := n.FTcpIpClient;
-    n.FTcpIpClient := ClientSocket;
+    oldSocket := n.FTcpBlockSocket;
+    n.FTcpBlockSocket := ClientSocket;
+    {$IFDEF Synapse}
+    n.FConnected := True;
+    n.RemoteHost := ClientSocket.GetRemoteSinIP;
+    n.RemotePort := ClientSocket.GetRemoteSinPort;
+    {$ENDIF}
     OnNewIncommingConnection(Sender,n);
   Finally
-    n.FTcpIpClient := oldSocket;
+    n.FTcpBlockSocket := oldSocket;
     FreeAndNil(n);
   End;
 end;
-{$ENDIF}
 
 procedure TNetTcpIpServer.SetActive(const Value: Boolean);
 begin
   {$IFDEF DelphiSockets}
   FTcpIpServer.Active := Value;
+  {$ELSE}
+  if Value then begin
+    if (Assigned(FTcpIpServer)) then exit;
+    FTcpIpServer := TTcpIpServerListenerThread.Create(Self);
+    FActive := true;
+  end else begin
+    if (Not Assigned(FTcpIpServer)) then exit;
+    FActive := false;
+    FTcpIpServer.Terminate;
+    FTcpIpServer.WaitFor;
+    FreeAndNil(FTcpIpServer);
+  end;
   {$ENDIF}
 end;
 
@@ -316,8 +500,120 @@ procedure TNetTcpIpServer.SetPort(const Value: Word);
 begin
   {$IFDEF DelphiSockets}
   FTcpIpServer.LocalPort := IntToStr(Value);
+  {$ELSE}
+  FPort := Value;
   {$ENDIF}
 end;
 
+{$IFDEF Synapse}
+{ TTcpIpServerListenerThread }
+
+procedure TTcpIpServerListenerThread.BCExecute;
+var ClientSocket: TSocket;
+    ClientThread: TTcpIpSocketThread;
+    lSockets : TList;
+    i : Integer;
+begin
+  FServerSocket.CreateSocket;
+  if FServerSocket.LastError<>0 then begin
+    TLog.NewLog(lterror,Classname,'Error initializing the socket: '+FServerSocket.GetErrorDescEx);
+    exit;
+  end;
+  FServerSocket.Family := SF_IP4;
+  FServerSocket.SetLinger(true,10000);
+  FServerSocket.Bind('0.0.0.0',IntToStr(FNetTcpIpServerServer.Port));
+  if FServerSocket.LastError<>0 then begin
+    TLog.NewLog(lterror,Classname,'Cannot bind port '+IntToStr(FNetTcpIpServerServer.Port)+': '+FServerSocket.GetErrorDescEx);
+    exit;
+  end;
+  FServerSocket.Listen;
+  lSockets := TList.Create;
+  try
+    while (Not Terminated) And (FNetTcpIpServerServer.Active) do begin
+      If (FServerSocket.CanRead(100)) And (lSockets.Count<FNetTcpIpServerServer.MaxConnections) then begin
+        ClientSocket := FServerSocket.Accept;
+        if FServerSocket.LastError = 0 then begin
+          ClientThread := TTcpIpSocketThread.Create(Self,ClientSocket);
+          lSockets.Add(ClientThread);
+          ClientThread.Suspended := false;
+        end;
+      end;
+      // Clean finished threads
+      for i := lSockets.Count - 1 downto 0 do begin
+        ClientThread := TTcpIpSocketThread(lSockets[i]);
+        if ClientThread.Terminated then begin
+          lSockets.Delete(i);
+          ClientThread.Free;
+        end;
+      end;
+      // Wait
+      sleep(1);
+    End;
+  finally
+    // Finalize all threads
+    for i := 0 to lSockets.Count - 1 do begin
+      // Here we no wait until terminated...
+      TTcpIpSocketThread(lSockets[i]).FListenerThread := Nil;
+      TTcpIpSocketThread(lSockets[i]).Terminate;
+      TTcpIpSocketThread(lSockets[i]).WaitFor;
+      TTcpIpSocketThread(lSockets[i]).Free;
+    end;
+    lSockets.free;
+  end;
+end;
+
+constructor TTcpIpServerListenerThread.Create(ANetTcpIpServer: TNetTcpIpServer);
+begin
+  FServerSocket := TTCPBlockSocket.Create;
+  FNetTcpIpServerServer := ANetTcpIpServer;
+  FNetTcpIpServerServer.FTcpIpServer := Self;
+  inherited Create(false);
+end;
+
+destructor TTcpIpServerListenerThread.Destroy;
+begin
+  FNetTcpIpServerServer.FTcpIpServer := Nil;
+  FServerSocket.Free;
+  inherited;
+end;
+
+{ TTcpIpSocketThread }
+
+procedure TTcpIpSocketThread.BCExecute;
+begin
+  if (Not Terminated) And (Assigned(FSock)) And (Assigned(FListenerThread)) then
+    FListenerThread.FNetTcpIpServerServer.OnTcpServerAccept(Self,FSock);
+end;
+
+constructor TTcpIpSocketThread.Create(AListenerThread: TTcpIpServerListenerThread; ASocket: TSocket);
+begin
+  FSock := TTCPBlockSocket.Create;
+  FSock.Socket := ASocket;
+  FListenerThread := AListenerThread;
+  inherited Create(true);
+end;
+
+destructor TTcpIpSocketThread.Destroy;
+begin
+  Try
+    if FSock.Socket<>INVALID_SOCKET then begin
+      FSock.CloseSocket;
+    end;
+  Except
+    On E:Exception do begin
+      TLog.NewLog(lterror,ClassName,'Error closign socket: '+E.Message);
+    end;
+  End;
+  Try
+    FreeAndNil(FSock);
+  Except
+    On E:Exception do begin
+      TLog.NewLog(lterror,ClassName,'Error destroying socket: '+E.Message);
+    end;
+  End;
+  inherited;
+end;
+
+{$ENDIF}
 
 end.

+ 33 - 18
Units/PascalCoin/UThread.pas

@@ -1,5 +1,9 @@
 unit UThread;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -16,7 +20,12 @@ unit UThread;
 interface
 
 uses
-  Classes, SyncObjs, Windows;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  Classes, SyncObjs;
 
 Type
   TPCThread = Class;
@@ -33,7 +42,8 @@ Type
     Class function ThreadClassFound(tclass : TPCThreadClass; Exclude : TObject) : Integer;
     Class function ThreadCount : Integer;
     Class function GetThread(index : Integer) : TPCThread;
-    Class function TerminateAllThreads : Integer;
+    Class function GetThreadByClass(tclass : TPCThreadClass; Exclude : TObject) : TPCThread;
+    Class function TerminateAllThreads(tclass: TPCThreadClass) : Integer;
     Class Procedure ProtectEnterCriticalSection(Const Sender : TObject; var Lock : TCriticalSection);
     Class Function TryProtectEnterCriticalSection(Const Sender : TObject; MaxWaitMilliseconds : Cardinal; var Lock : TCriticalSection) : Boolean;
     Class Procedure ThreadsListInfo(list: TStrings);
@@ -116,6 +126,25 @@ begin
   end;
 end;
 
+class function TPCThread.GetThreadByClass(tclass: TPCThreadClass; Exclude: TObject): TPCThread;
+Var l : TList;
+  i : Integer;
+begin
+  Result := Nil;
+  if Not Assigned(_threads) then exit;
+  l := _threads.LockList;
+  try
+    for i := 0 to l.Count - 1 do begin
+      if (TPCThread(l[i]) is tclass) And ((l[i])<>Exclude) then begin
+        Result := TPCThread(l[i]);
+        exit;
+      end;
+    end;
+  finally
+    _threads.UnlockList;
+  end;
+end;
+
 class procedure TPCThread.ProtectEnterCriticalSection(Const Sender : TObject; var Lock: TCriticalSection);
 begin
   if Not Lock.TryEnter then begin
@@ -127,23 +156,9 @@ begin
   end;
 end;
 
-class function TPCThread.TerminateAllThreads: Integer;
-Var l : TList;
-  i : Integer;
+class function TPCThread.TerminateAllThreads(tclass: TPCThreadClass): Integer;
 begin
-  Result := -1;
-  if Not Assigned(_threads) then exit;
-  l := _threads.LockList;
-  try
-    for i :=l.Count - 1 downto 0 do begin
-      TPCThread(l[i]).Terminate;
-      if TPCThread(l[i]).Suspended then TPCThread(l[i]).Suspended := false;
-      TPCThread(l[i]).WaitFor;
-    end;
-    Result := l.Count;
-  finally
-    _threads.UnlockList;
-  end;
+
 end;
 
 class function TPCThread.ThreadClassFound(tclass: TPCThreadClass; Exclude : TObject): Integer;

+ 33 - 3
Units/PascalCoin/UTime.pas

@@ -1,5 +1,9 @@
 unit UTime;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -15,10 +19,18 @@ unit UTime;
 
 interface
 
-Uses SysUtils, Windows;
+Uses
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages,
+{$ENDIF}
+  SysUtils;
 
+{$IFnDEF FPC}
 function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation; var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall;
 function SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation: PTimeZoneInformation; var lpUniversalTime,lpLocalTime: TSystemTime): BOOL; stdcall;
+{$ENDIF}
 
 Function DateTime2UnivDateTime(d:TDateTime):TDateTime;
 Function UnivDateTime2LocalDateTime(d:TDateTime):TDateTime;
@@ -31,9 +43,12 @@ Function DateTimeElapsedTime(dtDate : TDateTime) : AnsiString;
 
 implementation
 
-
-function TzSpecificLocalTimeToSystemTime; external kernel32 name 'TzSpecificLocalTimeToSystemTime';
+{$IFDEF FPC}
+Uses DateUtils;
+{$ELSE}
+function TzSpecificLocalTimeToSystemTime; external 'kernel32.dll' name 'TzSpecificLocalTimeToSystemTime';
 function SystemTimeToTzSpecificLocalTime; external kernel32 name 'SystemTimeToTzSpecificLocalTime';
+{$ENDIF}
 
 const
     UnixStartDate: TDateTime = 25569.0; // 01/01/1970
@@ -58,6 +73,12 @@ Begin
 End;
 
 Function DateTime2UnivDateTime(d:TDateTime):TDateTime;
+{$IFDEF FPC}
+begin
+  Result := UniversalTimeToLocal(d);
+//  Result := LocalTimeToUniversal(d);
+end;
+{$ELSE}
 var
  TZI:TTimeZoneInformation;
  LocalTime, UniversalTime:TSystemTime;
@@ -67,8 +88,16 @@ begin
   TzSpecificLocalTimeToSystemTime(@tzi,LocalTime,UniversalTime);
   Result := SystemTimeToDateTime(UniversalTime);
 end;
+{$ENDIF}
 
 Function UnivDateTime2LocalDateTime(d:TDateTime):TDateTime;
+{$IFDEF FPC}
+begin
+//  Result := UniversalTimeToLocal(d);
+  Result := LocalTimeToUniversal(d);
+end;
+
+{$ELSE}
 var
  TZI:TTimeZoneInformation;
  LocalTime, UniversalTime:TSystemTime;
@@ -78,6 +107,7 @@ begin
   SystemTimeToTzSpecificLocalTime(@tzi,UniversalTime,LocalTime);
   Result := SystemTimeToDateTime(LocalTime);
 end;
+{$ENDIF}
 
 function UnivDateTimeToUnix(dtDate: TDateTime): Longint;
 begin

+ 7 - 2
Units/PascalCoin/UWalletKeys.pas

@@ -1,5 +1,9 @@
 unit UWalletKeys;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -42,8 +46,8 @@ Type
     procedure SetWalletFileName(const Value: AnsiString);
   public
     Property Key[index : Integer] : TWalletKey read GetKey; default;
-    Constructor Create(AOwner : TComponent);
-    Destructor destroy;
+    Constructor Create(AOwner : TComponent); override;
+    Destructor destroy; override;
     Procedure LoadFromStream(Stream : TStream);
     Procedure SaveToStream(Stream : TStream);
     Property IsValidPassword : Boolean read FIsValidPassword;
@@ -161,6 +165,7 @@ begin
   FreeAndNil(FWalletFileStream);
   Clear;
   FKeys.Free;
+  inherited;
 end;
 
 procedure TWalletKeys.GeneratePrivateKeysFromPassword;

+ 10 - 1
Units/Utils/UAES.pas

@@ -1,5 +1,9 @@
 unit UAES;
 
+{$IFDEF FPC}
+  {$MODE Delphi}
+{$ENDIF}
+
 { Copyright (c) 2016 by Albert Molina
 
   Distributed under the MIT software license, see the accompanying file LICENSE
@@ -40,7 +44,12 @@ Type
 implementation
 
 uses
-  ssl_const, ssl_bn, ssl_types, ssl_evp, Windows;
+{$IFnDEF FPC}
+  Windows,
+{$ELSE}
+  LCLIntf, LCLType, LMessages, Windows,
+{$ENDIF}
+  ssl_const, ssl_bn, ssl_types, ssl_evp;
 
 
 CONST SALT_MAGIC: AnsiString = 'Salted__'; SALT_MAGIC_LEN: integer = 8; SALT_SIZE = 8;

+ 1 - 1
Units/Utils/UAppParams.pas

@@ -367,7 +367,7 @@ end;
 
 destructor TAppParams.Destroy;
 begin
-  FParamsStream.Free;
+  FreeAndNil(FParamsStream);
   InternalClear;
   FParams.Free;
   inherited;