diff --git a/Demos/ChatDemo/Server/ChatServer.identcache b/Demos/ChatDemo/Server/ChatServer.identcache
deleted file mode 100644
index 503e9b6..0000000
Binary files a/Demos/ChatDemo/Server/ChatServer.identcache and /dev/null differ
diff --git a/Demos/ChatDemo/Server/ChatServer.res b/Demos/ChatDemo/Server/ChatServer.res
deleted file mode 100644
index 2d1e943..0000000
Binary files a/Demos/ChatDemo/Server/ChatServer.res and /dev/null differ
diff --git a/Demos/DB/ChatDemo/Client/ChatClient.identcache b/Demos/DB/ChatDemo/Client/ChatClient.identcache
deleted file mode 100644
index 99d9dc7..0000000
Binary files a/Demos/DB/ChatDemo/Client/ChatClient.identcache and /dev/null differ
diff --git a/Demos/DB/ChatDemo/Client/ChatClient.res b/Demos/DB/ChatDemo/Client/ChatClient.res
deleted file mode 100644
index d543374..0000000
Binary files a/Demos/DB/ChatDemo/Client/ChatClient.res and /dev/null differ
diff --git a/Demos/NetComVSIndy/Client/NetComVSIndyClient.identcache b/Demos/NetComVSIndy/Client/NetComVSIndyClient.identcache
deleted file mode 100644
index c264ead..0000000
Binary files a/Demos/NetComVSIndy/Client/NetComVSIndyClient.identcache and /dev/null differ
diff --git a/Demos/NetComVSIndy/Client/NetComVSIndyClient.res b/Demos/NetComVSIndy/Client/NetComVSIndyClient.res
deleted file mode 100644
index 71b6a94..0000000
Binary files a/Demos/NetComVSIndy/Client/NetComVSIndyClient.res and /dev/null differ
diff --git a/Demos/NetComVSIndy/Server/NetComVSIndyServer.identcache b/Demos/NetComVSIndy/Server/NetComVSIndyServer.identcache
deleted file mode 100644
index 56929d7..0000000
Binary files a/Demos/NetComVSIndy/Server/NetComVSIndyServer.identcache and /dev/null differ
diff --git a/Demos/NetComVSIndy/Server/NetComVSIndyServer.res b/Demos/NetComVSIndy/Server/NetComVSIndyServer.res
deleted file mode 100644
index 9ed10ba..0000000
Binary files a/Demos/NetComVSIndy/Server/NetComVSIndyServer.res and /dev/null differ
diff --git a/Demos/SimpleSockets/Client.dproj b/Demos/SimpleSockets/Client.dproj
deleted file mode 100644
index 1273313..0000000
--- a/Demos/SimpleSockets/Client.dproj
+++ /dev/null
@@ -1,214 +0,0 @@
-
-
- {2F2F33BE-2A99-4B2A-A206-E1E4DE8915A3}
- 18.8
- Client.dpr
- Release
- DCC32
- VCL
- True
- Win64
- 3
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- Client.exe
- off
- vclx;vcl;vclimg;dbrtl;Rave77VCL;bdertl;rtl;vclactnband;xmlrtl;vcldb;vcldbx;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dclOfficeXP;$(DCC_UsePackage)
- $(BDSCOMMONDIR)\DCP
- $(BDSCOMMONDIR)\DCU
- x86
- 00400000
- Client
- Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace)
- true
- 1032
- CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
-
-
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\delphi_PROJECTICON.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\delphi_PROJECTICON.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
- System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
- DEBUG;$(DCC_Define)
-
-
- Debug
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
- 1033
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
-
-
-
- MainSource
-
-
-
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
-
- Delphi.Personality.12
-
-
-
-
- Client.dpr
-
-
- False
- True
- False
-
-
- True
- False
- 1
- 0
- 0
- 0
- False
- False
- False
- False
- False
- 1032
- 1253
-
-
-
-
- 1.0.0.0
-
-
-
-
-
- 1.0.0.0
-
-
-
- Microsoft Office 2000 Sample Automation Server Wrapper Components
-
-
-
- False
- True
- True
-
-
- 12
-
-
-
diff --git a/Demos/SimpleSockets/Client.dproj.local b/Demos/SimpleSockets/Client.dproj.local
deleted file mode 100644
index b4899b3..0000000
--- a/Demos/SimpleSockets/Client.dproj.local
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/Demos/SimpleSockets/Client.identcache b/Demos/SimpleSockets/Client.identcache
deleted file mode 100644
index 8b81f03..0000000
Binary files a/Demos/SimpleSockets/Client.identcache and /dev/null differ
diff --git a/Demos/SimpleSockets/Client.res b/Demos/SimpleSockets/Client.res
deleted file mode 100644
index 3e78508..0000000
Binary files a/Demos/SimpleSockets/Client.res and /dev/null differ
diff --git a/Demos/SimpleSockets/Srv/Server.dproj b/Demos/SimpleSockets/Srv/Server.dproj
deleted file mode 100644
index 4fcb55a..0000000
--- a/Demos/SimpleSockets/Srv/Server.dproj
+++ /dev/null
@@ -1,216 +0,0 @@
-
-
- {B76A70BC-BC2B-42B3-990D-FEC6939EAFD9}
- 18.8
- Server.dpr
- Release
- DCC32
- VCL
- True
- Win64
- 3
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- Server.exe
- off
- vclx;vcl;vclimg;dbrtl;Rave77VCL;bdertl;rtl;vclactnband;xmlrtl;vcldb;vcldbx;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dclOfficeXP;$(DCC_UsePackage)
- $(BDSCOMMONDIR)\DCP
- $(BDSCOMMONDIR)\DCU
- x86
- 00400000
- Server
- Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace)
- true
- 1032
- CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
-
-
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\delphi_PROJECTICON.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\delphi_PROJECTICON.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
- System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
- 1033
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- $(BDS)\bin\delphi_PROJECTICON.ico
-
-
- false
- DEBUG;$(DCC_Define)
-
-
- Debug
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
-
- Delphi.Personality.12
-
-
-
-
- False
- True
- False
-
-
- True
- False
- 1
- 0
- 0
- 0
- False
- False
- False
- False
- False
- 1032
- 1253
-
-
-
-
- 1.0.0.0
-
-
-
-
-
- 1.0.0.0
-
-
-
- Microsoft Office 2000 Sample Automation Server Wrapper Components
-
-
- Server.dpr
-
-
-
- False
- True
- True
-
-
- 12
-
-
-
diff --git a/Demos/SimpleSockets/Srv/Server.dproj.local b/Demos/SimpleSockets/Srv/Server.dproj.local
deleted file mode 100644
index b4899b3..0000000
--- a/Demos/SimpleSockets/Srv/Server.dproj.local
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/Demos/SimpleSockets/Srv/Server.identcache b/Demos/SimpleSockets/Srv/Server.identcache
deleted file mode 100644
index 764389c..0000000
Binary files a/Demos/SimpleSockets/Srv/Server.identcache and /dev/null differ
diff --git a/Demos/SimpleSockets/Srv/Server.res b/Demos/SimpleSockets/Srv/Server.res
deleted file mode 100644
index 8002f6e..0000000
Binary files a/Demos/SimpleSockets/Srv/Server.res and /dev/null differ
diff --git a/Demos/SimpleSockets/Srv/ufrmMain.pas b/Demos/SimpleSockets/Srv/ufrmMain.pas
deleted file mode 100644
index f2ff91e..0000000
--- a/Demos/SimpleSockets/Srv/ufrmMain.pas
+++ /dev/null
@@ -1,140 +0,0 @@
-unit ufrmMain;
-
-interface
-
-uses
-{$IFDEF MSWINDOWS}
- WinApi.Windows, WinApi.Winsock2,
-{$ELSE}
- Posix.SysSocket, Posix.Unistd,
-{$ENDIF}
- System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Samples.Spin,
- System.Diagnostics, ncLines, ncSocketList, ncSockets;
-
-type
- TfrmMain = class(TForm)
- memLog: TMemo;
- TCPServer: TncTCPServer;
- pnlToolbar: TPanel;
- btnActivate: TButton;
- pblPort: TPanel;
- edtPort: TSpinEdit;
- btnShutdownAllClients: TButton;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure TCPServerConnected(Sender: TObject; aLine: TncLine);
- procedure TCPServerDisconnected(Sender: TObject; aLine: TncLine);
- procedure TCPServerReadData(Sender: TObject; aLine: TncLine; const aBuf: TArray; aBufCount: Integer);
- procedure btnActivateClick(Sender: TObject);
- procedure edtPortChange(Sender: TObject);
- procedure btnShutdownAllClientsClick(Sender: TObject);
- private
- public
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.dfm}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- try
- TCPServer.Active := True;
- memLog.Lines.Add('Server is active at port: ' + IntToStr(TCPServer.Port));
- btnActivate.Caption := 'Deactivate';
- except
- on e: Exception do
- memLog.Lines.Add('Server cannot activate. ' + e.Message);
- end;
-end;
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- TCPServer.Active := False;
-end;
-
-procedure TfrmMain.btnActivateClick(Sender: TObject);
-begin
- try
- TCPServer.Active := not TCPServer.Active;
- finally
- if TCPServer.Active then
- begin
- memLog.Lines.Add('Server is active at port: ' + IntToStr(TCPServer.Port));
- btnActivate.Caption := 'Deactivate';
- end
- else
- begin
- memLog.Lines.Add('Server was deactivated');
- btnActivate.Caption := 'Activate';
- end;
- end;
-end;
-
-procedure TfrmMain.edtPortChange(Sender: TObject);
-begin
- try
- TCPServer.Port := edtPort.Value;
- except
- // if it is active, it will not allow us to change the value,
- // revert the edtPort value to its original
- edtPort.Value := TCPServer.Port;
- raise; // Reraise the exception so as the user sees the error
- end;
-end;
-
-procedure TfrmMain.btnShutdownAllClientsClick(Sender: TObject);
-var
- SocketList: TSocketList;
- i: Integer;
-begin
- SocketList := TCPServer.Lines.LockList;
- try
- for i := 0 to SocketList.Count - 1 do
- TCPServer.ShutDownLine(SocketList.Lines[i]);
- finally
- TCPServer.Lines.UnlockList;
- end;
-end;
-
-
-procedure TfrmMain.TCPServerConnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add('Connected: ' + aLine.PeerIP);
- end);
-
- TCPServer.Send(aLine, BytesOf('Hello mr. ' + IntToStr(aLine.Handle)));
-end;
-
-procedure TfrmMain.TCPServerDisconnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add('Disconnected: ' + aLine.PeerIP);
- end);
-end;
-
-procedure TfrmMain.TCPServerReadData(Sender: TObject; aLine: TncLine; const aBuf: TArray; aBufCount: Integer);
-var
- BytesReceived: TBytes;
-begin
- BytesReceived := Copy(aBuf, 0, aBufCount);
-
- TThread.Queue(nil,
- procedure
- begin
- memLog.Lines.Add('Received: "' + StringOf(BytesReceived) + '" from: ' + aLine.PeerIP);
- end);
-
- // Send back the buffer received
- TCPServer.Send(aLine, BytesReceived);
-end;
-
-end.
diff --git a/Demos/SimpleSockets/ufrmMain.pas b/Demos/SimpleSockets/ufrmMain.pas
deleted file mode 100644
index 2c10902..0000000
--- a/Demos/SimpleSockets/ufrmMain.pas
+++ /dev/null
@@ -1,147 +0,0 @@
-unit ufrmMain;
-
-interface
-
-uses
-{$IFDEF MSWINDOWS}
- WinApi.Windows, WinApi.Winsock2,
-{$ELSE}
- Posix.SysSocket, Posix.Unistd,
-{$ENDIF}
- System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Samples.Spin,
- System.Diagnostics, ncLines, ncSockets;
-
-type
- TForm1 = class(TForm)
- memLog: TMemo;
- TCPClient: TncTCPClient;
- pnlToolbar: TPanel;
- btnActivate: TButton;
- pnlAddress: TPanel;
- edtHost: TEdit;
- edtPort: TSpinEdit;
- Panel1: TPanel;
- btnSendData: TButton;
- Panel2: TPanel;
- edtDataToSend: TEdit;
- procedure btnActivateClick(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure TCPClientConnected(Sender: TObject; aLine: TncLine);
- procedure TCPClientDisconnected(Sender: TObject; aLine: TncLine);
- procedure TCPClientReconnected(Sender: TObject; aLine: TncLine);
- procedure TCPClientReadData(Sender: TObject; aLine: TncLine; const aBuf: TArray; aBufCount: Integer);
- procedure edtHostChange(Sender: TObject);
- procedure edtPortChange(Sender: TObject);
- procedure btnSendDataClick(Sender: TObject);
- procedure edtDataToSendEnter(Sender: TObject);
- procedure edtDataToSendExit(Sender: TObject);
- private
- public
- end;
-
-var
- Form1: TForm1;
-
-implementation
-
-{$R *.dfm}
-
-procedure TForm1.FormDestroy(Sender: TObject);
-begin
- TCPClient.Active := False;
-end;
-
-procedure TForm1.edtHostChange(Sender: TObject);
-begin
- try
- TCPClient.Host := edtHost.Text;
- except
- edtHost.OnChange := nil;
- try
- edtHost.Text := TCPClient.Host;
- finally
- edtHost.OnChange := edtHostChange;
- end;
- raise;
- end;
-end;
-
-procedure TForm1.edtPortChange(Sender: TObject);
-begin
- try
- TCPClient.Port := edtPort.Value;
- except
- edtPort.OnChange := nil;
- try
- edtPort.Value := TCPClient.Port;
- finally
- edtPort.OnChange := edtPortChange;
- end;
- raise;
- end;
-end;
-
-procedure TForm1.btnActivateClick(Sender: TObject);
-begin
- TCPClient.Active := not TCPClient.Active;
-end;
-
-procedure TForm1.edtDataToSendEnter(Sender: TObject);
-begin
- btnSendData.Default := True;
-end;
-
-procedure TForm1.edtDataToSendExit(Sender: TObject);
-begin
- btnSendData.Default := False;
-end;
-
-procedure TForm1.TCPClientConnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add('Connected');
- btnActivate.Caption := 'Deactivate';
- end);
-end;
-
-procedure TForm1.TCPClientDisconnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add('Disconnected');
- btnActivate.Caption := 'Activate';
- end);
-end;
-
-procedure TForm1.TCPClientReconnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add('Reconnected');
- end);
-end;
-
-procedure TForm1.TCPClientReadData(Sender: TObject; aLine: TncLine; const aBuf: TArray; aBufCount: Integer);
-var
- BytesReceived: TBytes;
-begin
- BytesReceived := Copy(aBuf, 0, aBufCount);
-
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add('Received: ' + StringOf(BytesReceived));
- end);
-end;
-
-procedure TForm1.btnSendDataClick(Sender: TObject);
-begin
- TCPClient.Send(edtDataToSend.Text);
-end;
-
-
-end.
diff --git a/Demos/ChatDemo/Client/ChatClient.dpr b/Demos/TCP/ChatDemo/Client/ChatClient.dpr
similarity index 94%
rename from Demos/ChatDemo/Client/ChatClient.dpr
rename to Demos/TCP/ChatDemo/Client/ChatClient.dpr
index 8c41207..2f85b6a 100644
--- a/Demos/ChatDemo/Client/ChatClient.dpr
+++ b/Demos/TCP/ChatDemo/Client/ChatClient.dpr
@@ -1,17 +1,17 @@
-program ChatClient;
-
-uses
- System.StartUpCopy,
- FMX.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain};
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program ChatClient;
+
+uses
+ System.StartUpCopy,
+ FMX.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/ChatDemo/Client/ChatClient.dproj b/Demos/TCP/ChatDemo/Client/ChatClient.dproj
similarity index 98%
rename from Demos/ChatDemo/Client/ChatClient.dproj
rename to Demos/TCP/ChatDemo/Client/ChatClient.dproj
index 79107f5..3d97885 100644
--- a/Demos/ChatDemo/Client/ChatClient.dproj
+++ b/Demos/TCP/ChatDemo/Client/ChatClient.dproj
@@ -1,1097 +1,1097 @@
-
-
- {E615DFF5-615F-4A51-B6AF-B5B187237486}
- 18.8
- FMX
- ChatClient.dpr
- True
- Debug
- Win64
- 32787
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- true
- true
- true
- true
- true
- true
- true
- true
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\delphi_PROJECTICNS.icns
- ChatClient
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
- 1
- #000000
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
- 1
- #000000
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
- true
- 1033
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
- fmx
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- ChatClient.dpr
-
-
- Microsoft Office 2000 Sample Automation Server Wrapper Components
-
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- ChatClient.exe
- true
-
-
-
-
- ChatClient.exe
- true
-
-
-
-
- ChatClient.rsm
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- True
- True
-
-
- 12
-
-
-
-
-
+
+
+ {E615DFF5-615F-4A51-B6AF-B5B187237486}
+ 18.8
+ FMX
+ ChatClient.dpr
+ True
+ Debug
+ Win64
+ 32787
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ ChatClient
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ 1
+ #000000
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ 1
+ #000000
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+ true
+ 1033
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ fmx
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ ChatClient.dpr
+
+
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ ChatClient.exe
+ true
+
+
+
+
+ ChatClient.exe
+ true
+
+
+
+
+ ChatClient.rsm
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 1
+
+
+ classes
+ 1
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/ChatDemo/Client/ChatClient.dproj.local b/Demos/TCP/ChatDemo/Client/ChatClient.dproj.local
similarity index 99%
rename from Demos/ChatDemo/Client/ChatClient.dproj.local
rename to Demos/TCP/ChatDemo/Client/ChatClient.dproj.local
index 653451a..aaa2336 100644
--- a/Demos/ChatDemo/Client/ChatClient.dproj.local
+++ b/Demos/TCP/ChatDemo/Client/ChatClient.dproj.local
@@ -1,38 +1,38 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/06/01 10:58:58.000.571,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
- 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/06/01 11:04:17.000.240,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ChatDemoClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
- 2020/08/10 16:11:38.000.249,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatDemoClient.dproj
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/06/01 10:58:58.000.571,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
+ 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/06/01 11:04:17.000.240,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ChatDemoClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
+ 2020/08/10 16:11:38.000.249,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatDemoClient.dproj
+
+
+
+
+
diff --git a/Demos/ChatDemo/Client/ChatClient.dsk b/Demos/TCP/ChatDemo/Client/ChatClient.dsk
similarity index 94%
rename from Demos/ChatDemo/Client/ChatClient.dsk
rename to Demos/TCP/ChatDemo/Client/ChatClient.dsk
index da02916..49298f0 100644
--- a/Demos/ChatDemo/Client/ChatClient.dsk
+++ b/Demos/TCP/ChatDemo/Client/ChatClient.dsk
@@ -1,764 +1,764 @@
-[Closed Files]
-File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,16018,1,16051,0,0,,
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,629,1,644,0,0,,
-File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,475,35,489,0,0,,
-File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncThreads.pas',0,1,17,29,33,0,0,,
-File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\Encryption\ncEncCast256.pas',0,1,401,1,417,0,0,,
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.ScrollBox.pas',0,1,1479,17,1487,0,0,,
-File_6=TSourceModule,'C:\Users\Programmer\Documents\Development\Workspace\AnimationPrototype\ufrmMain.pas',0,1,79,6,87,0,0,,
-File_7=TSourceModule,'C:\Users\Programmer\Documents\Development\Projects\StarFieldSimulation\ufrmMain.pas',0,1,100,1,114,0,0,,{1
-File_8=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.UITypes.pas',0,1,88,15,109,0,0,,
-File_9=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\ufrmMain.pas',0,1,145,1,1,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj]
-ModuleType=TBaseProject
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
-CursorX=3
-CursorY=12
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
-CursorX=7
-CursorY=115
-TopLine=90
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=1
-Breakpoint0='C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',644,'',0,1,'',1,0,0,'',1,'','','',0,''
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=28
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-318
-Top=-363
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,16018,1,16051,0,0,,
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,629,1,644,0,0,,
+File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,475,35,489,0,0,,
+File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncThreads.pas',0,1,17,29,33,0,0,,
+File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\Encryption\ncEncCast256.pas',0,1,401,1,417,0,0,,
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.ScrollBox.pas',0,1,1479,17,1487,0,0,,
+File_6=TSourceModule,'C:\Users\Programmer\Documents\Development\Workspace\AnimationPrototype\ufrmMain.pas',0,1,79,6,87,0,0,,
+File_7=TSourceModule,'C:\Users\Programmer\Documents\Development\Projects\StarFieldSimulation\ufrmMain.pas',0,1,100,1,114,0,0,,{1
+File_8=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.UITypes.pas',0,1,88,15,109,0,0,,
+File_9=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\ufrmMain.pas',0,1,145,1,1,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj]
+ModuleType=TBaseProject
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
+CursorX=3
+CursorY=12
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
+CursorX=7
+CursorY=115
+TopLine=90
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=1
+Breakpoint0='C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',644,'',0,1,'',1,0,0,'',1,'','','',0,''
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=28
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-318
+Top=-363
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/TCP/ChatDemo/Client/ChatClient.identcache b/Demos/TCP/ChatDemo/Client/ChatClient.identcache
new file mode 100644
index 0000000..e4ca886
Binary files /dev/null and b/Demos/TCP/ChatDemo/Client/ChatClient.identcache differ
diff --git a/Demos/TCP/ChatDemo/Client/ChatClient.res b/Demos/TCP/ChatDemo/Client/ChatClient.res
new file mode 100644
index 0000000..2cc0378
Binary files /dev/null and b/Demos/TCP/ChatDemo/Client/ChatClient.res differ
diff --git a/Demos/ChatDemo/Client/ufrmMain.fmx b/Demos/TCP/ChatDemo/Client/ufrmMain.fmx
similarity index 96%
rename from Demos/ChatDemo/Client/ufrmMain.fmx
rename to Demos/TCP/ChatDemo/Client/ufrmMain.fmx
index 07a75e0..d44cb92 100644
--- a/Demos/ChatDemo/Client/ufrmMain.fmx
+++ b/Demos/TCP/ChatDemo/Client/ufrmMain.fmx
@@ -1,126 +1,126 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- ActiveControl = edtText
- Caption = 'Chat Client'
- ClientHeight = 480
- ClientWidth = 640
- Position = ScreenCenter
- FormFactor.Width = 320
- FormFactor.Height = 480
- FormFactor.Devices = [Desktop]
- OnDestroy = FormDestroy
- DesignerMasterStyle = 0
- object memLog: TMemo
- Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
- DataDetectorTypes = []
- ReadOnly = True
- TextSettings.WordWrap = True
- Align = Client
- Margins.Left = 5.000000000000000000
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 630.000000000000000000
- Size.Height = 369.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Viewport.Width = 626.000000000000000000
- Viewport.Height = 365.000000000000000000
- end
- object ltMain: TLayout
- Align = Bottom
- Margins.Left = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Position.X = 5.000000000000000000
- Position.Y = 446.000000000000000000
- Size.Width = 630.000000000000000000
- Size.Height = 29.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 3
- TabStop = False
- object edtText: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Client
- TabOrder = 0
- Margins.Right = 4.000000000000000000
- Size.Width = 546.000000000000000000
- Size.Height = 29.000000000000000000
- Size.PlatformDefault = False
- OnEnter = edtTextEnter
- OnExit = edtTextExit
- end
- object btnSend: TButton
- Align = Right
- Default = True
- Position.X = 550.000000000000000000
- Size.Width = 80.000000000000000000
- Size.Height = 29.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Text = 'Send'
- OnClick = btnSendClick
- end
- end
- object edtClientName: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Bottom
- TabOrder = 2
- Text = 'Happy texter'
- Position.X = 5.000000000000000000
- Position.Y = 419.000000000000000000
- Margins.Left = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 630.000000000000000000
- Size.Height = 22.000000000000000000
- Size.PlatformDefault = False
- TextPrompt = 'Enter your name'
- end
- object ToolBar1: TToolBar
- Size.Width = 640.000000000000000000
- Size.Height = 40.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- TabStop = False
- object btnActivateClient: TButton
- Align = Left
- Margins.Left = 5.000000000000000000
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Position.X = 5.000000000000000000
- Position.Y = 5.000000000000000000
- Size.Width = 137.000000000000000000
- Size.Height = 30.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- Text = 'Activate Client'
- OnClick = btnActivateClientClick
- end
- object edtHost: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Client
- TabOrder = 1
- Text = 'LocalHost'
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 488.000000000000000000
- Size.Height = 30.000000000000000000
- Size.PlatformDefault = False
- OnChange = edtHostChange
- end
- end
- object Client: TncClientSource
- EncryptionKey = 'SetEncryptionKey'
- OnConnected = ClientConnected
- OnDisconnected = ClientDisconnected
- OnHandleCommand = ClientHandleCommand
- Host = 'LocalHost'
- OnReconnected = ClientReconnected
- Left = 32
- Top = 32
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ ActiveControl = edtText
+ Caption = 'Chat Client'
+ ClientHeight = 480
+ ClientWidth = 640
+ Position = ScreenCenter
+ FormFactor.Width = 320
+ FormFactor.Height = 480
+ FormFactor.Devices = [Desktop]
+ OnDestroy = FormDestroy
+ DesignerMasterStyle = 0
+ object memLog: TMemo
+ Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+ DataDetectorTypes = []
+ ReadOnly = True
+ TextSettings.WordWrap = True
+ Align = Client
+ Margins.Left = 5.000000000000000000
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 630.000000000000000000
+ Size.Height = 369.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Viewport.Width = 626.000000000000000000
+ Viewport.Height = 365.000000000000000000
+ end
+ object ltMain: TLayout
+ Align = Bottom
+ Margins.Left = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Position.X = 5.000000000000000000
+ Position.Y = 446.000000000000000000
+ Size.Width = 630.000000000000000000
+ Size.Height = 29.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 3
+ TabStop = False
+ object edtText: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Client
+ TabOrder = 0
+ Margins.Right = 4.000000000000000000
+ Size.Width = 546.000000000000000000
+ Size.Height = 29.000000000000000000
+ Size.PlatformDefault = False
+ OnEnter = edtTextEnter
+ OnExit = edtTextExit
+ end
+ object btnSend: TButton
+ Align = Right
+ Default = True
+ Position.X = 550.000000000000000000
+ Size.Width = 80.000000000000000000
+ Size.Height = 29.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Text = 'Send'
+ OnClick = btnSendClick
+ end
+ end
+ object edtClientName: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Bottom
+ TabOrder = 2
+ Text = 'Happy texter'
+ Position.X = 5.000000000000000000
+ Position.Y = 419.000000000000000000
+ Margins.Left = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 630.000000000000000000
+ Size.Height = 22.000000000000000000
+ Size.PlatformDefault = False
+ TextPrompt = 'Enter your name'
+ end
+ object ToolBar1: TToolBar
+ Size.Width = 640.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ TabStop = False
+ object btnActivateClient: TButton
+ Align = Left
+ Margins.Left = 5.000000000000000000
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Position.X = 5.000000000000000000
+ Position.Y = 5.000000000000000000
+ Size.Width = 137.000000000000000000
+ Size.Height = 30.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ Text = 'Activate Client'
+ OnClick = btnActivateClientClick
+ end
+ object edtHost: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Client
+ TabOrder = 1
+ Text = 'LocalHost'
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 488.000000000000000000
+ Size.Height = 30.000000000000000000
+ Size.PlatformDefault = False
+ OnChange = edtHostChange
+ end
+ end
+ object Client: TncClientSource
+ EncryptionKey = 'SetEncryptionKey'
+ OnConnected = ClientConnected
+ OnDisconnected = ClientDisconnected
+ OnHandleCommand = ClientHandleCommand
+ Host = 'LocalHost'
+ OnReconnected = ClientReconnected
+ Left = 32
+ Top = 32
+ end
+end
diff --git a/Demos/ChatDemo/Client/ufrmMain.pas b/Demos/TCP/ChatDemo/Client/ufrmMain.pas
similarity index 96%
rename from Demos/ChatDemo/Client/ufrmMain.pas
rename to Demos/TCP/ChatDemo/Client/ufrmMain.pas
index fa15358..51ddb1f 100644
--- a/Demos/ChatDemo/Client/ufrmMain.pas
+++ b/Demos/TCP/ChatDemo/Client/ufrmMain.pas
@@ -1,118 +1,118 @@
-unit ufrmMain;
-
-interface
-
-uses
- System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
- FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
- FMX.Edit, FMX.Layouts, FMX.Controls.Presentation, FMX.ScrollBox,
- FMX.Memo, System.SyncObjs, ncSources;
-
-type
- TfrmMain = class(TForm)
- memLog: TMemo;
- ltMain: TLayout;
- edtText: TEdit;
- btnSend: TButton;
- Client: TncClientSource;
- edtClientName: TEdit;
- ToolBar1: TToolBar;
- btnActivateClient: TButton;
- edtHost: TEdit;
- procedure FormDestroy(Sender: TObject);
- procedure btnSendClick(Sender: TObject);
- function ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
- const aSenderComponent, aReceiverComponent: string): TArray;
- procedure edtTextEnter(Sender: TObject);
- procedure edtTextExit(Sender: TObject);
- procedure btnActivateClientClick(Sender: TObject);
- procedure ClientConnected(Sender: TObject; aLine: TncLine);
- procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
- procedure ClientReconnected(Sender: TObject; aLine: TncLine);
- procedure edtHostChange(Sender: TObject);
- private
- public
- procedure Log(aStr: string);
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.fmx}
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- Client.Active := False;
-end;
-
-procedure TfrmMain.Log(aStr: string);
-begin
- // This is thread safe
- TThread.Queue(nil,
- procedure
- begin
- memLog.Lines.Add(aStr);
- memLog.ScrollBy(0, 100);
- end);
-end;
-
-procedure TfrmMain.btnActivateClientClick(Sender: TObject);
-begin
- Client.Active := not Client.Active;
-end;
-
-procedure TfrmMain.btnSendClick(Sender: TObject);
-begin
- Client.ExecCommand(0, BytesOf(edtClientName.Text + ': ' + edtText.Text));
- edtText.Text := '';
-end;
-
-procedure TfrmMain.edtHostChange(Sender: TObject);
-begin
- Client.Host := edtHost.Text;
-end;
-
-procedure TfrmMain.edtTextEnter(Sender: TObject);
-begin
- btnSend.Default := True;
-end;
-
-procedure TfrmMain.edtTextExit(Sender: TObject);
-begin
- btnSend.Default := False;
-end;
-
-procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
-begin
- Log('Client connected to peer: ' + aLine.PeerIP);
- TThread.Queue(nil,
- procedure
- begin
- btnActivateClient.Text := 'Deactivate client';
- end);
-end;
-
-procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
-begin
- Log('Client disconnected from peer: ' + aLine.PeerIP);
- TThread.Queue(nil,
- procedure
- begin
- btnActivateClient.Text := 'Activate client';
- end);
-end;
-
-procedure TfrmMain.ClientReconnected(Sender: TObject; aLine: TncLine);
-begin
- Log('Client was reconnected to peer: ' + aLine.PeerIP);
-end;
-
-function TfrmMain.ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
-const aSenderComponent, aReceiverComponent: string): TArray;
-begin
- Log(Stringof(aData));
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
+ FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
+ FMX.Edit, FMX.Layouts, FMX.Controls.Presentation, FMX.ScrollBox,
+ FMX.Memo, System.SyncObjs, ncSources;
+
+type
+ TfrmMain = class(TForm)
+ memLog: TMemo;
+ ltMain: TLayout;
+ edtText: TEdit;
+ btnSend: TButton;
+ Client: TncClientSource;
+ edtClientName: TEdit;
+ ToolBar1: TToolBar;
+ btnActivateClient: TButton;
+ edtHost: TEdit;
+ procedure FormDestroy(Sender: TObject);
+ procedure btnSendClick(Sender: TObject);
+ function ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+ const aSenderComponent, aReceiverComponent: string): TArray;
+ procedure edtTextEnter(Sender: TObject);
+ procedure edtTextExit(Sender: TObject);
+ procedure btnActivateClientClick(Sender: TObject);
+ procedure ClientConnected(Sender: TObject; aLine: TncLine);
+ procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ClientReconnected(Sender: TObject; aLine: TncLine);
+ procedure edtHostChange(Sender: TObject);
+ private
+ public
+ procedure Log(aStr: string);
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.fmx}
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ Client.Active := False;
+end;
+
+procedure TfrmMain.Log(aStr: string);
+begin
+ // This is thread safe
+ TThread.Queue(nil,
+ procedure
+ begin
+ memLog.Lines.Add(aStr);
+ memLog.ScrollBy(0, 100);
+ end);
+end;
+
+procedure TfrmMain.btnActivateClientClick(Sender: TObject);
+begin
+ Client.Active := not Client.Active;
+end;
+
+procedure TfrmMain.btnSendClick(Sender: TObject);
+begin
+ Client.ExecCommand(0, BytesOf(edtClientName.Text + ': ' + edtText.Text));
+ edtText.Text := '';
+end;
+
+procedure TfrmMain.edtHostChange(Sender: TObject);
+begin
+ Client.Host := edtHost.Text;
+end;
+
+procedure TfrmMain.edtTextEnter(Sender: TObject);
+begin
+ btnSend.Default := True;
+end;
+
+procedure TfrmMain.edtTextExit(Sender: TObject);
+begin
+ btnSend.Default := False;
+end;
+
+procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Client connected to peer: ' + aLine.PeerIP);
+ TThread.Queue(nil,
+ procedure
+ begin
+ btnActivateClient.Text := 'Deactivate client';
+ end);
+end;
+
+procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Client disconnected from peer: ' + aLine.PeerIP);
+ TThread.Queue(nil,
+ procedure
+ begin
+ btnActivateClient.Text := 'Activate client';
+ end);
+end;
+
+procedure TfrmMain.ClientReconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Client was reconnected to peer: ' + aLine.PeerIP);
+end;
+
+function TfrmMain.ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+const aSenderComponent, aReceiverComponent: string): TArray;
+begin
+ Log(Stringof(aData));
+end;
+
+end.
diff --git a/Demos/ChatDemo/Server/ChatServer.dpr b/Demos/TCP/ChatDemo/Server/ChatServer.dpr
similarity index 94%
rename from Demos/ChatDemo/Server/ChatServer.dpr
rename to Demos/TCP/ChatDemo/Server/ChatServer.dpr
index 8d643e1..4bd9fe0 100644
--- a/Demos/ChatDemo/Server/ChatServer.dpr
+++ b/Demos/TCP/ChatDemo/Server/ChatServer.dpr
@@ -1,17 +1,17 @@
-program ChatServer;
-
-uses
- System.StartUpCopy,
- FMX.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain};
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program ChatServer;
+
+uses
+ System.StartUpCopy,
+ FMX.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/ChatDemo/Server/ChatServer.dproj b/Demos/TCP/ChatDemo/Server/ChatServer.dproj
similarity index 98%
rename from Demos/ChatDemo/Server/ChatServer.dproj
rename to Demos/TCP/ChatDemo/Server/ChatServer.dproj
index fa2d0cb..50ccec4 100644
--- a/Demos/ChatDemo/Server/ChatServer.dproj
+++ b/Demos/TCP/ChatDemo/Server/ChatServer.dproj
@@ -1,1081 +1,1081 @@
-
-
- {FEC7E51C-DA51-43D3-A01B-067E5466B16D}
- 18.8
- FMX
- ChatServer.dpr
- True
- Release
- Win64
- 32787
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- true
- true
- true
- true
- true
- true
- true
- true
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\delphi_PROJECTICNS.icns
- ChatServer
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
- true
- 1033
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
- fmx
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- ChatServer.dpr
-
-
- Microsoft Office 2000 Sample Automation Server Wrapper Components
-
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- ChatServer.exe
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- True
- True
-
-
- 12
-
-
-
-
-
+
+
+ {FEC7E51C-DA51-43D3-A01B-067E5466B16D}
+ 18.8
+ FMX
+ ChatServer.dpr
+ True
+ Release
+ Win64
+ 32787
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ ChatServer
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+ true
+ 1033
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ fmx
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ ChatServer.dpr
+
+
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ ChatServer.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 1
+
+
+ classes
+ 1
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/ChatDemo/Server/ChatServer.dproj.local b/Demos/TCP/ChatDemo/Server/ChatServer.dproj.local
similarity index 99%
rename from Demos/ChatDemo/Server/ChatServer.dproj.local
rename to Demos/TCP/ChatDemo/Server/ChatServer.dproj.local
index 3b18226..a02cd12 100644
--- a/Demos/ChatDemo/Server/ChatServer.dproj.local
+++ b/Demos/TCP/ChatDemo/Server/ChatServer.dproj.local
@@ -1,44 +1,44 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/10 12:55:10.000.953,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/10 12:57:08.000.980,C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.fmx
- 2020/08/10 12:57:08.000.980,C:\Users\Programmer\Documents\Development\Projects\Unit3.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
- 2020/08/10 12:57:13.000.964,C:\Users\Programmer\Documents\Development\Projects\Project1.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dproj
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/10 12:55:10.000.953,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/10 12:57:08.000.980,C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.fmx
+ 2020/08/10 12:57:08.000.980,C:\Users\Programmer\Documents\Development\Projects\Unit3.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
+ 2020/08/10 12:57:13.000.964,C:\Users\Programmer\Documents\Development\Projects\Project1.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dproj
+
+
+
+
+
diff --git a/Demos/ChatDemo/Server/ChatServer.dsk b/Demos/TCP/ChatDemo/Server/ChatServer.dsk
similarity index 94%
rename from Demos/ChatDemo/Server/ChatServer.dsk
rename to Demos/TCP/ChatDemo/Server/ChatServer.dsk
index c484e80..44fd6e3 100644
--- a/Demos/ChatDemo/Server/ChatServer.dsk
+++ b/Demos/TCP/ChatDemo/Server/ChatServer.dsk
@@ -1,763 +1,763 @@
-[Closed Files]
-File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,889,1,891,0,0,,
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,1270,42,1296,0,0,,{1
-File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,104,64,117,0,0,,
-File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncCommandHandlers.pas',0,1,22,38,37,0,0,,
-File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncDBSrv.pas',0,1,121,71,132,0,0,,
-File_5=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncDBCnt.pas',0,1,137,47,142,0,0,,
-File_6=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSocketList.pas',0,1,286,41,301,0,0,,
-File_7=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncCommandPacking.pas',0,1,1,7,14,0,0,,
-File_8=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\NetComRegister.pas',0,1,5,1,37,0,0,,
-File_9=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,2670,10,2686,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dproj
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dproj]
-ModuleType=TBaseProject
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dpr
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dpr
-CursorX=3
-CursorY=12
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
-CursorX=9
-CursorY=45
-TopLine=29
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=28
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-318
-Top=-363
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,889,1,891,0,0,,
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,1270,42,1296,0,0,,{1
+File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,104,64,117,0,0,,
+File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncCommandHandlers.pas',0,1,22,38,37,0,0,,
+File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncDBSrv.pas',0,1,121,71,132,0,0,,
+File_5=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncDBCnt.pas',0,1,137,47,142,0,0,,
+File_6=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSocketList.pas',0,1,286,41,301,0,0,,
+File_7=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncCommandPacking.pas',0,1,1,7,14,0,0,,
+File_8=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\NetComRegister.pas',0,1,5,1,37,0,0,,
+File_9=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,2670,10,2686,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dproj
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dproj]
+ModuleType=TBaseProject
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dpr
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dpr
+CursorX=3
+CursorY=12
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ChatServer.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
+CursorX=9
+CursorY=45
+TopLine=29
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Server\ufrmMain.pas
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=28
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-318
+Top=-363
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/TCP/ChatDemo/Server/ChatServer.identcache b/Demos/TCP/ChatDemo/Server/ChatServer.identcache
new file mode 100644
index 0000000..ada193f
Binary files /dev/null and b/Demos/TCP/ChatDemo/Server/ChatServer.identcache differ
diff --git a/Demos/TCP/ChatDemo/Server/ChatServer.res b/Demos/TCP/ChatDemo/Server/ChatServer.res
new file mode 100644
index 0000000..f0a2763
Binary files /dev/null and b/Demos/TCP/ChatDemo/Server/ChatServer.res differ
diff --git a/Demos/ChatDemo/Server/ufrmMain.fmx b/Demos/TCP/ChatDemo/Server/ufrmMain.fmx
similarity index 96%
rename from Demos/ChatDemo/Server/ufrmMain.fmx
rename to Demos/TCP/ChatDemo/Server/ufrmMain.fmx
index 35a8851..a1085ba 100644
--- a/Demos/ChatDemo/Server/ufrmMain.fmx
+++ b/Demos/TCP/ChatDemo/Server/ufrmMain.fmx
@@ -1,71 +1,71 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'Chat Server'
- ClientHeight = 339
- ClientWidth = 583
- FormFactor.Width = 320
- FormFactor.Height = 480
- FormFactor.Devices = [Desktop]
- OnDestroy = FormDestroy
- DesignerMasterStyle = 0
- object memLog: TMemo
- Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
- DataDetectorTypes = []
- ReadOnly = True
- Align = Client
- Margins.Left = 5.000000000000000000
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 573.000000000000000000
- Size.Height = 289.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Viewport.Width = 569.000000000000000000
- Viewport.Height = 285.000000000000000000
- end
- object ToolBar1: TToolBar
- Size.Width = 583.000000000000000000
- Size.Height = 40.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- TabStop = False
- object btnActivateServer: TButton
- Align = Left
- Margins.Left = 5.000000000000000000
- Margins.Top = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Position.X = 5.000000000000000000
- Position.Y = 5.000000000000000000
- Size.Width = 137.000000000000000000
- Size.Height = 30.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- Text = 'Activate Server'
- OnClick = btnActivateServerClick
- end
- object btnShutDownClients: TButton
- Align = Right
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Position.X = 424.000000000000000000
- Position.Y = 5.000000000000000000
- Size.Width = 154.000000000000000000
- Size.Height = 30.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 2
- Text = 'Shutdown Clients'
- OnClick = btnShutDownClientsClick
- end
- end
- object Server: TncServerSource
- EncryptionKey = 'SetEncryptionKey'
- OnConnected = ServerConnected
- OnDisconnected = ServerDisconnected
- OnHandleCommand = ServerHandleCommand
- Left = 32
- Top = 32
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ Caption = 'Chat Server'
+ ClientHeight = 339
+ ClientWidth = 583
+ FormFactor.Width = 320
+ FormFactor.Height = 480
+ FormFactor.Devices = [Desktop]
+ OnDestroy = FormDestroy
+ DesignerMasterStyle = 0
+ object memLog: TMemo
+ Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+ DataDetectorTypes = []
+ ReadOnly = True
+ Align = Client
+ Margins.Left = 5.000000000000000000
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 573.000000000000000000
+ Size.Height = 289.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Viewport.Width = 569.000000000000000000
+ Viewport.Height = 285.000000000000000000
+ end
+ object ToolBar1: TToolBar
+ Size.Width = 583.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ TabStop = False
+ object btnActivateServer: TButton
+ Align = Left
+ Margins.Left = 5.000000000000000000
+ Margins.Top = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Position.X = 5.000000000000000000
+ Position.Y = 5.000000000000000000
+ Size.Width = 137.000000000000000000
+ Size.Height = 30.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ Text = 'Activate Server'
+ OnClick = btnActivateServerClick
+ end
+ object btnShutDownClients: TButton
+ Align = Right
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Position.X = 424.000000000000000000
+ Position.Y = 5.000000000000000000
+ Size.Width = 154.000000000000000000
+ Size.Height = 30.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 2
+ Text = 'Shutdown Clients'
+ OnClick = btnShutDownClientsClick
+ end
+ end
+ object Server: TncServerSource
+ EncryptionKey = 'SetEncryptionKey'
+ OnConnected = ServerConnected
+ OnDisconnected = ServerDisconnected
+ OnHandleCommand = ServerHandleCommand
+ Left = 32
+ Top = 32
+ end
+end
diff --git a/Demos/ChatDemo/Server/ufrmMain.pas b/Demos/TCP/ChatDemo/Server/ufrmMain.pas
similarity index 96%
rename from Demos/ChatDemo/Server/ufrmMain.pas
rename to Demos/TCP/ChatDemo/Server/ufrmMain.pas
index aa2ed06..da4a6c8 100644
--- a/Demos/ChatDemo/Server/ufrmMain.pas
+++ b/Demos/TCP/ChatDemo/Server/ufrmMain.pas
@@ -1,118 +1,118 @@
-unit ufrmMain;
-
-interface
-
-uses
- System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
- FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
- FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
- System.SyncObjs, ncSocketList, ncSources;
-
-type
- TfrmMain = class(TForm)
- Server: TncServerSource;
- memLog: TMemo;
- ToolBar1: TToolBar;
- btnActivateServer: TButton;
- btnShutDownClients: TButton;
- procedure FormDestroy(Sender: TObject);
- function ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
- const aSenderComponent, aReceiverComponent: string): TArray;
- procedure ServerConnected(Sender: TObject; aLine: TncLine);
- procedure ServerDisconnected(Sender: TObject; aLine: TncLine);
- procedure btnActivateServerClick(Sender: TObject);
- procedure btnShutDownClientsClick(Sender: TObject);
- private
- public
- procedure Log(aStr: string);
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.fmx}
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- Server.Active := False;
-end;
-
-procedure TfrmMain.Log(aStr: string);
-begin
- // This is thread safe
- TThread.Queue(nil,
- procedure
- begin
- memLog.Lines.Add(aStr);
- memLog.ScrollBy(0, 100);
- end);
-end;
-
-procedure TfrmMain.btnActivateServerClick(Sender: TObject);
-begin
- try
- Server.Active := not Server.Active;
- finally
- if Server.Active then
- begin
- btnActivateServer.Text := 'Deactivate Server';
- Log('Server is activated');
- end
- else
- begin
- btnActivateServer.Text := 'Activate Server';
- Log('Server was deactivated');
- end;
- end;
-end;
-
-procedure TfrmMain.ServerConnected(Sender: TObject; aLine: TncLine);
-begin
- Log('Client connected: ' + aLine.PeerIP);
-end;
-
-procedure TfrmMain.ServerDisconnected(Sender: TObject; aLine: TncLine);
-begin
- Log('Client disconnected: ' + aLine.PeerIP);
-end;
-
-function TfrmMain.ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
-const aSenderComponent, aReceiverComponent: string): TArray;
-var
- Clients: TSocketList;
- i: Integer;
-begin
- Log('Received: "' + StringOf(aData) + '" from peer: ' + aLine.PeerIP);
-
- // Now send this to all clients
- Clients := Server.Lines.LockList;
- try
- for i := 0 to Clients.Count - 1 do
- // if Clients.Lines[i] <> aLine then // If you do not want to send text back to original client
- Server.ExecCommand(Clients.Lines[i], 0, aData, False);
-
- // You can shutdown a line here by calling Server.ShutdownLine,
- // see following procecure
- finally
- Server.Lines.UnlockList;
- end;
-end;
-
-procedure TfrmMain.btnShutDownClientsClick(Sender: TObject);
-var
- Clients: TSocketList;
- i: Integer;
-begin
- Clients := Server.Lines.LockList;
- try
- for i := 0 to Clients.Count - 1 do
- Server.ShutDownLine(Clients.Lines[i]);
- finally
- Server.Lines.UnlockList;
- end;
-
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
+ FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
+ FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
+ System.SyncObjs, ncSocketList, ncSources;
+
+type
+ TfrmMain = class(TForm)
+ Server: TncServerSource;
+ memLog: TMemo;
+ ToolBar1: TToolBar;
+ btnActivateServer: TButton;
+ btnShutDownClients: TButton;
+ procedure FormDestroy(Sender: TObject);
+ function ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+ const aSenderComponent, aReceiverComponent: string): TArray;
+ procedure ServerConnected(Sender: TObject; aLine: TncLine);
+ procedure ServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure btnActivateServerClick(Sender: TObject);
+ procedure btnShutDownClientsClick(Sender: TObject);
+ private
+ public
+ procedure Log(aStr: string);
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.fmx}
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ Server.Active := False;
+end;
+
+procedure TfrmMain.Log(aStr: string);
+begin
+ // This is thread safe
+ TThread.Queue(nil,
+ procedure
+ begin
+ memLog.Lines.Add(aStr);
+ memLog.ScrollBy(0, 100);
+ end);
+end;
+
+procedure TfrmMain.btnActivateServerClick(Sender: TObject);
+begin
+ try
+ Server.Active := not Server.Active;
+ finally
+ if Server.Active then
+ begin
+ btnActivateServer.Text := 'Deactivate Server';
+ Log('Server is activated');
+ end
+ else
+ begin
+ btnActivateServer.Text := 'Activate Server';
+ Log('Server was deactivated');
+ end;
+ end;
+end;
+
+procedure TfrmMain.ServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Client connected: ' + aLine.PeerIP);
+end;
+
+procedure TfrmMain.ServerDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Client disconnected: ' + aLine.PeerIP);
+end;
+
+function TfrmMain.ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+const aSenderComponent, aReceiverComponent: string): TArray;
+var
+ Clients: TSocketList;
+ i: Integer;
+begin
+ Log('Received: "' + StringOf(aData) + '" from peer: ' + aLine.PeerIP);
+
+ // Now send this to all clients
+ Clients := Server.Lines.LockList;
+ try
+ for i := 0 to Clients.Count - 1 do
+ // if Clients.Lines[i] <> aLine then // If you do not want to send text back to original client
+ Server.ExecCommand(Clients.Lines[i], 0, aData, False);
+
+ // You can shutdown a line here by calling Server.ShutdownLine,
+ // see following procecure
+ finally
+ Server.Lines.UnlockList;
+ end;
+end;
+
+procedure TfrmMain.btnShutDownClientsClick(Sender: TObject);
+var
+ Clients: TSocketList;
+ i: Integer;
+begin
+ Clients := Server.Lines.LockList;
+ try
+ for i := 0 to Clients.Count - 1 do
+ Server.ShutDownLine(Clients.Lines[i]);
+ finally
+ Server.Lines.UnlockList;
+ end;
+
+end;
+
+end.
diff --git a/Demos/DB/ChatDemo/Client/ChatClient.dpr b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dpr
similarity index 94%
rename from Demos/DB/ChatDemo/Client/ChatClient.dpr
rename to Demos/TCP/DB/ChatDemo/Client/ChatClient.dpr
index 8c41207..2f85b6a 100644
--- a/Demos/DB/ChatDemo/Client/ChatClient.dpr
+++ b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dpr
@@ -1,17 +1,17 @@
-program ChatClient;
-
-uses
- System.StartUpCopy,
- FMX.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain};
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program ChatClient;
+
+uses
+ System.StartUpCopy,
+ FMX.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/DB/ChatDemo/Client/ChatClient.dproj b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dproj
similarity index 98%
rename from Demos/DB/ChatDemo/Client/ChatClient.dproj
rename to Demos/TCP/DB/ChatDemo/Client/ChatClient.dproj
index 41b7fa4..e16bdba 100644
--- a/Demos/DB/ChatDemo/Client/ChatClient.dproj
+++ b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dproj
@@ -1,1097 +1,1097 @@
-
-
- {E615DFF5-615F-4A51-B6AF-B5B187237486}
- 18.8
- FMX
- ChatClient.dpr
- True
- Debug
- Win64
- 32787
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- true
- true
- true
- true
- true
- true
- true
- true
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\delphi_PROJECTICNS.icns
- ChatClient
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
- 1
- #000000
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
- 1
- #000000
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
- true
- 1033
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
- fmx
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- ChatClient.dpr
-
-
- Microsoft Office 2000 Sample Automation Server Wrapper Components
-
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- ChatClient.exe
- true
-
-
-
-
- ChatClient.exe
- true
-
-
-
-
- ChatClient.rsm
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- True
- True
-
-
- 12
-
-
-
-
-
+
+
+ {E615DFF5-615F-4A51-B6AF-B5B187237486}
+ 18.8
+ FMX
+ ChatClient.dpr
+ True
+ Debug
+ Win64
+ 32787
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ ChatClient
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ 1
+ #000000
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ 1
+ #000000
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+ true
+ 1033
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ fmx
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ ChatClient.dpr
+
+
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ ChatClient.exe
+ true
+
+
+
+
+ ChatClient.exe
+ true
+
+
+
+
+ ChatClient.rsm
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 1
+
+
+ classes
+ 1
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/DB/ChatDemo/Client/ChatClient.dproj.local b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dproj.local
similarity index 99%
rename from Demos/DB/ChatDemo/Client/ChatClient.dproj.local
rename to Demos/TCP/DB/ChatDemo/Client/ChatClient.dproj.local
index e8d19a3..a8cb9ab 100644
--- a/Demos/DB/ChatDemo/Client/ChatClient.dproj.local
+++ b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dproj.local
@@ -1,38 +1,38 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/06/01 10:58:58.000.571,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
- 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/06/01 11:04:17.000.240,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ChatDemoClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
- 2020/08/10 16:11:38.249,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatDemoClient.dproj
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/06/01 10:58:58.000.571,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
+ 2020/06/01 11:04:10.000.068,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/06/01 11:04:17.000.240,C:\Users\Programmer\Documents\Development\Projects\ChatDemo\Client\ChatDemoClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
+ 2020/08/10 16:11:38.249,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatDemoClient.dproj
+
+
+
+
+
diff --git a/Demos/DB/ChatDemo/Client/ChatClient.dsk b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dsk
similarity index 94%
rename from Demos/DB/ChatDemo/Client/ChatClient.dsk
rename to Demos/TCP/DB/ChatDemo/Client/ChatClient.dsk
index a8a4502..182168d 100644
--- a/Demos/DB/ChatDemo/Client/ChatClient.dsk
+++ b/Demos/TCP/DB/ChatDemo/Client/ChatClient.dsk
@@ -1,762 +1,762 @@
-[Closed Files]
-File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.ScrollBox.pas',0,1,1479,17,1487,0,0,,
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Workspace\AnimationPrototype\ufrmMain.pas',0,1,79,6,87,0,0,,
-File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Projects\StarFieldSimulation\ufrmMain.pas',0,1,100,1,114,0,0,,{1
-File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.UITypes.pas',0,1,88,15,109,0,0,,
-File_4=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\ufrmMain.pas',0,1,145,1,1,0,0,,
-File_5=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\udmResources.pas',0,1,1,1,1,0,0,,
-File_6=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\udmMain.pas',0,1,46,1,1,0,0,,
-File_7=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\uComponents.pas',0,1,1,1,1,0,0,,
-File_8=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\u3DScene.pas',0,1,46,1,1,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj]
-ModuleType=TBaseProject
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
-CursorX=11
-CursorY=13
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatDemoClient.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
-CursorX=1
-CursorY=126
-TopLine=86
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-240
-Top=-285
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.ScrollBox.pas',0,1,1479,17,1487,0,0,,
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Workspace\AnimationPrototype\ufrmMain.pas',0,1,79,6,87,0,0,,
+File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Projects\StarFieldSimulation\ufrmMain.pas',0,1,100,1,114,0,0,,{1
+File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.UITypes.pas',0,1,88,15,109,0,0,,
+File_4=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\ufrmMain.pas',0,1,145,1,1,0,0,,
+File_5=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\udmResources.pas',0,1,1,1,1,0,0,,
+File_6=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\udmMain.pas',0,1,46,1,1,0,0,,
+File_7=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\uComponents.pas',0,1,1,1,1,0,0,,
+File_8=TSourceModule,'E:\Users\Bill\Desktop\RAD Studio\Projects\Roulette\u3DScene.pas',0,1,46,1,1,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dproj]
+ModuleType=TBaseProject
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatClient.dpr
+CursorX=11
+CursorY=13
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ChatDemoClient.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\ChatDemo\Client\ufrmMain.pas
+CursorX=1
+CursorY=126
+TopLine=86
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-240
+Top=-285
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/ChatDemo/Client/ChatClient.identcache b/Demos/TCP/DB/ChatDemo/Client/ChatClient.identcache
similarity index 100%
rename from Demos/ChatDemo/Client/ChatClient.identcache
rename to Demos/TCP/DB/ChatDemo/Client/ChatClient.identcache
diff --git a/Demos/ChatDemo/Client/ChatClient.res b/Demos/TCP/DB/ChatDemo/Client/ChatClient.res
similarity index 100%
rename from Demos/ChatDemo/Client/ChatClient.res
rename to Demos/TCP/DB/ChatDemo/Client/ChatClient.res
diff --git a/Demos/DB/ChatDemo/Client/Initial.txt b/Demos/TCP/DB/ChatDemo/Client/Initial.txt
similarity index 100%
rename from Demos/DB/ChatDemo/Client/Initial.txt
rename to Demos/TCP/DB/ChatDemo/Client/Initial.txt
diff --git a/Demos/DB/ChatDemo/Client/ufrmMain.fmx b/Demos/TCP/DB/ChatDemo/Client/ufrmMain.fmx
similarity index 96%
rename from Demos/DB/ChatDemo/Client/ufrmMain.fmx
rename to Demos/TCP/DB/ChatDemo/Client/ufrmMain.fmx
index b12e2ad..7566752 100644
--- a/Demos/DB/ChatDemo/Client/ufrmMain.fmx
+++ b/Demos/TCP/DB/ChatDemo/Client/ufrmMain.fmx
@@ -1,133 +1,133 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- ActiveControl = edtText
- Caption = 'Chat Client'
- ClientHeight = 480
- ClientWidth = 640
- Position = ScreenCenter
- FormFactor.Width = 320
- FormFactor.Height = 480
- FormFactor.Devices = [Desktop]
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- DesignerMasterStyle = 0
- object memLog: TMemo
- Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
- DataDetectorTypes = []
- ReadOnly = True
- TextSettings.WordWrap = True
- Align = Client
- Margins.Left = 5.000000000000000000
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 630.000000000000000000
- Size.Height = 369.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Viewport.Width = 626.000000000000000000
- Viewport.Height = 365.000000000000000000
- end
- object ltMain: TLayout
- Align = Bottom
- Margins.Left = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Position.X = 5.000000000000000000
- Position.Y = 446.000000000000000000
- Size.Width = 630.000000000000000000
- Size.Height = 29.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 3
- TabStop = False
- object edtText: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Client
- TabOrder = 0
- Margins.Right = 4.000000000000000000
- Size.Width = 546.000000000000000000
- Size.Height = 29.000000000000000000
- Size.PlatformDefault = False
- OnEnter = edtTextEnter
- OnExit = edtTextExit
- end
- object btnSend: TButton
- Align = Right
- Default = True
- Position.X = 550.000000000000000000
- Size.Width = 80.000000000000000000
- Size.Height = 29.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Text = 'Send'
- OnClick = btnSendClick
- end
- end
- object edtClientName: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Bottom
- TabOrder = 2
- Text = 'Happy texter'
- Position.X = 5.000000000000000000
- Position.Y = 419.000000000000000000
- Margins.Left = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 630.000000000000000000
- Size.Height = 22.000000000000000000
- Size.PlatformDefault = False
- TextPrompt = 'Enter your name'
- end
- object tmrUpdateLog: TTimer
- Interval = 1
- OnTimer = tmrUpdateLogTimer
- Left = 96
- Top = 32
- end
- object ToolBar1: TToolBar
- Size.Width = 640.000000000000000000
- Size.Height = 40.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- TabStop = False
- object btnActivateClient: TButton
- Align = Left
- Margins.Left = 5.000000000000000000
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Position.X = 5.000000000000000000
- Position.Y = 5.000000000000000000
- Size.Width = 137.000000000000000000
- Size.Height = 30.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- Text = 'Activate Client'
- OnClick = btnActivateClientClick
- end
- object edtHost: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Client
- TabOrder = 1
- Text = 'LocalHost'
- Margins.Top = 5.000000000000000000
- Margins.Right = 5.000000000000000000
- Margins.Bottom = 5.000000000000000000
- Size.Width = 488.000000000000000000
- Size.Height = 30.000000000000000000
- Size.PlatformDefault = False
- OnChange = edtHostChange
- end
- end
- object Client: TncClientSource
- EncryptionKey = 'SetEncryptionKey'
- OnConnected = ClientConnected
- OnDisconnected = ClientDisconnected
- OnHandleCommand = ClientHandleCommand
- Host = 'LocalHost'
- OnReconnected = ClientReconnected
- Left = 32
- Top = 32
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ ActiveControl = edtText
+ Caption = 'Chat Client'
+ ClientHeight = 480
+ ClientWidth = 640
+ Position = ScreenCenter
+ FormFactor.Width = 320
+ FormFactor.Height = 480
+ FormFactor.Devices = [Desktop]
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ DesignerMasterStyle = 0
+ object memLog: TMemo
+ Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+ DataDetectorTypes = []
+ ReadOnly = True
+ TextSettings.WordWrap = True
+ Align = Client
+ Margins.Left = 5.000000000000000000
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 630.000000000000000000
+ Size.Height = 369.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Viewport.Width = 626.000000000000000000
+ Viewport.Height = 365.000000000000000000
+ end
+ object ltMain: TLayout
+ Align = Bottom
+ Margins.Left = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Position.X = 5.000000000000000000
+ Position.Y = 446.000000000000000000
+ Size.Width = 630.000000000000000000
+ Size.Height = 29.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 3
+ TabStop = False
+ object edtText: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Client
+ TabOrder = 0
+ Margins.Right = 4.000000000000000000
+ Size.Width = 546.000000000000000000
+ Size.Height = 29.000000000000000000
+ Size.PlatformDefault = False
+ OnEnter = edtTextEnter
+ OnExit = edtTextExit
+ end
+ object btnSend: TButton
+ Align = Right
+ Default = True
+ Position.X = 550.000000000000000000
+ Size.Width = 80.000000000000000000
+ Size.Height = 29.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Text = 'Send'
+ OnClick = btnSendClick
+ end
+ end
+ object edtClientName: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Bottom
+ TabOrder = 2
+ Text = 'Happy texter'
+ Position.X = 5.000000000000000000
+ Position.Y = 419.000000000000000000
+ Margins.Left = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 630.000000000000000000
+ Size.Height = 22.000000000000000000
+ Size.PlatformDefault = False
+ TextPrompt = 'Enter your name'
+ end
+ object tmrUpdateLog: TTimer
+ Interval = 1
+ OnTimer = tmrUpdateLogTimer
+ Left = 96
+ Top = 32
+ end
+ object ToolBar1: TToolBar
+ Size.Width = 640.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ TabStop = False
+ object btnActivateClient: TButton
+ Align = Left
+ Margins.Left = 5.000000000000000000
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Position.X = 5.000000000000000000
+ Position.Y = 5.000000000000000000
+ Size.Width = 137.000000000000000000
+ Size.Height = 30.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ Text = 'Activate Client'
+ OnClick = btnActivateClientClick
+ end
+ object edtHost: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Client
+ TabOrder = 1
+ Text = 'LocalHost'
+ Margins.Top = 5.000000000000000000
+ Margins.Right = 5.000000000000000000
+ Margins.Bottom = 5.000000000000000000
+ Size.Width = 488.000000000000000000
+ Size.Height = 30.000000000000000000
+ Size.PlatformDefault = False
+ OnChange = edtHostChange
+ end
+ end
+ object Client: TncClientSource
+ EncryptionKey = 'SetEncryptionKey'
+ OnConnected = ClientConnected
+ OnDisconnected = ClientDisconnected
+ OnHandleCommand = ClientHandleCommand
+ Host = 'LocalHost'
+ OnReconnected = ClientReconnected
+ Left = 32
+ Top = 32
+ end
+end
diff --git a/Demos/DB/ChatDemo/Client/ufrmMain.pas b/Demos/TCP/DB/ChatDemo/Client/ufrmMain.pas
similarity index 96%
rename from Demos/DB/ChatDemo/Client/ufrmMain.pas
rename to Demos/TCP/DB/ChatDemo/Client/ufrmMain.pas
index 6536c2b..0bd12ea 100644
--- a/Demos/DB/ChatDemo/Client/ufrmMain.pas
+++ b/Demos/TCP/DB/ChatDemo/Client/ufrmMain.pas
@@ -1,158 +1,158 @@
-unit ufrmMain;
-
-interface
-
-uses
- System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
- FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
- FMX.Edit, FMX.Layouts, FMX.Controls.Presentation, FMX.ScrollBox,
- FMX.Memo, System.SyncObjs, ncSources;
-
-type
- TfrmMain = class(TForm)
- memLog: TMemo;
- ltMain: TLayout;
- edtText: TEdit;
- btnSend: TButton;
- Client: TncClientSource;
- tmrUpdateLog: TTimer;
- edtClientName: TEdit;
- ToolBar1: TToolBar;
- btnActivateClient: TButton;
- edtHost: TEdit;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure btnSendClick(Sender: TObject);
- procedure tmrUpdateLogTimer(Sender: TObject);
- function ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer;
- const aData: TArray; aRequiresResult: Boolean;
- const aSenderComponent, aReceiverComponent: string): TArray;
- procedure edtTextEnter(Sender: TObject);
- procedure edtTextExit(Sender: TObject);
- procedure btnActivateClientClick(Sender: TObject);
- procedure ClientConnected(Sender: TObject; aLine: TncLine);
- procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
- procedure ClientReconnected(Sender: TObject; aLine: TncLine);
- procedure edtHostChange(Sender: TObject);
- private
- LogLock: TCriticalSection;
- LogLines, LogLinesCopy: TStringList;
- public
- procedure Log(aStr: string);
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.fmx}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- LogLock := TCriticalSection.Create;
- LogLines := TStringList.Create;
- LogLinesCopy := TStringList.Create;
-end;
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- Client.Active := False;
-
- LogLinesCopy.Free;
- LogLines.Free;
- LogLock.Free;
-end;
-
-procedure TfrmMain.Log(aStr: string);
-begin
- // This is thread safe
- LogLock.Acquire;
- try
- LogLines.Add (aStr);
- finally
- LogLock.Release;
- end;
-end;
-
-procedure TfrmMain.tmrUpdateLogTimer(Sender: TObject);
-var
- i: Integer;
-begin
- // Update the memLog from LogLines
- LogLock.Acquire;
- try
- LogLinesCopy.Assign(LogLines);
- LogLines.Clear;
- finally
- LogLock.Release;
- end;
-
- for i := 0 to LogLinesCopy.Count - 1 do
- begin
- memLog.Lines.Add(LogLinesCopy.Strings[i]);
- memLog.SelStart := Length(memLog.Text);
- end;
- LogLinesCopy.Clear;
-end;
-
-procedure TfrmMain.btnActivateClientClick(Sender: TObject);
-begin
- Client.Active := not Client.Active;
-end;
-
-procedure TfrmMain.btnSendClick(Sender: TObject);
-begin
- Client.ExecCommand(0, BytesOf (edtClientName.Text + ': ' + edtText.Text));
- edtText.Text := '';
-end;
-
-procedure TfrmMain.edtHostChange(Sender: TObject);
-begin
- if not Client.Active then
- Client.Host := edtHost.Text;
-end;
-
-procedure TfrmMain.edtTextEnter(Sender: TObject);
-begin
- btnSend.Default := True;
-end;
-
-procedure TfrmMain.edtTextExit(Sender: TObject);
-begin
- btnSend.Default := False;
-end;
-
-procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
-begin
- Log ('Client connected to peer: ' + aLine.PeerIP);
- TThread.Synchronize(nil,
- procedure
- begin
- btnActivateClient.Text := 'Deactivate client';
- end);
-end;
-
-procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
-begin
- Log ('Client disconnected from peer: ' + aLine.PeerIP);
- TThread.Synchronize(nil,
- procedure
- begin
- btnActivateClient.Text := 'Activate client';
- end);
-end;
-
-procedure TfrmMain.ClientReconnected(Sender: TObject; aLine: TncLine);
-begin
- Log ('Client was reconnected to peer: ' + aLine.PeerIP);
-end;
-
-function TfrmMain.ClientHandleCommand(Sender: TObject; aLine: TncLine;
- aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
- const aSenderComponent, aReceiverComponent: string): TArray;
-begin
- Log (Stringof (aData));
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
+ FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
+ FMX.Edit, FMX.Layouts, FMX.Controls.Presentation, FMX.ScrollBox,
+ FMX.Memo, System.SyncObjs, ncSources;
+
+type
+ TfrmMain = class(TForm)
+ memLog: TMemo;
+ ltMain: TLayout;
+ edtText: TEdit;
+ btnSend: TButton;
+ Client: TncClientSource;
+ tmrUpdateLog: TTimer;
+ edtClientName: TEdit;
+ ToolBar1: TToolBar;
+ btnActivateClient: TButton;
+ edtHost: TEdit;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnSendClick(Sender: TObject);
+ procedure tmrUpdateLogTimer(Sender: TObject);
+ function ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer;
+ const aData: TArray; aRequiresResult: Boolean;
+ const aSenderComponent, aReceiverComponent: string): TArray;
+ procedure edtTextEnter(Sender: TObject);
+ procedure edtTextExit(Sender: TObject);
+ procedure btnActivateClientClick(Sender: TObject);
+ procedure ClientConnected(Sender: TObject; aLine: TncLine);
+ procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ClientReconnected(Sender: TObject; aLine: TncLine);
+ procedure edtHostChange(Sender: TObject);
+ private
+ LogLock: TCriticalSection;
+ LogLines, LogLinesCopy: TStringList;
+ public
+ procedure Log(aStr: string);
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.fmx}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ LogLock := TCriticalSection.Create;
+ LogLines := TStringList.Create;
+ LogLinesCopy := TStringList.Create;
+end;
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ Client.Active := False;
+
+ LogLinesCopy.Free;
+ LogLines.Free;
+ LogLock.Free;
+end;
+
+procedure TfrmMain.Log(aStr: string);
+begin
+ // This is thread safe
+ LogLock.Acquire;
+ try
+ LogLines.Add (aStr);
+ finally
+ LogLock.Release;
+ end;
+end;
+
+procedure TfrmMain.tmrUpdateLogTimer(Sender: TObject);
+var
+ i: Integer;
+begin
+ // Update the memLog from LogLines
+ LogLock.Acquire;
+ try
+ LogLinesCopy.Assign(LogLines);
+ LogLines.Clear;
+ finally
+ LogLock.Release;
+ end;
+
+ for i := 0 to LogLinesCopy.Count - 1 do
+ begin
+ memLog.Lines.Add(LogLinesCopy.Strings[i]);
+ memLog.SelStart := Length(memLog.Text);
+ end;
+ LogLinesCopy.Clear;
+end;
+
+procedure TfrmMain.btnActivateClientClick(Sender: TObject);
+begin
+ Client.Active := not Client.Active;
+end;
+
+procedure TfrmMain.btnSendClick(Sender: TObject);
+begin
+ Client.ExecCommand(0, BytesOf (edtClientName.Text + ': ' + edtText.Text));
+ edtText.Text := '';
+end;
+
+procedure TfrmMain.edtHostChange(Sender: TObject);
+begin
+ if not Client.Active then
+ Client.Host := edtHost.Text;
+end;
+
+procedure TfrmMain.edtTextEnter(Sender: TObject);
+begin
+ btnSend.Default := True;
+end;
+
+procedure TfrmMain.edtTextExit(Sender: TObject);
+begin
+ btnSend.Default := False;
+end;
+
+procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ Log ('Client connected to peer: ' + aLine.PeerIP);
+ TThread.Synchronize(nil,
+ procedure
+ begin
+ btnActivateClient.Text := 'Deactivate client';
+ end);
+end;
+
+procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log ('Client disconnected from peer: ' + aLine.PeerIP);
+ TThread.Synchronize(nil,
+ procedure
+ begin
+ btnActivateClient.Text := 'Activate client';
+ end);
+end;
+
+procedure TfrmMain.ClientReconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log ('Client was reconnected to peer: ' + aLine.PeerIP);
+end;
+
+function TfrmMain.ClientHandleCommand(Sender: TObject; aLine: TncLine;
+ aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+ const aSenderComponent, aReceiverComponent: string): TArray;
+begin
+ Log (Stringof (aData));
+end;
+
+end.
diff --git a/Demos/DB/ChatDemo/Server/Initial.txt b/Demos/TCP/DB/ChatDemo/Server/Initial.txt
similarity index 100%
rename from Demos/DB/ChatDemo/Server/Initial.txt
rename to Demos/TCP/DB/ChatDemo/Server/Initial.txt
diff --git a/Demos/DB/ChatDemo/initial.txt b/Demos/TCP/DB/ChatDemo/initial.txt
similarity index 100%
rename from Demos/DB/ChatDemo/initial.txt
rename to Demos/TCP/DB/ChatDemo/initial.txt
diff --git a/Demos/DB/DBClient/DBClient.dpr b/Demos/TCP/DB/DBClient/DBClient.dpr
similarity index 95%
rename from Demos/DB/DBClient/DBClient.dpr
rename to Demos/TCP/DB/DBClient/DBClient.dpr
index b86a578..b071dcd 100644
--- a/Demos/DB/DBClient/DBClient.dpr
+++ b/Demos/TCP/DB/DBClient/DBClient.dpr
@@ -1,17 +1,17 @@
-program DBClient;
-
-uses
- Vcl.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain},
- udmMain in 'udmMain.pas' {dmMain: TDataModule};
-
-{$R *.res}
-
-begin
- ReportMemoryLeaksOnShutdown := True;
- Application.Initialize;
- Application.MainFormOnTaskbar := True;
- Application.CreateForm(TfrmMain, frmMain);
- Application.CreateForm(TdmMain, dmMain);
- Application.Run;
-end.
+program DBClient;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain},
+ udmMain in 'udmMain.pas' {dmMain: TDataModule};
+
+{$R *.res}
+
+begin
+ ReportMemoryLeaksOnShutdown := True;
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.CreateForm(TdmMain, dmMain);
+ Application.Run;
+end.
diff --git a/Demos/DB/DBClient/DBClient.dproj b/Demos/TCP/DB/DBClient/DBClient.dproj
similarity index 98%
rename from Demos/DB/DBClient/DBClient.dproj
rename to Demos/TCP/DB/DBClient/DBClient.dproj
index e3466ad..5fe2cc3 100644
--- a/Demos/DB/DBClient/DBClient.dproj
+++ b/Demos/TCP/DB/DBClient/DBClient.dproj
@@ -1,209 +1,209 @@
-
-
- {5DC2BA92-67D1-464B-A6A6-59BD015406E5}
- 18.8
- DBClient.dpr
- Release
- DCC32
- VCL
- True
- Win32
- 32769
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- DBClient.exe
- $(BDSCOMMONDIR)\DCU
- $(BDSCOMMONDIR)\DCP
- vcl;rtl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dxSkinscxPCPainterD14;cxPageControlD14;dxSkinsCoreD14;dxSkinsdxLCPainterD14;dxLayoutControlD14;dxSkinscxScheduler3PainterD14;cxSchedulerD14;dxSkinsdxNavBar2PainterD14;dxNavBarD14;dxSkinsdxDLPainterD14;dxDockingD14;dxSkinsdxRibbonPainterD14;dxRibbonD14;dxBarD14;dxSkinsdxBarPainterD14;dclOfficeXP;$(DCC_UsePackage)
- 00400000
- x86
- true
- DBClient
- Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;Data.Win;$(DCC_Namespace)
- true
- 3
- 46
- true
- 1033
- CompanyName=Developer Express Inc.;FileDescription=ExpressScheduler 3 connection to ExpressQuantumGrid;FileVersion=3.46.0.0;InternalName=;LegalCopyright=Copyright (c) 1998-2009 Developer Express Inc.;LegalTrademarks=;OriginalFilename=dclcxSchedulerGridD14.BPL;ProductName=;ProductVersion=3.4
-
-
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- System.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
- 1033
- $(BDS)\bin\default_app.manifest
- DBClient_Icon.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- $(BDS)\bin\default_app.manifest
- DBClient_Icon.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- false
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- Debug
-
-
- true
- PerMonitorV2
-
-
- false
- true
- DEBUG;$(DCC_Define)
-
-
- Debug
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
-
-
-
- TDataModule
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
-
- Delphi.Personality.12
-
-
-
-
- DBClient.dpr
-
-
- False
- True
- False
-
-
- True
- False
- 3
- 46
- 0
- 0
- False
- False
- False
- False
- True
- 1033
- 1200
-
-
- Developer Express Inc.
- ExpressScheduler 3 connection to ExpressQuantumGrid
- 3.46.0.0
-
- Copyright (c) 1998-2009 Developer Express Inc.
-
- dclcxSchedulerGridD14.BPL
-
- 3.4
-
-
- Embarcadero C++Builder Office XP Servers Package
- Embarcadero C++Builder Office 2000 Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
-
-
-
- True
- True
- False
-
-
- 12
-
-
-
+
+
+ {5DC2BA92-67D1-464B-A6A6-59BD015406E5}
+ 18.8
+ DBClient.dpr
+ Release
+ DCC32
+ VCL
+ True
+ Win32
+ 32769
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ DBClient.exe
+ $(BDSCOMMONDIR)\DCU
+ $(BDSCOMMONDIR)\DCP
+ vcl;rtl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dxSkinscxPCPainterD14;cxPageControlD14;dxSkinsCoreD14;dxSkinsdxLCPainterD14;dxLayoutControlD14;dxSkinscxScheduler3PainterD14;cxSchedulerD14;dxSkinsdxNavBar2PainterD14;dxNavBarD14;dxSkinsdxDLPainterD14;dxDockingD14;dxSkinsdxRibbonPainterD14;dxRibbonD14;dxBarD14;dxSkinsdxBarPainterD14;dclOfficeXP;$(DCC_UsePackage)
+ 00400000
+ x86
+ true
+ DBClient
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;Data.Win;$(DCC_Namespace)
+ true
+ 3
+ 46
+ true
+ 1033
+ CompanyName=Developer Express Inc.;FileDescription=ExpressScheduler 3 connection to ExpressQuantumGrid;FileVersion=3.46.0.0;InternalName=;LegalCopyright=Copyright (c) 1998-2009 Developer Express Inc.;LegalTrademarks=;OriginalFilename=dclcxSchedulerGridD14.BPL;ProductName=;ProductVersion=3.4
+
+
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ System.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ DBClient_Icon.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\default_app.manifest
+ DBClient_Icon.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ false
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ Debug
+
+
+ true
+ PerMonitorV2
+
+
+ false
+ true
+ DEBUG;$(DCC_Define)
+
+
+ Debug
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+
+ TDataModule
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ DBClient.dpr
+
+
+ False
+ True
+ False
+
+
+ True
+ False
+ 3
+ 46
+ 0
+ 0
+ False
+ False
+ False
+ False
+ True
+ 1033
+ 1200
+
+
+ Developer Express Inc.
+ ExpressScheduler 3 connection to ExpressQuantumGrid
+ 3.46.0.0
+
+ Copyright (c) 1998-2009 Developer Express Inc.
+
+ dclcxSchedulerGridD14.BPL
+
+ 3.4
+
+
+ Embarcadero C++Builder Office XP Servers Package
+ Embarcadero C++Builder Office 2000 Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+
+
+
+ True
+ True
+ False
+
+
+ 12
+
+
+
diff --git a/Demos/DB/DBClient/DBClient.dproj.local b/Demos/TCP/DB/DBClient/DBClient.dproj.local
similarity index 99%
rename from Demos/DB/DBClient/DBClient.dproj.local
rename to Demos/TCP/DB/DBClient/DBClient.dproj.local
index c0b9684..0e0048f 100644
--- a/Demos/DB/DBClient/DBClient.dproj.local
+++ b/Demos/TCP/DB/DBClient/DBClient.dproj.local
@@ -1,11 +1,11 @@
-
-
-
- 2011/03/28 11:31:42.844.dfm,C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.dfm=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\ufrmMain.dfm
- 2011/03/28 11:31:42.844.pas,C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.pas=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
- 2011/03/28 11:31:46.702.dproj,C:\Users\BDemos\Documents\RAD Studio\Projects\Project1.dproj=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\DBClient.dproj
- 2011/03/28 11:32:45.130.dfm,C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\Unit1.dfm=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\udmMain.dfm
- 2011/03/28 11:32:45.130.pas,C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\Unit1.pas=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
-
-
-
+
+
+
+ 2011/03/28 11:31:42.844.dfm,C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.dfm=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\ufrmMain.dfm
+ 2011/03/28 11:31:42.844.pas,C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.pas=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
+ 2011/03/28 11:31:46.702.dproj,C:\Users\BDemos\Documents\RAD Studio\Projects\Project1.dproj=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\DBClient.dproj
+ 2011/03/28 11:32:45.130.dfm,C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\Unit1.dfm=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\udmMain.dfm
+ 2011/03/28 11:32:45.130.pas,C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\Unit1.pas=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
+
+
+
diff --git a/Demos/DB/DBClient/DBClient.dsk b/Demos/TCP/DB/DBClient/DBClient.dsk
similarity index 94%
rename from Demos/DB/DBClient/DBClient.dsk
rename to Demos/TCP/DB/DBClient/DBClient.dsk
index 8fedbb5..a84758c 100644
--- a/Demos/DB/DBClient/DBClient.dsk
+++ b/Demos/TCP/DB/DBClient/DBClient.dsk
@@ -1,785 +1,785 @@
-[Closed Files]
-File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\data\ado\Data.Win.ADODB.pas',0,1,1,6,14,0,0,,
-File_1=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\data\Data.DB.pas',0,1,1,6,10,0,0,,
-File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,1,6,10,0,0,,
-File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\RTL\SYS\System.SysUtils.pas',0,1,1,6,16,0,0,,
-File_4=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.Forms.pas',0,1,1,6,10,0,0,{{1755,4},{1771,15},{'TScrollWindow'}}{{1858,4},{1959,15},{'TMainMenuBarStyleHook'}},
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\ComObj.pas',0,1,783,30,786,0,0,,
-File_6=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\db\DB.pas',0,1,11243,1,11262,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\db\ADODB.pas',0,1,5604,1,5623,0,0,,
-File_8=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\RTL\SYS\System.pas',0,1,21903,1,21931,0,0,,
-File_9=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Classes.pas',0,1,5252,1,5266,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dproj
-Module2=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
-Count=3
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dproj]
-ModuleType=TBaseProject
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=3
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
-View0=0
-View1=1
-View2=2
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=00000800010100000000CC0E0000000000000166070000000000000100000000530E000009000000446F636B536974653301000000004D1A00001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=00000800010100000000CC0E00000000000001F50500000000000001000000004612000009000000446F636B536974653201000000004D1A000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=1622
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020100000009000000446F636B5369746531C0440000000000000256060000000000000100000000C04400000F0000004D65737361676556696577466F726DFFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dpr
-CursorX=48
-CursorY=6
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
-CursorX=38
-CursorY=36
-TopLine=26
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[View2]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
-CursorX=1
-CursorY=6
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=1
-Breakpoint0='c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\db\ADODB.pas',4017,'',0,1,'',1,0,0,'',1,'','','',0,''
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=9900
-Height=1372
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=1372
-TBDockHeight=1372
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=1826
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=1826
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=2884
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=2884
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Align,OnAsyncExecCommandResult
-ExpandedItems=LiveBindings=0,"LiveBindings Designer=0",Margins=0,Border=0,BorderIcons=0,Fill=0,FormFactor=0,Constraints=0,Anchors=0,BevelEdges=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-240
-Top=-285
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=1826
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=1826
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\data\ado\Data.Win.ADODB.pas',0,1,1,6,14,0,0,,
+File_1=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\data\Data.DB.pas',0,1,1,6,10,0,0,,
+File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,1,6,10,0,0,,
+File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\RTL\SYS\System.SysUtils.pas',0,1,1,6,16,0,0,,
+File_4=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.Forms.pas',0,1,1,6,10,0,0,{{1755,4},{1771,15},{'TScrollWindow'}}{{1858,4},{1959,15},{'TMainMenuBarStyleHook'}},
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\ComObj.pas',0,1,783,30,786,0,0,,
+File_6=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\db\DB.pas',0,1,11243,1,11262,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\db\ADODB.pas',0,1,5604,1,5623,0,0,,
+File_8=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\RTL\SYS\System.pas',0,1,21903,1,21931,0,0,,
+File_9=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Classes.pas',0,1,5252,1,5266,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dproj
+Module2=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
+Count=3
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dproj]
+ModuleType=TBaseProject
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=3
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
+View0=0
+View1=1
+View2=2
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=00000800010100000000CC0E0000000000000166070000000000000100000000530E000009000000446F636B536974653301000000004D1A00001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=00000800010100000000CC0E00000000000001F50500000000000001000000004612000009000000446F636B536974653201000000004D1A000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=1622
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020100000009000000446F636B5369746531C0440000000000000256060000000000000100000000C04400000F0000004D65737361676556696577466F726DFFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dpr
+CursorX=48
+CursorY=6
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\DBClient.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\ufrmMain.pas
+CursorX=38
+CursorY=36
+TopLine=26
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[View2]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
+CursorX=1
+CursorY=6
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBClient\udmMain.pas
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=1
+Breakpoint0='c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\db\ADODB.pas',4017,'',0,1,'',1,0,0,'',1,'','','',0,''
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=9900
+Height=1372
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=1372
+TBDockHeight=1372
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=1826
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=1826
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=2884
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=2884
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Align,OnAsyncExecCommandResult
+ExpandedItems=LiveBindings=0,"LiveBindings Designer=0",Margins=0,Border=0,BorderIcons=0,Fill=0,FormFactor=0,Constraints=0,Anchors=0,BevelEdges=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-240
+Top=-285
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=1826
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=1826
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/DB/DBClient/DBClient.identcache b/Demos/TCP/DB/DBClient/DBClient.identcache
similarity index 100%
rename from Demos/DB/DBClient/DBClient.identcache
rename to Demos/TCP/DB/DBClient/DBClient.identcache
diff --git a/Demos/DB/DBClient/DBClient.res b/Demos/TCP/DB/DBClient/DBClient.res
similarity index 100%
rename from Demos/DB/DBClient/DBClient.res
rename to Demos/TCP/DB/DBClient/DBClient.res
diff --git a/Demos/DB/DBClient/DBClient.skincfg b/Demos/TCP/DB/DBClient/DBClient.skincfg
similarity index 94%
rename from Demos/DB/DBClient/DBClient.skincfg
rename to Demos/TCP/DB/DBClient/DBClient.skincfg
index 6870d73..d58e821 100644
--- a/Demos/DB/DBClient/DBClient.skincfg
+++ b/Demos/TCP/DB/DBClient/DBClient.skincfg
@@ -1,33 +1,33 @@
-[ExpressSkins]
-Default=1
-ShowNotifications=1
-Enabled=1
-dxSkinBlack=0
-dxSkinBlue=0
-dxSkinCaramel=0
-dxSkinCoffee=0
-dxSkinDarkRoom=0
-dxSkinDarkSide=0
-dxSkinFoggy=0
-dxSkinGlassOceans=0
-dxSkiniMaginary=0
-dxSkinLilian=0
-dxSkinLiquidSky=0
-dxSkinLondonLiquidSky=0
-dxSkinMcSkin=0
-dxSkinMoneyTwins=0
-dxSkinOffice2007Black=0
-dxSkinOffice2007Blue=0
-dxSkinOffice2007Green=0
-dxSkinOffice2007Pink=0
-dxSkinOffice2007Silver=0
-dxSkinPumpkin=0
-dxSkinSeven=0
-dxSkinSharp=0
-dxSkinSilver=0
-dxSkinSpringTime=0
-dxSkinStardust=0
-dxSkinSummer2008=0
-dxSkinsDefaultPainters=0
-dxSkinValentine=0
-dxSkinXmas2008Blue=0
+[ExpressSkins]
+Default=1
+ShowNotifications=1
+Enabled=1
+dxSkinBlack=0
+dxSkinBlue=0
+dxSkinCaramel=0
+dxSkinCoffee=0
+dxSkinDarkRoom=0
+dxSkinDarkSide=0
+dxSkinFoggy=0
+dxSkinGlassOceans=0
+dxSkiniMaginary=0
+dxSkinLilian=0
+dxSkinLiquidSky=0
+dxSkinLondonLiquidSky=0
+dxSkinMcSkin=0
+dxSkinMoneyTwins=0
+dxSkinOffice2007Black=0
+dxSkinOffice2007Blue=0
+dxSkinOffice2007Green=0
+dxSkinOffice2007Pink=0
+dxSkinOffice2007Silver=0
+dxSkinPumpkin=0
+dxSkinSeven=0
+dxSkinSharp=0
+dxSkinSilver=0
+dxSkinSpringTime=0
+dxSkinStardust=0
+dxSkinSummer2008=0
+dxSkinsDefaultPainters=0
+dxSkinValentine=0
+dxSkinXmas2008Blue=0
diff --git a/Demos/DB/DBClient/DBClient_Icon.ico b/Demos/TCP/DB/DBClient/DBClient_Icon.ico
similarity index 100%
rename from Demos/DB/DBClient/DBClient_Icon.ico
rename to Demos/TCP/DB/DBClient/DBClient_Icon.ico
diff --git a/Demos/DB/DBClient/udmMain.dfm b/Demos/TCP/DB/DBClient/udmMain.dfm
similarity index 95%
rename from Demos/DB/DBClient/udmMain.dfm
rename to Demos/TCP/DB/DBClient/udmMain.dfm
index fc78ad6..900b2d1 100644
--- a/Demos/DB/DBClient/udmMain.dfm
+++ b/Demos/TCP/DB/DBClient/udmMain.dfm
@@ -1,58 +1,58 @@
-object dmMain: TdmMain
- OldCreateOrder = False
- OnCreate = DataModuleCreate
- Height = 351
- Width = 376
- object ncClientSource: TncClientSource
- Port = 18753
- EncryptionKey = 'SetEncryptionKey'
- Host = 'localhost'
- Left = 56
- Top = 36
- end
- object ncDBDataset1: TncDBDataset
- CursorType = ctStatic
- LockType = ltBatchOptimistic
- Source = ncClientSource
- PeerCommandHandler = 'DBServer'
- SQL.Strings = (
- 'select * from Customers')
- Parameters = <>
- Left = 112
- Top = 116
- end
- object DataSource1: TDataSource
- DataSet = ncDBDataset1
- Left = 196
- Top = 116
- end
- object ncDBDataset2: TncDBDataset
- CursorType = ctStatic
- LockType = ltBatchOptimistic
- Source = ncClientSource
- PeerCommandHandler = 'DBServer'
- SQL.Strings = (
- 'select * from Orders'
- 'where FKCustomersID=:ID')
- DataSource = DataSource1
- IndexFieldNames = 'FKCustomersID'
- Parameters = <
- item
- Name = 'ID'
- Size = -1
- Value = Null
- end>
- Left = 112
- Top = 184
- end
- object DataSource2: TDataSource
- DataSet = ncDBDataset2
- Left = 196
- Top = 184
- end
- object ADOQuery1: TADOQuery
- Parameters = <>
- Left = 56
- Top = 276
- end
-end
+object dmMain: TdmMain
+ OldCreateOrder = False
+ OnCreate = DataModuleCreate
+ Height = 351
+ Width = 376
+ object ncClientSource: TncClientSource
+ Port = 18753
+ EncryptionKey = 'SetEncryptionKey'
+ Host = 'localhost'
+ Left = 56
+ Top = 36
+ end
+ object ncDBDataset1: TncDBDataset
+ CursorType = ctStatic
+ LockType = ltBatchOptimistic
+ Source = ncClientSource
+ PeerCommandHandler = 'DBServer'
+ SQL.Strings = (
+ 'select * from Customers')
+ Parameters = <>
+ Left = 112
+ Top = 116
+ end
+ object DataSource1: TDataSource
+ DataSet = ncDBDataset1
+ Left = 196
+ Top = 116
+ end
+ object ncDBDataset2: TncDBDataset
+ CursorType = ctStatic
+ LockType = ltBatchOptimistic
+ Source = ncClientSource
+ PeerCommandHandler = 'DBServer'
+ SQL.Strings = (
+ 'select * from Orders'
+ 'where FKCustomersID=:ID')
+ DataSource = DataSource1
+ IndexFieldNames = 'FKCustomersID'
+ Parameters = <
+ item
+ Name = 'ID'
+ Size = -1
+ Value = Null
+ end>
+ Left = 112
+ Top = 184
+ end
+ object DataSource2: TDataSource
+ DataSet = ncDBDataset2
+ Left = 196
+ Top = 184
+ end
+ object ADOQuery1: TADOQuery
+ Parameters = <>
+ Left = 56
+ Top = 276
+ end
+end
diff --git a/Demos/DB/DBClient/udmMain.pas b/Demos/TCP/DB/DBClient/udmMain.pas
similarity index 94%
rename from Demos/DB/DBClient/udmMain.pas
rename to Demos/TCP/DB/DBClient/udmMain.pas
index 79d5884..54692f0 100644
--- a/Demos/DB/DBClient/udmMain.pas
+++ b/Demos/TCP/DB/DBClient/udmMain.pas
@@ -1,38 +1,38 @@
-unit udmMain;
-
-interface
-
-uses
- System.Classes, System.SysUtils, Data.DB, Data.Win.ADODB, ncSockets, ncSources, ncDBCnt;
-
-type
- TdmMain = class(TDataModule)
- ncClientSource: TncClientSource;
- ncDBDataset1: TncDBDataset;
- DataSource1: TDataSource;
- ncDBDataset2: TncDBDataset;
- DataSource2: TDataSource;
- ADOQuery1: TADOQuery;
- procedure DataModuleCreate(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
-var
- dmMain: TdmMain;
-
-implementation
-
-uses ufrmMain;
-
-{$R *.dfm}
-
-procedure TdmMain.DataModuleCreate(Sender: TObject);
-begin
- ncDBDataset1.Active := True;
- ncDBDataset2.Active := True;
-end;
-
-end.
+unit udmMain;
+
+interface
+
+uses
+ System.Classes, System.SysUtils, Data.DB, Data.Win.ADODB, ncSockets, ncSources, ncDBCnt;
+
+type
+ TdmMain = class(TDataModule)
+ ncClientSource: TncClientSource;
+ ncDBDataset1: TncDBDataset;
+ DataSource1: TDataSource;
+ ncDBDataset2: TncDBDataset;
+ DataSource2: TDataSource;
+ ADOQuery1: TADOQuery;
+ procedure DataModuleCreate(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ dmMain: TdmMain;
+
+implementation
+
+uses ufrmMain;
+
+{$R *.dfm}
+
+procedure TdmMain.DataModuleCreate(Sender: TObject);
+begin
+ ncDBDataset1.Active := True;
+ ncDBDataset2.Active := True;
+end;
+
+end.
diff --git a/Demos/DB/DBClient/ufrmMain.dfm b/Demos/TCP/DB/DBClient/ufrmMain.dfm
similarity index 95%
rename from Demos/DB/DBClient/ufrmMain.dfm
rename to Demos/TCP/DB/DBClient/ufrmMain.dfm
index 8de34cb..5bd6af1 100644
--- a/Demos/DB/DBClient/ufrmMain.dfm
+++ b/Demos/TCP/DB/DBClient/ufrmMain.dfm
@@ -1,144 +1,144 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'Client DB Tester'
- ClientHeight = 392
- ClientWidth = 945
- Color = clBtnFace
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Tahoma'
- Font.Style = []
- OldCreateOrder = False
- PixelsPerInch = 96
- TextHeight = 13
- object Panel2: TPanel
- Left = 245
- Top = 0
- Width = 700
- Height = 373
- Align = alClient
- TabOrder = 2
- object dbGrid1: TDBGrid
- AlignWithMargins = True
- Left = 4
- Top = 4
- Width = 692
- Height = 150
- Align = alTop
- DataSource = dmMain.DataSource1
- TabOrder = 0
- TitleFont.Charset = DEFAULT_CHARSET
- TitleFont.Color = clWindowText
- TitleFont.Height = -11
- TitleFont.Name = 'Tahoma'
- TitleFont.Style = []
- end
- object DBNavigator1: TDBNavigator
- AlignWithMargins = True
- Left = 4
- Top = 160
- Width = 692
- Height = 35
- DataSource = dmMain.DataSource1
- Align = alTop
- TabOrder = 1
- end
- object DBGrid2: TDBGrid
- AlignWithMargins = True
- Left = 4
- Top = 201
- Width = 692
- Height = 130
- Align = alClient
- DataSource = dmMain.DataSource2
- TabOrder = 2
- TitleFont.Charset = DEFAULT_CHARSET
- TitleFont.Color = clWindowText
- TitleFont.Height = -11
- TitleFont.Name = 'Tahoma'
- TitleFont.Style = []
- end
- object DBNavigator2: TDBNavigator
- AlignWithMargins = True
- Left = 4
- Top = 337
- Width = 692
- Height = 32
- DataSource = dmMain.DataSource2
- Align = alBottom
- TabOrder = 3
- end
- end
- object StatusBar: TStatusBar
- Left = 0
- Top = 373
- Width = 945
- Height = 19
- Panels = <>
- SimplePanel = True
- end
- object Panel1: TPanel
- Left = 0
- Top = 0
- Width = 245
- Height = 373
- Align = alLeft
- TabOrder = 0
- object Button1: TButton
- Left = 6
- Top = 52
- Width = 219
- Height = 25
- Caption = 'Test Activate/Deactivate Recordset Cycle'
- TabOrder = 0
- OnClick = Button1Click
- end
- object Button2: TButton
- Left = 6
- Top = 111
- Width = 219
- Height = 25
- Caption = 'Test Requery'
- TabOrder = 1
- OnClick = Button2Click
- end
- object cbShowOpenClose: TCheckBox
- Left = 12
- Top = 83
- Width = 213
- Height = 17
- Caption = 'Show Open/Close'
- TabOrder = 2
- end
- object Button4: TButton
- Left = 6
- Top = 230
- Width = 161
- Height = 45
- Caption = 'Filter Pending'
- TabOrder = 3
- OnClick = Button4Click
- end
- object edtHost: TEdit
- Left = 6
- Top = 10
- Width = 121
- Height = 21
- TabOrder = 4
- Text = 'LocalHost'
- TextHint = 'Host'
- OnChange = edtHostChange
- end
- object btnApplyUpdates: TButton
- Left = 6
- Top = 281
- Width = 161
- Height = 45
- Caption = 'Apply Updates'
- TabOrder = 5
- OnClick = btnApplyUpdatesClick
- end
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ Caption = 'Client DB Tester'
+ ClientHeight = 392
+ ClientWidth = 945
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Panel2: TPanel
+ Left = 245
+ Top = 0
+ Width = 700
+ Height = 373
+ Align = alClient
+ TabOrder = 2
+ object dbGrid1: TDBGrid
+ AlignWithMargins = True
+ Left = 4
+ Top = 4
+ Width = 692
+ Height = 150
+ Align = alTop
+ DataSource = dmMain.DataSource1
+ TabOrder = 0
+ TitleFont.Charset = DEFAULT_CHARSET
+ TitleFont.Color = clWindowText
+ TitleFont.Height = -11
+ TitleFont.Name = 'Tahoma'
+ TitleFont.Style = []
+ end
+ object DBNavigator1: TDBNavigator
+ AlignWithMargins = True
+ Left = 4
+ Top = 160
+ Width = 692
+ Height = 35
+ DataSource = dmMain.DataSource1
+ Align = alTop
+ TabOrder = 1
+ end
+ object DBGrid2: TDBGrid
+ AlignWithMargins = True
+ Left = 4
+ Top = 201
+ Width = 692
+ Height = 130
+ Align = alClient
+ DataSource = dmMain.DataSource2
+ TabOrder = 2
+ TitleFont.Charset = DEFAULT_CHARSET
+ TitleFont.Color = clWindowText
+ TitleFont.Height = -11
+ TitleFont.Name = 'Tahoma'
+ TitleFont.Style = []
+ end
+ object DBNavigator2: TDBNavigator
+ AlignWithMargins = True
+ Left = 4
+ Top = 337
+ Width = 692
+ Height = 32
+ DataSource = dmMain.DataSource2
+ Align = alBottom
+ TabOrder = 3
+ end
+ end
+ object StatusBar: TStatusBar
+ Left = 0
+ Top = 373
+ Width = 945
+ Height = 19
+ Panels = <>
+ SimplePanel = True
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 0
+ Width = 245
+ Height = 373
+ Align = alLeft
+ TabOrder = 0
+ object Button1: TButton
+ Left = 6
+ Top = 52
+ Width = 219
+ Height = 25
+ Caption = 'Test Activate/Deactivate Recordset Cycle'
+ TabOrder = 0
+ OnClick = Button1Click
+ end
+ object Button2: TButton
+ Left = 6
+ Top = 111
+ Width = 219
+ Height = 25
+ Caption = 'Test Requery'
+ TabOrder = 1
+ OnClick = Button2Click
+ end
+ object cbShowOpenClose: TCheckBox
+ Left = 12
+ Top = 83
+ Width = 213
+ Height = 17
+ Caption = 'Show Open/Close'
+ TabOrder = 2
+ end
+ object Button4: TButton
+ Left = 6
+ Top = 230
+ Width = 161
+ Height = 45
+ Caption = 'Filter Pending'
+ TabOrder = 3
+ OnClick = Button4Click
+ end
+ object edtHost: TEdit
+ Left = 6
+ Top = 10
+ Width = 121
+ Height = 21
+ TabOrder = 4
+ Text = 'LocalHost'
+ TextHint = 'Host'
+ OnChange = edtHostChange
+ end
+ object btnApplyUpdates: TButton
+ Left = 6
+ Top = 281
+ Width = 161
+ Height = 45
+ Caption = 'Apply Updates'
+ TabOrder = 5
+ OnClick = btnApplyUpdatesClick
+ end
+ end
+end
diff --git a/Demos/DB/DBClient/ufrmMain.pas b/Demos/TCP/DB/DBClient/ufrmMain.pas
similarity index 96%
rename from Demos/DB/DBClient/ufrmMain.pas
rename to Demos/TCP/DB/DBClient/ufrmMain.pas
index 6723e20..679a6d0 100644
--- a/Demos/DB/DBClient/ufrmMain.pas
+++ b/Demos/TCP/DB/DBClient/ufrmMain.pas
@@ -1,128 +1,128 @@
-unit ufrmMain;
-
-interface
-
-uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, udmMain, DBCtrls, ExtCtrls, Grids, DBGrids, StdCtrls, ncSockets, ncDBCnt,
- ComCtrls, ADOInt, ADODB, Data.DB;
-
-type
- TfrmMain = class(TForm)
- StatusBar: TStatusBar;
- Panel1: TPanel;
- Panel2: TPanel;
- dbGrid1: TDBGrid;
- DBNavigator1: TDBNavigator;
- DBGrid2: TDBGrid;
- DBNavigator2: TDBNavigator;
- Button1: TButton;
- Button2: TButton;
- cbShowOpenClose: TCheckBox;
- Button4: TButton;
- edtHost: TEdit;
- btnApplyUpdates: TButton;
- procedure Button1Click(Sender: TObject);
- procedure Button2Click(Sender: TObject);
- procedure Button4Click(Sender: TObject);
- procedure edtHostChange(Sender: TObject);
- procedure btnApplyUpdatesClick(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.dfm}
-
-var
- InButton1: Boolean = False;
- PrevBtn1Cap: string;
-
-procedure TfrmMain.Button1Click(Sender: TObject);
-var
- TimeStart, TimeEnd: Int64;
-
- Freq: Int64;
- i: Integer;
-begin
- if InButton1 then
- begin
- Button1.Caption := PrevBtn1Cap;
-
- InButton1 := False;
- Exit;
- end;
-
- // Test n alive queries
- InButton1 := True;
- try
- PrevBtn1Cap := Button1.Caption;
- Button1.Caption := 'Stop';
-
- if not cbShowOpenClose.Checked then
- begin
- dmMain.DataSource1.DataSet := nil;
- dmMain.DataSource2.DataSet := nil;
- end;
- try
- QueryPerformanceFrequency(Freq);
- QueryPerformanceCounter(TimeStart);
- i := 0;
- while InButton1 and not Application.Terminated do
- begin
- i := i + 1;
- if i mod 100 = 0 then
- begin
- StatusBar.SimpleText := Format('Iteration: %4.4d, Mean Open/Close Time: %f (ms)', [i, 1000 * (TimeEnd - TimeStart) / (i * Freq)]);
- Application.ProcessMessages;
- end;
- // Test open/close time
- dmMain.ncDBDataset1.Active := False;
- dmMain.ncDBDataset1.Active := True;
- // Test ExecSQL time
- // dmMain.ncDBDataset1.SQL.Text := 'UPDATE Customers SET CustomerName = ''Bill'' where ID = 1';
- // dmMain.ncDBDataset1.ExecSQL;
- QueryPerformanceCounter(TimeEnd);
- end;
- finally
- if dmMain.DataSource1.DataSet = nil then
- begin
- dmMain.DataSource1.DataSet := dmMain.ncDBDataset1;
- dmMain.DataSource2.DataSet := dmMain.ncDBDataset2;
- end;
- end;
- finally
- InButton1 := False;
- end;
-end;
-
-procedure TfrmMain.Button2Click(Sender: TObject);
-begin
- dmMain.ncDBDataset2.Requery;
-end;
-
-procedure TfrmMain.Button4Click(Sender: TObject);
-begin
- dmMain.ncDBDataset1.FilterGroup := fgPendingRecords;
- dmMain.ncDBDataset1.Filtered := not dmMain.ncDBDataset1.Filtered;
-end;
-
-procedure TfrmMain.btnApplyUpdatesClick(Sender: TObject);
-begin
- dmMain.ncDBDataset1.ApplyUpdates;
- dmMain.ncDBDataset2.ApplyUpdates;
-end;
-
-procedure TfrmMain.edtHostChange(Sender: TObject);
-begin
- dmMain.ncClientSource.Active := False;
- dmMain.ncClientSource.Host := edtHost.Text;
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+ Dialogs, udmMain, DBCtrls, ExtCtrls, Grids, DBGrids, StdCtrls, ncSockets, ncDBCnt,
+ ComCtrls, ADOInt, ADODB, Data.DB;
+
+type
+ TfrmMain = class(TForm)
+ StatusBar: TStatusBar;
+ Panel1: TPanel;
+ Panel2: TPanel;
+ dbGrid1: TDBGrid;
+ DBNavigator1: TDBNavigator;
+ DBGrid2: TDBGrid;
+ DBNavigator2: TDBNavigator;
+ Button1: TButton;
+ Button2: TButton;
+ cbShowOpenClose: TCheckBox;
+ Button4: TButton;
+ edtHost: TEdit;
+ btnApplyUpdates: TButton;
+ procedure Button1Click(Sender: TObject);
+ procedure Button2Click(Sender: TObject);
+ procedure Button4Click(Sender: TObject);
+ procedure edtHostChange(Sender: TObject);
+ procedure btnApplyUpdatesClick(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.dfm}
+
+var
+ InButton1: Boolean = False;
+ PrevBtn1Cap: string;
+
+procedure TfrmMain.Button1Click(Sender: TObject);
+var
+ TimeStart, TimeEnd: Int64;
+
+ Freq: Int64;
+ i: Integer;
+begin
+ if InButton1 then
+ begin
+ Button1.Caption := PrevBtn1Cap;
+
+ InButton1 := False;
+ Exit;
+ end;
+
+ // Test n alive queries
+ InButton1 := True;
+ try
+ PrevBtn1Cap := Button1.Caption;
+ Button1.Caption := 'Stop';
+
+ if not cbShowOpenClose.Checked then
+ begin
+ dmMain.DataSource1.DataSet := nil;
+ dmMain.DataSource2.DataSet := nil;
+ end;
+ try
+ QueryPerformanceFrequency(Freq);
+ QueryPerformanceCounter(TimeStart);
+ i := 0;
+ while InButton1 and not Application.Terminated do
+ begin
+ i := i + 1;
+ if i mod 100 = 0 then
+ begin
+ StatusBar.SimpleText := Format('Iteration: %4.4d, Mean Open/Close Time: %f (ms)', [i, 1000 * (TimeEnd - TimeStart) / (i * Freq)]);
+ Application.ProcessMessages;
+ end;
+ // Test open/close time
+ dmMain.ncDBDataset1.Active := False;
+ dmMain.ncDBDataset1.Active := True;
+ // Test ExecSQL time
+ // dmMain.ncDBDataset1.SQL.Text := 'UPDATE Customers SET CustomerName = ''Bill'' where ID = 1';
+ // dmMain.ncDBDataset1.ExecSQL;
+ QueryPerformanceCounter(TimeEnd);
+ end;
+ finally
+ if dmMain.DataSource1.DataSet = nil then
+ begin
+ dmMain.DataSource1.DataSet := dmMain.ncDBDataset1;
+ dmMain.DataSource2.DataSet := dmMain.ncDBDataset2;
+ end;
+ end;
+ finally
+ InButton1 := False;
+ end;
+end;
+
+procedure TfrmMain.Button2Click(Sender: TObject);
+begin
+ dmMain.ncDBDataset2.Requery;
+end;
+
+procedure TfrmMain.Button4Click(Sender: TObject);
+begin
+ dmMain.ncDBDataset1.FilterGroup := fgPendingRecords;
+ dmMain.ncDBDataset1.Filtered := not dmMain.ncDBDataset1.Filtered;
+end;
+
+procedure TfrmMain.btnApplyUpdatesClick(Sender: TObject);
+begin
+ dmMain.ncDBDataset1.ApplyUpdates;
+ dmMain.ncDBDataset2.ApplyUpdates;
+end;
+
+procedure TfrmMain.edtHostChange(Sender: TObject);
+begin
+ dmMain.ncClientSource.Active := False;
+ dmMain.ncClientSource.Host := edtHost.Text;
+end;
+
+end.
diff --git a/Demos/DB/DBServer/Service/DBServerService.dpr b/Demos/TCP/DB/DBServer/Service/DBServerService.dpr
similarity index 97%
rename from Demos/DB/DBServer/Service/DBServerService.dpr
rename to Demos/TCP/DB/DBServer/Service/DBServerService.dpr
index ebb50fa..3a1582c 100644
--- a/Demos/DB/DBServer/Service/DBServerService.dpr
+++ b/Demos/TCP/DB/DBServer/Service/DBServerService.dpr
@@ -1,32 +1,32 @@
-program DBServerService;
-
-uses
- Windows,
- SysUtils,
- SvcMgr,
- usvcMain in 'usvcMain.pas' {NetcomDataServer: TService},
- uscvServiceCommands in 'uscvServiceCommands.pas';
-
-{$R *.RES}
-
-begin
- // Windows 2003 Server requires StartServiceCtrlDispatcher to be
- // called before CoRegisterClassObject, which can be called indirectly
- // by Application.Initialize. TServiceApplication.DelayInitialize allows
- // Application.Initialize to be called from TService.Main (after
- // StartServiceCtrlDispatcher has been called).
- //
- // Delayed initialization of the Application object may affect
- // events which then occur prior to initialization, such as
- // TService.OnCreate. It is only recommended if the ServiceApplication
- // registers a class object with OLE and is intended for use with
- // Windows 2003 Server.
- //
- // Application.DelayInitialize := True;
- //
- SetCurrentDirectory(PChar (ExtractFilePath (ParamStr (0))));
- if not Application.DelayInitialize or Application.Installing then
- Application.Initialize;
- Application.CreateForm(TNetcomDataServer, Service);
- Application.Run;
-end.
+program DBServerService;
+
+uses
+ Windows,
+ SysUtils,
+ SvcMgr,
+ usvcMain in 'usvcMain.pas' {NetcomDataServer: TService},
+ uscvServiceCommands in 'uscvServiceCommands.pas';
+
+{$R *.RES}
+
+begin
+ // Windows 2003 Server requires StartServiceCtrlDispatcher to be
+ // called before CoRegisterClassObject, which can be called indirectly
+ // by Application.Initialize. TServiceApplication.DelayInitialize allows
+ // Application.Initialize to be called from TService.Main (after
+ // StartServiceCtrlDispatcher has been called).
+ //
+ // Delayed initialization of the Application object may affect
+ // events which then occur prior to initialization, such as
+ // TService.OnCreate. It is only recommended if the ServiceApplication
+ // registers a class object with OLE and is intended for use with
+ // Windows 2003 Server.
+ //
+ // Application.DelayInitialize := True;
+ //
+ SetCurrentDirectory(PChar (ExtractFilePath (ParamStr (0))));
+ if not Application.DelayInitialize or Application.Installing then
+ Application.Initialize;
+ Application.CreateForm(TNetcomDataServer, Service);
+ Application.Run;
+end.
diff --git a/Demos/DB/DBServer/Service/DBServerService.dproj b/Demos/TCP/DB/DBServer/Service/DBServerService.dproj
similarity index 98%
rename from Demos/DB/DBServer/Service/DBServerService.dproj
rename to Demos/TCP/DB/DBServer/Service/DBServerService.dproj
index 9701749..757d357 100644
--- a/Demos/DB/DBServer/Service/DBServerService.dproj
+++ b/Demos/TCP/DB/DBServer/Service/DBServerService.dproj
@@ -1,115 +1,115 @@
-
-
- {1CE60A32-3682-445E-BC9A-10E419519CEC}
- 12.0
- DBServerService.dpr
- Debug
- DCC32
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- DBServerService.exe
- $(BDSCOMMONDIR)\DCU
- $(BDSCOMMONDIR)\DCP
- vcl;rtl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dxSkinscxPCPainterD14;cxPageControlD14;dxSkinsCoreD14;dxSkinsdxLCPainterD14;dxLayoutControlD14;dxSkinscxScheduler3PainterD14;cxSchedulerD14;dxSkinsdxNavBar2PainterD14;dxNavBarD14;dxSkinsdxDLPainterD14;dxDockingD14;dxSkinsdxRibbonPainterD14;dxRibbonD14;dxBarD14;dxSkinsdxBarPainterD14;dclOfficeXP
- 00400000
- x86
- WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias)
- true
-
-
- false
- false
- RELEASE;$(DCC_Define)
- 0
- false
-
-
- true
- DEBUG;$(DCC_Define)
-
-
-
- MainSource
-
-
-
- TService
-
-
-
- Base
-
-
- Cfg_2
- Base
-
-
- Cfg_1
- Base
-
-
-
-
- Delphi.Personality.12
-
-
-
-
- DBServerService.dpr
-
-
- False
- True
- False
- /install
-
-
- True
- False
- 1
- 0
- 0
- 0
- False
- False
- False
- False
- True
- 1033
- 1200
-
-
-
- Service Prototype
- 1.0.0.0
-
-
-
-
-
- 1.0.0.0
-
-
- Embarcadero C++Builder Office XP Servers Package
- Embarcadero C++Builder Office 2000 Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- ExpressPivotGrid 2 OLAP by Developer Express Inc.
-
-
-
- 12
-
-
+
+
+ {1CE60A32-3682-445E-BC9A-10E419519CEC}
+ 12.0
+ DBServerService.dpr
+ Debug
+ DCC32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ DBServerService.exe
+ $(BDSCOMMONDIR)\DCU
+ $(BDSCOMMONDIR)\DCP
+ vcl;rtl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dxSkinscxPCPainterD14;cxPageControlD14;dxSkinsCoreD14;dxSkinsdxLCPainterD14;dxLayoutControlD14;dxSkinscxScheduler3PainterD14;cxSchedulerD14;dxSkinsdxNavBar2PainterD14;dxNavBarD14;dxSkinsdxDLPainterD14;dxDockingD14;dxSkinsdxRibbonPainterD14;dxRibbonD14;dxBarD14;dxSkinsdxBarPainterD14;dclOfficeXP
+ 00400000
+ x86
+ WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias)
+ true
+
+
+ false
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ false
+
+
+ true
+ DEBUG;$(DCC_Define)
+
+
+
+ MainSource
+
+
+
+ TService
+
+
+
+ Base
+
+
+ Cfg_2
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ DBServerService.dpr
+
+
+ False
+ True
+ False
+ /install
+
+
+ True
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ True
+ 1033
+ 1200
+
+
+
+ Service Prototype
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+ Embarcadero C++Builder Office XP Servers Package
+ Embarcadero C++Builder Office 2000 Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ ExpressPivotGrid 2 OLAP by Developer Express Inc.
+
+
+
+ 12
+
+
diff --git a/Demos/DB/DBServer/Service/DBServerService.dproj.local b/Demos/TCP/DB/DBServer/Service/DBServerService.dproj.local
similarity index 96%
rename from Demos/DB/DBServer/Service/DBServerService.dproj.local
rename to Demos/TCP/DB/DBServer/Service/DBServerService.dproj.local
index d576f03..b3811b7 100644
--- a/Demos/DB/DBServer/Service/DBServerService.dproj.local
+++ b/Demos/TCP/DB/DBServer/Service/DBServerService.dproj.local
@@ -1,2 +1,2 @@
-
-
+
+
diff --git a/Demos/DB/DBServer/Service/DBServerService.dsk b/Demos/TCP/DB/DBServer/Service/DBServerService.dsk
similarity index 94%
rename from Demos/DB/DBServer/Service/DBServerService.dsk
rename to Demos/TCP/DB/DBServer/Service/DBServerService.dsk
index ea49d38..da4604d 100644
--- a/Demos/DB/DBServer/Service/DBServerService.dsk
+++ b/Demos/TCP/DB/DBServer/Service/DBServerService.dsk
@@ -1,653 +1,653 @@
-[Closed Files]
-File_0=TSourceModule,'\\CODE\Backup\Code Snippets\udpEnvComponents.pas',0,1,15,1,52,0,0,,
-File_1=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDirectPanel.pas',0,1,751,1,762,0,0,,
-File_2=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectX9\uDirect3D9.pas',0,1,2855,5,2866,0,0,,{1,3058,17}{2,3021,11}
-File_3=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPIControls.pas',0,1,67,40,91,0,0,,
-File_4=TSourceModule,'\\CODE\Backup\Code Snippets\udpEnvironment.pas',0,1,76,39,14,0,0,,
-File_5=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Workspace\DirectPanelMultiTexture\ufrmMain.pas',0,1,1,1,13,0,0,,
-File_6=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7.zip',0,1,1,1,1,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Classes.pas',0,1,12189,3,12208,0,0,,
-File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameServer\Service\ufrmEngineEdit.pas',0,1,1,1,1,0,0,,
-File_9=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameEngine\ufrmEditor.pas',0,1,1,12,12,0,0,,
-File_10=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameEngine\ufmSpline.pas',0,1,1,1,1,0,0,,
-File_11=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameEngine\ufmWaveDrawer.pas',0,1,1,1,1,0,0,,
-File_12=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\Netcom7\Source\ncSources.pas',0,1,406,1,423,0,0,,
-File_13=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameServer\Service\uReelGameEngine.pas',0,1,162,11,193,0,0,,
-File_14=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameServer\Service\usvcMain.pas',0,1,165,22,187,0,0,,
-
-[Modules]
-Module0=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dproj
-Module1=default.htm
-Count=2
-EditWindowCount=1
-
-[C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dproj]
-ModuleType=TBaseProject
-
-[default.htm]
-ModuleType=TURLModule
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dpr
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=10000
-Height=9269
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=10000
-ClientHeight=9269
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1896
-LeftPanelClients=DockSite3,PropertyInspector
-LeftPanelData=000008000101000000002D100000000000000168070000000000000100000000A11500001100000050726F7065727479496E73706563746F720100000000C11C000009000000446F636B5369746533FFFFFFFF
-RightPanelSize=2000
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000002D1000000000000001D00700000000000001000000004412000009000000446F636B53697465320100000000C11C000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=1537
-BottomPanelClients=DockSite1,MessageView,DockSite0
-BottomPanelData=0000080001020100000009000000446F636B536974653172450000000000000201060000000000000100000000B922000009000000446F636B53697465300100000000724500000F0000004D65737361676556696577466F726DFFFFFFFF
-BottomMiddlePanelSize=0
-
-[View0]
-CustomEditViewType=TWelcomePageView
-WelcomePageURL=bds:/default.htm
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dpr
-CursorX=1
-CursorY=1
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dpr
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3823
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1135
-TBDockHeight=212
-LRDockWidth=13599
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=1068
-Top=0
-Width=8932
-Height=8519
-MaxLeft=-5
-MaxTop=-10
-MaxWidth=10083
-MaxHeight=10154
-ClientWidth=10000
-ClientHeight=9788
-BottomPanelSize=8926
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2000
-Height=4356
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2000
-ClientHeight=4356
-TBDockHeight=5894
-LRDockWidth=2349
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=960
-Top=23
-Width=5000
-Height=1375
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=5000
-ClientHeight=1375
-TBDockHeight=1375
-LRDockWidth=2771
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2000
-Height=2567
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2000
-ClientHeight=2567
-TBDockHeight=7154
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-1728
-Top=270
-Width=276
-Height=356
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=276
-ClientHeight=356
-TBDockHeight=356
-LRDockWidth=276
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3823
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1135
-TBDockHeight=404
-LRDockWidth=4948
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3823
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1135
-TBDockHeight=212
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=250
-Column4Width=250
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3823
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1135
-TBDockHeight=1538
-LRDockWidth=3479
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3823
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1135
-TBDockHeight=2058
-LRDockWidth=3479
-Dockable=1
-StayOnTop=0
-
-[TFileExplorerForm]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-1418
-Top=-11
-Width=2844
-Height=6212
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2844
-ClientHeight=6212
-TBDockHeight=6212
-LRDockWidth=2844
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=5000
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=5000
-ClientHeight=1135
-TBDockHeight=2317
-LRDockWidth=2823
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=5000
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=5000
-ClientHeight=1135
-TBDockHeight=3212
-LRDockWidth=2823
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=4979
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=4979
-ClientHeight=1135
-TBDockHeight=1154
-LRDockWidth=3677
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2000
-Height=6788
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2000
-ClientHeight=6788
-TBDockHeight=4885
-LRDockWidth=7151
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2000
-Height=6788
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2000
-ClientHeight=6788
-TBDockHeight=4885
-LRDockWidth=5307
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=-99
-Width=1844
-Height=3144
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1844
-ClientHeight=3144
-TBDockHeight=3144
-LRDockWidth=1844
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=23
-Width=1896
-Height=5490
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1896
-ClientHeight=5490
-TBDockHeight=9029
-LRDockWidth=1896
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3823
-Height=1135
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1135
-TBDockHeight=1548
-LRDockWidth=8745
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1896
-Height=1673
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1896
-ClientHeight=1673
-TBDockHeight=3673
-LRDockWidth=1896
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=4260
-Top=2654
-Width=3474
-Height=6779
-MaxLeft=-5
-MaxTop=-10
-ClientWidth=3391
-ClientHeight=6452
-TBDockHeight=6779
-LRDockWidth=3474
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1823
-Height=6173
-MaxLeft=-5
-MaxTop=-10
-ClientWidth=1740
-ClientHeight=5846
-TBDockHeight=6173
-LRDockWidth=1823
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=23
-Width=4979
-Height=1375
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=4979
-ClientHeight=1375
-TBDockHeight=1375
-LRDockWidth=2339
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToDo List
-TabDockClients=RefactoringForm,FindReferencsForm,ToDo List
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=23
-Width=3823
-Height=1375
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3823
-ClientHeight=1375
-TBDockHeight=1375
-LRDockWidth=3823
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=23
-Width=2000
-Height=4596
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2000
-ClientHeight=4596
-TBDockHeight=9029
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorer,TFileExplorerForm
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=621
-Width=1896
-Height=1673
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1896
-ClientHeight=1673
-TBDockHeight=9029
-LRDockWidth=1896
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=528
-Width=2000
-Height=2567
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2000
-ClientHeight=2567
-TBDockHeight=7029
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'\\CODE\Backup\Code Snippets\udpEnvComponents.pas',0,1,15,1,52,0,0,,
+File_1=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDirectPanel.pas',0,1,751,1,762,0,0,,
+File_2=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectX9\uDirect3D9.pas',0,1,2855,5,2866,0,0,,{1,3058,17}{2,3021,11}
+File_3=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPIControls.pas',0,1,67,40,91,0,0,,
+File_4=TSourceModule,'\\CODE\Backup\Code Snippets\udpEnvironment.pas',0,1,76,39,14,0,0,,
+File_5=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Workspace\DirectPanelMultiTexture\ufrmMain.pas',0,1,1,1,13,0,0,,
+File_6=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7.zip',0,1,1,1,1,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Classes.pas',0,1,12189,3,12208,0,0,,
+File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameServer\Service\ufrmEngineEdit.pas',0,1,1,1,1,0,0,,
+File_9=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameEngine\ufrmEditor.pas',0,1,1,12,12,0,0,,
+File_10=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameEngine\ufmSpline.pas',0,1,1,1,1,0,0,,
+File_11=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameEngine\ufmWaveDrawer.pas',0,1,1,1,1,0,0,,
+File_12=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\Netcom7\Source\ncSources.pas',0,1,406,1,423,0,0,,
+File_13=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameServer\Service\uReelGameEngine.pas',0,1,162,11,193,0,0,,
+File_14=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Projects\GameServer\Service\usvcMain.pas',0,1,165,22,187,0,0,,
+
+[Modules]
+Module0=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dproj
+Module1=default.htm
+Count=2
+EditWindowCount=1
+
+[C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dproj]
+ModuleType=TBaseProject
+
+[default.htm]
+ModuleType=TURLModule
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dpr
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=10000
+Height=9269
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=10000
+ClientHeight=9269
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1896
+LeftPanelClients=DockSite3,PropertyInspector
+LeftPanelData=000008000101000000002D100000000000000168070000000000000100000000A11500001100000050726F7065727479496E73706563746F720100000000C11C000009000000446F636B5369746533FFFFFFFF
+RightPanelSize=2000
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000002D1000000000000001D00700000000000001000000004412000009000000446F636B53697465320100000000C11C000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=1537
+BottomPanelClients=DockSite1,MessageView,DockSite0
+BottomPanelData=0000080001020100000009000000446F636B536974653172450000000000000201060000000000000100000000B922000009000000446F636B53697465300100000000724500000F0000004D65737361676556696577466F726DFFFFFFFF
+BottomMiddlePanelSize=0
+
+[View0]
+CustomEditViewType=TWelcomePageView
+WelcomePageURL=bds:/default.htm
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dpr
+CursorX=1
+CursorY=1
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\Service\DBServerService.dpr
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3823
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1135
+TBDockHeight=212
+LRDockWidth=13599
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=1068
+Top=0
+Width=8932
+Height=8519
+MaxLeft=-5
+MaxTop=-10
+MaxWidth=10083
+MaxHeight=10154
+ClientWidth=10000
+ClientHeight=9788
+BottomPanelSize=8926
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2000
+Height=4356
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2000
+ClientHeight=4356
+TBDockHeight=5894
+LRDockWidth=2349
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=960
+Top=23
+Width=5000
+Height=1375
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=5000
+ClientHeight=1375
+TBDockHeight=1375
+LRDockWidth=2771
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2000
+Height=2567
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2000
+ClientHeight=2567
+TBDockHeight=7154
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-1728
+Top=270
+Width=276
+Height=356
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=276
+ClientHeight=356
+TBDockHeight=356
+LRDockWidth=276
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3823
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1135
+TBDockHeight=404
+LRDockWidth=4948
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3823
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1135
+TBDockHeight=212
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=250
+Column4Width=250
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3823
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1135
+TBDockHeight=1538
+LRDockWidth=3479
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3823
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1135
+TBDockHeight=2058
+LRDockWidth=3479
+Dockable=1
+StayOnTop=0
+
+[TFileExplorerForm]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-1418
+Top=-11
+Width=2844
+Height=6212
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2844
+ClientHeight=6212
+TBDockHeight=6212
+LRDockWidth=2844
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=5000
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=5000
+ClientHeight=1135
+TBDockHeight=2317
+LRDockWidth=2823
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=5000
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=5000
+ClientHeight=1135
+TBDockHeight=3212
+LRDockWidth=2823
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=4979
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=4979
+ClientHeight=1135
+TBDockHeight=1154
+LRDockWidth=3677
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2000
+Height=6788
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2000
+ClientHeight=6788
+TBDockHeight=4885
+LRDockWidth=7151
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2000
+Height=6788
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2000
+ClientHeight=6788
+TBDockHeight=4885
+LRDockWidth=5307
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=-99
+Width=1844
+Height=3144
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1844
+ClientHeight=3144
+TBDockHeight=3144
+LRDockWidth=1844
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=23
+Width=1896
+Height=5490
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1896
+ClientHeight=5490
+TBDockHeight=9029
+LRDockWidth=1896
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3823
+Height=1135
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1135
+TBDockHeight=1548
+LRDockWidth=8745
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1896
+Height=1673
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1896
+ClientHeight=1673
+TBDockHeight=3673
+LRDockWidth=1896
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=4260
+Top=2654
+Width=3474
+Height=6779
+MaxLeft=-5
+MaxTop=-10
+ClientWidth=3391
+ClientHeight=6452
+TBDockHeight=6779
+LRDockWidth=3474
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1823
+Height=6173
+MaxLeft=-5
+MaxTop=-10
+ClientWidth=1740
+ClientHeight=5846
+TBDockHeight=6173
+LRDockWidth=1823
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=23
+Width=4979
+Height=1375
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=4979
+ClientHeight=1375
+TBDockHeight=1375
+LRDockWidth=2339
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToDo List
+TabDockClients=RefactoringForm,FindReferencsForm,ToDo List
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=23
+Width=3823
+Height=1375
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3823
+ClientHeight=1375
+TBDockHeight=1375
+LRDockWidth=3823
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=23
+Width=2000
+Height=4596
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2000
+ClientHeight=4596
+TBDockHeight=9029
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorer,TFileExplorerForm
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=621
+Width=1896
+Height=1673
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1896
+ClientHeight=1673
+TBDockHeight=9029
+LRDockWidth=1896
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=528
+Width=2000
+Height=2567
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2000
+ClientHeight=2567
+TBDockHeight=7029
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/DB/DBServer/Service/DBServerService.identcache b/Demos/TCP/DB/DBServer/Service/DBServerService.identcache
similarity index 100%
rename from Demos/DB/DBServer/Service/DBServerService.identcache
rename to Demos/TCP/DB/DBServer/Service/DBServerService.identcache
diff --git a/Demos/DB/DBServer/Service/DBServerService.res b/Demos/TCP/DB/DBServer/Service/DBServerService.res
similarity index 100%
rename from Demos/DB/DBServer/Service/DBServerService.res
rename to Demos/TCP/DB/DBServer/Service/DBServerService.res
diff --git a/Demos/DB/DBServer/Service/DBServerService.skincfg b/Demos/TCP/DB/DBServer/Service/DBServerService.skincfg
similarity index 94%
rename from Demos/DB/DBServer/Service/DBServerService.skincfg
rename to Demos/TCP/DB/DBServer/Service/DBServerService.skincfg
index 6870d73..d58e821 100644
--- a/Demos/DB/DBServer/Service/DBServerService.skincfg
+++ b/Demos/TCP/DB/DBServer/Service/DBServerService.skincfg
@@ -1,33 +1,33 @@
-[ExpressSkins]
-Default=1
-ShowNotifications=1
-Enabled=1
-dxSkinBlack=0
-dxSkinBlue=0
-dxSkinCaramel=0
-dxSkinCoffee=0
-dxSkinDarkRoom=0
-dxSkinDarkSide=0
-dxSkinFoggy=0
-dxSkinGlassOceans=0
-dxSkiniMaginary=0
-dxSkinLilian=0
-dxSkinLiquidSky=0
-dxSkinLondonLiquidSky=0
-dxSkinMcSkin=0
-dxSkinMoneyTwins=0
-dxSkinOffice2007Black=0
-dxSkinOffice2007Blue=0
-dxSkinOffice2007Green=0
-dxSkinOffice2007Pink=0
-dxSkinOffice2007Silver=0
-dxSkinPumpkin=0
-dxSkinSeven=0
-dxSkinSharp=0
-dxSkinSilver=0
-dxSkinSpringTime=0
-dxSkinStardust=0
-dxSkinSummer2008=0
-dxSkinsDefaultPainters=0
-dxSkinValentine=0
-dxSkinXmas2008Blue=0
+[ExpressSkins]
+Default=1
+ShowNotifications=1
+Enabled=1
+dxSkinBlack=0
+dxSkinBlue=0
+dxSkinCaramel=0
+dxSkinCoffee=0
+dxSkinDarkRoom=0
+dxSkinDarkSide=0
+dxSkinFoggy=0
+dxSkinGlassOceans=0
+dxSkiniMaginary=0
+dxSkinLilian=0
+dxSkinLiquidSky=0
+dxSkinLondonLiquidSky=0
+dxSkinMcSkin=0
+dxSkinMoneyTwins=0
+dxSkinOffice2007Black=0
+dxSkinOffice2007Blue=0
+dxSkinOffice2007Green=0
+dxSkinOffice2007Pink=0
+dxSkinOffice2007Silver=0
+dxSkinPumpkin=0
+dxSkinSeven=0
+dxSkinSharp=0
+dxSkinSilver=0
+dxSkinSpringTime=0
+dxSkinStardust=0
+dxSkinSummer2008=0
+dxSkinsDefaultPainters=0
+dxSkinValentine=0
+dxSkinXmas2008Blue=0
diff --git a/Demos/DB/DBServer/Service/DBServerService_Icon.ico b/Demos/TCP/DB/DBServer/Service/DBServerService_Icon.ico
similarity index 100%
rename from Demos/DB/DBServer/Service/DBServerService_Icon.ico
rename to Demos/TCP/DB/DBServer/Service/DBServerService_Icon.ico
diff --git a/Demos/DB/DBServer/Service/uscvServiceCommands.pas b/Demos/TCP/DB/DBServer/Service/uscvServiceCommands.pas
similarity index 89%
rename from Demos/DB/DBServer/Service/uscvServiceCommands.pas
rename to Demos/TCP/DB/DBServer/Service/uscvServiceCommands.pas
index b118f32..0cf3444 100644
--- a/Demos/DB/DBServer/Service/uscvServiceCommands.pas
+++ b/Demos/TCP/DB/DBServer/Service/uscvServiceCommands.pas
@@ -1,7 +1,7 @@
-unit uscvServiceCommands;
-
-interface
-
-implementation
-
-end.
+unit uscvServiceCommands;
+
+interface
+
+implementation
+
+end.
diff --git a/Demos/DB/DBServer/Service/usvcMain.dfm b/Demos/TCP/DB/DBServer/Service/usvcMain.dfm
similarity index 96%
rename from Demos/DB/DBServer/Service/usvcMain.dfm
rename to Demos/TCP/DB/DBServer/Service/usvcMain.dfm
index e20e9aa..6bf834e 100644
--- a/Demos/DB/DBServer/Service/usvcMain.dfm
+++ b/Demos/TCP/DB/DBServer/Service/usvcMain.dfm
@@ -1,33 +1,33 @@
-object NetcomDataServer: TNetcomDataServer
- OldCreateOrder = False
- OnCreate = ServiceCreate
- OnDestroy = ServiceDestroy
- DisplayName = 'Netcom7 Database Server'
- OnShutdown = ServiceShutdown
- OnStart = ServiceStart
- OnStop = ServiceStop
- Height = 254
- Width = 270
- object srvController: TncServerSource
- Port = 18753
- EncryptionKey = 'SetEncryptionKey'
- Left = 40
- Top = 32
- end
- object DBServer: TncDBServer
- ADOConnection = ADOConnection
- Source = srvController
- Left = 40
- Top = 92
- end
- object ADOConnection: TADOConnection
- ConnectionString =
- 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\..\TestData\Custo' +
- 'mers.mdb;Persist Security Info=False;'
- LoginPrompt = False
- Mode = cmShareDenyNone
- Provider = 'Microsoft.Jet.OLEDB.4.0'
- Left = 128
- Top = 92
- end
-end
+object NetcomDataServer: TNetcomDataServer
+ OldCreateOrder = False
+ OnCreate = ServiceCreate
+ OnDestroy = ServiceDestroy
+ DisplayName = 'Netcom7 Database Server'
+ OnShutdown = ServiceShutdown
+ OnStart = ServiceStart
+ OnStop = ServiceStop
+ Height = 254
+ Width = 270
+ object srvController: TncServerSource
+ Port = 18753
+ EncryptionKey = 'SetEncryptionKey'
+ Left = 40
+ Top = 32
+ end
+ object DBServer: TncDBServer
+ ADOConnection = ADOConnection
+ Source = srvController
+ Left = 40
+ Top = 92
+ end
+ object ADOConnection: TADOConnection
+ ConnectionString =
+ 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\..\TestData\Custo' +
+ 'mers.mdb;Persist Security Info=False;'
+ LoginPrompt = False
+ Mode = cmShareDenyNone
+ Provider = 'Microsoft.Jet.OLEDB.4.0'
+ Left = 128
+ Top = 92
+ end
+end
diff --git a/Demos/DB/DBServer/Service/usvcMain.pas b/Demos/TCP/DB/DBServer/Service/usvcMain.pas
similarity index 96%
rename from Demos/DB/DBServer/Service/usvcMain.pas
rename to Demos/TCP/DB/DBServer/Service/usvcMain.pas
index 5d1b42b..3f7d228 100644
--- a/Demos/DB/DBServer/Service/usvcMain.pas
+++ b/Demos/TCP/DB/DBServer/Service/usvcMain.pas
@@ -1,184 +1,184 @@
-unit usvcMain;
-
-interface
-
-uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
- ncSources, ncSockets, Registry, DB, ADODB, ncCommandHandlers, ncDBSrv, ActiveX;
-
-type
- TsvcOnLogMessage = procedure(Sender: TObject; aMessage: string; aError: Boolean = False) of object;
-
- // Name property is the name we are going to use to uniquelly identify our service
- TNetcomDataServer = class(TService)
- srvController: TncServerSource;
- DBServer: TncDBServer;
- ADOConnection: TADOConnection;
- procedure ServiceCreate(Sender: TObject);
- procedure ServiceDestroy(Sender: TObject);
- procedure ServiceStart(Sender: TService; var Started: Boolean);
- procedure ServiceStop(Sender: TService; var Stopped: Boolean);
- procedure ServiceShutdown(Sender: TService);
- private
- FOnLogMessage: TsvcOnLogMessage;
- function GetServicePort: Integer;
- procedure SetServicePort(const Value: Integer);
- function GetDBConnectionString: string;
- procedure SetDBConnectionString(const Value: string);
- procedure StopAndShutdown;
- function GetCacheResponses: Boolean;
- procedure SetCacheResponses(const Value: Boolean);
- public
- Settings: TRegistry;
- procedure Log(aStr: string; aError: Boolean = False);
- function GetServiceController: TServiceController; override;
- property OnLogMessage: TsvcOnLogMessage read FOnLogMessage write FOnLogMessage;
- property ServicePort: Integer read GetServicePort write SetServicePort;
- property DBConnectionString: string read GetDBConnectionString write SetDBConnectionString;
- property CacheResponses: Boolean read GetCacheResponses write SetCacheResponses;
- end;
-
-var
- Service: TNetcomDataServer;
-
-implementation
-
-uses uscvServiceCommands;
-{$R *.DFM}
-
-procedure ServiceController(CtrlCode: DWord); stdcall;
-begin
- Service.Controller(CtrlCode);
-end;
-
-function TNetcomDataServer.GetServiceController: TServiceController;
-begin
- Result := ServiceController;
-end;
-
-procedure TNetcomDataServer.ServiceCreate(Sender: TObject);
-begin
- FOnLogMessage := nil;
- Settings := TRegistry.Create(KEY_READ or KEY_WRITE);
- Settings.LazyWrite := False;
- Settings.RootKey := HKEY_CURRENT_USER;
- if not Settings.OpenKey('\HKEY_CURRENT_USER\Software\' + Name, True) then
- Log('Cannot open settings key: \HKEY_CURRENT_USER\Software\' + Name);
-end;
-
-procedure TNetcomDataServer.ServiceDestroy(Sender: TObject);
-begin
- Settings.CloseKey;
- Settings.Free;
-end;
-
-procedure TNetcomDataServer.Log(aStr: string; aError: Boolean = False);
-var
- ErrType: DWord;
-begin
- if Assigned(FOnLogMessage) then
- // Call custom handler
- FOnLogMessage(Self, aStr, aError)
- else
- begin
- // Write to windows log system
- if aError then
- ErrType := EVENTLOG_AUDIT_FAILURE
- else
- ErrType := EVENTLOG_AUDIT_SUCCESS;
- Self.LogMessage(aStr, ErrType);
- end;
-end;
-
-procedure TNetcomDataServer.ServiceStart(Sender: TService; var Started: Boolean);
-begin
- try
- CoInitialize(nil);
- // Put critical startup code here
- srvController.Port := ServicePort;
- ADOConnection.ConnectionString := DBConnectionString;
- DBServer.CacheResponses := CacheResponses;
-
- ADOConnection.Connected := True;
- srvController.Active := True;
-
- Log('"' + DisplayName + '" (' + Name + ') service started successfully, on port: ' + IntTostr(srvController.Port));
- except
- on E: Exception do
- begin
- Log('"' + DisplayName + '" (' + Name + ') service failed to start. ' + E.Message, True);
- Started := False;
- end;
- end;
-end;
-
-procedure TNetcomDataServer.ServiceStop(Sender: TService; var Stopped: Boolean);
-begin
- StopAndShutdown;
-
- Log('"' + DisplayName + '" service stopped successfully');
-end;
-
-procedure TNetcomDataServer.ServiceShutdown(Sender: TService);
-begin
- StopAndShutdown;
-
- Log('"' + DisplayName + '" service stopped successfully');
-end;
-
-procedure TNetcomDataServer.StopAndShutdown;
-begin
- srvController.Active := False;
- ADOConnection.Connected := False;
- CoUninitialize;
-end;
-
-function TNetcomDataServer.GetServicePort: Integer;
-begin
- try
- if not Settings.ValueExists('ServicePort') then
- Abort;
- Result := Settings.ReadInteger('ServicePort');
- except
- Result := srvController.Port;
- end;
-end;
-
-procedure TNetcomDataServer.SetServicePort(const Value: Integer);
-begin
- Settings.WriteInteger('ServicePort', Value);
-end;
-
-function TNetcomDataServer.GetDBConnectionString: string;
-begin
- try
- if not Settings.ValueExists('DBConnection') then
- Abort;
- Result := Settings.ReadString('DBConnection');
- except
- Result := ADOConnection.ConnectionString;
- end;
-end;
-
-procedure TNetcomDataServer.SetDBConnectionString(const Value: string);
-begin
- Settings.WriteString('DBConnection', Value);
-end;
-
-function TNetcomDataServer.GetCacheResponses: Boolean;
-begin
- try
- if not Settings.ValueExists('CacheResponses') then
- Abort;
- Result := Settings.ReadBool('CacheResponses');
- except
- Result := DBServer.CacheResponses;
- end;
-end;
-
-procedure TNetcomDataServer.SetCacheResponses(const Value: Boolean);
-begin
- Settings.WriteBool('CacheResponses', Value);
-end;
-
-end.
+unit usvcMain;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
+ ncSources, ncSockets, Registry, DB, ADODB, ncCommandHandlers, ncDBSrv, ActiveX;
+
+type
+ TsvcOnLogMessage = procedure(Sender: TObject; aMessage: string; aError: Boolean = False) of object;
+
+ // Name property is the name we are going to use to uniquelly identify our service
+ TNetcomDataServer = class(TService)
+ srvController: TncServerSource;
+ DBServer: TncDBServer;
+ ADOConnection: TADOConnection;
+ procedure ServiceCreate(Sender: TObject);
+ procedure ServiceDestroy(Sender: TObject);
+ procedure ServiceStart(Sender: TService; var Started: Boolean);
+ procedure ServiceStop(Sender: TService; var Stopped: Boolean);
+ procedure ServiceShutdown(Sender: TService);
+ private
+ FOnLogMessage: TsvcOnLogMessage;
+ function GetServicePort: Integer;
+ procedure SetServicePort(const Value: Integer);
+ function GetDBConnectionString: string;
+ procedure SetDBConnectionString(const Value: string);
+ procedure StopAndShutdown;
+ function GetCacheResponses: Boolean;
+ procedure SetCacheResponses(const Value: Boolean);
+ public
+ Settings: TRegistry;
+ procedure Log(aStr: string; aError: Boolean = False);
+ function GetServiceController: TServiceController; override;
+ property OnLogMessage: TsvcOnLogMessage read FOnLogMessage write FOnLogMessage;
+ property ServicePort: Integer read GetServicePort write SetServicePort;
+ property DBConnectionString: string read GetDBConnectionString write SetDBConnectionString;
+ property CacheResponses: Boolean read GetCacheResponses write SetCacheResponses;
+ end;
+
+var
+ Service: TNetcomDataServer;
+
+implementation
+
+uses uscvServiceCommands;
+{$R *.DFM}
+
+procedure ServiceController(CtrlCode: DWord); stdcall;
+begin
+ Service.Controller(CtrlCode);
+end;
+
+function TNetcomDataServer.GetServiceController: TServiceController;
+begin
+ Result := ServiceController;
+end;
+
+procedure TNetcomDataServer.ServiceCreate(Sender: TObject);
+begin
+ FOnLogMessage := nil;
+ Settings := TRegistry.Create(KEY_READ or KEY_WRITE);
+ Settings.LazyWrite := False;
+ Settings.RootKey := HKEY_CURRENT_USER;
+ if not Settings.OpenKey('\HKEY_CURRENT_USER\Software\' + Name, True) then
+ Log('Cannot open settings key: \HKEY_CURRENT_USER\Software\' + Name);
+end;
+
+procedure TNetcomDataServer.ServiceDestroy(Sender: TObject);
+begin
+ Settings.CloseKey;
+ Settings.Free;
+end;
+
+procedure TNetcomDataServer.Log(aStr: string; aError: Boolean = False);
+var
+ ErrType: DWord;
+begin
+ if Assigned(FOnLogMessage) then
+ // Call custom handler
+ FOnLogMessage(Self, aStr, aError)
+ else
+ begin
+ // Write to windows log system
+ if aError then
+ ErrType := EVENTLOG_AUDIT_FAILURE
+ else
+ ErrType := EVENTLOG_AUDIT_SUCCESS;
+ Self.LogMessage(aStr, ErrType);
+ end;
+end;
+
+procedure TNetcomDataServer.ServiceStart(Sender: TService; var Started: Boolean);
+begin
+ try
+ CoInitialize(nil);
+ // Put critical startup code here
+ srvController.Port := ServicePort;
+ ADOConnection.ConnectionString := DBConnectionString;
+ DBServer.CacheResponses := CacheResponses;
+
+ ADOConnection.Connected := True;
+ srvController.Active := True;
+
+ Log('"' + DisplayName + '" (' + Name + ') service started successfully, on port: ' + IntTostr(srvController.Port));
+ except
+ on E: Exception do
+ begin
+ Log('"' + DisplayName + '" (' + Name + ') service failed to start. ' + E.Message, True);
+ Started := False;
+ end;
+ end;
+end;
+
+procedure TNetcomDataServer.ServiceStop(Sender: TService; var Stopped: Boolean);
+begin
+ StopAndShutdown;
+
+ Log('"' + DisplayName + '" service stopped successfully');
+end;
+
+procedure TNetcomDataServer.ServiceShutdown(Sender: TService);
+begin
+ StopAndShutdown;
+
+ Log('"' + DisplayName + '" service stopped successfully');
+end;
+
+procedure TNetcomDataServer.StopAndShutdown;
+begin
+ srvController.Active := False;
+ ADOConnection.Connected := False;
+ CoUninitialize;
+end;
+
+function TNetcomDataServer.GetServicePort: Integer;
+begin
+ try
+ if not Settings.ValueExists('ServicePort') then
+ Abort;
+ Result := Settings.ReadInteger('ServicePort');
+ except
+ Result := srvController.Port;
+ end;
+end;
+
+procedure TNetcomDataServer.SetServicePort(const Value: Integer);
+begin
+ Settings.WriteInteger('ServicePort', Value);
+end;
+
+function TNetcomDataServer.GetDBConnectionString: string;
+begin
+ try
+ if not Settings.ValueExists('DBConnection') then
+ Abort;
+ Result := Settings.ReadString('DBConnection');
+ except
+ Result := ADOConnection.ConnectionString;
+ end;
+end;
+
+procedure TNetcomDataServer.SetDBConnectionString(const Value: string);
+begin
+ Settings.WriteString('DBConnection', Value);
+end;
+
+function TNetcomDataServer.GetCacheResponses: Boolean;
+begin
+ try
+ if not Settings.ValueExists('CacheResponses') then
+ Abort;
+ Result := Settings.ReadBool('CacheResponses');
+ except
+ Result := DBServer.CacheResponses;
+ end;
+end;
+
+procedure TNetcomDataServer.SetCacheResponses(const Value: Boolean);
+begin
+ Settings.WriteBool('CacheResponses', Value);
+end;
+
+end.
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dpr b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dpr
similarity index 96%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.dpr
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dpr
index b3628dc..ecaa008 100644
--- a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dpr
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dpr
@@ -1,24 +1,24 @@
-program DBServerApplication;
-
-uses
- Forms,
- ufrmMain in 'ufrmMain.pas' { frmMain } ,
- uscvServiceCommands in '..\Service\uscvServiceCommands.pas',
- usvcMain in '..\Service\usvcMain.pas' { svcMain: TService } ;
-{$R *.res}
-
-begin
- ReportMemoryLeaksOnShutdown := True;
-
- Application.Initialize;
- Application.MainFormOnTaskbar := True;
- Application.ShowMainForm := False;
- Service := TNetcomDataServer.Create(nil);
- try
- Application.Title := Service.DisplayName;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
- finally
- Service.Free;
- end;
-end.
+program DBServerApplication;
+
+uses
+ Forms,
+ ufrmMain in 'ufrmMain.pas' { frmMain } ,
+ uscvServiceCommands in '..\Service\uscvServiceCommands.pas',
+ usvcMain in '..\Service\usvcMain.pas' { svcMain: TService } ;
+{$R *.res}
+
+begin
+ ReportMemoryLeaksOnShutdown := True;
+
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.ShowMainForm := False;
+ Service := TNetcomDataServer.Create(nil);
+ try
+ Application.Title := Service.DisplayName;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+ finally
+ Service.Free;
+ end;
+end.
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dproj b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dproj
similarity index 98%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.dproj
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dproj
index 6cfbacf..d5c8e07 100644
--- a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dproj
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dproj
@@ -1,220 +1,220 @@
-
-
- {7EC35961-3AF1-4464-AC69-01EF47AFB21B}
- 18.8
- DBServerApplication.dpr
- Release
- DCC32
- VCL
- True
- Win32
- 37889
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- DBServerApplication.exe
- $(BDSCOMMONDIR)\DCU
- $(BDSCOMMONDIR)\DCP
- vcl;rtl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dxSkinscxPCPainterD14;cxPageControlD14;dxSkinsCoreD14;dxSkinsdxLCPainterD14;dxLayoutControlD14;dxSkinscxScheduler3PainterD14;cxSchedulerD14;dxSkinsdxNavBar2PainterD14;dxNavBarD14;dxSkinsdxDLPainterD14;dxDockingD14;dxSkinsdxRibbonPainterD14;dxRibbonD14;dxBarD14;dxSkinsdxBarPainterD14;dclOfficeXP;$(DCC_UsePackage)
- 00400000
- x86
- true
- DBServerApplication
- Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Data.Win;Winapi;System.Win;$(DCC_Namespace)
- true
- true
- 175
- 1033
- CompanyName=Simetron Informatics;FileDescription=Netcom7 DBServer Application;FileVersion=1.0.0.175;InternalName=;LegalCopyright=Copyright (c) 1998-2011 Simetron;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0
-
-
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
- 1033
- $(BDS)\bin\default_app.manifest
- DBServerApplication_Icon.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- $(BDS)\bin\default_app.manifest
- DBServerApplication_Icon.ico
- true
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- false
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- DEBUG;$(DCC_Define)
-
-
- Debug
-
-
- Debug
-
-
- Debug
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
-
-
-
-
- TService
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
-
- Delphi.Personality.12
-
-
-
-
- DBServerApplication.dpr
-
-
- False
- True
- False
-
-
- True
- True
- 1
- 0
- 0
- 175
- False
- False
- False
- False
- False
- 1033
- 1200
-
-
- Simetron Informatics
- Netcom7 DBServer Application
- 1.0.0.175
-
- Copyright (c) 1998-2011 Simetron
-
-
-
- 1.0.0.0
-
-
- Embarcadero C++Builder Office XP Servers Package
- Embarcadero C++Builder Office 2000 Servers Package
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- ExpressPivotGrid 2 OLAP by Developer Express Inc.
-
-
-
- True
- True
- True
- True
- False
-
-
- 12
-
-
-
+
+
+ {7EC35961-3AF1-4464-AC69-01EF47AFB21B}
+ 18.8
+ DBServerApplication.dpr
+ Release
+ DCC32
+ VCL
+ True
+ Win32
+ 37889
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ DBServerApplication.exe
+ $(BDSCOMMONDIR)\DCU
+ $(BDSCOMMONDIR)\DCP
+ vcl;rtl;vclx;vclactnband;xmlrtl;vclimg;dbrtl;vcldb;vcldbx;bdertl;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dxSkinscxPCPainterD14;cxPageControlD14;dxSkinsCoreD14;dxSkinsdxLCPainterD14;dxLayoutControlD14;dxSkinscxScheduler3PainterD14;cxSchedulerD14;dxSkinsdxNavBar2PainterD14;dxNavBarD14;dxSkinsdxDLPainterD14;dxDockingD14;dxSkinsdxRibbonPainterD14;dxRibbonD14;dxBarD14;dxSkinsdxBarPainterD14;dclOfficeXP;$(DCC_UsePackage)
+ 00400000
+ x86
+ true
+ DBServerApplication
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Data.Win;Winapi;System.Win;$(DCC_Namespace)
+ true
+ true
+ 175
+ 1033
+ CompanyName=Simetron Informatics;FileDescription=Netcom7 DBServer Application;FileVersion=1.0.0.175;InternalName=;LegalCopyright=Copyright (c) 1998-2011 Simetron;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0
+
+
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ DBServerApplication_Icon.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\default_app.manifest
+ DBServerApplication_Icon.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ false
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ DEBUG;$(DCC_Define)
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+
+
+ TService
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ DBServerApplication.dpr
+
+
+ False
+ True
+ False
+
+
+ True
+ True
+ 1
+ 0
+ 0
+ 175
+ False
+ False
+ False
+ False
+ False
+ 1033
+ 1200
+
+
+ Simetron Informatics
+ Netcom7 DBServer Application
+ 1.0.0.175
+
+ Copyright (c) 1998-2011 Simetron
+
+
+
+ 1.0.0.0
+
+
+ Embarcadero C++Builder Office XP Servers Package
+ Embarcadero C++Builder Office 2000 Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ ExpressPivotGrid 2 OLAP by Developer Express Inc.
+
+
+
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dproj.local b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dproj.local
similarity index 99%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.dproj.local
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dproj.local
index 1a86a44..86b675f 100644
--- a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dproj.local
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dproj.local
@@ -1,11 +1,11 @@
-
-
-
- 2011/04/04 13:08:58.034.dfm,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ufrmMain.dfm=C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.dfm
- 2011/04/04 13:08:58.034.pas,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ufrmMain.pas=C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.pas
- 2011/04/04 13:09:06.196.dproj,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ServiceConsole.dproj=C:\Users\BDemos\Documents\RAD Studio\Projects\Project1.dproj
- 2011/04/05 09:14:37.644.dproj,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ServiceApplication.dproj=C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ServiceConsole.dproj
- 2011/04/06 10:27:07.382.dproj,C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\DBServerApplication.dproj=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ServiceApplication.dproj
-
-
-
+
+
+
+ 2011/04/04 13:08:58.034.dfm,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ufrmMain.dfm=C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.dfm
+ 2011/04/04 13:08:58.034.pas,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ufrmMain.pas=C:\Users\BDemos\Documents\RAD Studio\Projects\Unit1.pas
+ 2011/04/04 13:09:06.196.dproj,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ServiceConsole.dproj=C:\Users\BDemos\Documents\RAD Studio\Projects\Project1.dproj
+ 2011/04/05 09:14:37.644.dproj,C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ServiceApplication.dproj=C:\Users\BDemos\Documents\RAD Studio\Workspace\TrayLogServiceModule\ServiceConsole\ServiceConsole.dproj
+ 2011/04/06 10:27:07.382.dproj,C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\DBServerApplication.dproj=C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ServiceApplication.dproj
+
+
+
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dsk b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dsk
similarity index 94%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.dsk
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dsk
index 8faeb9d..af4c73c 100644
--- a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.dsk
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.dsk
@@ -1,768 +1,768 @@
-[Closed Files]
-File_0=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\RTL\SYS\System.pas',0,1,4091,1,4109,0,0,,
-File_1=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Classes.pas',0,1,5241,8,5266,0,0,,
-File_2=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\Netcom7\Source\ncSockets.pas',0,1,1547,1,1565,0,0,,
-File_3=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Registry.pas',0,1,711,1,729,0,0,,
-File_4=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\RTL\SYS\SysUtils.pas',0,1,15677,5,15519,0,0,,
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\Forms.pas',0,1,1259,1,1279,0,0,,
-File_6=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\ExtCtrls.pas',0,1,1894,3,1856,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\Controls.pas',0,1,2514,1,2533,0,0,,
-File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncDBCnt.pas',0,1,250,30,259,0,0,,
-File_9=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\Netcom7\Source\ncDBCommands.pas',0,1,1,23,11,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ufrmMain.pas
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas]
-ModuleType=TSourceModule
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1844
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000134070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=762
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001FA0200000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ufrmMain.pas
-CursorX=1
-CursorY=1
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas
-CursorX=1
-CursorY=1
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=762
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=762
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1844
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1844
-ClientHeight=4674
-TBDockHeight=4674
-LRDockWidth=1844
-Dockable=1
-StayOnTop=0
-SplitPos=110
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Name,ADOConnection
-ExpandedItems=ADOConnection=0,"LiveBindings Designer=0",Source=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3488
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3488
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=0
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=0
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-344
-Top=-389
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1844
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1844
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=0
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=0
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=762
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=762
-ClientHeight=4477
-TBDockHeight=4477
-LRDockWidth=762
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1844
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1844
-ClientHeight=3419
-TBDockHeight=3419
-LRDockWidth=1844
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=762
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=762
-ClientHeight=3616
-TBDockHeight=3616
-LRDockWidth=762
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\RTL\SYS\System.pas',0,1,4091,1,4109,0,0,,
+File_1=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Classes.pas',0,1,5241,8,5266,0,0,,
+File_2=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\Netcom7\Source\ncSockets.pas',0,1,1547,1,1565,0,0,,
+File_3=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\source\Win32\rtl\common\Registry.pas',0,1,711,1,729,0,0,,
+File_4=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\RTL\SYS\SysUtils.pas',0,1,15677,5,15519,0,0,,
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\Forms.pas',0,1,1259,1,1279,0,0,,
+File_6=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\ExtCtrls.pas',0,1,1894,3,1856,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\Controls.pas',0,1,2514,1,2533,0,0,,
+File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncDBCnt.pas',0,1,250,30,259,0,0,,
+File_9=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\Netcom7\Source\ncDBCommands.pas',0,1,1,23,11,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ufrmMain.pas
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas]
+ModuleType=TSourceModule
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1844
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000134070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=762
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001FA0200000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\ServiceApplication\ufrmMain.pas
+CursorX=1
+CursorY=1
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\DB\DBServer\Service\usvcMain.pas
+CursorX=1
+CursorY=1
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=762
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=762
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1844
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1844
+ClientHeight=4674
+TBDockHeight=4674
+LRDockWidth=1844
+Dockable=1
+StayOnTop=0
+SplitPos=110
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Name,ADOConnection
+ExpandedItems=ADOConnection=0,"LiveBindings Designer=0",Source=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3488
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3488
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=0
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=0
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-344
+Top=-389
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1844
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1844
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=0
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=0
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=762
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=762
+ClientHeight=4477
+TBDockHeight=4477
+LRDockWidth=762
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1844
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1844
+ClientHeight=3419
+TBDockHeight=3419
+LRDockWidth=1844
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=762
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=762
+ClientHeight=3616
+TBDockHeight=3616
+LRDockWidth=762
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.identcache b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.identcache
similarity index 100%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.identcache
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.identcache
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.res b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.res
similarity index 100%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.res
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.res
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.skincfg b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.skincfg
similarity index 94%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication.skincfg
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.skincfg
index 6870d73..d58e821 100644
--- a/Demos/DB/DBServer/ServiceApplication/DBServerApplication.skincfg
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication.skincfg
@@ -1,33 +1,33 @@
-[ExpressSkins]
-Default=1
-ShowNotifications=1
-Enabled=1
-dxSkinBlack=0
-dxSkinBlue=0
-dxSkinCaramel=0
-dxSkinCoffee=0
-dxSkinDarkRoom=0
-dxSkinDarkSide=0
-dxSkinFoggy=0
-dxSkinGlassOceans=0
-dxSkiniMaginary=0
-dxSkinLilian=0
-dxSkinLiquidSky=0
-dxSkinLondonLiquidSky=0
-dxSkinMcSkin=0
-dxSkinMoneyTwins=0
-dxSkinOffice2007Black=0
-dxSkinOffice2007Blue=0
-dxSkinOffice2007Green=0
-dxSkinOffice2007Pink=0
-dxSkinOffice2007Silver=0
-dxSkinPumpkin=0
-dxSkinSeven=0
-dxSkinSharp=0
-dxSkinSilver=0
-dxSkinSpringTime=0
-dxSkinStardust=0
-dxSkinSummer2008=0
-dxSkinsDefaultPainters=0
-dxSkinValentine=0
-dxSkinXmas2008Blue=0
+[ExpressSkins]
+Default=1
+ShowNotifications=1
+Enabled=1
+dxSkinBlack=0
+dxSkinBlue=0
+dxSkinCaramel=0
+dxSkinCoffee=0
+dxSkinDarkRoom=0
+dxSkinDarkSide=0
+dxSkinFoggy=0
+dxSkinGlassOceans=0
+dxSkiniMaginary=0
+dxSkinLilian=0
+dxSkinLiquidSky=0
+dxSkinLondonLiquidSky=0
+dxSkinMcSkin=0
+dxSkinMoneyTwins=0
+dxSkinOffice2007Black=0
+dxSkinOffice2007Blue=0
+dxSkinOffice2007Green=0
+dxSkinOffice2007Pink=0
+dxSkinOffice2007Silver=0
+dxSkinPumpkin=0
+dxSkinSeven=0
+dxSkinSharp=0
+dxSkinSilver=0
+dxSkinSpringTime=0
+dxSkinStardust=0
+dxSkinSummer2008=0
+dxSkinsDefaultPainters=0
+dxSkinValentine=0
+dxSkinXmas2008Blue=0
diff --git a/Demos/DB/DBServer/ServiceApplication/DBServerApplication_Icon.ico b/Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication_Icon.ico
similarity index 100%
rename from Demos/DB/DBServer/ServiceApplication/DBServerApplication_Icon.ico
rename to Demos/TCP/DB/DBServer/ServiceApplication/DBServerApplication_Icon.ico
diff --git a/Demos/DB/DBServer/ServiceApplication/ufrmMain.dfm b/Demos/TCP/DB/DBServer/ServiceApplication/ufrmMain.dfm
similarity index 96%
rename from Demos/DB/DBServer/ServiceApplication/ufrmMain.dfm
rename to Demos/TCP/DB/DBServer/ServiceApplication/ufrmMain.dfm
index 688129e..1bba110 100644
--- a/Demos/DB/DBServer/ServiceApplication/ufrmMain.dfm
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/ufrmMain.dfm
@@ -1,316 +1,316 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- ActiveControl = memLog
- Caption = 'Netcom7 Database Server Management'
- ClientHeight = 388
- ClientWidth = 1030
- Color = clBtnFace
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Tahoma'
- Font.Style = []
- OldCreateOrder = False
- ScreenSnap = True
- ShowHint = True
- OnClose = FormClose
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- PixelsPerInch = 96
- TextHeight = 13
- object Splitter1: TSplitter
- Left = 257
- Top = 50
- Height = 338
- ExplicitLeft = 308
- ExplicitTop = 276
- ExplicitHeight = 100
- end
- object pnlCaption: TPanel
- Left = 0
- Top = 0
- Width = 1030
- Height = 50
- Align = alTop
- BevelOuter = bvNone
- Caption = 'In-memory service - stopped'
- Color = clBlack
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWhite
- Font.Height = -27
- Font.Name = 'Tahoma'
- Font.Style = []
- ParentBackground = False
- ParentFont = False
- TabOrder = 0
- end
- object memLog: TMemo
- Left = 260
- Top = 50
- Width = 770
- Height = 338
- Align = alClient
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Courier New'
- Font.Style = []
- ParentFont = False
- ReadOnly = True
- ScrollBars = ssBoth
- TabOrder = 2
- WordWrap = False
- end
- object CategoryPanelGroup1: TCategoryPanelGroup
- Left = 0
- Top = 50
- Width = 257
- Height = 338
- VertScrollBar.Tracking = True
- BevelInner = bvNone
- BevelOuter = bvNone
- ChevronAlignment = taRightJustify
- Color = clGradientActiveCaption
- HeaderAlignment = taRightJustify
- HeaderFont.Charset = DEFAULT_CHARSET
- HeaderFont.Color = clWindowText
- HeaderFont.Height = -11
- HeaderFont.Name = 'Tahoma'
- HeaderFont.Style = []
- Padding.Left = 3
- Padding.Top = 3
- Padding.Right = 3
- Padding.Bottom = 3
- TabOrder = 1
- object CategoryPanel3: TCategoryPanel
- AlignWithMargins = True
- Top = 204
- Height = 65
- Caption = 'Startup'
- TabOrder = 2
- object cbAutorunLogon: TCheckBox
- AlignWithMargins = True
- Left = 7
- Top = 3
- Width = 163
- Height = 33
- Hint =
- 'Check this if you want to run this program instead of the servic' +
- 'e for testing over time. This application will launch with windo' +
- 'ws logon.'
- Margins.Left = 7
- Margins.Right = 7
- Align = alLeft
- Caption = 'Autorun with Windows logon'
- TabOrder = 0
- OnClick = cbAutorunLogonClick
- end
- end
- object cpConnection: TCategoryPanel
- AlignWithMargins = True
- Top = 77
- Height = 121
- Caption = 'Engine Settings'
- TabOrder = 1
- object GridPanel1: TGridPanel
- AlignWithMargins = True
- Left = 7
- Top = 7
- Width = 227
- Height = 81
- Margins.Left = 7
- Margins.Top = 7
- Margins.Right = 7
- Margins.Bottom = 7
- Align = alClient
- BevelOuter = bvNone
- ColumnCollection = <
- item
- Value = 100.000000000000000000
- end>
- ControlCollection = <
- item
- Column = 0
- Control = Panel1
- Row = 0
- end
- item
- Column = 0
- Control = Panel2
- Row = 1
- end
- item
- Column = 0
- Control = Panel3
- Row = 2
- end>
- RowCollection = <
- item
- Value = 33.333333333333330000
- end
- item
- Value = 33.333333333333330000
- end
- item
- Value = 33.333333333333330000
- end>
- TabOrder = 0
- object Panel1: TPanel
- Left = 0
- Top = 0
- Width = 227
- Height = 26
- Align = alClient
- BevelOuter = bvNone
- Caption = 'Panel1'
- TabOrder = 0
- object edtConnectionString: TEdit
- AlignWithMargins = True
- Left = 0
- Top = 2
- Width = 202
- Height = 22
- Margins.Left = 0
- Margins.Top = 2
- Margins.Right = 1
- Margins.Bottom = 2
- Align = alClient
- TabOrder = 0
- TextHint = 'ADO Connection String'
- OnChange = edtConnectionStringChange
- ExplicitHeight = 21
- end
- object btnEditConnectionString: TButton
- AlignWithMargins = True
- Left = 204
- Top = 2
- Width = 23
- Height = 22
- Hint = 'Edit connection string...'
- Margins.Left = 1
- Margins.Top = 2
- Margins.Right = 0
- Margins.Bottom = 2
- Align = alRight
- Caption = '...'
- TabOrder = 1
- OnClick = btnEditConnectionStringClick
- end
- end
- object Panel2: TPanel
- Left = 0
- Top = 26
- Width = 227
- Height = 26
- Align = alClient
- BevelOuter = bvNone
- TabOrder = 1
- object lblPort: TLabel
- Left = 71
- Top = 5
- Width = 64
- Height = 13
- Caption = '(TCP/IP Port)'
- end
- object edtPort: TSpinEdit
- Left = 0
- Top = 2
- Width = 65
- Height = 22
- MaxValue = 0
- MinValue = 0
- TabOrder = 0
- Value = 0
- OnChange = edtPortChange
- end
- end
- object Panel3: TPanel
- Left = 0
- Top = 52
- Width = 227
- Height = 29
- Align = alClient
- BevelOuter = bvNone
- TabOrder = 2
- object cbEnableCachedResults: TCheckBox
- Left = 0
- Top = 0
- Width = 227
- Height = 29
- Align = alClient
- Caption = 'Enable cached query responses'
- Checked = True
- Color = clWindow
- ParentColor = False
- State = cbChecked
- TabOrder = 0
- OnClick = cbEnableCachedResultsClick
- end
- end
- end
- end
- object CategoryPanel1: TCategoryPanel
- AlignWithMargins = True
- Top = 6
- Height = 65
- Caption = 'In-memory Server Activation'
- TabOrder = 0
- object btnStartService: TButton
- AlignWithMargins = True
- Left = 7
- Top = 7
- Width = 102
- Height = 25
- Margins.Left = 7
- Margins.Top = 7
- Margins.Bottom = 7
- Align = alLeft
- Caption = 'Start Engine'
- TabOrder = 0
- OnClick = btnStartServiceClick
- end
- object cbAutostartServer: TCheckBox
- AlignWithMargins = True
- Left = 168
- Top = 3
- Width = 66
- Height = 33
- Hint = 'Start Engine when this program starts'
- Margins.Right = 7
- Align = alRight
- Caption = 'Autostart'
- TabOrder = 1
- OnClick = cbAutostartServerClick
- end
- end
- end
- object TrayIcon: TTrayIcon
- PopupMenu = popTray
- Visible = True
- OnClick = miShowHideServerClick
- Left = 316
- Top = 68
- end
- object popTray: TPopupMenu
- Left = 368
- Top = 68
- object miShowHideServer: TMenuItem
- Caption = 'Show/Hide Server'
- OnClick = miShowHideServerClick
- end
- object miN1: TMenuItem
- Caption = '-'
- end
- object miShutdown: TMenuItem
- Caption = 'Shutdown'
- OnClick = miShutdownClick
- end
- end
- object tmrUpdateLog: TTimer
- Interval = 10
- OnTimer = tmrUpdateLogTimer
- Left = 316
- Top = 116
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ ActiveControl = memLog
+ Caption = 'Netcom7 Database Server Management'
+ ClientHeight = 388
+ ClientWidth = 1030
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ ScreenSnap = True
+ ShowHint = True
+ OnClose = FormClose
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Splitter1: TSplitter
+ Left = 257
+ Top = 50
+ Height = 338
+ ExplicitLeft = 308
+ ExplicitTop = 276
+ ExplicitHeight = 100
+ end
+ object pnlCaption: TPanel
+ Left = 0
+ Top = 0
+ Width = 1030
+ Height = 50
+ Align = alTop
+ BevelOuter = bvNone
+ Caption = 'In-memory service - stopped'
+ Color = clBlack
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWhite
+ Font.Height = -27
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ ParentBackground = False
+ ParentFont = False
+ TabOrder = 0
+ end
+ object memLog: TMemo
+ Left = 260
+ Top = 50
+ Width = 770
+ Height = 338
+ Align = alClient
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Courier New'
+ Font.Style = []
+ ParentFont = False
+ ReadOnly = True
+ ScrollBars = ssBoth
+ TabOrder = 2
+ WordWrap = False
+ end
+ object CategoryPanelGroup1: TCategoryPanelGroup
+ Left = 0
+ Top = 50
+ Width = 257
+ Height = 338
+ VertScrollBar.Tracking = True
+ BevelInner = bvNone
+ BevelOuter = bvNone
+ ChevronAlignment = taRightJustify
+ Color = clGradientActiveCaption
+ HeaderAlignment = taRightJustify
+ HeaderFont.Charset = DEFAULT_CHARSET
+ HeaderFont.Color = clWindowText
+ HeaderFont.Height = -11
+ HeaderFont.Name = 'Tahoma'
+ HeaderFont.Style = []
+ Padding.Left = 3
+ Padding.Top = 3
+ Padding.Right = 3
+ Padding.Bottom = 3
+ TabOrder = 1
+ object CategoryPanel3: TCategoryPanel
+ AlignWithMargins = True
+ Top = 204
+ Height = 65
+ Caption = 'Startup'
+ TabOrder = 2
+ object cbAutorunLogon: TCheckBox
+ AlignWithMargins = True
+ Left = 7
+ Top = 3
+ Width = 163
+ Height = 33
+ Hint =
+ 'Check this if you want to run this program instead of the servic' +
+ 'e for testing over time. This application will launch with windo' +
+ 'ws logon.'
+ Margins.Left = 7
+ Margins.Right = 7
+ Align = alLeft
+ Caption = 'Autorun with Windows logon'
+ TabOrder = 0
+ OnClick = cbAutorunLogonClick
+ end
+ end
+ object cpConnection: TCategoryPanel
+ AlignWithMargins = True
+ Top = 77
+ Height = 121
+ Caption = 'Engine Settings'
+ TabOrder = 1
+ object GridPanel1: TGridPanel
+ AlignWithMargins = True
+ Left = 7
+ Top = 7
+ Width = 227
+ Height = 81
+ Margins.Left = 7
+ Margins.Top = 7
+ Margins.Right = 7
+ Margins.Bottom = 7
+ Align = alClient
+ BevelOuter = bvNone
+ ColumnCollection = <
+ item
+ Value = 100.000000000000000000
+ end>
+ ControlCollection = <
+ item
+ Column = 0
+ Control = Panel1
+ Row = 0
+ end
+ item
+ Column = 0
+ Control = Panel2
+ Row = 1
+ end
+ item
+ Column = 0
+ Control = Panel3
+ Row = 2
+ end>
+ RowCollection = <
+ item
+ Value = 33.333333333333330000
+ end
+ item
+ Value = 33.333333333333330000
+ end
+ item
+ Value = 33.333333333333330000
+ end>
+ TabOrder = 0
+ object Panel1: TPanel
+ Left = 0
+ Top = 0
+ Width = 227
+ Height = 26
+ Align = alClient
+ BevelOuter = bvNone
+ Caption = 'Panel1'
+ TabOrder = 0
+ object edtConnectionString: TEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 2
+ Width = 202
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 2
+ Margins.Right = 1
+ Margins.Bottom = 2
+ Align = alClient
+ TabOrder = 0
+ TextHint = 'ADO Connection String'
+ OnChange = edtConnectionStringChange
+ ExplicitHeight = 21
+ end
+ object btnEditConnectionString: TButton
+ AlignWithMargins = True
+ Left = 204
+ Top = 2
+ Width = 23
+ Height = 22
+ Hint = 'Edit connection string...'
+ Margins.Left = 1
+ Margins.Top = 2
+ Margins.Right = 0
+ Margins.Bottom = 2
+ Align = alRight
+ Caption = '...'
+ TabOrder = 1
+ OnClick = btnEditConnectionStringClick
+ end
+ end
+ object Panel2: TPanel
+ Left = 0
+ Top = 26
+ Width = 227
+ Height = 26
+ Align = alClient
+ BevelOuter = bvNone
+ TabOrder = 1
+ object lblPort: TLabel
+ Left = 71
+ Top = 5
+ Width = 64
+ Height = 13
+ Caption = '(TCP/IP Port)'
+ end
+ object edtPort: TSpinEdit
+ Left = 0
+ Top = 2
+ Width = 65
+ Height = 22
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 0
+ OnChange = edtPortChange
+ end
+ end
+ object Panel3: TPanel
+ Left = 0
+ Top = 52
+ Width = 227
+ Height = 29
+ Align = alClient
+ BevelOuter = bvNone
+ TabOrder = 2
+ object cbEnableCachedResults: TCheckBox
+ Left = 0
+ Top = 0
+ Width = 227
+ Height = 29
+ Align = alClient
+ Caption = 'Enable cached query responses'
+ Checked = True
+ Color = clWindow
+ ParentColor = False
+ State = cbChecked
+ TabOrder = 0
+ OnClick = cbEnableCachedResultsClick
+ end
+ end
+ end
+ end
+ object CategoryPanel1: TCategoryPanel
+ AlignWithMargins = True
+ Top = 6
+ Height = 65
+ Caption = 'In-memory Server Activation'
+ TabOrder = 0
+ object btnStartService: TButton
+ AlignWithMargins = True
+ Left = 7
+ Top = 7
+ Width = 102
+ Height = 25
+ Margins.Left = 7
+ Margins.Top = 7
+ Margins.Bottom = 7
+ Align = alLeft
+ Caption = 'Start Engine'
+ TabOrder = 0
+ OnClick = btnStartServiceClick
+ end
+ object cbAutostartServer: TCheckBox
+ AlignWithMargins = True
+ Left = 168
+ Top = 3
+ Width = 66
+ Height = 33
+ Hint = 'Start Engine when this program starts'
+ Margins.Right = 7
+ Align = alRight
+ Caption = 'Autostart'
+ TabOrder = 1
+ OnClick = cbAutostartServerClick
+ end
+ end
+ end
+ object TrayIcon: TTrayIcon
+ PopupMenu = popTray
+ Visible = True
+ OnClick = miShowHideServerClick
+ Left = 316
+ Top = 68
+ end
+ object popTray: TPopupMenu
+ Left = 368
+ Top = 68
+ object miShowHideServer: TMenuItem
+ Caption = 'Show/Hide Server'
+ OnClick = miShowHideServerClick
+ end
+ object miN1: TMenuItem
+ Caption = '-'
+ end
+ object miShutdown: TMenuItem
+ Caption = 'Shutdown'
+ OnClick = miShutdownClick
+ end
+ end
+ object tmrUpdateLog: TTimer
+ Interval = 10
+ OnTimer = tmrUpdateLogTimer
+ Left = 316
+ Top = 116
+ end
+end
diff --git a/Demos/DB/DBServer/ServiceApplication/ufrmMain.pas b/Demos/TCP/DB/DBServer/ServiceApplication/ufrmMain.pas
similarity index 96%
rename from Demos/DB/DBServer/ServiceApplication/ufrmMain.pas
rename to Demos/TCP/DB/DBServer/ServiceApplication/ufrmMain.pas
index e3ece21..03e80e5 100644
--- a/Demos/DB/DBServer/ServiceApplication/ufrmMain.pas
+++ b/Demos/TCP/DB/DBServer/ServiceApplication/ufrmMain.pas
@@ -1,318 +1,318 @@
-unit ufrmMain;
-
-interface
-
-uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, ExtCtrls, StdCtrls, Registry, Menus, SyncObjs, ComCtrls, ADOConEd,
- Spin;
-
-type
- TStringArray = array of string;
- TBooleanArray = array of Boolean;
-
- TfrmMain = class(TForm)
- pnlCaption: TPanel;
- memLog: TMemo;
- TrayIcon: TTrayIcon;
- popTray: TPopupMenu;
- miShowHideServer: TMenuItem;
- miN1: TMenuItem;
- miShutdown: TMenuItem;
- tmrUpdateLog: TTimer;
- CategoryPanelGroup1: TCategoryPanelGroup;
- CategoryPanel1: TCategoryPanel;
- cpConnection: TCategoryPanel;
- btnStartService: TButton;
- cbAutostartServer: TCheckBox;
- CategoryPanel3: TCategoryPanel;
- cbAutorunLogon: TCheckBox;
- Splitter1: TSplitter;
- GridPanel1: TGridPanel;
- Panel1: TPanel;
- edtConnectionString: TEdit;
- btnEditConnectionString: TButton;
- Panel2: TPanel;
- edtPort: TSpinEdit;
- lblPort: TLabel;
- Panel3: TPanel;
- cbEnableCachedResults: TCheckBox;
- procedure FormCreate(Sender: TObject);
- procedure btnStartServiceClick(Sender: TObject);
- procedure cbAutostartServerClick(Sender: TObject);
- procedure cbAutorunLogonClick(Sender: TObject);
- procedure miShowHideServerClick(Sender: TObject);
- procedure FormClose(Sender: TObject; var Action: TCloseAction);
- procedure miShutdownClick(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure tmrUpdateLogTimer(Sender: TObject);
- procedure btnEditConnectionStringClick(Sender: TObject);
- procedure edtConnectionStringChange(Sender: TObject);
- procedure edtPortChange(Sender: TObject);
- procedure cbEnableCachedResultsClick(Sender: TObject);
- private
- svcStarted: Boolean;
- LogLock: TCriticalSection;
- LogStrs: TStringArray;
- LogErrs: TBooleanArray;
- btnStartServiceCaption: string;
- procedure RefreshGUI;
- procedure ServiceLogMessage(Sender: TObject; aMessage: string; aError: Boolean = False);
- procedure ApplicationException(Sender: TObject; E: Exception);
- public
- function IsAutoRun: Boolean;
- procedure SetAutoRun(aAutoRun: Boolean);
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-uses usvcMain;
-{$R *.dfm}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- svcStarted := False;
-
- btnStartServiceCaption := btnStartService.Caption;
-
- LogLock := TCriticalSection.Create;
- SetLength(LogStrs, 0);
- SetLength(LogErrs, 0);
-
- Application.OnException := ApplicationException;
- Service.OnLogMessage := ServiceLogMessage;
-
- if Service.Settings.ValueExists('AppAutostart') then
- cbAutostartServer.Checked := Service.Settings.ReadBool('AppAutostart');
- cbAutorunLogon.Checked := IsAutoRun;
-
- edtConnectionString.Text := Service.DBConnectionString;
- edtPort.Value := Service.ServicePort;
- cbEnableCachedResults.Checked := Service.CacheResponses;
-
- RefreshGUI;
-
- if cbAutostartServer.Checked then
- btnStartService.Click;
-end;
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- LogLock.Free;
-end;
-
-procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
-begin
- Action := caNone;
- Visible := False;
-end;
-
-procedure TfrmMain.ApplicationException(Sender: TObject; E: Exception);
-begin
- memLog.Lines.Add('*** APPLICATION EXCEPTION (' + E.ClassName + ')! ' + DateTimeToStr(Now) + ': ' + E.Message);
-end;
-
-procedure TfrmMain.ServiceLogMessage(Sender: TObject; aMessage: string; aError: Boolean = False);
-begin
- // This must be thread safe, a log can be called all over the place
-
- LogLock.Acquire;
- try
- SetLength(LogStrs, Length(LogStrs) + 1);
- LogStrs[ High(LogStrs)] := aMessage;
- SetLength(LogErrs, Length(LogErrs) + 1);
- LogErrs[ High(LogErrs)] := aError;
- finally
- LogLock.Release;
- end;
-end;
-
-procedure TfrmMain.tmrUpdateLogTimer(Sender: TObject);
-var
- Strs: TStringArray;
- Errs: TBooleanArray;
-
- MsgStr: string;
- i: Integer;
-begin
- // Get thread critical data as fast as possible onto local copies
- LogLock.Acquire;
- try
- Strs := LogStrs;
- Errs := LogErrs;
- SetLength(LogStrs, 0);
- SetLength(LogErrs, 0);
- finally
- LogLock.Release;
- end;
-
- // And begin showing the messages/errors in the log area
- if Length(Strs) > 0 then
- begin
- memLog.Lines.BeginUpdate;
- try
- for i := 0 to High(Strs) do
- begin
- MsgStr := '';
- if Errs[i] then
- begin
- Visible := True;
- MsgStr := MsgStr + '*** Error! ';
- end;
-
- MsgStr := MsgStr + '[' + DateTimeToStr(Now) + ']: ' + Strs[i];
- if memLog.Lines.Count > 10000 then
- memLog.Lines.Text := 'Log cleared - reached 10000 lines';
- memLog.Lines.Add(MsgStr);
- end;
- finally
- memLog.Lines.EndUpdate;
- end;
- end;
-end;
-
-procedure TfrmMain.RefreshGUI;
-var
- Caption: string;
-begin
- Caption := Service.DisplayName;
- if svcStarted then
- Caption := Caption + ' - started'
- else
- Caption := Caption + ' - stopped';
- pnlCaption.Caption := Caption;
-end;
-
-procedure TfrmMain.btnStartServiceClick(Sender: TObject);
-var
- svcStopped: Boolean;
-begin
- if svcStarted then
- begin
- svcStarted := False;
- btnStartService.Caption := btnStartServiceCaption;
- cpConnection.Enabled := True;
- Service.ServiceStop(nil, svcStopped);
- end
- else
- begin
- svcStarted := True;
- try
- Service.ServiceStart(nil, svcStarted);
- if svcStarted then
- begin
- btnStartService.Caption := 'Stop service';
- cpConnection.Enabled := False;
- end;
- except
- svcStarted := False;
- raise ;
- end;
- end;
- RefreshGUI;
-end;
-
-procedure TfrmMain.cbAutostartServerClick(Sender: TObject);
-begin
- Service.Settings.WriteBool('AppAutostart', cbAutostartServer.Checked);
-end;
-
-procedure TfrmMain.edtConnectionStringChange(Sender: TObject);
-begin
- edtConnectionString.Hint := edtConnectionString.Text;
- Service.DBConnectionString := edtConnectionString.Text;
-end;
-
-procedure TfrmMain.edtPortChange(Sender: TObject);
-begin
- Service.ServicePort := edtPort.Value;
-end;
-
-procedure TfrmMain.cbEnableCachedResultsClick(Sender: TObject);
-begin
- Service.CacheResponses := cbEnableCachedResults.Checked;
-end;
-
-procedure TfrmMain.cbAutorunLogonClick(Sender: TObject);
-begin
- if cbAutorunLogon.Checked then
- cbAutoStartServer.Checked := True;
- SetAutoRun(cbAutorunLogon.Checked);
-end;
-
-procedure TfrmMain.btnEditConnectionStringClick(Sender: TObject);
-begin
- if EditConnectionString(Service.ADOConnection) then
- begin
- edtConnectionString.Text := Service.ADOConnection.ConnectionString;
- end;
-end;
-
-function TfrmMain.IsAutoRun: Boolean;
-var
- Reg: TRegistry;
- AppName: string;
-begin
- Result := False;
-
- Reg := TRegistry.Create;
- try
- Reg.RootKey := HKEY_LOCAL_MACHINE;
- if Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run', True) then
- try
- AppName := ExtractFileName(ParamStr(0));
- AppName := Copy(AppName, 1, Length(AppName) - Length(ExtractFileExt(AppName)));
- AppName := AppName + '.' + Service.Name;
-
- Result := SameText(Reg.ReadString(AppName), ParamStr(0));
- finally
- Reg.CloseKey;
- end;
- finally
- Reg.Free;
- end;
-end;
-
-procedure TfrmMain.SetAutoRun(aAutoRun: Boolean);
-var
- Reg: TRegistry;
- AppName: string;
-begin
- Reg := TRegistry.Create;
- try
- Reg.RootKey := HKEY_LOCAL_MACHINE;
- Reg.LazyWrite := False;
- if not Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run', True) then
- raise Exception.Create('Cannot open registry key.');
- try
- AppName := ExtractFileName(ParamStr(0));
- AppName := Copy(AppName, 1, Length(AppName) - Length(ExtractFileExt(AppName)));
- AppName := AppName + '.' + Service.Name;
-
- if cbAutorunLogon.Checked then
- Reg.WriteString(AppName, ParamStr(0))
- else
- Reg.DeleteValue(AppName);
- finally
- Reg.CloseKey;
- end;
- finally
- Reg.Free;
- end;
-end;
-
-procedure TfrmMain.miShowHideServerClick(Sender: TObject);
-begin
- Application.BringToFront;
- frmMain.Visible := not frmMain.Visible;
-end;
-
-procedure TfrmMain.miShutdownClick(Sender: TObject);
-begin
- Application.Terminate;
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+ Dialogs, ExtCtrls, StdCtrls, Registry, Menus, SyncObjs, ComCtrls, ADOConEd,
+ Spin;
+
+type
+ TStringArray = array of string;
+ TBooleanArray = array of Boolean;
+
+ TfrmMain = class(TForm)
+ pnlCaption: TPanel;
+ memLog: TMemo;
+ TrayIcon: TTrayIcon;
+ popTray: TPopupMenu;
+ miShowHideServer: TMenuItem;
+ miN1: TMenuItem;
+ miShutdown: TMenuItem;
+ tmrUpdateLog: TTimer;
+ CategoryPanelGroup1: TCategoryPanelGroup;
+ CategoryPanel1: TCategoryPanel;
+ cpConnection: TCategoryPanel;
+ btnStartService: TButton;
+ cbAutostartServer: TCheckBox;
+ CategoryPanel3: TCategoryPanel;
+ cbAutorunLogon: TCheckBox;
+ Splitter1: TSplitter;
+ GridPanel1: TGridPanel;
+ Panel1: TPanel;
+ edtConnectionString: TEdit;
+ btnEditConnectionString: TButton;
+ Panel2: TPanel;
+ edtPort: TSpinEdit;
+ lblPort: TLabel;
+ Panel3: TPanel;
+ cbEnableCachedResults: TCheckBox;
+ procedure FormCreate(Sender: TObject);
+ procedure btnStartServiceClick(Sender: TObject);
+ procedure cbAutostartServerClick(Sender: TObject);
+ procedure cbAutorunLogonClick(Sender: TObject);
+ procedure miShowHideServerClick(Sender: TObject);
+ procedure FormClose(Sender: TObject; var Action: TCloseAction);
+ procedure miShutdownClick(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure tmrUpdateLogTimer(Sender: TObject);
+ procedure btnEditConnectionStringClick(Sender: TObject);
+ procedure edtConnectionStringChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure cbEnableCachedResultsClick(Sender: TObject);
+ private
+ svcStarted: Boolean;
+ LogLock: TCriticalSection;
+ LogStrs: TStringArray;
+ LogErrs: TBooleanArray;
+ btnStartServiceCaption: string;
+ procedure RefreshGUI;
+ procedure ServiceLogMessage(Sender: TObject; aMessage: string; aError: Boolean = False);
+ procedure ApplicationException(Sender: TObject; E: Exception);
+ public
+ function IsAutoRun: Boolean;
+ procedure SetAutoRun(aAutoRun: Boolean);
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+uses usvcMain;
+{$R *.dfm}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ svcStarted := False;
+
+ btnStartServiceCaption := btnStartService.Caption;
+
+ LogLock := TCriticalSection.Create;
+ SetLength(LogStrs, 0);
+ SetLength(LogErrs, 0);
+
+ Application.OnException := ApplicationException;
+ Service.OnLogMessage := ServiceLogMessage;
+
+ if Service.Settings.ValueExists('AppAutostart') then
+ cbAutostartServer.Checked := Service.Settings.ReadBool('AppAutostart');
+ cbAutorunLogon.Checked := IsAutoRun;
+
+ edtConnectionString.Text := Service.DBConnectionString;
+ edtPort.Value := Service.ServicePort;
+ cbEnableCachedResults.Checked := Service.CacheResponses;
+
+ RefreshGUI;
+
+ if cbAutostartServer.Checked then
+ btnStartService.Click;
+end;
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ LogLock.Free;
+end;
+
+procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
+begin
+ Action := caNone;
+ Visible := False;
+end;
+
+procedure TfrmMain.ApplicationException(Sender: TObject; E: Exception);
+begin
+ memLog.Lines.Add('*** APPLICATION EXCEPTION (' + E.ClassName + ')! ' + DateTimeToStr(Now) + ': ' + E.Message);
+end;
+
+procedure TfrmMain.ServiceLogMessage(Sender: TObject; aMessage: string; aError: Boolean = False);
+begin
+ // This must be thread safe, a log can be called all over the place
+
+ LogLock.Acquire;
+ try
+ SetLength(LogStrs, Length(LogStrs) + 1);
+ LogStrs[ High(LogStrs)] := aMessage;
+ SetLength(LogErrs, Length(LogErrs) + 1);
+ LogErrs[ High(LogErrs)] := aError;
+ finally
+ LogLock.Release;
+ end;
+end;
+
+procedure TfrmMain.tmrUpdateLogTimer(Sender: TObject);
+var
+ Strs: TStringArray;
+ Errs: TBooleanArray;
+
+ MsgStr: string;
+ i: Integer;
+begin
+ // Get thread critical data as fast as possible onto local copies
+ LogLock.Acquire;
+ try
+ Strs := LogStrs;
+ Errs := LogErrs;
+ SetLength(LogStrs, 0);
+ SetLength(LogErrs, 0);
+ finally
+ LogLock.Release;
+ end;
+
+ // And begin showing the messages/errors in the log area
+ if Length(Strs) > 0 then
+ begin
+ memLog.Lines.BeginUpdate;
+ try
+ for i := 0 to High(Strs) do
+ begin
+ MsgStr := '';
+ if Errs[i] then
+ begin
+ Visible := True;
+ MsgStr := MsgStr + '*** Error! ';
+ end;
+
+ MsgStr := MsgStr + '[' + DateTimeToStr(Now) + ']: ' + Strs[i];
+ if memLog.Lines.Count > 10000 then
+ memLog.Lines.Text := 'Log cleared - reached 10000 lines';
+ memLog.Lines.Add(MsgStr);
+ end;
+ finally
+ memLog.Lines.EndUpdate;
+ end;
+ end;
+end;
+
+procedure TfrmMain.RefreshGUI;
+var
+ Caption: string;
+begin
+ Caption := Service.DisplayName;
+ if svcStarted then
+ Caption := Caption + ' - started'
+ else
+ Caption := Caption + ' - stopped';
+ pnlCaption.Caption := Caption;
+end;
+
+procedure TfrmMain.btnStartServiceClick(Sender: TObject);
+var
+ svcStopped: Boolean;
+begin
+ if svcStarted then
+ begin
+ svcStarted := False;
+ btnStartService.Caption := btnStartServiceCaption;
+ cpConnection.Enabled := True;
+ Service.ServiceStop(nil, svcStopped);
+ end
+ else
+ begin
+ svcStarted := True;
+ try
+ Service.ServiceStart(nil, svcStarted);
+ if svcStarted then
+ begin
+ btnStartService.Caption := 'Stop service';
+ cpConnection.Enabled := False;
+ end;
+ except
+ svcStarted := False;
+ raise ;
+ end;
+ end;
+ RefreshGUI;
+end;
+
+procedure TfrmMain.cbAutostartServerClick(Sender: TObject);
+begin
+ Service.Settings.WriteBool('AppAutostart', cbAutostartServer.Checked);
+end;
+
+procedure TfrmMain.edtConnectionStringChange(Sender: TObject);
+begin
+ edtConnectionString.Hint := edtConnectionString.Text;
+ Service.DBConnectionString := edtConnectionString.Text;
+end;
+
+procedure TfrmMain.edtPortChange(Sender: TObject);
+begin
+ Service.ServicePort := edtPort.Value;
+end;
+
+procedure TfrmMain.cbEnableCachedResultsClick(Sender: TObject);
+begin
+ Service.CacheResponses := cbEnableCachedResults.Checked;
+end;
+
+procedure TfrmMain.cbAutorunLogonClick(Sender: TObject);
+begin
+ if cbAutorunLogon.Checked then
+ cbAutoStartServer.Checked := True;
+ SetAutoRun(cbAutorunLogon.Checked);
+end;
+
+procedure TfrmMain.btnEditConnectionStringClick(Sender: TObject);
+begin
+ if EditConnectionString(Service.ADOConnection) then
+ begin
+ edtConnectionString.Text := Service.ADOConnection.ConnectionString;
+ end;
+end;
+
+function TfrmMain.IsAutoRun: Boolean;
+var
+ Reg: TRegistry;
+ AppName: string;
+begin
+ Result := False;
+
+ Reg := TRegistry.Create;
+ try
+ Reg.RootKey := HKEY_LOCAL_MACHINE;
+ if Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run', True) then
+ try
+ AppName := ExtractFileName(ParamStr(0));
+ AppName := Copy(AppName, 1, Length(AppName) - Length(ExtractFileExt(AppName)));
+ AppName := AppName + '.' + Service.Name;
+
+ Result := SameText(Reg.ReadString(AppName), ParamStr(0));
+ finally
+ Reg.CloseKey;
+ end;
+ finally
+ Reg.Free;
+ end;
+end;
+
+procedure TfrmMain.SetAutoRun(aAutoRun: Boolean);
+var
+ Reg: TRegistry;
+ AppName: string;
+begin
+ Reg := TRegistry.Create;
+ try
+ Reg.RootKey := HKEY_LOCAL_MACHINE;
+ Reg.LazyWrite := False;
+ if not Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Run', True) then
+ raise Exception.Create('Cannot open registry key.');
+ try
+ AppName := ExtractFileName(ParamStr(0));
+ AppName := Copy(AppName, 1, Length(AppName) - Length(ExtractFileExt(AppName)));
+ AppName := AppName + '.' + Service.Name;
+
+ if cbAutorunLogon.Checked then
+ Reg.WriteString(AppName, ParamStr(0))
+ else
+ Reg.DeleteValue(AppName);
+ finally
+ Reg.CloseKey;
+ end;
+ finally
+ Reg.Free;
+ end;
+end;
+
+procedure TfrmMain.miShowHideServerClick(Sender: TObject);
+begin
+ Application.BringToFront;
+ frmMain.Visible := not frmMain.Visible;
+end;
+
+procedure TfrmMain.miShutdownClick(Sender: TObject);
+begin
+ Application.Terminate;
+end;
+
+end.
diff --git a/Demos/DB/DBServer/TestData/Customers.mdb b/Demos/TCP/DB/DBServer/TestData/Customers.mdb
similarity index 100%
rename from Demos/DB/DBServer/TestData/Customers.mdb
rename to Demos/TCP/DB/DBServer/TestData/Customers.mdb
diff --git a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dpr b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dpr
similarity index 94%
rename from Demos/NetComVSIndy/Client/NetComVSIndyClient.dpr
rename to Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dpr
index aacd074..ecb956c 100644
--- a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dpr
+++ b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dpr
@@ -1,14 +1,14 @@
-program NetComVSIndyClient;
-
-uses
- Vcl.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain};
-
-{$R *.res}
-
-begin
- Application.Initialize;
- Application.MainFormOnTaskbar := True;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program NetComVSIndyClient;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dproj b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dproj
similarity index 76%
rename from Demos/NetComVSIndy/Client/NetComVSIndyClient.dproj
rename to Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dproj
index 9b3fd67..f12bdd1 100644
--- a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dproj
+++ b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dproj
@@ -1,1002 +1,1108 @@
-
-
- {87A44595-5F1F-4CE4-8F52-2D9AF02CFC5C}
- 18.8
- VCL
- NetComVSIndyClient.dpr
- True
- Release
- Win64
- 3
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
- NetComVSIndyClient
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
- dfm
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- NetComVSIndyClient.dpr
-
-
-
-
-
- NetComVSIndyClient.exe
- true
-
-
-
-
- NetComVSIndyClient.exe
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
-
-
- 12
-
-
-
-
-
+
+
+ {87A44595-5F1F-4CE4-8F52-2D9AF02CFC5C}
+ 20.2
+ VCL
+ NetComVSIndyClient.dpr
+ True
+ Release
+ Win32
+ 3
+ Application
+ NetComVSIndyClient
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ NetComVSIndyClient
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ NetComVSIndyClient.dpr
+
+
+
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dproj.local b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dproj.local
similarity index 89%
rename from Demos/NetComVSIndy/Client/NetComVSIndyClient.dproj.local
rename to Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dproj.local
index dcb08ed..3a0c17e 100644
--- a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dproj.local
+++ b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dproj.local
@@ -1,45 +1,45 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/11 06:18:58.000.380,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/11 06:47:57.000.575,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.dfm=C:\Users\Programmer\Documents\Development\Projects\Unit3.dfm
- 2020/08/11 06:47:57.000.575,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/11 06:48:06.000.793,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\NetComVSIndyClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/11 06:18:58.000.380,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/11 06:47:57.000.575,C:\Users\Programmer\Documents\Development\Projects\Unit3.dfm=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.dfm
+ 2020/08/11 06:47:57.000.575,C:\Users\Programmer\Documents\Development\Projects\Unit3.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
+ 2020/08/11 06:48:06.000.793,C:\Users\Programmer\Documents\Development\Projects\Project1.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\NetComVSIndyClient.dproj
+
+
+
+
+
diff --git a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dsk b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dsk
similarity index 94%
rename from Demos/NetComVSIndy/Client/NetComVSIndyClient.dsk
rename to Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dsk
index c835053..f6b9598 100644
--- a/Demos/NetComVSIndy/Client/NetComVSIndyClient.dsk
+++ b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.dsk
@@ -1,755 +1,755 @@
-[Closed Files]
-File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,520,1,923,0,0,,{1,910,1}
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,499,5,475,0,0,,
-File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdIOHandler.pas',0,1,1837,3,1853,0,0,,
-File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackBSDBase.pas',0,1,498,1,513,0,0,,
-File_4=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackConsts.pas',0,1,128,1,144,0,0,,
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdSocketHandle.pas',0,1,362,11,378,0,0,,
-File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdIOHandlerStack.pas',0,1,366,1,368,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdGlobal.pas',0,1,2735,10,2524,0,0,,
-File_8=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,3264,1,3279,0,0,,
-File_9=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackWindows.pas',0,1,1054,1,1070,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
-Count=1
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=1
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
-View0=0
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
-CursorX=1
-CursorY=14
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=3
-Breakpoint0='c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdSocketHandle.pas',340,'',0,1,'',1,0,0,'',1,'','','',0,''
-Breakpoint1='c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackBSDBase.pas',448,'',0,1,'',1,0,0,'',1,'','','',0,''
-Breakpoint2='c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackBSDBase.pas',513,'',0,1,'',1,0,0,'',1,'','','',0,''
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Caption,
-ExpandedItems=Anchors=0,BorderIcons=0,Constraints=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-214
-Top=-259
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,520,1,923,0,0,,{1,910,1}
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,499,5,475,0,0,,
+File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdIOHandler.pas',0,1,1837,3,1853,0,0,,
+File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackBSDBase.pas',0,1,498,1,513,0,0,,
+File_4=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackConsts.pas',0,1,128,1,144,0,0,,
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdSocketHandle.pas',0,1,362,11,378,0,0,,
+File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdIOHandlerStack.pas',0,1,366,1,368,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdGlobal.pas',0,1,2735,10,2524,0,0,,
+File_8=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,3264,1,3279,0,0,,
+File_9=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackWindows.pas',0,1,1054,1,1070,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
+Count=1
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=1
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
+View0=0
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Client\ufrmMain.pas
+CursorX=1
+CursorY=14
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=3
+Breakpoint0='c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdSocketHandle.pas',340,'',0,1,'',1,0,0,'',1,'','','',0,''
+Breakpoint1='c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackBSDBase.pas',448,'',0,1,'',1,0,0,'',1,'','','',0,''
+Breakpoint2='c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\System\IdStackBSDBase.pas',513,'',0,1,'',1,0,0,'',1,'','','',0,''
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Caption,
+ExpandedItems=Anchors=0,BorderIcons=0,Constraints=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-214
+Top=-259
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.res b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.res
new file mode 100644
index 0000000..7cb3dbd
Binary files /dev/null and b/Demos/TCP/NetComVSIndy/Client/NetComVSIndyClient.res differ
diff --git a/Demos/NetComVSIndy/Client/ufrmMain.dfm b/Demos/TCP/NetComVSIndy/Client/ufrmMain.dfm
similarity index 90%
rename from Demos/NetComVSIndy/Client/ufrmMain.dfm
rename to Demos/TCP/NetComVSIndy/Client/ufrmMain.dfm
index a50f87b..5d97777 100644
--- a/Demos/NetComVSIndy/Client/ufrmMain.dfm
+++ b/Demos/TCP/NetComVSIndy/Client/ufrmMain.dfm
@@ -1,98 +1,95 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'NetCom vs Indy speed testing'
- ClientHeight = 358
- ClientWidth = 802
- Color = clBtnFace
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Tahoma'
- Font.Style = []
- OldCreateOrder = False
- OnCreate = FormCreate
- PixelsPerInch = 96
- TextHeight = 13
- object pnlToolbar: TPanel
- Left = 0
- Top = 0
- Width = 802
- Height = 41
- Align = alTop
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 0
- object Label1: TLabel
- Left = 328
- Top = 14
- Width = 51
- Height = 13
- Caption = 'Iterations:'
- end
- object btnTestSpeed: TButton
- Left = 0
- Top = 0
- Width = 121
- Height = 41
- Align = alLeft
- Caption = 'Test Speed'
- TabOrder = 0
- OnClick = btnTestSpeedClick
- end
- object edtIterations: TSpinEdit
- Left = 385
- Top = 11
- Width = 81
- Height = 22
- MaxValue = 0
- MinValue = 0
- TabOrder = 1
- Value = 10000
- end
- object rbTestNetCom: TRadioButton
- Left = 145
- Top = 12
- Width = 80
- Height = 17
- Caption = 'Test NetCom'
- Checked = True
- TabOrder = 2
- TabStop = True
- end
- object rbTestIndy: TRadioButton
- Left = 231
- Top = 12
- Width = 82
- Height = 17
- Caption = 'Test Indy'
- TabOrder = 3
- end
- end
- object memLog: TMemo
- Left = 0
- Top = 41
- Width = 802
- Height = 317
- Align = alClient
- TabOrder = 1
- end
- object ncClient: TncTCPClient
- Host = 'LocalHost'
- UseReaderThread = False
- NoDelay = True
- KeepAlive = False
- Reconnect = False
- Left = 304
- Top = 32
- end
- object idClient: TIdTCPClient
- ConnectTimeout = 0
- Host = 'LocalHost'
- IPVersion = Id_IPv4
- Port = 16234
- ReadTimeout = -1
- Left = 304
- Top = 88
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ Caption = 'NetCom vs Indy speed testing'
+ ClientHeight = 358
+ ClientWidth = 802
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OnCreate = FormCreate
+ TextHeight = 13
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 802
+ Height = 41
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object Label1: TLabel
+ Left = 328
+ Top = 14
+ Width = 51
+ Height = 13
+ Caption = 'Iterations:'
+ end
+ object btnTestSpeed: TButton
+ Left = 0
+ Top = 0
+ Width = 121
+ Height = 41
+ Align = alLeft
+ Caption = 'Test Speed'
+ TabOrder = 0
+ OnClick = btnTestSpeedClick
+ end
+ object edtIterations: TSpinEdit
+ Left = 385
+ Top = 11
+ Width = 81
+ Height = 22
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 10000
+ end
+ object rbTestNetCom: TRadioButton
+ Left = 145
+ Top = 12
+ Width = 80
+ Height = 17
+ Caption = 'Test NetCom'
+ Checked = True
+ TabOrder = 2
+ TabStop = True
+ end
+ object rbTestIndy: TRadioButton
+ Left = 231
+ Top = 12
+ Width = 82
+ Height = 17
+ Caption = 'Test Indy'
+ TabOrder = 3
+ end
+ end
+ object memLog: TMemo
+ Left = 0
+ Top = 41
+ Width = 802
+ Height = 317
+ Align = alClient
+ TabOrder = 1
+ end
+ object ncClient: TncTCPClient
+ Host = 'LocalHost'
+ UseReaderThread = False
+ NoDelay = True
+ KeepAlive = False
+ Reconnect = False
+ Left = 224
+ Top = 88
+ end
+ object idClient: TIdTCPClient
+ ConnectTimeout = 0
+ Host = 'LocalHost'
+ Port = 16234
+ ReadTimeout = -1
+ Left = 304
+ Top = 88
+ end
+end
diff --git a/Demos/NetComVSIndy/Client/ufrmMain.pas b/Demos/TCP/NetComVSIndy/Client/ufrmMain.pas
similarity index 96%
rename from Demos/NetComVSIndy/Client/ufrmMain.pas
rename to Demos/TCP/NetComVSIndy/Client/ufrmMain.pas
index 307a1e7..ca6dee8 100644
--- a/Demos/NetComVSIndy/Client/ufrmMain.pas
+++ b/Demos/TCP/NetComVSIndy/Client/ufrmMain.pas
@@ -1,94 +1,95 @@
-unit ufrmMain;
-
-interface
-
-uses
- Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
- Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Samples.Spin,
- IdTCPConnection, IdTCPClient, IdBaseComponent, IdComponent, IdCustomTCPServer,
- IdTCPServer, IdContext, IdGlobal,
- Winapi.Winsock2, System.Diagnostics, ncSockets, ncLines;
-
-const
- // We are testing the socket mechanisms here and not how fast tcp/ip is,
- // therefore the buffer sent back and forth is kept at a fairly minimal size
- BuffSize = 256;
-
-type
- TfrmMain = class(TForm)
- ncClient: TncTCPClient;
- idClient: TIdTCPClient;
- pnlToolbar: TPanel;
- memLog: TMemo;
- btnTestSpeed: TButton;
- edtIterations: TSpinEdit;
- Label1: TLabel;
- rbTestNetCom: TRadioButton;
- rbTestIndy: TRadioButton;
- procedure FormCreate(Sender: TObject);
- procedure btnTestSpeedClick(Sender: TObject);
- private
- BufferSend, BufferRead: TBytes;
- idBufferSend, idBufferRead: TidBytes;
- public
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.dfm}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- SetLength(BufferSend, BuffSize);
- SetLength(BufferRead, BuffSize);
- SetLength(idBufferSend, BuffSize);
- SetLength(idBufferRead, BuffSize);
-end;
-
-procedure TfrmMain.btnTestSpeedClick(Sender: TObject);
-var
- i: Integer;
- TimeSt: Cardinal;
- TimeTaken: Cardinal;
-begin
- if rbTestNetCom.Checked then
- ncClient.Active := True;
- if rbTestIndy.Checked then
- idClient.Connect;
-
- if rbTestNetCom.Checked then
- begin
- memLog.Lines.Add('Testing NetCom...');
- TimeSt := GetTickCount;
- for i := 1 to edtIterations.Value do
- begin
- ncClient.Send(BufferSend);
- ncClient.ReceiveRaw(BufferRead);
- end;
- TimeTaken := GetTickCount - TimeSt;
- memLog.Lines.Add('Time taken: ' + IntToStr(TimeTaken) + ' msec');
- end;
-
- if rbTestIndy.Checked then
- begin
- memLog.Lines.Add('Testing Indy...');
- TimeSt := GetTickCount;
- for i := 1 to edtIterations.Value do
- begin
- idClient.Socket.Write(idBufferSend);
- idClient.Socket.ReadBytes(idBufferRead, BuffSize, False);
- end;
- TimeTaken := GetTickCount - TimeSt;
- memLog.Lines.Add('Time taken: ' + IntToStr(TimeTaken) + ' msec');
- end;
-
- if rbTestNetCom.Checked then
- ncClient.Active := False;
- if rbTestIndy.Checked then
- idClient.Disconnect;
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Samples.Spin,
+ IdTCPConnection, IdTCPClient, IdBaseComponent, IdComponent, IdCustomTCPServer,
+ IdTCPServer, IdContext, IdGlobal,
+ Winapi.Winsock2, System.Diagnostics, ncSockets, ncLines;
+
+const
+ // We are testing the socket mechanisms here and not how fast tcp/ip is,
+ // therefore the buffer sent back and forth is kept at a fairly minimal size
+ BuffSize = 256;
+
+type
+ TfrmMain = class(TForm)
+ ncClient: TncTCPClient;
+ idClient: TIdTCPClient;
+ pnlToolbar: TPanel;
+ memLog: TMemo;
+ btnTestSpeed: TButton;
+ edtIterations: TSpinEdit;
+ Label1: TLabel;
+ rbTestNetCom: TRadioButton;
+ rbTestIndy: TRadioButton;
+ procedure FormCreate(Sender: TObject);
+ procedure btnTestSpeedClick(Sender: TObject);
+ private
+ BufferSend, BufferRead: TBytes;
+ idBufferSend, idBufferRead: TidBytes;
+ public
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.dfm}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ SetLength(BufferSend, BuffSize);
+ SetLength(BufferRead, BuffSize);
+ SetLength(idBufferSend, BuffSize);
+ SetLength(idBufferRead, BuffSize);
+end;
+
+procedure TfrmMain.btnTestSpeedClick(Sender: TObject);
+var
+ i: Integer;
+ TimeSt: Cardinal;
+ TimeTaken: Cardinal;
+begin
+ if rbTestNetCom.Checked then
+ ncClient.Active := True;
+ if rbTestIndy.Checked then
+ idClient.Connect;
+
+ if rbTestNetCom.Checked then
+ begin
+ memLog.Lines.Add('Testing NetCom...');
+ TimeSt := GetTickCount;
+ for i := 1 to edtIterations.Value do
+ begin
+ ncClient.Send(BufferSend);
+ ncClient.ReceiveRaw(BufferRead);
+ end;
+ TimeTaken := GetTickCount - TimeSt;
+ memLog.Lines.Add('Time taken: ' + IntToStr(TimeTaken) + ' msec');
+ end;
+
+ if rbTestIndy.Checked then
+ begin
+ memLog.Lines.Add('Testing Indy...');
+ TimeSt := GetTickCount;
+ for i := 1 to edtIterations.Value do
+ begin
+ idClient.Socket.Write(idBufferSend);
+ idClient.Socket.ReadBytes(idBufferRead, BuffSize, False);
+ end;
+ TimeTaken := GetTickCount - TimeSt;
+ memLog.Lines.Add('Time taken: ' + IntToStr(TimeTaken) + ' msec');
+ end;
+
+ if rbTestNetCom.Checked then
+ ncClient.Active := False;
+ if rbTestIndy.Checked then
+ idClient.Disconnect;
+end;
+
+end.
+
diff --git a/Demos/TCP/NetComVSIndy/NetComVSIndy.groupproj b/Demos/TCP/NetComVSIndy/NetComVSIndy.groupproj
new file mode 100644
index 0000000..5a20ee2
--- /dev/null
+++ b/Demos/TCP/NetComVSIndy/NetComVSIndy.groupproj
@@ -0,0 +1,48 @@
+
+
+ {BAC706C1-FD83-4697-8BAD-8B892870DBDE}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/TCP/NetComVSIndy/NetComVSIndy.groupproj.local b/Demos/TCP/NetComVSIndy/NetComVSIndy.groupproj.local
new file mode 100644
index 0000000..64d433f
--- /dev/null
+++ b/Demos/TCP/NetComVSIndy/NetComVSIndy.groupproj.local
@@ -0,0 +1,9 @@
+
+
+
+ 2025/07/19 21:15:44.000.829,C:\Users\leet\Documents\Embarcadero\Studio\Projects\ProjectGroup1.groupproj=D:\_Delphi\_Library\Netcom7\Demos\NetComVSIndy\NetComVSIndy.groupproj
+
+
+
+
+
diff --git a/Demos/TCP/NetComVSIndy/NetComVSIndy_prjgroup.tvsconfig b/Demos/TCP/NetComVSIndy/NetComVSIndy_prjgroup.tvsconfig
new file mode 100644
index 0000000..d430780
--- /dev/null
+++ b/Demos/TCP/NetComVSIndy/NetComVSIndy_prjgroup.tvsconfig
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dpr b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dpr
similarity index 94%
rename from Demos/NetComVSIndy/Server/NetComVSIndyServer.dpr
rename to Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dpr
index fc14422..3a60130 100644
--- a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dpr
+++ b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dpr
@@ -1,14 +1,14 @@
-program NetComVSIndyServer;
-
-uses
- Vcl.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain};
-
-{$R *.res}
-
-begin
- Application.Initialize;
- Application.MainFormOnTaskbar := True;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program NetComVSIndyServer;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dproj b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dproj
similarity index 76%
rename from Demos/NetComVSIndy/Server/NetComVSIndyServer.dproj
rename to Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dproj
index 761da63..7eaa6ff 100644
--- a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dproj
+++ b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dproj
@@ -1,996 +1,1107 @@
-
-
- {DB8AA72F-75BF-4D63-A09D-AB194FD815B9}
- 18.8
- VCL
- NetComVSIndyServer.dpr
- True
- Release
- Win64
- 3
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
- NetComVSIndyServer
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
- dfm
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- NetComVSIndyServer.dpr
-
-
-
-
-
- NetComVSIndyServer.exe
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
-
-
- 12
-
-
-
-
-
+
+
+ {DB8AA72F-75BF-4D63-A09D-AB194FD815B9}
+ 20.2
+ VCL
+ NetComVSIndyServer.dpr
+ True
+ Release
+ Win32
+ 3
+ Application
+ NetComVSIndyServer
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ NetComVSIndyServer
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ NetComVSIndyServer.dpr
+
+
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dproj.local b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dproj.local
similarity index 89%
rename from Demos/NetComVSIndy/Server/NetComVSIndyServer.dproj.local
rename to Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dproj.local
index 76c5145..5cefd78 100644
--- a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dproj.local
+++ b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dproj.local
@@ -1,45 +1,45 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/11 06:48:47.000.137,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/11 06:50:30.000.325,C:\Users\Programmer\Documents\Development\Projects\Unit3.dfm=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.dfm
- 2020/08/11 06:50:30.000.325,C:\Users\Programmer\Documents\Development\Projects\Unit3.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
- 2020/08/11 06:50:45.000.950,C:\Users\Programmer\Documents\Development\Projects\Project1.dproj=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\NetComVSIndyServer.dproj
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/11 06:48:47.000.137,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/11 06:50:30.000.325,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.dfm=C:\Users\Programmer\Documents\Development\Projects\Unit3.dfm
+ 2020/08/11 06:50:30.000.325,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/11 06:50:45.000.950,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\NetComVSIndyServer.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
+
+
+
+
+
diff --git a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dsk b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dsk
similarity index 94%
rename from Demos/NetComVSIndy/Server/NetComVSIndyServer.dsk
rename to Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dsk
index 0bf34f0..311dc9e 100644
--- a/Demos/NetComVSIndy/Server/NetComVSIndyServer.dsk
+++ b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.dsk
@@ -1,752 +1,752 @@
-[Closed Files]
-File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,319,27,327,0,0,,{1
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,58,28,74,0,0,,
-File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdIOHandler.pas',0,1,2262,1,2239,0,0,,
-File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\NetComRegister.pas',0,1,79,1,95,0,0,,
-File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,420,19,436,0,0,,
-File_5=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\NetCom7.vrc',0,1,65,1,65,0,0,,
-File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\ToolsAPI\DesignEditors.pas',0,1,1,1,1,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\ToolsAPI\DesignIntf.pas',0,1,1,1,1,0,0,,
-File_8=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\ToolsAPI\ToolsAPI.pas',0,1,1,1,11,0,0,,
-File_9=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncCommandHandlers.pas',0,1,22,38,37,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
-Count=1
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=1
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
-View0=0
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
-CursorX=25
-CursorY=9
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Action,
-ExpandedItems=Anchors=0,BorderIcons=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-214
-Top=-259
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,319,27,327,0,0,,{1
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,58,28,74,0,0,,
+File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\Indy10\Core\IdIOHandler.pas',0,1,2262,1,2239,0,0,,
+File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\NetComRegister.pas',0,1,79,1,95,0,0,,
+File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,420,19,436,0,0,,
+File_5=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\NetCom7.vrc',0,1,65,1,65,0,0,,
+File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\ToolsAPI\DesignEditors.pas',0,1,1,1,1,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\ToolsAPI\DesignIntf.pas',0,1,1,1,1,0,0,,
+File_8=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\ToolsAPI\ToolsAPI.pas',0,1,1,1,11,0,0,,
+File_9=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncCommandHandlers.pas',0,1,22,38,37,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
+Count=1
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=1
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
+View0=0
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\NetComVSIndy\Server\ufrmMain.pas
+CursorX=25
+CursorY=9
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Action,
+ExpandedItems=Anchors=0,BorderIcons=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-214
+Top=-259
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.res b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.res
new file mode 100644
index 0000000..a141ec6
Binary files /dev/null and b/Demos/TCP/NetComVSIndy/Server/NetComVSIndyServer.res differ
diff --git a/Demos/NetComVSIndy/Server/ufrmMain.dfm b/Demos/TCP/NetComVSIndy/Server/ufrmMain.dfm
similarity index 95%
rename from Demos/NetComVSIndy/Server/ufrmMain.dfm
rename to Demos/TCP/NetComVSIndy/Server/ufrmMain.dfm
index 072e13f..3a6b1d0 100644
--- a/Demos/NetComVSIndy/Server/ufrmMain.dfm
+++ b/Demos/TCP/NetComVSIndy/Server/ufrmMain.dfm
@@ -1,39 +1,39 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'NetCom VS Indy Server'
- ClientHeight = 57
- ClientWidth = 601
- Color = clBtnFace
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Tahoma'
- Font.Style = []
- OldCreateOrder = False
- OnCreate = FormCreate
- PixelsPerInch = 96
- TextHeight = 13
- object Label1: TLabel
- Left = 24
- Top = 24
- Width = 555
- Height = 13
- Caption =
- 'Servers activate on creation (except if there was an error). You' +
- ' can now run the client while this program is running'
- end
- object ncServer: TncTCPServer
- NoDelay = True
- OnReadData = ncServerReadData
- Left = 456
- Top = 8
- end
- object idServer: TIdTCPServer
- Bindings = <>
- DefaultPort = 16234
- OnExecute = idServerExecute
- Left = 504
- Top = 8
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ Caption = 'NetCom VS Indy Server'
+ ClientHeight = 57
+ ClientWidth = 601
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ OnCreate = FormCreate
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Label1: TLabel
+ Left = 24
+ Top = 24
+ Width = 555
+ Height = 13
+ Caption =
+ 'Servers activate on creation (except if there was an error). You' +
+ ' can now run the client while this program is running'
+ end
+ object ncServer: TncTCPServer
+ NoDelay = True
+ OnReadData = ncServerReadData
+ Left = 456
+ Top = 8
+ end
+ object idServer: TIdTCPServer
+ Bindings = <>
+ DefaultPort = 16234
+ OnExecute = idServerExecute
+ Left = 504
+ Top = 8
+ end
+end
diff --git a/Demos/NetComVSIndy/Server/ufrmMain.pas b/Demos/TCP/NetComVSIndy/Server/ufrmMain.pas
similarity index 96%
rename from Demos/NetComVSIndy/Server/ufrmMain.pas
rename to Demos/TCP/NetComVSIndy/Server/ufrmMain.pas
index 95ff4ef..3b60ed0 100644
--- a/Demos/NetComVSIndy/Server/ufrmMain.pas
+++ b/Demos/TCP/NetComVSIndy/Server/ufrmMain.pas
@@ -1,61 +1,61 @@
-unit ufrmMain;
-
-interface
-
-uses
- Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
- Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winapi.Winsock2,
- IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdGlobal,
- System.Diagnostics, ncLines, ncSockets, Vcl.StdCtrls;
-
-type
- TfrmMain = class(TForm)
- ncServer: TncTCPServer;
- idServer: TIdTCPServer;
- Label1: TLabel;
- procedure FormCreate(Sender: TObject);
- procedure ncServerReadData(Sender: TObject; aLine: TncLine;
- const aBuf: TArray; aBufCount: Integer);
- procedure idServerExecute(AContext: TIdContext);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.dfm}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- ncServer.Active := True;
- idServer.Active := True;
-end;
-
-procedure TfrmMain.idServerExecute(AContext: TIdContext);
-var
- Data: TIdBytes;
-begin
- // Reply with data received
- if not aContext.Connection.IOHandler.InputBufferIsEmpty then
- begin
- aContext.Connection.IOHandler.InputBuffer.ExtractToBytes(Data);
- aContext.Binding.Send(Data);
- end;
-end;
-
-procedure TfrmMain.ncServerReadData(Sender: TObject; aLine: TncLine;
- const aBuf: TArray; aBufCount: Integer);
-var
- Data: TBytes;
-begin
- // Reply with data received
- Data := Copy (aBuf, 0, aBufCount);
- ncServer.Send(aLine, Data);
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winapi.Winsock2,
+ IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdGlobal,
+ System.Diagnostics, ncLines, ncSockets, Vcl.StdCtrls;
+
+type
+ TfrmMain = class(TForm)
+ ncServer: TncTCPServer;
+ idServer: TIdTCPServer;
+ Label1: TLabel;
+ procedure FormCreate(Sender: TObject);
+ procedure ncServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TArray; aBufCount: Integer);
+ procedure idServerExecute(AContext: TIdContext);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.dfm}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ ncServer.Active := True;
+ idServer.Active := True;
+end;
+
+procedure TfrmMain.idServerExecute(AContext: TIdContext);
+var
+ Data: TIdBytes;
+begin
+ // Reply with data received
+ if not aContext.Connection.IOHandler.InputBufferIsEmpty then
+ begin
+ aContext.Connection.IOHandler.InputBuffer.ExtractToBytes(Data);
+ aContext.Binding.Send(Data);
+ end;
+end;
+
+procedure TfrmMain.ncServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TArray; aBufCount: Integer);
+var
+ Data: TBytes;
+begin
+ // Reply with data received
+ Data := Copy (aBuf, 0, aBufCount);
+ ncServer.Send(aLine, Data);
+end;
+
+end.
diff --git a/Demos/SimpleSockets/Client.dpr b/Demos/TCP/SimpleSockets/Client/Client.dpr
similarity index 94%
rename from Demos/SimpleSockets/Client.dpr
rename to Demos/TCP/SimpleSockets/Client/Client.dpr
index 028c5c1..aa89c08 100644
--- a/Demos/SimpleSockets/Client.dpr
+++ b/Demos/TCP/SimpleSockets/Client/Client.dpr
@@ -1,17 +1,17 @@
-program Client;
-
-uses
- Vcl.Forms,
- ufrmMain in 'ufrmMain.pas' {Form1};
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.MainFormOnTaskbar := True;
- Application.CreateForm(TForm1, Form1);
- Application.Run;
-end.
+program Client;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/SimpleSockets/Client/Client.dproj b/Demos/TCP/SimpleSockets/Client/Client.dproj
new file mode 100644
index 0000000..4a0ef54
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/Client/Client.dproj
@@ -0,0 +1,200 @@
+
+
+ {A7946007-4A7F-492A-BC3D-79264B590A5A}
+ Client.dpr
+ True
+ Debug
+ Client
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ Client
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Client.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/SimpleSockets/Client/Client.identcache b/Demos/TCP/SimpleSockets/Client/Client.identcache
new file mode 100644
index 0000000..86daade
Binary files /dev/null and b/Demos/TCP/SimpleSockets/Client/Client.identcache differ
diff --git a/Demos/TCP/SimpleSockets/Client/Client.res b/Demos/TCP/SimpleSockets/Client/Client.res
new file mode 100644
index 0000000..e16426e
Binary files /dev/null and b/Demos/TCP/SimpleSockets/Client/Client.res differ
diff --git a/Demos/TCP/SimpleSockets/Client/ufrmMain.dcu b/Demos/TCP/SimpleSockets/Client/ufrmMain.dcu
new file mode 100644
index 0000000..af14704
Binary files /dev/null and b/Demos/TCP/SimpleSockets/Client/ufrmMain.dcu differ
diff --git a/Demos/SimpleSockets/ufrmMain.dfm b/Demos/TCP/SimpleSockets/Client/ufrmMain.dfm
similarity index 91%
rename from Demos/SimpleSockets/ufrmMain.dfm
rename to Demos/TCP/SimpleSockets/Client/ufrmMain.dfm
index adf35a8..b7cad98 100644
--- a/Demos/SimpleSockets/ufrmMain.dfm
+++ b/Demos/TCP/SimpleSockets/Client/ufrmMain.dfm
@@ -1,174 +1,173 @@
-object Form1: TForm1
- Left = 0
- Top = 0
- ActiveControl = edtDataToSend
- Caption = 'TCPClient'
- ClientHeight = 243
- ClientWidth = 527
- Color = clBtnFace
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Tahoma'
- Font.Style = []
- OldCreateOrder = False
- Position = poScreenCenter
- OnDestroy = FormDestroy
- PixelsPerInch = 96
- TextHeight = 13
- object memLog: TMemo
- AlignWithMargins = True
- Left = 5
- Top = 37
- Width = 517
- Height = 169
- Margins.Left = 5
- Margins.Top = 0
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alClient
- ReadOnly = True
- ScrollBars = ssVertical
- TabOrder = 1
- end
- object pnlToolbar: TPanel
- Left = 0
- Top = 0
- Width = 527
- Height = 37
- Align = alTop
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 0
- object btnActivate: TButton
- AlignWithMargins = True
- Left = 5
- Top = 5
- Width = 105
- Height = 27
- Margins.Left = 5
- Margins.Top = 5
- Margins.Right = 0
- Margins.Bottom = 5
- Align = alLeft
- Caption = 'Activate'
- TabOrder = 0
- OnClick = btnActivateClick
- end
- object pnlAddress: TPanel
- AlignWithMargins = True
- Left = 110
- Top = 3
- Width = 417
- Height = 31
- Margins.Left = 0
- Margins.Right = 0
- Align = alClient
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 1
- object edtHost: TEdit
- AlignWithMargins = True
- Left = 5
- Top = 5
- Width = 281
- Height = 21
- Margins.Left = 5
- Margins.Top = 5
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alClient
- TabOrder = 0
- Text = 'LocalHost'
- TextHint = 'Enter host address'
- OnChange = edtHostChange
- end
- object edtPort: TSpinEdit
- AlignWithMargins = True
- Left = 291
- Top = 5
- Width = 121
- Height = 22
- Margins.Left = 0
- Margins.Top = 5
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alRight
- MaxValue = 0
- MinValue = 0
- TabOrder = 1
- Value = 16233
- OnChange = edtPortChange
- end
- end
- end
- object Panel1: TPanel
- Left = 0
- Top = 211
- Width = 527
- Height = 32
- Margins.Left = 5
- Margins.Top = 0
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alBottom
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 2
- object btnSendData: TButton
- AlignWithMargins = True
- Left = 5
- Top = 0
- Width = 105
- Height = 27
- Margins.Left = 5
- Margins.Top = 0
- Margins.Right = 0
- Margins.Bottom = 5
- Align = alLeft
- Caption = 'Send'
- Default = True
- TabOrder = 0
- OnClick = btnSendDataClick
- end
- object Panel2: TPanel
- AlignWithMargins = True
- Left = 110
- Top = 3
- Width = 417
- Height = 26
- Margins.Left = 0
- Margins.Right = 0
- Align = alClient
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 1
- object edtDataToSend: TEdit
- AlignWithMargins = True
- Left = 5
- Top = 0
- Width = 407
- Height = 21
- Margins.Left = 5
- Margins.Top = 0
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alClient
- TabOrder = 0
- Text = 'This is some text data'
- TextHint = 'Enter data to send here'
- OnEnter = edtDataToSendEnter
- OnExit = edtDataToSendExit
- end
- end
- end
- object TCPClient: TncTCPClient
- Host = 'localhost'
- OnConnected = TCPClientConnected
- OnDisconnected = TCPClientDisconnected
- OnReadData = TCPClientReadData
- OnReconnected = TCPClientReconnected
- Left = 92
- Top = 52
- end
-end
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ ActiveControl = edtDataToSend
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'TCPClient'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 169
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start TCP Client'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pnlAddress: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtHost: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 281
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ TextHint = 'Enter host address'
+ OnChange = edtHostChange
+ end
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 291
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 211
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendData: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send'
+ Default = True
+ TabOrder = 0
+ OnClick = btnSendDataClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtDataToSend: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 407
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'This is some text data'
+ TextHint = 'Enter data to send here'
+ OnEnter = edtDataToSendEnter
+ OnExit = edtDataToSendExit
+ end
+ end
+ end
+ object TCPClient: TncTCPClient
+ OnConnected = TCPClientConnected
+ OnDisconnected = TCPClientDisconnected
+ OnReadData = TCPClientReadData
+ OnReconnected = TCPClientReconnected
+ Left = 208
+ Top = 80
+ end
+end
diff --git a/Demos/TCP/SimpleSockets/Client/ufrmMain.pas b/Demos/TCP/SimpleSockets/Client/ufrmMain.pas
new file mode 100644
index 0000000..b032383
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/Client/ufrmMain.pas
@@ -0,0 +1,234 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin,
+ System.Diagnostics, ncLines, ncSockets;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pnlAddress: TPanel;
+ edtHost: TEdit;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendData: TButton;
+ Panel2: TPanel;
+ edtDataToSend: TEdit;
+ TCPClient: TncTCPClient;
+ procedure btnActivateClick(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure TCPClientConnected(Sender: TObject; aLine: TncLine);
+ procedure TCPClientDisconnected(Sender: TObject; aLine: TncLine);
+ procedure TCPClientReconnected(Sender: TObject; aLine: TncLine);
+ procedure edtHostChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnSendDataClick(Sender: TObject);
+ procedure edtDataToSendEnter(Sender: TObject);
+ procedure edtDataToSendExit(Sender: TObject);
+ procedure TCPClientReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure FormCreate(Sender: TObject);
+ private
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+//
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ TCPClient.Active := False;
+end;
+
+// *****************************************************************************
+// Start/Stop Main CLient
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if TCPClient.Active then
+ begin
+ // Deactivate the TCP client
+ TCPClient.Active := False;
+ btnActivate.Caption := 'Start TCP Client';
+ Log('TCP Client Deactivated');
+ end
+ else
+ begin
+ // Check if the host field is blank
+ if Trim(edtHost.Text) = '' then
+ begin
+ Log('Host field cannot be blank.');
+ Exit; // Exit the procedure if the host field is blank
+ end;
+
+ try
+ // Set the host from the text field
+ TCPClient.Host := edtHost.Text;
+
+ // Activate the TCP client
+ TCPClient.Port := edtPort.Value;
+ TCPClient.Active := True;
+ btnActivate.Caption := 'Stop TCP Client';
+ Log('TCP Client Activated');
+ except
+ on E: Exception do
+ Log('Failed to activate TCP Client: ' + E.Message);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change host (server)
+// *****************************************************************************
+procedure TForm1.edtHostChange(Sender: TObject);
+begin
+ try
+ TCPClient.Host := edtHost.Text;
+ except
+ edtHost.OnChange := nil;
+ try
+ edtHost.Text := TCPClient.Host;
+ finally
+ edtHost.OnChange := edtHostChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ TCPClient.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := TCPClient.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Data to send
+// *****************************************************************************
+procedure TForm1.edtDataToSendEnter(Sender: TObject);
+begin
+ btnSendData.Default := True;
+end;
+
+procedure TForm1.edtDataToSendExit(Sender: TObject);
+begin
+ btnSendData.Default := False;
+end;
+
+procedure TForm1.btnSendDataClick(Sender: TObject);
+begin
+ // Check if the data field is blank
+ if Trim(edtDataToSend.Text) = '' then
+ begin
+ Log('Cannot send - Data field cannot be blank.');
+ Exit; // Exit the procedure if the data field is blank
+ end;
+
+ try
+ // Send the data
+ TCPClient.Send(edtDataToSend.Text);
+ Log('Data sent: ' + edtDataToSend.Text);
+ except
+ on E: Exception do
+ Log('Failed to send data: ' + E.Message);
+ end;
+end;
+
+// *****************************************************************************
+// TCPClientConnected
+// *****************************************************************************
+procedure TForm1.TCPClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Connected');
+ btnActivate.Caption := 'Deactivate';
+end;
+
+// *****************************************************************************
+// TCPClientDisconnected
+// *****************************************************************************
+procedure TForm1.TCPClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Disconnected');
+ btnActivate.Caption := 'Activate';
+end;
+
+// *****************************************************************************
+// TCPClientReconnected
+// *****************************************************************************
+procedure TForm1.TCPClientReconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('Reconnected');
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.TCPClientReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ BytesReceived: TBytes;
+begin
+ BytesReceived := Copy(aBuf, 0, aBufCount);
+
+ Log('Received: ' + StringOf(BytesReceived));
+
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/SimpleSockets/Server/Server.dpr b/Demos/TCP/SimpleSockets/Server/Server.dpr
new file mode 100644
index 0000000..63d6f38
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/Server/Server.dpr
@@ -0,0 +1,17 @@
+program Server;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/SimpleSockets/Server/Server.dproj b/Demos/TCP/SimpleSockets/Server/Server.dproj
new file mode 100644
index 0000000..f45ef2f
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/Server/Server.dproj
@@ -0,0 +1,200 @@
+
+
+ {0B2EB3CC-F54E-41A8-A712-8771BC0FC4AD}
+ Server.dpr
+ True
+ Debug
+ Server
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ Server
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Server.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/SimpleSockets/Server/Server.dproj.local b/Demos/TCP/SimpleSockets/Server/Server.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/Server/Server.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/SimpleSockets/Server/Server.res b/Demos/TCP/SimpleSockets/Server/Server.res
new file mode 100644
index 0000000..ac78dad
Binary files /dev/null and b/Demos/TCP/SimpleSockets/Server/Server.res differ
diff --git a/Demos/TCP/SimpleSockets/Server/ufrmMain.dcu b/Demos/TCP/SimpleSockets/Server/ufrmMain.dcu
new file mode 100644
index 0000000..51543a2
Binary files /dev/null and b/Demos/TCP/SimpleSockets/Server/ufrmMain.dcu differ
diff --git a/Demos/SimpleSockets/Srv/ufrmMain.dfm b/Demos/TCP/SimpleSockets/Server/ufrmMain.dfm
similarity index 87%
rename from Demos/SimpleSockets/Srv/ufrmMain.dfm
rename to Demos/TCP/SimpleSockets/Server/ufrmMain.dfm
index 0e1ff11..7719392 100644
--- a/Demos/SimpleSockets/Srv/ufrmMain.dfm
+++ b/Demos/TCP/SimpleSockets/Server/ufrmMain.dfm
@@ -1,113 +1,122 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'TCPServer'
- ClientHeight = 243
- ClientWidth = 527
- Color = clBtnFace
- Font.Charset = DEFAULT_CHARSET
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Tahoma'
- Font.Style = []
- OldCreateOrder = False
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- PixelsPerInch = 96
- TextHeight = 13
- object memLog: TMemo
- AlignWithMargins = True
- Left = 5
- Top = 37
- Width = 517
- Height = 201
- Margins.Left = 5
- Margins.Top = 0
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alClient
- ReadOnly = True
- ScrollBars = ssVertical
- TabOrder = 0
- end
- object pnlToolbar: TPanel
- Left = 0
- Top = 0
- Width = 527
- Height = 37
- Align = alTop
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 1
- object btnActivate: TButton
- AlignWithMargins = True
- Left = 5
- Top = 5
- Width = 105
- Height = 27
- Margins.Left = 5
- Margins.Top = 5
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alLeft
- Caption = 'Activate'
- TabOrder = 0
- OnClick = btnActivateClick
- end
- object pblPort: TPanel
- AlignWithMargins = True
- Left = 115
- Top = 3
- Width = 412
- Height = 31
- Margins.Left = 0
- Margins.Right = 0
- Align = alClient
- BevelOuter = bvNone
- FullRepaint = False
- TabOrder = 1
- ExplicitLeft = 110
- ExplicitWidth = 417
- object edtPort: TSpinEdit
- AlignWithMargins = True
- Left = 0
- Top = 5
- Width = 121
- Height = 22
- Margins.Left = 0
- Margins.Top = 5
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alLeft
- MaxValue = 0
- MinValue = 0
- TabOrder = 0
- Value = 16233
- OnChange = edtPortChange
- ExplicitLeft = 291
- end
- object btnShutdownAllClients: TButton
- AlignWithMargins = True
- Left = 256
- Top = 5
- Width = 151
- Height = 21
- Margins.Left = 5
- Margins.Top = 5
- Margins.Right = 5
- Margins.Bottom = 5
- Align = alRight
- Caption = 'Shutdown all clients'
- TabOrder = 1
- OnClick = btnShutdownAllClientsClick
- end
- end
- end
- object TCPServer: TncTCPServer
- OnConnected = TCPServerConnected
- OnDisconnected = TCPServerDisconnected
- OnReadData = TCPServerReadData
- Left = 92
- Top = 52
- end
-end
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'TCPServer'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 182
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Activate'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pblPort: TPanel
+ AlignWithMargins = True
+ Left = 115
+ Top = 3
+ Width = 412
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ object btnShutdownAllClients: TButton
+ AlignWithMargins = True
+ Left = 256
+ Top = 5
+ Width = 151
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ Caption = 'Shutdown all clients'
+ TabOrder = 1
+ OnClick = btnShutdownAllClientsClick
+ end
+ end
+ end
+ object StatusBar1: TStatusBar
+ Left = 0
+ Top = 224
+ Width = 527
+ Height = 19
+ Panels = <
+ item
+ Text = 'Connections: 0'
+ Width = 150
+ end>
+ end
+ object TCPServer: TncTCPServer
+ OnConnected = TCPServerConnected
+ OnDisconnected = TCPServerDisconnected
+ OnReadData = TCPServerReadData
+ Left = 92
+ Top = 52
+ end
+end
diff --git a/Demos/TCP/SimpleSockets/Server/ufrmMain.pas b/Demos/TCP/SimpleSockets/Server/ufrmMain.pas
new file mode 100644
index 0000000..036aaa5
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/Server/ufrmMain.pas
@@ -0,0 +1,197 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.ComCtrls,
+ System.Diagnostics, ncLines, ncSocketList, ncSockets;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ TCPServer: TncTCPServer;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pblPort: TPanel;
+ edtPort: TSpinEdit;
+ btnShutdownAllClients: TButton;
+ StatusBar1: TStatusBar;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure TCPServerConnected(Sender: TObject; aLine: TncLine);
+ procedure TCPServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure btnActivateClick(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnShutdownAllClientsClick(Sender: TObject);
+ procedure TCPServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ private
+ FConnectionCount: Integer;
+ procedure UpdateConnectionCount;
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ FConnectionCount := 0;
+ UpdateConnectionCount;
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ TCPServer.Active := False;
+end;
+
+// *****************************************************************************
+// Start/Stop Main Server
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if TCPServer.Active then
+ begin
+ // Deactivate the TCP Server
+ TCPServer.Active := False;
+ btnActivate.Caption := 'Start TCP Server';
+ Log('TCP Server Deactivated');
+ end
+ else
+ begin
+ try
+ // Activate the TCP Server
+ TCPServer.Port := edtPort.Value;
+ TCPServer.Active := True;
+ btnActivate.Caption := 'Stop TCP Server';
+ Log('TCP Server Activated at port: ' + IntToStr(TCPServer.Port));
+
+ except
+ on E: Exception do
+ Log('Failed to activate TCP Server: ' + E.Message);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ TCPServer.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := TCPServer.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Shutdown all Clients
+// *****************************************************************************
+procedure TForm1.btnShutdownAllClientsClick(Sender: TObject);
+var
+ SocketList: TSocketList;
+ i: Integer;
+begin
+ SocketList := TCPServer.Lines.LockList;
+ try
+ for i := 0 to SocketList.Count - 1 do
+ TCPServer.ShutDownLine(SocketList.Lines[i]);
+ finally
+ TCPServer.Lines.UnlockList;
+ end;
+end;
+
+procedure TForm1.UpdateConnectionCount;
+begin
+ StatusBar1.Panels[0].Text := 'Connections: ' + IntToStr(FConnectionCount);
+end;
+
+// *****************************************************************************
+// TCPServerConnected
+// *****************************************************************************
+procedure TForm1.TCPServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ Inc(FConnectionCount);
+ UpdateConnectionCount;
+
+ Log('Connected: ' + aLine.PeerIP);
+
+ TCPServer.Send(aLine, BytesOf('Hello mr. ' + IntToStr(aLine.Handle)));
+end;
+
+// *****************************************************************************
+// TCPServerDisconnected
+// *****************************************************************************
+procedure TForm1.TCPServerDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Dec(FConnectionCount);
+ UpdateConnectionCount;
+
+ Log('Disconnected: ' + aLine.PeerIP);
+
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.TCPServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ BytesReceived: TBytes;
+begin
+ BytesReceived := Copy(aBuf, 0, aBufCount);
+
+ Log('Received: "' + StringOf(BytesReceived) + '" from: ' + aLine.PeerIP);
+
+ // Send back the buffer received
+ TCPServer.Send(aLine, BytesReceived);
+
+ Log('Data sent: ' + StringOf(BytesReceived));
+
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/SimpleSockets/SimpleSockets.groupproj b/Demos/TCP/SimpleSockets/SimpleSockets.groupproj
new file mode 100644
index 0000000..3122a45
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/SimpleSockets.groupproj
@@ -0,0 +1,48 @@
+
+
+ {A9A55D39-6A58-48E9-AA5F-4DED5B38E8A8}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/TCP/SimpleSockets/SimpleSockets.groupproj.local b/Demos/TCP/SimpleSockets/SimpleSockets.groupproj.local
new file mode 100644
index 0000000..e31bd9b
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/SimpleSockets.groupproj.local
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Demos/TCP/SimpleSockets/SimpleSockets_TCPv4.PNG b/Demos/TCP/SimpleSockets/SimpleSockets_TCPv4.PNG
new file mode 100644
index 0000000..95f8d5d
Binary files /dev/null and b/Demos/TCP/SimpleSockets/SimpleSockets_TCPv4.PNG differ
diff --git a/Demos/TCP/SimpleSockets/SimpleSockets_TCPv6.PNG b/Demos/TCP/SimpleSockets/SimpleSockets_TCPv6.PNG
new file mode 100644
index 0000000..9549054
Binary files /dev/null and b/Demos/TCP/SimpleSockets/SimpleSockets_TCPv6.PNG differ
diff --git a/Demos/TCP/SimpleSockets/SimpleSockets_prjgroup.tvsconfig b/Demos/TCP/SimpleSockets/SimpleSockets_prjgroup.tvsconfig
new file mode 100644
index 0000000..d430780
--- /dev/null
+++ b/Demos/TCP/SimpleSockets/SimpleSockets_prjgroup.tvsconfig
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/Client.dpr b/Demos/TCP/SimpleSockets_TLS/Client/Client.dpr
new file mode 100644
index 0000000..8992c4c
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Client/Client.dpr
@@ -0,0 +1,19 @@
+program Client;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
+
+
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/Client.dproj b/Demos/TCP/SimpleSockets_TLS/Client/Client.dproj
new file mode 100644
index 0000000..5b50ed4
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Client/Client.dproj
@@ -0,0 +1,262 @@
+
+
+ {A7946007-4A7F-492A-BC3D-79264B590A5A}
+ Client.dpr
+ True
+ Debug
+ Client
+ 3
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ Client
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ RELEASE;$(DCC_Define)
+ false
+ 0
+ true
+ 3
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+ 3
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Client.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+ False
+ False
+ False
+ False
+ False
+ False
+ True
+ True
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/Client.dproj.local b/Demos/TCP/SimpleSockets_TLS/Client/Client.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Client/Client.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/Client.drc b/Demos/TCP/SimpleSockets_TLS/Client/Client.drc
new file mode 100644
index 0000000..1a550dd
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Client/Client.drc
@@ -0,0 +1,773 @@
+/* VER360
+ Generated by the Embarcadero Delphi Pascal Compiler
+ because -GD or --drc was supplied to the compiler.
+
+ This file contains compiler-generated resources that
+ were bound to the executable.
+ If this file is empty, then no compiler-generated
+ resources were bound to the produced executable.
+*/
+
+#define System_Win_ComConst_SVarNotObject 65152
+#define System_Win_ComConst_STooManyParams 65153
+#define ncSockets_ECannotSetPortWhileConnectionIsActiveStr 65154
+#define ncSockets_ECannotSetHostWhileConnectionIsActiveStr 65155
+#define ncSockets_ECannotSendWhileSocketInactiveStr 65156
+#define ncSockets_ECannotSetUseReaderThreadWhileActiveStr 65157
+#define ncSockets_ECannotSetFamilyWhileConnectionIsActiveStr 65158
+#define ncSockets_EOpenSSLNotAvailableStr 65159
+#define Vcl_Consts_SStyleRegisterError 65168
+#define Vcl_Consts_SStyleClassRegisterError 65169
+#define Vcl_Consts_SStyleNotFound 65170
+#define Vcl_Consts_SStyleClassNotFound 65171
+#define Vcl_Consts_SStyleInvalidHandle 65172
+#define Vcl_Consts_SStyleFormatError 65173
+#define Vcl_Consts_SStyleHookClassRegistered 65174
+#define Vcl_Consts_SStyleHookClassNotRegistered 65175
+#define Vcl_Consts_SStyleInvalidParameter 65176
+#define Vcl_Consts_SStyleFeatureNotSupported 65177
+#define Vcl_Consts_SStyleNotRegistered 65178
+#define Vcl_Consts_SStyleUnregisterError 65179
+#define Vcl_Consts_SStyleNotRegisteredNoName 65180
+#define Vcl_Consts_sBeginInvokeNoHandle 65181
+#define System_Win_ComConst_SOleError 65182
+#define System_Win_ComConst_SNoMethod 65183
+#define Vcl_Consts_SDockZoneNotFound 65184
+#define Vcl_Consts_SDockZoneHasNoCtl 65185
+#define Vcl_Consts_SDockZoneVersionConflict 65186
+#define Vcl_Consts_SPromptArrayTooShort 65187
+#define Vcl_Consts_SPromptArrayEmpty 65188
+#define Vcl_Consts_SUsername 65189
+#define Vcl_Consts_SPassword 65190
+#define Vcl_Consts_SDomain 65191
+#define Vcl_Consts_SLogin 65192
+#define Vcl_Consts_STrayIconRemoveError 65193
+#define Vcl_Consts_SWindowsVistaRequired 65194
+#define Vcl_Consts_STaskDlgButtonCaption 65195
+#define Vcl_Consts_STaskDlgRadioButtonCaption 65196
+#define Vcl_Consts_SInvalidTaskDlgButtonCaption 65197
+#define Vcl_Consts_SStyleLoadError 65198
+#define Vcl_Consts_SStyleLoadErrors 65199
+#define Vcl_Consts_SmkcDown 65200
+#define Vcl_Consts_SmkcIns 65201
+#define Vcl_Consts_SmkcDel 65202
+#define Vcl_Consts_SmkcShift 65203
+#define Vcl_Consts_SmkcCtrl 65204
+#define Vcl_Consts_SmkcAlt 65205
+#define Vcl_Consts_SOutOfRange 65206
+#define Vcl_Consts_sAllFilter 65207
+#define Vcl_Consts_SIconToClipboard 65208
+#define Vcl_Consts_SCannotOpenClipboard 65209
+#define Vcl_Consts_SInvalidMemoSize 65210
+#define Vcl_Consts_SInvalidPrinterOp 65211
+#define Vcl_Consts_SNoDefaultPrinter 65212
+#define Vcl_Consts_SDuplicateMenus 65213
+#define Vcl_Consts_SDockedCtlNeedsName 65214
+#define Vcl_Consts_SDockTreeRemoveError 65215
+#define Vcl_Consts_SMsgDlgAll 65216
+#define Vcl_Consts_SMsgDlgNoToAll 65217
+#define Vcl_Consts_SMsgDlgYesToAll 65218
+#define Vcl_Consts_SMsgDlgClose 65219
+#define Vcl_Consts_SmkcBkSp 65220
+#define Vcl_Consts_SmkcTab 65221
+#define Vcl_Consts_SmkcEsc 65222
+#define Vcl_Consts_SmkcEnter 65223
+#define Vcl_Consts_SmkcSpace 65224
+#define Vcl_Consts_SmkcPgUp 65225
+#define Vcl_Consts_SmkcPgDn 65226
+#define Vcl_Consts_SmkcEnd 65227
+#define Vcl_Consts_SmkcHome 65228
+#define Vcl_Consts_SmkcLeft 65229
+#define Vcl_Consts_SmkcUp 65230
+#define Vcl_Consts_SmkcRight 65231
+#define Vcl_Consts_SVEnhMetafiles 65232
+#define Vcl_Consts_SVIcons 65233
+#define Vcl_Consts_SVBitmaps 65234
+#define Vcl_Consts_SVTIFFImages 65235
+#define Vcl_Consts_SMsgDlgWarning 65236
+#define Vcl_Consts_SMsgDlgError 65237
+#define Vcl_Consts_SMsgDlgInformation 65238
+#define Vcl_Consts_SMsgDlgConfirm 65239
+#define Vcl_Consts_SMsgDlgYes 65240
+#define Vcl_Consts_SMsgDlgNo 65241
+#define Vcl_Consts_SMsgDlgOK 65242
+#define Vcl_Consts_SMsgDlgCancel 65243
+#define Vcl_Consts_SMsgDlgHelp 65244
+#define Vcl_Consts_SMsgDlgAbort 65245
+#define Vcl_Consts_SMsgDlgRetry 65246
+#define Vcl_Consts_SMsgDlgIgnore 65247
+#define Vcl_Consts_SNoMDIForm 65248
+#define Vcl_Consts_SImageCanvasNeedsBitmap 65249
+#define Vcl_Consts_SControlParentSetToSelf 65250
+#define Vcl_Consts_SControlNonMainThreadUsage 65251
+#define Vcl_Consts_SOKButton 65252
+#define Vcl_Consts_SCancelButton 65253
+#define Vcl_Consts_SYesButton 65254
+#define Vcl_Consts_SNoButton 65255
+#define Vcl_Consts_SHelpButton 65256
+#define Vcl_Consts_SCloseButton 65257
+#define Vcl_Consts_SIgnoreButton 65258
+#define Vcl_Consts_SRetryButton 65259
+#define Vcl_Consts_SAbortButton 65260
+#define Vcl_Consts_SAllButton 65261
+#define Vcl_Consts_SCannotDragForm 65262
+#define Vcl_Consts_SVMetafiles 65263
+#define Vcl_Consts_SParentGivenNotAParent 65264
+#define Vcl_Consts_SMDIChildNotVisible 65265
+#define Vcl_Consts_SVisibleChanged 65266
+#define Vcl_Consts_SCannotShowModal 65267
+#define Vcl_Consts_SScrollBarRange 65268
+#define Vcl_Consts_SPropertyOutOfRange 65269
+#define Vcl_Consts_SMenuIndexError 65270
+#define Vcl_Consts_SMenuReinserted 65271
+#define Vcl_Consts_SMenuNotFound 65272
+#define Vcl_Consts_SNoTimers 65273
+#define Vcl_Consts_SNotPrinting 65274
+#define Vcl_Consts_SPrinting 65275
+#define Vcl_Consts_SPrinterIndexError 65276
+#define Vcl_Consts_SInvalidPrinter 65277
+#define Vcl_Consts_SDeviceOnPort 65278
+#define Vcl_Consts_SGroupIndexTooLow 65279
+#define Vcl_Consts_SOutOfResources 65280
+#define Vcl_Consts_SNoCanvasHandle 65281
+#define Vcl_Consts_SInvalidTextFormatFlag 65282
+#define Vcl_Consts_SInvalidFrameIndex 65283
+#define Vcl_Consts_SInvalidImageSize 65284
+#define Vcl_Consts_SInvalidImageList 65285
+#define Vcl_Consts_SReplaceImage 65286
+#define Vcl_Consts_SInsertImage 65287
+#define Vcl_Consts_SImageIndexError 65288
+#define Vcl_Consts_SImageReadFail 65289
+#define Vcl_Consts_SImageWriteFail 65290
+#define Vcl_Consts_SWindowDCError 65291
+#define Vcl_Consts_SWindowClass 65292
+#define Vcl_Consts_SCannotFocus 65293
+#define Vcl_Consts_SParentRequired 65294
+#define Vcl_Consts_SControlPath 65295
+#define System_RTLConsts_sObserverNoSinglecastFound 65296
+#define System_RTLConsts_sObserverNoMulticastFound 65297
+#define System_RTLConsts_sObserverNotAvailable 65298
+#define System_RTLConsts_sMustWaitOnOneEvent 65299
+#define System_RTLConsts_sBeginInvokeDestroying 65300
+#define Vcl_Consts_SInvalidBitmap 65301
+#define Vcl_Consts_SInvalidIcon 65302
+#define Vcl_Consts_SInvalidMetafile 65303
+#define Vcl_Consts_SInvalidPixelFormat 65304
+#define Vcl_Consts_SInvalidImage 65305
+#define Vcl_Consts_SScanLine 65306
+#define Vcl_Consts_SChangeIconSize 65307
+#define Vcl_Consts_SChangeWicSize 65308
+#define Vcl_Consts_SUnknownExtension 65309
+#define Vcl_Consts_SUnknownClipboardFormat 65310
+#define Vcl_Consts_SUnknownStreamFormat 65311
+#define System_RTLConsts_SWindowsXP 65312
+#define System_RTLConsts_SWindowsServer2003 65313
+#define System_RTLConsts_SWindowsServer2003R2 65314
+#define System_RTLConsts_SWindowsServer2012 65315
+#define System_RTLConsts_SWindowsServer2012R2 65316
+#define System_RTLConsts_SWindowsServer2016 65317
+#define System_RTLConsts_SWindowsServer2019 65318
+#define System_RTLConsts_SWindowsServer2022 65319
+#define System_RTLConsts_SWindows8 65320
+#define System_RTLConsts_SWindows8Point1 65321
+#define System_RTLConsts_SWindows10 65322
+#define System_RTLConsts_SWindows11 65323
+#define System_RTLConsts_SWinRTInstanceError 65324
+#define System_RTLConsts_sObserverUnsupported 65325
+#define System_RTLConsts_sObserverMultipleSingleCast 65326
+#define System_RTLConsts_sObserverNoInterface 65327
+#define System_RTLConsts_SNonPublicType 65328
+#define System_RTLConsts_SByRefArgMismatch 65329
+#define System_RTLConsts_SPropIsReadOnly 65330
+#define System_RTLConsts_SPropIsWriteOnly 65331
+#define System_RTLConsts_SInvalidRttiDestroy 65332
+#define System_RTLConsts_SServiceNotFound 65333
+#define System_RTLConsts_SVersionStr 65334
+#define System_RTLConsts_SSPVersionStr 65335
+#define System_RTLConsts_SVersion32 65336
+#define System_RTLConsts_SVersion64 65337
+#define System_RTLConsts_SWindows 65338
+#define System_RTLConsts_SWindowsVista 65339
+#define System_RTLConsts_SWindowsServer2008 65340
+#define System_RTLConsts_SWindows7 65341
+#define System_RTLConsts_SWindowsServer2008R2 65342
+#define System_RTLConsts_SWindows2000 65343
+#define System_RTLConsts_sCannotNegateTimespan 65344
+#define System_RTLConsts_sInvalidTimespanFormat 65345
+#define System_RTLConsts_sTimespanElementTooLong 65346
+#define System_RTLConsts_SNoContext 65347
+#define System_RTLConsts_SNoContextFound 65348
+#define System_RTLConsts_SNoIndex 65349
+#define System_RTLConsts_SNoSearch 65350
+#define System_RTLConsts_SNoTableOfContents 65351
+#define System_RTLConsts_SNoTopics 65352
+#define System_RTLConsts_SNothingFound 65353
+#define System_RTLConsts_SArgumentOutOfRange 65354
+#define System_RTLConsts_SArgumentNil 65355
+#define System_RTLConsts_SGenericItemNotFound 65356
+#define System_RTLConsts_SGenericDuplicateItem 65357
+#define System_RTLConsts_SInsufficientRtti 65358
+#define System_RTLConsts_SParameterCountMismatch 65359
+#define System_RTLConsts_SThreadExternalCheckTerminated 65360
+#define System_RTLConsts_SThreadExternalSetReturnValue 65361
+#define System_RTLConsts_SParamIsNil 65362
+#define System_RTLConsts_SParamIsNegative 65363
+#define System_RTLConsts_SInputBufferExceed 65364
+#define System_RTLConsts_SInvalidCharsInPath 65365
+#define System_RTLConsts_hNoFilterViewer 65366
+#define System_RTLConsts_sArgumentInvalid 65367
+#define System_RTLConsts_sInvalidStringAndObjectArrays 65368
+#define System_RTLConsts_sSameArrays 65369
+#define System_RTLConsts_sNoConstruct 65370
+#define System_RTLConsts_sInvalidTimeoutValue 65371
+#define System_RTLConsts_sSpinCountOutOfRange 65372
+#define System_RTLConsts_sTimespanTooLong 65373
+#define System_RTLConsts_sInvalidTimespanDuration 65374
+#define System_RTLConsts_sTimespanValueCannotBeNan 65375
+#define System_RTLConsts_SReadError 65376
+#define System_RTLConsts_SReadOnlyProperty 65377
+#define System_RTLConsts_SRegCreateFailed 65378
+#define System_RTLConsts_SRegGetDataFailed 65379
+#define System_RTLConsts_SRegSetDataFailed 65380
+#define System_RTLConsts_SResNotFound 65381
+#define System_RTLConsts_SSeekNotImplemented 65382
+#define System_RTLConsts_SSortedListError 65383
+#define System_RTLConsts_SUnknownGroup 65384
+#define System_RTLConsts_SUnknownProperty 65385
+#define System_RTLConsts_SWriteError 65386
+#define System_RTLConsts_SThreadCreateError 65387
+#define System_RTLConsts_SThreadError 65388
+#define System_RTLConsts_SThreadExternalTerminate 65389
+#define System_RTLConsts_SThreadExternalWait 65390
+#define System_RTLConsts_SThreadStartError 65391
+#define System_RTLConsts_SFCreateErrorEx 65392
+#define System_RTLConsts_SFOpenErrorEx 65393
+#define System_RTLConsts_SInvalidImage 65394
+#define System_RTLConsts_SInvalidName 65395
+#define System_RTLConsts_SInvalidProperty 65396
+#define System_RTLConsts_SInvalidPropertyPath 65397
+#define System_RTLConsts_SInvalidPropertyValue 65398
+#define System_RTLConsts_SInvalidRegType 65399
+#define System_RTLConsts_SListCapacityError 65400
+#define System_RTLConsts_SListCountError 65401
+#define System_RTLConsts_SListIndexError 65402
+#define System_RTLConsts_SListIndexErrorRangeReason 65403
+#define System_RTLConsts_SListIndexErrorEmptyReason 65404
+#define System_RTLConsts_SMemoryStreamError 65405
+#define System_RTLConsts_SNoComSupport 65406
+#define System_RTLConsts_SPropertyException 65407
+#define System_SysConst_SInvalidCharCount 65408
+#define System_SysConst_SInvalidDestinationIndex 65409
+#define System_SysConst_SInvalidCodePage 65410
+#define System_SysConst_SInvalidEncodingName 65411
+#define System_SysConst_SNoMappingForUnicodeCharacter 65412
+#define System_SysConst_SInvalidStringBaseIndex 65413
+#define System_RTLConsts_SAncestorNotFound 65414
+#define System_RTLConsts_SAssignError 65415
+#define System_RTLConsts_SBitsIndexError 65416
+#define System_RTLConsts_SCantWriteResourceStreamError 65417
+#define System_RTLConsts_SCheckSynchronizeError 65418
+#define System_RTLConsts_SClassNotFound 65419
+#define System_RTLConsts_SDuplicateClass 65420
+#define System_RTLConsts_SDuplicateItem 65421
+#define System_RTLConsts_SDuplicateName 65422
+#define System_RTLConsts_SDuplicateString 65423
+#define System_SysConst_SShortDayNameTue 65424
+#define System_SysConst_SShortDayNameWed 65425
+#define System_SysConst_SShortDayNameThu 65426
+#define System_SysConst_SShortDayNameFri 65427
+#define System_SysConst_SShortDayNameSat 65428
+#define System_SysConst_SLongDayNameSun 65429
+#define System_SysConst_SLongDayNameMon 65430
+#define System_SysConst_SLongDayNameTue 65431
+#define System_SysConst_SLongDayNameWed 65432
+#define System_SysConst_SLongDayNameThu 65433
+#define System_SysConst_SLongDayNameFri 65434
+#define System_SysConst_SLongDayNameSat 65435
+#define System_SysConst_SInvalidSourceArray 65436
+#define System_SysConst_SInvalidDestinationArray 65437
+#define System_SysConst_SCharIndexOutOfBounds 65438
+#define System_SysConst_SByteIndexOutOfBounds 65439
+#define System_SysConst_SShortMonthNameNov 65440
+#define System_SysConst_SShortMonthNameDec 65441
+#define System_SysConst_SLongMonthNameJan 65442
+#define System_SysConst_SLongMonthNameFeb 65443
+#define System_SysConst_SLongMonthNameMar 65444
+#define System_SysConst_SLongMonthNameApr 65445
+#define System_SysConst_SLongMonthNameMay 65446
+#define System_SysConst_SLongMonthNameJun 65447
+#define System_SysConst_SLongMonthNameJul 65448
+#define System_SysConst_SLongMonthNameAug 65449
+#define System_SysConst_SLongMonthNameSep 65450
+#define System_SysConst_SLongMonthNameOct 65451
+#define System_SysConst_SLongMonthNameNov 65452
+#define System_SysConst_SLongMonthNameDec 65453
+#define System_SysConst_SShortDayNameSun 65454
+#define System_SysConst_SShortDayNameMon 65455
+#define System_SysConst_SObjectDisposed 65456
+#define System_SysConst_SAssertError 65457
+#define System_SysConst_SAbstractError 65458
+#define System_SysConst_SModuleAccessViolation 65459
+#define System_SysConst_SOSError 65460
+#define System_SysConst_SUnkOSError 65461
+#define System_SysConst_SShortMonthNameJan 65462
+#define System_SysConst_SShortMonthNameFeb 65463
+#define System_SysConst_SShortMonthNameMar 65464
+#define System_SysConst_SShortMonthNameApr 65465
+#define System_SysConst_SShortMonthNameMay 65466
+#define System_SysConst_SShortMonthNameJun 65467
+#define System_SysConst_SShortMonthNameJul 65468
+#define System_SysConst_SShortMonthNameAug 65469
+#define System_SysConst_SShortMonthNameSep 65470
+#define System_SysConst_SShortMonthNameOct 65471
+#define System_SysConst_SVarTypeNotUsableWithPrefix 65472
+#define System_SysConst_SVarTypeTooManyCustom 65473
+#define System_SysConst_SVarTypeCouldNotConvert 65474
+#define System_SysConst_SVarTypeConvertOverflow 65475
+#define System_SysConst_SVarOverflow 65476
+#define System_SysConst_SVarInvalid 65477
+#define System_SysConst_SVarBadType 65478
+#define System_SysConst_SVarNotImplemented 65479
+#define System_SysConst_SVarUnexpected 65480
+#define System_SysConst_SExternalException 65481
+#define System_SysConst_SAssertionFailed 65482
+#define System_SysConst_SIntfCastError 65483
+#define System_SysConst_SSafecallException 65484
+#define System_SysConst_SMonitorLockException 65485
+#define System_SysConst_SNoMonitorSupportException 65486
+#define System_SysConst_SNotImplemented 65487
+#define System_SysConst_SInvalidFormat 65488
+#define System_SysConst_SArgumentMissing 65489
+#define System_SysConst_SDispatchError 65490
+#define System_SysConst_SReadAccess 65491
+#define System_SysConst_SWriteAccess 65492
+#define System_SysConst_SExecuteAccess 65493
+#define System_SysConst_SInvalidAccess 65494
+#define System_SysConst_SVarArrayCreate 65495
+#define System_SysConst_SVarArrayBounds 65496
+#define System_SysConst_SVarArrayLocked 65497
+#define System_SysConst_SInvalidVarCast 65498
+#define System_SysConst_SInvalidVarOp 65499
+#define System_SysConst_SInvalidVarNullOp 65500
+#define System_SysConst_SInvalidVarOpWithHResultWithPrefix 65501
+#define System_SysConst_SVarTypeOutOfRangeWithPrefix 65502
+#define System_SysConst_SVarTypeAlreadyUsedWithPrefix 65503
+#define System_SysConst_SRangeError 65504
+#define System_SysConst_SIntOverflow 65505
+#define System_SysConst_SInvalidOp 65506
+#define System_SysConst_SZeroDivide 65507
+#define System_SysConst_SOverflow 65508
+#define System_SysConst_SUnderflow 65509
+#define System_SysConst_SInvalidPointer 65510
+#define System_SysConst_SInvalidCast 65511
+#define System_SysConst_SAccessViolationArg3 65512
+#define System_SysConst_SAccessViolationNoArg 65513
+#define System_SysConst_SStackOverflow 65514
+#define System_SysConst_SControlC 65515
+#define System_SysConst_SPrivilege 65516
+#define System_SysConst_SOperationAborted 65517
+#define System_SysConst_SException 65518
+#define System_SysConst_SExceptTitle 65519
+#define System_SysConst_SUnknown 65520
+#define System_SysConst_SInvalidInteger 65521
+#define System_SysConst_SInvalidTimeStamp 65522
+#define System_SysConst_SInvalidGUID 65523
+#define System_SysConst_STimeEncodeError 65524
+#define System_SysConst_SDateEncodeError 65525
+#define System_SysConst_SOutOfMemory 65526
+#define System_SysConst_SInOutError 65527
+#define System_SysConst_SFileNotFound 65528
+#define System_SysConst_SInvalidUnknownFilename 65529
+#define System_SysConst_STooManyOpenFiles 65530
+#define System_SysConst_SAccessDenied 65531
+#define System_SysConst_SEndOfFile 65532
+#define System_SysConst_SDiskFull 65533
+#define System_SysConst_SInvalidInput 65534
+#define System_SysConst_SDivByZero 65535
+STRINGTABLE
+BEGIN
+ System_Win_ComConst_SVarNotObject, L"Variant does not reference an automation object"
+ System_Win_ComConst_STooManyParams, L"Dispatch methods do not support more than 64 parameters"
+ ncSockets_ECannotSetPortWhileConnectionIsActiveStr, L"Cannot set Port property whilst the connection is active"
+ ncSockets_ECannotSetHostWhileConnectionIsActiveStr, L"Cannot set Host property whilst the connection is active"
+ ncSockets_ECannotSendWhileSocketInactiveStr, L"Cannot send data while socket is inactive"
+ ncSockets_ECannotSetUseReaderThreadWhileActiveStr, L"Cannot set UseReaderThread property whilst the connection is active"
+ ncSockets_ECannotSetFamilyWhileConnectionIsActiveStr, L"Cannot set Family property whilst the connection is active"
+ ncSockets_EOpenSSLNotAvailableStr, L"OpenSSL libraries not available"
+ Vcl_Consts_SStyleRegisterError, L"Style '%s' already registered"
+ Vcl_Consts_SStyleClassRegisterError, L"Style class '%s' already registered"
+ Vcl_Consts_SStyleNotFound, L"Style '%s' not found"
+ Vcl_Consts_SStyleClassNotFound, L"Style class '%s' not found"
+ Vcl_Consts_SStyleInvalidHandle, L"Invalid style handle"
+ Vcl_Consts_SStyleFormatError, L"Invalid style format"
+ Vcl_Consts_SStyleHookClassRegistered, L"Class '%s' is already registered for '%s'"
+ Vcl_Consts_SStyleHookClassNotRegistered, L"Class '%s' is not registered for '%s'"
+ Vcl_Consts_SStyleInvalidParameter, L"%s parameter cannot be nil"
+ Vcl_Consts_SStyleFeatureNotSupported, L"Feature not supported by this style"
+ Vcl_Consts_SStyleNotRegistered, L"Style '%s' is not registered"
+ Vcl_Consts_SStyleUnregisterError, L"Cannot unregister the system style"
+ Vcl_Consts_SStyleNotRegisteredNoName, L"Style not registered"
+ Vcl_Consts_sBeginInvokeNoHandle, L"Cannot call BeginInvoke on a control with no parent or window handle"
+ System_Win_ComConst_SOleError, L"OLE error %.8x"
+ System_Win_ComConst_SNoMethod, L"Method '%s' not supported by automation object"
+ Vcl_Consts_SDockZoneNotFound, L" - Dock zone not found"
+ Vcl_Consts_SDockZoneHasNoCtl, L" - Dock zone has no control"
+ Vcl_Consts_SDockZoneVersionConflict, L"Error loading dock zone from the stream. Expecting version %d, but found %d."
+ Vcl_Consts_SPromptArrayTooShort, L"Length of value array must be >= length of prompt array"
+ Vcl_Consts_SPromptArrayEmpty, L"Prompt array must not be empty"
+ Vcl_Consts_SUsername, L"&Username"
+ Vcl_Consts_SPassword, L"&Password"
+ Vcl_Consts_SDomain, L"&Domain"
+ Vcl_Consts_SLogin, L"Login"
+ Vcl_Consts_STrayIconRemoveError, L"Cannot remove shell notification icon"
+ Vcl_Consts_SWindowsVistaRequired, L"%s requires Windows Vista or later"
+ Vcl_Consts_STaskDlgButtonCaption, L"Button%d"
+ Vcl_Consts_STaskDlgRadioButtonCaption, L"RadioButton%d"
+ Vcl_Consts_SInvalidTaskDlgButtonCaption, L"Caption cannot be empty"
+ Vcl_Consts_SStyleLoadError, L"Unable to load style '%s'"
+ Vcl_Consts_SStyleLoadErrors, L"Unable to load styles: %s"
+ Vcl_Consts_SmkcDown, L"Down"
+ Vcl_Consts_SmkcIns, L"Ins"
+ Vcl_Consts_SmkcDel, L"Del"
+ Vcl_Consts_SmkcShift, L"Shift+"
+ Vcl_Consts_SmkcCtrl, L"Ctrl+"
+ Vcl_Consts_SmkcAlt, L"Alt+"
+ Vcl_Consts_SOutOfRange, L"Value must be between %d and %d"
+ Vcl_Consts_sAllFilter, L"All"
+ Vcl_Consts_SIconToClipboard, L"Clipboard does not support Icons"
+ Vcl_Consts_SCannotOpenClipboard, L"Cannot open clipboard: %s"
+ Vcl_Consts_SInvalidMemoSize, L"Text exceeds memo capacity"
+ Vcl_Consts_SInvalidPrinterOp, L"Operation not supported on selected printer"
+ Vcl_Consts_SNoDefaultPrinter, L"There is no default printer currently selected"
+ Vcl_Consts_SDuplicateMenus, L"Menu '%s' is already being used by another form"
+ Vcl_Consts_SDockedCtlNeedsName, L"Docked control must have a name"
+ Vcl_Consts_SDockTreeRemoveError, L"Error removing control from dock tree"
+ Vcl_Consts_SMsgDlgAll, L"&All"
+ Vcl_Consts_SMsgDlgNoToAll, L"N&o to All"
+ Vcl_Consts_SMsgDlgYesToAll, L"Yes to &All"
+ Vcl_Consts_SMsgDlgClose, L"&Close"
+ Vcl_Consts_SmkcBkSp, L"BkSp"
+ Vcl_Consts_SmkcTab, L"Tab"
+ Vcl_Consts_SmkcEsc, L"Esc"
+ Vcl_Consts_SmkcEnter, L"Enter"
+ Vcl_Consts_SmkcSpace, L"Space"
+ Vcl_Consts_SmkcPgUp, L"PgUp"
+ Vcl_Consts_SmkcPgDn, L"PgDn"
+ Vcl_Consts_SmkcEnd, L"End"
+ Vcl_Consts_SmkcHome, L"Home"
+ Vcl_Consts_SmkcLeft, L"Left"
+ Vcl_Consts_SmkcUp, L"Up"
+ Vcl_Consts_SmkcRight, L"Right"
+ Vcl_Consts_SVEnhMetafiles, L"Enhanced Metafiles"
+ Vcl_Consts_SVIcons, L"Icons"
+ Vcl_Consts_SVBitmaps, L"Bitmaps"
+ Vcl_Consts_SVTIFFImages, L"TIFF Images"
+ Vcl_Consts_SMsgDlgWarning, L"Warning"
+ Vcl_Consts_SMsgDlgError, L"Error"
+ Vcl_Consts_SMsgDlgInformation, L"Information"
+ Vcl_Consts_SMsgDlgConfirm, L"Confirm"
+ Vcl_Consts_SMsgDlgYes, L"&Yes"
+ Vcl_Consts_SMsgDlgNo, L"&No"
+ Vcl_Consts_SMsgDlgOK, L"OK"
+ Vcl_Consts_SMsgDlgCancel, L"Cancel"
+ Vcl_Consts_SMsgDlgHelp, L"&Help"
+ Vcl_Consts_SMsgDlgAbort, L"&Abort"
+ Vcl_Consts_SMsgDlgRetry, L"&Retry"
+ Vcl_Consts_SMsgDlgIgnore, L"&Ignore"
+ Vcl_Consts_SNoMDIForm, L"Cannot create form. No MDI forms are currently active"
+ Vcl_Consts_SImageCanvasNeedsBitmap, L"Can only modify an image if it contains a bitmap"
+ Vcl_Consts_SControlParentSetToSelf, L"A control cannot have itself as its parent"
+ Vcl_Consts_SControlNonMainThreadUsage, L"Control '%s' is used on a not main thread"
+ Vcl_Consts_SOKButton, L"OK"
+ Vcl_Consts_SCancelButton, L"Cancel"
+ Vcl_Consts_SYesButton, L"&Yes"
+ Vcl_Consts_SNoButton, L"&No"
+ Vcl_Consts_SHelpButton, L"&Help"
+ Vcl_Consts_SCloseButton, L"&Close"
+ Vcl_Consts_SIgnoreButton, L"&Ignore"
+ Vcl_Consts_SRetryButton, L"&Retry"
+ Vcl_Consts_SAbortButton, L"Abort"
+ Vcl_Consts_SAllButton, L"&All"
+ Vcl_Consts_SCannotDragForm, L"Cannot drag a form"
+ Vcl_Consts_SVMetafiles, L"Metafiles"
+ Vcl_Consts_SParentGivenNotAParent, L"Parent given is not a parent of '%s'"
+ Vcl_Consts_SMDIChildNotVisible, L"Cannot hide an MDI Child Form"
+ Vcl_Consts_SVisibleChanged, L"Cannot change Visible in OnShow or OnHide"
+ Vcl_Consts_SCannotShowModal, L"Cannot make a visible window modal"
+ Vcl_Consts_SScrollBarRange, L"Scrollbar property out of range"
+ Vcl_Consts_SPropertyOutOfRange, L"%s property out of range"
+ Vcl_Consts_SMenuIndexError, L"Menu index out of range"
+ Vcl_Consts_SMenuReinserted, L"Menu inserted twice"
+ Vcl_Consts_SMenuNotFound, L"Sub-menu is not in menu"
+ Vcl_Consts_SNoTimers, L"Not enough timers available"
+ Vcl_Consts_SNotPrinting, L"Printer is not currently printing"
+ Vcl_Consts_SPrinting, L"Printing in progress"
+ Vcl_Consts_SPrinterIndexError, L"Printer index out of range"
+ Vcl_Consts_SInvalidPrinter, L"Printer selected is not valid"
+ Vcl_Consts_SDeviceOnPort, L"%s on %s"
+ Vcl_Consts_SGroupIndexTooLow, L"GroupIndex cannot be less than a previous menu item's GroupIndex"
+ Vcl_Consts_SOutOfResources, L"Out of system resources"
+ Vcl_Consts_SNoCanvasHandle, L"Canvas does not allow drawing"
+ Vcl_Consts_SInvalidTextFormatFlag, L"Text format flag '%s' not supported"
+ Vcl_Consts_SInvalidFrameIndex, L"Invalid image frame index %d: there are %d frames (0-%d)"
+ Vcl_Consts_SInvalidImageSize, L"Invalid image size"
+ Vcl_Consts_SInvalidImageList, L"Invalid ImageList"
+ Vcl_Consts_SReplaceImage, L"Unable to Replace Image"
+ Vcl_Consts_SInsertImage, L"Unable to Insert Image"
+ Vcl_Consts_SImageIndexError, L"Invalid ImageList Index"
+ Vcl_Consts_SImageReadFail, L"Failed to read ImageList data from stream"
+ Vcl_Consts_SImageWriteFail, L"Failed to write ImageList data to stream"
+ Vcl_Consts_SWindowDCError, L"Error creating window device context"
+ Vcl_Consts_SWindowClass, L"Error creating window class"
+ Vcl_Consts_SCannotFocus, L"Cannot focus a disabled or invisible window"
+ Vcl_Consts_SParentRequired, L"Control '%s' has no parent window"
+ Vcl_Consts_SControlPath, L". Path:\r\n%s"
+ System_RTLConsts_sObserverNoSinglecastFound, L"No single cast observer with ID %d was added to the observer collection"
+ System_RTLConsts_sObserverNoMulticastFound, L"No multi cast observer with ID %d was added to the observer collection"
+ System_RTLConsts_sObserverNotAvailable, L"Observer is not available"
+ System_RTLConsts_sMustWaitOnOneEvent, L"Must wait on at least one event"
+ System_RTLConsts_sBeginInvokeDestroying, L"Cannot call BeginInvoke on a TComponent in the process of destruction"
+ Vcl_Consts_SInvalidBitmap, L"Bitmap image is not valid"
+ Vcl_Consts_SInvalidIcon, L"Icon image is not valid"
+ Vcl_Consts_SInvalidMetafile, L"Metafile is not valid"
+ Vcl_Consts_SInvalidPixelFormat, L"Invalid pixel format"
+ Vcl_Consts_SInvalidImage, L"Invalid image"
+ Vcl_Consts_SScanLine, L"Scan line index out of range"
+ Vcl_Consts_SChangeIconSize, L"Cannot change the size of an icon"
+ Vcl_Consts_SChangeWicSize, L"Cannot change the size of a WIC Image"
+ Vcl_Consts_SUnknownExtension, L"Unknown picture file extension (.%s)"
+ Vcl_Consts_SUnknownClipboardFormat, L"Unsupported clipboard format"
+ Vcl_Consts_SUnknownStreamFormat, L"Unsupported stream format"
+ System_RTLConsts_SWindowsXP, L"Windows XP"
+ System_RTLConsts_SWindowsServer2003, L"Windows Server 2003"
+ System_RTLConsts_SWindowsServer2003R2, L"Windows Server 2003 R2"
+ System_RTLConsts_SWindowsServer2012, L"Windows Server 2012"
+ System_RTLConsts_SWindowsServer2012R2, L"Windows Server 2012 R2"
+ System_RTLConsts_SWindowsServer2016, L"Windows Server 2016"
+ System_RTLConsts_SWindowsServer2019, L"Windows Server 2019"
+ System_RTLConsts_SWindowsServer2022, L"Windows Server 2022"
+ System_RTLConsts_SWindows8, L"Windows 8"
+ System_RTLConsts_SWindows8Point1, L"Windows 8.1"
+ System_RTLConsts_SWindows10, L"Windows 10"
+ System_RTLConsts_SWindows11, L"Windows 11"
+ System_RTLConsts_SWinRTInstanceError, L"Cannot create instance of class %s"
+ System_RTLConsts_sObserverUnsupported, L"Observer is not supported"
+ System_RTLConsts_sObserverMultipleSingleCast, L"Cannot have multiple single cast observers added to the observers collection"
+ System_RTLConsts_sObserverNoInterface, L"The object does not implement the observer interface"
+ System_RTLConsts_SNonPublicType, L"Type '%s' is not declared in the interface section of a unit"
+ System_RTLConsts_SByRefArgMismatch, L"VAR and OUT arguments must match parameter type exactly"
+ System_RTLConsts_SPropIsReadOnly, L"Property '%s' is read-only"
+ System_RTLConsts_SPropIsWriteOnly, L"Property '%s' is write-only"
+ System_RTLConsts_SInvalidRttiDestroy, L"RTTI objects cannot be manually destroyed by application code"
+ System_RTLConsts_SServiceNotFound, L"Specified Login Credential Service not found"
+ System_RTLConsts_SVersionStr, L"%s (Version %d.%d, Build %d, %5:s)"
+ System_RTLConsts_SSPVersionStr, L"%s Service Pack %4:d (Version %1:d.%2:d, Build %3:d, %5:s)"
+ System_RTLConsts_SVersion32, L"32-bit Edition"
+ System_RTLConsts_SVersion64, L"64-bit Edition"
+ System_RTLConsts_SWindows, L"Windows"
+ System_RTLConsts_SWindowsVista, L"Windows Vista"
+ System_RTLConsts_SWindowsServer2008, L"Windows Server 2008"
+ System_RTLConsts_SWindows7, L"Windows 7"
+ System_RTLConsts_SWindowsServer2008R2, L"Windows Server 2008 R2"
+ System_RTLConsts_SWindows2000, L"Windows 2000"
+ System_RTLConsts_sCannotNegateTimespan, L"Negating the minimum value of a Timespan is invalid"
+ System_RTLConsts_sInvalidTimespanFormat, L"Invalid Timespan format"
+ System_RTLConsts_sTimespanElementTooLong, L"Timespan element too long"
+ System_RTLConsts_SNoContext, L"No context-sensitive help installed"
+ System_RTLConsts_SNoContextFound, L"No help found for context %d"
+ System_RTLConsts_SNoIndex, L"Unable to open Index"
+ System_RTLConsts_SNoSearch, L"Unable to open Search"
+ System_RTLConsts_SNoTableOfContents, L"Unable to find a Table of Contents"
+ System_RTLConsts_SNoTopics, L"No topic-based help system installed"
+ System_RTLConsts_SNothingFound, L"No help found for %s"
+ System_RTLConsts_SArgumentOutOfRange, L"Argument out of range"
+ System_RTLConsts_SArgumentNil, L"Argument must not be nil"
+ System_RTLConsts_SGenericItemNotFound, L"Item not found"
+ System_RTLConsts_SGenericDuplicateItem, L"Duplicates not allowed"
+ System_RTLConsts_SInsufficientRtti, L"Insufficient RTTI available to support this operation"
+ System_RTLConsts_SParameterCountMismatch, L"Parameter count mismatch"
+ System_RTLConsts_SThreadExternalCheckTerminated, L"Cannot call CheckTerminated on an externally created thread"
+ System_RTLConsts_SThreadExternalSetReturnValue, L"Cannot call SetReturnValue on an externally create thread"
+ System_RTLConsts_SParamIsNil, L"Parameter %s cannot be nil"
+ System_RTLConsts_SParamIsNegative, L"Parameter %s cannot be a negative value"
+ System_RTLConsts_SInputBufferExceed, L"Input buffer exceeded for %s = %d, %s = %d"
+ System_RTLConsts_SInvalidCharsInPath, L"Invalid characters in path"
+ System_RTLConsts_hNoFilterViewer, L"No help viewer that supports filters"
+ System_RTLConsts_sArgumentInvalid, L"Invalid argument"
+ System_RTLConsts_sInvalidStringAndObjectArrays, L"Length of Strings and Objects arrays must be equal"
+ System_RTLConsts_sSameArrays, L"Source and Destination arrays must not be the same"
+ System_RTLConsts_sNoConstruct, L"Class %s is not intended to be constructed"
+ System_RTLConsts_sInvalidTimeoutValue, L"Invalid Timeout value: %s"
+ System_RTLConsts_sSpinCountOutOfRange, L"SpinCount out of range. Must be between 0 and %d"
+ System_RTLConsts_sTimespanTooLong, L"Timespan too long"
+ System_RTLConsts_sInvalidTimespanDuration, L"The duration cannot be returned because the absolute value exceeds the value of TTimeSpan.MaxValue"
+ System_RTLConsts_sTimespanValueCannotBeNan, L"Value cannot be NaN"
+ System_RTLConsts_SReadError, L"Stream read error"
+ System_RTLConsts_SReadOnlyProperty, L"Property is read-only"
+ System_RTLConsts_SRegCreateFailed, L"Failed to create key %s"
+ System_RTLConsts_SRegGetDataFailed, L"Failed to get data for '%s'"
+ System_RTLConsts_SRegSetDataFailed, L"Failed to set data for '%s'"
+ System_RTLConsts_SResNotFound, L"Resource %s not found"
+ System_RTLConsts_SSeekNotImplemented, L"%s.Seek not implemented"
+ System_RTLConsts_SSortedListError, L"Operation not allowed on sorted list"
+ System_RTLConsts_SUnknownGroup, L"%s not in a class registration group"
+ System_RTLConsts_SUnknownProperty, L"Property %s does not exist"
+ System_RTLConsts_SWriteError, L"Stream write error"
+ System_RTLConsts_SThreadCreateError, L"Thread creation error: %s"
+ System_RTLConsts_SThreadError, L"Thread Error: %s (%d)"
+ System_RTLConsts_SThreadExternalTerminate, L"Cannot terminate an externally created thread"
+ System_RTLConsts_SThreadExternalWait, L"Cannot wait for an externally created thread"
+ System_RTLConsts_SThreadStartError, L"Cannot call Start on a running or suspended thread"
+ System_RTLConsts_SFCreateErrorEx, L"Cannot create file \"%s\". %s"
+ System_RTLConsts_SFOpenErrorEx, L"Cannot open file \"%s\". %s"
+ System_RTLConsts_SInvalidImage, L"Invalid stream format"
+ System_RTLConsts_SInvalidName, L"''%s'' is not a valid component name"
+ System_RTLConsts_SInvalidProperty, L"Invalid property value"
+ System_RTLConsts_SInvalidPropertyPath, L"Invalid property path"
+ System_RTLConsts_SInvalidPropertyValue, L"Invalid property value"
+ System_RTLConsts_SInvalidRegType, L"Invalid data type for '%s'"
+ System_RTLConsts_SListCapacityError, L"List capacity out of bounds (%d)"
+ System_RTLConsts_SListCountError, L"List count out of bounds (%d)"
+ System_RTLConsts_SListIndexError, L"List index out of bounds (%d)"
+ System_RTLConsts_SListIndexErrorRangeReason, L". %s range is 0..%d"
+ System_RTLConsts_SListIndexErrorEmptyReason, L". %s is empty"
+ System_RTLConsts_SMemoryStreamError, L"Out of memory while expanding memory stream"
+ System_RTLConsts_SNoComSupport, L"%s has not been registered as a COM class"
+ System_RTLConsts_SPropertyException, L"Error reading %s%s%s: %s"
+ System_SysConst_SInvalidCharCount, L"Invalid count (%d)"
+ System_SysConst_SInvalidDestinationIndex, L"Invalid destination index (%d)"
+ System_SysConst_SInvalidCodePage, L"Invalid code page"
+ System_SysConst_SInvalidEncodingName, L"Invalid encoding name"
+ System_SysConst_SNoMappingForUnicodeCharacter, L"No mapping for the Unicode character exists in the target multi-byte code page"
+ System_SysConst_SInvalidStringBaseIndex, L"Invalid StringBaseIndex"
+ System_RTLConsts_SAncestorNotFound, L"Ancestor for '%s' not found"
+ System_RTLConsts_SAssignError, L"Cannot assign a %s to a %s"
+ System_RTLConsts_SBitsIndexError, L"Bits index out of range"
+ System_RTLConsts_SCantWriteResourceStreamError, L"Can't write to a read-only resource stream"
+ System_RTLConsts_SCheckSynchronizeError, L"CheckSynchronize called from thread $%x, which is NOT the main thread"
+ System_RTLConsts_SClassNotFound, L"Class %s not found"
+ System_RTLConsts_SDuplicateClass, L"A class named %s already exists"
+ System_RTLConsts_SDuplicateItem, L"List does not allow duplicates ($0%x)"
+ System_RTLConsts_SDuplicateName, L"A component named %s already exists"
+ System_RTLConsts_SDuplicateString, L"String list does not allow duplicates"
+ System_SysConst_SShortDayNameTue, L"Tue"
+ System_SysConst_SShortDayNameWed, L"Wed"
+ System_SysConst_SShortDayNameThu, L"Thu"
+ System_SysConst_SShortDayNameFri, L"Fri"
+ System_SysConst_SShortDayNameSat, L"Sat"
+ System_SysConst_SLongDayNameSun, L"Sunday"
+ System_SysConst_SLongDayNameMon, L"Monday"
+ System_SysConst_SLongDayNameTue, L"Tuesday"
+ System_SysConst_SLongDayNameWed, L"Wednesday"
+ System_SysConst_SLongDayNameThu, L"Thursday"
+ System_SysConst_SLongDayNameFri, L"Friday"
+ System_SysConst_SLongDayNameSat, L"Saturday"
+ System_SysConst_SInvalidSourceArray, L"Invalid source array"
+ System_SysConst_SInvalidDestinationArray, L"Invalid destination array"
+ System_SysConst_SCharIndexOutOfBounds, L"Character index out of bounds (%d)"
+ System_SysConst_SByteIndexOutOfBounds, L"Start index out of bounds (%d)"
+ System_SysConst_SShortMonthNameNov, L"Nov"
+ System_SysConst_SShortMonthNameDec, L"Dec"
+ System_SysConst_SLongMonthNameJan, L"January"
+ System_SysConst_SLongMonthNameFeb, L"February"
+ System_SysConst_SLongMonthNameMar, L"March"
+ System_SysConst_SLongMonthNameApr, L"April"
+ System_SysConst_SLongMonthNameMay, L"May"
+ System_SysConst_SLongMonthNameJun, L"June"
+ System_SysConst_SLongMonthNameJul, L"July"
+ System_SysConst_SLongMonthNameAug, L"August"
+ System_SysConst_SLongMonthNameSep, L"September"
+ System_SysConst_SLongMonthNameOct, L"October"
+ System_SysConst_SLongMonthNameNov, L"November"
+ System_SysConst_SLongMonthNameDec, L"December"
+ System_SysConst_SShortDayNameSun, L"Sun"
+ System_SysConst_SShortDayNameMon, L"Mon"
+ System_SysConst_SObjectDisposed, L"Method called on disposed object"
+ System_SysConst_SAssertError, L"%s (%s, line %d)"
+ System_SysConst_SAbstractError, L"Abstract Error"
+ System_SysConst_SModuleAccessViolation, L"Access violation at address %p in module '%s' (offset %x). %s of address %p"
+ System_SysConst_SOSError, L"System Error. Code: %d.\r\n%s%s"
+ System_SysConst_SUnkOSError, L"A call to an OS function failed"
+ System_SysConst_SShortMonthNameJan, L"Jan"
+ System_SysConst_SShortMonthNameFeb, L"Feb"
+ System_SysConst_SShortMonthNameMar, L"Mar"
+ System_SysConst_SShortMonthNameApr, L"Apr"
+ System_SysConst_SShortMonthNameMay, L"May"
+ System_SysConst_SShortMonthNameJun, L"Jun"
+ System_SysConst_SShortMonthNameJul, L"Jul"
+ System_SysConst_SShortMonthNameAug, L"Aug"
+ System_SysConst_SShortMonthNameSep, L"Sep"
+ System_SysConst_SShortMonthNameOct, L"Oct"
+ System_SysConst_SVarTypeNotUsableWithPrefix, L"Custom variant type (%s%.4x) is not usable"
+ System_SysConst_SVarTypeTooManyCustom, L"Too many custom variant types have been registered"
+ System_SysConst_SVarTypeCouldNotConvert, L"Could not convert variant of type (%s) into type (%s)"
+ System_SysConst_SVarTypeConvertOverflow, L"Overflow while converting variant of type (%s) into type (%s)"
+ System_SysConst_SVarOverflow, L"Variant overflow"
+ System_SysConst_SVarInvalid, L"Invalid argument"
+ System_SysConst_SVarBadType, L"Invalid variant type"
+ System_SysConst_SVarNotImplemented, L"Operation not supported"
+ System_SysConst_SVarUnexpected, L"Unexpected variant error"
+ System_SysConst_SExternalException, L"External exception %x"
+ System_SysConst_SAssertionFailed, L"Assertion failed"
+ System_SysConst_SIntfCastError, L"Interface not supported"
+ System_SysConst_SSafecallException, L"Exception in safecall method"
+ System_SysConst_SMonitorLockException, L"Object lock not owned"
+ System_SysConst_SNoMonitorSupportException, L"Monitor support function not initialized"
+ System_SysConst_SNotImplemented, L"Feature not implemented"
+ System_SysConst_SInvalidFormat, L"Format '%s' invalid or incompatible with argument"
+ System_SysConst_SArgumentMissing, L"No argument for format '%s'"
+ System_SysConst_SDispatchError, L"Variant method calls not supported"
+ System_SysConst_SReadAccess, L"Read"
+ System_SysConst_SWriteAccess, L"Write"
+ System_SysConst_SExecuteAccess, L"Execution"
+ System_SysConst_SInvalidAccess, L"Invalid access"
+ System_SysConst_SVarArrayCreate, L"Error creating variant or safe array"
+ System_SysConst_SVarArrayBounds, L"Variant or safe array index out of bounds"
+ System_SysConst_SVarArrayLocked, L"Variant or safe array is locked"
+ System_SysConst_SInvalidVarCast, L"Invalid variant type conversion"
+ System_SysConst_SInvalidVarOp, L"Invalid variant operation"
+ System_SysConst_SInvalidVarNullOp, L"Invalid NULL variant operation"
+ System_SysConst_SInvalidVarOpWithHResultWithPrefix, L"Invalid variant operation (%s%.8x)\n%s"
+ System_SysConst_SVarTypeOutOfRangeWithPrefix, L"Custom variant type (%s%.4x) is out of range"
+ System_SysConst_SVarTypeAlreadyUsedWithPrefix, L"Custom variant type (%s%.4x) already used by %s"
+ System_SysConst_SRangeError, L"Range check error"
+ System_SysConst_SIntOverflow, L"Integer overflow"
+ System_SysConst_SInvalidOp, L"Invalid floating point operation"
+ System_SysConst_SZeroDivide, L"Floating point division by zero"
+ System_SysConst_SOverflow, L"Floating point overflow"
+ System_SysConst_SUnderflow, L"Floating point underflow"
+ System_SysConst_SInvalidPointer, L"Invalid pointer operation"
+ System_SysConst_SInvalidCast, L"Invalid class typecast"
+ System_SysConst_SAccessViolationArg3, L"Access violation at address %p. %s of address %p"
+ System_SysConst_SAccessViolationNoArg, L"Access violation"
+ System_SysConst_SStackOverflow, L"Stack overflow"
+ System_SysConst_SControlC, L"Control-C hit"
+ System_SysConst_SPrivilege, L"Privileged instruction"
+ System_SysConst_SOperationAborted, L"Operation aborted"
+ System_SysConst_SException, L"Exception %s in module %s at %p.\r\n%s%s\r\n"
+ System_SysConst_SExceptTitle, L"Application Error"
+ System_SysConst_SUnknown, L""
+ System_SysConst_SInvalidInteger, L"'%s' is not a valid integer value"
+ System_SysConst_SInvalidTimeStamp, L"'%d.%d' is not a valid timestamp"
+ System_SysConst_SInvalidGUID, L"'%s' is not a valid GUID value"
+ System_SysConst_STimeEncodeError, L"Invalid argument to time encode"
+ System_SysConst_SDateEncodeError, L"Invalid argument to date encode"
+ System_SysConst_SOutOfMemory, L"Out of memory"
+ System_SysConst_SInOutError, L"I/O error %d"
+ System_SysConst_SFileNotFound, L"File not found"
+ System_SysConst_SInvalidUnknownFilename, L"Invalid filename"
+ System_SysConst_STooManyOpenFiles, L"Too many open files"
+ System_SysConst_SAccessDenied, L"File access denied"
+ System_SysConst_SEndOfFile, L"Read beyond end of file"
+ System_SysConst_SDiskFull, L"Disk full"
+ System_SysConst_SInvalidInput, L"Invalid numeric input"
+ System_SysConst_SDivByZero, L"Division by zero"
+END
+
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release\Controls.res */
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release\Dialogs.res */
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release\Buttons.res */
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win32\release\SPIN.RES */
+/* D:\_Delphi\_Library\Netcom7\Demos\TCP\SimpleSockets_TLS\Client\ufrmMain.dfm */
+/* D:\_Delphi\_Library\Netcom7\Demos\TCP\SimpleSockets_TLS\Client\Client.res */
+/* D:\_Delphi\_Library\Netcom7\Demos\TCP\SimpleSockets_TLS\Client\Client.drf */
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/Client.identcache b/Demos/TCP/SimpleSockets_TLS/Client/Client.identcache
new file mode 100644
index 0000000..ef31e90
Binary files /dev/null and b/Demos/TCP/SimpleSockets_TLS/Client/Client.identcache differ
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/Client.res b/Demos/TCP/SimpleSockets_TLS/Client/Client.res
new file mode 100644
index 0000000..07e9981
Binary files /dev/null and b/Demos/TCP/SimpleSockets_TLS/Client/Client.res differ
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.dcu b/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.dcu
new file mode 100644
index 0000000..b9cca5e
Binary files /dev/null and b/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.dcu differ
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.dfm b/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.dfm
new file mode 100644
index 0000000..0e8b317
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.dfm
@@ -0,0 +1,173 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ ActiveControl = edtDataToSend
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'TCPClient - TLS'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 169
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start TCP Client'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pnlAddress: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtHost: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 281
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ TextHint = 'Enter host address'
+ OnChange = edtHostChange
+ end
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 291
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 211
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendData: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send'
+ Default = True
+ TabOrder = 0
+ OnClick = btnSendDataClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtDataToSend: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 407
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'This is some text data'
+ TextHint = 'Enter data to send here'
+ OnEnter = edtDataToSendEnter
+ OnExit = edtDataToSendExit
+ end
+ end
+ end
+ object TCPClient: TncTCPClient
+ OnConnected = TCPClientConnected
+ OnDisconnected = TCPClientDisconnected
+ OnReadData = TCPClientReadData
+ OnReconnected = TCPClientReconnected
+ Left = 208
+ Top = 80
+ end
+end
diff --git a/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.pas b/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.pas
new file mode 100644
index 0000000..8142475
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Client/ufrmMain.pas
@@ -0,0 +1,247 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin,
+ System.Diagnostics, ncLines, ncSockets;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pnlAddress: TPanel;
+ edtHost: TEdit;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendData: TButton;
+ Panel2: TPanel;
+ edtDataToSend: TEdit;
+ TCPClient: TncTCPClient;
+ procedure btnActivateClick(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure TCPClientConnected(Sender: TObject; aLine: TncLine);
+ procedure TCPClientDisconnected(Sender: TObject; aLine: TncLine);
+ procedure TCPClientReconnected(Sender: TObject; aLine: TncLine);
+ procedure edtHostChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnSendDataClick(Sender: TObject);
+ procedure edtDataToSendEnter(Sender: TObject);
+ procedure edtDataToSendExit(Sender: TObject);
+ procedure TCPClientReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure FormCreate(Sender: TObject);
+ private
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ // Configure TLS settings for the client
+ TCPClient.UseTLS := True; // Enable TLS encryption
+ TCPClient.TlsProvider := tpSChannel; // Use Windows SChannel (Windows built-in TLS)
+ TCPClient.IgnoreCertificateErrors := True; // For demo purposes with self-signed certificates
+
+ // Set initial button caption
+ btnActivate.Caption := 'Start TLS Client';
+
+ Log('TLS Client configured with SChannel provider');
+ Log('Note: Certificate errors are ignored for demo purposes');
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ TCPClient.Active := False;
+ Log('TLS Client shutdown complete');
+end;
+
+// *****************************************************************************
+// Start/Stop Main CLient
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if TCPClient.Active then
+ begin
+ // Deactivate the TCP client
+ TCPClient.Active := False;
+ btnActivate.Caption := 'Start TLS Client';
+ Log('TLS Client Deactivated');
+ end
+ else
+ begin
+ // Check if the host field is blank
+ if Trim(edtHost.Text) = '' then
+ begin
+ Log('Host field cannot be blank.');
+ Exit; // Exit the procedure if the host field is blank
+ end;
+
+ try
+ // Set the host from the text field
+ TCPClient.Host := edtHost.Text;
+
+ // Activate the TCP client
+ TCPClient.Port := edtPort.Value;
+ TCPClient.Active := True;
+ btnActivate.Caption := 'Stop TLS Client';
+ Log('TLS Client Activated - attempting secure connection...');
+ except
+ on E: Exception do
+ Log('Failed to activate TLS Client: ' + E.Message);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change host (server)
+// *****************************************************************************
+procedure TForm1.edtHostChange(Sender: TObject);
+begin
+ try
+ TCPClient.Host := edtHost.Text;
+ except
+ edtHost.OnChange := nil;
+ try
+ edtHost.Text := TCPClient.Host;
+ finally
+ edtHost.OnChange := edtHostChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ TCPClient.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := TCPClient.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Data to send
+// *****************************************************************************
+procedure TForm1.edtDataToSendEnter(Sender: TObject);
+begin
+ btnSendData.Default := True;
+end;
+
+procedure TForm1.edtDataToSendExit(Sender: TObject);
+begin
+ btnSendData.Default := False;
+end;
+
+procedure TForm1.btnSendDataClick(Sender: TObject);
+begin
+ // Check if the data field is blank
+ if Trim(edtDataToSend.Text) = '' then
+ begin
+ Log('Cannot send - Data field cannot be blank.');
+ Exit; // Exit the procedure if the data field is blank
+ end;
+
+ try
+ // Send the data
+ TCPClient.Send(edtDataToSend.Text);
+ Log('Data sent via TLS: ' + edtDataToSend.Text);
+ except
+ on E: Exception do
+ Log('Failed to send data via TLS: ' + E.Message);
+ end;
+end;
+
+// *****************************************************************************
+// TCPClientConnected
+// *****************************************************************************
+procedure TForm1.TCPClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ if TCPClient.UseTLS then
+ Log('Connected with TLS encryption (SChannel)')
+ else
+ Log('Connected without encryption');
+ btnActivate.Caption := 'Deactivate';
+end;
+
+// *****************************************************************************
+// TCPClientDisconnected
+// *****************************************************************************
+procedure TForm1.TCPClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('TLS Connection Disconnected');
+ btnActivate.Caption := 'Start TLS Client';
+end;
+
+// *****************************************************************************
+// TCPClientReconnected
+// *****************************************************************************
+procedure TForm1.TCPClientReconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('TLS Connection Reconnected');
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.TCPClientReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ BytesReceived: TBytes;
+begin
+ BytesReceived := Copy(aBuf, 0, aBufCount);
+
+ Log('Received via TLS: ' + StringOf(BytesReceived));
+
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/Server.dpr b/Demos/TCP/SimpleSockets_TLS/Server/Server.dpr
new file mode 100644
index 0000000..63d6f38
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Server/Server.dpr
@@ -0,0 +1,17 @@
+program Server;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/Server.dproj b/Demos/TCP/SimpleSockets_TLS/Server/Server.dproj
new file mode 100644
index 0000000..c8ac3b5
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Server/Server.dproj
@@ -0,0 +1,260 @@
+
+
+ {0B2EB3CC-F54E-41A8-A712-8771BC0FC4AD}
+ Server.dpr
+ True
+ Debug
+ Server
+ 3
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ Server
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Server.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+ False
+ False
+ False
+ False
+ False
+ False
+ True
+ True
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/Server.dproj.local b/Demos/TCP/SimpleSockets_TLS/Server/Server.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Server/Server.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/Server.identcache b/Demos/TCP/SimpleSockets_TLS/Server/Server.identcache
new file mode 100644
index 0000000..4a109ca
Binary files /dev/null and b/Demos/TCP/SimpleSockets_TLS/Server/Server.identcache differ
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/Server.res b/Demos/TCP/SimpleSockets_TLS/Server/Server.res
new file mode 100644
index 0000000..a57e245
Binary files /dev/null and b/Demos/TCP/SimpleSockets_TLS/Server/Server.res differ
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/server.key b/Demos/TCP/SimpleSockets_TLS/Server/server.key
new file mode 100644
index 0000000..be9053f
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Server/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZF6wX9HCEqm0K
+yByBjMqIzbN9dpOc9kX5tJSMF2TLuSFxjQqL8qiTJsY5lFevpZ6OvA7kI+X5u5AV
+Fu15Epl9GSdSuYxVYj33NGWTyLUEb4ctwF5ado86D+ezQP8Dnlg5bhPPimhBQTpv
+/Fl/FptrcyzzYEBWCyeSbzy8hPQLEomJc8A5OX7l+wm5dhFM6tWTHRR0gV1ZXIIk
+1nQgXdF+HcUeamHY2+xpF0wLdCSTTj/em21blPmEE7JtmxYuAXFqo3H9YPlTNwJv
+6Ztsl59XRJFOFiWm8PINB23oDwDI+yTqXbzSRIX0BpZs3B/TSSneVjKOFZVxYdnM
+lr1UMeefAgMBAAECggEANbCfoicP7vb2FvnnRWfi/+dkM3QKgNm94Lz7+8WYi/n5
+SKF2OW54wGKw0jC8L9WdreE2N7x/Qv4ModjQn81uFvljWRfJp4g0wyWVGichlNSo
+S9tTO9aolGxPjgYVaWd2+W0pdXfM6FW/8NZHbNK43w4djZ0L8yEmV6y7WEIodFkY
+8jDmU3OBjdJ0/bdh5zQe/g+IY2RF6+JIYUM4qsxWiWWvtLXIL5npVo0oMOAlNI+/
+iR6i3fXrvR3HvHBK9n/aLeXg4Qei2buNVSbVhM7zOjf1ziDypb7/VGJLf/Kkv8wB
+qrHTNa5d8N6JsmDNRNhtw01TmezHFMrGmEDrMQBXwQKBgQDPOwqPBUAD4/1rAp9/
+QvZQAiU443E+20I9eQlewCNc+/vbNHF9N8lqNm03LR0o/JIHCbU+w+POFXqyvoRG
+3Zj3j3lfpR3kO8ED3qy2o3LRi3/Rdu10XyAC6DCTc5HDtY26SGiM4LMSiYJKcxyT
+AA0BPi7RuaEEdAByFnTfUwbFzQKBgQC9Hvx6T2YLWAWbrsUcKwkJPWdYjI5HH3hn
+vTnFSsmLKpV4olwDT4R2yYlk0Wpt29Nu0ePSI5QxAwfKuwdmt701LkyRsErhZS29
+gzOvo2cCRB1R59Xnpj/nLQTVQw5tnHaT/fb+I6C8lIZRT8vZv9Xs+PUijbONf0aL
+8ZIw2ew3GwKBgQCEY2efbu8yjRh8oLRcjN7mxjgZW9QhH9n1g7mkuoLdCG4h4CMQ
+p+8Y16R2N3AFmzV/IYiUjHigU8CLKINA8piirxoPLGEoSbRJUJxuIYVcsQ37N0sD
+qTG+Ka++w3o/2WCtvUxtk69TDF4cSeXbU5D7Vkp62WgwfBs8x3PqqBQPkQKBgEM/
+qXe0lAykmBnr45tIkkX+16jdEhqoTiBVYR2OomwiEFR9J0rmE6xJrdlzveyipmRZ
+rjEjBacH9NVZ/B/CZj1q4T9M+NN9Lu6coNxrtk1P+z0MuztMGp0RnQ5YceD4KhIl
+1JY6BQYJqllvjoU3edJyFHjc+mPuRh+tHtbQJvbRAoGAR1T9fGCYn+uDwBq2B9Jt
+wMMXDD6homo+OiqEALAjUt2dOxCDH84IhGnSYP27M/pAwsMI416oskPXXEPV4nB+
+GNxbI9eKnAwiWkktbY610j6pSmHu1T0Z1GBm5HnXYrtFUHi9k+1LU/iuj2mouNus
+XpqwE8eeQQeaqJP7BmuwJXk=
+-----END PRIVATE KEY-----
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/server.pfx b/Demos/TCP/SimpleSockets_TLS/Server/server.pfx
new file mode 100644
index 0000000..0b1ad11
Binary files /dev/null and b/Demos/TCP/SimpleSockets_TLS/Server/server.pfx differ
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/ufrmMain.dfm b/Demos/TCP/SimpleSockets_TLS/Server/ufrmMain.dfm
new file mode 100644
index 0000000..18b9359
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Server/ufrmMain.dfm
@@ -0,0 +1,122 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'TCPServer - TLS'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 182
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Activate'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pblPort: TPanel
+ AlignWithMargins = True
+ Left = 115
+ Top = 3
+ Width = 412
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ object btnShutdownAllClients: TButton
+ AlignWithMargins = True
+ Left = 256
+ Top = 5
+ Width = 151
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ Caption = 'Shutdown all clients'
+ TabOrder = 1
+ OnClick = btnShutdownAllClientsClick
+ end
+ end
+ end
+ object StatusBar1: TStatusBar
+ Left = 0
+ Top = 224
+ Width = 527
+ Height = 19
+ Panels = <
+ item
+ Text = 'Connections: 0'
+ Width = 150
+ end>
+ end
+ object TCPServer: TncTCPServer
+ OnConnected = TCPServerConnected
+ OnDisconnected = TCPServerDisconnected
+ OnReadData = TCPServerReadData
+ Left = 92
+ Top = 52
+ end
+end
diff --git a/Demos/TCP/SimpleSockets_TLS/Server/ufrmMain.pas b/Demos/TCP/SimpleSockets_TLS/Server/ufrmMain.pas
new file mode 100644
index 0000000..963afa7
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/Server/ufrmMain.pas
@@ -0,0 +1,294 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.ComCtrls,
+ System.Diagnostics, ncLines, ncSocketList, ncSockets;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ TCPServer: TncTCPServer;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pblPort: TPanel;
+ edtPort: TSpinEdit;
+ btnShutdownAllClients: TButton;
+ StatusBar1: TStatusBar;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure TCPServerConnected(Sender: TObject; aLine: TncLine);
+ procedure TCPServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure btnActivateClick(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnShutdownAllClientsClick(Sender: TObject);
+ procedure TCPServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ private
+ FConnectionCount: Integer;
+ procedure UpdateConnectionCount;
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+function FileSize(const AFilename: string): Int64;
+var
+ FileStream: TFileStream;
+begin
+ Result := 0;
+ if FileExists(AFilename) then
+ try
+ FileStream := TFileStream.Create(AFilename, fmOpenRead or fmShareDenyNone);
+ try
+ Result := FileStream.Size;
+ finally
+ FileStream.Free;
+ end;
+ except
+ Result := 0;
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+var
+ CertPath: string;
+begin
+ FConnectionCount := 0;
+ UpdateConnectionCount;
+
+ // Configure TLS settings for the server
+ TCPServer.UseTLS := True; // Enable TLS encryption
+ TCPServer.TlsProvider := tpSChannel; // Use Windows SChannel (Windows built-in TLS)
+
+ // Verify certificate file exists
+ CertPath := ExtractFilePath(Application.ExeName) + 'server.pfx';
+ if FileExists(CertPath) then
+ begin
+ TCPServer.CertificateFile := CertPath; // Certificate file path
+ TCPServer.PrivateKeyPassword := 'test'; // Certificate password
+ TCPServer.IgnoreCertificateErrors := False; // For demo purposes
+
+ Log('Certificate file found: ' + CertPath);
+ Log('Certificate file size: ' + IntToStr(FileSize(CertPath)) + ' bytes');
+ end
+ else
+ begin
+ Log('ERROR: Certificate file not found: ' + CertPath);
+ Log('Please ensure server.pfx is in the same directory as the executable');
+ // Still configure TLS but it will fail
+ TCPServer.CertificateFile := CertPath;
+ TCPServer.PrivateKeyPassword := 'test';
+ TCPServer.IgnoreCertificateErrors := False;
+ end;
+
+ // Set initial button caption
+ btnActivate.Caption := 'Start TLS Server';
+
+ Log('TLS Server configured with SChannel provider');
+ Log('Note: Certificate errors are ignored for demo purposes');
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ TCPServer.Active := False;
+ Log('TLS Server shutdown complete');
+end;
+
+// *****************************************************************************
+// Start/Stop Main Server
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if TCPServer.Active then
+ begin
+ // Deactivate the TCP Server
+ TCPServer.Active := False;
+ btnActivate.Caption := 'Start TLS Server';
+ Log('TLS Server Deactivated');
+ end
+ else
+ begin
+ try
+ // Validate TLS configuration before starting
+ if not FileExists(TCPServer.CertificateFile) then
+ begin
+ Log('ERROR: Certificate file not found: ' + TCPServer.CertificateFile);
+ Log('Cannot start TLS server without valid certificate');
+ Exit;
+ end;
+
+ Log('Starting TLS server with configuration:');
+ Log(' UseTLS: ' + BoolToStr(TCPServer.UseTLS, True));
+ Log(' TlsProvider: ' + IntToStr(Ord(TCPServer.TlsProvider)));
+ Log(' Certificate: ' + TCPServer.CertificateFile);
+ Log(' IgnoreCertErrors: ' + BoolToStr(TCPServer.IgnoreCertificateErrors, True));
+
+ // Activate the TCP Server
+ TCPServer.Port := edtPort.Value;
+ TCPServer.Active := True;
+ btnActivate.Caption := 'Stop TLS Server';
+ Log('TLS Server Activated at port: ' + IntToStr(TCPServer.Port));
+ Log('Server ready to accept TLS connections');
+
+ except
+ on E: Exception do
+ begin
+ Log('Failed to activate TLS Server: ' + E.Message);
+ Log('Exception class: ' + E.ClassName);
+ end;
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ TCPServer.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := TCPServer.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Shutdown all Clients
+// *****************************************************************************
+procedure TForm1.btnShutdownAllClientsClick(Sender: TObject);
+var
+ SocketList: TSocketList;
+ i: Integer;
+begin
+ SocketList := TCPServer.Lines.LockList;
+ try
+ Log('Shutting down all TLS clients...');
+ for i := 0 to SocketList.Count - 1 do
+ TCPServer.ShutDownLine(SocketList.Lines[i]);
+ Log('All TLS clients shutdown requested');
+ finally
+ TCPServer.Lines.UnlockList;
+ end;
+end;
+
+procedure TForm1.UpdateConnectionCount;
+begin
+ StatusBar1.Panels[0].Text := 'TLS Connections: ' + IntToStr(FConnectionCount);
+end;
+
+// *****************************************************************************
+// TCPServerConnected
+// *****************************************************************************
+procedure TForm1.TCPServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ Inc(FConnectionCount);
+ UpdateConnectionCount;
+
+ Log('TLS Client Connected: ' + aLine.PeerIP + ' (Handle: ' + IntToStr(aLine.Handle) + ')');
+ Log('Starting TLS handshake...');
+
+ try
+ // Send welcome message
+ TCPServer.Send(aLine, BytesOf('Hello mr. ' + IntToStr(aLine.Handle) + ' - TLS connection established'));
+ Log('Welcome message sent to: ' + aLine.PeerIP);
+ Log('TLS handshake completed successfully');
+ except
+ on E: Exception do
+ begin
+ Log('ERROR during TLS handshake with ' + aLine.PeerIP + ': ' + E.Message);
+ Log('Exception class: ' + E.ClassName);
+ // Don't re-raise - let the connection continue to see what happens
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// TCPServerDisconnected
+// *****************************************************************************
+procedure TForm1.TCPServerDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Dec(FConnectionCount);
+ UpdateConnectionCount;
+
+ Log('TLS Client Disconnected: ' + aLine.PeerIP + ' (Handle: ' + IntToStr(aLine.Handle) + ')');
+ Log('Connection duration: Client was connected');
+
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.TCPServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ BytesReceived: TBytes;
+ ReceivedText: string;
+begin
+ try
+ BytesReceived := Copy(aBuf, 0, aBufCount);
+
+ // Convert bytes to string using proper UTF-8 decoding
+ ReceivedText := TEncoding.UTF8.GetString(BytesReceived);
+
+ Log('Received via TLS: "' + ReceivedText + '" from: ' + aLine.PeerIP + ' (Handle: ' + IntToStr(aLine.Handle) + ')');
+
+ // Send back the buffer received
+ TCPServer.Send(aLine, BytesReceived);
+
+ Log('Data sent via TLS: ' + ReceivedText + ' to: ' + aLine.PeerIP);
+ except
+ on E: Exception do
+ begin
+ Log('ERROR in TLS data handling with ' + aLine.PeerIP + ': ' + E.Message);
+ Log('Exception class: ' + E.ClassName);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/SimpleSockets_TLS/SimpleSockets_TLS.groupproj b/Demos/TCP/SimpleSockets_TLS/SimpleSockets_TLS.groupproj
new file mode 100644
index 0000000..3122a45
--- /dev/null
+++ b/Demos/TCP/SimpleSockets_TLS/SimpleSockets_TLS.groupproj
@@ -0,0 +1,48 @@
+
+
+ {A9A55D39-6A58-48E9-AA5F-4DED5B38E8A8}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/VideoChat/Client/AndroidManifest.template.xml b/Demos/TCP/VideoChat/Client/AndroidManifest.template.xml
similarity index 100%
rename from Demos/VideoChat/Client/AndroidManifest.template.xml
rename to Demos/TCP/VideoChat/Client/AndroidManifest.template.xml
diff --git a/Demos/VideoChat/Client/VideoChatClient.deployproj b/Demos/TCP/VideoChat/Client/VideoChatClient.deployproj
similarity index 98%
rename from Demos/VideoChat/Client/VideoChatClient.deployproj
rename to Demos/TCP/VideoChat/Client/VideoChatClient.deployproj
index 2b87501..d1546ba 100644
--- a/Demos/VideoChat/Client/VideoChatClient.deployproj
+++ b/Demos/TCP/VideoChat/Client/VideoChatClient.deployproj
@@ -1,462 +1,462 @@
-
-
-
- 12
-
-
- 4JPNU18C10101373
- 4JPNU18C10101373
-
-
-
- VideoChatClient\
- VideoChatClient.exe
- ProjectOutput
- 0
-
-
- True
- True
-
-
- VideoChatClient\
- VideoChatClient.exe
- ProjectOutput
- 0
-
-
- True
- True
-
-
-
-
-
- VideoChatClient\res\drawable\
- splash_image_def.xml
- AndroidSplashImageDef
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-mdpi\
- ic_notification.png
- Android_NotificationIcon24
- 1
-
-
- True
-
-
- VideoChatClient\res\values-v21\
- styles.xml
- AndroidSplashStylesV21
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xxhdpi\
- ic_notification.png
- Android_NotificationIcon72
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-normal\
- splash_image.png
- Android_SplashImage470
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xxxhdpi\
- ic_notification.png
- Android_NotificationIcon96
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xhdpi\
- ic_notification.png
- Android_NotificationIcon48
- 1
-
-
- True
-
-
- VideoChatClient\classes\
- classes.dex
- AndroidClassesDexFile
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-mdpi\
- ic_launcher.png
- Android_LauncherIcon48
- 1
-
-
- True
-
-
- VideoChatClient\res\values\
- styles.xml
- AndroidSplashStyles
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-ldpi\
- ic_launcher.png
- Android_LauncherIcon36
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-small\
- splash_image.png
- Android_SplashImage426
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xlarge\
- splash_image.png
- Android_SplashImage960
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-hdpi\
- ic_launcher.png
- Android_LauncherIcon72
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-hdpi\
- ic_notification.png
- Android_NotificationIcon36
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xxhdpi\
- ic_launcher.png
- Android_LauncherIcon144
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xhdpi\
- ic_launcher.png
- Android_LauncherIcon96
- 1
-
-
- True
-
-
- VideoChatClient\res\values\
- strings.xml
- Android_Strings
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-large\
- splash_image.png
- Android_SplashImage640
- 1
-
-
- True
-
-
- VideoChatClient\res\values\
- colors.xml
- Android_Colors
- 1
-
-
- True
-
-
- VideoChatClient\
- AndroidManifest.xml
- ProjectAndroidManifest
- 1
-
-
- True
-
-
- VideoChatClient\library\lib\armeabi-v7a\
- libVideoChatClient.so
- ProjectOutput
- 1
-
-
- True
- True
-
-
-
-
- VideoChatClient\res\drawable-hdpi\
- ic_launcher.png
- Android_LauncherIcon72
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xxhdpi\
- ic_notification.png
- Android_NotificationIcon72
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xlarge\
- splash_image.png
- Android_SplashImage960
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-hdpi\
- ic_notification.png
- Android_NotificationIcon36
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-mdpi\
- ic_notification.png
- Android_NotificationIcon24
- 1
-
-
- True
-
-
- VideoChatClient\res\values\
- styles.xml
- AndroidSplashStyles
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xhdpi\
- ic_notification.png
- Android_NotificationIcon48
- 1
-
-
- True
-
-
- VideoChatClient\library\lib\armeabi\
- libVideoChatClient.so
- AndroidLibnativeArmeabiFile
- 1
-
-
- True
-
-
- VideoChatClient\res\values\
- strings.xml
- Android_Strings
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xhdpi\
- ic_launcher.png
- Android_LauncherIcon96
- 1
-
-
- True
-
-
- VideoChatClient\res\values\
- colors.xml
- Android_Colors
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xxhdpi\
- ic_launcher.png
- Android_LauncherIcon144
- 1
-
-
- True
-
-
- VideoChatClient\library\lib\arm64-v8a\
- libVideoChatClient.so
- ProjectOutput
- 1
-
-
- True
- True
-
-
- VideoChatClient\res\drawable-large\
- splash_image.png
- Android_SplashImage640
- 1
-
-
- True
-
-
- VideoChatClient\classes\
- classes.dex
- AndroidClassesDexFile
- 1
-
-
- True
-
-
- VideoChatClient\
- AndroidManifest.xml
- ProjectAndroidManifest
- 1
-
-
- True
-
-
- VideoChatClient\res\values-v21\
- styles.xml
- AndroidSplashStylesV21
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-mdpi\
- ic_launcher.png
- Android_LauncherIcon48
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-xxxhdpi\
- ic_notification.png
- Android_NotificationIcon96
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable\
- splash_image_def.xml
- AndroidSplashImageDef
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-normal\
- splash_image.png
- Android_SplashImage470
- 1
-
-
- True
-
-
- VideoChatClient\library\lib\mips\
- libVideoChatClient.so
- AndroidLibnativeMipsFile
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-ldpi\
- ic_launcher.png
- Android_LauncherIcon36
- 1
-
-
- True
-
-
- VideoChatClient\res\drawable-small\
- splash_image.png
- Android_SplashImage426
- 1
-
-
- True
-
-
- VideoChatClient\library\lib\armeabi-v7a\
- libVideoChatClient.so
- AndroidLibnativeArmeabiv7aFile
- 1
-
-
- True
-
-
-
+
+
+
+ 12
+
+
+ 4JPNU18C10101373
+ 4JPNU18C10101373
+
+
+
+ VideoChatClient\
+ VideoChatClient.exe
+ ProjectOutput
+ 0
+
+
+ True
+ True
+
+
+ VideoChatClient\
+ VideoChatClient.exe
+ ProjectOutput
+ 0
+
+
+ True
+ True
+
+
+
+
+
+ VideoChatClient\res\drawable\
+ splash_image_def.xml
+ AndroidSplashImageDef
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-mdpi\
+ ic_notification.png
+ Android_NotificationIcon24
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values-v21\
+ styles.xml
+ AndroidSplashStylesV21
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xxhdpi\
+ ic_notification.png
+ Android_NotificationIcon72
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-normal\
+ splash_image.png
+ Android_SplashImage470
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xxxhdpi\
+ ic_notification.png
+ Android_NotificationIcon96
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xhdpi\
+ ic_notification.png
+ Android_NotificationIcon48
+ 1
+
+
+ True
+
+
+ VideoChatClient\classes\
+ classes.dex
+ AndroidClassesDexFile
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-mdpi\
+ ic_launcher.png
+ Android_LauncherIcon48
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values\
+ styles.xml
+ AndroidSplashStyles
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-ldpi\
+ ic_launcher.png
+ Android_LauncherIcon36
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-small\
+ splash_image.png
+ Android_SplashImage426
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xlarge\
+ splash_image.png
+ Android_SplashImage960
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-hdpi\
+ ic_launcher.png
+ Android_LauncherIcon72
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-hdpi\
+ ic_notification.png
+ Android_NotificationIcon36
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xxhdpi\
+ ic_launcher.png
+ Android_LauncherIcon144
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xhdpi\
+ ic_launcher.png
+ Android_LauncherIcon96
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values\
+ strings.xml
+ Android_Strings
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-large\
+ splash_image.png
+ Android_SplashImage640
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values\
+ colors.xml
+ Android_Colors
+ 1
+
+
+ True
+
+
+ VideoChatClient\
+ AndroidManifest.xml
+ ProjectAndroidManifest
+ 1
+
+
+ True
+
+
+ VideoChatClient\library\lib\armeabi-v7a\
+ libVideoChatClient.so
+ ProjectOutput
+ 1
+
+
+ True
+ True
+
+
+
+
+ VideoChatClient\res\drawable-hdpi\
+ ic_launcher.png
+ Android_LauncherIcon72
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xxhdpi\
+ ic_notification.png
+ Android_NotificationIcon72
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xlarge\
+ splash_image.png
+ Android_SplashImage960
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-hdpi\
+ ic_notification.png
+ Android_NotificationIcon36
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-mdpi\
+ ic_notification.png
+ Android_NotificationIcon24
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values\
+ styles.xml
+ AndroidSplashStyles
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xhdpi\
+ ic_notification.png
+ Android_NotificationIcon48
+ 1
+
+
+ True
+
+
+ VideoChatClient\library\lib\armeabi\
+ libVideoChatClient.so
+ AndroidLibnativeArmeabiFile
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values\
+ strings.xml
+ Android_Strings
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xhdpi\
+ ic_launcher.png
+ Android_LauncherIcon96
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values\
+ colors.xml
+ Android_Colors
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xxhdpi\
+ ic_launcher.png
+ Android_LauncherIcon144
+ 1
+
+
+ True
+
+
+ VideoChatClient\library\lib\arm64-v8a\
+ libVideoChatClient.so
+ ProjectOutput
+ 1
+
+
+ True
+ True
+
+
+ VideoChatClient\res\drawable-large\
+ splash_image.png
+ Android_SplashImage640
+ 1
+
+
+ True
+
+
+ VideoChatClient\classes\
+ classes.dex
+ AndroidClassesDexFile
+ 1
+
+
+ True
+
+
+ VideoChatClient\
+ AndroidManifest.xml
+ ProjectAndroidManifest
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\values-v21\
+ styles.xml
+ AndroidSplashStylesV21
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-mdpi\
+ ic_launcher.png
+ Android_LauncherIcon48
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-xxxhdpi\
+ ic_notification.png
+ Android_NotificationIcon96
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable\
+ splash_image_def.xml
+ AndroidSplashImageDef
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-normal\
+ splash_image.png
+ Android_SplashImage470
+ 1
+
+
+ True
+
+
+ VideoChatClient\library\lib\mips\
+ libVideoChatClient.so
+ AndroidLibnativeMipsFile
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-ldpi\
+ ic_launcher.png
+ Android_LauncherIcon36
+ 1
+
+
+ True
+
+
+ VideoChatClient\res\drawable-small\
+ splash_image.png
+ Android_SplashImage426
+ 1
+
+
+ True
+
+
+ VideoChatClient\library\lib\armeabi-v7a\
+ libVideoChatClient.so
+ AndroidLibnativeArmeabiv7aFile
+ 1
+
+
+ True
+
+
+
diff --git a/Demos/VideoChat/Client/VideoChatClient.dpr b/Demos/TCP/VideoChat/Client/VideoChatClient.dpr
similarity index 94%
rename from Demos/VideoChat/Client/VideoChatClient.dpr
rename to Demos/TCP/VideoChat/Client/VideoChatClient.dpr
index b1bc7b7..91996b1 100644
--- a/Demos/VideoChat/Client/VideoChatClient.dpr
+++ b/Demos/TCP/VideoChat/Client/VideoChatClient.dpr
@@ -1,19 +1,19 @@
-program VideoChatClient;
-
-uses
- System.StartUpCopy,
- FMX.Forms,
- FMX.Types,
- ufrmMain in 'ufrmMain.pas' {frmMain},
- CommonCommands in '..\Server\CommonCommands.pas';
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program VideoChatClient;
+
+uses
+ System.StartUpCopy,
+ FMX.Forms,
+ FMX.Types,
+ ufrmMain in 'ufrmMain.pas' {frmMain},
+ CommonCommands in '..\Server\CommonCommands.pas';
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/VideoChat/Client/VideoChatClient.dproj b/Demos/TCP/VideoChat/Client/VideoChatClient.dproj
similarity index 98%
rename from Demos/VideoChat/Client/VideoChatClient.dproj
rename to Demos/TCP/VideoChat/Client/VideoChatClient.dproj
index 900c066..bc960b3 100644
--- a/Demos/VideoChat/Client/VideoChatClient.dproj
+++ b/Demos/TCP/VideoChat/Client/VideoChatClient.dproj
@@ -1,1354 +1,1354 @@
-
-
- {E544FF24-71AB-4245-B7DE-2E2358404669}
- 18.8
- FMX
- VideoChatClient.dpr
- True
- Release
- Win64
- 32787
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- true
- true
- true
- true
- true
- true
- true
- true
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\delphi_PROJECTICNS.icns
- VideoChatClient
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
-
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- VideoChatClient.dpr
-
-
-
-
-
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- VideoChatClient.exe
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- VideoChatClient.exe
- true
-
-
-
-
- styles.xml
- true
-
-
-
-
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- true
-
-
-
-
- libVideoChatClient.so
- true
-
-
-
-
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- classes.dex
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- libVideoChatClient.so
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- classes.dex
- true
-
-
-
-
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- styles.xml
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- ic_notification.png
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- libVideoChatClient.so
- true
-
-
-
-
- ic_launcher.png
- true
-
-
-
-
- splash_image.png
- true
-
-
-
-
- true
-
-
-
-
- libVideoChatClient.so
- true
-
-
-
-
- libVideoChatClient.so
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- True
- True
-
-
- 12
-
-
-
-
-
+
+
+ {E544FF24-71AB-4245-B7DE-2E2358404669}
+ 18.8
+ FMX
+ VideoChatClient.dpr
+ True
+ Release
+ Win64
+ 32787
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ VideoChatClient
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ VideoChatClient.dpr
+
+
+
+
+
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ VideoChatClient.exe
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ VideoChatClient.exe
+ true
+
+
+
+
+ styles.xml
+ true
+
+
+
+
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ true
+
+
+
+
+ libVideoChatClient.so
+ true
+
+
+
+
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ classes.dex
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ libVideoChatClient.so
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ classes.dex
+ true
+
+
+
+
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ styles.xml
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ ic_notification.png
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ libVideoChatClient.so
+ true
+
+
+
+
+ ic_launcher.png
+ true
+
+
+
+
+ splash_image.png
+ true
+
+
+
+
+ true
+
+
+
+
+ libVideoChatClient.so
+ true
+
+
+
+
+ libVideoChatClient.so
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 1
+
+
+ classes
+ 1
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/VideoChat/Client/VideoChatClient.dproj.local b/Demos/TCP/VideoChat/Client/VideoChatClient.dproj.local
similarity index 99%
rename from Demos/VideoChat/Client/VideoChatClient.dproj.local
rename to Demos/TCP/VideoChat/Client/VideoChatClient.dproj.local
index 827bc5a..7193ca5 100644
--- a/Demos/VideoChat/Client/VideoChatClient.dproj.local
+++ b/Demos/TCP/VideoChat/Client/VideoChatClient.dproj.local
@@ -1,48 +1,48 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 00:19:14.000.567,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 09:24:02.000.042,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 09:29:13.000.265,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 09:29:13.000.265,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
- 2020/08/12 09:29:28.000.515,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
- 2020/08/12 10:06:25.000.279,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\Unit1.pas
- 2020/08/12 10:06:52.000.317,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\Unit1.pas
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 00:19:14.000.567,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 09:24:02.000.042,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 09:29:13.000.265,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 09:29:13.000.265,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
+ 2020/08/12 09:29:28.000.515,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
+ 2020/08/12 10:06:25.000.279,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\Unit1.pas
+ 2020/08/12 10:06:52.000.317,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\Unit1.pas
+
+
+
+
+
diff --git a/Demos/VideoChat/Client/VideoChatClient.dsk b/Demos/TCP/VideoChat/Client/VideoChatClient.dsk
similarity index 94%
rename from Demos/VideoChat/Client/VideoChatClient.dsk
rename to Demos/TCP/VideoChat/Client/VideoChatClient.dsk
index 674b3e5..2e5db05 100644
--- a/Demos/VideoChat/Client/VideoChatClient.dsk
+++ b/Demos/TCP/VideoChat/Client/VideoChatClient.dsk
@@ -1,768 +1,768 @@
-[Closed Files]
-File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.Graphics.pas',0,1,4137,1,4144,0,0,,
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas',0,1,1,3,10,0,0,,
-File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,465,39,481,0,0,,
-File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,1155,3,1170,0,0,,
-File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,610,86,624,0,0,,
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.Edit.pas',0,1,1362,1,1379,0,0,,
-File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\RTL\SYS\System.SysUtils.pas',0,1,34069,1,34086,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,3261,1,3276,0,0,,
-File_8=TSourceModule,'C:\Users\Programmer\Documents\Development\Temp\NetComTester\Client\ufrmMain.pas',0,1,1,57,7,0,0,,
-File_9=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncThreads.pas',0,1,107,1,123,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dproj
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dproj]
-ModuleType=TBaseProject
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dpr
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dpr
-CursorX=3
-CursorY=14
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas
-CursorX=1
-CursorY=74
-TopLine=67
-LeftCol=1
-Elisions=
-Bookmarks={1,87,1}
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=28
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Name,OnPaint
-ExpandedItems=BorderIcons=0,Constraints=0,Anchors=0,"LiveBindings Designer=0",Caret=0,Fill=0,FormFactor=0,Padding=0,Border=0,SystemStatusBar=0,Touch=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-318
-Top=-363
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.Graphics.pas',0,1,4137,1,4144,0,0,,
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas',0,1,1,3,10,0,0,,
+File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,465,39,481,0,0,,
+File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,1155,3,1170,0,0,,
+File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,610,86,624,0,0,,
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\fmx\FMX.Edit.pas',0,1,1362,1,1379,0,0,,
+File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\RTL\SYS\System.SysUtils.pas',0,1,34069,1,34086,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,3261,1,3276,0,0,,
+File_8=TSourceModule,'C:\Users\Programmer\Documents\Development\Temp\NetComTester\Client\ufrmMain.pas',0,1,1,57,7,0,0,,
+File_9=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncThreads.pas',0,1,107,1,123,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dproj
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dproj]
+ModuleType=TBaseProject
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dpr
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dpr
+CursorX=3
+CursorY=14
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\VideoChatClient.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Client\ufrmMain.pas
+CursorX=1
+CursorY=74
+TopLine=67
+LeftCol=1
+Elisions=
+Bookmarks={1,87,1}
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=28
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Name,OnPaint
+ExpandedItems=BorderIcons=0,Constraints=0,Anchors=0,"LiveBindings Designer=0",Caret=0,Fill=0,FormFactor=0,Padding=0,Border=0,SystemStatusBar=0,Touch=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-318
+Top=-363
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/VideoChat/Client/VideoChatClient.identcache b/Demos/TCP/VideoChat/Client/VideoChatClient.identcache
similarity index 100%
rename from Demos/VideoChat/Client/VideoChatClient.identcache
rename to Demos/TCP/VideoChat/Client/VideoChatClient.identcache
diff --git a/Demos/VideoChat/Client/VideoChatClient.res b/Demos/TCP/VideoChat/Client/VideoChatClient.res
similarity index 100%
rename from Demos/VideoChat/Client/VideoChatClient.res
rename to Demos/TCP/VideoChat/Client/VideoChatClient.res
diff --git a/Demos/VideoChat/Client/ufrmMain.fmx b/Demos/TCP/VideoChat/Client/ufrmMain.fmx
similarity index 98%
rename from Demos/VideoChat/Client/ufrmMain.fmx
rename to Demos/TCP/VideoChat/Client/ufrmMain.fmx
index 01ffd4a..fc7dcb3 100644
--- a/Demos/VideoChat/Client/ufrmMain.fmx
+++ b/Demos/TCP/VideoChat/Client/ufrmMain.fmx
@@ -1,1442 +1,1442 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'NetCom Video Chat Demo'
- ClientHeight = 576
- ClientWidth = 957
- FormFactor.Width = 320
- FormFactor.Height = 480
- FormFactor.Devices = [Desktop]
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- OnPaint = FormPaint
- DesignerMasterStyle = 0
- object ToolBar: TToolBar
- Size.Width = 957.000000000000000000
- Size.Height = 48.000000000000000000
- Size.PlatformDefault = False
- StyleLookup = 'toolbarstyle'
- TabOrder = 1
- TabStop = False
- object btnConnect: TButton
- Align = Left
- Margins.Right = 5.000000000000000000
- Position.X = 48.000000000000000000
- Size.Width = 105.000000000000000000
- Size.Height = 48.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Text = 'Connect'
- OnClick = btnConnectClick
- end
- object edtUsername: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Client
- StyleLookup = 'transparentedit'
- TabOrder = 2
- Size.Width = 799.000000000000000000
- Size.Height = 48.000000000000000000
- Size.PlatformDefault = False
- TextPrompt = 'Enter your username'
- OnEnter = edtUsernameEnter
- OnExit = edtUsernameExit
- end
- object btnMasterView: TButton
- Align = Left
- Size.Width = 48.000000000000000000
- Size.Height = 48.000000000000000000
- Size.PlatformDefault = False
- StyleLookup = 'drawertoolbutton'
- TabOrder = 4
- end
- end
- object ltContent: TLayout
- Align = Client
- Margins.Left = 48.000000000000000000
- Size.Width = 909.000000000000000000
- Size.Height = 528.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 2
- object ltCameras: TGridPanelLayout
- Align = Client
- Padding.Left = 5.000000000000000000
- Padding.Top = 5.000000000000000000
- Padding.Right = 5.000000000000000000
- Padding.Bottom = 5.000000000000000000
- Size.Width = 909.000000000000000000
- Size.Height = 323.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- TabStop = False
- ColumnCollection = <
- item
- Value = 50.000000000000000000
- end
- item
- Value = 50.000000000000000000
- end>
- ControlCollection = <
- item
- Column = 0
- Control = imgUserVideo
- Row = 0
- end
- item
- Column = 1
- Control = imgPeerUserVideo
- Row = 0
- end>
- RowCollection = <
- item
- Value = 100.000000000000000000
- end
- item
- SizeStyle = Auto
- end>
- object imgUserVideo: TImage
- MultiResBitmap.Height = 256
- MultiResBitmap.Width = 256
- MultiResBitmap = <
- item
- Width = 256
- Height = 256
- PNG = {
- 89504E470D0A1A0A0000000D49484452000001000000010008060000005C72A8
- 66000000017352474200AECE1CE90000000467414D410000B18F0BFC61050000
- 4A6C49444154785EEDBD69705CC795A89979EFADBD5028EC0417102401901037
- 71114951A2244BA216DBA224B764BBDD1D6DBB9F67625EC44C77CCC49B989F8E
- FE39332F5EC4EB9988F7625E77DBEE68B9F52CB5B5D9962C4AB2245214497111
- 3781044002044882D80B05D47EEFCD39A7942C11BC5900AAEE2DA000E4C7A860
- 9D045095F7E4C993FB4922914824128944229148241289442291482412894422
- 9148241289442291482412894422914824128944229148241289442291482412
- 8944229148241289442291482412894422914824128944229148241289442291
- 4824128944229148241289442291482412894422914824128944229148241289
- 4400E5FF4B962A8CD19718F3C23B9F41886612E23128A52A218ACA980B7F05E4
- 0CFCCC04992984A4E0673A24275EA734492865F83B92A58974008B9C4719D342
- 8CD5404186A1E286A08287A0C686E047155099FDF01E2B7FD1C0E726E133E3F0
- 7612DE47E133A3E02CA2F0B99128A5A39F508ACE42B248910E6011F13263EE34
- 212BA1A16E80CA5E0B95B01692C3F0FF8294237C297C3589C0FF23E01446A063
- 31E826E4D66B944236258B01E900CA981F43D77D82B12668815741855F89157E
- A12AFB5C41A7C01DC22DE82DDCACA4B4EF573894909425D2019419CF99660314
- 4A337FAD28F70A3F1B907906CF701B5EBDF87A475106F98F2465C0A236AEA502
- 567A682DDBA0305AA192E0F87DC902CF88F3075DD0ABE994CE60E1910E608138
- 649A3849B705DEB63B55E9E17332194252669CA4F408496762246D4C115D9F84
- D7444CD71353BA393566E01CBF6EEACC8C46A0A74E88120AAB9AA251A2C1FB60
- B5AAF9829A5619D0B40AA2A941A2B902C4AD85895BF1138F8B100F184D76F5C0
- 2EE80CE0BF0E700617DF5694C9AF5325F3897400F3C8CF1953CE30B65EA1740B
- 656C2D54D8A2F40F7F67EA2689A5C7483C350CAF1BA9C4E4D5CEC49D0A5D6AD0
- 61546C68F379567B7C9E3AE2775713BFA690003C0CF8B4C281BF638CD2EB2663
- 1777527AEDEF28059F20990FA40398075E324D1F34BA5BE1ED76A8BC81AF53E7
- 0ED4065D8F9368F226998AF6A42627BF3A1BA7E90C7C54F9C0DC2E5A71DF0E7F
- 689DA7C2BB8A04353F098137803E45618041C6E0BF73F087175E5794C4D7A992
- 52211D400979C634436E42764145D80CB5B5A0CA9026642AD54F27263A9291C9
- F350E1CDF2AAF0B3C1147008DB76F82BDBBD61CF1A56097A08F21FCD09304CE8
- E4904BA087D3EF290A0E152425403A80128015DF47C85E78DB0E463CE76E71C6
- 24935357C9D8C4B1EBE3C9C1BE25B596EE6A5CE3AADED75C1DDC40AA5D0AA9E0
- C9B302CAC3E1400774054E4847E03CD20138C841D30C40C5DF034AC5C93DF5EB
- D49981417B72AA870C8F1FBB3E9ABCB9B42A7D3EBCAB9ADC55FBD7D604D7913A
- 50D25C772A1AE00C2E4D812338AC28384C90388074000E80DB71AB18DB09CA7C
- 009AAB5967C871122F3549C627CE40C53FF139B46ACB7537AD46AAF63E18AADC
- 49EA3C15A40AF4376B6F097E01C7425F8C537A466E43B68F74003679C134DBC0
- 200FC0DB59BBB5389937D54F86863FE81ECC0C0F6478B20470D535BAEA9E6C69
- 08AE21F550C9E7325F8267138EBCA9289D5C961481740045F23C6361C2D813F0
- 76CDD729F9818A9F1AEFA003A31F9E1E35E3B17959AA5BAC28FE805AF3C4AE9A
- AA76D6088EC0C39367A25FA7F4A3DF533ACE65490148075020B8967F9EB15DD0
- EAEF85D78C2D15D4F474A483DE1A3B7C7AC448C670324B324798DB4FEB9FDE5D
- 176E672B5542DC3C590818B10EAF13DB283D2DF7101486740005F09269D641A5
- 7E0A2CAC8E2709819FEB135DE4D6C8BB678664C5B787EA0D28B5CFEEACAF6C25
- 2B671B1AC0CF87C159BCFFBAA20CF324C92C4807301718A32F10B29331B61FA4
- BCB3FBA04C161D2483C36F75DC4A4746E4049583B8C3B55ADDF3ED2B430DA401
- 7A5E33D92DC63B39F6262167643093D9910E60165E662C9866EC69783BE3583F
- 9D2113836F0E5E8FF574CAA3AF2524B0AECDDB70A861ADDB432A79523EFADD94
- FEF1354AA7B82C11201DC00C3CCF583365EC196846F2AE55C3CF32A36749DFC8
- E123A33C49320FD41E3C5053B383348101E75D76859F2519A5EFBD45692F4F92
- DC8374007978C134F7C07F0FCED4DD8C4F9291DBAF75F4A54764777F2170D7D6
- 6A2B5E6E6FF2576423230981C2C361C0E76F2ACAC9AF532477231DC03D3C639A
- 1E37214F8362D6F3240BD8EA8F1C233DA3478F4478926401A979F840B8763F59
- 076596B7370065762D4DC81FDF5394144F9200D201DC053FBCF30228A59A2759
- 48A7C844FFAFBBAF95FB461EC5ED515D8D75956AB8AA8A7A3C3EC5EBF2134DF3
- 2B1AF3514A14A610FCF7F5F29A49D2D4242663C434759AC0B38766321367A954
- C2888C8F67068627CC74AAACF72FE046A2553F6A5DE7F5B0304FB2004E600C9C
- C09BF24CC1374807C07999B11519C69E0323111ED70545B1B12ED237F8C6E783
- E5B475375BD19B9BEAB4AAAA06ADC253AF78593D75931AA23A1C59C820519626
- A366920EE993A9217D7C7C30D3DB375C5E8E41230D2F3ED8106ECDCE0D086D9B
- 521A876EC2DBAF517A9B272D6BA403009E33CD16153A0050F985EBCCB8A167E8
- B0D13D71F6D882CF286385F7B4AD5FADD5D7366B7EB69AF8C82A28C41937CA94
- 0AD0579A24C84D3D4E6FE84323BDA9CE6B37CAC12154EED81FAC3FA862990AF5
- 02FAD22193EFBDA328DD3C69D9B2EC1DC021D3BC4F21E42018B350177844B7EF
- 95DEEECC40FF8275F99570D8E7DBD8D6E6AA71B742FF64DD1CB7C8CE3B262129
- 12233D99D17457E24A67A719892C58400F1C1234FDB8A525DFD163286C8C5EFC
- E11B8A7291272D4B96B50378D134B783D17E8B8B16121132DCFBCBE3BD0B117D
- 87FA7CAEC0B6CDEDAE3A6F3BF393F50A9BDBF1E272C1A4C4A071722D339CEC88
- 9DBFD4C112897977A018A5A8F927FB9A7DE1FC3B37614870E44D4A4F7371D9B1
- 6C1D00B4FCBBE1E11FE6A285893ED23FF0EA91012ECE1B9EB6D615DEB50DF7D3
- 30D9EA644B6F1A2445E1C50C92668C18CC8406DB205F574A95B8A842144A894A
- 55E2662AF128F0CAFECC01B067C026C8C564EFE0D95467D7BC8FBD1B7F78A0B1
- B229FF462ED0F367D013F8828BCB8A65E90066AAFCD0D49BA36749CF7C6EECC1
- F059C1EDEDADAE35A17D8A8734F1E4823175658A25CC8811D3237A7C326AC626
- 63466432A64F15D715D782619F1AAE0828818A80E6AF08A9012D4C7D4A58D1CC
- 82C27BDD8D99227D99FEE8F1A9731D5DF319E6ACEEC903D5D53BC97A2877A8EF
- 56202347DF5694535C5C362C3B073053B71F2BFFE0A7A42B72FCC8044F2A2938
- A1E7DBB17D8B7BA57B3FD5480D4F9E133080652C4E46F5A83EA88F8E8C24076F
- 0EB364725EBAD9D4EB75791B56D56935B5B55A486BA07E52435961B6C474329A
- BE953E96387BEEE27C4D1C86F71DA86C7884B4E6730290F827E8099CE3E2B260
- 593980E74C733314F2412EDE8B71EB03A3337AE658C9E3D3675BFCDDDB377BD6
- 781F01ABCBBBE7C0824192FA38B9991A19BA95BAD13FC832F353E16783BABC2E
- CFEA350D9EDAFA954A15595DD0F0C12463A9FEE4A753A7CE5D9A8F1E4168E7FE
- 8A954FAA6DF05638A7028DC3E17714E51217973CCBC6017C8FB1F5E6D7EBFC96
- 678642D76FBD1BBB3275E14CC963CDF9B6B4AFF5B6D43C455DA48127CD0C2319
- A8F4FDA98181DE447FDF1065FABC759B8B81518DFAD634D57B1A1B9BB52A1877
- D3B95D22C2326430D93DFA7EE262C7759E5432825B7706563E1BD8088D8165D9
- 178C832994BEF35B4AAFF1A425CDB270007C93CF4B507344EBFCC68D775397A7
- 2E9C2C69E577AF6EA8F46F6B3DA804C8269E34234602BAC8B727BA125D5D7DCC
- 28EF5D78F9A09A4BF3B56C5CE35E51D9AAFAE636C4D113A43371AEE7FD4CFFCD
- 926EB30E6EDD1358FDAC07CBC2D213804AA1BB287D7D396C165AF20E8087EEFA
- 01BCF57D9DF20D38E61FF8C0B852CA6E3F76F7430FEF7E406B501F0365CFBA61
- 479F207DC99EBECBA981FE2575BAD0D3B8A6C6BBAE69935639FB2427944B5A1F
- 343E8E1E3DF545298705381C687C52DD08E5229A1348B8297D159CC0BCCC072D
- 144BDA01E0C11E188C7E1FDE5A5A1F787076FB137265FCC49192ED0B77AF6DAE
- F3DFBFFA39C54D56F2242138A1678C929EA9CECB978CF1D1257D7E5DADAA0906
- DB366D566BC8BAD9260ECD34B915FFF2C63BE9EBBD258BF053B5F74068C5A364
- 2378194B5E20612449C86B4BF900D1927600874CF3103CA0F054DFF059726DF4
- F091112E3A4EF0E13DBBDC2BDD07A1399B318C15B6F8B1CB572EE86323CBEA80
- 8A0B1C81BF7DD3F6597B0494E8E95BE9C353474F966CB34ECDC103B5753BC476
- 028EE1DADB8AF23617971C4BD601E0797E283C0CE165A1949B7C70DB6EE5C35B
- 0E511F69E54942708C9FB8D2777AA975F50B058706BE8D4DBB669B236009D235
- 71F4E2DBA5DA5E3CD36621A824C7966A3C8125E90078249FE745DDBAA9513274
- E31F8F9424428CA76DFD0AFF96952F53357FB82A939154AA77E26CFCF2C51E9E
- 2401FC6DF7ADF3ACAFDAA1D0FC4B88CC2013F18BB75E4B755E2BC9E4DCEA7F77
- A0395843EAB998038C086F2F7E6B2946165A720E0063F86518FB4BA8FC96305E
- 78B0A7FBEF4F5FA6E938FCD859827B776F73AFF57E7BA62E3F76F727CF9D3F6D
- C62665DC40014AA0C25BB17DDBAE1987053824B89EFCC3D48953E7798A636028
- F296BFD9B5497480082A4AD245E9BF2CB518834BCE013C6F9A7F06FF59BA7278
- A4B7F717DD979C0EE4919DE57F6CDFA3AE1A96F75C0163249DE81EFD22D17DB9
- 8F274966C0D7B2A9C9D752F300A5F9574DF431FAD9C49F8E7FECF42A019E226C
- FE69CBE63C4789FBDF52947FE3EF97044BCA01BC8017763086D7744D03BB7037
- 3F302E3BBDDC875B79434F3EF09C12C85E062AC48893C1A9B3973ED7A30B7734
- 7631A285C2BEE08ECD0FAAFEFC1BA6CC18B918FDE08B779CDE4A8CCB83AB9E54
- 378986904BEDF4E092710078690734ED3F84B7968D1DE35DE4FAE01B4706B9E8
- 08785C37FCC4AEEF531F59C7932CA407F54BD1B3A72F94FBEEBD720577158676
- ECDAEA6ED036F3240B2C417A221F9EFE8DD3C78D1B5E3CB0A2AA553814315C84
- BCBA542E1F111E8A586CC0B85FD509C1D8FD96CA9F4CD1C8D761BC9C43AB0879
- 2A0FEEFAF3BC959F113D7679E8C8E49913E765E52F1ED41DEA1075893AE5C9D3
- C032C0B2C032E1498E0036731BE33F72F16EB2B68636C7E545CD92700029C676
- 432DB3848686B4CCCD5F77F5C08891A7D8070D2DF8F8B6BFC87B6CD72089C9D3
- D7DE4FF674DDE029129BA02E51A7A85B9E340D2C0B2C13679D804E30F82BDA10
- 4FC881B6A633F6001717358B7E08F01DC6AA34C6FE12DE5A3CF2F031D2E964E8
- 6EECF6636B93AFF21B29323675F2D2A7C59EBF77124A5CAA6B457DA356155EA9
- F8FCB58AC75D43351686570555981F7F254D5976A2CBCD681AFE63CCA471A6D3
- 497845CC547AD44CC447F4F1C8ADCCEDA10146320B7E1E01E31304F76C7E44F5
- 884F5062AC8189C3A7FFD5C9E100861CAFDB4FF0F4E0BDE050E015180A8C7179
- 51B2E81DC021D37C091E62351773E0A51D7DFFE5886327BA70C2AFF2E9077E40
- BDE21D6366828C448E9FFE78BECEE4DF8B1A0804DCAB9B37B94295AD4A806DA0
- 9ECCEA64427CE4B550BC3E621869579F31C5AE98636397D3FDBDDD463A8D4E63
- DEC15804E17DBB1E537CE2CB40704E60E2FD2F5E757262B0E9DF1F582FBA7C04
- 7A0237DE5694D7B9B82859D40EE07BA6D90AA5FC1D2EE6C06E5BCF3F755C70EA
- C61E5CEAAB7A66EFF3F966FBF549723BFAF9A94FE7FBD49E5A5553ED6B6ADEAD
- 557A7628EEF4BA447A7E867450F9325AD2DD6B4452E7127DBDA78CF1D1796D05
- A9EA51430FEE7E44AB202B78D234707560FCBD136F39B544883710ADFBEBF6AD
- 50592C479BC1C3FEFEB78AD2C5C545C7A275008F32A65531F65750C296F8F7A3
- 6748F7F007471C33CAD013071ED7AAB337035BF8BAF29F84CA3F3F5D640CBEE1
- 6BD9B0D3555FF988EA4A6F98AF4A9F0F9F9B9846C67D353334F169A2FBEA99F9
- 0A52822B04E187F63E96CF09E863F458F4C3231F71D1361852AC662769E1620E
- A840D1714AFFF9134A9D9B689A4716AD0380AEFF5EC8FC835CCC81B3FEBDFFF9
- D34E2EDA26B067F716CF5AEF0B5C9C46B6DB7FE4D447F3D1F26BA1CA90AFB5ED
- 51AD9A7E2B992A3E265F29F17A94297D4C3992E8EAF8508F4E94FC7013F604C2
- 07763F9E6F3890EE4BBEEDE48EC1E6BF7DA44D74F310D8E1A23D2BB0281DC041
- D30C400DF889794F970C1E86F5BD317A21D6F595235B6D31426FE0FE869FC098
- C2B2BD97A5C9C4F867A70F977ACCAF064341FFA6FB9ED57CFAA3C91976C6CD84
- 9791B4696813990C8D28462269E8668299D088EABA4E554A99AA6A4455DD54D5
- DC54D3DC9AC6420AD5C376BE4F4F689F243A3BFE586A47807302550FED3A48DD
- 82F31794E8B12F077FE95424E240EB7DDEA6176BB642AF735ABD812E58668A90
- 5F1E5694924794729A45E9009E67EC31C2D8FD5CCC3139486EDFFCD51147B6DB
- 664FF53DBEE567C2833D06494C1CBF04C65DBAD97EECEA07B66E3DE80A799F4D
- 9A89392F6F795D34694C6A037A2C3A90999C18CD4C44C6592C569461D24020E0
- AA0C57B92A2A6BB440A851ADD01B931996F7AAF47BF12ABE54269A7C3776E1C2
- E1520E0D70D760E5BECD4FC380DC1AF4C52013131F5DFC07A74E11AEFAF181A6
- 8A06C1B083D22FDFA2F4632E2D1A169D03C0C33E69C67E0A6FA7CD70635CBFDE
- FFAFE37C3AE2CCC45FD5771FFE81F0482F2399C9D3D70EA787074A1629C6DBD2
- B6D5B5BAFA47BAA9CF298C9647552399F1F8D5F4D0506F7A6878043209EA2805
- 5471D7D7D5BAEBEB9B5D55FE0D29C3C87B11E7DDB8DDDA58AA77EC956477E705
- 9EE438EEBAC6CA8A5DEB0F82455B26EAF028F1D81F4EFCC689494177B8566BFE
- 1FDBB741AB7F6FAFD0800FFFE5DB8A52F2A0B24EB2E81CC0F3A6F904FCB7F56B
- E91B9CDCEE9B0DE6D1E87E968BD388758E1C495EBD52924D3ED9EEFEB62D3FD4
- B5F41E9E9417EC66A712B43B7DA3EFABCCC8D0826C4B75D5D6D7B95737DDE7F1
- B196B90C1734DD7D327EFEE2ABC654B42427EABCEB5A570736D55BCE8220E981
- F4BB4E05156978F14043552B59CBC5BBB9F096A27CC8DF2F0A16950338649A15
- D0ECFF149AB76933DF0694EFB5BF3F73DE48C66CB77CEEA6E6DAE0BED53F138D
- FB716F3F6E4DE5A2A3F8D6B7B47BD7D7FC249936AA7892102F51A65223B10B89
- DEEEAFCC055A8BBF17C5ED76FB9A5BEEF3D406B626C9CC13945EB71A49F68CFF
- 3271B5F32B9EE428153BF76E139E1DA0449F3A7EE31FD27DBDB6A340A9DE80B2
- FE6F766E035B9CE6F4C0284DB0C55F2CA65EC0822E21150AA574D7BD951F8974
- D05B4E547EA6B915FF8ED58744951F4FF5E1C11E2E3A062E6755EC7AE039DFFA
- F0DFCE54F915378DB3E1A923E3C7CFFC3AD6F9D597E552F911CC0BE609F34686
- E29F615EF98F2CC033867DEB427F83CF8CCFCE931D03CB08CB8A8BDF00658A65
- 8B65CC538A066D0D6D8E8B39D036D146B9B82858340E00037C2A8C593C3B283D
- 35F4C7538E748143FB77ED1605F0C47BF5A64E5D3CE6F4C11EC5EDF7861FDEF3
- 3FEB01F65CBEF57CDC8547278D73B1CFCEFF3AD175E522338D79DD6C540898B7
- 7877C779CC2B9934BEC4BCF31F4D039F159F199F1D75C0931D01CB08CB0ACB8C
- 27E5C0B2C532E6A22DD0E6D0F6B898036D146D958B65CFA27100D0D7DA0A0AB7
- 4CF04C7491DB4E44F8C1B8FD18BA9B8BD3485C1D39A9C7261C8DE2A3866BAA02
- FBB6FFEF699AB6CC67DC4163AEDBD1D33DAFC52E7C798C65D20BB2C5B81830AF
- F10B5F7E8E79C767E0C916F0D95107A80B9EE408585658665C9C0696B16BCDAA
- 394D5ECE04DADC7807B5C495441B455BE562D9B3281CC0CF195320A33BB89803
- 94AD8F1C3EE348EBEFDBDEFA24F4472D1359D938FD0E4FFAB9EA1A1A82BB5BFF
- 0F9D64844128B3ADFE48E2F3E8E727DED22363E33C79D18179C767C067C9D71B
- 401DA02E50273CC911B0CCB0ECB89803CBD8BF6D1D4E24DB66EC4FA747D006B9
- 98036D75B11C175E140EE00C63EBA1890F7031C7D42D32644CD91FFBE3755DAA
- 9FB473310706F0C4187E5C740477C3CA95EEEDCDFF219DD68527DA5CAA1A9D3C
- D7FF068EA9B153CD931731CCC467C167C267E389D3405DA04E50373CC911B2F1
- 170543012C6B2C732E160DDA1EDA201773A0AD6618DBC0C5B2665138008552CB
- 211C50B239FCC76EDBCB7E78D007EFEAE3E234307AAF93013CB5DA867AD7D635
- FFAB99368451835DA6EBC6D4C973FFB650CB7AA5049F099F0D9F91274D037582
- BA411DF124DB60D9A57AC7CF72711A58E658F65C2C1AB441B4452EE680B44531
- 0C287B07F08C69862863166F9D9A24E34E04F8C45B7A45177562DC7E27437767
- C7FCF7AFFBDFF2557E35462F474F1EFF83914A2DD988C1F86CF88CF8AC3C691A
- A81BD491937302F1CEAF7AB02CB99803CB1CCB9E8B45833688B6C8C5BB5903C3
- 80BCE1E1CB85B277005E42368337B578EA8933C4762B8967FCB357740BC04B3B
- F85BDB28BE802FB8A3ED7FC9D7ED275103BAC8A7FE041DFEB29DE1770A7C467C
- 567C669E340DD411EA0A75C6936C93AF2CB1ECD106B85834F96C312D58B52A37
- CADE0140DFCA729B2ED492E4F889CF6D1F32F1EDD8BE053460A9949908E975EA
- C61E46290DECDAFE3FA48D8C2568499648FA64FCE2979F7369D9907D6678762E
- 4E0375853A43DDF1245B6059629972F11BA0ECB3366013B445B4492EE680866B
- 237F5BB694B50378CE341BC0022CDDA8A91EF4B8F6B6FCE3F8CFB3DAFD101773
- E0459D89CB971DDBF013DAB9FBBBBA92161A993A619C897F7561C984982E147C
- 76D40117A7813A43DD71D13658A658B65CCC8136607F2E40E736391DB45DB461
- 2E962565ED002073A2586C64FCD875DBAD7360D7E63651EB8FB7F4661CBAA1D7
- B7A1ED3E5715B3442C4268827E3579E9CB135C5CB6A00E50175C9C06EA0EB748
- 73D11658A658B65CFC06B081AC2DD8249F4DE6B3E172A1AC1D007850CB693CBC
- DE2B79B3CFF636587763702F7F9B035B88A9AF2E5DE4A22DF0608FB2AEEAA7A2
- 1D7E6ED375237EEEEC512ECE2B5473A9AEBA15214FD3DA1A7F6B5B23BEF03DA6
- E1CFF8AFCD2BA80BD4091773A0EEBCEB6B7E8ABAE449B6C0B215F50244B65028
- 6893689B5CBC9BB276008E8CB14AC1CB8CAD483386177D4CC389537F78896760
- FBCA9F7131076E1C9938F6D9675CB445C5FEFD3F139DEAC3B5F0A953E7FECD48
- CCC36CBF4AA96F5D6BBDA7A9A6C9DBC01A55B75EC3180BA93E9FD0F11B898409
- C3EEA891D64693837420D537DA97E8E91A2206B3541AA7513D1E6F70CFF63FCB
- 188625C41B9E229C3C76EC1FB8688BCAFD0F3D24BA7B3076EED63FD8BD7434DF
- 294137A5AFBE4669492E34B54BD9EE566AFBF9CF711DD5327176EB0FBD3DE654
- D4D60699E0AECD0714AF75CF7FFC72DF09632A6A3B70049EE76795DAF7B89803
- 77C3C52EF6FD5E8F464B1A25C7D7D2D6103AD0B6A7E681FAA7036DE19D9E1AA5
- 49F528D554D3BC8A2BFF78177F86BF83BF8B7FE35F1FD81A6AAFDBAE35375710
- C39FD0C7464B16F18619866EC633B703AB2B37EAFAF45E93A918AB3457B017BE
- DFB2E9A660741277AFA8B46CD2517D152C75B5AF9B8B45919E60E9EAEDE1462E
- E600638D5DFEBBBF2BCB7B22CA7608004D8EE5D61D1D149919E8B7B5F68FB1FD
- 69A535BA2FC6F77362E61F23F960300F2E4E2371337DAA949B7C423BF7B436FC
- 74CF8F6A9FA8FF5160857A3F3CABEDA534FC0CFC2CFC4CFC6CFC0EFE23C741DD
- A08EB8380DD429EA968B4583658C65CDC51C6813681B5C2C0AB44DB4512EE610
- D972B950960EE025D3F4413355C7C51C897E6AFB928FC0B6CDEDF0D096D35AC9
- 817147028906B76C7D4A14C9C76D6A4389CB17856BDF7609B46F5EBDF2A77BFE
- A2F201F777DD6E77C9669DF1B3F13BF0BBE03B57F16447411DA1AEB89803758A
- BAE5A22D9237AD658D3681B6C1C5A211D928DA32DA3417CB8AB2740069429AC0
- 6B5ABAAA539793B6C370B9EABCD642662493ECB67F951746EED52ABDCF703187
- D74DCC5877CFA7F0458EEEEDC716ABFEC5070F563F52F5B2EA763BB6857636F0
- BBE03BBF8FDF6DB7D5B4C2B2BA429DF1841CA85BD431178B2679ADEB065ED9CE
- C51C5ABDD7F6C61D918DA22DA34D73B1AC28D72180F54C3E34029173676D8D41
- 31D027F35B6FF6D1C749BF1371FD7D6DED4F8B027866C688E361BBBCCDEBEA1A
- BFBFF9479E7A754E1B59D25142A25708193D3E4606DFEF21B7DEBE486EFEDBD9
- EC0BDF631AFE0C7F077F772EE077631E302F3CC9115057A8332EE640DDA28EB9
- 583458D64684F473F11B7CA4196D844B4581360A155E344C75F4A0935394A503
- 5005CAD2E3246A37A8A36F635B9BC2AC139FC98181EBFC6DD1645B7F9FFE2817
- 7360749CD8954B8EC68C0F3EB06763DD23D53F54BD5EF1D6624E72142AFC49B0
- F4FF7E92DC7EEB28899C3C4A625D5F91D4E04DA24F4488118F655FF81ED3F067
- F83BF8BB37E06FF06FF1336602F38079C13CF12447409D89220BA18EB550D8F6
- 1EFBD42D6B99A36D04DADB2C3B4F0B016D3419B72E078A6CBA1C283B0780D154
- A0965B2E7A48DE24B637E7B86ADC96092C3C2E9AECEFB37DAAD0DBD2F6982830
- 26BB153F67A6929623A9C552F9D8FEFBAB76BABF4D7C3E4BD8B23BC46F1132F0
- FB2B64E80F50E1AF5C24AC88E86126FC0DFE2D7E067E167E665E202F9827CC1B
- 4FB10DEACCBC11B39CE4431D7B5B5A2D8EB65012FD7D43C4B06EDF55ABDCB68F
- F126FBAC0E006DBA1C2305959D03F013B202C74C5CCC11ED4ED90AB4983DF411
- B0CEC69A5172C36EA8AFECCC7F0DB54413C218FDF19EEE4B5CB44DF8B1FD3B42
- 1B956F71D1421A5CE4ED77BBC8C8874761D8E1DC88033F0B3F133F1BBF231F98
- 37CC23176D93B8D6790983A0723107EADAEE8A0096B91E2537B9F80D6023760F
- 08C5AFC5440E80A26D73B16C283B07A00B9404CA3327AF9CCD1B68722E78DAD6
- AF8687B578E0D4E0D04C6DDB9CC0BBFA44D775256FA7CE3B15CAAB62EFFE4D15
- 1B1561C83204C7EEB7DFFA8CA4471C898C2E043F1BBF03BF2B1F9847CC2B176D
- 8131063102321773A0AE51E75C2C1A51D9A38DA0AD70B128A29D17702F89654E
- 4964DB0B4DD9390070BD96EEBF6E92184DDB1BFF6BF5B5CDFC6D0EDC169ABAD1
- 6FBBC6E0459DFC6D0E8CDB9FECED72645BB16FDD8686F0C6D4412E4E039532FC
- C9ADECD81D4318951CF80EFC2EFCCE7CDF8679C53C73D11689EBD73A50975CCC
- 21D279A160D98BB6068B6CA510D0563326B1345822DB5E68CACE014069589494
- 1EB32AB350B420B3C4DF6371326AF7CA2ABCA21B6FE9E5628E4C82763931F657
- BC0177C581C6EF88C6FCB84E36F8FE5592E8BBF675C23C82DF89DF2D5CD784BC
- 629E31EF3CA5685087A84B2EE6409DA3EEB9581458F668035CCC21B2954211D9
- ACC8B6179AB2720078E537FC6789D89A1AB6E700B2633A8F606521AADB6EFD7D
- 6B9B77890EFC246FF475F0B7B6A87976DB231E9FF54834365B4338261FB404A6
- 9D37F0BB310FA29E00E6B916F2CE455B8874893AF73535DB0EF12DB401B015BB
- F707E4B1D930B7F1B2A1AC1C403563D5604C9609C0D4F594ADFDF9AE754DF5F0
- A1D688BFA323F66F89A9F45866BEB377F539B0EE8F27F5BC15E25802239FDC2C
- E9787FAE601E86FF649D4B433C90777C062E160DEAD24DB4312EE650C39EEDFC
- 6DD1886C006DC5BB61ADAD218CC866D1B6438CCDE9BEC7F9A2AC1C8041883016
- DC6477A72D07A085AB84BBE49283376D555235100808BBFFE3F1ABFCAD2DC20F
- 871F87EEB47545E43276C11D0B57689BE48D9E6C9E2C40DEB3CFE0007A346679
- E0EC3000CA808B4591CF06F2D9CC5CC967B35098B6EF247092B272002A21966D
- 9EE03533663C626B979E56E1B11426D349CCEEDDFEEED5CD9B44DD7FBCA597BF
- 2D9A8A1DBBD68BB6F7666284444E3B7262D951304F98B77BC167C067E162D188
- 748ABA77AF69B6B57F1F6DC0D4AD4B8D229B2904B459305A8B7D896C7C2129AF
- 1E00A596B12E68D0FE449A9F59BA73664218C9B5205CA14ACBC6225CFBFFFA8A
- 6E7B78B7ABC22015A39F41E7623E66FB0B05F294CD9B807CCF5208A853D42D17
- 73B82A2A5BF8DBA26109D3728047643385020EC062BB221B5F48CACA01288C59
- BCA33969DF01504D10FA2BA6DB3E59A804AC973F1893DA009894AD433F789EDF
- EB715BD68C7137DE424EFACD06E62D66DD614FF059F099B85824CCFC5AB7D311
- 9541A1886C4164338522B25D918D2F2465E50018A516E5E893D635E042C8AE00
- A8D66E971E9FB415948312974A3DD648BF9968D4FEC6A2CD35F7F1B7D398383B
- C30E9C32217A4EBCF891EF990A418F452D0E00CB00CB828B4521B405B019BB3B
- 02F3D86E05FFBF2C282B074019B3DC140BE34A5B0E405BD1289C583463315B27
- 0B5D2BEA57241338A49B8E3119B137FBAF52EAAF4C5B0ED6A4C640170E6EEF2D
- 1599F151E101A2EC33C1B371B128F4A855B758065016B6561ACCD8A4D016F2D9
- CE5CC963BB651517A07C1C00631446B6160700DD285B13755A558570CC654427
- 6C3900AD2A2C0C8891898C5996AB0A21D0B271A52892CF54E7E2B92334D66555
- 4136B2103C1B178B221D9D10C68380B2B0F5B946248F03C8633B734564BB591B
- 075BE7E28253360EE0BB793C6366CABAA7BA1014AF47B84C04AD89ADA545C5E7
- B7ECEAF2BA9498DDDD7FEEB555C27DE889EB96CD70654BFCBA38B45EBE679B2B
- 0C7A6DA26DC1A2B228047D2A92106D09CE673B73259FEDBE24E8E92E1465E300
- BC7994A2C762B66E00A11E97B55721B831B650A8CB6D098291498B6FBF2D044F
- 2DB34CFEA5A1DDC3E3B98B053C7E9C12B4D56A2DB3BD29C8649A75C6DEE3B6BD
- B986E982EEBAC763ABBB3E83ED96CD30A06C1C00B84AE159697D3C62CB01104D
- F3F37739A8030E40710B562C92F66316A85AC6B2FE9C5CF80D7F059312E4D9A3
- 656C470ECAA4A8C5B5508DD9DE5C23B209AA29F61C401EDBCD67EB0B41393900
- E1B8C848256C2DA929AAB567C10C7B138B08D398E5F8AF62246CC5FAA76E97AA
- F87C96CFCD446CAF58CE3BA23CE3B3E13372B128443A169545A1886C42D1982D
- 0790CF76F3D9FA4250360E40234418E081A632B61C00A8DAA26C53C7A3D9F650
- 1566191F1ABA696FCB72558DD090F5C8E29900BC43BE3CBBC275B696C18C9455
- C7A2B22814276CE25EF2D96E3E5B5F08CAC60164F2E4C56EB950CDDADD62547C
- 8AB5104C8AE5381D660A0FC6CD19AD22249C0731D3B6FCCA82902FCF5A45D0D6
- 049868B24E54168522B20991ED14423EDBCD67EB0B41D9640410760DCDA8BD73
- 00221466DF0128845974C732695B730B8AAA080D79314D00DE215F9E615C6D6B
- 08400CEB074359D8EE523B6113F792CF764101D20148ACD8ED412C06EC3EA3A2
- A8F61C88641AE5E40084DE5209851D2F70E832DA7E6E93506B97D1E5B6D56534
- 532961B3A9B86D07D69977F2E539DF33CE1546544B2F09CAC2B6E374C226EE25
- 9FED82A13BDEDB2896B27100AE3C4AD16C0EEF982E58DE61F69F1BBA8C96011E
- 55ECCDEE1AF1987008A1B8CB66D978CEE4CBB39188D97200D4AD5A9CACA82C0A
- 45641322DB29847CB69BCFD61782B271005082C22DBFCCE3B2974766ED72C248
- DBF6A4916152CBF651D5EEBA71745C18FA4C0BDBDA92BE20E4CBB33E316E6B0B
- B6A26A96B2139545A1386113F792CF76F3D9FA4250360E201FAA477C97FD5C31
- 0DEB1972AA5AC383150AD5A965D38FA9FAECCD70A73386994858E3E087CB2A88
- CC9C70555AF38CCF86CFC8C5E2D0348B8E45655128229B30756A6BF9259FEDC2
- B8A06CE67ACAC60180F6859B68B4AAB03DCFACEBD6E8AC1822D426669A5AB6FD
- 2A5E627B434A4A77594EBC796C87A6987F3C8208F819C3653F06A3C62CFB0844
- 655128229B60B6F775886D171C80ADA18593948D0348526B4B8D6881802D07C0
- 5219CBE72A0E380096495B2AAACB6DD80EF6A0DFA696089B9E4A68A116D14420
- E615F37C2FE9016AFB066685EA96AE85A82C0A856A825E61CA66305A7F20DF04
- 76D96CEC281B07F0BB3C4A7105C5FB03E68A994C898F7A06EDDD026B26E296D6
- 2C9931038AC76BCBB9A4AF8F0A62EA10E25F6B3BF2D5BC912FAFF99E6DAED040
- 2020BA7F5154168580B6409960C7681EDB992B5A85785EE1F53C8DDD4250360E
- 80508ABB39ACAD7585BD6D93FAF8A4F00CB91AAEB4B57D541F8F0823FFB8C295
- B64249C57BBB0659226171868156DB11AAE60D515EF199F0D9B85814EE50A538
- B64324622B4E9A1AAE101F19CF633B734564BB591B075BE7E282533E0E006002
- CFE80AD89BB0D36F0F0837A52B36C349676E0F0D787DD6BD0B6A458DBD136F06
- 63F109B725F697B7067451EDE835FC25C1555593CDEBBD649F099E8D8B45A185
- C216056019A407ECDDEFA804F238803CB63357F2D86ED974FF91B272009431CB
- 640E74A36C3900339D32A09A5A3FD75F616BBCCE48C6602997654CAB55866C9F
- 794F5C1AFD8ABF9D46E5FD8E5EC15F1242DBC551BA9317476DDF94A405ACBAC5
- 32C0B2E06251086DC154A6B2B663833CB66BEB966BA7292B076052C1CC7A8503
- 13763AB1DE2A13D06CAFAD99316A8983AD05F595E0CA6CE935D1DD39984CA56F
- 7331877F1574831B6CFB979281790B086ED54BA7D283F1AB9D96E7290CAAA815
- BAE5E145655028225B6019D3F68A85C8764536BE909495035019B38CB9601065
- DB0198716A197B2A3EF12D448590999CB0C4BE4A6698D75D5F67FB12C8E439E3
- 047F3B8DEAFD1B20F3B6CFBE380FE4A9E6217184EE789E672904D429EA968B39
- 44655028D4A7581C80C8660A4515D8AE22E8E52E2465E500A0BF65510E98BA4B
- F1DB3B0FA04FA686F8DB1C542301EAF5DA9A604CF7F776F8DCD66D9DEEFA7A5B
- D74B2393674F5F33D2694BBEDD4142C2BB1EE252F980798231AF057C067816DB
- ADB448A7A87B2C032E1605DA80A29996FD1B229B2904B459305A8B7D81B1D89A
- 58749AB272008C1061E89B8A96367B5B6C23E3C2C2F436ACB235AB66C4623123
- E3B60E03428175FCAD2D2247231FF1B7D3086D02E35FE3C857388277F5BA6C9E
- 44448E4685CF5028229D9A19F7352C032E16453E1BC8673373259FCDE6B3F185
- A2AC1C4094D25168F12D33C59EB5F68233667AFA86E0432D8750B49A5ADB5D75
- 23923AC7DFE64813BDDA555B6F7BCA3EDED539901A322E70711AB58FAD22EEDA
- 85DF228879A8FB9630423AC1BCC7BB2EDBBECA0875893AE5620E3D92FA92BF2D
- 1A910DA0ADA0CD70B12844368BB68D36CEC5B2A0AC1CC02794E2A92E8B87F4D4
- 114B60CF42C8CEE6A68865A9480B69B66B50A2AFF7946818E05DDD64EBD2CA3B
- 8CBC7BFE53239E100D8D48FDB3AD0B3A2988DF8D7910CD48609E31EF5CB48548
- 97A873D43D178B466803602B765700F2D86C84DB78D950560E000163B2CCBEBA
- ABED3900449FA2965D68D44F6AA8CBDE3C80313E3A261A06B87CACD5EEAE40C4
- 4CC6D2E34723BF238984C570B0F01A9EDA407C4DB62FDF2D18FC4EFC6EA10141
- 5E31CF98779E52348ADBED465D723107EA1C75CFC5A2C0B2471BE0620E91AD14
- 8AC86645B6BDD0949D0300B76B5192A6900073BB440DCD9CD187462CD74BE3F6
- 4FCFEA35B67B01FAE0E411FE36076E59F536B76EE1A22D123D570723573C87B9
- 380D544ADDA32B49F88187A1346DA9686EC077E077E177E6FB36CC2BE6998BB6
- F035B7DC27DAFE2BD279A160D98BB6008B6CA510D0565D8AD501886C7BA1293B
- 07A01162592F8612522A36EEB0D50B48755EBB01FD74CB292C4F43BDAD6BA590
- F8D5AED35E8FF58E79EF0ACF36EA72DBEA61DC61F2C4B1CB9357CC8FB9680127
- E1561C7A08C6E4B6AEB59F11FC6CFC8E7C137E08E611F3CA455B5045553DB581
- AD5CCC81BA469D73B1683CB5D6B2471B415BE1625184DAB6E2F8DFB27225B2ED
- 85A6EC1C401C940415DE3211186AF1D80A279D1DD3C5480F17736821B28A51CD
- 56D3C932C94C6694592A27AE5BFBD7B7D8BE15F70E918F8F9D8D76981F4117DB
- A21FC40D1A5AF16C1BA97DFC6147B70DE367E167E267E37708813C61DE308F3C
- C536BEF56D9B93C4BA4487BA469D73B128B0CCB52A629DBD041BB13BFEF7AE0B
- 5AF28C368DB6CDC5B2A1EC1CC07B8A92026559BA4ADE55F6CFDA6746D3D60BF6
- 54E2F5AD69B2DD6C26BBBB3E11DD5B471BFDF73B31177087894F8F9D9BB8A8FE
- 5E34277007DC31D8F89D8DA4FEDB0F9340EBE6A28E12E3DFE0DFE267E067E167
- E605F28279C2BCF114DBA0CE94D5811D5CCC813A4E765FFD848B45932D73287B
- 2EE630C6D3B6F72CF8D75A6F8D429B46DBE662D950760E0001F76B9DB1F79310
- 53ECCD0324AE74769A143F7E3A9E958D6BF9DBA2D1A391093DA1590CD34C337F
- 60E3E63D5C7484E899935DC39F8EBD6A2693331E56C1433935FBAAC89A1FEC81
- AEFBC324BC071DC27D30EC5945B4CA30DED4937DE17B4CC39FE1EFE0EFE2DFE0
- DF8A0EF6DC0DE4218279C13CF12447409DA1EEB8980375AC47C76C6FA6119539
- DA46ACA3D3D6F0056DD4EB27967E92C8A6CB81B2740080455990512DBC7D87AD
- 137C66249220096299E051C3640D55ED5D5985243A3BFEE8557C162FEFAA26F7
- 39B12FE06E92BD3DC3B77E73E995D4B0719127CD88BB1286511BD121549386A7
- D6919587B690D52FEDCABEF03DA6E1CFF077F077E7027E37E4E15F302F3CC911
- 5057A8332EE640DDA28EB9583458D658E65CFC06B08DAC8DD8006D145A29D1BC
- 8F740073053AAC7D3866E2628EE026EF1C4D333FFA50F2127F9B83E28CFDFA56
- 5B5757237A7422AA4F24DFE3628E649A288196758FC03739AA6F964864867EFB
- F9E1B14FC75F136D1B2E15F85DF89DF8DD98079EEC1034AB2BD4194FC881BA45
- 1D73B168B0ACB1CCB99843641B8522B251B465B4692E961565E9005E57149CE5
- B2B42ABE35F66F818D9DBFD4215A0DF0AEAA6AE36F6D3175F1C2FB9AA259767B
- A515BD3ED0D6BE8D8B8E12EBB874E3D62F4EBE32F145FA77E974DA91E53711F8
- D9F81DB77EF9C5AFF13B79B2A3A08E50575CCCE1766B63A85B2EDA4254D66813
- 681B5C2C1A918DA22DA34D73B1AC284B078080D7B4CED8837DB81AD7D85A56C3
- 168B4D104BB759F1915A4FE39A5946BCB3935D11B831F66B2E4EC3B3C6B7C7E9
- A1C0DDE0387CF017277F3DFAC1D0BFC66E1B5FC2B3DA0E3D859F819F859F899F
- 9D1DEB337B813DF281BA411D71711AA9DEC82B7667FE112C632C6B2EE6409BB0
- DB9B41DB441BE5620E912D970B65EB005C940A9556BDAFD9766CAC64EFA070A9
- CABBAE698615EEB993ECEEBCA0E9EE935CCC914C10D5DFDEFC94EAF1D80A1F3E
- 1B78F67EECADCFFF74E39533FF152BEE6497713433A95FC309BB7C4B8859E067
- F83BF8BBF837F8B7F819F859F6CFF3CF0CEA0475833AE249395CBAFB8B64F765
- E1998842C957C6C9DE5BB6972FF3D9663E5B2E07C039952F2F98E65F83B54E5B
- 52C99864F2EA7F3C62BBAB163EF4F05F291ED2C4C52C78F3ECC4914BEF189311
- DB174DA8C150D0BBAFFDE766DAB08C09DDA6EBC6C4C92FFEC04CC3D67A733150
- CDA5BAAA6B2AD440C0A3F0E3D050E933462C91CA8C0D4F32DD66DCFE22C00D3F
- 957B1EF8765AC958E66114B73A913CDEF177C654D476EC7FB5221CA83CB0F9B9
- 7B77FF9929D21779FBE83F73B16836FC8703ED2EC5B20230F996A2FC237F5F76
- 946D0F0081CA6F595A42057B573515BEB07D0FE981294B900A348CE07D9B1DD9
- BE8B066B5E1BFD27D141213474FFB61D0F73715EC10A9E1EBA1DC1ADBA388EC7
- 17BE4F0FDD8A2C44E54782DB763C24AAFCA83BB367FC174E547E24B879F366D1
- D65F912D140ADAA4A0F2239DFCFFB2A4AC1D00D41CA1F2AAF6AFB53D568F9DBE
- D4095F600D155643D6B9AA6A6C6F3A4212D7BA3B32E3F4F75C9C06F3B3FB825B
- B638BA3F603152B1F9FEBD869F6DE6E234507789AB9DC2F888858265AA5613EB
- A929B081AC2DD8249F4DE6B3E172A1AC1DC03B8A3208BD00CBA68FE03A52979D
- 12B40135332C7523FD191773600BE1DBB4C9B2FFBC58A267CEFE4E33DDC2B57A
- 33E4D9E5BF6FEB2E2E2E3BF0D98D4A752717A7813A43DD71D13658A6A2D61F6D
- 006D818B45A2719B9C0EDA2EDA3017CB92B276000864D0B2334B851E57D5DE07
- 6DDFC293387BEEA2A817E00A936627560410CA74163B7DEEBFB9556B04E12C61
- F71EFF96FB1FE4D2B221FBCCF0EC5C9C06EA0A7586BAE349B6C0B2C432E5E237
- 40D9676DC02655BB1E0CA14D723107781B4B78F772A3EC1D4092904BA0488B21
- 54EEB47ADC42C1431FA9FEA43068856F6393632DB3998825A6CE76FE3FB896CD
- 93A61352EF0FECD8FD2855AC33E04B0D7CC6C0FDBB1FC567E649D3C8AEF783AE
- 50673CC936F9CA327D2379D4EEC11FA4728FD816DD94DADE58546ACADE01BCA7
- 285146E9752EE6F054902A575DA3EDA3B653A7CE5D621962E9A6A93E52E36FBB
- CFB1C07B4664743CF165CF7F7269AA70271BF3B1FB2A1ED8F76CA9970817127C
- 367C469CFFE049D340DDA08E50573CC936588658965CCC81653EF9C539DB4B8B
- 6883688B5CBC9BFED7282DAB00A022CADE01202663966E1AF40A94BAA75B6C07
- F3C0F15FB27B54B8C3CCD35CB543F1071D3BC9971E191C4A5EEAFF4FB8B4C593
- A6A1AB9935C13DDBFFAC949B85160A7C267C367C469E348DEC721FE80675C493
- 6C83658765C8C56924AF8E1DB63FF627046D106D918B3920CD917D0BA5665138
- 002FA53DA050CBDA7C7025A9578301DBCF90B8D871DD8813CBDE02BC45B8E2FE
- EDBBB9E808E9C15BB7D2E77AFF63BEE140C6304215DBD7BC1868BB0FBAC8CE9E
- 1D5818A882CF82CF84CFC613A781BA409DA06E78922304B76FDF29BA09DA8C91
- CB890B5FD98AFA83A0EDA10D723107DAAA8BDABFB0643E581406065D2903946A
- 89000B99D7AABFB5CB76645F247EBEE743680EAC91832B4993779DFD83427793
- 191E1C9C3AD5F57F6AC4258C3D87BBE158ADEFC18A07F71ED2C2D5B62F305928
- 30EFF80CF82CA21D7E084EF8A12E50273CC911B0CC44137F58C6B10B3D1F70D1
- 16687B68835CCC611272166D968B65CDA2696112849C87CC5AF66A57B5B346E6
- F6837FB047A6FF66441F348421B77CADF57BB440A5A363731CE7C68E9FFBBFDD
- CC9DB7AB68D04C6368D7BA9771C6DCA9D062F301E615D7F731EFF80C3CD9023E
- FBE467E7FE2F27C7FC089615961917A781658C65CDC5A2419B43DBE3620EB451
- 68451645F71F59340E00A3A99882595578004FFDD3BB1D1933478F9D3E65A605
- B108A01B19DCBD65BFDDD061F762A6E3C9C8D193FFAF16A3EF88760C22D99613
- 57091EDAF6235FEBC62DB86D96FFA8ECC0BCF95BDAB7615E717D3F5FAB8FCF8A
- CF8CCF8E3AE0C98E8065846525ECFA43D9621973D1166873687B5CCC81365A8E
- 917FF2B1681C00C2183B0D19B65494703B5BA97AEDCF05503D6DC6BFBCF10E0C
- E22CE1B6543F6908EDD8E5D806A13BE05AF7E4E92FDE49F444FFDEEB56F3B64C
- 181D87D6050F54EDDBF9231C5363B86CFEA30507F38279C2BC917AFF43A2483E
- 77C067C467C567766A9DFF6EB08CB0ACB8F80D50A6F18B37DEC132E6294583B6
- 8636C7C51C689B29C6CE707151E0688B361F3C6F9A4FC07F968A38DE45AE0FBE
- 71C4917164F0E13DBBDC8DEE67B9388DD8E5A123C99EAE929C85C70344FE6D5B
- 7EA86BE959B708636CBC4C8276256FF4756446861C8DC8335770661F2FEDC0B8
- FDA2D0DDF7822724E3E72FBEEAD4DEFE7BC1717F6053FD012E4E233D907E77EA
- E849DB91849186170F3454B5125118B90B6F29CA87FCFDA260D1398043A65901
- 99FE09BC9DD6BD04B7AEF7FED78E73E9E888EDC9178CEB56FDEDBDDFA73E62B9
- 90823092993C7DED707A78A0646BBCDE96B6ADAED5D53FD24D7D4EBB113DAA1A
- C98CC7AFA687867AD343C3239049DBAD9C18AAE02DBD7851A7ABCABF21651873
- 0AD082B3FCA9DEB157F098344F721C775D6365C5AEF507C1A22D73252C41BAC6
- FE70E2374E2CFBB943B56AF3FFD4BE1D5AFB7B27FF0CF8F05FBEAD28935C5E14
- 2C3A07808013F816647C3B17734C0E92DB377F75C491D04B4A38ECAB7C7CCBCF
- A84AAC61C80C9298387EE98F7AD45EFCB899C05B6B025BB71E7485BCCF26CDC4
- 9CF722785D34694C6A037A2C3AA047224399C8D898994A163526C5C8BCAE7075
- B5160ED76B815023DECF2FBAA23B1F18C32F134DBE1BBB70E1B013C13CF2A185
- A0ACF66D7E1A9A04CB7D7CCC2013137FBAF48FE6F8789C27D962D58F0F345534
- 90155CFC064ABF7C8BD2BCF736942B8BD2011C34CD40107A01D0CC4DF3F6F030
- ACEFB5C10BB19E4E4726963C6DAD2B02F737FC045A7DCB528F91226313C74E7F
- C492A5336C440B55867C6DED4F6B3EFDD1B974B345785D4A2C9356A366924C29
- 462269A4CC04C63EC0E07E8AA2AA8CA81A71AB6EAA6A6E0C18A07849D0E53642
- C98C595410561C9E60F45E0CE0E9440CBF99C0EBBD2BF7EF7A5CF5106B300E18
- F7C7BE1CFC65AAB3CB91602681756DDEA6971BB6424B3FADDE406F2003639A5F
- 1E5614DB7124E69B45E90010E805EC85CC5B0ED1245334D2FB9F3F75EC086670
- EFEE6DEE26EF212E4EC34C9091C891531F31C3FE7EF2D9C83A82D6B647B56AFA
- AD64CA7A5946398037F6E863CA9144D7E58F304C3A4F2E1954F5A8E103BB1F17
- 85F842527DE97762274E3A765741F3DF3ED2E6F50863FE7D0E5D7FDB31051682
- 45EB001E654CAB62ECAF40F996DD65A36748F7F00747C4076F8A20F4C481C7B5
- 6AB69F8BD3D027C9EDC867273E2EC58CB6081C1AF837B4EED21A2A0EA8AEF486
- 84207AEE7C824B7A785127DED587D77595B2AB7F37B8DC177E68EF635A85A03B
- 0EE863F458F4C3231F71D136754F1EA8AED9495AB898032A50749CD27F2EB75B
- 7FE7CAA27500C8F74CB3159ADEEF703107D4C44CCF3F755C488F8C3852283829
- 58F5CCDEE7950011460B422710FDFCD4A7F3D113B81BB5AAA6DAD7D4BC5BABF4
- EC50DCE975F3E50CA0C5CD684977AF11499DC32BBAEDDED25B28D8F2871EDCFD
- 48BECA6FC6C8C5F1F74EBCE5C4A41FE2AEADD5D6FD75FB56A82C9609469590DF
- FF56511CBD14653E59D40E0081A1C04BF01096ADBAF14932D2F75F8E5CE3A26D
- 14B747AD7CEA811F521F119E10CC0E078E9FFEB8D47302F9500381807B4D73BB
- ABA2B24509B00DD493599D6F234EA1787DC430D2AE3E638A5D31C7C62EA7FB7B
- BB8D74DAF6D5DFC58063FEF0BE5D8FE5EBF6B304E99978FF8B579D38E67B87A6
- 7F7F60BDBF42104998901BD0F57F9D8B8B9245EF005E32CD6AA8717F016F2DC6
- 3E7C8C748E1E3D627BDBE71DA8CFE7AA3CB8EBCFEF0D267A079C189C3A79E953
- 7DAA74AB0373855297E65E51DFA886C38D8ACF5FAB78DC354C6555AA8B05A992
- DDA8430DC6B2AB0B2AA5B84AC09849E346864E51838E9BA9F4A899888F1891C8
- 40FAF6D000639905EFE2E216DFE0DE2D8F0A27FC000CEE3971F8F4BF3A795949
- CDC307C275FB89E8CE0803BA03AFBCAE28F3DAFB719A45EF0090174D739F49C8
- 3E2EE6C0A1C0B55F745FCC0C0F3866105A45C8137C7CDB5F286E22BC569CE924
- 36F5E5B54F4AB94F603982EBFCC1FBD73F4A356BDC7D04B7F94E7D74FE157D32
- EAD8365C3CEBBFFEA72D5B445D7F186B1D7F43518E7371D1B2A013484EA151FA
- 051492E546612CB8553F6A852EBBBDF881778306868686AD0D4F9A061A68C5AE
- F54F397D827039E35DDFBA0A37F9E4ADFC50164E577EB419B41D51E5475B439B
- E3E2A2664938003C7A09551C2F8DB48CFB70D9A6E1C5076D070EB91B34B4AFBB
- 9A796E7CA1D05BDD547FA062E7DE6D4E1F205A4EA0EE5087818DF58F804E2D15
- 11C98EF9A12C9CADFCB8DDF7C106D1921F8047D3DF5F2CC77D67634919E70B8C
- ED628C59F682C343B25B878D8E89B3C71CDD838E1383A1271F782EDFEA0062C4
- C9E0D4D94B9F9772D7E0520477F705776C7E5078B08783B3FDD10FBE78C7C909
- 3FA472C7FEE0CA836A3B0C212DF583527AE44D4A1D3953500E2CADD68931FA3C
- 63DF837796B0536021E9DE5F745F72723E00C125C2CA6FED7B4CAB660FF1240B
- 2623A978D7F017A9AB9DC2002092E97836B4ADF1B7D63DA050EB71DB3BE863F4
- B3893F1DFFD8A9A5BE3BE0B8BFF9A72D9B5522DC75D9FF16A5BF052FE0E8772E
- 244BCB01002F3316CC30F6975042963DEB78AD58F7DF1FBF4CD3CE1A0D92DD31
- B8D6FB6D22D8367C874C84F44E9D3F7FD68C4D3A7A067EA98031FC308C973084
- F71D28D1D3D7937F983A71EA3C4F710CE676D196BFD9B74974C30F5494A48BD2
- 7F81AE7F494E322E144BCE0120D00B68A68C3D2FEAC24D8D92A11BFF78C4763C
- 38117876C0BFA5E165E101220EF60652D7C6CFC63BBF2ADB0B2317028CDEEB59
- 5FB563A6561F0FF6C42F0EBEE6D4DEFE7B59FDEF0E34076B8431FEA06F49DF82
- D6BF2476B3902C490780E43B2B804CF491FE81578F0C70D15194AA2A7FE5439B
- 9F131E25BE0B2341461357FA4EA706FA4779D2B2042FEDC0B8FDA2D0DD778347
- 7A273EBBF48E53A7FAEEA5F187071A2B9BAC4347041A9245BBD77F3696AC0340
- C0091C8207B4DE07070C9F25D7460F1FB12C1D3A01CE0B54ECDFB1D3BDD27D70
- A6210182C382C4E5CB1732E3A34BAA6B391B78579F7FD3A62D5A58BCB3320776
- F96FA50F4F1E3B7BC6E9F1FE1D6A0E1EA8ADDB21B613F8C26B50F9DFE6E29263
- 493B80674CD3E326E407F090969D6350B06CE8137265FCC491921D5775AF6DAE
- F3DFBFFAB97C9B86EE8047738D51D233F5D5A58B4E5C4D5ECEE015DD7803335E
- C22ABAABEF6E70730F86F14A5FED2D59C4A3AABD0742F58F9236C88868497C34
- 45C86F16538CBF4259D20E00799EB1308CE07E006F2DC1220063E070EACAC4D9
- 93256B7DB137107A78F7035A83FA18287BC6F3FC59471021FDC96B3D1DA9DBB7
- 16F516D37BF1AC5859ED5DBFAE5D0D9335B3557C70CEE9CC20FB64F2E8C993A5
- 6AF591CA1D7B828D073D1BE1ADE8CC448250FADF61DCEFD856F27264C93B00E4
- 65C65664187B092CC9D21DC75062B7DE8D5D99BA70A6A42DAF6BCDAAB06FFBBA
- A7349F705FB9053C5C94BA3DD19DE8BAD2C78C85B9B7DF2E5475A9BED68D4D9E
- 15952DF90EEFDC8B9E209D89733DEF3B11BA7B26825B7706563E1BD808CDBEC5
- 26A052E82E4A5F7F8DD2924C369613CBC20120DF636CBDC9D873E0042CCF3C5F
- 4E00F16D695FEB6DA9798ABAF26F70990623197D9CF4A706067A13FD7D43F315
- 77A05870F79E6F4D53BDA7B1B159AB226B40DBC21D7CF78277F5E1156D784B13
- 4F2A19B3547EA650FACE6F2975EC246939B36C1C00F29C696E86423FC8C57B31
- 6E7D607446CF1C2B7950C7EC24E103DBB7BA577B1F8691A7F0649B108324C119
- DC4C8D0CDD4ADDE81F9CAFE01BB381414A3CABD734786AEB5742A55F051DEAB9
- 5FA2629231BCA5172FEA2C6577FF0EA19DFB2B563EA9622F4C78541A1A83C3EF
- 284AD9DFEAEB14CBCA0120CF33763F61EC312E4E03ACCF1CFA8474967262F06E
- 702BB16FC7F62D9ED5EE870A720400CE17B03819D527F4DBFAD8C86872F0E6F0
- 7CC522C033F9DE8655755A756D8D56A9ADA07E5233DBB8DE0254FCD48DF46778
- 3FBFD35B79F331CB841F3C18FD18C6FC962BE89632CBCE0120874C73373CF8C3
- 5C9C063A81B133E49A9321C566037B04C1EDEDADAE35A17DF9620DCC0533A34C
- 997173CC4CA4A3FA542C6A262663466432566C7C022D18F6A9E18A80E2AB0868
- C18A901AD0C2D4AB841557F13109F1E45EA63F7A7CEA5C47D77CB4F877C0905E
- D53BC9FA7C951F123F7B435196C409BF4258960E0079D1341F80EE5EDEFDFB13
- 3DA47FE0B5D26C169A09DC4DE86D6ED8412BC91630CA3987039F15183E3083A4
- B32F460C66421B6CF0BB1655E2A20A81A12F51A94ADCF82AA81B3F0BA0E7149B
- 201793BD83674BB58B6F261A5F3ED058B94EBCC907814A70EC4D4539C9C565C5
- B27500083881ED609CDFE2A285C43819EAFDD5F1EBA5383B301B187D28B06D73
- BBABCEDBCEFC64BDC2C463D672C5A4E05E12A4571F4A5E8A9DBFD4E164949EB9
- 827BFB9B7FBC6FADAFCABABDF70E4BED745FA12C6B0780E0C420D4AC27A1860B
- 75810788FA7ED5DDEDF429C242C04B4A7C1BDBDA5C35EE561220EB1CED193808
- B6F424467A32A3E9AEC495CE4E33B27047A0F1545FD38F5B5A44077B10286C06
- AF0FA1DB7F91272D4B96BD0340C009B4801378069C8070DB2E1E251E3A6C743B
- 1D4FA01870E2D0D3B67EB5565FDBACF9D96AE223ABA0108BBA30C42EA0AF34B4
- F237F538BDA10F8DF4A63AAFDD98AF09BD99C0F3FCF507552C53A15E405F3A64
- F2BD7714A59B272D5BA403E064370B11728831F1CDB660EC2CD245FA06DFF87C
- 10EC87A72E3CE8105CCD4D755A55558356E1A957FCAC81BA945AA2387C7988A9
- 4CB18C3962C6E9A03E991AD2C7C70733BD7DC3E550E1BF41CB46F209B7922630
- 6CA16D43973FEE22E4EDE5B0C9672E48077017CF9866089A8C1740297997E4F0
- E6A19BBFEEEA59C821C15CC83A86C6BA4A355C55A5783D01EA717989A6F9158D
- F928250A5308FEFBBA8534499A9AC4648C98A64E1344D7E32C95499AC954CC88
- 8C8F67068627CAABA25BC12E3FC6F0CB13C62B0B38F1B134216FBEA728F3B2CC
- BB18900EE01EF801A2A74131C2D36108185266E418E97132E4B8A478C20F1DA8
- 6C7828BBC49777D721FCAC2709DDFEA57CB0A718A403C803C6135008D907953D
- AF8EF0F291DBFFDAD1978E38730391A430DCE15A6DC59FB737892EEDB803141E
- DE957E7CA99EE7B78B740033C0230BE1E460DE3571EC0D8C9D21D7E773E39024
- B7B1672D18F04CAD7E9251FADE528CE4E314D201CC02C6184C33F634BCCDBB91
- 04C1B981E1B76FF7397535B9440C5ED15D776845D34C637D4EBF9BD23F2EB518
- 7E4E231DC05C608CBE40C84EC6B23704E7DD9003CA64D1413238FC56C72D392C
- 7016ECEED73DDFBE32D4401A661A960106A5F4D89B849C214B287A6FA9900EA0
- 005E344DDC517610C694755FA788819FEB135DE4E6C8BB67868D640C4449B1A8
- DE8052FBECCEBACA56B24AC9B34FE30E60CC23F07AFF0D4519E2499259900EA0
- 407ECE98721E2F2021642FBC663448DC4014E9A0B786FE786A98A6E3B2352A00
- E6F6D3FAA777D785DBD9CA7C1B7AEE00468CBDAD93DB293DF577944A875B00D2
- 0114C97718AB52197B021438EB1D806091A9F10E3A30FAE1E951331E2BEBF5F4
- 8546F107D49A2776D554B5B3C6B96C7906AF7A03FAFC1FFE9ED2719E242900E9
- 006C72C834378212F168B170CFF9DDE0D060AA9F0C0D7FD03D58EE1B89E61BDC
- C853F7644B43700DA99FADABCF9984CA7FF46D45B9C26549114807E0008F32A6
- 5531B6139489478C670D8105866BA626C9F8C449323C7EFAF368396D2D9E5F34
- 52B5EBC150E51E52E7A92055A03FA8FB3303BF804733BF18A7F4CC2794CA8956
- 9B4807E020074D33E023640F28152F0BCDBB5A7037301E484EF5802338767D34
- 79B32FCD939734DE554DEEAAFD6B6B82EB481D2869AE71070CA8F8171330D63F
- AC284B3A74FA7C221D400980614105A174AFCAD87DD02398B555BB031E3D9EBA
- 4AC6C68EF78E6506FA97D410C1D5B8C655BDAFB93AB88154E73BA22B029467C2
- 18FF2BC2D809E8EE973C5EE372433A801282878B3C94EE5418DB3C97A1C1DD40
- 57602AD54F27263A9291C9F367E3F3193ECB193412DCBA2D10DC14A8F4AF2561
- B7420A3A9D885D7D93D24B29C6CEC8C33BA5433A8079E0C78C79A38C6D851A7C
- 3FBC023C79CEE0E4A11E27D1E44D3215ED4E4D4E5E0187B000518A6602A3EF54
- 6CDCE10FB5782ABCAB48D0E52715605C05393D04FE2606AF2F43945EF815A572
- 576589910E601EC13D041718DBA0936CBCBF26A8C145E91FFECED44D124B8F91
- 786A185ED75389C9EECE84198FCCCB12A3E20FAB152D6D3ECF5A8FCF5347FCEE
- 6AE2D71412808799F370E76EE0EFF0C04E9F0663FCAD945E956BF9F38774000B
- 040E0FBC846C86B7ED50A1435FA7DA033E27932124654E929401AF7494648C04
- D10DF85F8FC5F4CCD494614E8D19B8E8A0A77576C7616085D6DC1AC5C5372558
- ADBA8241550B043435445CAA8F686EFCBF827814784193EE01A329B86517019F
- 835DFB0E68E62FC96EFEC2201D401980D188D28CE175E27861C59C27C8162938
- 91D7E9A6B44B46E55978A40328339E33CD06289466FE5A51EC30A15C80CC3378
- 86DBF0EAC5D73B8A32C87F24290316B5712D7570F27082B1261810AF52095909
- 15A8B6DC1D025678F86F14F27C53815725A57D7232AF7C910E601181E1CA3C94
- 3632C61AC021D49A94D651C62A17CA29606567944E288C0D1B78128FD2C11463
- 0332ECD6E2413A80450E6E430E315603051906A7103228AD840A89938A3897E0
- 07E760EB0E01F85CACCC71784D82C389C26747A1759F80CF8D44291D95DB7117
- 37D2012C75A08DFE2E213E2F0C27A026BBA0C5CE3A04E839A82E7EE82643880E
- E9D91501484FC12F6492D06DFF1D210919544322914824128944229148241289
- 4422914824128944229148241289442291482412894422914824128944229148
- 2412894422914824128944229148241289442291482412894422914824128944
- 2291482412894422914824128944229148241289442291482412894422914824
- 1289442291482412C9728390FF1F97ED6E34D64226CD0000000049454E44AE42
- 6082}
- FileName = 'C:\Users\Programmer\Pictures\Icons\'#931#969#964#942#961#951#962'\icon_simulation.png'
- end>
- Align = Client
- Size.Width = 444.500000000000000000
- Size.Height = 313.000000000000000000
- Size.PlatformDefault = False
- end
- object imgPeerUserVideo: TImage
- MultiResBitmap.Height = 256
- MultiResBitmap.Width = 256
- MultiResBitmap = <
- item
- Width = 256
- Height = 256
- PNG = {
- 89504E470D0A1A0A0000000D49484452000001000000010008060000005C72A8
- 66000000017352474200AECE1CE90000000467414D410000B18F0BFC61050000
- 4A6C49444154785EEDBD69705CC795A89979EFADBD5028EC0417102401901037
- 71114951A2244BA216DBA224B764BBDD1D6DBB9F67625EC44C77CCC49B989F8E
- FE39332F5EC4EB9988F7625E77DBEE68B9F52CB5B5D9962C4AB2245214497111
- 3781044002044882D80B05D47EEFCD39A7942C11BC5900AAEE2DA000E4C7A860
- 9D045095F7E4C993FB4922914824128944229148241289442291482412894422
- 9148241289442291482412894422914824128944229148241289442291482412
- 8944229148241289442291482412894422914824128944229148241289442291
- 4824128944229148241289442291482412894422914824128944229148241289
- 4400E5FF4B962A8CD19718F3C23B9F41886612E23128A52A218ACA980B7F05E4
- 0CFCCC04992984A4E0673A24275EA734492865F83B92A58974008B9C4719D342
- 8CD5404186A1E286A08287A0C686E047155099FDF01E2B7FD1C0E726E133E3F0
- 7612DE47E133A3E02CA2F0B99128A5A39F508ACE42B248910E6011F13263EE34
- 212BA1A16E80CA5E0B95B01692C3F0FF8294237C297C3589C0FF23E01446A063
- 31E826E4D66B944236258B01E900CA981F43D77D82B12668815741855F89157E
- A12AFB5C41A7C01DC22DE82DDCACA4B4EF573894909425D2019419CF99660314
- 4A337FAD28F70A3F1B907906CF701B5EBDF87A475106F98F2465C0A236AEA502
- 567A682DDBA0305AA192E0F87DC902CF88F3075DD0ABE994CE60E1910E608138
- 649A3849B705DEB63B55E9E17332194252669CA4F408496762246D4C115D9F84
- D7444CD71353BA393566E01CBF6EEACC8C46A0A74E88120AAB9AA251A2C1FB60
- B5AAF9829A5619D0B40AA2A941A2B902C4AD85895BF1138F8B100F184D76F5C0
- 2EE80CE0BF0E700617DF5694C9AF5325F3897400F3C8CF1953CE30B65EA1740B
- 656C2D54D8A2F40F7F67EA2689A5C7483C350CAF1BA9C4E4D5CEC49D0A5D6AD0
- 61546C68F379567B7C9E3AE2775713BFA690003C0CF8B4C281BF638CD2EB2663
- 1777527AEDEF28059F20990FA40398075E324D1F34BA5BE1ED76A8BC81AF53E7
- 0ED4065D8F9368F226998AF6A42627BF3A1BA7E90C7C54F9C0DC2E5A71DF0E7F
- 689DA7C2BB8A04353F098137803E45618041C6E0BF73F087175E5794C4D7A992
- 52211D400979C634436E42764145D80CB5B5A0CA9026642AD54F27263A9291C9
- F350E1CDF2AAF0B3C1147008DB76F82BDBBD61CF1A56097A08F21FCD09304CE8
- E4904BA087D3EF290A0E152425403A80128015DF47C85E78DB0E463CE76E71C6
- 24935357C9D8C4B1EBE3C9C1BE25B596EE6A5CE3AADED75C1DDC40AA5D0AA9E0
- C9B302CAC3E1400774054E4847E03CD20138C841D30C40C5DF034AC5C93DF5EB
- D49981417B72AA870C8F1FBB3E9ABCB9B42A7D3EBCAB9ADC55FBD7D604D7913A
- 50D25C772A1AE00C2E4D812338AC28384C90388074000E80DB71AB18DB09CA7C
- 009AAB5967C871122F3549C627CE40C53FF139B46ACB7537AD46AAF63E18AADC
- 49EA3C15A40AF4376B6F097E01C7425F8C537A466E43B68F74003679C134DBC0
- 200FC0DB59BBB5389937D54F86863FE81ECC0C0F6478B20470D535BAEA9E6C69
- 08AE21F550C9E7325F8267138EBCA9289D5C961481740045F23C6361C2D813F0
- 76CDD729F9818A9F1AEFA003A31F9E1E35E3B17959AA5BAC28FE805AF3C4AE9A
- AA76D6088EC0C39367A25FA7F4A3DF533ACE65490148075020B8967F9EB15DD0
- EAEF85D78C2D15D4F474A483DE1A3B7C7AC448C670324B324798DB4FEB9FDE5D
- 176E672B5542DC3C590818B10EAF13DB283D2DF7101486740005F09269D641A5
- 7E0A2CAC8E2709819FEB135DE4D6C8BB678664C5B787EA0D28B5CFEEACAF6C25
- 2B671B1AC0CF87C159BCFFBAA20CF324C92C4807301718A32F10B29331B61FA4
- BCB3FBA04C161D2483C36F75DC4A4746E4049583B8C3B55ADDF3ED2B430DA401
- 7A5E33D92DC63B39F6262167643093D9910E60165E662C9866EC69783BE3583F
- 9D2113836F0E5E8FF574CAA3AF2524B0AECDDB70A861ADDB432A79523EFADD94
- FEF1354AA7B82C11201DC00C3CCF583365EC196846F2AE55C3CF32A36749DFC8
- E123A33C49320FD41E3C5053B383348101E75D76859F2519A5EFBD45692F4F92
- DC8374007978C134F7C07F0FCED4DD8C4F9291DBAF75F4A54764777F2170D7D6
- 6A2B5E6E6FF2576423230981C2C361C0E76F2ACAC9AF532477231DC03D3C639A
- 1E37214F8362D6F3240BD8EA8F1C233DA3478F4478926401A979F840B8763F59
- 076596B7370065762D4DC81FDF5394144F9200D201DC053FBCF30228A59A2759
- 48A7C844FFAFBBAF95FB461EC5ED515D8D75956AB8AA8A7A3C3EC5EBF2134DF3
- 2B1AF3514A14A610FCF7F5F29A49D2D4242663C434759AC0B38766321367A954
- C2888C8F67068627CC74AAACF72FE046A2553F6A5DE7F5B0304FB2004E600C9C
- C09BF24CC1374807C07999B11519C69E0323111ED70545B1B12ED237F8C6E783
- E5B475375BD19B9BEAB4AAAA06ADC253AF78593D75931AA23A1C59C820519626
- A366920EE993A9217D7C7C30D3DB375C5E8E41230D2F3ED8106ECDCE0D086D9B
- 521A876EC2DBAF517A9B272D6BA403009E33CD16153A0050F985EBCCB8A167E8
- B0D13D71F6D882CF286385F7B4AD5FADD5D7366B7EB69AF8C82A28C41937CA94
- 0AD0579A24C84D3D4E6FE84323BDA9CE6B37CAC12154EED81FAC3FA862990AF5
- 02FAD22193EFBDA328DD3C69D9B2EC1DC021D3BC4F21E42018B350177844B7EF
- 95DEEECC40FF8275F99570D8E7DBD8D6E6AA71B742FF64DD1CB7C8CE3B262129
- 12233D99D17457E24A67A719892C58400F1C1234FDB8A525DFD163286C8C5EFC
- E11B8A7291272D4B96B50378D134B783D17E8B8B16121132DCFBCBE3BD0B117D
- 87FA7CAEC0B6CDEDAE3A6F3BF393F50A9BDBF1E272C1A4C4A071722D339CEC88
- 9DBFD4C112897977A018A5A8F927FB9A7DE1FC3B37614870E44D4A4F7371D9B1
- 6C1D00B4FCBBE1E11FE6A285893ED23FF0EA91012ECE1B9EB6D615DEB50DF7D3
- 30D9EA644B6F1A2445E1C50C92668C18CC8406DB205F574A95B8A842144A894A
- 55E2662AF128F0CAFECC01B067C026C8C564EFE0D95467D7BC8FBD1B7F78A0B1
- B229FF462ED0F367D013F8828BCB8A65E90066AAFCD0D49BA36749CF7C6EECC1
- F059C1EDEDADAE35A17D8A8734F1E4823175658A25CC8811D3237A7C326AC626
- 63466432A64F15D715D782619F1AAE0828818A80E6AF08A9012D4C7D4A58D1CC
- 82C27BDD8D99227D99FEE8F1A9731D5DF319E6ACEEC903D5D53BC97A2877A8EF
- 56202347DF5694535C5C362C3B073053B71F2BFFE0A7A42B72FCC8044F2A2938
- A1E7DBB17D8B7BA57B3FD5480D4F9E133080652C4E46F5A83EA88F8E8C24076F
- 0EB364725EBAD9D4EB75791B56D56935B5B55A486BA07E52435961B6C474329A
- BE953E96387BEEE27C4D1C86F71DA86C7884B4E6730290F827E8099CE3E2B260
- 593980E74C733314F2412EDE8B71EB03A3337AE658C9E3D3675BFCDDDB377BD6
- 781F01ABCBBBE7C0824192FA38B9991A19BA95BAD13FC832F353E16783BABC2E
- CFEA350D9EDAFA954A15595DD0F0C12463A9FEE4A753A7CE5D9A8F1E4168E7FE
- 8A954FAA6DF05638A7028DC3E17714E51217973CCBC6017C8FB1F5E6D7EBFC96
- 678642D76FBD1BBB3275E14CC963CDF9B6B4AFF5B6D43C455DA48127CD0C2319
- A8F4FDA98181DE447FDF1065FABC759B8B81518DFAD634D57B1A1B9BB52A1877
- D3B95D22C2326430D93DFA7EE262C7759E5432825B7706563E1BD8088D8165D9
- 178C832994BEF35B4AAFF1A425CDB270007C93CF4B507344EBFCC68D775397A7
- 2E9C2C69E577AF6EA8F46F6B3DA804C8269E34234602BAC8B727BA125D5D7DCC
- 28EF5D78F9A09A4BF3B56C5CE35E51D9AAFAE636C4D113A43371AEE7FD4CFFCD
- 926EB30E6EDD1358FDAC07CBC2D213804AA1BB287D7D396C165AF20E8087EEFA
- 01BCF57D9DF20D38E61FF8C0B852CA6E3F76F7430FEF7E406B501F0365CFBA61
- 479F207DC99EBECBA981FE2575BAD0D3B8A6C6BBAE69935639FB2427944B5A1F
- 343E8E1E3DF545298705381C687C52DD08E5229A1348B8297D159CC0BCCC072D
- 144BDA01E0C11E188C7E1FDE5A5A1F787076FB137265FCC49192ED0B77AF6DAE
- F3DFBFFA39C54D56F2242138A1678C929EA9CECB978CF1D1257D7E5DADAA0906
- DB366D566BC8BAD9260ECD34B915FFF2C63BE9EBBD258BF053B5F74068C5A364
- 2378194B5E20612449C86B4BF900D1927600874CF3103CA0F054DFF059726DF4
- F091112E3A4EF0E13DBBDC2BDD07A1399B318C15B6F8B1CB572EE86323CBEA80
- 8A0B1C81BF7DD3F6597B0494E8E95BE9C353474F966CB34ECDC103B5753BC476
- 028EE1DADB8AF23617971C4BD601E0797E283C0CE165A1949B7C70DB6EE5C35B
- 0E511F69E54942708C9FB8D2777AA975F50B058706BE8D4DBB669B236009D235
- 71F4E2DBA5DA5E3CD36621A824C7966A3C8125E90078249FE745DDBAA9513274
- E31F8F9424428CA76DFD0AFF96952F53357FB82A939154AA77E26CFCF2C51E9E
- 2401FC6DF7ADF3ACAFDAA1D0FC4B88CC2013F18BB75E4B755E2BC9E4DCEA7F77
- A0395843EAB998038C086F2F7E6B2946165A720E0063F86518FB4BA8FC96305E
- 78B0A7FBEF4F5FA6E938FCD859827B776F73AFF57E7BA62E3F76F727CF9D3F6D
- C62665DC40014AA0C25BB17DDBAE1987053824B89EFCC3D48953E7798A636028
- F296BFD9B5497480082A4AD245E9BF2CB518834BCE013C6F9A7F06FF59BA7278
- A4B7F717DD979C0EE4919DE57F6CDFA3AE1A96F75C0163249DE81EFD22D17DB9
- 8F274966C0D7B2A9C9D752F300A5F9574DF431FAD9C49F8E7FECF42A019E226C
- FE69CBE63C4789FBDF52947FE3EF97044BCA01BC8017763086D7744D03BB7037
- 3F302E3BBDDC875B79434F3EF09C12C85E062AC48893C1A9B3973ED7A30B7734
- 7631A285C2BEE08ECD0FAAFEFC1BA6CC18B918FDE08B779CDE4A8CCB83AB9E54
- 378986904BEDF4E092710078690734ED3F84B7968D1DE35DE4FAE01B4706B9E8
- 08785C37FCC4AEEF531F59C7932CA407F54BD1B3A72F94FBEEBD720577158676
- ECDAEA6ED036F3240B2C417A221F9EFE8DD3C78D1B5E3CB0A2AA553814315C84
- BCBA542E1F111E8A586CC0B85FD509C1D8FD96CA9F4CD1C8D761BC9C43AB0879
- 2A0FEEFAF3BC959F113D7679E8C8E49913E765E52F1ED41DEA1075893AE5C9D3
- C032C0B2C032E1498E0036731BE33F72F16EB2B68636C7E545CD92700029C676
- 432DB3848686B4CCCD5F77F5C08891A7D8070D2DF8F8B6BFC87B6CD72089C9D3
- D7DE4FF674DDE029129BA02E51A7A85B9E340D2C0B2C13679D804E30F82BDA10
- 4FC881B6A633F6001717358B7E08F01DC6AA34C6FE12DE5A3CF2F031D2E964E8
- 6EECF6636B93AFF21B29323675F2D2A7C59EBF77124A5CAA6B457DA356155EA9
- F8FCB58AC75D43351686570555981F7F254D5976A2CBCD681AFE63CCA471A6D3
- 497845CC547AD44CC447F4F1C8ADCCEDA10146320B7E1E01E31304F76C7E44F5
- 884F5062AC8189C3A7FFD5C9E100861CAFDB4FF0F4E0BDE050E015180A8C7179
- 51B2E81DC021D37C091E62351773E0A51D7DFFE5886327BA70C2AFF2E9077E40
- BDE21D6366828C448E9FFE78BECEE4DF8B1A0804DCAB9B37B94295AD4A806DA0
- 9ECCEA64427CE4B550BC3E621869579F31C5AE98636397D3FDBDDD463A8D4E63
- DEC15804E17DBB1E537CE2CB40704E60E2FD2F5E757262B0E9DF1F582FBA7C04
- 7A0237DE5694D7B9B82859D40EE07BA6D90AA5FC1D2EE6C06E5BCF3F755C70EA
- C61E5CEAAB7A66EFF3F966FBF549723BFAF9A94FE7FBD49E5A5553ED6B6ADEAD
- 557A7628EEF4BA447A7E867450F9325AD2DD6B4452E7127DBDA78CF1D1796D05
- A9EA51430FEE7E44AB202B78D234707560FCBD136F39B544883710ADFBEBF6AD
- 50592C479BC1C3FEFEB78AD2C5C545C7A275008F32A65531F65750C296F8F7A3
- 6748F7F007471C33CAD013071ED7AAB337035BF8BAF29F84CA3F3F5D640CBEE1
- 6BD9B0D3555FF988EA4A6F98AF4A9F0F9F9B9846C67D353334F169A2FBEA99F9
- 0A52822B04E187F63E96CF09E863F458F4C3231F71D1361852AC662769E1620E
- A840D1714AFFF9134A9D9B689A4716AD0380AEFF5EC8FC835CCC81B3FEBDFFF9
- D34E2EDA26B067F716CF5AEF0B5C9C46B6DB7FE4D447F3D1F26BA1CA90AFB5ED
- 51AD9A7E2B992A3E265F29F17A94297D4C3992E8EAF8508F4E94FC7013F604C2
- 07763F9E6F3890EE4BBEEDE48EC1E6BF7DA44D74F310D8E1A23D2BB0281DC041
- D30C400DF889794F970C1E86F5BD317A21D6F595235B6D31426FE0FE869FC098
- C2B2BD97A5C9C4F867A70F977ACCAF064341FFA6FB9ED57CFAA3C91976C6CD84
- 9791B4696813990C8D28462269E8668299D088EABA4E554A99AA6A4455DD54D5
- DC54D3DC9AC6420AD5C376BE4F4F689F243A3BFE586A47807302550FED3A48DD
- 82F31794E8B12F077FE95424E240EB7DDEA6176BB642AF735ABD812E58668A90
- 5F1E5694924794729A45E9009E67EC31C2D8FD5CCC3139486EDFFCD51147B6DB
- 664FF53DBEE567C2833D06494C1CBF04C65DBAD97EECEA07B66E3DE80A799F4D
- 9A89392F6F795D34694C6A037A2C3A90999C18CD4C44C6592C569461D24020E0
- AA0C57B92A2A6BB440A851ADD01B931996F7AAF47BF12ABE54269A7C3776E1C2
- E1520E0D70D760E5BECD4FC380DC1AF4C52013131F5DFC07A74E11AEFAF181A6
- 8A06C1B083D22FDFA2F4632E2D1A169D03C0C33E69C67E0A6FA7CD70635CBFDE
- FFAFE37C3AE2CCC45FD5771FFE81F0482F2399C9D3D70EA787074A1629C6DBD2
- B6D5B5BAFA47BAA9CF298C9647552399F1F8D5F4D0506F7A6878043209EA2805
- 5471D7D7D5BAEBEB9B5D55FE0D29C3C87B11E7DDB8DDDA58AA77EC956477E705
- 9EE438EEBAC6CA8A5DEB0F82455B26EAF028F1D81F4EFCC689494177B8566BFE
- 1FDBB741AB7F6FAFD0800FFFE5DB8A52F2A0B24EB2E81CC0F3A6F904FCB7F56B
- E91B9CDCEE9B0DE6D1E87E968BD388758E1C495EBD52924D3ED9EEFEB62D3FD4
- B5F41E9E9417EC66A712B43B7DA3EFABCCC8D0826C4B75D5D6D7B95737DDE7F1
- B196B90C1734DD7D327EFEE2ABC654B42427EABCEB5A570736D55BCE8220E981
- F4BB4E05156978F14043552B59CBC5BBB9F096A27CC8DF2F0A16950338649A15
- D0ECFF149AB76933DF0694EFB5BF3F73DE48C66CB77CEEA6E6DAE0BED53F138D
- FB716F3F6E4DE5A2A3F8D6B7B47BD7D7FC249936AA7892102F51A65223B10B89
- DEEEAFCC055A8BBF17C5ED76FB9A5BEEF3D406B626C9CC13945EB71A49F68CFF
- 3271B5F32B9EE428153BF76E139E1DA0449F3A7EE31FD27DBDB6A340A9DE80B2
- FE6F766E035B9CE6F4C0284DB0C55F2CA65EC0822E21150AA574D7BD951F8974
- D05B4E547EA6B915FF8ED58744951F4FF5E1C11E2E3A062E6755EC7AE039DFFA
- F0DFCE54F915378DB3E1A923E3C7CFFC3AD6F9D597E552F911CC0BE609F34686
- E29F615EF98F2CC033867DEB427F83CF8CCFCE931D03CB08CB8A8BDF00658A65
- 8B65CC538A066D0D6D8E8B39D036D146B9B82858340E00037C2A8C593C3B283D
- 35F4C7538E748143FB77ED1605F0C47BF5A64E5D3CE6F4C11EC5EDF7861FDEF3
- 3FEB01F65CBEF57CDC8547278D73B1CFCEFF3AD175E522338D79DD6C540898B7
- 7877C779CC2B9934BEC4BCF31F4D039F159F199F1D75C0931D01CB08CB0ACB8C
- 27E5C0B2C532E6A22DD0E6D0F6B898036D146D958B65CFA27100D0D7DA0A0AB7
- 4CF04C7491DB4E44F8C1B8FD18BA9B8BD3485C1D39A9C7261C8DE2A3866BAA02
- FBB6FFEF699AB6CC67DC4163AEDBD1D33DAFC52E7C798C65D20BB2C5B81830AF
- F10B5F7E8E79C767E0C916F0D95107A80B9EE408585658665C9C0696B16BCDAA
- 394D5ECE04DADC7807B5C495441B455BE562D9B3281CC0CF195320A33BB89803
- 94AD8F1C3EE348EBEFDBDEFA24F4472D1359D938FD0E4FFAB9EA1A1A82BB5BFF
- 0F9D64844128B3ADFE48E2F3E8E727DED22363E33C79D18179C767C067C9D71B
- 401DA02E50273CC911B0CCB0ECB89803CBD8BF6D1D4E24DB66EC4FA747D006B9
- 98036D75B11C175E140EE00C63EBA1890F7031C7D42D32644CD91FFBE3755DAA
- 9FB473310706F0C4187E5C740477C3CA95EEEDCDFF219DD68527DA5CAA1A9D3C
- D7FF068EA9B153CD931731CCC467C167C267E389D3405DA04E50373CC911B2F1
- 170543012C6B2C732E160DDA1EDA201773A0AD6618DBC0C5B2665138008552CB
- 211C50B239FCC76EDBCB7E78D007EFEAE3E234307AAF93013CB5DA867AD7D635
- FFAB99368451835DA6EBC6D4C973FFB650CB7AA5049F099F0D9F91274D037582
- BA411DF124DB60D9A57AC7CF72711A58E658F65C2C1AB441B4452EE680B44531
- 0C287B07F08C69862863166F9D9A24E34E04F8C45B7A45177562DC7E27437767
- C7FCF7AFFBDFF2557E35462F474F1EFF83914A2DD988C1F86CF88CF8AC3C691A
- A81BD491937302F1CEAF7AB02CB99803CB1CCB9E8B45833688B6C8C5BB5903C3
- 80BCE1E1CB85B277005E42368337B578EA8933C4762B8967FCB357740BC04B3B
- F85BDB28BE802FB8A3ED7FC9D7ED275103BAC8A7FE041DFEB29DE1770A7C467C
- 567C669E340DD411EA0A75C6936C93AF2CB1ECD106B85834F96C312D58B52A37
- CADE0140DFCA729B2ED492E4F889CF6D1F32F1EDD8BE053460A9949908E975EA
- C61E46290DECDAFE3FA48D8C2568499648FA64FCE2979F7369D9907D6678762E
- 4E0375853A43DDF1245B6059629972F11BA0ECB3366013B445B4492EE680866B
- 237F5BB694B50378CE341BC0022CDDA8A91EF4B8F6B6FCE3F8CFB3DAFD101773
- E0459D89CB971DDBF013DAB9FBBBBA92161A993A619C897F7561C984982E147C
- 76D40117A7813A43DD71D13658A658B65CCC8136607F2E40E736391DB45DB461
- 2E962565ED002073A2586C64FCD875DBAD7360D7E63651EB8FB7F4661CBAA1D7
- B7A1ED3E5715B3442C4268827E3579E9CB135C5CB6A00E50175C9C06EA0EB748
- 73D11658A658B65CFC06B081AC2DD8249F4DE6B3E172A1AC1D007850CB693CBC
- DE2B79B3CFF636587763702F7F9B035B88A9AF2E5DE4A22DF0608FB2AEEAA7A2
- 1D7E6ED375237EEEEC512ECE2B5473A9AEBA15214FD3DA1A7F6B5B23BEF03DA6
- E1CFF8AFCD2BA80BD4091773A0EEBCEB6B7E8ABAE449B6C0B215F50244B65028
- 6893689B5CBC9BB276008E8CB14AC1CB8CAD483386177D4CC389537F78896760
- FBCA9F7131076E1C9938F6D9675CB445C5FEFD3F139DEAC3B5F0A953E7FECD48
- CCC36CBF4AA96F5D6BBDA7A9A6C9DBC01A55B75EC3180BA93E9FD0F11B898409
- C3EEA891D64693837420D537DA97E8E91A2206B3541AA7513D1E6F70CFF63FCB
- 188625C41B9E229C3C76EC1FB8688BCAFD0F3D24BA7B3076EED63FD8BD7434DF
- 294137A5AFBE4669492E34B54BD9EE566AFBF9CF711DD5327176EB0FBD3DE654
- D4D60699E0AECD0714AF75CF7FFC72DF09632A6A3B70049EE76795DAF7B89803
- 77C3C52EF6FD5E8F464B1A25C7D7D2D6103AD0B6A7E681FAA7036DE19D9E1AA5
- 49F528D554D3BC8A2BFF78177F86BF83BF8B7FE35F1FD81A6AAFDBAE35375710
- C39FD0C7464B16F18619866EC633B703AB2B37EAFAF45E93A918AB3457B017BE
- DFB2E9A660741277AFA8B46CD2517D152C75B5AF9B8B45919E60E9EAEDE1462E
- E600638D5DFEBBBF2BCB7B22CA7608004D8EE5D61D1D149919E8B7B5F68FB1FD
- 69A535BA2FC6F77362E61F23F960300F2E4E2371337DAA949B7C423BF7B436FC
- 74CF8F6A9FA8FF5160857A3F3CABEDA534FC0CFC2CFC4CFC6CFC0EFE23C741DD
- A08EB8380DD429EA968B4583658C65CDC51C6813681B5C2C0AB44DB4512EE610
- D972B950960EE025D3F4413355C7C51C897E6AFB928FC0B6CDEDF0D096D35AC9
- 817147028906B76C7D4A14C9C76D6A4389CB17856BDF7609B46F5EBDF2A77BFE
- A2F201F777DD6E77C9669DF1B3F13BF0BBE03B57F16447411DA1AEB89803758A
- BAE5A22D9237AD658D3681B6C1C5A211D928DA32DA3417CB8AB2740069429AC0
- 6B5ABAAA539793B6C370B9EABCD642662493ECB67F951746EED52ABDCF703187
- D74DCC5877CFA7F0458EEEEDC716ABFEC5070F563F52F5B2EA763BB6857636F0
- BBE03BBF8FDF6DB7D5B4C2B2BA429DF1841CA85BD431178B2679ADEB065ED9CE
- C51C5ABDD7F6C61D918DA22DA34D73B1AC28D72180F54C3E34029173676D8D41
- 31D027F35B6FF6D1C749BF1371FD7D6DED4F8B027866C688E361BBBCCDEBEA1A
- BFBFF9479E7A754E1B59D25142A25708193D3E4606DFEF21B7DEBE486EFEDBD9
- EC0BDF631AFE0C7F077F772EE077631E302F3CC9115057A8332EE640DDA28EB9
- 583458D64684F473F11B7CA4196D844B4581360A155E344C75F4A0935394A503
- 5005CAD2E3246A37A8A36F635B9BC2AC139FC98181EBFC6DD1645B7F9FFE2817
- 7360749CD8954B8EC68C0F3EB06763DD23D53F54BD5EF1D6624E72142AFC49B0
- F4FF7E92DC7EEB28899C3C4A625D5F91D4E04DA24F4488118F655FF81ED3F067
- F83BF8BB37E06FF06FF1336602F38079C13CF12447409D89220BA18EB550D8F6
- 1EFBD42D6B99A36D04DADB2C3B4F0B016D3419B72E078A6CBA1C283B0780D154
- A0965B2E7A48DE24B637E7B86ADC96092C3C2E9AECEFB37DAAD0DBD2F6982830
- 26BB153F67A6929623A9C552F9D8FEFBAB76BABF4D7C3E4BD8B23BC46F1132F0
- FB2B64E80F50E1AF5C24AC88E86126FC0DFE2D7E067E167E665E202F9827CC1B
- 4FB10DEACCBC11B39CE4431D7B5B5A2D8EB65012FD7D43C4B06EDF55ABDCB68F
- F126FBAC0E006DBA1C2305959D03F013B202C74C5CCC11ED4ED90AB4983DF411
- B0CEC69A5172C36EA8AFECCC7F0DB54413C218FDF19EEE4B5CB44DF8B1FD3B42
- 1B956F71D1421A5CE4ED77BBC8C8874761D8E1DC88033F0B3F133F1BBF231F98
- 37CC23176D93B8D6790983A0723107EADAEE8A0096B91E2537B9F80D6023760F
- 08C5AFC5440E80A26D73B16C283B07A00B9404CA3327AF9CCD1B68722E78DAD6
- AF8687B578E0D4E0D04C6DDB9CC0BBFA44D775256FA7CE3B15CAAB62EFFE4D15
- 1B1561C83204C7EEB7DFFA8CA4471C898C2E043F1BBF03BF2B1F9847CC2B176D
- 8131063102321773A0AE51E75C2C1A51D9A38DA0AD70B128A29D17702F89654E
- 4964DB0B4DD9390070BD96EEBF6E92184DDB1BFF6BF5B5CDFC6D0EDC169ABAD1
- 6FBBC6E0459DFC6D0E8CDB9FECED72645BB16FDD8686F0C6D4412E4E039532FC
- C9ADECD81D4318951CF80EFC2EFCCE7CDF8679C53C73D11689EBD73A50975CCC
- 21D279A160D98BB6068B6CA510D0563326B1345822DB5E68CACE014069589494
- 1EB32AB350B420B3C4DF6371326AF7CA2ABCA21B6FE9E5628E4C82763931F657
- BC0177C581C6EF88C6FCB84E36F8FE5592E8BBF675C23C82DF89DF2D5CD784BC
- 629E31EF3CA5685087A84B2EE6409DA3EEB9581458F668035CCC21B2954211D9
- ACC8B6179AB2720078E537FC6789D89A1AB6E700B2633A8F606521AADB6EFD7D
- 6B9B77890EFC246FF475F0B7B6A87976DB231E9FF54834365B4338261FB404A6
- 9D37F0BB310FA29E00E6B916F2CE455B8874893AF73535DB0EF12DB401B015BB
- F707E4B1D930B7F1B2A1AC1C403563D5604C9609C0D4F594ADFDF9AE754DF5F0
- A1D688BFA323F66F89A9F45866BEB377F539B0EE8F27F5BC15E25802239FDC2C
- E9787FAE601E86FF649D4B433C90777C062E160DEAD24DB4312EE650C39EEDFC
- 6DD1886C006DC5BB61ADAD218CC866D1B6438CCDE9BEC7F9A2AC1C8041883016
- DC6477A72D07A085AB84BBE49283376D555235100808BBFFE3F1ABFCAD2DC20F
- 871F87EEB47545E43276C11D0B57689BE48D9E6C9E2C40DEB3CFE0007A346679
- E0EC3000CA808B4591CF06F2D9CC5CC967B35098B6EF247092B272002A21966D
- 9EE03533663C626B979E56E1B11426D349CCEEDDFEEED5CD9B44DD7FBCA597BF
- 2D9A8A1DBBD68BB6F7666284444E3B7262D951304F98B77BC167C067E162D188
- 748ABA77AF69B6B57F1F6DC0D4AD4B8D229B2904B459305A8B7D896C7C2129AF
- 1E00A596B12E68D0FE449A9F59BA73664218C9B5205CA14ACBC6225CFBFFFA8A
- 6E7B78B7ABC22015A39F41E7623E66FB0B05F294CD9B807CCF5208A853D42D17
- 73B82A2A5BF8DBA26109D3728047643385020EC062BB221B5F48CACA01288C59
- BCA33969DF01504D10FA2BA6DB3E59A804AC973F1893DA009894AD433F789EDF
- EB715BD68C7137DE424EFACD06E62D66DD614FF059F099B85824CCFC5AB7D311
- 9541A1886C4164338522B25D918D2F2465E50018A516E5E893D635E042C8AE00
- A8D66E971E9FB415948312974A3DD648BF9968D4FEC6A2CD35F7F1B7D398383B
- C30E9C32217A4EBCF891EF990A418F452D0E00CB00CB828B4521B405B019BB3B
- 02F3D86E05FFBF2C282B074019B3DC140BE34A5B0E405BD1289C583463315B27
- 0B5D2BEA57241338A49B8E3119B137FBAF52EAAF4C5B0ED6A4C640170E6EEF2D
- 1599F151E101A2EC33C1B371B128F4A855B758065016B6561ACCD8A4D016F2D9
- CE5CC963BB651517A07C1C00631446B6160700DD285B13755A558570CC654427
- 6C3900AD2A2C0C8891898C5996AB0A21D0B271A52892CF54E7E2B92334D66555
- 4136B2103C1B178B221D9D10C68380B2B0F5B946248F03C8633B734564BB591B
- 075BE7E28253360EE0BB793C6366CABAA7BA1014AF47B84C04AD89ADA545C5E7
- B7ECEAF2BA9498DDDD7FEEB555C27DE889EB96CD70654BFCBA38B45EBE679B2B
- 0C7A6DA26DC1A2B228047D2A92106D09CE673B73259FEDBE24E8E92E1465E300
- BC7994A2C762B66E00A11E97B55721B831B650A8CB6D098291498B6FBF2D044F
- 2DB34CFEA5A1DDC3E3B98B053C7E9C12B4D56A2DB3BD29C8649A75C6DEE3B6BD
- B986E982EEBAC763ABBB3E83ED96CD30A06C1C00B84AE159697D3C62CB01104D
- F3F37739A8030E40710B562C92F66316A85AC6B2FE9C5CF80D7F059312E4D9A3
- 656C470ECAA4A8C5B5508DD9DE5C23B209AA29F61C401EDBCD67EB0B41393900
- E1B8C848256C2DA929AAB567C10C7B138B08D398E5F8AF62246CC5FAA76E97AA
- F87C96CFCD446CAF58CE3BA23CE3B3E13372B128443A169545A1886C42D1982D
- 0790CF76F3D9FA4250360E40234418E081A632B61C00A8DAA26C53C7A3D9F650
- 1566191F1ABA696FCB72558DD090F5C8E29900BC43BE3CBBC275B696C18C9455
- C7A2B22814276CE25EF2D96E3E5B5F08CAC60164F2E4C56EB950CDDADD62547C
- 8AB5104C8AE5381D660A0FC6CD19AD22249C0731D3B6FCCA82902FCF5A45D0D6
- 049868B24E54168522B20991ED14423EDBCD67EB0B41D9640410760DCDA8BD73
- 00221466DF0128845974C732695B730B8AAA080D79314D00DE215F9E615C6D6B
- 08400CEB074359D8EE523B6113F792CF764101D20148ACD8ED412C06EC3EA3A2
- A8F61C88641AE5E40084DE5209851D2F70E832DA7E6E93506B97D1E5B6D56534
- 532961B3A9B86D07D69977F2E539DF33CE1546544B2F09CAC2B6E374C226EE25
- 9FED82A13BDEDB2896B27100AE3C4AD16C0EEF982E58DE61F69F1BBA8C96011E
- 55ECCDEE1AF1987008A1B8CB66D978CEE4CBB39188D97200D4AD5A9CACA82C0A
- 45641322DB29847CB69BCFD61782B271005082C22DBFCCE3B2974766ED72C248
- DBF6A4916152CBF651D5EEBA71745C18FA4C0BDBDA92BE20E4CBB33E316E6B0B
- B6A26A96B2139545A1386113F792CF76F3D9FA4250360E201FAA477C97FD5C31
- 0DEB1972AA5AC383150AD5A965D38FA9FAECCD70A73386994858E3E087CB2A88
- CC9C70555AF38CCF86CFC8C5E2D0348B8E45655128229B30756A6BF9259FEDC2
- B8A06CE67ACAC60180F6859B68B4AAB03DCFACEBD6E8AC1822D426669A5AB6FD
- 2A5E627B434A4A77594EBC796C87A6987F3C8208F819C3653F06A3C62CFB0844
- 655128229B60B6F775886D171C80ADA18593948D0348526B4B8D6881802D07C0
- 5219CBE72A0E380096495B2AAACB6DD80EF6A0DFA696089B9E4A68A116D14420
- E615F37C2FE9016AFB066685EA96AE85A82C0A856A825E61CA66305A7F20DF04
- 76D96CEC281B07F0BB3C4A7105C5FB03E68A994C898F7A06EDDD026B26E296D6
- 2C9931038AC76BCBB9A4AF8F0A62EA10E25F6B3BF2D5BC912FAFF99E6DAED040
- 2020BA7F5154168580B6409960C7681EDB992B5A85785EE1F53C8DDD4250360E
- 80508ABB39ACAD7585BD6D93FAF8A4F00CB91AAEB4B57D541F8F0823FFB8C295
- B64249C57BBB0659226171868156DB11AAE60D515EF199F0D9B85814EE50A538
- B64324622B4E9A1AAE101F19CF633B734564BB591B075BE7E282533E0E006002
- CFE80AD89BB0D36F0F0837A52B36C349676E0F0D787DD6BD0B6A458DBD136F06
- 63F109B725F697B7067451EDE835FC25C1555593CDEBBD649F099E8D8B45A185
- C216056019A407ECDDEFA804F238803CB63357F2D86ED974FF91B272009431CB
- 640E74A36C3900339D32A09A5A3FD75F616BBCCE48C6602997654CAB55866C9F
- 794F5C1AFD8ABF9D46E5FD8E5EC15F1242DBC551BA9317476DDF94A405ACBAC5
- 32C0B2E06251086DC154A6B2B663833CB66BEB966BA7292B076052C1CC7A8503
- 13763AB1DE2A13D06CAFAD99316A8983AD05F595E0CA6CE935D1DD39984CA56F
- 7331877F1574831B6CFB979281790B086ED54BA7D283F1AB9D96E7290CAAA815
- BAE5E145655028225B6019D3F68A85C8764536BE909495035019B38CB9601065
- DB0198716A197B2A3EF12D448590999CB0C4BE4A6698D75D5F67FB12C8E439E3
- 047F3B8DEAFD1B20F3B6CFBE380FE4A9E6217184EE789E672904D429EA968B39
- 44655028D4A7581C80C8660A4515D8AE22E8E52E2465E500A0BF65510E98BA4B
- F1DB3B0FA04FA686F8DB1C542301EAF5DA9A604CF7F776F8DCD66D9DEEFA7A5B
- D74B2393674F5F33D2694BBEDD4142C2BB1EE252F980798231AF057C067816DB
- ADB448A7A87B2C032E1605DA80A29996FD1B229B2904B459305A8B7D81B1D89A
- 58749AB272008C1061E89B8A96367B5B6C23E3C2C2F436ACB235AB66C4623123
- E3B60E03428175FCAD2D2247231FF1B7D3086D02E35FE3C857388277F5BA6C9E
- 44448E4685CF5028229D9A19F7352C032E16453E1BC8673373259FCDE6B3F185
- A2AC1C4094D25168F12D33C59EB5F68233667AFA86E0432D8750B49A5ADB5D75
- 23923AC7DFE64813BDDA555B6F7BCA3EDED539901A322E70711AB58FAD22EEDA
- 85DF228879A8FB9630423AC1BCC7BB2EDBBECA0875893AE5620E3D92FA92BF2D
- 1A910DA0ADA0CD70B12844368BB68D36CEC5B2A0AC1CC02794E2A92E8B87F4D4
- 114B60CF42C8CEE6A68865A9480B69B66B50A2AFF7946818E05DDD64EBD2CA3B
- 8CBC7BFE53239E100D8D48FDB3AD0B3A2988DF8D7910CD48609E31EF5CB48548
- 97A873D43D178B466803602B765700F2D86C84DB78D950560E000163B2CCBEBA
- ABED3900449FA2965D68D44F6AA8CBDE3C80313E3A261A06B87CACD5EEAE40C4
- 4CC6D2E34723BF238984C570B0F01A9EDA407C4DB62FDF2D18FC4EFC6EA10141
- 5E31CF98779E52348ADBED465D723107EA1C75CFC5A2C0B2471BE0620E91AD14
- 8AC86645B6BDD0949D0300B76B5192A6900073BB440DCD9CD187462CD74BE3F6
- 4FCFEA35B67B01FAE0E411FE36076E59F536B76EE1A22D123D570723573C87B9
- 380D544ADDA32B49F88187A1346DA9686EC077E077E177E6FB36CC2BE6998BB6
- F035B7DC27DAFE2BD279A160D98BB6008B6CA510D0565D8AD501886C7BA1293B
- 07A01162592F8612522A36EEB0D50B48755EBB01FD74CB292C4F43BDAD6BA590
- F8D5AED35E8FF58E79EF0ACF36EA72DBEA61DC61F2C4B1CB9357CC8FB9680127
- E1561C7A08C6E4B6AEB59F11FC6CFC8E7C137E08E611F3CA455B5045553DB581
- AD5CCC81BA469D73B1683CB5D6B2471B415BE1625184DAB6E2F8DFB27225B2ED
- 85A6EC1C401C940415DE3211186AF1D80A279D1DD3C5480F17736821B28A51CD
- 56D3C932C94C6694592A27AE5BFBD7B7D8BE15F70E918F8F9D8D76981F4117DB
- A21FC40D1A5AF16C1BA97DFC6147B70DE367E167E267E37708813C61DE308F3C
- C536BEF56D9B93C4BA4487BA469D73B128B0CCB52A629DBD041BB13BFEF7AE0B
- 5AF28C368DB6CDC5B2A1EC1CC07B8A92026559BA4ADE55F6CFDA6746D3D60BF6
- 54E2F5AD69B2DD6C26BBBB3E11DD5B471BFDF73B31177087894F8F9D9BB8A8FE
- 5E34277007DC31D8F89D8DA4FEDB0F9340EBE6A28E12E3DFE0DFE267E067E167
- E605F28279C2BCF114DBA0CE94D5811D5CCC813A4E765FFD848B45932D73287B
- 2EE630C6D3B6F72CF8D75A6F8D429B46DBE662D950760E0001F76B9DB1F79310
- 53ECCD0324AE74769A143F7E3A9E958D6BF9DBA2D1A391093DA1590CD34C337F
- 60E3E63D5C7484E899935DC39F8EBD6A2693331E56C1433935FBAAC89A1FEC81
- AEFBC324BC071DC27D30EC5945B4CA30DED4937DE17B4CC39FE1EFE0EFE2DFE0
- DF8A0EF6DC0DE4218279C13CF12447409DA1EEB8980375AC47C76C6FA6119539
- DA46ACA3D3D6F0056DD4EB27967E92C8A6CB81B2740080455990512DBC7D87AD
- 137C66249220096299E051C3640D55ED5D5985243A3BFEE8557C162FEFAA26F7
- 39B12FE06E92BD3DC3B77E73E995D4B0719127CD88BB1286511BD121549386A7
- D6919587B690D52FEDCABEF03DA6E1CFF077F077E7027E37E4E15F302F3CC911
- 5057A8332EE640DDA28EB9583458D658E65CFC06B08DAC8DD8006D145A29D1BC
- 8F740073053AAC7D3866E2628EE026EF1C4D333FFA50F2127F9B83E28CFDFA56
- 5B5757237A7422AA4F24DFE3628E649A288196758FC03739AA6F964864867EFB
- F9E1B14FC75F136D1B2E15F85DF89DF8DD98079EEC1034AB2BD4194FC881BA45
- 1D73B168B0ACB1CCB99843641B8522B251B465B4692E961565E9005E57149CE5
- B2B42ABE35F66F818D9DBFD4215A0DF0AEAA6AE36F6D3175F1C2FB9AA259767B
- A515BD3ED0D6BE8D8B8E12EBB874E3D62F4EBE32F145FA77E974DA91E53711F8
- D9F81DB77EF9C5AFF13B79B2A3A08E50575CCCE1766B63A85B2EDA4254D66813
- 681B5C2C1A918DA22DA34D73B1AC284B078080D7B4CED8837DB81AD7D85A56C3
- 168B4D104BB759F1915A4FE39A5946BCB3935D11B831F66B2E4EC3B3C6B7C7E9
- A1C0DDE0387CF017277F3DFAC1D0BFC66E1B5FC2B3DA0E3D859F819F859F899F
- 9D1DEB337B813DF281BA411D71711AA9DEC82B7667FE112C632C6B2EE6409BB0
- DB9B41DB441BE5620E912D970B65EB005C940A9556BDAFD9766CAC64EFA070A9
- CABBAE698615EEB993ECEEBCA0E9EE935CCC914C10D5DFDEFC94EAF1D80A1F3E
- 1B78F67EECADCFFF74E39533FF152BEE6497713433A95FC309BB7C4B8859E067
- F83BF8BBF837F8B7F819F859F6CFF3CF0CEA0475833AE249395CBAFB8B64F765
- E1998842C957C6C9DE5BB6972FF3D9663E5B2E07C039952F2F98E65F83B54E5B
- 52C99864F2EA7F3C62BBAB163EF4F05F291ED2C4C52C78F3ECC4914BEF189311
- DB174DA8C150D0BBAFFDE766DAB08C09DDA6EBC6C4C92FFEC04CC3D67A733150
- CDA5BAAA6B2AD440C0A3F0E3D050E933462C91CA8C0D4F32DD66DCFE22C00D3F
- 957B1EF8765AC958E66114B73A913CDEF177C654D476EC7FB5221CA83CB0F9B9
- 7B77FF9929D21779FBE83F73B16836FC8703ED2EC5B20230F996A2FC237F5F76
- 946D0F0081CA6F595A42057B573515BEB07D0FE981294B900A348CE07D9B1DD9
- BE8B066B5E1BFD27D141213474FFB61D0F73715EC10A9E1EBA1DC1ADBA388EC7
- 17BE4F0FDD8A2C44E54782DB763C24AAFCA83BB367FC174E547E24B879F366D1
- D65F912D140ADAA4A0F2239DFCFFB2A4AC1D00D41CA1F2AAF6AFB53D568F9DBE
- D4095F600D155643D6B9AA6A6C6F3A4212D7BA3B32E3F4F75C9C06F3B3FB825B
- B638BA3F603152B1F9FEBD869F6DE6E234507789AB9DC2F888858265AA5613EB
- A929B081AC2DD8249F4DE6B3E172A1AC1DC03B8A3208BD00CBA68FE03A52979D
- 12B40135332C7523FD191773600BE1DBB4C9B2FFBC58A267CEFE4E33DDC2B57A
- 33E4D9E5BF6FEB2E2E2E3BF0D98D4A752717A7813A43DD71D13658A6A2D61F6D
- 006D818B45A2719B9C0EDA2EDA3017CB92B276000864D0B2334B851E57D5DE07
- 6DDFC293387BEEA2A817E00A936627560410CA74163B7DEEBFB9556B04E12C61
- F71EFF96FB1FE4D2B221FBCCF0EC5C9C06EA0A7586BAE349B6C0B2C432E5E237
- 40D9676DC02655BB1E0CA14D723107781B4B78F772A3EC1D4092904BA0488B21
- 54EEB47ADC42C1431FA9FEA43068856F6393632DB3998825A6CE76FE3FB896CD
- 93A61352EF0FECD8FD2855AC33E04B0D7CC6C0FDBB1FC567E649D3C8AEF783AE
- 50673CC936F9CA327D2379D4EEC11FA4728FD816DD94DADE58546ACADE01BCA7
- 285146E9752EE6F054902A575DA3EDA3B653A7CE5D621962E9A6A93E52E36FBB
- CFB1C07B4664743CF165CF7F7269AA70271BF3B1FB2A1ED8F76CA9970817127C
- 367C469CFFE049D340DDA08E50573CC936588658965CCC81653EF9C539DB4B8B
- 6883688B5CBC9BFED7282DAB00A022CADE01202663966E1AF40A94BAA75B6C07
- F3C0F15FB27B54B8C3CCD35CB543F1071D3BC9971E191C4A5EEAFF4FB8B4C593
- A6A1AB9935C13DDBFFAC949B85160A7C267C367C469E348DEC721FE80675C493
- 6C83658765C8C56924AF8E1DB63FF627046D106D918B3920CD917D0BA5665138
- 002FA53DA050CBDA7C7025A9578301DBCF90B8D871DD8813CBDE02BC45B8E2FE
- EDBBB9E808E9C15BB7D2E77AFF63BEE140C6304215DBD7BC1868BB0FBAC8CE9E
- 1D5818A882CF82CF84CFC613A781BA409DA06E78922304B76FDF29BA09DA8C91
- CB890B5FD98AFA83A0EDA10D723107DAAA8BDABFB0643E581406065D2903946A
- 89000B99D7AABFB5CB76645F247EBEE743680EAC91832B4993779DFD83427793
- 191E1C9C3AD5F57F6AC4258C3D87BBE158ADEFC18A07F71ED2C2D5B62F305928
- 30EFF80CF82CA21D7E084EF8A12E50273CC911B0CC44137F58C6B10B3D1F70D1
- 16687B68835CCC611272166D968B65CDA2696112849C87CC5AF66A57B5B346E6
- F6837FB047A6FF66441F348421B77CADF57BB440A5A363731CE7C68E9FFBBFDD
- CC9DB7AB68D04C6368D7BA9771C6DCA9D062F301E615D7F731EFF80C3CD9023E
- FBE467E7FE2F27C7FC089615961917A781658C65CDC5A2419B43DBE3620EB451
- 68451645F71F59340E00A3A99882595578004FFDD3BB1D1933478F9D3E65A605
- B108A01B19DCBD65BFDDD061F762A6E3C9C8D193FFAF16A3EF88760C22D99613
- 57091EDAF6235FEBC62DB86D96FFA8ECC0BCF95BDAB7615E717D3F5FAB8FCF8A
- CF8CCF8E3AE0C98E8065846525ECFA43D9621973D1166873687B5CCC81365A8E
- 917FF2B1681C00C2183B0D19B65494703B5BA97AEDCF05503D6DC6BFBCF10E0C
- E22CE1B6543F6908EDD8E5D806A13BE05AF7E4E92FDE49F444FFDEEB56F3B64C
- 181D87D6050F54EDDBF9231C5363B86CFEA30507F38279C2BC917AFF43A2483E
- 77C067C467C567766A9DFF6EB08CB0ACB8F80D50A6F18B37DEC132E6294583B6
- 8636C7C51C689B29C6CE707151E0688B361F3C6F9A4FC07F968A38DE45AE0FBE
- 71C4917164F0E13DBBDC8DEE67B9388DD8E5A123C99EAE929C85C70344FE6D5B
- 7EA86BE959B708636CBC4C8276256FF4756446861C8DC8335770661F2FEDC0B8
- FDA2D0DDF7822724E3E72FBEEAD4DEFE7BC1717F6053FD012E4E233D907E77EA
- E849DB91849186170F3454B5125118B90B6F29CA87FCFDA260D1398043A65901
- 99FE09BC9DD6BD04B7AEF7FED78E73E9E888EDC9178CEB56FDEDBDDFA73E62B9
- 90823092993C7DED707A78A0646BBCDE96B6ADAED5D53FD24D7D4EBB113DAA1A
- C98CC7AFA687867AD343C3239049DBAD9C18AAE02DBD7851A7ABCABF21651873
- 0AD082B3FCA9DEB157F098344F721C775D6365C5AEF507C1A22D73252C41BAC6
- FE70E2374E2CFBB943B56AF3FFD4BE1D5AFB7B27FF0CF8F05FBEAD28935C5E14
- 2C3A07808013F816647C3B17734C0E92DB377F75C491D04B4A38ECAB7C7CCBCF
- A84AAC61C80C9298387EE98F7AD45EFCB899C05B6B025BB71E7485BCCF26CDC4
- 9CF722785D34694C6A037A2C3AA047224399C8D898994A163526C5C8BCAE7075
- B5160ED76B815023DECF2FBAA23B1F18C32F134DBE1BBB70E1B013C13CF2A185
- A0ACF66D7E1A9A04CB7D7CCC2013137FBAF48FE6F8789C27D962D58F0F345534
- 90155CFC064ABF7C8BD2BCF736942B8BD2011C34CD40107A01D0CC4DF3F6F030
- ACEFB5C10BB19E4E4726963C6DAD2B02F737FC045A7DCB528F91226313C74E7F
- C492A5336C440B55867C6DED4F6B3EFDD1B974B345785D4A2C9356A366924C29
- 462269A4CC04C63EC0E07E8AA2AA8CA81A71AB6EAA6A6E0C18A07849D0E53642
- C98C595410561C9E60F45E0CE0E9440CBF99C0EBBD2BF7EF7A5CF5106B300E18
- F7C7BE1CFC65AAB3CB91602681756DDEA6971BB6424B3FADDE406F2003639A5F
- 1E5614DB7124E69B45E90010E805EC85CC5B0ED1245334D2FB9F3F75EC086670
- EFEE6DEE26EF212E4EC34C9091C891531F31C3FE7EF2D9C83A82D6B647B56AFA
- AD64CA7A5946398037F6E863CA9144D7E58F304C3A4F2E1954F5A8E103BB1F17
- 85F842527DE97762274E3A765741F3DF3ED2E6F50863FE7D0E5D7FDB31051682
- 45EB001E654CAB62ECAF40F996DD65A36748F7F00747C4076F8A20F4C481C7B5
- 6AB69F8BD3D027C9EDC867273E2EC58CB6081C1AF837B4EED21A2A0EA8AEF486
- 84207AEE7C824B7A785127DED587D77595B2AB7F37B8DC177E68EF635A85A03B
- 0EE863F458F4C3231F71D136754F1EA8AED9495AB898032A50749CD27F2EB75B
- 7FE7CAA27500C8F74CB3159ADEEF703107D4C44CCF3F755C488F8C3852283829
- 58F5CCDEE7950011460B422710FDFCD4A7F3D113B81BB5AAA6DAD7D4BC5BABF4
- EC50DCE975F3E50CA0C5CD684977AF11499DC32BBAEDDED25B28D8F2871EDCFD
- 48BECA6FC6C8C5F1F74EBCE5C4A41FE2AEADD5D6FD75FB56A82C9609469590DF
- FF56511CBD14653E59D40E0081A1C04BF01096ADBAF14932D2F75F8E5CE3A26D
- 14B747AD7CEA811F521F119E10CC0E078E9FFEB8D47302F9500381807B4D73BB
- ABA2B24509B00DD493599D6F234EA1787DC430D2AE3E638A5D31C7C62EA7FB7B
- BB8D74DAF6D5DFC58063FEF0BE5D8FE5EBF6B304E99978FF8B579D38E67B87A6
- 7F7F60BDBF42104998901BD0F57F9D8B8B9245EF005E32CD6AA8717F016F2DC6
- 3E7C8C748E1E3D627BDBE71DA8CFE7AA3CB8EBCFEF0D267A079C189C3A79E953
- 7DAA74AB0373855297E65E51DFA886C38D8ACF5FAB78DC354C6555AA8B05A992
- DDA8430DC6B2AB0B2AA5B84AC09849E346864E51838E9BA9F4A899888F1891C8
- 40FAF6D000639905EFE2E216DFE0DE2D8F0A27FC000CEE3971F8F4BF3A795949
- CDC307C275FB89E8CE0803BA03AFBCAE28F3DAFB719A45EF0090174D739F49C8
- 3E2EE6C0A1C0B55F745FCC0C0F3866105A45C8137C7CDB5F286E22BC569CE924
- 36F5E5B54F4AB94F603982EBFCC1FBD73F4A356BDC7D04B7F94E7D74FE157D32
- EAD8365C3CEBBFFEA72D5B445D7F186B1D7F43518E7371D1B2A013484EA151FA
- 051492E546612CB8553F6A852EBBBDF881778306868686AD0D4F9A061A68C5AE
- F54F397D827039E35DDFBA0A37F9E4ADFC50164E577EB419B41D51E5475B439B
- E3E2A2664938003C7A09551C2F8DB48CFB70D9A6E1C5076D070EB91B34B4AFBB
- 9A796E7CA1D05BDD547FA062E7DE6D4E1F205A4EA0EE5087818DF58F804E2D15
- 11C98EF9A12C9CADFCB8DDF7C106D1921F8047D3DF5F2CC77D67634919E70B8C
- ED628C59F682C343B25B878D8E89B3C71CDD838E1383A1271F782EDFEA0062C4
- C9E0D4D94B9F9772D7E0520477F705776C7E5078B08783B3FDD10FBE78C7C909
- 3FA472C7FEE0CA836A3B0C212DF583527AE44D4A1D3953500E2CADD68931FA3C
- 63DF837796B0536021E9DE5F745F72723E00C125C2CA6FED7B4CAB660FF1240B
- 2623A978D7F017A9AB9DC2002092E97836B4ADF1B7D63DA050EB71DB3BE863F4
- B3893F1DFFD8A9A5BE3BE0B8BFF9A72D9B5522DC75D9FF16A5BF052FE0E8772E
- 244BCB01002F3316CC30F6975042963DEB78AD58F7DF1FBF4CD3CE1A0D92DD31
- B8D6FB6D22D8367C874C84F44E9D3F7FD68C4D3A7A067EA98031FC308C973084
- F71D28D1D3D7937F983A71EA3C4F710CE676D196BFD9B74974C30F5494A48BD2
- 7F81AE7F494E322E144BCE0120D00B68A68C3D2FEAC24D8D92A11BFF78C4763C
- 38117876C0BFA5E165E101220EF60652D7C6CFC63BBF2ADB0B2317028CDEEB59
- 5FB563A6561F0FF6C42F0EBEE6D4DEFE7B59FDEF0E34076B8431FEA06F49DF82
- D6BF2476B3902C490780E43B2B804CF491FE81578F0C70D15194AA2A7FE5439B
- 9F131E25BE0B2341461357FA4EA706FA4779D2B2042FEDC0B8FDA2D0DD778347
- 7A273EBBF48E53A7FAEEA5F187071A2B9BAC4347041A9245BBD77F3696AC0340
- C0091C8207B4DE07070C9F25D7460F1FB12C1D3A01CE0B54ECDFB1D3BDD27D70
- A6210182C382C4E5CB1732E3A34BAA6B391B78579F7FD3A62D5A58BCB3320776
- F96FA50F4F1E3B7BC6E9F1FE1D6A0E1EA8ADDB21B613F8C26B50F9DFE6E29263
- 493B80674CD3E326E407F090969D6350B06CE8137265FCC491921D5775AF6DAE
- F3DFBFFAB97C9B86EE8047738D51D233F5D5A58B4E5C4D5ECEE015DD7803335E
- C22ABAABEF6E70730F86F14A5FED2D59C4A3AABD0742F58F9236C88868497C34
- 45C86F16538CBF4259D20E00799EB1308CE07E006F2DC1220063E070EACAC4D9
- 93256B7DB137107A78F7035A83FA18287BC6F3FC59471021FDC96B3D1DA9DBB7
- 16F516D37BF1AC5859ED5DBFAE5D0D9335B3557C70CEE9CC20FB64F2E8C993A5
- 6AF591CA1D7B828D073D1BE1ADE8CC448250FADF61DCEFD856F27264C93B00E4
- 65C65664187B092CC9D21DC75062B7DE8D5D99BA70A6A42DAF6BCDAAB06FFBBA
- A7349F705FB9053C5C94BA3DD19DE8BAD2C78C85B9B7DF2E5475A9BED68D4D9E
- 15952DF90EEFDC8B9E209D89733DEF3B11BA7B26825B7706563E1BD808CDBEC5
- 26A052E82E4A5F7F8DD2924C369613CBC20120DF636CBDC9D873E0042CCF3C5F
- 4E00F16D695FEB6DA9798ABAF26F70990623197D9CF4A706067A13FD7D43F315
- 77A05870F79E6F4D53BDA7B1B159AB226B40DBC21D7CF78277F5E1156D784B13
- 4F2A19B3547EA650FACE6F2975EC246939B36C1C00F29C696E86423FC8C57B31
- 6E7D607446CF1C2B7950C7EC24E103DBB7BA577B1F8691A7F0649B108324C119
- DC4C8D0CDD4ADDE81F9CAFE01BB381414A3CABD734786AEB5742A55F051DEAB9
- 5FA2629231BCA5172FEA2C6577FF0EA19DFB2B563EA9622F4C78541A1A83C3EF
- 284AD9DFEAEB14CBCA0120CF33763F61EC312E4E03ACCF1CFA8474967262F06E
- 702BB16FC7F62D9ED5EE870A720400CE17B03819D527F4DBFAD8C86872F0E6F0
- 7CC522C033F9DE8655755A756D8D56A9ADA07E5233DBB8DE0254FCD48DF46778
- 3FBFD35B79F331CB841F3C18FD18C6FC962BE89632CBCE0120874C73373CF8C3
- 5C9C063A81B133E49A9321C566037B04C1EDEDADAE35A17DF9620DCC0533A34C
- 997173CC4CA4A3FA542C6A262663466432566C7C022D18F6A9E18A80E2AB0868
- C18A901AD0C2D4AB841557F13109F1E45EA63F7A7CEA5C47D77CB4F877C0905E
- D53BC9FA7C951F123F7B435196C409BF4258960E0079D1341F80EE5EDEFDFB13
- 3DA47FE0B5D26C169A09DC4DE86D6ED8412BC91630CA3987039F15183E3083A4
- B32F460C66421B6CF0BB1655E2A20A81A12F51A94ADCF82AA81B3F0BA0E7149B
- 201793BD83674BB58B6F261A5F3ED058B94EBCC907814A70EC4D4539C9C565C5
- B27500083881ED609CDFE2A285C43819EAFDD5F1EBA5383B301B187D28B06D73
- BBABCEDBCEFC64BDC2C463D672C5A4E05E12A4571F4A5E8A9DBFD4E164949EB9
- 827BFB9B7FBC6FADAFCABABDF70E4BED745FA12C6B0780E0C420D4AC27A1860B
- 75810788FA7ED5DDEDF429C242C04B4A7C1BDBDA5C35EE561220EB1CED193808
- B6F424467A32A3E9AEC495CE4E33B27047A0F1545FD38F5B5A44077B10286C06
- AF0FA1DB7F91272D4B96BD0340C009B4801378069C8070DB2E1E251E3A6C743B
- 1D4FA01870E2D0D3B67EB5565FDBACF9D96AE223ABA0108BBA30C42EA0AF34B4
- F237F538BDA10F8DF4A63AAFDD98AF09BD99C0F3FCF507552C53A15E405F3A64
- F2BD7714A59B272D5BA403E064370B11728831F1CDB660EC2CD245FA06DFF87C
- 10EC87A72E3CE8105CCD4D755A55558356E1A957FCAC81BA945AA2387C7988A9
- 4CB18C3962C6E9A03E991AD2C7C70733BD7DC3E550E1BF41CB46F209B7922630
- 6CA16D43973FEE22E4EDE5B0C9672E48077017CF9866089A8C1740297997E4F0
- E6A19BBFEEEA59C821C15CC83A86C6BA4A355C55A5783D01EA717989A6F9158D
- F928250A5308FEFBBA8534499A9AC4648C98A64E1344D7E32C95499AC954CC88
- 8C8F67068627CAABA25BC12E3FC6F0CB13C62B0B38F1B134216FBEA728F3B2CC
- BB18900EE01EF801A2A74131C2D36108185266E418E97132E4B8A478C20F1DA8
- 6C7828BBC49777D721FCAC2709DDFEA57CB0A718A403C803C6135008D907953D
- AF8EF0F291DBFFDAD1978E38730391A430DCE15A6DC59FB737892EEDB803141E
- DE957E7CA99EE7B78B740033C0230BE1E460DE3571EC0D8C9D21D7E773E39024
- B7B1672D18F04CAD7E9251FADE528CE4E314D201CC02C6184C33F634BCCDBB91
- 04C1B981E1B76FF7397535B9440C5ED15D776845D34C637D4EBF9BD23F2EB518
- 7E4E231DC05C608CBE40C84EC6B23704E7DD9003CA64D1413238FC56C72D392C
- 7016ECEED73DDFBE32D4401A661A960106A5F4D89B849C214B287A6FA9900EA0
- 005E344DDC517610C694755FA788819FEB135DE4E6C8BB67868D640C4449B1A8
- DE8052FBECCEBACA56B24AC9B34FE30E60CC23F07AFF0D4519E2499259900EA0
- 407ECE98721E2F2021642FBC663448DC4014E9A0B786FE786A98A6E3B2352A00
- E6F6D3FAA777D785DBD9CA7C1B7AEE00468CBDAD93DB293DF577944A875B00D2
- 0114C97718AB52197B021438EB1D806091A9F10E3A30FAE1E951331E2BEBF5F4
- 8546F107D49A2776D554B5B3C6B96C7906AF7A03FAFC1FFE9ED2719E242900E9
- 006C72C834378212F168B170CFF9DDE0D060AA9F0C0D7FD03D58EE1B89E61BDC
- C853F7644B43700DA99FADABCF9984CA7FF46D45B9C26549114807E0008F32A6
- 5531B6139489478C670D8105866BA626C9F8C449323C7EFAF368396D2D9E5F34
- 52B5EBC150E51E52E7A92055A03FA8FB3303BF804733BF18A7F4CC2794CA8956
- 9B4807E020074D33E023640F28152F0BCDBB5A7037301E484EF5802338767D34
- 79B32FCD939734DE554DEEAAFD6B6B82EB481D2869AE71070CA8F8171330D63F
- AC284B3A74FA7C221D400980614105A174AFCAD87DD02398B555BB031E3D9EBA
- 4AC6C68EF78E6506FA97D410C1D5B8C655BDAFB93AB88154E73BA22B029467C2
- 18FF2BC2D809E8EE973C5EE372433A801282878B3C94EE5418DB3C97A1C1DD40
- 57602AD54F27263A9291C9F367E3F3193ECB193412DCBA2D10DC14A8F4AF2561
- B7420A3A9D885D7D93D24B29C6CEC8C33BA5433A8079E0C78C79A38C6D851A7C
- 3FBC023C79CEE0E4A11E27D1E44D3215ED4E4D4E5E0187B000518A6602A3EF54
- 6CDCE10FB5782ABCAB48D0E52715605C05393D04FE2606AF2F43945EF815A572
- 576589910E601EC13D041718DBA0936CBCBF26A8C145E91FFECED44D124B8F91
- 786A185ED75389C9EECE84198FCCCB12A3E20FAB152D6D3ECF5A8FCF5347FCEE
- 6AE2D71412808799F370E76EE0EFF0C04E9F0663FCAD945E956BF9F38774000B
- 040E0FBC846C86B7ED50A1435FA7DA033E27932124654E929401AF7494648C04
- D10DF85F8FC5F4CCD494614E8D19B8E8A0A77576C7616085D6DC1AC5C5372558
- ADBA8241550B043435445CAA8F686EFCBF827814784193EE01A329B86517019F
- 835DFB0E68E62FC96EFEC2201D401980D188D28CE175E27861C59C27C8162938
- 91D7E9A6B44B46E55978A40328339E33CD06289466FE5A51EC30A15C80CC3378
- 86DBF0EAC5D73B8A32C87F24290316B5712D7570F27082B1261810AF52095909
- 15A8B6DC1D025678F86F14F27C53815725A57D7232AF7C910E601181E1CA3C94
- 3632C61AC021D49A94D651C62A17CA29606567944E288C0D1B78128FD2C11463
- 0332ECD6E2413A80450E6E430E315603051906A7103228AD840A89938A3897E0
- 07E760EB0E01F85CACCC71784D82C389C26747A1759F80CF8D44291D95DB7117
- 37D2012C75A08DFE2E213E2F0C27A026BBA0C5CE3A04E839A82E7EE82643880E
- E9D91501484FC12F6492D06DFF1D210919544322914824128944229148241289
- 4422914824128944229148241289442291482412894422914824128944229148
- 2412894422914824128944229148241289442291482412894422914824128944
- 2291482412894422914824128944229148241289442291482412894422914824
- 1289442291482412C9728390FF1F97ED6E34D64226CD0000000049454E44AE42
- 6082}
- FileName =
- 'C:\Users\Programmer\Pictures\Icons\'#931#969#964#942#961#951#962'\256x256\icon_simulati' +
- 'on_256.png'
- end>
- Align = Client
- Size.Width = 444.500000000000000000
- Size.Height = 313.000000000000000000
- Size.PlatformDefault = False
- end
- end
- object ltSendText: TLayout
- Align = Bottom
- Padding.Left = 5.000000000000000000
- Padding.Top = 5.000000000000000000
- Padding.Right = 5.000000000000000000
- Padding.Bottom = 5.000000000000000000
- Position.Y = 480.000000000000000000
- Size.Width = 909.000000000000000000
- Size.Height = 48.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 2
- TabStop = False
- object edtTextToSend: TEdit
- Touch.InteractiveGestures = [LongTap, DoubleTap]
- Align = Client
- StyleLookup = 'editstyle'
- TabOrder = 0
- Margins.Right = 5.000000000000000000
- Size.Width = 823.000000000000000000
- Size.Height = 38.000000000000000000
- Size.PlatformDefault = False
- OnEnter = edtTextToSendEnter
- OnExit = edtTextToSendExit
- end
- object btnSendText: TButton
- Align = Right
- Position.X = 833.000000000000000000
- Position.Y = 5.000000000000000000
- Size.Width = 71.000000000000000000
- Size.Height = 38.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Text = 'Send'
- OnClick = btnSendTextClick
- end
- end
- object ltMessages: TLayout
- Align = Bottom
- Padding.Left = 5.000000000000000000
- Padding.Top = 5.000000000000000000
- Padding.Right = 5.000000000000000000
- Padding.Bottom = 5.000000000000000000
- Position.Y = 328.000000000000000000
- Size.Width = 909.000000000000000000
- Size.Height = 152.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- TabStop = False
- object memMessages: TMemo
- Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
- DataDetectorTypes = []
- ReadOnly = True
- Align = Client
- Size.Width = 899.000000000000000000
- Size.Height = 142.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 0
- Viewport.Width = 895.000000000000000000
- Viewport.Height = 138.000000000000000000
- end
- end
- object Splitter: TSplitter
- Align = Bottom
- Cursor = crVSplit
- MinSize = 20.000000000000000000
- Position.Y = 323.000000000000000000
- ShowGrip = False
- Size.Width = 909.000000000000000000
- Size.Height = 5.000000000000000000
- Size.PlatformDefault = False
- end
- end
- object CameraComponent: TCameraComponent
- OnSampleBufferReady = CameraComponentSampleBufferReady
- Left = 184
- Top = 128
- end
- object MultiView: TMultiView
- TargetControl = ltContent
- MasterButton = btnMasterView
- Mode = NavigationPane
- NavigationPaneOptions.CollapsedWidth = 48.000000000000000000
- Size.Width = 250.000000000000000000
- Size.Height = 50.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 5
- object lbUsers: TListBox
- Align = Client
- Size.Width = 48.000000000000000000
- Size.Height = 528.000000000000000000
- Size.PlatformDefault = False
- StyleLookup = 'transparentlistboxstyle'
- TabOrder = 2
- DisableFocusEffect = True
- ItemHeight = 48.000000000000000000
- DefaultItemStyles.ItemStyle = 'listboxitemleftdetail'
- DefaultItemStyles.GroupHeaderStyle = ''
- DefaultItemStyles.GroupFooterStyle = ''
- Viewport.Width = 48.000000000000000000
- Viewport.Height = 528.000000000000000000
- end
- end
- object Client: TncClientSource
- Port = 17244
- CommandProcessorThreadsPerCPU = 1
- CommandProcessorThreadsGrowUpto = 10
- ExecCommandTimeout = 2000
- EncryptionKey = 'SetEncryptionKey'
- OnConnected = ClientConnected
- OnDisconnected = ClientDisconnected
- OnHandleCommand = ClientHandleCommand
- Host = 'LocalHost'
- Left = 64
- Top = 128
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ Caption = 'NetCom Video Chat Demo'
+ ClientHeight = 576
+ ClientWidth = 957
+ FormFactor.Width = 320
+ FormFactor.Height = 480
+ FormFactor.Devices = [Desktop]
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnPaint = FormPaint
+ DesignerMasterStyle = 0
+ object ToolBar: TToolBar
+ Size.Width = 957.000000000000000000
+ Size.Height = 48.000000000000000000
+ Size.PlatformDefault = False
+ StyleLookup = 'toolbarstyle'
+ TabOrder = 1
+ TabStop = False
+ object btnConnect: TButton
+ Align = Left
+ Margins.Right = 5.000000000000000000
+ Position.X = 48.000000000000000000
+ Size.Width = 105.000000000000000000
+ Size.Height = 48.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Text = 'Connect'
+ OnClick = btnConnectClick
+ end
+ object edtUsername: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Client
+ StyleLookup = 'transparentedit'
+ TabOrder = 2
+ Size.Width = 799.000000000000000000
+ Size.Height = 48.000000000000000000
+ Size.PlatformDefault = False
+ TextPrompt = 'Enter your username'
+ OnEnter = edtUsernameEnter
+ OnExit = edtUsernameExit
+ end
+ object btnMasterView: TButton
+ Align = Left
+ Size.Width = 48.000000000000000000
+ Size.Height = 48.000000000000000000
+ Size.PlatformDefault = False
+ StyleLookup = 'drawertoolbutton'
+ TabOrder = 4
+ end
+ end
+ object ltContent: TLayout
+ Align = Client
+ Margins.Left = 48.000000000000000000
+ Size.Width = 909.000000000000000000
+ Size.Height = 528.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 2
+ object ltCameras: TGridPanelLayout
+ Align = Client
+ Padding.Left = 5.000000000000000000
+ Padding.Top = 5.000000000000000000
+ Padding.Right = 5.000000000000000000
+ Padding.Bottom = 5.000000000000000000
+ Size.Width = 909.000000000000000000
+ Size.Height = 323.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ TabStop = False
+ ColumnCollection = <
+ item
+ Value = 50.000000000000000000
+ end
+ item
+ Value = 50.000000000000000000
+ end>
+ ControlCollection = <
+ item
+ Column = 0
+ Control = imgUserVideo
+ Row = 0
+ end
+ item
+ Column = 1
+ Control = imgPeerUserVideo
+ Row = 0
+ end>
+ RowCollection = <
+ item
+ Value = 100.000000000000000000
+ end
+ item
+ SizeStyle = Auto
+ end>
+ object imgUserVideo: TImage
+ MultiResBitmap.Height = 256
+ MultiResBitmap.Width = 256
+ MultiResBitmap = <
+ item
+ Width = 256
+ Height = 256
+ PNG = {
+ 89504E470D0A1A0A0000000D49484452000001000000010008060000005C72A8
+ 66000000017352474200AECE1CE90000000467414D410000B18F0BFC61050000
+ 4A6C49444154785EEDBD69705CC795A89979EFADBD5028EC0417102401901037
+ 71114951A2244BA216DBA224B764BBDD1D6DBB9F67625EC44C77CCC49B989F8E
+ FE39332F5EC4EB9988F7625E77DBEE68B9F52CB5B5D9962C4AB2245214497111
+ 3781044002044882D80B05D47EEFCD39A7942C11BC5900AAEE2DA000E4C7A860
+ 9D045095F7E4C993FB4922914824128944229148241289442291482412894422
+ 9148241289442291482412894422914824128944229148241289442291482412
+ 8944229148241289442291482412894422914824128944229148241289442291
+ 4824128944229148241289442291482412894422914824128944229148241289
+ 4400E5FF4B962A8CD19718F3C23B9F41886612E23128A52A218ACA980B7F05E4
+ 0CFCCC04992984A4E0673A24275EA734492865F83B92A58974008B9C4719D342
+ 8CD5404186A1E286A08287A0C686E047155099FDF01E2B7FD1C0E726E133E3F0
+ 7612DE47E133A3E02CA2F0B99128A5A39F508ACE42B248910E6011F13263EE34
+ 212BA1A16E80CA5E0B95B01692C3F0FF8294237C297C3589C0FF23E01446A063
+ 31E826E4D66B944236258B01E900CA981F43D77D82B12668815741855F89157E
+ A12AFB5C41A7C01DC22DE82DDCACA4B4EF573894909425D2019419CF99660314
+ 4A337FAD28F70A3F1B907906CF701B5EBDF87A475106F98F2465C0A236AEA502
+ 567A682DDBA0305AA192E0F87DC902CF88F3075DD0ABE994CE60E1910E608138
+ 649A3849B705DEB63B55E9E17332194252669CA4F408496762246D4C115D9F84
+ D7444CD71353BA393566E01CBF6EEACC8C46A0A74E88120AAB9AA251A2C1FB60
+ B5AAF9829A5619D0B40AA2A941A2B902C4AD85895BF1138F8B100F184D76F5C0
+ 2EE80CE0BF0E700617DF5694C9AF5325F3897400F3C8CF1953CE30B65EA1740B
+ 656C2D54D8A2F40F7F67EA2689A5C7483C350CAF1BA9C4E4D5CEC49D0A5D6AD0
+ 61546C68F379567B7C9E3AE2775713BFA690003C0CF8B4C281BF638CD2EB2663
+ 1777527AEDEF28059F20990FA40398075E324D1F34BA5BE1ED76A8BC81AF53E7
+ 0ED4065D8F9368F226998AF6A42627BF3A1BA7E90C7C54F9C0DC2E5A71DF0E7F
+ 689DA7C2BB8A04353F098137803E45618041C6E0BF73F087175E5794C4D7A992
+ 52211D400979C634436E42764145D80CB5B5A0CA9026642AD54F27263A9291C9
+ F350E1CDF2AAF0B3C1147008DB76F82BDBBD61CF1A56097A08F21FCD09304CE8
+ E4904BA087D3EF290A0E152425403A80128015DF47C85E78DB0E463CE76E71C6
+ 24935357C9D8C4B1EBE3C9C1BE25B596EE6A5CE3AADED75C1DDC40AA5D0AA9E0
+ C9B302CAC3E1400774054E4847E03CD20138C841D30C40C5DF034AC5C93DF5EB
+ D49981417B72AA870C8F1FBB3E9ABCB9B42A7D3EBCAB9ADC55FBD7D604D7913A
+ 50D25C772A1AE00C2E4D812338AC28384C90388074000E80DB71AB18DB09CA7C
+ 009AAB5967C871122F3549C627CE40C53FF139B46ACB7537AD46AAF63E18AADC
+ 49EA3C15A40AF4376B6F097E01C7425F8C537A466E43B68F74003679C134DBC0
+ 200FC0DB59BBB5389937D54F86863FE81ECC0C0F6478B20470D535BAEA9E6C69
+ 08AE21F550C9E7325F8267138EBCA9289D5C961481740045F23C6361C2D813F0
+ 76CDD729F9818A9F1AEFA003A31F9E1E35E3B17959AA5BAC28FE805AF3C4AE9A
+ AA76D6088EC0C39367A25FA7F4A3DF533ACE65490148075020B8967F9EB15DD0
+ EAEF85D78C2D15D4F474A483DE1A3B7C7AC448C670324B324798DB4FEB9FDE5D
+ 176E672B5542DC3C590818B10EAF13DB283D2DF7101486740005F09269D641A5
+ 7E0A2CAC8E2709819FEB135DE4D6C8BB678664C5B787EA0D28B5CFEEACAF6C25
+ 2B671B1AC0CF87C159BCFFBAA20CF324C92C4807301718A32F10B29331B61FA4
+ BCB3FBA04C161D2483C36F75DC4A4746E4049583B8C3B55ADDF3ED2B430DA401
+ 7A5E33D92DC63B39F6262167643093D9910E60165E662C9866EC69783BE3583F
+ 9D2113836F0E5E8FF574CAA3AF2524B0AECDDB70A861ADDB432A79523EFADD94
+ FEF1354AA7B82C11201DC00C3CCF583365EC196846F2AE55C3CF32A36749DFC8
+ E123A33C49320FD41E3C5053B383348101E75D76859F2519A5EFBD45692F4F92
+ DC8374007978C134F7C07F0FCED4DD8C4F9291DBAF75F4A54764777F2170D7D6
+ 6A2B5E6E6FF2576423230981C2C361C0E76F2ACAC9AF532477231DC03D3C639A
+ 1E37214F8362D6F3240BD8EA8F1C233DA3478F4478926401A979F840B8763F59
+ 076596B7370065762D4DC81FDF5394144F9200D201DC053FBCF30228A59A2759
+ 48A7C844FFAFBBAF95FB461EC5ED515D8D75956AB8AA8A7A3C3EC5EBF2134DF3
+ 2B1AF3514A14A610FCF7F5F29A49D2D4242663C434759AC0B38766321367A954
+ C2888C8F67068627CC74AAACF72FE046A2553F6A5DE7F5B0304FB2004E600C9C
+ C09BF24CC1374807C07999B11519C69E0323111ED70545B1B12ED237F8C6E783
+ E5B475375BD19B9BEAB4AAAA06ADC253AF78593D75931AA23A1C59C820519626
+ A366920EE993A9217D7C7C30D3DB375C5E8E41230D2F3ED8106ECDCE0D086D9B
+ 521A876EC2DBAF517A9B272D6BA403009E33CD16153A0050F985EBCCB8A167E8
+ B0D13D71F6D882CF286385F7B4AD5FADD5D7366B7EB69AF8C82A28C41937CA94
+ 0AD0579A24C84D3D4E6FE84323BDA9CE6B37CAC12154EED81FAC3FA862990AF5
+ 02FAD22193EFBDA328DD3C69D9B2EC1DC021D3BC4F21E42018B350177844B7EF
+ 95DEEECC40FF8275F99570D8E7DBD8D6E6AA71B742FF64DD1CB7C8CE3B262129
+ 12233D99D17457E24A67A719892C58400F1C1234FDB8A525DFD163286C8C5EFC
+ E11B8A7291272D4B96B50378D134B783D17E8B8B16121132DCFBCBE3BD0B117D
+ 87FA7CAEC0B6CDEDAE3A6F3BF393F50A9BDBF1E272C1A4C4A071722D339CEC88
+ 9DBFD4C112897977A018A5A8F927FB9A7DE1FC3B37614870E44D4A4F7371D9B1
+ 6C1D00B4FCBBE1E11FE6A285893ED23FF0EA91012ECE1B9EB6D615DEB50DF7D3
+ 30D9EA644B6F1A2445E1C50C92668C18CC8406DB205F574A95B8A842144A894A
+ 55E2662AF128F0CAFECC01B067C026C8C564EFE0D95467D7BC8FBD1B7F78A0B1
+ B229FF462ED0F367D013F8828BCB8A65E90066AAFCD0D49BA36749CF7C6EECC1
+ F059C1EDEDADAE35A17D8A8734F1E4823175658A25CC8811D3237A7C326AC626
+ 63466432A64F15D715D782619F1AAE0828818A80E6AF08A9012D4C7D4A58D1CC
+ 82C27BDD8D99227D99FEE8F1A9731D5DF319E6ACEEC903D5D53BC97A2877A8EF
+ 56202347DF5694535C5C362C3B073053B71F2BFFE0A7A42B72FCC8044F2A2938
+ A1E7DBB17D8B7BA57B3FD5480D4F9E133080652C4E46F5A83EA88F8E8C24076F
+ 0EB364725EBAD9D4EB75791B56D56935B5B55A486BA07E52435961B6C474329A
+ BE953E96387BEEE27C4D1C86F71DA86C7884B4E6730290F827E8099CE3E2B260
+ 593980E74C733314F2412EDE8B71EB03A3337AE658C9E3D3675BFCDDDB377BD6
+ 781F01ABCBBBE7C0824192FA38B9991A19BA95BAD13FC832F353E16783BABC2E
+ CFEA350D9EDAFA954A15595DD0F0C12463A9FEE4A753A7CE5D9A8F1E4168E7FE
+ 8A954FAA6DF05638A7028DC3E17714E51217973CCBC6017C8FB1F5E6D7EBFC96
+ 678642D76FBD1BBB3275E14CC963CDF9B6B4AFF5B6D43C455DA48127CD0C2319
+ A8F4FDA98181DE447FDF1065FABC759B8B81518DFAD634D57B1A1B9BB52A1877
+ D3B95D22C2326430D93DFA7EE262C7759E5432825B7706563E1BD8088D8165D9
+ 178C832994BEF35B4AAFF1A425CDB270007C93CF4B507344EBFCC68D775397A7
+ 2E9C2C69E577AF6EA8F46F6B3DA804C8269E34234602BAC8B727BA125D5D7DCC
+ 28EF5D78F9A09A4BF3B56C5CE35E51D9AAFAE636C4D113A43371AEE7FD4CFFCD
+ 926EB30E6EDD1358FDAC07CBC2D213804AA1BB287D7D396C165AF20E8087EEFA
+ 01BCF57D9DF20D38E61FF8C0B852CA6E3F76F7430FEF7E406B501F0365CFBA61
+ 479F207DC99EBECBA981FE2575BAD0D3B8A6C6BBAE69935639FB2427944B5A1F
+ 343E8E1E3DF545298705381C687C52DD08E5229A1348B8297D159CC0BCCC072D
+ 144BDA01E0C11E188C7E1FDE5A5A1F787076FB137265FCC49192ED0B77AF6DAE
+ F3DFBFFA39C54D56F2242138A1678C929EA9CECB978CF1D1257D7E5DADAA0906
+ DB366D566BC8BAD9260ECD34B915FFF2C63BE9EBBD258BF053B5F74068C5A364
+ 2378194B5E20612449C86B4BF900D1927600874CF3103CA0F054DFF059726DF4
+ F091112E3A4EF0E13DBBDC2BDD07A1399B318C15B6F8B1CB572EE86323CBEA80
+ 8A0B1C81BF7DD3F6597B0494E8E95BE9C353474F966CB34ECDC103B5753BC476
+ 028EE1DADB8AF23617971C4BD601E0797E283C0CE165A1949B7C70DB6EE5C35B
+ 0E511F69E54942708C9FB8D2777AA975F50B058706BE8D4DBB669B236009D235
+ 71F4E2DBA5DA5E3CD36621A824C7966A3C8125E90078249FE745DDBAA9513274
+ E31F8F9424428CA76DFD0AFF96952F53357FB82A939154AA77E26CFCF2C51E9E
+ 2401FC6DF7ADF3ACAFDAA1D0FC4B88CC2013F18BB75E4B755E2BC9E4DCEA7F77
+ A0395843EAB998038C086F2F7E6B2946165A720E0063F86518FB4BA8FC96305E
+ 78B0A7FBEF4F5FA6E938FCD859827B776F73AFF57E7BA62E3F76F727CF9D3F6D
+ C62665DC40014AA0C25BB17DDBAE1987053824B89EFCC3D48953E7798A636028
+ F296BFD9B5497480082A4AD245E9BF2CB518834BCE013C6F9A7F06FF59BA7278
+ A4B7F717DD979C0EE4919DE57F6CDFA3AE1A96F75C0163249DE81EFD22D17DB9
+ 8F274966C0D7B2A9C9D752F300A5F9574DF431FAD9C49F8E7FECF42A019E226C
+ FE69CBE63C4789FBDF52947FE3EF97044BCA01BC8017763086D7744D03BB7037
+ 3F302E3BBDDC875B79434F3EF09C12C85E062AC48893C1A9B3973ED7A30B7734
+ 7631A285C2BEE08ECD0FAAFEFC1BA6CC18B918FDE08B779CDE4A8CCB83AB9E54
+ 378986904BEDF4E092710078690734ED3F84B7968D1DE35DE4FAE01B4706B9E8
+ 08785C37FCC4AEEF531F59C7932CA407F54BD1B3A72F94FBEEBD720577158676
+ ECDAEA6ED036F3240B2C417A221F9EFE8DD3C78D1B5E3CB0A2AA553814315C84
+ BCBA542E1F111E8A586CC0B85FD509C1D8FD96CA9F4CD1C8D761BC9C43AB0879
+ 2A0FEEFAF3BC959F113D7679E8C8E49913E765E52F1ED41DEA1075893AE5C9D3
+ C032C0B2C032E1498E0036731BE33F72F16EB2B68636C7E545CD92700029C676
+ 432DB3848686B4CCCD5F77F5C08891A7D8070D2DF8F8B6BFC87B6CD72089C9D3
+ D7DE4FF674DDE029129BA02E51A7A85B9E340D2C0B2C13679D804E30F82BDA10
+ 4FC881B6A633F6001717358B7E08F01DC6AA34C6FE12DE5A3CF2F031D2E964E8
+ 6EECF6636B93AFF21B29323675F2D2A7C59EBF77124A5CAA6B457DA356155EA9
+ F8FCB58AC75D43351686570555981F7F254D5976A2CBCD681AFE63CCA471A6D3
+ 497845CC547AD44CC447F4F1C8ADCCEDA10146320B7E1E01E31304F76C7E44F5
+ 884F5062AC8189C3A7FFD5C9E100861CAFDB4FF0F4E0BDE050E015180A8C7179
+ 51B2E81DC021D37C091E62351773E0A51D7DFFE5886327BA70C2AFF2E9077E40
+ BDE21D6366828C448E9FFE78BECEE4DF8B1A0804DCAB9B37B94295AD4A806DA0
+ 9ECCEA64427CE4B550BC3E621869579F31C5AE98636397D3FDBDDD463A8D4E63
+ DEC15804E17DBB1E537CE2CB40704E60E2FD2F5E757262B0E9DF1F582FBA7C04
+ 7A0237DE5694D7B9B82859D40EE07BA6D90AA5FC1D2EE6C06E5BCF3F755C70EA
+ C61E5CEAAB7A66EFF3F966FBF549723BFAF9A94FE7FBD49E5A5553ED6B6ADEAD
+ 557A7628EEF4BA447A7E867450F9325AD2DD6B4452E7127DBDA78CF1D1796D05
+ A9EA51430FEE7E44AB202B78D234707560FCBD136F39B544883710ADFBEBF6AD
+ 50592C479BC1C3FEFEB78AD2C5C545C7A275008F32A65531F65750C296F8F7A3
+ 6748F7F007471C33CAD013071ED7AAB337035BF8BAF29F84CA3F3F5D640CBEE1
+ 6BD9B0D3555FF988EA4A6F98AF4A9F0F9F9B9846C67D353334F169A2FBEA99F9
+ 0A52822B04E187F63E96CF09E863F458F4C3231F71D1361852AC662769E1620E
+ A840D1714AFFF9134A9D9B689A4716AD0380AEFF5EC8FC835CCC81B3FEBDFFF9
+ D34E2EDA26B067F716CF5AEF0B5C9C46B6DB7FE4D447F3D1F26BA1CA90AFB5ED
+ 51AD9A7E2B992A3E265F29F17A94297D4C3992E8EAF8508F4E94FC7013F604C2
+ 07763F9E6F3890EE4BBEEDE48EC1E6BF7DA44D74F310D8E1A23D2BB0281DC041
+ D30C400DF889794F970C1E86F5BD317A21D6F595235B6D31426FE0FE869FC098
+ C2B2BD97A5C9C4F867A70F977ACCAF064341FFA6FB9ED57CFAA3C91976C6CD84
+ 9791B4696813990C8D28462269E8668299D088EABA4E554A99AA6A4455DD54D5
+ DC54D3DC9AC6420AD5C376BE4F4F689F243A3BFE586A47807302550FED3A48DD
+ 82F31794E8B12F077FE95424E240EB7DDEA6176BB642AF735ABD812E58668A90
+ 5F1E5694924794729A45E9009E67EC31C2D8FD5CCC3139486EDFFCD51147B6DB
+ 664FF53DBEE567C2833D06494C1CBF04C65DBAD97EECEA07B66E3DE80A799F4D
+ 9A89392F6F795D34694C6A037A2C3A90999C18CD4C44C6592C569461D24020E0
+ AA0C57B92A2A6BB440A851ADD01B931996F7AAF47BF12ABE54269A7C3776E1C2
+ E1520E0D70D760E5BECD4FC380DC1AF4C52013131F5DFC07A74E11AEFAF181A6
+ 8A06C1B083D22FDFA2F4632E2D1A169D03C0C33E69C67E0A6FA7CD70635CBFDE
+ FFAFE37C3AE2CCC45FD5771FFE81F0482F2399C9D3D70EA787074A1629C6DBD2
+ B6D5B5BAFA47BAA9CF298C9647552399F1F8D5F4D0506F7A6878043209EA2805
+ 5471D7D7D5BAEBEB9B5D55FE0D29C3C87B11E7DDB8DDDA58AA77EC956477E705
+ 9EE438EEBAC6CA8A5DEB0F82455B26EAF028F1D81F4EFCC689494177B8566BFE
+ 1FDBB741AB7F6FAFD0800FFFE5DB8A52F2A0B24EB2E81CC0F3A6F904FCB7F56B
+ E91B9CDCEE9B0DE6D1E87E968BD388758E1C495EBD52924D3ED9EEFEB62D3FD4
+ B5F41E9E9417EC66A712B43B7DA3EFABCCC8D0826C4B75D5D6D7B95737DDE7F1
+ B196B90C1734DD7D327EFEE2ABC654B42427EABCEB5A570736D55BCE8220E981
+ F4BB4E05156978F14043552B59CBC5BBB9F096A27CC8DF2F0A16950338649A15
+ D0ECFF149AB76933DF0694EFB5BF3F73DE48C66CB77CEEA6E6DAE0BED53F138D
+ FB716F3F6E4DE5A2A3F8D6B7B47BD7D7FC249936AA7892102F51A65223B10B89
+ DEEEAFCC055A8BBF17C5ED76FB9A5BEEF3D406B626C9CC13945EB71A49F68CFF
+ 3271B5F32B9EE428153BF76E139E1DA0449F3A7EE31FD27DBDB6A340A9DE80B2
+ FE6F766E035B9CE6F4C0284DB0C55F2CA65EC0822E21150AA574D7BD951F8974
+ D05B4E547EA6B915FF8ED58744951F4FF5E1C11E2E3A062E6755EC7AE039DFFA
+ F0DFCE54F915378DB3E1A923E3C7CFFC3AD6F9D597E552F911CC0BE609F34686
+ E29F615EF98F2CC033867DEB427F83CF8CCFCE931D03CB08CB8A8BDF00658A65
+ 8B65CC538A066D0D6D8E8B39D036D146B9B82858340E00037C2A8C593C3B283D
+ 35F4C7538E748143FB77ED1605F0C47BF5A64E5D3CE6F4C11EC5EDF7861FDEF3
+ 3FEB01F65CBEF57CDC8547278D73B1CFCEFF3AD175E522338D79DD6C540898B7
+ 7877C779CC2B9934BEC4BCF31F4D039F159F199F1D75C0931D01CB08CB0ACB8C
+ 27E5C0B2C532E6A22DD0E6D0F6B898036D146D958B65CFA27100D0D7DA0A0AB7
+ 4CF04C7491DB4E44F8C1B8FD18BA9B8BD3485C1D39A9C7261C8DE2A3866BAA02
+ FBB6FFEF699AB6CC67DC4163AEDBD1D33DAFC52E7C798C65D20BB2C5B81830AF
+ F10B5F7E8E79C767E0C916F0D95107A80B9EE408585658665C9C0696B16BCDAA
+ 394D5ECE04DADC7807B5C495441B455BE562D9B3281CC0CF195320A33BB89803
+ 94AD8F1C3EE348EBEFDBDEFA24F4472D1359D938FD0E4FFAB9EA1A1A82BB5BFF
+ 0F9D64844128B3ADFE48E2F3E8E727DED22363E33C79D18179C767C067C9D71B
+ 401DA02E50273CC911B0CCB0ECB89803CBD8BF6D1D4E24DB66EC4FA747D006B9
+ 98036D75B11C175E140EE00C63EBA1890F7031C7D42D32644CD91FFBE3755DAA
+ 9FB473310706F0C4187E5C740477C3CA95EEEDCDFF219DD68527DA5CAA1A9D3C
+ D7FF068EA9B153CD931731CCC467C167C267E389D3405DA04E50373CC911B2F1
+ 170543012C6B2C732E160DDA1EDA201773A0AD6618DBC0C5B2665138008552CB
+ 211C50B239FCC76EDBCB7E78D007EFEAE3E234307AAF93013CB5DA867AD7D635
+ FFAB99368451835DA6EBC6D4C973FFB650CB7AA5049F099F0D9F91274D037582
+ BA411DF124DB60D9A57AC7CF72711A58E658F65C2C1AB441B4452EE680B44531
+ 0C287B07F08C69862863166F9D9A24E34E04F8C45B7A45177562DC7E27437767
+ C7FCF7AFFBDFF2557E35462F474F1EFF83914A2DD988C1F86CF88CF8AC3C691A
+ A81BD491937302F1CEAF7AB02CB99803CB1CCB9E8B45833688B6C8C5BB5903C3
+ 80BCE1E1CB85B277005E42368337B578EA8933C4762B8967FCB357740BC04B3B
+ F85BDB28BE802FB8A3ED7FC9D7ED275103BAC8A7FE041DFEB29DE1770A7C467C
+ 567C669E340DD411EA0A75C6936C93AF2CB1ECD106B85834F96C312D58B52A37
+ CADE0140DFCA729B2ED492E4F889CF6D1F32F1EDD8BE053460A9949908E975EA
+ C61E46290DECDAFE3FA48D8C2568499648FA64FCE2979F7369D9907D6678762E
+ 4E0375853A43DDF1245B6059629972F11BA0ECB3366013B445B4492EE680866B
+ 237F5BB694B50378CE341BC0022CDDA8A91EF4B8F6B6FCE3F8CFB3DAFD101773
+ E0459D89CB971DDBF013DAB9FBBBBA92161A993A619C897F7561C984982E147C
+ 76D40117A7813A43DD71D13658A658B65CCC8136607F2E40E736391DB45DB461
+ 2E962565ED002073A2586C64FCD875DBAD7360D7E63651EB8FB7F4661CBAA1D7
+ B7A1ED3E5715B3442C4268827E3579E9CB135C5CB6A00E50175C9C06EA0EB748
+ 73D11658A658B65CFC06B081AC2DD8249F4DE6B3E172A1AC1D007850CB693CBC
+ DE2B79B3CFF636587763702F7F9B035B88A9AF2E5DE4A22DF0608FB2AEEAA7A2
+ 1D7E6ED375237EEEEC512ECE2B5473A9AEBA15214FD3DA1A7F6B5B23BEF03DA6
+ E1CFF8AFCD2BA80BD4091773A0EEBCEB6B7E8ABAE449B6C0B215F50244B65028
+ 6893689B5CBC9BB276008E8CB14AC1CB8CAD483386177D4CC389537F78896760
+ FBCA9F7131076E1C9938F6D9675CB445C5FEFD3F139DEAC3B5F0A953E7FECD48
+ CCC36CBF4AA96F5D6BBDA7A9A6C9DBC01A55B75EC3180BA93E9FD0F11B898409
+ C3EEA891D64693837420D537DA97E8E91A2206B3541AA7513D1E6F70CFF63FCB
+ 188625C41B9E229C3C76EC1FB8688BCAFD0F3D24BA7B3076EED63FD8BD7434DF
+ 294137A5AFBE4669492E34B54BD9EE566AFBF9CF711DD5327176EB0FBD3DE654
+ D4D60699E0AECD0714AF75CF7FFC72DF09632A6A3B70049EE76795DAF7B89803
+ 77C3C52EF6FD5E8F464B1A25C7D7D2D6103AD0B6A7E681FAA7036DE19D9E1AA5
+ 49F528D554D3BC8A2BFF78177F86BF83BF8B7FE35F1FD81A6AAFDBAE35375710
+ C39FD0C7464B16F18619866EC633B703AB2B37EAFAF45E93A918AB3457B017BE
+ DFB2E9A660741277AFA8B46CD2517D152C75B5AF9B8B45919E60E9EAEDE1462E
+ E600638D5DFEBBBF2BCB7B22CA7608004D8EE5D61D1D149919E8B7B5F68FB1FD
+ 69A535BA2FC6F77362E61F23F960300F2E4E2371337DAA949B7C423BF7B436FC
+ 74CF8F6A9FA8FF5160857A3F3CABEDA534FC0CFC2CFC4CFC6CFC0EFE23C741DD
+ A08EB8380DD429EA968B4583658C65CDC51C6813681B5C2C0AB44DB4512EE610
+ D972B950960EE025D3F4413355C7C51C897E6AFB928FC0B6CDEDF0D096D35AC9
+ 817147028906B76C7D4A14C9C76D6A4389CB17856BDF7609B46F5EBDF2A77BFE
+ A2F201F777DD6E77C9669DF1B3F13BF0BBE03B57F16447411DA1AEB89803758A
+ BAE5A22D9237AD658D3681B6C1C5A211D928DA32DA3417CB8AB2740069429AC0
+ 6B5ABAAA539793B6C370B9EABCD642662493ECB67F951746EED52ABDCF703187
+ D74DCC5877CFA7F0458EEEEDC716ABFEC5070F563F52F5B2EA763BB6857636F0
+ BBE03BBF8FDF6DB7D5B4C2B2BA429DF1841CA85BD431178B2679ADEB065ED9CE
+ C51C5ABDD7F6C61D918DA22DA34D73B1AC28D72180F54C3E34029173676D8D41
+ 31D027F35B6FF6D1C749BF1371FD7D6DED4F8B027866C688E361BBBCCDEBEA1A
+ BFBFF9479E7A754E1B59D25142A25708193D3E4606DFEF21B7DEBE486EFEDBD9
+ EC0BDF631AFE0C7F077F772EE077631E302F3CC9115057A8332EE640DDA28EB9
+ 583458D64684F473F11B7CA4196D844B4581360A155E344C75F4A0935394A503
+ 5005CAD2E3246A37A8A36F635B9BC2AC139FC98181EBFC6DD1645B7F9FFE2817
+ 7360749CD8954B8EC68C0F3EB06763DD23D53F54BD5EF1D6624E72142AFC49B0
+ F4FF7E92DC7EEB28899C3C4A625D5F91D4E04DA24F4488118F655FF81ED3F067
+ F83BF8BB37E06FF06FF1336602F38079C13CF12447409D89220BA18EB550D8F6
+ 1EFBD42D6B99A36D04DADB2C3B4F0B016D3419B72E078A6CBA1C283B0780D154
+ A0965B2E7A48DE24B637E7B86ADC96092C3C2E9AECEFB37DAAD0DBD2F6982830
+ 26BB153F67A6929623A9C552F9D8FEFBAB76BABF4D7C3E4BD8B23BC46F1132F0
+ FB2B64E80F50E1AF5C24AC88E86126FC0DFE2D7E067E167E665E202F9827CC1B
+ 4FB10DEACCBC11B39CE4431D7B5B5A2D8EB65012FD7D43C4B06EDF55ABDCB68F
+ F126FBAC0E006DBA1C2305959D03F013B202C74C5CCC11ED4ED90AB4983DF411
+ B0CEC69A5172C36EA8AFECCC7F0DB54413C218FDF19EEE4B5CB44DF8B1FD3B42
+ 1B956F71D1421A5CE4ED77BBC8C8874761D8E1DC88033F0B3F133F1BBF231F98
+ 37CC23176D93B8D6790983A0723107EADAEE8A0096B91E2537B9F80D6023760F
+ 08C5AFC5440E80A26D73B16C283B07A00B9404CA3327AF9CCD1B68722E78DAD6
+ AF8687B578E0D4E0D04C6DDB9CC0BBFA44D775256FA7CE3B15CAAB62EFFE4D15
+ 1B1561C83204C7EEB7DFFA8CA4471C898C2E043F1BBF03BF2B1F9847CC2B176D
+ 8131063102321773A0AE51E75C2C1A51D9A38DA0AD70B128A29D17702F89654E
+ 4964DB0B4DD9390070BD96EEBF6E92184DDB1BFF6BF5B5CDFC6D0EDC169ABAD1
+ 6FBBC6E0459DFC6D0E8CDB9FECED72645BB16FDD8686F0C6D4412E4E039532FC
+ C9ADECD81D4318951CF80EFC2EFCCE7CDF8679C53C73D11689EBD73A50975CCC
+ 21D279A160D98BB6068B6CA510D0563326B1345822DB5E68CACE014069589494
+ 1EB32AB350B420B3C4DF6371326AF7CA2ABCA21B6FE9E5628E4C82763931F657
+ BC0177C581C6EF88C6FCB84E36F8FE5592E8BBF675C23C82DF89DF2D5CD784BC
+ 629E31EF3CA5685087A84B2EE6409DA3EEB9581458F668035CCC21B2954211D9
+ ACC8B6179AB2720078E537FC6789D89A1AB6E700B2633A8F606521AADB6EFD7D
+ 6B9B77890EFC246FF475F0B7B6A87976DB231E9FF54834365B4338261FB404A6
+ 9D37F0BB310FA29E00E6B916F2CE455B8874893AF73535DB0EF12DB401B015BB
+ F707E4B1D930B7F1B2A1AC1C403563D5604C9609C0D4F594ADFDF9AE754DF5F0
+ A1D688BFA323F66F89A9F45866BEB377F539B0EE8F27F5BC15E25802239FDC2C
+ E9787FAE601E86FF649D4B433C90777C062E160DEAD24DB4312EE650C39EEDFC
+ 6DD1886C006DC5BB61ADAD218CC866D1B6438CCDE9BEC7F9A2AC1C8041883016
+ DC6477A72D07A085AB84BBE49283376D555235100808BBFFE3F1ABFCAD2DC20F
+ 871F87EEB47545E43276C11D0B57689BE48D9E6C9E2C40DEB3CFE0007A346679
+ E0EC3000CA808B4591CF06F2D9CC5CC967B35098B6EF247092B272002A21966D
+ 9EE03533663C626B979E56E1B11426D349CCEEDDFEEED5CD9B44DD7FBCA597BF
+ 2D9A8A1DBBD68BB6F7666284444E3B7262D951304F98B77BC167C067E162D188
+ 748ABA77AF69B6B57F1F6DC0D4AD4B8D229B2904B459305A8B7D896C7C2129AF
+ 1E00A596B12E68D0FE449A9F59BA73664218C9B5205CA14ACBC6225CFBFFFA8A
+ 6E7B78B7ABC22015A39F41E7623E66FB0B05F294CD9B807CCF5208A853D42D17
+ 73B82A2A5BF8DBA26109D3728047643385020EC062BB221B5F48CACA01288C59
+ BCA33969DF01504D10FA2BA6DB3E59A804AC973F1893DA009894AD433F789EDF
+ EB715BD68C7137DE424EFACD06E62D66DD614FF059F099B85824CCFC5AB7D311
+ 9541A1886C4164338522B25D918D2F2465E50018A516E5E893D635E042C8AE00
+ A8D66E971E9FB415948312974A3DD648BF9968D4FEC6A2CD35F7F1B7D398383B
+ C30E9C32217A4EBCF891EF990A418F452D0E00CB00CB828B4521B405B019BB3B
+ 02F3D86E05FFBF2C282B074019B3DC140BE34A5B0E405BD1289C583463315B27
+ 0B5D2BEA57241338A49B8E3119B137FBAF52EAAF4C5B0ED6A4C640170E6EEF2D
+ 1599F151E101A2EC33C1B371B128F4A855B758065016B6561ACCD8A4D016F2D9
+ CE5CC963BB651517A07C1C00631446B6160700DD285B13755A558570CC654427
+ 6C3900AD2A2C0C8891898C5996AB0A21D0B271A52892CF54E7E2B92334D66555
+ 4136B2103C1B178B221D9D10C68380B2B0F5B946248F03C8633B734564BB591B
+ 075BE7E28253360EE0BB793C6366CABAA7BA1014AF47B84C04AD89ADA545C5E7
+ B7ECEAF2BA9498DDDD7FEEB555C27DE889EB96CD70654BFCBA38B45EBE679B2B
+ 0C7A6DA26DC1A2B228047D2A92106D09CE673B73259FEDBE24E8E92E1465E300
+ BC7994A2C762B66E00A11E97B55721B831B650A8CB6D098291498B6FBF2D044F
+ 2DB34CFEA5A1DDC3E3B98B053C7E9C12B4D56A2DB3BD29C8649A75C6DEE3B6BD
+ B986E982EEBAC763ABBB3E83ED96CD30A06C1C00B84AE159697D3C62CB01104D
+ F3F37739A8030E40710B562C92F66316A85AC6B2FE9C5CF80D7F059312E4D9A3
+ 656C470ECAA4A8C5B5508DD9DE5C23B209AA29F61C401EDBCD67EB0B41393900
+ E1B8C848256C2DA929AAB567C10C7B138B08D398E5F8AF62246CC5FAA76E97AA
+ F87C96CFCD446CAF58CE3BA23CE3B3E13372B128443A169545A1886C42D1982D
+ 0790CF76F3D9FA4250360E40234418E081A632B61C00A8DAA26C53C7A3D9F650
+ 1566191F1ABA696FCB72558DD090F5C8E29900BC43BE3CBBC275B696C18C9455
+ C7A2B22814276CE25EF2D96E3E5B5F08CAC60164F2E4C56EB950CDDADD62547C
+ 8AB5104C8AE5381D660A0FC6CD19AD22249C0731D3B6FCCA82902FCF5A45D0D6
+ 049868B24E54168522B20991ED14423EDBCD67EB0B41D9640410760DCDA8BD73
+ 00221466DF0128845974C732695B730B8AAA080D79314D00DE215F9E615C6D6B
+ 08400CEB074359D8EE523B6113F792CF764101D20148ACD8ED412C06EC3EA3A2
+ A8F61C88641AE5E40084DE5209851D2F70E832DA7E6E93506B97D1E5B6D56534
+ 532961B3A9B86D07D69977F2E539DF33CE1546544B2F09CAC2B6E374C226EE25
+ 9FED82A13BDEDB2896B27100AE3C4AD16C0EEF982E58DE61F69F1BBA8C96011E
+ 55ECCDEE1AF1987008A1B8CB66D978CEE4CBB39188D97200D4AD5A9CACA82C0A
+ 45641322DB29847CB69BCFD61782B271005082C22DBFCCE3B2974766ED72C248
+ DBF6A4916152CBF651D5EEBA71745C18FA4C0BDBDA92BE20E4CBB33E316E6B0B
+ B6A26A96B2139545A1386113F792CF76F3D9FA4250360E201FAA477C97FD5C31
+ 0DEB1972AA5AC383150AD5A965D38FA9FAECCD70A73386994858E3E087CB2A88
+ CC9C70555AF38CCF86CFC8C5E2D0348B8E45655128229B30756A6BF9259FEDC2
+ B8A06CE67ACAC60180F6859B68B4AAB03DCFACEBD6E8AC1822D426669A5AB6FD
+ 2A5E627B434A4A77594EBC796C87A6987F3C8208F819C3653F06A3C62CFB0844
+ 655128229B60B6F775886D171C80ADA18593948D0348526B4B8D6881802D07C0
+ 5219CBE72A0E380096495B2AAACB6DD80EF6A0DFA696089B9E4A68A116D14420
+ E615F37C2FE9016AFB066685EA96AE85A82C0A856A825E61CA66305A7F20DF04
+ 76D96CEC281B07F0BB3C4A7105C5FB03E68A994C898F7A06EDDD026B26E296D6
+ 2C9931038AC76BCBB9A4AF8F0A62EA10E25F6B3BF2D5BC912FAFF99E6DAED040
+ 2020BA7F5154168580B6409960C7681EDB992B5A85785EE1F53C8DDD4250360E
+ 80508ABB39ACAD7585BD6D93FAF8A4F00CB91AAEB4B57D541F8F0823FFB8C295
+ B64249C57BBB0659226171868156DB11AAE60D515EF199F0D9B85814EE50A538
+ B64324622B4E9A1AAE101F19CF633B734564BB591B075BE7E282533E0E006002
+ CFE80AD89BB0D36F0F0837A52B36C349676E0F0D787DD6BD0B6A458DBD136F06
+ 63F109B725F697B7067451EDE835FC25C1555593CDEBBD649F099E8D8B45A185
+ C216056019A407ECDDEFA804F238803CB63357F2D86ED974FF91B272009431CB
+ 640E74A36C3900339D32A09A5A3FD75F616BBCCE48C6602997654CAB55866C9F
+ 794F5C1AFD8ABF9D46E5FD8E5EC15F1242DBC551BA9317476DDF94A405ACBAC5
+ 32C0B2E06251086DC154A6B2B663833CB66BEB966BA7292B076052C1CC7A8503
+ 13763AB1DE2A13D06CAFAD99316A8983AD05F595E0CA6CE935D1DD39984CA56F
+ 7331877F1574831B6CFB979281790B086ED54BA7D283F1AB9D96E7290CAAA815
+ BAE5E145655028225B6019D3F68A85C8764536BE909495035019B38CB9601065
+ DB0198716A197B2A3EF12D448590999CB0C4BE4A6698D75D5F67FB12C8E439E3
+ 047F3B8DEAFD1B20F3B6CFBE380FE4A9E6217184EE789E672904D429EA968B39
+ 44655028D4A7581C80C8660A4515D8AE22E8E52E2465E500A0BF65510E98BA4B
+ F1DB3B0FA04FA686F8DB1C542301EAF5DA9A604CF7F776F8DCD66D9DEEFA7A5B
+ D74B2393674F5F33D2694BBEDD4142C2BB1EE252F980798231AF057C067816DB
+ ADB448A7A87B2C032E1605DA80A29996FD1B229B2904B459305A8B7D81B1D89A
+ 58749AB272008C1061E89B8A96367B5B6C23E3C2C2F436ACB235AB66C4623123
+ E3B60E03428175FCAD2D2247231FF1B7D3086D02E35FE3C857388277F5BA6C9E
+ 44448E4685CF5028229D9A19F7352C032E16453E1BC8673373259FCDE6B3F185
+ A2AC1C4094D25168F12D33C59EB5F68233667AFA86E0432D8750B49A5ADB5D75
+ 23923AC7DFE64813BDDA555B6F7BCA3EDED539901A322E70711AB58FAD22EEDA
+ 85DF228879A8FB9630423AC1BCC7BB2EDBBECA0875893AE5620E3D92FA92BF2D
+ 1A910DA0ADA0CD70B12844368BB68D36CEC5B2A0AC1CC02794E2A92E8B87F4D4
+ 114B60CF42C8CEE6A68865A9480B69B66B50A2AFF7946818E05DDD64EBD2CA3B
+ 8CBC7BFE53239E100D8D48FDB3AD0B3A2988DF8D7910CD48609E31EF5CB48548
+ 97A873D43D178B466803602B765700F2D86C84DB78D950560E000163B2CCBEBA
+ ABED3900449FA2965D68D44F6AA8CBDE3C80313E3A261A06B87CACD5EEAE40C4
+ 4CC6D2E34723BF238984C570B0F01A9EDA407C4DB62FDF2D18FC4EFC6EA10141
+ 5E31CF98779E52348ADBED465D723107EA1C75CFC5A2C0B2471BE0620E91AD14
+ 8AC86645B6BDD0949D0300B76B5192A6900073BB440DCD9CD187462CD74BE3F6
+ 4FCFEA35B67B01FAE0E411FE36076E59F536B76EE1A22D123D570723573C87B9
+ 380D544ADDA32B49F88187A1346DA9686EC077E077E177E6FB36CC2BE6998BB6
+ F035B7DC27DAFE2BD279A160D98BB6008B6CA510D0565D8AD501886C7BA1293B
+ 07A01162592F8612522A36EEB0D50B48755EBB01FD74CB292C4F43BDAD6BA590
+ F8D5AED35E8FF58E79EF0ACF36EA72DBEA61DC61F2C4B1CB9357CC8FB9680127
+ E1561C7A08C6E4B6AEB59F11FC6CFC8E7C137E08E611F3CA455B5045553DB581
+ AD5CCC81BA469D73B1683CB5D6B2471B415BE1625184DAB6E2F8DFB27225B2ED
+ 85A6EC1C401C940415DE3211186AF1D80A279D1DD3C5480F17736821B28A51CD
+ 56D3C932C94C6694592A27AE5BFBD7B7D8BE15F70E918F8F9D8D76981F4117DB
+ A21FC40D1A5AF16C1BA97DFC6147B70DE367E167E267E37708813C61DE308F3C
+ C536BEF56D9B93C4BA4487BA469D73B128B0CCB52A629DBD041BB13BFEF7AE0B
+ 5AF28C368DB6CDC5B2A1EC1CC07B8A92026559BA4ADE55F6CFDA6746D3D60BF6
+ 54E2F5AD69B2DD6C26BBBB3E11DD5B471BFDF73B31177087894F8F9D9BB8A8FE
+ 5E34277007DC31D8F89D8DA4FEDB0F9340EBE6A28E12E3DFE0DFE267E067E167
+ E605F28279C2BCF114DBA0CE94D5811D5CCC813A4E765FFD848B45932D73287B
+ 2EE630C6D3B6F72CF8D75A6F8D429B46DBE662D950760E0001F76B9DB1F79310
+ 53ECCD0324AE74769A143F7E3A9E958D6BF9DBA2D1A391093DA1590CD34C337F
+ 60E3E63D5C7484E899935DC39F8EBD6A2693331E56C1433935FBAAC89A1FEC81
+ AEFBC324BC071DC27D30EC5945B4CA30DED4937DE17B4CC39FE1EFE0EFE2DFE0
+ DF8A0EF6DC0DE4218279C13CF12447409DA1EEB8980375AC47C76C6FA6119539
+ DA46ACA3D3D6F0056DD4EB27967E92C8A6CB81B2740080455990512DBC7D87AD
+ 137C66249220096299E051C3640D55ED5D5985243A3BFEE8557C162FEFAA26F7
+ 39B12FE06E92BD3DC3B77E73E995D4B0719127CD88BB1286511BD121549386A7
+ D6919587B690D52FEDCABEF03DA6E1CFF077F077E7027E37E4E15F302F3CC911
+ 5057A8332EE640DDA28EB9583458D658E65CFC06B08DAC8DD8006D145A29D1BC
+ 8F740073053AAC7D3866E2628EE026EF1C4D333FFA50F2127F9B83E28CFDFA56
+ 5B5757237A7422AA4F24DFE3628E649A288196758FC03739AA6F964864867EFB
+ F9E1B14FC75F136D1B2E15F85DF89DF8DD98079EEC1034AB2BD4194FC881BA45
+ 1D73B168B0ACB1CCB99843641B8522B251B465B4692E961565E9005E57149CE5
+ B2B42ABE35F66F818D9DBFD4215A0DF0AEAA6AE36F6D3175F1C2FB9AA259767B
+ A515BD3ED0D6BE8D8B8E12EBB874E3D62F4EBE32F145FA77E974DA91E53711F8
+ D9F81DB77EF9C5AFF13B79B2A3A08E50575CCCE1766B63A85B2EDA4254D66813
+ 681B5C2C1A918DA22DA34D73B1AC284B078080D7B4CED8837DB81AD7D85A56C3
+ 168B4D104BB759F1915A4FE39A5946BCB3935D11B831F66B2E4EC3B3C6B7C7E9
+ A1C0DDE0387CF017277F3DFAC1D0BFC66E1B5FC2B3DA0E3D859F819F859F899F
+ 9D1DEB337B813DF281BA411D71711AA9DEC82B7667FE112C632C6B2EE6409BB0
+ DB9B41DB441BE5620E912D970B65EB005C940A9556BDAFD9766CAC64EFA070A9
+ CABBAE698615EEB993ECEEBCA0E9EE935CCC914C10D5DFDEFC94EAF1D80A1F3E
+ 1B78F67EECADCFFF74E39533FF152BEE6497713433A95FC309BB7C4B8859E067
+ F83BF8BBF837F8B7F819F859F6CFF3CF0CEA0475833AE249395CBAFB8B64F765
+ E1998842C957C6C9DE5BB6972FF3D9663E5B2E07C039952F2F98E65F83B54E5B
+ 52C99864F2EA7F3C62BBAB163EF4F05F291ED2C4C52C78F3ECC4914BEF189311
+ DB174DA8C150D0BBAFFDE766DAB08C09DDA6EBC6C4C92FFEC04CC3D67A733150
+ CDA5BAAA6B2AD440C0A3F0E3D050E933462C91CA8C0D4F32DD66DCFE22C00D3F
+ 957B1EF8765AC958E66114B73A913CDEF177C654D476EC7FB5221CA83CB0F9B9
+ 7B77FF9929D21779FBE83F73B16836FC8703ED2EC5B20230F996A2FC237F5F76
+ 946D0F0081CA6F595A42057B573515BEB07D0FE981294B900A348CE07D9B1DD9
+ BE8B066B5E1BFD27D141213474FFB61D0F73715EC10A9E1EBA1DC1ADBA388EC7
+ 17BE4F0FDD8A2C44E54782DB763C24AAFCA83BB367FC174E547E24B879F366D1
+ D65F912D140ADAA4A0F2239DFCFFB2A4AC1D00D41CA1F2AAF6AFB53D568F9DBE
+ D4095F600D155643D6B9AA6A6C6F3A4212D7BA3B32E3F4F75C9C06F3B3FB825B
+ B638BA3F603152B1F9FEBD869F6DE6E234507789AB9DC2F888858265AA5613EB
+ A929B081AC2DD8249F4DE6B3E172A1AC1DC03B8A3208BD00CBA68FE03A52979D
+ 12B40135332C7523FD191773600BE1DBB4C9B2FFBC58A267CEFE4E33DDC2B57A
+ 33E4D9E5BF6FEB2E2E2E3BF0D98D4A752717A7813A43DD71D13658A6A2D61F6D
+ 006D818B45A2719B9C0EDA2EDA3017CB92B276000864D0B2334B851E57D5DE07
+ 6DDFC293387BEEA2A817E00A936627560410CA74163B7DEEBFB9556B04E12C61
+ F71EFF96FB1FE4D2B221FBCCF0EC5C9C06EA0A7586BAE349B6C0B2C432E5E237
+ 40D9676DC02655BB1E0CA14D723107781B4B78F772A3EC1D4092904BA0488B21
+ 54EEB47ADC42C1431FA9FEA43068856F6393632DB3998825A6CE76FE3FB896CD
+ 93A61352EF0FECD8FD2855AC33E04B0D7CC6C0FDBB1FC567E649D3C8AEF783AE
+ 50673CC936F9CA327D2379D4EEC11FA4728FD816DD94DADE58546ACADE01BCA7
+ 285146E9752EE6F054902A575DA3EDA3B653A7CE5D621962E9A6A93E52E36FBB
+ CFB1C07B4664743CF165CF7F7269AA70271BF3B1FB2A1ED8F76CA9970817127C
+ 367C469CFFE049D340DDA08E50573CC936588658965CCC81653EF9C539DB4B8B
+ 6883688B5CBC9BFED7282DAB00A022CADE01202663966E1AF40A94BAA75B6C07
+ F3C0F15FB27B54B8C3CCD35CB543F1071D3BC9971E191C4A5EEAFF4FB8B4C593
+ A6A1AB9935C13DDBFFAC949B85160A7C267C367C469E348DEC721FE80675C493
+ 6C83658765C8C56924AF8E1DB63FF627046D106D918B3920CD917D0BA5665138
+ 002FA53DA050CBDA7C7025A9578301DBCF90B8D871DD8813CBDE02BC45B8E2FE
+ EDBBB9E808E9C15BB7D2E77AFF63BEE140C6304215DBD7BC1868BB0FBAC8CE9E
+ 1D5818A882CF82CF84CFC613A781BA409DA06E78922304B76FDF29BA09DA8C91
+ CB890B5FD98AFA83A0EDA10D723107DAAA8BDABFB0643E581406065D2903946A
+ 89000B99D7AABFB5CB76645F247EBEE743680EAC91832B4993779DFD83427793
+ 191E1C9C3AD5F57F6AC4258C3D87BBE158ADEFC18A07F71ED2C2D5B62F305928
+ 30EFF80CF82CA21D7E084EF8A12E50273CC911B0CC44137F58C6B10B3D1F70D1
+ 16687B68835CCC611272166D968B65CDA2696112849C87CC5AF66A57B5B346E6
+ F6837FB047A6FF66441F348421B77CADF57BB440A5A363731CE7C68E9FFBBFDD
+ CC9DB7AB68D04C6368D7BA9771C6DCA9D062F301E615D7F731EFF80C3CD9023E
+ FBE467E7FE2F27C7FC089615961917A781658C65CDC5A2419B43DBE3620EB451
+ 68451645F71F59340E00A3A99882595578004FFDD3BB1D1933478F9D3E65A605
+ B108A01B19DCBD65BFDDD061F762A6E3C9C8D193FFAF16A3EF88760C22D99613
+ 57091EDAF6235FEBC62DB86D96FFA8ECC0BCF95BDAB7615E717D3F5FAB8FCF8A
+ CF8CCF8E3AE0C98E8065846525ECFA43D9621973D1166873687B5CCC81365A8E
+ 917FF2B1681C00C2183B0D19B65494703B5BA97AEDCF05503D6DC6BFBCF10E0C
+ E22CE1B6543F6908EDD8E5D806A13BE05AF7E4E92FDE49F444FFDEEB56F3B64C
+ 181D87D6050F54EDDBF9231C5363B86CFEA30507F38279C2BC917AFF43A2483E
+ 77C067C467C567766A9DFF6EB08CB0ACB8F80D50A6F18B37DEC132E6294583B6
+ 8636C7C51C689B29C6CE707151E0688B361F3C6F9A4FC07F968A38DE45AE0FBE
+ 71C4917164F0E13DBBDC8DEE67B9388DD8E5A123C99EAE929C85C70344FE6D5B
+ 7EA86BE959B708636CBC4C8276256FF4756446861C8DC8335770661F2FEDC0B8
+ FDA2D0DDF7822724E3E72FBEEAD4DEFE7BC1717F6053FD012E4E233D907E77EA
+ E849DB91849186170F3454B5125118B90B6F29CA87FCFDA260D1398043A65901
+ 99FE09BC9DD6BD04B7AEF7FED78E73E9E888EDC9178CEB56FDEDBDDFA73E62B9
+ 90823092993C7DED707A78A0646BBCDE96B6ADAED5D53FD24D7D4EBB113DAA1A
+ C98CC7AFA687867AD343C3239049DBAD9C18AAE02DBD7851A7ABCABF21651873
+ 0AD082B3FCA9DEB157F098344F721C775D6365C5AEF507C1A22D73252C41BAC6
+ FE70E2374E2CFBB943B56AF3FFD4BE1D5AFB7B27FF0CF8F05FBEAD28935C5E14
+ 2C3A07808013F816647C3B17734C0E92DB377F75C491D04B4A38ECAB7C7CCBCF
+ A84AAC61C80C9298387EE98F7AD45EFCB899C05B6B025BB71E7485BCCF26CDC4
+ 9CF722785D34694C6A037A2C3AA047224399C8D898994A163526C5C8BCAE7075
+ B5160ED76B815023DECF2FBAA23B1F18C32F134DBE1BBB70E1B013C13CF2A185
+ A0ACF66D7E1A9A04CB7D7CCC2013137FBAF48FE6F8789C27D962D58F0F345534
+ 90155CFC064ABF7C8BD2BCF736942B8BD2011C34CD40107A01D0CC4DF3F6F030
+ ACEFB5C10BB19E4E4726963C6DAD2B02F737FC045A7DCB528F91226313C74E7F
+ C492A5336C440B55867C6DED4F6B3EFDD1B974B345785D4A2C9356A366924C29
+ 462269A4CC04C63EC0E07E8AA2AA8CA81A71AB6EAA6A6E0C18A07849D0E53642
+ C98C595410561C9E60F45E0CE0E9440CBF99C0EBBD2BF7EF7A5CF5106B300E18
+ F7C7BE1CFC65AAB3CB91602681756DDEA6971BB6424B3FADDE406F2003639A5F
+ 1E5614DB7124E69B45E90010E805EC85CC5B0ED1245334D2FB9F3F75EC086670
+ EFEE6DEE26EF212E4EC34C9091C891531F31C3FE7EF2D9C83A82D6B647B56AFA
+ AD64CA7A5946398037F6E863CA9144D7E58F304C3A4F2E1954F5A8E103BB1F17
+ 85F842527DE97762274E3A765741F3DF3ED2E6F50863FE7D0E5D7FDB31051682
+ 45EB001E654CAB62ECAF40F996DD65A36748F7F00747C4076F8A20F4C481C7B5
+ 6AB69F8BD3D027C9EDC867273E2EC58CB6081C1AF837B4EED21A2A0EA8AEF486
+ 84207AEE7C824B7A785127DED587D77595B2AB7F37B8DC177E68EF635A85A03B
+ 0EE863F458F4C3231F71D136754F1EA8AED9495AB898032A50749CD27F2EB75B
+ 7FE7CAA27500C8F74CB3159ADEEF703107D4C44CCF3F755C488F8C3852283829
+ 58F5CCDEE7950011460B422710FDFCD4A7F3D113B81BB5AAA6DAD7D4BC5BABF4
+ EC50DCE975F3E50CA0C5CD684977AF11499DC32BBAEDDED25B28D8F2871EDCFD
+ 48BECA6FC6C8C5F1F74EBCE5C4A41FE2AEADD5D6FD75FB56A82C9609469590DF
+ FF56511CBD14653E59D40E0081A1C04BF01096ADBAF14932D2F75F8E5CE3A26D
+ 14B747AD7CEA811F521F119E10CC0E078E9FFEB8D47302F9500381807B4D73BB
+ ABA2B24509B00DD493599D6F234EA1787DC430D2AE3E638A5D31C7C62EA7FB7B
+ BB8D74DAF6D5DFC58063FEF0BE5D8FE5EBF6B304E99978FF8B579D38E67B87A6
+ 7F7F60BDBF42104998901BD0F57F9D8B8B9245EF005E32CD6AA8717F016F2DC6
+ 3E7C8C748E1E3D627BDBE71DA8CFE7AA3CB8EBCFEF0D267A079C189C3A79E953
+ 7DAA74AB0373855297E65E51DFA886C38D8ACF5FAB78DC354C6555AA8B05A992
+ DDA8430DC6B2AB0B2AA5B84AC09849E346864E51838E9BA9F4A899888F1891C8
+ 40FAF6D000639905EFE2E216DFE0DE2D8F0A27FC000CEE3971F8F4BF3A795949
+ CDC307C275FB89E8CE0803BA03AFBCAE28F3DAFB719A45EF0090174D739F49C8
+ 3E2EE6C0A1C0B55F745FCC0C0F3866105A45C8137C7CDB5F286E22BC569CE924
+ 36F5E5B54F4AB94F603982EBFCC1FBD73F4A356BDC7D04B7F94E7D74FE157D32
+ EAD8365C3CEBBFFEA72D5B445D7F186B1D7F43518E7371D1B2A013484EA151FA
+ 051492E546612CB8553F6A852EBBBDF881778306868686AD0D4F9A061A68C5AE
+ F54F397D827039E35DDFBA0A37F9E4ADFC50164E577EB419B41D51E5475B439B
+ E3E2A2664938003C7A09551C2F8DB48CFB70D9A6E1C5076D070EB91B34B4AFBB
+ 9A796E7CA1D05BDD547FA062E7DE6D4E1F205A4EA0EE5087818DF58F804E2D15
+ 11C98EF9A12C9CADFCB8DDF7C106D1921F8047D3DF5F2CC77D67634919E70B8C
+ ED628C59F682C343B25B878D8E89B3C71CDD838E1383A1271F782EDFEA0062C4
+ C9E0D4D94B9F9772D7E0520477F705776C7E5078B08783B3FDD10FBE78C7C909
+ 3FA472C7FEE0CA836A3B0C212DF583527AE44D4A1D3953500E2CADD68931FA3C
+ 63DF837796B0536021E9DE5F745F72723E00C125C2CA6FED7B4CAB660FF1240B
+ 2623A978D7F017A9AB9DC2002092E97836B4ADF1B7D63DA050EB71DB3BE863F4
+ B3893F1DFFD8A9A5BE3BE0B8BFF9A72D9B5522DC75D9FF16A5BF052FE0E8772E
+ 244BCB01002F3316CC30F6975042963DEB78AD58F7DF1FBF4CD3CE1A0D92DD31
+ B8D6FB6D22D8367C874C84F44E9D3F7FD68C4D3A7A067EA98031FC308C973084
+ F71D28D1D3D7937F983A71EA3C4F710CE676D196BFD9B74974C30F5494A48BD2
+ 7F81AE7F494E322E144BCE0120D00B68A68C3D2FEAC24D8D92A11BFF78C4763C
+ 38117876C0BFA5E165E101220EF60652D7C6CFC63BBF2ADB0B2317028CDEEB59
+ 5FB563A6561F0FF6C42F0EBEE6D4DEFE7B59FDEF0E34076B8431FEA06F49DF82
+ D6BF2476B3902C490780E43B2B804CF491FE81578F0C70D15194AA2A7FE5439B
+ 9F131E25BE0B2341461357FA4EA706FA4779D2B2042FEDC0B8FDA2D0DD778347
+ 7A273EBBF48E53A7FAEEA5F187071A2B9BAC4347041A9245BBD77F3696AC0340
+ C0091C8207B4DE07070C9F25D7460F1FB12C1D3A01CE0B54ECDFB1D3BDD27D70
+ A6210182C382C4E5CB1732E3A34BAA6B391B78579F7FD3A62D5A58BCB3320776
+ F96FA50F4F1E3B7BC6E9F1FE1D6A0E1EA8ADDB21B613F8C26B50F9DFE6E29263
+ 493B80674CD3E326E407F090969D6350B06CE8137265FCC491921D5775AF6DAE
+ F3DFBFFAB97C9B86EE8047738D51D233F5D5A58B4E5C4D5ECEE015DD7803335E
+ C22ABAABEF6E70730F86F14A5FED2D59C4A3AABD0742F58F9236C88868497C34
+ 45C86F16538CBF4259D20E00799EB1308CE07E006F2DC1220063E070EACAC4D9
+ 93256B7DB137107A78F7035A83FA18287BC6F3FC59471021FDC96B3D1DA9DBB7
+ 16F516D37BF1AC5859ED5DBFAE5D0D9335B3557C70CEE9CC20FB64F2E8C993A5
+ 6AF591CA1D7B828D073D1BE1ADE8CC448250FADF61DCEFD856F27264C93B00E4
+ 65C65664187B092CC9D21DC75062B7DE8D5D99BA70A6A42DAF6BCDAAB06FFBBA
+ A7349F705FB9053C5C94BA3DD19DE8BAD2C78C85B9B7DF2E5475A9BED68D4D9E
+ 15952DF90EEFDC8B9E209D89733DEF3B11BA7B26825B7706563E1BD808CDBEC5
+ 26A052E82E4A5F7F8DD2924C369613CBC20120DF636CBDC9D873E0042CCF3C5F
+ 4E00F16D695FEB6DA9798ABAF26F70990623197D9CF4A706067A13FD7D43F315
+ 77A05870F79E6F4D53BDA7B1B159AB226B40DBC21D7CF78277F5E1156D784B13
+ 4F2A19B3547EA650FACE6F2975EC246939B36C1C00F29C696E86423FC8C57B31
+ 6E7D607446CF1C2B7950C7EC24E103DBB7BA577B1F8691A7F0649B108324C119
+ DC4C8D0CDD4ADDE81F9CAFE01BB381414A3CABD734786AEB5742A55F051DEAB9
+ 5FA2629231BCA5172FEA2C6577FF0EA19DFB2B563EA9622F4C78541A1A83C3EF
+ 284AD9DFEAEB14CBCA0120CF33763F61EC312E4E03ACCF1CFA8474967262F06E
+ 702BB16FC7F62D9ED5EE870A720400CE17B03819D527F4DBFAD8C86872F0E6F0
+ 7CC522C033F9DE8655755A756D8D56A9ADA07E5233DBB8DE0254FCD48DF46778
+ 3FBFD35B79F331CB841F3C18FD18C6FC962BE89632CBCE0120874C73373CF8C3
+ 5C9C063A81B133E49A9321C566037B04C1EDEDADAE35A17DF9620DCC0533A34C
+ 997173CC4CA4A3FA542C6A262663466432566C7C022D18F6A9E18A80E2AB0868
+ C18A901AD0C2D4AB841557F13109F1E45EA63F7A7CEA5C47D77CB4F877C0905E
+ D53BC9FA7C951F123F7B435196C409BF4258960E0079D1341F80EE5EDEFDFB13
+ 3DA47FE0B5D26C169A09DC4DE86D6ED8412BC91630CA3987039F15183E3083A4
+ B32F460C66421B6CF0BB1655E2A20A81A12F51A94ADCF82AA81B3F0BA0E7149B
+ 201793BD83674BB58B6F261A5F3ED058B94EBCC907814A70EC4D4539C9C565C5
+ B27500083881ED609CDFE2A285C43819EAFDD5F1EBA5383B301B187D28B06D73
+ BBABCEDBCEFC64BDC2C463D672C5A4E05E12A4571F4A5E8A9DBFD4E164949EB9
+ 827BFB9B7FBC6FADAFCABABDF70E4BED745FA12C6B0780E0C420D4AC27A1860B
+ 75810788FA7ED5DDEDF429C242C04B4A7C1BDBDA5C35EE561220EB1CED193808
+ B6F424467A32A3E9AEC495CE4E33B27047A0F1545FD38F5B5A44077B10286C06
+ AF0FA1DB7F91272D4B96BD0340C009B4801378069C8070DB2E1E251E3A6C743B
+ 1D4FA01870E2D0D3B67EB5565FDBACF9D96AE223ABA0108BBA30C42EA0AF34B4
+ F237F538BDA10F8DF4A63AAFDD98AF09BD99C0F3FCF507552C53A15E405F3A64
+ F2BD7714A59B272D5BA403E064370B11728831F1CDB660EC2CD245FA06DFF87C
+ 10EC87A72E3CE8105CCD4D755A55558356E1A957FCAC81BA945AA2387C7988A9
+ 4CB18C3962C6E9A03E991AD2C7C70733BD7DC3E550E1BF41CB46F209B7922630
+ 6CA16D43973FEE22E4EDE5B0C9672E48077017CF9866089A8C1740297997E4F0
+ E6A19BBFEEEA59C821C15CC83A86C6BA4A355C55A5783D01EA717989A6F9158D
+ F928250A5308FEFBBA8534499A9AC4648C98A64E1344D7E32C95499AC954CC88
+ 8C8F67068627CAABA25BC12E3FC6F0CB13C62B0B38F1B134216FBEA728F3B2CC
+ BB18900EE01EF801A2A74131C2D36108185266E418E97132E4B8A478C20F1DA8
+ 6C7828BBC49777D721FCAC2709DDFEA57CB0A718A403C803C6135008D907953D
+ AF8EF0F291DBFFDAD1978E38730391A430DCE15A6DC59FB737892EEDB803141E
+ DE957E7CA99EE7B78B740033C0230BE1E460DE3571EC0D8C9D21D7E773E39024
+ B7B1672D18F04CAD7E9251FADE528CE4E314D201CC02C6184C33F634BCCDBB91
+ 04C1B981E1B76FF7397535B9440C5ED15D776845D34C637D4EBF9BD23F2EB518
+ 7E4E231DC05C608CBE40C84EC6B23704E7DD9003CA64D1413238FC56C72D392C
+ 7016ECEED73DDFBE32D4401A661A960106A5F4D89B849C214B287A6FA9900EA0
+ 005E344DDC517610C694755FA788819FEB135DE4E6C8BB67868D640C4449B1A8
+ DE8052FBECCEBACA56B24AC9B34FE30E60CC23F07AFF0D4519E2499259900EA0
+ 407ECE98721E2F2021642FBC663448DC4014E9A0B786FE786A98A6E3B2352A00
+ E6F6D3FAA777D785DBD9CA7C1B7AEE00468CBDAD93DB293DF577944A875B00D2
+ 0114C97718AB52197B021438EB1D806091A9F10E3A30FAE1E951331E2BEBF5F4
+ 8546F107D49A2776D554B5B3C6B96C7906AF7A03FAFC1FFE9ED2719E242900E9
+ 006C72C834378212F168B170CFF9DDE0D060AA9F0C0D7FD03D58EE1B89E61BDC
+ C853F7644B43700DA99FADABCF9984CA7FF46D45B9C26549114807E0008F32A6
+ 5531B6139489478C670D8105866BA626C9F8C449323C7EFAF368396D2D9E5F34
+ 52B5EBC150E51E52E7A92055A03FA8FB3303BF804733BF18A7F4CC2794CA8956
+ 9B4807E020074D33E023640F28152F0BCDBB5A7037301E484EF5802338767D34
+ 79B32FCD939734DE554DEEAAFD6B6B82EB481D2869AE71070CA8F8171330D63F
+ AC284B3A74FA7C221D400980614105A174AFCAD87DD02398B555BB031E3D9EBA
+ 4AC6C68EF78E6506FA97D410C1D5B8C655BDAFB93AB88154E73BA22B029467C2
+ 18FF2BC2D809E8EE973C5EE372433A801282878B3C94EE5418DB3C97A1C1DD40
+ 57602AD54F27263A9291C9F367E3F3193ECB193412DCBA2D10DC14A8F4AF2561
+ B7420A3A9D885D7D93D24B29C6CEC8C33BA5433A8079E0C78C79A38C6D851A7C
+ 3FBC023C79CEE0E4A11E27D1E44D3215ED4E4D4E5E0187B000518A6602A3EF54
+ 6CDCE10FB5782ABCAB48D0E52715605C05393D04FE2606AF2F43945EF815A572
+ 576589910E601EC13D041718DBA0936CBCBF26A8C145E91FFECED44D124B8F91
+ 786A185ED75389C9EECE84198FCCCB12A3E20FAB152D6D3ECF5A8FCF5347FCEE
+ 6AE2D71412808799F370E76EE0EFF0C04E9F0663FCAD945E956BF9F38774000B
+ 040E0FBC846C86B7ED50A1435FA7DA033E27932124654E929401AF7494648C04
+ D10DF85F8FC5F4CCD494614E8D19B8E8A0A77576C7616085D6DC1AC5C5372558
+ ADBA8241550B043435445CAA8F686EFCBF827814784193EE01A329B86517019F
+ 835DFB0E68E62FC96EFEC2201D401980D188D28CE175E27861C59C27C8162938
+ 91D7E9A6B44B46E55978A40328339E33CD06289466FE5A51EC30A15C80CC3378
+ 86DBF0EAC5D73B8A32C87F24290316B5712D7570F27082B1261810AF52095909
+ 15A8B6DC1D025678F86F14F27C53815725A57D7232AF7C910E601181E1CA3C94
+ 3632C61AC021D49A94D651C62A17CA29606567944E288C0D1B78128FD2C11463
+ 0332ECD6E2413A80450E6E430E315603051906A7103228AD840A89938A3897E0
+ 07E760EB0E01F85CACCC71784D82C389C26747A1759F80CF8D44291D95DB7117
+ 37D2012C75A08DFE2E213E2F0C27A026BBA0C5CE3A04E839A82E7EE82643880E
+ E9D91501484FC12F6492D06DFF1D210919544322914824128944229148241289
+ 4422914824128944229148241289442291482412894422914824128944229148
+ 2412894422914824128944229148241289442291482412894422914824128944
+ 2291482412894422914824128944229148241289442291482412894422914824
+ 1289442291482412C9728390FF1F97ED6E34D64226CD0000000049454E44AE42
+ 6082}
+ FileName = 'C:\Users\Programmer\Pictures\Icons\'#931#969#964#942#961#951#962'\icon_simulation.png'
+ end>
+ Align = Client
+ Size.Width = 444.500000000000000000
+ Size.Height = 313.000000000000000000
+ Size.PlatformDefault = False
+ end
+ object imgPeerUserVideo: TImage
+ MultiResBitmap.Height = 256
+ MultiResBitmap.Width = 256
+ MultiResBitmap = <
+ item
+ Width = 256
+ Height = 256
+ PNG = {
+ 89504E470D0A1A0A0000000D49484452000001000000010008060000005C72A8
+ 66000000017352474200AECE1CE90000000467414D410000B18F0BFC61050000
+ 4A6C49444154785EEDBD69705CC795A89979EFADBD5028EC0417102401901037
+ 71114951A2244BA216DBA224B764BBDD1D6DBB9F67625EC44C77CCC49B989F8E
+ FE39332F5EC4EB9988F7625E77DBEE68B9F52CB5B5D9962C4AB2245214497111
+ 3781044002044882D80B05D47EEFCD39A7942C11BC5900AAEE2DA000E4C7A860
+ 9D045095F7E4C993FB4922914824128944229148241289442291482412894422
+ 9148241289442291482412894422914824128944229148241289442291482412
+ 8944229148241289442291482412894422914824128944229148241289442291
+ 4824128944229148241289442291482412894422914824128944229148241289
+ 4400E5FF4B962A8CD19718F3C23B9F41886612E23128A52A218ACA980B7F05E4
+ 0CFCCC04992984A4E0673A24275EA734492865F83B92A58974008B9C4719D342
+ 8CD5404186A1E286A08287A0C686E047155099FDF01E2B7FD1C0E726E133E3F0
+ 7612DE47E133A3E02CA2F0B99128A5A39F508ACE42B248910E6011F13263EE34
+ 212BA1A16E80CA5E0B95B01692C3F0FF8294237C297C3589C0FF23E01446A063
+ 31E826E4D66B944236258B01E900CA981F43D77D82B12668815741855F89157E
+ A12AFB5C41A7C01DC22DE82DDCACA4B4EF573894909425D2019419CF99660314
+ 4A337FAD28F70A3F1B907906CF701B5EBDF87A475106F98F2465C0A236AEA502
+ 567A682DDBA0305AA192E0F87DC902CF88F3075DD0ABE994CE60E1910E608138
+ 649A3849B705DEB63B55E9E17332194252669CA4F408496762246D4C115D9F84
+ D7444CD71353BA393566E01CBF6EEACC8C46A0A74E88120AAB9AA251A2C1FB60
+ B5AAF9829A5619D0B40AA2A941A2B902C4AD85895BF1138F8B100F184D76F5C0
+ 2EE80CE0BF0E700617DF5694C9AF5325F3897400F3C8CF1953CE30B65EA1740B
+ 656C2D54D8A2F40F7F67EA2689A5C7483C350CAF1BA9C4E4D5CEC49D0A5D6AD0
+ 61546C68F379567B7C9E3AE2775713BFA690003C0CF8B4C281BF638CD2EB2663
+ 1777527AEDEF28059F20990FA40398075E324D1F34BA5BE1ED76A8BC81AF53E7
+ 0ED4065D8F9368F226998AF6A42627BF3A1BA7E90C7C54F9C0DC2E5A71DF0E7F
+ 689DA7C2BB8A04353F098137803E45618041C6E0BF73F087175E5794C4D7A992
+ 52211D400979C634436E42764145D80CB5B5A0CA9026642AD54F27263A9291C9
+ F350E1CDF2AAF0B3C1147008DB76F82BDBBD61CF1A56097A08F21FCD09304CE8
+ E4904BA087D3EF290A0E152425403A80128015DF47C85E78DB0E463CE76E71C6
+ 24935357C9D8C4B1EBE3C9C1BE25B596EE6A5CE3AADED75C1DDC40AA5D0AA9E0
+ C9B302CAC3E1400774054E4847E03CD20138C841D30C40C5DF034AC5C93DF5EB
+ D49981417B72AA870C8F1FBB3E9ABCB9B42A7D3EBCAB9ADC55FBD7D604D7913A
+ 50D25C772A1AE00C2E4D812338AC28384C90388074000E80DB71AB18DB09CA7C
+ 009AAB5967C871122F3549C627CE40C53FF139B46ACB7537AD46AAF63E18AADC
+ 49EA3C15A40AF4376B6F097E01C7425F8C537A466E43B68F74003679C134DBC0
+ 200FC0DB59BBB5389937D54F86863FE81ECC0C0F6478B20470D535BAEA9E6C69
+ 08AE21F550C9E7325F8267138EBCA9289D5C961481740045F23C6361C2D813F0
+ 76CDD729F9818A9F1AEFA003A31F9E1E35E3B17959AA5BAC28FE805AF3C4AE9A
+ AA76D6088EC0C39367A25FA7F4A3DF533ACE65490148075020B8967F9EB15DD0
+ EAEF85D78C2D15D4F474A483DE1A3B7C7AC448C670324B324798DB4FEB9FDE5D
+ 176E672B5542DC3C590818B10EAF13DB283D2DF7101486740005F09269D641A5
+ 7E0A2CAC8E2709819FEB135DE4D6C8BB678664C5B787EA0D28B5CFEEACAF6C25
+ 2B671B1AC0CF87C159BCFFBAA20CF324C92C4807301718A32F10B29331B61FA4
+ BCB3FBA04C161D2483C36F75DC4A4746E4049583B8C3B55ADDF3ED2B430DA401
+ 7A5E33D92DC63B39F6262167643093D9910E60165E662C9866EC69783BE3583F
+ 9D2113836F0E5E8FF574CAA3AF2524B0AECDDB70A861ADDB432A79523EFADD94
+ FEF1354AA7B82C11201DC00C3CCF583365EC196846F2AE55C3CF32A36749DFC8
+ E123A33C49320FD41E3C5053B383348101E75D76859F2519A5EFBD45692F4F92
+ DC8374007978C134F7C07F0FCED4DD8C4F9291DBAF75F4A54764777F2170D7D6
+ 6A2B5E6E6FF2576423230981C2C361C0E76F2ACAC9AF532477231DC03D3C639A
+ 1E37214F8362D6F3240BD8EA8F1C233DA3478F4478926401A979F840B8763F59
+ 076596B7370065762D4DC81FDF5394144F9200D201DC053FBCF30228A59A2759
+ 48A7C844FFAFBBAF95FB461EC5ED515D8D75956AB8AA8A7A3C3EC5EBF2134DF3
+ 2B1AF3514A14A610FCF7F5F29A49D2D4242663C434759AC0B38766321367A954
+ C2888C8F67068627CC74AAACF72FE046A2553F6A5DE7F5B0304FB2004E600C9C
+ C09BF24CC1374807C07999B11519C69E0323111ED70545B1B12ED237F8C6E783
+ E5B475375BD19B9BEAB4AAAA06ADC253AF78593D75931AA23A1C59C820519626
+ A366920EE993A9217D7C7C30D3DB375C5E8E41230D2F3ED8106ECDCE0D086D9B
+ 521A876EC2DBAF517A9B272D6BA403009E33CD16153A0050F985EBCCB8A167E8
+ B0D13D71F6D882CF286385F7B4AD5FADD5D7366B7EB69AF8C82A28C41937CA94
+ 0AD0579A24C84D3D4E6FE84323BDA9CE6B37CAC12154EED81FAC3FA862990AF5
+ 02FAD22193EFBDA328DD3C69D9B2EC1DC021D3BC4F21E42018B350177844B7EF
+ 95DEEECC40FF8275F99570D8E7DBD8D6E6AA71B742FF64DD1CB7C8CE3B262129
+ 12233D99D17457E24A67A719892C58400F1C1234FDB8A525DFD163286C8C5EFC
+ E11B8A7291272D4B96B50378D134B783D17E8B8B16121132DCFBCBE3BD0B117D
+ 87FA7CAEC0B6CDEDAE3A6F3BF393F50A9BDBF1E272C1A4C4A071722D339CEC88
+ 9DBFD4C112897977A018A5A8F927FB9A7DE1FC3B37614870E44D4A4F7371D9B1
+ 6C1D00B4FCBBE1E11FE6A285893ED23FF0EA91012ECE1B9EB6D615DEB50DF7D3
+ 30D9EA644B6F1A2445E1C50C92668C18CC8406DB205F574A95B8A842144A894A
+ 55E2662AF128F0CAFECC01B067C026C8C564EFE0D95467D7BC8FBD1B7F78A0B1
+ B229FF462ED0F367D013F8828BCB8A65E90066AAFCD0D49BA36749CF7C6EECC1
+ F059C1EDEDADAE35A17D8A8734F1E4823175658A25CC8811D3237A7C326AC626
+ 63466432A64F15D715D782619F1AAE0828818A80E6AF08A9012D4C7D4A58D1CC
+ 82C27BDD8D99227D99FEE8F1A9731D5DF319E6ACEEC903D5D53BC97A2877A8EF
+ 56202347DF5694535C5C362C3B073053B71F2BFFE0A7A42B72FCC8044F2A2938
+ A1E7DBB17D8B7BA57B3FD5480D4F9E133080652C4E46F5A83EA88F8E8C24076F
+ 0EB364725EBAD9D4EB75791B56D56935B5B55A486BA07E52435961B6C474329A
+ BE953E96387BEEE27C4D1C86F71DA86C7884B4E6730290F827E8099CE3E2B260
+ 593980E74C733314F2412EDE8B71EB03A3337AE658C9E3D3675BFCDDDB377BD6
+ 781F01ABCBBBE7C0824192FA38B9991A19BA95BAD13FC832F353E16783BABC2E
+ CFEA350D9EDAFA954A15595DD0F0C12463A9FEE4A753A7CE5D9A8F1E4168E7FE
+ 8A954FAA6DF05638A7028DC3E17714E51217973CCBC6017C8FB1F5E6D7EBFC96
+ 678642D76FBD1BBB3275E14CC963CDF9B6B4AFF5B6D43C455DA48127CD0C2319
+ A8F4FDA98181DE447FDF1065FABC759B8B81518DFAD634D57B1A1B9BB52A1877
+ D3B95D22C2326430D93DFA7EE262C7759E5432825B7706563E1BD8088D8165D9
+ 178C832994BEF35B4AAFF1A425CDB270007C93CF4B507344EBFCC68D775397A7
+ 2E9C2C69E577AF6EA8F46F6B3DA804C8269E34234602BAC8B727BA125D5D7DCC
+ 28EF5D78F9A09A4BF3B56C5CE35E51D9AAFAE636C4D113A43371AEE7FD4CFFCD
+ 926EB30E6EDD1358FDAC07CBC2D213804AA1BB287D7D396C165AF20E8087EEFA
+ 01BCF57D9DF20D38E61FF8C0B852CA6E3F76F7430FEF7E406B501F0365CFBA61
+ 479F207DC99EBECBA981FE2575BAD0D3B8A6C6BBAE69935639FB2427944B5A1F
+ 343E8E1E3DF545298705381C687C52DD08E5229A1348B8297D159CC0BCCC072D
+ 144BDA01E0C11E188C7E1FDE5A5A1F787076FB137265FCC49192ED0B77AF6DAE
+ F3DFBFFA39C54D56F2242138A1678C929EA9CECB978CF1D1257D7E5DADAA0906
+ DB366D566BC8BAD9260ECD34B915FFF2C63BE9EBBD258BF053B5F74068C5A364
+ 2378194B5E20612449C86B4BF900D1927600874CF3103CA0F054DFF059726DF4
+ F091112E3A4EF0E13DBBDC2BDD07A1399B318C15B6F8B1CB572EE86323CBEA80
+ 8A0B1C81BF7DD3F6597B0494E8E95BE9C353474F966CB34ECDC103B5753BC476
+ 028EE1DADB8AF23617971C4BD601E0797E283C0CE165A1949B7C70DB6EE5C35B
+ 0E511F69E54942708C9FB8D2777AA975F50B058706BE8D4DBB669B236009D235
+ 71F4E2DBA5DA5E3CD36621A824C7966A3C8125E90078249FE745DDBAA9513274
+ E31F8F9424428CA76DFD0AFF96952F53357FB82A939154AA77E26CFCF2C51E9E
+ 2401FC6DF7ADF3ACAFDAA1D0FC4B88CC2013F18BB75E4B755E2BC9E4DCEA7F77
+ A0395843EAB998038C086F2F7E6B2946165A720E0063F86518FB4BA8FC96305E
+ 78B0A7FBEF4F5FA6E938FCD859827B776F73AFF57E7BA62E3F76F727CF9D3F6D
+ C62665DC40014AA0C25BB17DDBAE1987053824B89EFCC3D48953E7798A636028
+ F296BFD9B5497480082A4AD245E9BF2CB518834BCE013C6F9A7F06FF59BA7278
+ A4B7F717DD979C0EE4919DE57F6CDFA3AE1A96F75C0163249DE81EFD22D17DB9
+ 8F274966C0D7B2A9C9D752F300A5F9574DF431FAD9C49F8E7FECF42A019E226C
+ FE69CBE63C4789FBDF52947FE3EF97044BCA01BC8017763086D7744D03BB7037
+ 3F302E3BBDDC875B79434F3EF09C12C85E062AC48893C1A9B3973ED7A30B7734
+ 7631A285C2BEE08ECD0FAAFEFC1BA6CC18B918FDE08B779CDE4A8CCB83AB9E54
+ 378986904BEDF4E092710078690734ED3F84B7968D1DE35DE4FAE01B4706B9E8
+ 08785C37FCC4AEEF531F59C7932CA407F54BD1B3A72F94FBEEBD720577158676
+ ECDAEA6ED036F3240B2C417A221F9EFE8DD3C78D1B5E3CB0A2AA553814315C84
+ BCBA542E1F111E8A586CC0B85FD509C1D8FD96CA9F4CD1C8D761BC9C43AB0879
+ 2A0FEEFAF3BC959F113D7679E8C8E49913E765E52F1ED41DEA1075893AE5C9D3
+ C032C0B2C032E1498E0036731BE33F72F16EB2B68636C7E545CD92700029C676
+ 432DB3848686B4CCCD5F77F5C08891A7D8070D2DF8F8B6BFC87B6CD72089C9D3
+ D7DE4FF674DDE029129BA02E51A7A85B9E340D2C0B2C13679D804E30F82BDA10
+ 4FC881B6A633F6001717358B7E08F01DC6AA34C6FE12DE5A3CF2F031D2E964E8
+ 6EECF6636B93AFF21B29323675F2D2A7C59EBF77124A5CAA6B457DA356155EA9
+ F8FCB58AC75D43351686570555981F7F254D5976A2CBCD681AFE63CCA471A6D3
+ 497845CC547AD44CC447F4F1C8ADCCEDA10146320B7E1E01E31304F76C7E44F5
+ 884F5062AC8189C3A7FFD5C9E100861CAFDB4FF0F4E0BDE050E015180A8C7179
+ 51B2E81DC021D37C091E62351773E0A51D7DFFE5886327BA70C2AFF2E9077E40
+ BDE21D6366828C448E9FFE78BECEE4DF8B1A0804DCAB9B37B94295AD4A806DA0
+ 9ECCEA64427CE4B550BC3E621869579F31C5AE98636397D3FDBDDD463A8D4E63
+ DEC15804E17DBB1E537CE2CB40704E60E2FD2F5E757262B0E9DF1F582FBA7C04
+ 7A0237DE5694D7B9B82859D40EE07BA6D90AA5FC1D2EE6C06E5BCF3F755C70EA
+ C61E5CEAAB7A66EFF3F966FBF549723BFAF9A94FE7FBD49E5A5553ED6B6ADEAD
+ 557A7628EEF4BA447A7E867450F9325AD2DD6B4452E7127DBDA78CF1D1796D05
+ A9EA51430FEE7E44AB202B78D234707560FCBD136F39B544883710ADFBEBF6AD
+ 50592C479BC1C3FEFEB78AD2C5C545C7A275008F32A65531F65750C296F8F7A3
+ 6748F7F007471C33CAD013071ED7AAB337035BF8BAF29F84CA3F3F5D640CBEE1
+ 6BD9B0D3555FF988EA4A6F98AF4A9F0F9F9B9846C67D353334F169A2FBEA99F9
+ 0A52822B04E187F63E96CF09E863F458F4C3231F71D1361852AC662769E1620E
+ A840D1714AFFF9134A9D9B689A4716AD0380AEFF5EC8FC835CCC81B3FEBDFFF9
+ D34E2EDA26B067F716CF5AEF0B5C9C46B6DB7FE4D447F3D1F26BA1CA90AFB5ED
+ 51AD9A7E2B992A3E265F29F17A94297D4C3992E8EAF8508F4E94FC7013F604C2
+ 07763F9E6F3890EE4BBEEDE48EC1E6BF7DA44D74F310D8E1A23D2BB0281DC041
+ D30C400DF889794F970C1E86F5BD317A21D6F595235B6D31426FE0FE869FC098
+ C2B2BD97A5C9C4F867A70F977ACCAF064341FFA6FB9ED57CFAA3C91976C6CD84
+ 9791B4696813990C8D28462269E8668299D088EABA4E554A99AA6A4455DD54D5
+ DC54D3DC9AC6420AD5C376BE4F4F689F243A3BFE586A47807302550FED3A48DD
+ 82F31794E8B12F077FE95424E240EB7DDEA6176BB642AF735ABD812E58668A90
+ 5F1E5694924794729A45E9009E67EC31C2D8FD5CCC3139486EDFFCD51147B6DB
+ 664FF53DBEE567C2833D06494C1CBF04C65DBAD97EECEA07B66E3DE80A799F4D
+ 9A89392F6F795D34694C6A037A2C3A90999C18CD4C44C6592C569461D24020E0
+ AA0C57B92A2A6BB440A851ADD01B931996F7AAF47BF12ABE54269A7C3776E1C2
+ E1520E0D70D760E5BECD4FC380DC1AF4C52013131F5DFC07A74E11AEFAF181A6
+ 8A06C1B083D22FDFA2F4632E2D1A169D03C0C33E69C67E0A6FA7CD70635CBFDE
+ FFAFE37C3AE2CCC45FD5771FFE81F0482F2399C9D3D70EA787074A1629C6DBD2
+ B6D5B5BAFA47BAA9CF298C9647552399F1F8D5F4D0506F7A6878043209EA2805
+ 5471D7D7D5BAEBEB9B5D55FE0D29C3C87B11E7DDB8DDDA58AA77EC956477E705
+ 9EE438EEBAC6CA8A5DEB0F82455B26EAF028F1D81F4EFCC689494177B8566BFE
+ 1FDBB741AB7F6FAFD0800FFFE5DB8A52F2A0B24EB2E81CC0F3A6F904FCB7F56B
+ E91B9CDCEE9B0DE6D1E87E968BD388758E1C495EBD52924D3ED9EEFEB62D3FD4
+ B5F41E9E9417EC66A712B43B7DA3EFABCCC8D0826C4B75D5D6D7B95737DDE7F1
+ B196B90C1734DD7D327EFEE2ABC654B42427EABCEB5A570736D55BCE8220E981
+ F4BB4E05156978F14043552B59CBC5BBB9F096A27CC8DF2F0A16950338649A15
+ D0ECFF149AB76933DF0694EFB5BF3F73DE48C66CB77CEEA6E6DAE0BED53F138D
+ FB716F3F6E4DE5A2A3F8D6B7B47BD7D7FC249936AA7892102F51A65223B10B89
+ DEEEAFCC055A8BBF17C5ED76FB9A5BEEF3D406B626C9CC13945EB71A49F68CFF
+ 3271B5F32B9EE428153BF76E139E1DA0449F3A7EE31FD27DBDB6A340A9DE80B2
+ FE6F766E035B9CE6F4C0284DB0C55F2CA65EC0822E21150AA574D7BD951F8974
+ D05B4E547EA6B915FF8ED58744951F4FF5E1C11E2E3A062E6755EC7AE039DFFA
+ F0DFCE54F915378DB3E1A923E3C7CFFC3AD6F9D597E552F911CC0BE609F34686
+ E29F615EF98F2CC033867DEB427F83CF8CCFCE931D03CB08CB8A8BDF00658A65
+ 8B65CC538A066D0D6D8E8B39D036D146B9B82858340E00037C2A8C593C3B283D
+ 35F4C7538E748143FB77ED1605F0C47BF5A64E5D3CE6F4C11EC5EDF7861FDEF3
+ 3FEB01F65CBEF57CDC8547278D73B1CFCEFF3AD175E522338D79DD6C540898B7
+ 7877C779CC2B9934BEC4BCF31F4D039F159F199F1D75C0931D01CB08CB0ACB8C
+ 27E5C0B2C532E6A22DD0E6D0F6B898036D146D958B65CFA27100D0D7DA0A0AB7
+ 4CF04C7491DB4E44F8C1B8FD18BA9B8BD3485C1D39A9C7261C8DE2A3866BAA02
+ FBB6FFEF699AB6CC67DC4163AEDBD1D33DAFC52E7C798C65D20BB2C5B81830AF
+ F10B5F7E8E79C767E0C916F0D95107A80B9EE408585658665C9C0696B16BCDAA
+ 394D5ECE04DADC7807B5C495441B455BE562D9B3281CC0CF195320A33BB89803
+ 94AD8F1C3EE348EBEFDBDEFA24F4472D1359D938FD0E4FFAB9EA1A1A82BB5BFF
+ 0F9D64844128B3ADFE48E2F3E8E727DED22363E33C79D18179C767C067C9D71B
+ 401DA02E50273CC911B0CCB0ECB89803CBD8BF6D1D4E24DB66EC4FA747D006B9
+ 98036D75B11C175E140EE00C63EBA1890F7031C7D42D32644CD91FFBE3755DAA
+ 9FB473310706F0C4187E5C740477C3CA95EEEDCDFF219DD68527DA5CAA1A9D3C
+ D7FF068EA9B153CD931731CCC467C167C267E389D3405DA04E50373CC911B2F1
+ 170543012C6B2C732E160DDA1EDA201773A0AD6618DBC0C5B2665138008552CB
+ 211C50B239FCC76EDBCB7E78D007EFEAE3E234307AAF93013CB5DA867AD7D635
+ FFAB99368451835DA6EBC6D4C973FFB650CB7AA5049F099F0D9F91274D037582
+ BA411DF124DB60D9A57AC7CF72711A58E658F65C2C1AB441B4452EE680B44531
+ 0C287B07F08C69862863166F9D9A24E34E04F8C45B7A45177562DC7E27437767
+ C7FCF7AFFBDFF2557E35462F474F1EFF83914A2DD988C1F86CF88CF8AC3C691A
+ A81BD491937302F1CEAF7AB02CB99803CB1CCB9E8B45833688B6C8C5BB5903C3
+ 80BCE1E1CB85B277005E42368337B578EA8933C4762B8967FCB357740BC04B3B
+ F85BDB28BE802FB8A3ED7FC9D7ED275103BAC8A7FE041DFEB29DE1770A7C467C
+ 567C669E340DD411EA0A75C6936C93AF2CB1ECD106B85834F96C312D58B52A37
+ CADE0140DFCA729B2ED492E4F889CF6D1F32F1EDD8BE053460A9949908E975EA
+ C61E46290DECDAFE3FA48D8C2568499648FA64FCE2979F7369D9907D6678762E
+ 4E0375853A43DDF1245B6059629972F11BA0ECB3366013B445B4492EE680866B
+ 237F5BB694B50378CE341BC0022CDDA8A91EF4B8F6B6FCE3F8CFB3DAFD101773
+ E0459D89CB971DDBF013DAB9FBBBBA92161A993A619C897F7561C984982E147C
+ 76D40117A7813A43DD71D13658A658B65CCC8136607F2E40E736391DB45DB461
+ 2E962565ED002073A2586C64FCD875DBAD7360D7E63651EB8FB7F4661CBAA1D7
+ B7A1ED3E5715B3442C4268827E3579E9CB135C5CB6A00E50175C9C06EA0EB748
+ 73D11658A658B65CFC06B081AC2DD8249F4DE6B3E172A1AC1D007850CB693CBC
+ DE2B79B3CFF636587763702F7F9B035B88A9AF2E5DE4A22DF0608FB2AEEAA7A2
+ 1D7E6ED375237EEEEC512ECE2B5473A9AEBA15214FD3DA1A7F6B5B23BEF03DA6
+ E1CFF8AFCD2BA80BD4091773A0EEBCEB6B7E8ABAE449B6C0B215F50244B65028
+ 6893689B5CBC9BB276008E8CB14AC1CB8CAD483386177D4CC389537F78896760
+ FBCA9F7131076E1C9938F6D9675CB445C5FEFD3F139DEAC3B5F0A953E7FECD48
+ CCC36CBF4AA96F5D6BBDA7A9A6C9DBC01A55B75EC3180BA93E9FD0F11B898409
+ C3EEA891D64693837420D537DA97E8E91A2206B3541AA7513D1E6F70CFF63FCB
+ 188625C41B9E229C3C76EC1FB8688BCAFD0F3D24BA7B3076EED63FD8BD7434DF
+ 294137A5AFBE4669492E34B54BD9EE566AFBF9CF711DD5327176EB0FBD3DE654
+ D4D60699E0AECD0714AF75CF7FFC72DF09632A6A3B70049EE76795DAF7B89803
+ 77C3C52EF6FD5E8F464B1A25C7D7D2D6103AD0B6A7E681FAA7036DE19D9E1AA5
+ 49F528D554D3BC8A2BFF78177F86BF83BF8B7FE35F1FD81A6AAFDBAE35375710
+ C39FD0C7464B16F18619866EC633B703AB2B37EAFAF45E93A918AB3457B017BE
+ DFB2E9A660741277AFA8B46CD2517D152C75B5AF9B8B45919E60E9EAEDE1462E
+ E600638D5DFEBBBF2BCB7B22CA7608004D8EE5D61D1D149919E8B7B5F68FB1FD
+ 69A535BA2FC6F77362E61F23F960300F2E4E2371337DAA949B7C423BF7B436FC
+ 74CF8F6A9FA8FF5160857A3F3CABEDA534FC0CFC2CFC4CFC6CFC0EFE23C741DD
+ A08EB8380DD429EA968B4583658C65CDC51C6813681B5C2C0AB44DB4512EE610
+ D972B950960EE025D3F4413355C7C51C897E6AFB928FC0B6CDEDF0D096D35AC9
+ 817147028906B76C7D4A14C9C76D6A4389CB17856BDF7609B46F5EBDF2A77BFE
+ A2F201F777DD6E77C9669DF1B3F13BF0BBE03B57F16447411DA1AEB89803758A
+ BAE5A22D9237AD658D3681B6C1C5A211D928DA32DA3417CB8AB2740069429AC0
+ 6B5ABAAA539793B6C370B9EABCD642662493ECB67F951746EED52ABDCF703187
+ D74DCC5877CFA7F0458EEEEDC716ABFEC5070F563F52F5B2EA763BB6857636F0
+ BBE03BBF8FDF6DB7D5B4C2B2BA429DF1841CA85BD431178B2679ADEB065ED9CE
+ C51C5ABDD7F6C61D918DA22DA34D73B1AC28D72180F54C3E34029173676D8D41
+ 31D027F35B6FF6D1C749BF1371FD7D6DED4F8B027866C688E361BBBCCDEBEA1A
+ BFBFF9479E7A754E1B59D25142A25708193D3E4606DFEF21B7DEBE486EFEDBD9
+ EC0BDF631AFE0C7F077F772EE077631E302F3CC9115057A8332EE640DDA28EB9
+ 583458D64684F473F11B7CA4196D844B4581360A155E344C75F4A0935394A503
+ 5005CAD2E3246A37A8A36F635B9BC2AC139FC98181EBFC6DD1645B7F9FFE2817
+ 7360749CD8954B8EC68C0F3EB06763DD23D53F54BD5EF1D6624E72142AFC49B0
+ F4FF7E92DC7EEB28899C3C4A625D5F91D4E04DA24F4488118F655FF81ED3F067
+ F83BF8BB37E06FF06FF1336602F38079C13CF12447409D89220BA18EB550D8F6
+ 1EFBD42D6B99A36D04DADB2C3B4F0B016D3419B72E078A6CBA1C283B0780D154
+ A0965B2E7A48DE24B637E7B86ADC96092C3C2E9AECEFB37DAAD0DBD2F6982830
+ 26BB153F67A6929623A9C552F9D8FEFBAB76BABF4D7C3E4BD8B23BC46F1132F0
+ FB2B64E80F50E1AF5C24AC88E86126FC0DFE2D7E067E167E665E202F9827CC1B
+ 4FB10DEACCBC11B39CE4431D7B5B5A2D8EB65012FD7D43C4B06EDF55ABDCB68F
+ F126FBAC0E006DBA1C2305959D03F013B202C74C5CCC11ED4ED90AB4983DF411
+ B0CEC69A5172C36EA8AFECCC7F0DB54413C218FDF19EEE4B5CB44DF8B1FD3B42
+ 1B956F71D1421A5CE4ED77BBC8C8874761D8E1DC88033F0B3F133F1BBF231F98
+ 37CC23176D93B8D6790983A0723107EADAEE8A0096B91E2537B9F80D6023760F
+ 08C5AFC5440E80A26D73B16C283B07A00B9404CA3327AF9CCD1B68722E78DAD6
+ AF8687B578E0D4E0D04C6DDB9CC0BBFA44D775256FA7CE3B15CAAB62EFFE4D15
+ 1B1561C83204C7EEB7DFFA8CA4471C898C2E043F1BBF03BF2B1F9847CC2B176D
+ 8131063102321773A0AE51E75C2C1A51D9A38DA0AD70B128A29D17702F89654E
+ 4964DB0B4DD9390070BD96EEBF6E92184DDB1BFF6BF5B5CDFC6D0EDC169ABAD1
+ 6FBBC6E0459DFC6D0E8CDB9FECED72645BB16FDD8686F0C6D4412E4E039532FC
+ C9ADECD81D4318951CF80EFC2EFCCE7CDF8679C53C73D11689EBD73A50975CCC
+ 21D279A160D98BB6068B6CA510D0563326B1345822DB5E68CACE014069589494
+ 1EB32AB350B420B3C4DF6371326AF7CA2ABCA21B6FE9E5628E4C82763931F657
+ BC0177C581C6EF88C6FCB84E36F8FE5592E8BBF675C23C82DF89DF2D5CD784BC
+ 629E31EF3CA5685087A84B2EE6409DA3EEB9581458F668035CCC21B2954211D9
+ ACC8B6179AB2720078E537FC6789D89A1AB6E700B2633A8F606521AADB6EFD7D
+ 6B9B77890EFC246FF475F0B7B6A87976DB231E9FF54834365B4338261FB404A6
+ 9D37F0BB310FA29E00E6B916F2CE455B8874893AF73535DB0EF12DB401B015BB
+ F707E4B1D930B7F1B2A1AC1C403563D5604C9609C0D4F594ADFDF9AE754DF5F0
+ A1D688BFA323F66F89A9F45866BEB377F539B0EE8F27F5BC15E25802239FDC2C
+ E9787FAE601E86FF649D4B433C90777C062E160DEAD24DB4312EE650C39EEDFC
+ 6DD1886C006DC5BB61ADAD218CC866D1B6438CCDE9BEC7F9A2AC1C8041883016
+ DC6477A72D07A085AB84BBE49283376D555235100808BBFFE3F1ABFCAD2DC20F
+ 871F87EEB47545E43276C11D0B57689BE48D9E6C9E2C40DEB3CFE0007A346679
+ E0EC3000CA808B4591CF06F2D9CC5CC967B35098B6EF247092B272002A21966D
+ 9EE03533663C626B979E56E1B11426D349CCEEDDFEEED5CD9B44DD7FBCA597BF
+ 2D9A8A1DBBD68BB6F7666284444E3B7262D951304F98B77BC167C067E162D188
+ 748ABA77AF69B6B57F1F6DC0D4AD4B8D229B2904B459305A8B7D896C7C2129AF
+ 1E00A596B12E68D0FE449A9F59BA73664218C9B5205CA14ACBC6225CFBFFFA8A
+ 6E7B78B7ABC22015A39F41E7623E66FB0B05F294CD9B807CCF5208A853D42D17
+ 73B82A2A5BF8DBA26109D3728047643385020EC062BB221B5F48CACA01288C59
+ BCA33969DF01504D10FA2BA6DB3E59A804AC973F1893DA009894AD433F789EDF
+ EB715BD68C7137DE424EFACD06E62D66DD614FF059F099B85824CCFC5AB7D311
+ 9541A1886C4164338522B25D918D2F2465E50018A516E5E893D635E042C8AE00
+ A8D66E971E9FB415948312974A3DD648BF9968D4FEC6A2CD35F7F1B7D398383B
+ C30E9C32217A4EBCF891EF990A418F452D0E00CB00CB828B4521B405B019BB3B
+ 02F3D86E05FFBF2C282B074019B3DC140BE34A5B0E405BD1289C583463315B27
+ 0B5D2BEA57241338A49B8E3119B137FBAF52EAAF4C5B0ED6A4C640170E6EEF2D
+ 1599F151E101A2EC33C1B371B128F4A855B758065016B6561ACCD8A4D016F2D9
+ CE5CC963BB651517A07C1C00631446B6160700DD285B13755A558570CC654427
+ 6C3900AD2A2C0C8891898C5996AB0A21D0B271A52892CF54E7E2B92334D66555
+ 4136B2103C1B178B221D9D10C68380B2B0F5B946248F03C8633B734564BB591B
+ 075BE7E28253360EE0BB793C6366CABAA7BA1014AF47B84C04AD89ADA545C5E7
+ B7ECEAF2BA9498DDDD7FEEB555C27DE889EB96CD70654BFCBA38B45EBE679B2B
+ 0C7A6DA26DC1A2B228047D2A92106D09CE673B73259FEDBE24E8E92E1465E300
+ BC7994A2C762B66E00A11E97B55721B831B650A8CB6D098291498B6FBF2D044F
+ 2DB34CFEA5A1DDC3E3B98B053C7E9C12B4D56A2DB3BD29C8649A75C6DEE3B6BD
+ B986E982EEBAC763ABBB3E83ED96CD30A06C1C00B84AE159697D3C62CB01104D
+ F3F37739A8030E40710B562C92F66316A85AC6B2FE9C5CF80D7F059312E4D9A3
+ 656C470ECAA4A8C5B5508DD9DE5C23B209AA29F61C401EDBCD67EB0B41393900
+ E1B8C848256C2DA929AAB567C10C7B138B08D398E5F8AF62246CC5FAA76E97AA
+ F87C96CFCD446CAF58CE3BA23CE3B3E13372B128443A169545A1886C42D1982D
+ 0790CF76F3D9FA4250360E40234418E081A632B61C00A8DAA26C53C7A3D9F650
+ 1566191F1ABA696FCB72558DD090F5C8E29900BC43BE3CBBC275B696C18C9455
+ C7A2B22814276CE25EF2D96E3E5B5F08CAC60164F2E4C56EB950CDDADD62547C
+ 8AB5104C8AE5381D660A0FC6CD19AD22249C0731D3B6FCCA82902FCF5A45D0D6
+ 049868B24E54168522B20991ED14423EDBCD67EB0B41D9640410760DCDA8BD73
+ 00221466DF0128845974C732695B730B8AAA080D79314D00DE215F9E615C6D6B
+ 08400CEB074359D8EE523B6113F792CF764101D20148ACD8ED412C06EC3EA3A2
+ A8F61C88641AE5E40084DE5209851D2F70E832DA7E6E93506B97D1E5B6D56534
+ 532961B3A9B86D07D69977F2E539DF33CE1546544B2F09CAC2B6E374C226EE25
+ 9FED82A13BDEDB2896B27100AE3C4AD16C0EEF982E58DE61F69F1BBA8C96011E
+ 55ECCDEE1AF1987008A1B8CB66D978CEE4CBB39188D97200D4AD5A9CACA82C0A
+ 45641322DB29847CB69BCFD61782B271005082C22DBFCCE3B2974766ED72C248
+ DBF6A4916152CBF651D5EEBA71745C18FA4C0BDBDA92BE20E4CBB33E316E6B0B
+ B6A26A96B2139545A1386113F792CF76F3D9FA4250360E201FAA477C97FD5C31
+ 0DEB1972AA5AC383150AD5A965D38FA9FAECCD70A73386994858E3E087CB2A88
+ CC9C70555AF38CCF86CFC8C5E2D0348B8E45655128229B30756A6BF9259FEDC2
+ B8A06CE67ACAC60180F6859B68B4AAB03DCFACEBD6E8AC1822D426669A5AB6FD
+ 2A5E627B434A4A77594EBC796C87A6987F3C8208F819C3653F06A3C62CFB0844
+ 655128229B60B6F775886D171C80ADA18593948D0348526B4B8D6881802D07C0
+ 5219CBE72A0E380096495B2AAACB6DD80EF6A0DFA696089B9E4A68A116D14420
+ E615F37C2FE9016AFB066685EA96AE85A82C0A856A825E61CA66305A7F20DF04
+ 76D96CEC281B07F0BB3C4A7105C5FB03E68A994C898F7A06EDDD026B26E296D6
+ 2C9931038AC76BCBB9A4AF8F0A62EA10E25F6B3BF2D5BC912FAFF99E6DAED040
+ 2020BA7F5154168580B6409960C7681EDB992B5A85785EE1F53C8DDD4250360E
+ 80508ABB39ACAD7585BD6D93FAF8A4F00CB91AAEB4B57D541F8F0823FFB8C295
+ B64249C57BBB0659226171868156DB11AAE60D515EF199F0D9B85814EE50A538
+ B64324622B4E9A1AAE101F19CF633B734564BB591B075BE7E282533E0E006002
+ CFE80AD89BB0D36F0F0837A52B36C349676E0F0D787DD6BD0B6A458DBD136F06
+ 63F109B725F697B7067451EDE835FC25C1555593CDEBBD649F099E8D8B45A185
+ C216056019A407ECDDEFA804F238803CB63357F2D86ED974FF91B272009431CB
+ 640E74A36C3900339D32A09A5A3FD75F616BBCCE48C6602997654CAB55866C9F
+ 794F5C1AFD8ABF9D46E5FD8E5EC15F1242DBC551BA9317476DDF94A405ACBAC5
+ 32C0B2E06251086DC154A6B2B663833CB66BEB966BA7292B076052C1CC7A8503
+ 13763AB1DE2A13D06CAFAD99316A8983AD05F595E0CA6CE935D1DD39984CA56F
+ 7331877F1574831B6CFB979281790B086ED54BA7D283F1AB9D96E7290CAAA815
+ BAE5E145655028225B6019D3F68A85C8764536BE909495035019B38CB9601065
+ DB0198716A197B2A3EF12D448590999CB0C4BE4A6698D75D5F67FB12C8E439E3
+ 047F3B8DEAFD1B20F3B6CFBE380FE4A9E6217184EE789E672904D429EA968B39
+ 44655028D4A7581C80C8660A4515D8AE22E8E52E2465E500A0BF65510E98BA4B
+ F1DB3B0FA04FA686F8DB1C542301EAF5DA9A604CF7F776F8DCD66D9DEEFA7A5B
+ D74B2393674F5F33D2694BBEDD4142C2BB1EE252F980798231AF057C067816DB
+ ADB448A7A87B2C032E1605DA80A29996FD1B229B2904B459305A8B7D81B1D89A
+ 58749AB272008C1061E89B8A96367B5B6C23E3C2C2F436ACB235AB66C4623123
+ E3B60E03428175FCAD2D2247231FF1B7D3086D02E35FE3C857388277F5BA6C9E
+ 44448E4685CF5028229D9A19F7352C032E16453E1BC8673373259FCDE6B3F185
+ A2AC1C4094D25168F12D33C59EB5F68233667AFA86E0432D8750B49A5ADB5D75
+ 23923AC7DFE64813BDDA555B6F7BCA3EDED539901A322E70711AB58FAD22EEDA
+ 85DF228879A8FB9630423AC1BCC7BB2EDBBECA0875893AE5620E3D92FA92BF2D
+ 1A910DA0ADA0CD70B12844368BB68D36CEC5B2A0AC1CC02794E2A92E8B87F4D4
+ 114B60CF42C8CEE6A68865A9480B69B66B50A2AFF7946818E05DDD64EBD2CA3B
+ 8CBC7BFE53239E100D8D48FDB3AD0B3A2988DF8D7910CD48609E31EF5CB48548
+ 97A873D43D178B466803602B765700F2D86C84DB78D950560E000163B2CCBEBA
+ ABED3900449FA2965D68D44F6AA8CBDE3C80313E3A261A06B87CACD5EEAE40C4
+ 4CC6D2E34723BF238984C570B0F01A9EDA407C4DB62FDF2D18FC4EFC6EA10141
+ 5E31CF98779E52348ADBED465D723107EA1C75CFC5A2C0B2471BE0620E91AD14
+ 8AC86645B6BDD0949D0300B76B5192A6900073BB440DCD9CD187462CD74BE3F6
+ 4FCFEA35B67B01FAE0E411FE36076E59F536B76EE1A22D123D570723573C87B9
+ 380D544ADDA32B49F88187A1346DA9686EC077E077E177E6FB36CC2BE6998BB6
+ F035B7DC27DAFE2BD279A160D98BB6008B6CA510D0565D8AD501886C7BA1293B
+ 07A01162592F8612522A36EEB0D50B48755EBB01FD74CB292C4F43BDAD6BA590
+ F8D5AED35E8FF58E79EF0ACF36EA72DBEA61DC61F2C4B1CB9357CC8FB9680127
+ E1561C7A08C6E4B6AEB59F11FC6CFC8E7C137E08E611F3CA455B5045553DB581
+ AD5CCC81BA469D73B1683CB5D6B2471B415BE1625184DAB6E2F8DFB27225B2ED
+ 85A6EC1C401C940415DE3211186AF1D80A279D1DD3C5480F17736821B28A51CD
+ 56D3C932C94C6694592A27AE5BFBD7B7D8BE15F70E918F8F9D8D76981F4117DB
+ A21FC40D1A5AF16C1BA97DFC6147B70DE367E167E267E37708813C61DE308F3C
+ C536BEF56D9B93C4BA4487BA469D73B128B0CCB52A629DBD041BB13BFEF7AE0B
+ 5AF28C368DB6CDC5B2A1EC1CC07B8A92026559BA4ADE55F6CFDA6746D3D60BF6
+ 54E2F5AD69B2DD6C26BBBB3E11DD5B471BFDF73B31177087894F8F9D9BB8A8FE
+ 5E34277007DC31D8F89D8DA4FEDB0F9340EBE6A28E12E3DFE0DFE267E067E167
+ E605F28279C2BCF114DBA0CE94D5811D5CCC813A4E765FFD848B45932D73287B
+ 2EE630C6D3B6F72CF8D75A6F8D429B46DBE662D950760E0001F76B9DB1F79310
+ 53ECCD0324AE74769A143F7E3A9E958D6BF9DBA2D1A391093DA1590CD34C337F
+ 60E3E63D5C7484E899935DC39F8EBD6A2693331E56C1433935FBAAC89A1FEC81
+ AEFBC324BC071DC27D30EC5945B4CA30DED4937DE17B4CC39FE1EFE0EFE2DFE0
+ DF8A0EF6DC0DE4218279C13CF12447409DA1EEB8980375AC47C76C6FA6119539
+ DA46ACA3D3D6F0056DD4EB27967E92C8A6CB81B2740080455990512DBC7D87AD
+ 137C66249220096299E051C3640D55ED5D5985243A3BFEE8557C162FEFAA26F7
+ 39B12FE06E92BD3DC3B77E73E995D4B0719127CD88BB1286511BD121549386A7
+ D6919587B690D52FEDCABEF03DA6E1CFF077F077E7027E37E4E15F302F3CC911
+ 5057A8332EE640DDA28EB9583458D658E65CFC06B08DAC8DD8006D145A29D1BC
+ 8F740073053AAC7D3866E2628EE026EF1C4D333FFA50F2127F9B83E28CFDFA56
+ 5B5757237A7422AA4F24DFE3628E649A288196758FC03739AA6F964864867EFB
+ F9E1B14FC75F136D1B2E15F85DF89DF8DD98079EEC1034AB2BD4194FC881BA45
+ 1D73B168B0ACB1CCB99843641B8522B251B465B4692E961565E9005E57149CE5
+ B2B42ABE35F66F818D9DBFD4215A0DF0AEAA6AE36F6D3175F1C2FB9AA259767B
+ A515BD3ED0D6BE8D8B8E12EBB874E3D62F4EBE32F145FA77E974DA91E53711F8
+ D9F81DB77EF9C5AFF13B79B2A3A08E50575CCCE1766B63A85B2EDA4254D66813
+ 681B5C2C1A918DA22DA34D73B1AC284B078080D7B4CED8837DB81AD7D85A56C3
+ 168B4D104BB759F1915A4FE39A5946BCB3935D11B831F66B2E4EC3B3C6B7C7E9
+ A1C0DDE0387CF017277F3DFAC1D0BFC66E1B5FC2B3DA0E3D859F819F859F899F
+ 9D1DEB337B813DF281BA411D71711AA9DEC82B7667FE112C632C6B2EE6409BB0
+ DB9B41DB441BE5620E912D970B65EB005C940A9556BDAFD9766CAC64EFA070A9
+ CABBAE698615EEB993ECEEBCA0E9EE935CCC914C10D5DFDEFC94EAF1D80A1F3E
+ 1B78F67EECADCFFF74E39533FF152BEE6497713433A95FC309BB7C4B8859E067
+ F83BF8BBF837F8B7F819F859F6CFF3CF0CEA0475833AE249395CBAFB8B64F765
+ E1998842C957C6C9DE5BB6972FF3D9663E5B2E07C039952F2F98E65F83B54E5B
+ 52C99864F2EA7F3C62BBAB163EF4F05F291ED2C4C52C78F3ECC4914BEF189311
+ DB174DA8C150D0BBAFFDE766DAB08C09DDA6EBC6C4C92FFEC04CC3D67A733150
+ CDA5BAAA6B2AD440C0A3F0E3D050E933462C91CA8C0D4F32DD66DCFE22C00D3F
+ 957B1EF8765AC958E66114B73A913CDEF177C654D476EC7FB5221CA83CB0F9B9
+ 7B77FF9929D21779FBE83F73B16836FC8703ED2EC5B20230F996A2FC237F5F76
+ 946D0F0081CA6F595A42057B573515BEB07D0FE981294B900A348CE07D9B1DD9
+ BE8B066B5E1BFD27D141213474FFB61D0F73715EC10A9E1EBA1DC1ADBA388EC7
+ 17BE4F0FDD8A2C44E54782DB763C24AAFCA83BB367FC174E547E24B879F366D1
+ D65F912D140ADAA4A0F2239DFCFFB2A4AC1D00D41CA1F2AAF6AFB53D568F9DBE
+ D4095F600D155643D6B9AA6A6C6F3A4212D7BA3B32E3F4F75C9C06F3B3FB825B
+ B638BA3F603152B1F9FEBD869F6DE6E234507789AB9DC2F888858265AA5613EB
+ A929B081AC2DD8249F4DE6B3E172A1AC1DC03B8A3208BD00CBA68FE03A52979D
+ 12B40135332C7523FD191773600BE1DBB4C9B2FFBC58A267CEFE4E33DDC2B57A
+ 33E4D9E5BF6FEB2E2E2E3BF0D98D4A752717A7813A43DD71D13658A6A2D61F6D
+ 006D818B45A2719B9C0EDA2EDA3017CB92B276000864D0B2334B851E57D5DE07
+ 6DDFC293387BEEA2A817E00A936627560410CA74163B7DEEBFB9556B04E12C61
+ F71EFF96FB1FE4D2B221FBCCF0EC5C9C06EA0A7586BAE349B6C0B2C432E5E237
+ 40D9676DC02655BB1E0CA14D723107781B4B78F772A3EC1D4092904BA0488B21
+ 54EEB47ADC42C1431FA9FEA43068856F6393632DB3998825A6CE76FE3FB896CD
+ 93A61352EF0FECD8FD2855AC33E04B0D7CC6C0FDBB1FC567E649D3C8AEF783AE
+ 50673CC936F9CA327D2379D4EEC11FA4728FD816DD94DADE58546ACADE01BCA7
+ 285146E9752EE6F054902A575DA3EDA3B653A7CE5D621962E9A6A93E52E36FBB
+ CFB1C07B4664743CF165CF7F7269AA70271BF3B1FB2A1ED8F76CA9970817127C
+ 367C469CFFE049D340DDA08E50573CC936588658965CCC81653EF9C539DB4B8B
+ 6883688B5CBC9BFED7282DAB00A022CADE01202663966E1AF40A94BAA75B6C07
+ F3C0F15FB27B54B8C3CCD35CB543F1071D3BC9971E191C4A5EEAFF4FB8B4C593
+ A6A1AB9935C13DDBFFAC949B85160A7C267C367C469E348DEC721FE80675C493
+ 6C83658765C8C56924AF8E1DB63FF627046D106D918B3920CD917D0BA5665138
+ 002FA53DA050CBDA7C7025A9578301DBCF90B8D871DD8813CBDE02BC45B8E2FE
+ EDBBB9E808E9C15BB7D2E77AFF63BEE140C6304215DBD7BC1868BB0FBAC8CE9E
+ 1D5818A882CF82CF84CFC613A781BA409DA06E78922304B76FDF29BA09DA8C91
+ CB890B5FD98AFA83A0EDA10D723107DAAA8BDABFB0643E581406065D2903946A
+ 89000B99D7AABFB5CB76645F247EBEE743680EAC91832B4993779DFD83427793
+ 191E1C9C3AD5F57F6AC4258C3D87BBE158ADEFC18A07F71ED2C2D5B62F305928
+ 30EFF80CF82CA21D7E084EF8A12E50273CC911B0CC44137F58C6B10B3D1F70D1
+ 16687B68835CCC611272166D968B65CDA2696112849C87CC5AF66A57B5B346E6
+ F6837FB047A6FF66441F348421B77CADF57BB440A5A363731CE7C68E9FFBBFDD
+ CC9DB7AB68D04C6368D7BA9771C6DCA9D062F301E615D7F731EFF80C3CD9023E
+ FBE467E7FE2F27C7FC089615961917A781658C65CDC5A2419B43DBE3620EB451
+ 68451645F71F59340E00A3A99882595578004FFDD3BB1D1933478F9D3E65A605
+ B108A01B19DCBD65BFDDD061F762A6E3C9C8D193FFAF16A3EF88760C22D99613
+ 57091EDAF6235FEBC62DB86D96FFA8ECC0BCF95BDAB7615E717D3F5FAB8FCF8A
+ CF8CCF8E3AE0C98E8065846525ECFA43D9621973D1166873687B5CCC81365A8E
+ 917FF2B1681C00C2183B0D19B65494703B5BA97AEDCF05503D6DC6BFBCF10E0C
+ E22CE1B6543F6908EDD8E5D806A13BE05AF7E4E92FDE49F444FFDEEB56F3B64C
+ 181D87D6050F54EDDBF9231C5363B86CFEA30507F38279C2BC917AFF43A2483E
+ 77C067C467C567766A9DFF6EB08CB0ACB8F80D50A6F18B37DEC132E6294583B6
+ 8636C7C51C689B29C6CE707151E0688B361F3C6F9A4FC07F968A38DE45AE0FBE
+ 71C4917164F0E13DBBDC8DEE67B9388DD8E5A123C99EAE929C85C70344FE6D5B
+ 7EA86BE959B708636CBC4C8276256FF4756446861C8DC8335770661F2FEDC0B8
+ FDA2D0DDF7822724E3E72FBEEAD4DEFE7BC1717F6053FD012E4E233D907E77EA
+ E849DB91849186170F3454B5125118B90B6F29CA87FCFDA260D1398043A65901
+ 99FE09BC9DD6BD04B7AEF7FED78E73E9E888EDC9178CEB56FDEDBDDFA73E62B9
+ 90823092993C7DED707A78A0646BBCDE96B6ADAED5D53FD24D7D4EBB113DAA1A
+ C98CC7AFA687867AD343C3239049DBAD9C18AAE02DBD7851A7ABCABF21651873
+ 0AD082B3FCA9DEB157F098344F721C775D6365C5AEF507C1A22D73252C41BAC6
+ FE70E2374E2CFBB943B56AF3FFD4BE1D5AFB7B27FF0CF8F05FBEAD28935C5E14
+ 2C3A07808013F816647C3B17734C0E92DB377F75C491D04B4A38ECAB7C7CCBCF
+ A84AAC61C80C9298387EE98F7AD45EFCB899C05B6B025BB71E7485BCCF26CDC4
+ 9CF722785D34694C6A037A2C3AA047224399C8D898994A163526C5C8BCAE7075
+ B5160ED76B815023DECF2FBAA23B1F18C32F134DBE1BBB70E1B013C13CF2A185
+ A0ACF66D7E1A9A04CB7D7CCC2013137FBAF48FE6F8789C27D962D58F0F345534
+ 90155CFC064ABF7C8BD2BCF736942B8BD2011C34CD40107A01D0CC4DF3F6F030
+ ACEFB5C10BB19E4E4726963C6DAD2B02F737FC045A7DCB528F91226313C74E7F
+ C492A5336C440B55867C6DED4F6B3EFDD1B974B345785D4A2C9356A366924C29
+ 462269A4CC04C63EC0E07E8AA2AA8CA81A71AB6EAA6A6E0C18A07849D0E53642
+ C98C595410561C9E60F45E0CE0E9440CBF99C0EBBD2BF7EF7A5CF5106B300E18
+ F7C7BE1CFC65AAB3CB91602681756DDEA6971BB6424B3FADDE406F2003639A5F
+ 1E5614DB7124E69B45E90010E805EC85CC5B0ED1245334D2FB9F3F75EC086670
+ EFEE6DEE26EF212E4EC34C9091C891531F31C3FE7EF2D9C83A82D6B647B56AFA
+ AD64CA7A5946398037F6E863CA9144D7E58F304C3A4F2E1954F5A8E103BB1F17
+ 85F842527DE97762274E3A765741F3DF3ED2E6F50863FE7D0E5D7FDB31051682
+ 45EB001E654CAB62ECAF40F996DD65A36748F7F00747C4076F8A20F4C481C7B5
+ 6AB69F8BD3D027C9EDC867273E2EC58CB6081C1AF837B4EED21A2A0EA8AEF486
+ 84207AEE7C824B7A785127DED587D77595B2AB7F37B8DC177E68EF635A85A03B
+ 0EE863F458F4C3231F71D136754F1EA8AED9495AB898032A50749CD27F2EB75B
+ 7FE7CAA27500C8F74CB3159ADEEF703107D4C44CCF3F755C488F8C3852283829
+ 58F5CCDEE7950011460B422710FDFCD4A7F3D113B81BB5AAA6DAD7D4BC5BABF4
+ EC50DCE975F3E50CA0C5CD684977AF11499DC32BBAEDDED25B28D8F2871EDCFD
+ 48BECA6FC6C8C5F1F74EBCE5C4A41FE2AEADD5D6FD75FB56A82C9609469590DF
+ FF56511CBD14653E59D40E0081A1C04BF01096ADBAF14932D2F75F8E5CE3A26D
+ 14B747AD7CEA811F521F119E10CC0E078E9FFEB8D47302F9500381807B4D73BB
+ ABA2B24509B00DD493599D6F234EA1787DC430D2AE3E638A5D31C7C62EA7FB7B
+ BB8D74DAF6D5DFC58063FEF0BE5D8FE5EBF6B304E99978FF8B579D38E67B87A6
+ 7F7F60BDBF42104998901BD0F57F9D8B8B9245EF005E32CD6AA8717F016F2DC6
+ 3E7C8C748E1E3D627BDBE71DA8CFE7AA3CB8EBCFEF0D267A079C189C3A79E953
+ 7DAA74AB0373855297E65E51DFA886C38D8ACF5FAB78DC354C6555AA8B05A992
+ DDA8430DC6B2AB0B2AA5B84AC09849E346864E51838E9BA9F4A899888F1891C8
+ 40FAF6D000639905EFE2E216DFE0DE2D8F0A27FC000CEE3971F8F4BF3A795949
+ CDC307C275FB89E8CE0803BA03AFBCAE28F3DAFB719A45EF0090174D739F49C8
+ 3E2EE6C0A1C0B55F745FCC0C0F3866105A45C8137C7CDB5F286E22BC569CE924
+ 36F5E5B54F4AB94F603982EBFCC1FBD73F4A356BDC7D04B7F94E7D74FE157D32
+ EAD8365C3CEBBFFEA72D5B445D7F186B1D7F43518E7371D1B2A013484EA151FA
+ 051492E546612CB8553F6A852EBBBDF881778306868686AD0D4F9A061A68C5AE
+ F54F397D827039E35DDFBA0A37F9E4ADFC50164E577EB419B41D51E5475B439B
+ E3E2A2664938003C7A09551C2F8DB48CFB70D9A6E1C5076D070EB91B34B4AFBB
+ 9A796E7CA1D05BDD547FA062E7DE6D4E1F205A4EA0EE5087818DF58F804E2D15
+ 11C98EF9A12C9CADFCB8DDF7C106D1921F8047D3DF5F2CC77D67634919E70B8C
+ ED628C59F682C343B25B878D8E89B3C71CDD838E1383A1271F782EDFEA0062C4
+ C9E0D4D94B9F9772D7E0520477F705776C7E5078B08783B3FDD10FBE78C7C909
+ 3FA472C7FEE0CA836A3B0C212DF583527AE44D4A1D3953500E2CADD68931FA3C
+ 63DF837796B0536021E9DE5F745F72723E00C125C2CA6FED7B4CAB660FF1240B
+ 2623A978D7F017A9AB9DC2002092E97836B4ADF1B7D63DA050EB71DB3BE863F4
+ B3893F1DFFD8A9A5BE3BE0B8BFF9A72D9B5522DC75D9FF16A5BF052FE0E8772E
+ 244BCB01002F3316CC30F6975042963DEB78AD58F7DF1FBF4CD3CE1A0D92DD31
+ B8D6FB6D22D8367C874C84F44E9D3F7FD68C4D3A7A067EA98031FC308C973084
+ F71D28D1D3D7937F983A71EA3C4F710CE676D196BFD9B74974C30F5494A48BD2
+ 7F81AE7F494E322E144BCE0120D00B68A68C3D2FEAC24D8D92A11BFF78C4763C
+ 38117876C0BFA5E165E101220EF60652D7C6CFC63BBF2ADB0B2317028CDEEB59
+ 5FB563A6561F0FF6C42F0EBEE6D4DEFE7B59FDEF0E34076B8431FEA06F49DF82
+ D6BF2476B3902C490780E43B2B804CF491FE81578F0C70D15194AA2A7FE5439B
+ 9F131E25BE0B2341461357FA4EA706FA4779D2B2042FEDC0B8FDA2D0DD778347
+ 7A273EBBF48E53A7FAEEA5F187071A2B9BAC4347041A9245BBD77F3696AC0340
+ C0091C8207B4DE07070C9F25D7460F1FB12C1D3A01CE0B54ECDFB1D3BDD27D70
+ A6210182C382C4E5CB1732E3A34BAA6B391B78579F7FD3A62D5A58BCB3320776
+ F96FA50F4F1E3B7BC6E9F1FE1D6A0E1EA8ADDB21B613F8C26B50F9DFE6E29263
+ 493B80674CD3E326E407F090969D6350B06CE8137265FCC491921D5775AF6DAE
+ F3DFBFFAB97C9B86EE8047738D51D233F5D5A58B4E5C4D5ECEE015DD7803335E
+ C22ABAABEF6E70730F86F14A5FED2D59C4A3AABD0742F58F9236C88868497C34
+ 45C86F16538CBF4259D20E00799EB1308CE07E006F2DC1220063E070EACAC4D9
+ 93256B7DB137107A78F7035A83FA18287BC6F3FC59471021FDC96B3D1DA9DBB7
+ 16F516D37BF1AC5859ED5DBFAE5D0D9335B3557C70CEE9CC20FB64F2E8C993A5
+ 6AF591CA1D7B828D073D1BE1ADE8CC448250FADF61DCEFD856F27264C93B00E4
+ 65C65664187B092CC9D21DC75062B7DE8D5D99BA70A6A42DAF6BCDAAB06FFBBA
+ A7349F705FB9053C5C94BA3DD19DE8BAD2C78C85B9B7DF2E5475A9BED68D4D9E
+ 15952DF90EEFDC8B9E209D89733DEF3B11BA7B26825B7706563E1BD808CDBEC5
+ 26A052E82E4A5F7F8DD2924C369613CBC20120DF636CBDC9D873E0042CCF3C5F
+ 4E00F16D695FEB6DA9798ABAF26F70990623197D9CF4A706067A13FD7D43F315
+ 77A05870F79E6F4D53BDA7B1B159AB226B40DBC21D7CF78277F5E1156D784B13
+ 4F2A19B3547EA650FACE6F2975EC246939B36C1C00F29C696E86423FC8C57B31
+ 6E7D607446CF1C2B7950C7EC24E103DBB7BA577B1F8691A7F0649B108324C119
+ DC4C8D0CDD4ADDE81F9CAFE01BB381414A3CABD734786AEB5742A55F051DEAB9
+ 5FA2629231BCA5172FEA2C6577FF0EA19DFB2B563EA9622F4C78541A1A83C3EF
+ 284AD9DFEAEB14CBCA0120CF33763F61EC312E4E03ACCF1CFA8474967262F06E
+ 702BB16FC7F62D9ED5EE870A720400CE17B03819D527F4DBFAD8C86872F0E6F0
+ 7CC522C033F9DE8655755A756D8D56A9ADA07E5233DBB8DE0254FCD48DF46778
+ 3FBFD35B79F331CB841F3C18FD18C6FC962BE89632CBCE0120874C73373CF8C3
+ 5C9C063A81B133E49A9321C566037B04C1EDEDADAE35A17DF9620DCC0533A34C
+ 997173CC4CA4A3FA542C6A262663466432566C7C022D18F6A9E18A80E2AB0868
+ C18A901AD0C2D4AB841557F13109F1E45EA63F7A7CEA5C47D77CB4F877C0905E
+ D53BC9FA7C951F123F7B435196C409BF4258960E0079D1341F80EE5EDEFDFB13
+ 3DA47FE0B5D26C169A09DC4DE86D6ED8412BC91630CA3987039F15183E3083A4
+ B32F460C66421B6CF0BB1655E2A20A81A12F51A94ADCF82AA81B3F0BA0E7149B
+ 201793BD83674BB58B6F261A5F3ED058B94EBCC907814A70EC4D4539C9C565C5
+ B27500083881ED609CDFE2A285C43819EAFDD5F1EBA5383B301B187D28B06D73
+ BBABCEDBCEFC64BDC2C463D672C5A4E05E12A4571F4A5E8A9DBFD4E164949EB9
+ 827BFB9B7FBC6FADAFCABABDF70E4BED745FA12C6B0780E0C420D4AC27A1860B
+ 75810788FA7ED5DDEDF429C242C04B4A7C1BDBDA5C35EE561220EB1CED193808
+ B6F424467A32A3E9AEC495CE4E33B27047A0F1545FD38F5B5A44077B10286C06
+ AF0FA1DB7F91272D4B96BD0340C009B4801378069C8070DB2E1E251E3A6C743B
+ 1D4FA01870E2D0D3B67EB5565FDBACF9D96AE223ABA0108BBA30C42EA0AF34B4
+ F237F538BDA10F8DF4A63AAFDD98AF09BD99C0F3FCF507552C53A15E405F3A64
+ F2BD7714A59B272D5BA403E064370B11728831F1CDB660EC2CD245FA06DFF87C
+ 10EC87A72E3CE8105CCD4D755A55558356E1A957FCAC81BA945AA2387C7988A9
+ 4CB18C3962C6E9A03E991AD2C7C70733BD7DC3E550E1BF41CB46F209B7922630
+ 6CA16D43973FEE22E4EDE5B0C9672E48077017CF9866089A8C1740297997E4F0
+ E6A19BBFEEEA59C821C15CC83A86C6BA4A355C55A5783D01EA717989A6F9158D
+ F928250A5308FEFBBA8534499A9AC4648C98A64E1344D7E32C95499AC954CC88
+ 8C8F67068627CAABA25BC12E3FC6F0CB13C62B0B38F1B134216FBEA728F3B2CC
+ BB18900EE01EF801A2A74131C2D36108185266E418E97132E4B8A478C20F1DA8
+ 6C7828BBC49777D721FCAC2709DDFEA57CB0A718A403C803C6135008D907953D
+ AF8EF0F291DBFFDAD1978E38730391A430DCE15A6DC59FB737892EEDB803141E
+ DE957E7CA99EE7B78B740033C0230BE1E460DE3571EC0D8C9D21D7E773E39024
+ B7B1672D18F04CAD7E9251FADE528CE4E314D201CC02C6184C33F634BCCDBB91
+ 04C1B981E1B76FF7397535B9440C5ED15D776845D34C637D4EBF9BD23F2EB518
+ 7E4E231DC05C608CBE40C84EC6B23704E7DD9003CA64D1413238FC56C72D392C
+ 7016ECEED73DDFBE32D4401A661A960106A5F4D89B849C214B287A6FA9900EA0
+ 005E344DDC517610C694755FA788819FEB135DE4E6C8BB67868D640C4449B1A8
+ DE8052FBECCEBACA56B24AC9B34FE30E60CC23F07AFF0D4519E2499259900EA0
+ 407ECE98721E2F2021642FBC663448DC4014E9A0B786FE786A98A6E3B2352A00
+ E6F6D3FAA777D785DBD9CA7C1B7AEE00468CBDAD93DB293DF577944A875B00D2
+ 0114C97718AB52197B021438EB1D806091A9F10E3A30FAE1E951331E2BEBF5F4
+ 8546F107D49A2776D554B5B3C6B96C7906AF7A03FAFC1FFE9ED2719E242900E9
+ 006C72C834378212F168B170CFF9DDE0D060AA9F0C0D7FD03D58EE1B89E61BDC
+ C853F7644B43700DA99FADABCF9984CA7FF46D45B9C26549114807E0008F32A6
+ 5531B6139489478C670D8105866BA626C9F8C449323C7EFAF368396D2D9E5F34
+ 52B5EBC150E51E52E7A92055A03FA8FB3303BF804733BF18A7F4CC2794CA8956
+ 9B4807E020074D33E023640F28152F0BCDBB5A7037301E484EF5802338767D34
+ 79B32FCD939734DE554DEEAAFD6B6B82EB481D2869AE71070CA8F8171330D63F
+ AC284B3A74FA7C221D400980614105A174AFCAD87DD02398B555BB031E3D9EBA
+ 4AC6C68EF78E6506FA97D410C1D5B8C655BDAFB93AB88154E73BA22B029467C2
+ 18FF2BC2D809E8EE973C5EE372433A801282878B3C94EE5418DB3C97A1C1DD40
+ 57602AD54F27263A9291C9F367E3F3193ECB193412DCBA2D10DC14A8F4AF2561
+ B7420A3A9D885D7D93D24B29C6CEC8C33BA5433A8079E0C78C79A38C6D851A7C
+ 3FBC023C79CEE0E4A11E27D1E44D3215ED4E4D4E5E0187B000518A6602A3EF54
+ 6CDCE10FB5782ABCAB48D0E52715605C05393D04FE2606AF2F43945EF815A572
+ 576589910E601EC13D041718DBA0936CBCBF26A8C145E91FFECED44D124B8F91
+ 786A185ED75389C9EECE84198FCCCB12A3E20FAB152D6D3ECF5A8FCF5347FCEE
+ 6AE2D71412808799F370E76EE0EFF0C04E9F0663FCAD945E956BF9F38774000B
+ 040E0FBC846C86B7ED50A1435FA7DA033E27932124654E929401AF7494648C04
+ D10DF85F8FC5F4CCD494614E8D19B8E8A0A77576C7616085D6DC1AC5C5372558
+ ADBA8241550B043435445CAA8F686EFCBF827814784193EE01A329B86517019F
+ 835DFB0E68E62FC96EFEC2201D401980D188D28CE175E27861C59C27C8162938
+ 91D7E9A6B44B46E55978A40328339E33CD06289466FE5A51EC30A15C80CC3378
+ 86DBF0EAC5D73B8A32C87F24290316B5712D7570F27082B1261810AF52095909
+ 15A8B6DC1D025678F86F14F27C53815725A57D7232AF7C910E601181E1CA3C94
+ 3632C61AC021D49A94D651C62A17CA29606567944E288C0D1B78128FD2C11463
+ 0332ECD6E2413A80450E6E430E315603051906A7103228AD840A89938A3897E0
+ 07E760EB0E01F85CACCC71784D82C389C26747A1759F80CF8D44291D95DB7117
+ 37D2012C75A08DFE2E213E2F0C27A026BBA0C5CE3A04E839A82E7EE82643880E
+ E9D91501484FC12F6492D06DFF1D210919544322914824128944229148241289
+ 4422914824128944229148241289442291482412894422914824128944229148
+ 2412894422914824128944229148241289442291482412894422914824128944
+ 2291482412894422914824128944229148241289442291482412894422914824
+ 1289442291482412C9728390FF1F97ED6E34D64226CD0000000049454E44AE42
+ 6082}
+ FileName =
+ 'C:\Users\Programmer\Pictures\Icons\'#931#969#964#942#961#951#962'\256x256\icon_simulati' +
+ 'on_256.png'
+ end>
+ Align = Client
+ Size.Width = 444.500000000000000000
+ Size.Height = 313.000000000000000000
+ Size.PlatformDefault = False
+ end
+ end
+ object ltSendText: TLayout
+ Align = Bottom
+ Padding.Left = 5.000000000000000000
+ Padding.Top = 5.000000000000000000
+ Padding.Right = 5.000000000000000000
+ Padding.Bottom = 5.000000000000000000
+ Position.Y = 480.000000000000000000
+ Size.Width = 909.000000000000000000
+ Size.Height = 48.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 2
+ TabStop = False
+ object edtTextToSend: TEdit
+ Touch.InteractiveGestures = [LongTap, DoubleTap]
+ Align = Client
+ StyleLookup = 'editstyle'
+ TabOrder = 0
+ Margins.Right = 5.000000000000000000
+ Size.Width = 823.000000000000000000
+ Size.Height = 38.000000000000000000
+ Size.PlatformDefault = False
+ OnEnter = edtTextToSendEnter
+ OnExit = edtTextToSendExit
+ end
+ object btnSendText: TButton
+ Align = Right
+ Position.X = 833.000000000000000000
+ Position.Y = 5.000000000000000000
+ Size.Width = 71.000000000000000000
+ Size.Height = 38.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Text = 'Send'
+ OnClick = btnSendTextClick
+ end
+ end
+ object ltMessages: TLayout
+ Align = Bottom
+ Padding.Left = 5.000000000000000000
+ Padding.Top = 5.000000000000000000
+ Padding.Right = 5.000000000000000000
+ Padding.Bottom = 5.000000000000000000
+ Position.Y = 328.000000000000000000
+ Size.Width = 909.000000000000000000
+ Size.Height = 152.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ TabStop = False
+ object memMessages: TMemo
+ Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+ DataDetectorTypes = []
+ ReadOnly = True
+ Align = Client
+ Size.Width = 899.000000000000000000
+ Size.Height = 142.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ Viewport.Width = 895.000000000000000000
+ Viewport.Height = 138.000000000000000000
+ end
+ end
+ object Splitter: TSplitter
+ Align = Bottom
+ Cursor = crVSplit
+ MinSize = 20.000000000000000000
+ Position.Y = 323.000000000000000000
+ ShowGrip = False
+ Size.Width = 909.000000000000000000
+ Size.Height = 5.000000000000000000
+ Size.PlatformDefault = False
+ end
+ end
+ object CameraComponent: TCameraComponent
+ OnSampleBufferReady = CameraComponentSampleBufferReady
+ Left = 184
+ Top = 128
+ end
+ object MultiView: TMultiView
+ TargetControl = ltContent
+ MasterButton = btnMasterView
+ Mode = NavigationPane
+ NavigationPaneOptions.CollapsedWidth = 48.000000000000000000
+ Size.Width = 250.000000000000000000
+ Size.Height = 50.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 5
+ object lbUsers: TListBox
+ Align = Client
+ Size.Width = 48.000000000000000000
+ Size.Height = 528.000000000000000000
+ Size.PlatformDefault = False
+ StyleLookup = 'transparentlistboxstyle'
+ TabOrder = 2
+ DisableFocusEffect = True
+ ItemHeight = 48.000000000000000000
+ DefaultItemStyles.ItemStyle = 'listboxitemleftdetail'
+ DefaultItemStyles.GroupHeaderStyle = ''
+ DefaultItemStyles.GroupFooterStyle = ''
+ Viewport.Width = 48.000000000000000000
+ Viewport.Height = 528.000000000000000000
+ end
+ end
+ object Client: TncClientSource
+ Port = 17244
+ CommandProcessorThreadsPerCPU = 1
+ CommandProcessorThreadsGrowUpto = 10
+ ExecCommandTimeout = 2000
+ EncryptionKey = 'SetEncryptionKey'
+ OnConnected = ClientConnected
+ OnDisconnected = ClientDisconnected
+ OnHandleCommand = ClientHandleCommand
+ Host = 'LocalHost'
+ Left = 64
+ Top = 128
+ end
+end
diff --git a/Demos/VideoChat/Client/ufrmMain.pas b/Demos/TCP/VideoChat/Client/ufrmMain.pas
similarity index 96%
rename from Demos/VideoChat/Client/ufrmMain.pas
rename to Demos/TCP/VideoChat/Client/ufrmMain.pas
index 8778f46..39fb0c7 100644
--- a/Demos/VideoChat/Client/ufrmMain.pas
+++ b/Demos/TCP/VideoChat/Client/ufrmMain.pas
@@ -1,249 +1,249 @@
-unit ufrmMain;
-
-interface
-
-uses
- System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
- FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
- FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
- FMX.Layouts, ncSources, FMX.Edit, FMX.StdCtrls, FMX.ListView,
- FMX.Controls.Presentation, FMX.Objects, FMX.ScrollBox, FMX.Memo, FMX.MultiView,
- FMX.ListBox, CommonCommands, FMX.Media;
-
-type
- TfrmMain = class(TForm)
- ToolBar: TToolBar;
- btnConnect: TButton;
- edtUsername: TEdit;
- ltContent: TLayout;
- Client: TncClientSource;
- ltCameras: TGridPanelLayout;
- ltSendText: TLayout;
- imgUserVideo: TImage;
- imgPeerUserVideo: TImage;
- edtTextToSend: TEdit;
- btnSendText: TButton;
- ltMessages: TLayout;
- memMessages: TMemo;
- Splitter: TSplitter;
- btnMasterView: TButton;
- MultiView: TMultiView;
- lbUsers: TListBox;
- CameraComponent: TCameraComponent;
- procedure edtUsernameEnter(Sender: TObject);
- procedure edtUsernameExit(Sender: TObject);
- procedure edtTextToSendEnter(Sender: TObject);
- procedure edtTextToSendExit(Sender: TObject);
- procedure btnConnectClick(Sender: TObject);
- procedure ClientConnected(Sender: TObject; aLine: TncLine);
- procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
- function ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
- const aSenderComponent, aReceiverComponent: string): TArray;
- procedure btnSendTextClick(Sender: TObject);
- procedure CameraComponentSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
- private
- ConnectErrorMsg: string;
- public
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.fmx}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- //
-end;
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- Client.Active := False;
-end;
-
-procedure TfrmMain.FormPaint(Sender: TObject; Canvas: TCanvas;
- const ARect: TRectF);
-begin
- // We set the camera on when the form has fully loaded, as in some phones,
- // we may not get the permission to use the camera. In such a case, if we
- // had enabled the camera at creation time, the application would terminate...
- OnPaint := nil;
- CameraComponent.Active := True;
-end;
-
-procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- btnConnect.Text := 'Disconnect';
- if edtUsername.Text = '' then
- edtUsername.Text := 'Anonymous'; // Although Eponymous
- edtUsername.Enabled := False;
- end);
-
- try
- Client.ExecCommand(cmdCntUserLogin, BytesOf(edtUsername.Text), True);
- except
- on e: exception do
- begin
- // We do not want to show exceptions here, as this might be a reconnect
- // attempt, we will show the exception only when the user presses the button
- // in btnConnectClick
- ConnectErrorMsg := e.Message;
- Client.Active := False;
- end;
- end;
-end;
-
-procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- btnConnect.Text := 'Connect';
- edtUsername.Enabled := True;
- lbUsers.Clear;
- end);
-end;
-
-procedure TfrmMain.btnConnectClick(Sender: TObject);
-begin
- if Client.Active then
- begin
- Client.Active := False;
- end
- else
- begin
- Client.Active := True;
- if not Client.Active then
- raise Exception.Create(ConnectErrorMsg);
- end;
-end;
-
-function TfrmMain.ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
-const aSenderComponent, aReceiverComponent: string): TArray;
-begin
- SetLength(Result, 0);
-
- TThread.Synchronize(nil,
-
- procedure
- var
- i: Integer;
- Username: string;
- BytesStream: TBytesStream;
- lbIndex: Integer;
- PrevUser: string;
- begin
- // This is called from the server to update information
- case aCmd of
- cmdSrvUpdateLoggedInUsers:
- begin
- // Save the user we are on
- lbUsers.BeginUpdate;
- try
- if lbUsers.ItemIndex <> -1 then
- PrevUser := lbUsers.Items.Strings[lbUsers.ItemIndex]
- else
- PrevUser := '';
-
- lbUsers.Items.CommaText := StringOf(aData);
-
- if PrevUser <> '' then
- lbUsers.ItemIndex := lbUsers.Items.IndexOf(PrevUser);
- finally
- lbUsers.EndUpdate;
- end;
- end;
- cmdSrvUpdateImage:
- begin
- // Extract the #13#10 from the aData
- for i := 0 to High(aData) - 1 do
- if (aData[i] = 13) and (aData[i + 1] = 10) then
- begin
- Username := StringOf(Copy(aData, 0, i));
-
- BytesStream := TBytesStream.Create(Copy(aData, i + 2));
- try
- lbIndex := lbUsers.Items.IndexOf(Username);
- lbUsers.ItemByIndex(lbIndex).ItemData.Bitmap.LoadFromStream(BytesStream);
- lbUsers.ItemByIndex(lbIndex).StyleLookup := 'listboxitemleftdetail';
-
- if lbUsers.ItemIndex = lbIndex then
- imgPeerUserVideo.Bitmap.LoadFromStream(BytesStream);
- finally
- BytesStream.Free;
- end;
-
- Break;
- end;
- end;
- cmdSrvGetText:
- begin
- memMessages.Lines.Add(StringOf(aData));
- memMessages.ScrollBy(0, 100);
- end;
- end;
- end);
-end;
-
-procedure TfrmMain.CameraComponentSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
-var
- BytesStream: TBytesStream;
-begin
- // We got a new image from the camera
- // Assign it first to our own imgUserVideo component
- CameraComponent.SampleBufferToBitmap(imgUserVideo.Bitmap, True);
-
- // This try is because the CameraComponent OnSampleBufferReady cannot cope
- // with thrown exceptions
- try
- if Client.Active then
- begin
- // If we are logged in, send the picture to the server
- // (SaveToStream will save it as png format)
- BytesStream := TBytesStream.Create;
- try
- imgUserVideo.Bitmap.SaveToStream(BytesStream);
- Client.ExecCommand(cmdCntCameraImage, BytesStream.Bytes, False);
- finally
- BytesStream.Free;
- end;
- end;
- except
- end;
-end;
-
-procedure TfrmMain.btnSendTextClick(Sender: TObject);
-begin
- Client.ExecCommand(cmdCntGetText, BytesOf(edtUsername.Text + ': ' + edtTextToSend.Text), False);
- edtTextToSend.Text := '';
-end;
-
-procedure TfrmMain.edtUsernameEnter(Sender: TObject);
-begin
- btnConnect.Default := True;
-end;
-
-procedure TfrmMain.edtUsernameExit(Sender: TObject);
-begin
- btnConnect.Default := False;
-end;
-
-procedure TfrmMain.edtTextToSendEnter(Sender: TObject);
-begin
- btnSendText.Default := True;
-end;
-
-procedure TfrmMain.edtTextToSendExit(Sender: TObject);
-begin
- btnSendText.Default := False;
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
+ FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
+ FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
+ FMX.Layouts, ncSources, FMX.Edit, FMX.StdCtrls, FMX.ListView,
+ FMX.Controls.Presentation, FMX.Objects, FMX.ScrollBox, FMX.Memo, FMX.MultiView,
+ FMX.ListBox, CommonCommands, FMX.Media;
+
+type
+ TfrmMain = class(TForm)
+ ToolBar: TToolBar;
+ btnConnect: TButton;
+ edtUsername: TEdit;
+ ltContent: TLayout;
+ Client: TncClientSource;
+ ltCameras: TGridPanelLayout;
+ ltSendText: TLayout;
+ imgUserVideo: TImage;
+ imgPeerUserVideo: TImage;
+ edtTextToSend: TEdit;
+ btnSendText: TButton;
+ ltMessages: TLayout;
+ memMessages: TMemo;
+ Splitter: TSplitter;
+ btnMasterView: TButton;
+ MultiView: TMultiView;
+ lbUsers: TListBox;
+ CameraComponent: TCameraComponent;
+ procedure edtUsernameEnter(Sender: TObject);
+ procedure edtUsernameExit(Sender: TObject);
+ procedure edtTextToSendEnter(Sender: TObject);
+ procedure edtTextToSendExit(Sender: TObject);
+ procedure btnConnectClick(Sender: TObject);
+ procedure ClientConnected(Sender: TObject; aLine: TncLine);
+ procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
+ function ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+ const aSenderComponent, aReceiverComponent: string): TArray;
+ procedure btnSendTextClick(Sender: TObject);
+ procedure CameraComponentSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
+ private
+ ConnectErrorMsg: string;
+ public
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.fmx}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ //
+end;
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ Client.Active := False;
+end;
+
+procedure TfrmMain.FormPaint(Sender: TObject; Canvas: TCanvas;
+ const ARect: TRectF);
+begin
+ // We set the camera on when the form has fully loaded, as in some phones,
+ // we may not get the permission to use the camera. In such a case, if we
+ // had enabled the camera at creation time, the application would terminate...
+ OnPaint := nil;
+ CameraComponent.Active := True;
+end;
+
+procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ TThread.Synchronize(nil,
+ procedure
+ begin
+ btnConnect.Text := 'Disconnect';
+ if edtUsername.Text = '' then
+ edtUsername.Text := 'Anonymous'; // Although Eponymous
+ edtUsername.Enabled := False;
+ end);
+
+ try
+ Client.ExecCommand(cmdCntUserLogin, BytesOf(edtUsername.Text), True);
+ except
+ on e: exception do
+ begin
+ // We do not want to show exceptions here, as this might be a reconnect
+ // attempt, we will show the exception only when the user presses the button
+ // in btnConnectClick
+ ConnectErrorMsg := e.Message;
+ Client.Active := False;
+ end;
+ end;
+end;
+
+procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ TThread.Synchronize(nil,
+ procedure
+ begin
+ btnConnect.Text := 'Connect';
+ edtUsername.Enabled := True;
+ lbUsers.Clear;
+ end);
+end;
+
+procedure TfrmMain.btnConnectClick(Sender: TObject);
+begin
+ if Client.Active then
+ begin
+ Client.Active := False;
+ end
+ else
+ begin
+ Client.Active := True;
+ if not Client.Active then
+ raise Exception.Create(ConnectErrorMsg);
+ end;
+end;
+
+function TfrmMain.ClientHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+const aSenderComponent, aReceiverComponent: string): TArray;
+begin
+ SetLength(Result, 0);
+
+ TThread.Synchronize(nil,
+
+ procedure
+ var
+ i: Integer;
+ Username: string;
+ BytesStream: TBytesStream;
+ lbIndex: Integer;
+ PrevUser: string;
+ begin
+ // This is called from the server to update information
+ case aCmd of
+ cmdSrvUpdateLoggedInUsers:
+ begin
+ // Save the user we are on
+ lbUsers.BeginUpdate;
+ try
+ if lbUsers.ItemIndex <> -1 then
+ PrevUser := lbUsers.Items.Strings[lbUsers.ItemIndex]
+ else
+ PrevUser := '';
+
+ lbUsers.Items.CommaText := StringOf(aData);
+
+ if PrevUser <> '' then
+ lbUsers.ItemIndex := lbUsers.Items.IndexOf(PrevUser);
+ finally
+ lbUsers.EndUpdate;
+ end;
+ end;
+ cmdSrvUpdateImage:
+ begin
+ // Extract the #13#10 from the aData
+ for i := 0 to High(aData) - 1 do
+ if (aData[i] = 13) and (aData[i + 1] = 10) then
+ begin
+ Username := StringOf(Copy(aData, 0, i));
+
+ BytesStream := TBytesStream.Create(Copy(aData, i + 2));
+ try
+ lbIndex := lbUsers.Items.IndexOf(Username);
+ lbUsers.ItemByIndex(lbIndex).ItemData.Bitmap.LoadFromStream(BytesStream);
+ lbUsers.ItemByIndex(lbIndex).StyleLookup := 'listboxitemleftdetail';
+
+ if lbUsers.ItemIndex = lbIndex then
+ imgPeerUserVideo.Bitmap.LoadFromStream(BytesStream);
+ finally
+ BytesStream.Free;
+ end;
+
+ Break;
+ end;
+ end;
+ cmdSrvGetText:
+ begin
+ memMessages.Lines.Add(StringOf(aData));
+ memMessages.ScrollBy(0, 100);
+ end;
+ end;
+ end);
+end;
+
+procedure TfrmMain.CameraComponentSampleBufferReady(Sender: TObject; const ATime: TMediaTime);
+var
+ BytesStream: TBytesStream;
+begin
+ // We got a new image from the camera
+ // Assign it first to our own imgUserVideo component
+ CameraComponent.SampleBufferToBitmap(imgUserVideo.Bitmap, True);
+
+ // This try is because the CameraComponent OnSampleBufferReady cannot cope
+ // with thrown exceptions
+ try
+ if Client.Active then
+ begin
+ // If we are logged in, send the picture to the server
+ // (SaveToStream will save it as png format)
+ BytesStream := TBytesStream.Create;
+ try
+ imgUserVideo.Bitmap.SaveToStream(BytesStream);
+ Client.ExecCommand(cmdCntCameraImage, BytesStream.Bytes, False);
+ finally
+ BytesStream.Free;
+ end;
+ end;
+ except
+ end;
+end;
+
+procedure TfrmMain.btnSendTextClick(Sender: TObject);
+begin
+ Client.ExecCommand(cmdCntGetText, BytesOf(edtUsername.Text + ': ' + edtTextToSend.Text), False);
+ edtTextToSend.Text := '';
+end;
+
+procedure TfrmMain.edtUsernameEnter(Sender: TObject);
+begin
+ btnConnect.Default := True;
+end;
+
+procedure TfrmMain.edtUsernameExit(Sender: TObject);
+begin
+ btnConnect.Default := False;
+end;
+
+procedure TfrmMain.edtTextToSendEnter(Sender: TObject);
+begin
+ btnSendText.Default := True;
+end;
+
+procedure TfrmMain.edtTextToSendExit(Sender: TObject);
+begin
+ btnSendText.Default := False;
+end;
+
+end.
diff --git a/Demos/VideoChat/Server/AndroidManifest.template.xml b/Demos/TCP/VideoChat/Server/AndroidManifest.template.xml
similarity index 100%
rename from Demos/VideoChat/Server/AndroidManifest.template.xml
rename to Demos/TCP/VideoChat/Server/AndroidManifest.template.xml
diff --git a/Demos/VideoChat/Server/CommonCommands.pas b/Demos/TCP/VideoChat/Server/CommonCommands.pas
similarity index 93%
rename from Demos/VideoChat/Server/CommonCommands.pas
rename to Demos/TCP/VideoChat/Server/CommonCommands.pas
index 78daf13..a8fde58 100644
--- a/Demos/VideoChat/Server/CommonCommands.pas
+++ b/Demos/TCP/VideoChat/Server/CommonCommands.pas
@@ -1,15 +1,15 @@
-unit CommonCommands;
-
-interface
-
-const
- cmdCntUserLogin = 0;
- cmdSrvUpdateLoggedInUsers = 1;
- cmdCntCameraImage = 2;
- cmdSrvUpdateImage = 3;
- cmdCntGetText = 4;
- cmdSrvGetText = 5;
-
-implementation
-
-end.
+unit CommonCommands;
+
+interface
+
+const
+ cmdCntUserLogin = 0;
+ cmdSrvUpdateLoggedInUsers = 1;
+ cmdCntCameraImage = 2;
+ cmdSrvUpdateImage = 3;
+ cmdCntGetText = 4;
+ cmdSrvGetText = 5;
+
+implementation
+
+end.
diff --git a/Demos/VideoChat/Server/VideoChatServer.dpr b/Demos/TCP/VideoChat/Server/VideoChatServer.dpr
similarity index 94%
rename from Demos/VideoChat/Server/VideoChatServer.dpr
rename to Demos/TCP/VideoChat/Server/VideoChatServer.dpr
index 0b8ad85..3ba6988 100644
--- a/Demos/VideoChat/Server/VideoChatServer.dpr
+++ b/Demos/TCP/VideoChat/Server/VideoChatServer.dpr
@@ -1,18 +1,18 @@
-program VideoChatServer;
-
-uses
- System.StartUpCopy,
- FMX.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain},
- CommonCommands in 'CommonCommands.pas';
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program VideoChatServer;
+
+uses
+ System.StartUpCopy,
+ FMX.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain},
+ CommonCommands in 'CommonCommands.pas';
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
diff --git a/Demos/VideoChat/Server/VideoChatServer.dproj b/Demos/TCP/VideoChat/Server/VideoChatServer.dproj
similarity index 98%
rename from Demos/VideoChat/Server/VideoChatServer.dproj
rename to Demos/TCP/VideoChat/Server/VideoChatServer.dproj
index f5d2aa6..53b886b 100644
--- a/Demos/VideoChat/Server/VideoChatServer.dproj
+++ b/Demos/TCP/VideoChat/Server/VideoChatServer.dproj
@@ -1,1084 +1,1084 @@
-
-
- {4E64D787-4C5F-4E0F-BEE7-DDE5A692111D}
- 18.8
- FMX
- VideoChatServer.dpr
- True
- Release
- Win64
- 32787
- Application
-
-
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Cfg_1
- true
- true
-
-
- true
- Base
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- true
- Cfg_2
- true
- true
-
-
- .\$(Platform)\$(Config)
- .\$(Platform)\$(Config)
- false
- false
- false
- false
- false
- System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
- true
- true
- true
- true
- true
- true
- true
- true
- $(BDS)\bin\delphi_PROJECTICON.ico
- $(BDS)\bin\delphi_PROJECTICNS.icns
- VideoChatServer
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
- Debug
- true
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
- $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
- $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
- $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
- android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
- Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- Debug
- true
- CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
- 1033
- $(BDS)\bin\default_app.manifest
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
- $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
-
-
- DEBUG;$(DCC_Define)
- true
- false
- true
- true
- true
-
-
- false
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
- false
- RELEASE;$(DCC_Define)
- 0
- 0
-
-
- true
- PerMonitorV2
-
-
- true
- PerMonitorV2
-
-
-
- MainSource
-
-
-
- fmx
-
-
-
- Cfg_2
- Base
-
-
- Base
-
-
- Cfg_1
- Base
-
-
-
- Delphi.Personality.12
- Application
-
-
-
- VideoChatServer.dpr
-
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- VideoChatServer.exe
- true
-
-
-
-
- VideoChatServer.exe
- true
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- classes
- 1
-
-
- classes
- 1
-
-
-
-
- res\xml
- 1
-
-
- res\xml
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\armeabi
- 1
-
-
- library\lib\armeabi
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- library\lib\mips
- 1
-
-
- library\lib\mips
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\values-v21
- 1
-
-
- res\values-v21
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- res\drawable
- 1
-
-
- res\drawable
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-ldpi
- 1
-
-
- res\drawable-ldpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-mdpi
- 1
-
-
- res\drawable-mdpi
- 1
-
-
-
-
- res\drawable-hdpi
- 1
-
-
- res\drawable-hdpi
- 1
-
-
-
-
- res\drawable-xhdpi
- 1
-
-
- res\drawable-xhdpi
- 1
-
-
-
-
- res\drawable-xxhdpi
- 1
-
-
- res\drawable-xxhdpi
- 1
-
-
-
-
- res\drawable-xxxhdpi
- 1
-
-
- res\drawable-xxxhdpi
- 1
-
-
-
-
- res\drawable-small
- 1
-
-
- res\drawable-small
- 1
-
-
-
-
- res\drawable-normal
- 1
-
-
- res\drawable-normal
- 1
-
-
-
-
- res\drawable-large
- 1
-
-
- res\drawable-large
- 1
-
-
-
-
- res\drawable-xlarge
- 1
-
-
- res\drawable-xlarge
- 1
-
-
-
-
- res\values
- 1
-
-
- res\values
- 1
-
-
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- Contents\MacOS
- 1
- .framework
-
-
- Contents\MacOS
- 1
- .framework
-
-
- 0
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .dll;.bpl
-
-
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- Contents\MacOS
- 1
- .dylib
-
-
- 0
- .bpl
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- Contents\Resources\StartUp\
- 0
-
-
- 0
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
-
-
- ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
- 1
-
-
-
-
- ..\
- 1
-
-
- ..\
- 1
-
-
-
-
- Contents
- 1
-
-
- Contents
- 1
-
-
-
-
- Contents\Resources
- 1
-
-
- Contents\Resources
- 1
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
- library\lib\arm64-v8a
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- Contents\MacOS
- 1
-
-
- Contents\MacOS
- 1
-
-
- 0
-
-
-
-
- library\lib\armeabi-v7a
- 1
-
-
-
-
- 1
-
-
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
- Assets
- 1
-
-
- Assets
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- True
- True
-
-
- 12
-
-
-
-
-
-
+
+
+ {4E64D787-4C5F-4E0F-BEE7-DDE5A692111D}
+ 18.8
+ FMX
+ VideoChatServer.dpr
+ True
+ Release
+ Win64
+ 32787
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ VideoChatServer
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;NetCom7;tethering;fmxFireDAC;Quantiser;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ Debug
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;Quantiser;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;Intraweb_14_D10_3;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;NetCom8;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;DirectPanelPackage;DirectGraphics11;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;vclFireDAC;IndySystem;NetCom7;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;officeXPrt;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ fmx
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ VideoChatServer.dpr
+
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ VideoChatServer.exe
+ true
+
+
+
+
+ VideoChatServer.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ classes
+ 1
+
+
+ classes
+ 1
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+
+
+ 12
+
+
+
+
+
+
diff --git a/Demos/VideoChat/Server/VideoChatServer.dproj.local b/Demos/TCP/VideoChat/Server/VideoChatServer.dproj.local
similarity index 99%
rename from Demos/VideoChat/Server/VideoChatServer.dproj.local
rename to Demos/TCP/VideoChat/Server/VideoChatServer.dproj.local
index 537c2ef..13ce0f2 100644
--- a/Demos/VideoChat/Server/VideoChatServer.dproj.local
+++ b/Demos/TCP/VideoChat/Server/VideoChatServer.dproj.local
@@ -1,47 +1,47 @@
-
-
-
- 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
- 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
- 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 00:19:14.000.567,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 09:20:35.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 09:22:06.000.529,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
- 2020/08/12 09:22:06.000.529,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
- 2020/08/12 09:22:13.000.248,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
- 2020/08/12 10:07:55.000.801,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas
-
-
-
-
-
+
+
+
+ 2018/09/21 12:49:51.000.179,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/09/24 13:18:27.000.279,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/10 13:56:06.000.238,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 10:56:54.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/10/16 11:40:09.000.191,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 15:48:45.000.203,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:18.000.148,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/04 16:17:48.000.272,=C:\Users\Programmer\Documents\Development\Projects\Unit1.pas
+ 2018/11/23 20:02:18.000.772,=C:\Users\Programmer\Documents\Development\Projects\Unit2.pas
+ 2019/02/27 18:05:16.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:06:31.000.995,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/02/27 18:12:19.000.197,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 12:15:54.000.434,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/05 13:06:38.000.677,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/11 18:09:12.000.176,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/03/25 16:12:14.000.258,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/29 14:49:59.000.196,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/05/31 18:08:29.000.138,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/08/21 21:29:49.000.507,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/09/18 13:39:12.000.759,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/11/09 19:07:03.000.902,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2019/12/15 14:13:57.000.985,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/13 08:49:52.000.721,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/14 04:39:08.000.542,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/04/15 03:31:58.000.910,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 09:58:25.000.183,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/02 20:01:51.000.926,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/05 15:55:38.000.562,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/08 18:03:33.000.205,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/07/16 00:09:13.000.392,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/07 10:38:54.000.477,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/08 10:30:32.000.363,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/10 13:26:25.000.247,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 00:19:14.000.567,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 09:20:35.000.938,=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 09:22:06.000.529,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.fmx=C:\Users\Programmer\Documents\Development\Projects\Unit3.fmx
+ 2020/08/12 09:22:06.000.529,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas=C:\Users\Programmer\Documents\Development\Projects\Unit3.pas
+ 2020/08/12 09:22:13.000.248,C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dproj=C:\Users\Programmer\Documents\Development\Projects\Project1.dproj
+ 2020/08/12 10:07:55.000.801,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas
+
+
+
+
+
diff --git a/Demos/VideoChat/Server/VideoChatServer.dsk b/Demos/TCP/VideoChat/Server/VideoChatServer.dsk
similarity index 94%
rename from Demos/VideoChat/Server/VideoChatServer.dsk
rename to Demos/TCP/VideoChat/Server/VideoChatServer.dsk
index 9594ed1..517a193 100644
--- a/Demos/VideoChat/Server/VideoChatServer.dsk
+++ b/Demos/TCP/VideoChat/Server/VideoChatServer.dsk
@@ -1,763 +1,763 @@
-[Closed Files]
-File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas',0,1,1,3,11,0,0,,
-File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,1187,51,1209,0,0,,
-File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,608,1,612,0,0,,{1
-File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSocketList.pas',0,1,1,1,1,0,0,,
-File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,294,37,307,0,0,,
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,419,1,435,0,0,,
-File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,3267,1,3282,0,0,,
-File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.SyncObjs.pas',0,1,1039,3,1055,0,0,,
-File_8=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncThreads.pas',0,1,162,45,177,0,0,,
-File_9=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Windows.pas',0,1,38884,1,38900,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dproj
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dproj]
-ModuleType=TBaseProject
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dpr
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=00000800010100000000CC0E0000000000000166070000000000000100000000530E000009000000446F636B536974653301000000004D1A00001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=00000800010100000000CC0E00000000000001F50500000000000001000000004612000009000000446F636B536974653201000000004D1A000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=1622
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020100000009000000446F636B5369746531C0440000000000000256060000000000000100000000C04400000F0000004D65737361676556696577466F726DFFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dpr
-CursorX=3
-CursorY=13
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas
-CursorX=39
-CursorY=9
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks={1,86,1}
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=9900
-Height=1372
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=1372
-TBDockHeight=1372
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=1826
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=1826
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=2884
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=2884
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-1348
-Top=185
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=319
-Top=671
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-8
-Top=-120
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=28
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=1826
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=1826
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\CommonCommands.pas',0,1,1,3,11,0,0,,
+File_1=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,1187,51,1209,0,0,,
+File_2=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSources.pas',0,1,608,1,612,0,0,,{1
+File_3=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSocketList.pas',0,1,1,1,1,0,0,,
+File_4=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas',0,1,294,37,307,0,0,,
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,419,1,435,0,0,,
+File_6=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Winsock2.pas',0,1,3267,1,3282,0,0,,
+File_7=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.SyncObjs.pas',0,1,1039,3,1055,0,0,,
+File_8=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncThreads.pas',0,1,162,45,177,0,0,,
+File_9=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Windows.pas',0,1,38884,1,38900,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dproj
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dproj]
+ModuleType=TBaseProject
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dpr
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=00000800010100000000CC0E0000000000000166070000000000000100000000530E000009000000446F636B536974653301000000004D1A00001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=00000800010100000000CC0E00000000000001F50500000000000001000000004612000009000000446F636B536974653201000000004D1A000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=1622
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020100000009000000446F636B5369746531C0440000000000000256060000000000000100000000C04400000F0000004D65737361676556696577466F726DFFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dpr
+CursorX=3
+CursorY=13
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\VideoChatServer.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas
+CursorX=39
+CursorY=9
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks={1,86,1}
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\VideoChat\Server\ufrmMain.pas
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=9900
+Height=1372
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=1372
+TBDockHeight=1372
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=1826
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=1826
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=2884
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=2884
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-1348
+Top=185
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=319
+Top=671
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-8
+Top=-120
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=28
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=1826
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=1826
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/VideoChat/Server/VideoChatServer.identcache b/Demos/TCP/VideoChat/Server/VideoChatServer.identcache
similarity index 100%
rename from Demos/VideoChat/Server/VideoChatServer.identcache
rename to Demos/TCP/VideoChat/Server/VideoChatServer.identcache
diff --git a/Demos/VideoChat/Server/VideoChatServer.res b/Demos/TCP/VideoChat/Server/VideoChatServer.res
similarity index 100%
rename from Demos/VideoChat/Server/VideoChatServer.res
rename to Demos/TCP/VideoChat/Server/VideoChatServer.res
diff --git a/Demos/VideoChat/Server/ufrmMain.fmx b/Demos/TCP/VideoChat/Server/ufrmMain.fmx
similarity index 96%
rename from Demos/VideoChat/Server/ufrmMain.fmx
rename to Demos/TCP/VideoChat/Server/ufrmMain.fmx
index 65de8cb..2406aa0 100644
--- a/Demos/VideoChat/Server/ufrmMain.fmx
+++ b/Demos/TCP/VideoChat/Server/ufrmMain.fmx
@@ -1,36 +1,36 @@
-object frmMain: TfrmMain
- Left = 0
- Top = 0
- Caption = 'NetCom Video Chat Server'
- ClientHeight = 480
- ClientWidth = 640
- FormFactor.Width = 320
- FormFactor.Height = 480
- FormFactor.Devices = [Desktop]
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- DesignerMasterStyle = 0
- object memLog: TMemo
- Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
- DataDetectorTypes = []
- Align = Client
- Size.Width = 640.000000000000000000
- Size.Height = 480.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 1
- Viewport.Width = 636.000000000000000000
- Viewport.Height = 476.000000000000000000
- end
- object Server: TncServerSource
- Port = 17244
- CommandProcessorThreadsPerCPU = 2
- CommandProcessorThreadsGrowUpto = 20
- ExecCommandTimeout = 2000
- EncryptionKey = 'SetEncryptionKey'
- OnConnected = ServerConnected
- OnDisconnected = ServerDisconnected
- OnHandleCommand = ServerHandleCommand
- Left = 40
- Top = 40
- end
-end
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ Caption = 'NetCom Video Chat Server'
+ ClientHeight = 480
+ ClientWidth = 640
+ FormFactor.Width = 320
+ FormFactor.Height = 480
+ FormFactor.Devices = [Desktop]
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ DesignerMasterStyle = 0
+ object memLog: TMemo
+ Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+ DataDetectorTypes = []
+ Align = Client
+ Size.Width = 640.000000000000000000
+ Size.Height = 480.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Viewport.Width = 636.000000000000000000
+ Viewport.Height = 476.000000000000000000
+ end
+ object Server: TncServerSource
+ Port = 17244
+ CommandProcessorThreadsPerCPU = 2
+ CommandProcessorThreadsGrowUpto = 20
+ ExecCommandTimeout = 2000
+ EncryptionKey = 'SetEncryptionKey'
+ OnConnected = ServerConnected
+ OnDisconnected = ServerDisconnected
+ OnHandleCommand = ServerHandleCommand
+ Left = 40
+ Top = 40
+ end
+end
diff --git a/Demos/VideoChat/Server/ufrmMain.pas b/Demos/TCP/VideoChat/Server/ufrmMain.pas
similarity index 96%
rename from Demos/VideoChat/Server/ufrmMain.pas
rename to Demos/TCP/VideoChat/Server/ufrmMain.pas
index 6f32137..40c92d2 100644
--- a/Demos/VideoChat/Server/ufrmMain.pas
+++ b/Demos/TCP/VideoChat/Server/ufrmMain.pas
@@ -1,217 +1,217 @@
-unit ufrmMain;
-
-interface
-
-uses
- System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
- FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
- FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
- System.SyncObjs, ncSocketList, ncSources, CommonCommands;
-
-type
- TConnectedUserData = class
- Line: TncLine;
- Image: TBitmap;
- end;
-
- TfrmMain = class(TForm)
- Server: TncServerSource;
- memLog: TMemo;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- function ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
- const aSenderComponent, aReceiverComponent: string): TArray;
- procedure ServerDisconnected(Sender: TObject; aLine: TncLine);
- procedure ServerConnected(Sender: TObject; aLine: TncLine);
- private
- ConnectedUsersLock: TCriticalSection;
- ConnectedUsers: TStringList;
- procedure InformClientsOfLogins(aDontSendToLine: TncLine = nil);
- public
- end;
-
-var
- frmMain: TfrmMain;
-
-implementation
-
-{$R *.fmx}
-
-procedure TfrmMain.FormCreate(Sender: TObject);
-begin
- ConnectedUsersLock := TCriticalSection.Create;
-
- ConnectedUsers := TStringList.Create;
- ConnectedUsers.Sorted := True;
- ConnectedUsers.Duplicates := dupError;
- ConnectedUsers.CaseSensitive := False;
-
- try
- Server.Active := True;
- memLog.Lines.Add('Server started! Do not close this window');
- except
- on e: Exception do
- memLog.Lines.Add('Cannot start server: ' + e.Message);
- end;
-end;
-
-procedure TfrmMain.FormDestroy(Sender: TObject);
-begin
- Server.Active := False;
- ConnectedUsers.Free;
- ConnectedUsersLock.Free;
-end;
-
-procedure TfrmMain.ServerConnected(Sender: TObject; aLine: TncLine);
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add(aLine.PeerIP + ' Client connected');
- memLog.ScrollBy(0, 100);
- end);
-end;
-
-procedure TfrmMain.ServerDisconnected(Sender: TObject; aLine: TncLine);
-var
- i: Integer;
- UserData: TConnectedUserData;
-begin
- TThread.Synchronize(nil,
- procedure
- begin
- memLog.Lines.Add(aLine.PeerIP + ' Client disconnected');
- memLog.ScrollBy(0, 100);
- end);
-
- // Check Connected Users list to delete the entry
- ConnectedUsersLock.Acquire;
- try
- for i := 0 to ConnectedUsers.Count - 1 do
- begin
- UserData := TConnectedUserData(ConnectedUsers.Objects[i]);
- if UserData.Line = aLine then
- begin
- UserData.Image.Free;
- UserData.Free;
- ConnectedUsers.Delete(i);
- Break;
- end;
- end;
- finally
- ConnectedUsersLock.Release;
- end;
-
- InformClientsOfLogins(aLine);
-end;
-
-// DontSendTo parameter is used by disconnect, so that we don't send the
-// disconnected line the message
-procedure TfrmMain.InformClientsOfLogins(aDontSendToLine: TncLine = nil);
-var
- SocketList: TSocketList;
- i: Integer;
-begin
- // Now inform all clients to update their user lists
- ConnectedUsersLock.Acquire;
- try
- SocketList := Server.Lines.LockList;
- try
- for i := 0 to SocketList.Count - 1 do
- if SocketList.Lines[i] <> aDontSendToLine then
- Server.ExecCommand(SocketList.Lines[i], cmdSrvUpdateLoggedInUsers, BytesOf(ConnectedUsers.CommaText), False);
- finally
- Server.Lines.UnlockList;
- end;
- finally
- ConnectedUsersLock.Release;
- end;
-end;
-
-function TfrmMain.ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
-const aSenderComponent, aReceiverComponent: string): TArray;
-var
- UserData: TConnectedUserData;
- i, j: Integer;
- BytesStream: TBytesStream;
- DataToSend: TBytes;
- SocketList: TSocketList;
-begin
- SetLength(Result, 0);
-
- case aCmd of
- cmdCntUserLogin:
- begin
- // When the user logs in, he/she sends a name which is held in aData
- ConnectedUsersLock.Acquire;
- try
- // If a username already exists, the ConnectedUsers will raise an exception
- // as it has Duplicates set to dupError
- // This exception will travel back to the client. Since we want a custom
- // message, we trap the exception and change its message
- UserData := TConnectedUserData.Create;
- UserData.Line := aLine;
- UserData.Image := TBitmap.Create;
- try
- ConnectedUsers.AddObject(StringOf(aData), UserData);
- except
- UserData.Image.Free;
- UserData.Free;
- raise Exception.Create('Cannot login with this name, another user has already taken it');
- end;
- finally
- ConnectedUsersLock.Release;
- end;
-
- // Inform all connected clients of the new data
- InformClientsOfLogins;
- end;
- cmdCntCameraImage:
- begin
- // The client is sending us a video image, update our list
- ConnectedUsersLock.Acquire;
- try
- for i := 0 to ConnectedUsers.Count - 1 do
- begin
- UserData := TConnectedUserData(ConnectedUsers.Objects[i]);
- if UserData.Line = aLine then
- begin
- BytesStream := TBytesStream.Create(aData);
- try
- UserData.Image.LoadFromStream(BytesStream);
- finally
- BytesStream.Free;
- end;
-
- // Send the image to everyone
- DataToSend := BytesOf(ConnectedUsers.Strings[i]) + BytesOf(#13#10) + aData;
- SocketList := Server.Lines.LockList;
- try
- for j := 0 to SocketList.Count - 1 do
- Server.ExecCommand(SocketList.Lines[j], cmdSrvUpdateImage, DataToSend, False);
- finally
- Server.Lines.UnlockList;
- end;
-
- Break;
- end;
- end;
- finally
- ConnectedUsersLock.Release;
- end;
- end;
- cmdCntGetText:
- begin
- // Send the text to all users
- SocketList := Server.Lines.LockList;
- try
- for j := 0 to SocketList.Count - 1 do
- Server.ExecCommand(SocketList.Lines[j], cmdSrvGetText, aData, False);
- finally
- Server.Lines.UnlockList;
- end;
- end;
- end;
-end;
-
-end.
+unit ufrmMain;
+
+interface
+
+uses
+ System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
+ FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
+ FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
+ System.SyncObjs, ncSocketList, ncSources, CommonCommands;
+
+type
+ TConnectedUserData = class
+ Line: TncLine;
+ Image: TBitmap;
+ end;
+
+ TfrmMain = class(TForm)
+ Server: TncServerSource;
+ memLog: TMemo;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ function ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+ const aSenderComponent, aReceiverComponent: string): TArray;
+ procedure ServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ServerConnected(Sender: TObject; aLine: TncLine);
+ private
+ ConnectedUsersLock: TCriticalSection;
+ ConnectedUsers: TStringList;
+ procedure InformClientsOfLogins(aDontSendToLine: TncLine = nil);
+ public
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.fmx}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ ConnectedUsersLock := TCriticalSection.Create;
+
+ ConnectedUsers := TStringList.Create;
+ ConnectedUsers.Sorted := True;
+ ConnectedUsers.Duplicates := dupError;
+ ConnectedUsers.CaseSensitive := False;
+
+ try
+ Server.Active := True;
+ memLog.Lines.Add('Server started! Do not close this window');
+ except
+ on e: Exception do
+ memLog.Lines.Add('Cannot start server: ' + e.Message);
+ end;
+end;
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ Server.Active := False;
+ ConnectedUsers.Free;
+ ConnectedUsersLock.Free;
+end;
+
+procedure TfrmMain.ServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ TThread.Synchronize(nil,
+ procedure
+ begin
+ memLog.Lines.Add(aLine.PeerIP + ' Client connected');
+ memLog.ScrollBy(0, 100);
+ end);
+end;
+
+procedure TfrmMain.ServerDisconnected(Sender: TObject; aLine: TncLine);
+var
+ i: Integer;
+ UserData: TConnectedUserData;
+begin
+ TThread.Synchronize(nil,
+ procedure
+ begin
+ memLog.Lines.Add(aLine.PeerIP + ' Client disconnected');
+ memLog.ScrollBy(0, 100);
+ end);
+
+ // Check Connected Users list to delete the entry
+ ConnectedUsersLock.Acquire;
+ try
+ for i := 0 to ConnectedUsers.Count - 1 do
+ begin
+ UserData := TConnectedUserData(ConnectedUsers.Objects[i]);
+ if UserData.Line = aLine then
+ begin
+ UserData.Image.Free;
+ UserData.Free;
+ ConnectedUsers.Delete(i);
+ Break;
+ end;
+ end;
+ finally
+ ConnectedUsersLock.Release;
+ end;
+
+ InformClientsOfLogins(aLine);
+end;
+
+// DontSendTo parameter is used by disconnect, so that we don't send the
+// disconnected line the message
+procedure TfrmMain.InformClientsOfLogins(aDontSendToLine: TncLine = nil);
+var
+ SocketList: TSocketList;
+ i: Integer;
+begin
+ // Now inform all clients to update their user lists
+ ConnectedUsersLock.Acquire;
+ try
+ SocketList := Server.Lines.LockList;
+ try
+ for i := 0 to SocketList.Count - 1 do
+ if SocketList.Lines[i] <> aDontSendToLine then
+ Server.ExecCommand(SocketList.Lines[i], cmdSrvUpdateLoggedInUsers, BytesOf(ConnectedUsers.CommaText), False);
+ finally
+ Server.Lines.UnlockList;
+ end;
+ finally
+ ConnectedUsersLock.Release;
+ end;
+end;
+
+function TfrmMain.ServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd: Integer; const aData: TArray; aRequiresResult: Boolean;
+const aSenderComponent, aReceiverComponent: string): TArray;
+var
+ UserData: TConnectedUserData;
+ i, j: Integer;
+ BytesStream: TBytesStream;
+ DataToSend: TBytes;
+ SocketList: TSocketList;
+begin
+ SetLength(Result, 0);
+
+ case aCmd of
+ cmdCntUserLogin:
+ begin
+ // When the user logs in, he/she sends a name which is held in aData
+ ConnectedUsersLock.Acquire;
+ try
+ // If a username already exists, the ConnectedUsers will raise an exception
+ // as it has Duplicates set to dupError
+ // This exception will travel back to the client. Since we want a custom
+ // message, we trap the exception and change its message
+ UserData := TConnectedUserData.Create;
+ UserData.Line := aLine;
+ UserData.Image := TBitmap.Create;
+ try
+ ConnectedUsers.AddObject(StringOf(aData), UserData);
+ except
+ UserData.Image.Free;
+ UserData.Free;
+ raise Exception.Create('Cannot login with this name, another user has already taken it');
+ end;
+ finally
+ ConnectedUsersLock.Release;
+ end;
+
+ // Inform all connected clients of the new data
+ InformClientsOfLogins;
+ end;
+ cmdCntCameraImage:
+ begin
+ // The client is sending us a video image, update our list
+ ConnectedUsersLock.Acquire;
+ try
+ for i := 0 to ConnectedUsers.Count - 1 do
+ begin
+ UserData := TConnectedUserData(ConnectedUsers.Objects[i]);
+ if UserData.Line = aLine then
+ begin
+ BytesStream := TBytesStream.Create(aData);
+ try
+ UserData.Image.LoadFromStream(BytesStream);
+ finally
+ BytesStream.Free;
+ end;
+
+ // Send the image to everyone
+ DataToSend := BytesOf(ConnectedUsers.Strings[i]) + BytesOf(#13#10) + aData;
+ SocketList := Server.Lines.LockList;
+ try
+ for j := 0 to SocketList.Count - 1 do
+ Server.ExecCommand(SocketList.Lines[j], cmdSrvUpdateImage, DataToSend, False);
+ finally
+ Server.Lines.UnlockList;
+ end;
+
+ Break;
+ end;
+ end;
+ finally
+ ConnectedUsersLock.Release;
+ end;
+ end;
+ cmdCntGetText:
+ begin
+ // Send the text to all users
+ SocketList := Server.Lines.LockList;
+ try
+ for j := 0 to SocketList.Count - 1 do
+ Server.ExecCommand(SocketList.Lines[j], cmdSrvGetText, aData, False);
+ finally
+ Server.Lines.UnlockList;
+ end;
+ end;
+ end;
+end;
+
+end.
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Certificate/server.pfx b/Demos/TCP/ncSocketsDual_Multi-Socket/Certificate/server.pfx
new file mode 100644
index 0000000..0b1ad11
Binary files /dev/null and b/Demos/TCP/ncSocketsDual_Multi-Socket/Certificate/server.pfx differ
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dpr b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dpr
new file mode 100644
index 0000000..969aaf0
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dpr
@@ -0,0 +1,17 @@
+program Client;
+
+uses
+ Vcl.Forms,
+ uMainClient in 'uMainClient.pas' {Form1},
+ Vcl.Themes,
+ Vcl.Styles;
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ TStyleManager.TrySetStyle('Carbon');
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dproj b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dproj
new file mode 100644
index 0000000..2e11d93
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dproj
@@ -0,0 +1,1118 @@
+
+
+ {2635BC82-0C4B-4449-AF1B-5DA3BEEDB231}
+ 20.2
+ VCL
+ True
+ Release
+ Win32
+ Client
+ 3
+ Application
+ Client.dpr
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ Client
+ Carbon|VCLSTYLE|$(BDSCOMMONDIR)\Styles\Carbon.vsf
+
+
+ JvNet;RaizeComponentsVcl;vclwinx;DataSnapServer;TMSVCLUIPackPkgDXE12;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;dbxcds;vcledge;sed12Athens;VCLTMSFNCMapsPkgDXE12;DBXFirebirdDriver;JvAppFrm;dacvcl290;FireDACSqliteDriver;DbxClientDriver;JclVcl;soapmidas;TMSCryptoPkgDEDXE12;Jcl;dbexpress;JvManagedThreads;clinetsuite_12;TMSVCLUIPackPkgExDXE12;vquery290;inet;vcltouch;GLibWMI;JvDB;FireDACDBXDriver;fmxdae;MSICS_Rtl;JvCustom;CustomIPTransport;FireDACMSSQLDriver;LockBox3DR;JvSystem;JvControls;PKIEDB29;acntDX12_R;JvCrypt;JvJans;JvMM;IndySystem;JvGlobus;VirtualTreesR;JclContainers;JvPageComps;vclFireDAC;madDisAsm_;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IcsFmxNewRun;ResizeKitPKD29;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;IcsCommonNewRun;NxStandard6Run_d12;DBXSybaseASEDriver;JvRuntimeDesign;JvXPCtrls;NetCom7;vclimg;DataSnapFireDAC;unidacfmx290;inetdbxpress;FireDAC;JvDocking;JvDlgs;xmlrtl;TMSCryptoPkgDXE12;dsnap;JvCmp;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;StyleControls_d12Athens;DatasnapConnectorsFreePascal;vc2;emshosting;FireDACCommonDriver;VCLTMSFNCCorePkgDXE12;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;madBasic_;JvBands;crcontrols290;inetdb;GR32_R;FireDACASADriver;vclactnband;fmxFireDAC;FireDACInfxDriver;AcmComponents;DBXMySQLDriver;VclSmp;DataSnapCommon;JvPascalInterpreter;EurekaLogCore;fmxase;JvPluginSystem;DBXOdbcDriver;JvTimeFramework;dbrtl;FireDACOracleDriver;FMXTMSFNCUIPackPkgDXE12;Skia.Package.FMX;FireDACMSAccDriver;DataSnapIndy10ServerTransport;JclDeveloperTools;PKIECtrl29;DataSnapConnectors;MiTeC_Common;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;CnPack_D120A;JvWizards;FMXTMSFNCMapsPkgDXE12;FireDACTDataDriver;Skia.Package.VCL;vcldb;SynEditDR;VCLTMSFNCUIPackPkgDXE12;JvCore;unidacvcl290;dacfmx290;bindcomp;inetstn;MfPackX317;IndyCore;RESTBackendComponents;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;JvDotNetCtrls;JvHMI;mORMot2Components;IcsVclNewRun;DBXDb2Driver;FMXTMSFNCCorePkgDXE12;dac290;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;JvPrintPreview;tethering;JvStdCtrls;bindcompvcl;CloudService;DBXSybaseASADriver;TMSMemInsightPkgDXE12;mORMot2wsComponents;soaprtl;unidac290;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ RaizeComponentsVcl;vclwinx;DataSnapServer;TMSVCLUIPackPkgDXE12;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;appanalytics;IndyProtocols;vclx;dbxcds;vcledge;VCLTMSFNCMapsPkgDXE12;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;clinetsuite_12;TMSVCLUIPackPkgExDXE12;inet;vcltouch;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;LockBox3DR;PKIEDB29;IndySystem;VirtualTreesR;vclFireDAC;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IcsFmxNewRun;ResizeKitPKD29;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;IcsCommonNewRun;NxStandard6Run_d12;DBXSybaseASEDriver;NetCom7;vclimg;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;TMSCryptoPkgDXE12;dsnap;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;StyleControls_d12Athens;DatasnapConnectorsFreePascal;emshosting;FireDACCommonDriver;VCLTMSFNCCorePkgDXE12;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;inetdb;FireDACASADriver;vclactnband;fmxFireDAC;FireDACInfxDriver;DBXMySQLDriver;VclSmp;DataSnapCommon;fmxase;DBXOdbcDriver;dbrtl;FireDACOracleDriver;FMXTMSFNCUIPackPkgDXE12;FireDACMSAccDriver;DataSnapIndy10ServerTransport;PKIECtrl29;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;FMXTMSFNCMapsPkgDXE12;FireDACTDataDriver;Skia.Package.VCL;vcldb;SynEditDR;VCLTMSFNCUIPackPkgDXE12;bindcomp;inetstn;IndyCore;RESTBackendComponents;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;IcsVclNewRun;DBXDb2Driver;FMXTMSFNCCorePkgDXE12;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;bindcompvcl;CloudService;DBXSybaseASADriver;TMSMemInsightPkgDXE12;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+ true
+ true
+
+
+ false
+ PerMonitorV2
+
+
+ PerMonitorV2
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ PerMonitorV2
+ true
+ 1033
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Client.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+
+
+ Client.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dproj.local b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dproj.local
new file mode 100644
index 0000000..2cac641
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.dproj.local
@@ -0,0 +1,12 @@
+
+
+
+ 2025/06/27 10:23:15.000.944,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/06/27 10:25:54.000.288,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/12 15:36:10.000.674,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/15 19:46:01.000.895,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/15 19:47:05.000.814,D:\_Delphi\_Library\Netcom7\NetCom7-Templates\NeCom7-Multi-Socket_ncSocketsPro_v2.0\Client\uMainClient.pas=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/15 19:47:05.000.814,D:\_Delphi\_Library\Netcom7\NetCom7-Templates\NeCom7-Multi-Socket_ncSocketsPro_v2.0\Client\uMainClient.dfm=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.dfm
+ 2025/07/15 19:47:13.000.854,D:\_Delphi\_Library\Netcom7\NetCom7-Templates\NeCom7-Multi-Socket_ncSocketsPro_v2.0\Client\Client.dproj=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Project1.dproj
+
+
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.identcache b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.identcache
new file mode 100644
index 0000000..c6b129a
Binary files /dev/null and b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.identcache differ
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.res b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.res
new file mode 100644
index 0000000..bdfb066
Binary files /dev/null and b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/Client.res differ
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/uMainClient.dfm b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/uMainClient.dfm
new file mode 100644
index 0000000..3a32349
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/uMainClient.dfm
@@ -0,0 +1,41 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'Client - ncSocketsPro Demo'
+ ClientHeight = 203
+ ClientWidth = 489
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -12
+ Font.Name = 'Segoe UI'
+ Font.Style = []
+ Position = poMainFormCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 15
+ object Memo1: TMemo
+ Left = 0
+ Top = 0
+ Width = 489
+ Height = 203
+ Align = alClient
+ Lines.Strings = (
+ '')
+ TabOrder = 0
+ end
+ object Timer1: TTimer
+ Enabled = False
+ OnTimer = Timer1Timer
+ Left = 232
+ Top = 64
+ end
+ object ClientSocket: TncTCPClientDual
+ OnConnected = ClientSocketConnected
+ OnDisconnected = ClientSocketDisconnected
+ OnCommand = ClientSocketCommand
+ Left = 120
+ Top = 64
+ end
+end
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Client/uMainClient.pas b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/uMainClient.pas
new file mode 100644
index 0000000..1624f67
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Client/uMainClient.pas
@@ -0,0 +1,362 @@
+unit uMainClient;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
+ System.Classes, Vcl.Graphics,System.Threading,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Imaging.jpeg,
+ Vcl.ExtCtrls, System.SyncObjs, ncLines, ncSocketsDual;
+
+type
+ TForm1 = class(TForm)
+ ClientSocket: TncTCPClientDual;
+ Memo1: TMemo;
+ Timer1: TTimer;
+ procedure ClientSocketConnected(Sender: TObject; aLine: TncLine);
+ procedure ClientSocketCommand(Sender: TObject; aLine: TncLine;
+ aCmd: Integer; const aData: TBytes);
+ procedure ClientSocketReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure Timer1Timer(Sender: TObject);
+ procedure ClientSocketDisconnected(Sender: TObject; aLine: TncLine);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+
+ private
+ FConnecting: Boolean;
+ FCommandParser: TStringList; // Pre-allocated for command parsing
+ FCommandLock: TCriticalSection; // Thread safety for command processing
+ procedure ConnectToServer;
+ procedure StartReconnectTimer;
+ procedure StopReconnectTimer;
+ public
+ { Public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+function CaptureScreenshot: TBytes;
+var
+ DC: HDC; // Device context for screen
+ ScreenBMP: TBitmap; // Bitmap for screen capture
+ jpgImage: TJPEGImage; // JPEG for compression
+ MS: TMemoryStream; // Memory stream for processing
+begin
+ Result := nil;
+
+ // Create required objects for screen capture
+ ScreenBMP := TBitmap.Create;
+ jpgImage := TJPEGImage.Create;
+ MS := TMemoryStream.Create;
+ try
+ // Set bitmap dimensions to match screen resolution
+ ScreenBMP.Width := Screen.Width;
+ ScreenBMP.Height := Screen.Height;
+
+ // Get device context for the entire screen (0 = desktop window)
+ DC := GetDC(0);
+ try
+ // Copy screen pixels to bitmap using BitBlt
+ // SRCCOPY = direct copy of source pixels
+ BitBlt(ScreenBMP.Canvas.Handle, 0, 0, Screen.Width,
+ Screen.Height, DC, 0, 0, SRCCOPY);
+ finally
+ // Always release the device context
+ ReleaseDC(0, DC);
+ end;
+
+ // Convert to JPEG with 30% quality (already compressed)
+ jpgImage.Assign(ScreenBMP);
+ jpgImage.CompressionQuality := 30;
+ jpgImage.SaveToStream(MS);
+
+ // Return JPEG data directly (no additional compression needed)
+ MS.Position := 0;
+ SetLength(Result, MS.Size);
+ if MS.Size > 0 then
+ MS.ReadBuffer(Result[0], MS.Size);
+
+ finally
+ // Clean up resources
+ ScreenBMP.Free;
+ jpgImage.Free;
+ MS.Free;
+ end;
+end;
+
+procedure TForm1.ConnectToServer;
+begin
+ if FConnecting then
+ Exit;
+
+ FConnecting := True;
+ StopReconnectTimer;
+
+ if ClientSocket.Active then
+ ClientSocket.Active := False;
+
+ // Set connection parameters on main thread (these are just property assignments)
+ ClientSocket.Host := '192.168.10.30';
+ //ClientSocket.Host := '109.134.250.129';
+ ClientSocket.Port := 3434;
+
+ // Move the blocking call to background thread
+ TTask.Run(procedure
+ begin
+ try
+ ClientSocket.Active := True; // Now runs in background thread
+ except
+ on E: Exception do
+ begin
+ // Marshal back to main thread for UI updates
+ TThread.Queue(nil, procedure
+ begin
+ FConnecting := False;
+ Log('Connection failed: ' + E.Message);
+ StartReconnectTimer;
+ end);
+ end;
+ end;
+ end);
+end;
+
+procedure TForm1.StartReconnectTimer;
+begin
+ if not Timer1.Enabled then
+ begin
+ Timer1.Interval := 3000;
+ Timer1.Enabled := True;
+ end;
+end;
+
+procedure TForm1.StopReconnectTimer;
+begin
+ Timer1.Enabled := False;
+end;
+
+procedure TForm1.Timer1Timer(Sender: TObject);
+begin
+ Timer1.Enabled := False;
+ Log('Retrying connection...');
+ ConnectToServer;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+
+ // Configure TLS settings for the client
+ ClientSocket.UseTLS := True;
+ ClientSocket.TlsProvider := tpSChannel;
+ ClientSocket.IgnoreCertificateErrors := True;
+
+ // Initialize command parsing structures
+ FCommandParser := TStringList.Create;
+ FCommandParser.Delimiter := '|';
+ FCommandParser.StrictDelimiter := True;
+ FCommandLock := TCriticalSection.Create;
+
+ // Set up events for dual protocol support
+ ClientSocket.OnCommand := ClientSocketCommand; // Binary protocol handler
+ ClientSocket.OnReadData := ClientSocketReadData; // Raw text protocol handler
+
+ Log('Client starting......');
+
+ ConnectToServer;
+
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ StopReconnectTimer;
+ if ClientSocket.Active then
+ ClientSocket.Active := False;
+
+ // Clean up command parsing structures (same pattern as server)
+ if Assigned(FCommandParser) then
+ FCommandParser.Free;
+
+ if Assigned(FCommandLock) then
+ FCommandLock.Free;
+end;
+
+procedure TForm1.ClientSocketConnected(Sender: TObject; aLine: TncLine);
+var
+ FClientName: String;
+begin
+ FConnecting := False;
+ StopReconnectTimer;
+
+ FClientName := 'Client' + IntToStr(GetTickCount);
+
+ Log('Connected to server as: ' + FClientName);
+
+ //send over nickname info and authentication command...
+ self.ClientSocket.SendCommand(0,bytesof('NewAuth|' + FClientName));
+end;
+
+procedure TForm1.ClientSocketDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ FConnecting := False;
+
+ Log('Disconnected from server');
+
+ // Only start auto-reconnection if we're not already trying to connect
+ // This prevents rapid connect/disconnect cycles when server shuts down
+ if not Timer1.Enabled then
+ StartReconnectTimer;
+end;
+
+procedure TForm1.ClientSocketCommand(Sender: TObject; aLine: TncLine;
+ aCmd: Integer; const aData: TBytes);
+var
+ dataReceived: String;
+ CommandName: string;
+begin
+ // Convert bytes to string
+ dataReceived := StringOf(aData);
+
+ // Parse command first (no lock needed for parsing) - EXACT same logic as ncSources
+ FCommandParser.Clear;
+ FCommandParser.DelimitedText := dataReceived;
+
+ if FCommandParser.Count > 0 then
+ begin
+ CommandName := FCommandParser[0];
+
+ // Lock per command for better concurrency
+ FCommandLock.Enter;
+ try
+////////////////////////////////////////////////////////////////////////////////
+/// Handle command ScreenShot (server requesting screenshot)
+////////////////////////////////////////////////////////////////////////////////
+ if CommandName = 'ScreenShot' then
+ begin
+ TThread.Queue(nil,
+ procedure
+ var
+ ScreenshotData: TBytes;
+ begin
+ // Capture screenshot
+ ScreenshotData := CaptureScreenshot;
+
+ try
+
+ ClientSocket.SendCommand(0, BytesOf('ScreenShot|') + ScreenshotData);
+
+ Log('SEND SCREENSHOT');
+
+ except
+ on E: Exception do
+ Log('Error sending screenshot: ' + E.Message);
+ end;
+ end);
+ end
+////////////////////////////////////////////////////////////////////////////////
+/// Handle command TITLE (server setting window title)
+////////////////////////////////////////////////////////////////////////////////
+ else if CommandName = 'TITLE' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ Self.Caption := FCommandParser[1];
+ end);
+ end;
+ end
+////////////////////////////////////////////////////////////////////////////////
+/// Handle unknown commands
+////////////////////////////////////////////////////////////////////////////////
+ else
+ begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ Log('Unknown command: ' + CommandName);
+ end);
+ end;
+ finally
+ FCommandLock.Leave;
+ end;
+ end
+ else
+ begin
+ // Handle non-command data (direct message) - lock for consistency
+ FCommandLock.Enter;
+ try
+ TThread.Queue(nil,
+ procedure
+ begin
+ Log('Server: ' + dataReceived);
+ end);
+ finally
+ FCommandLock.Leave;
+ end;
+ end;
+end;
+
+procedure TForm1.ClientSocketReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ dataReceived: String;
+begin
+ // Convert raw bytes to string
+ dataReceived := StringOf(Copy(aBuf, 0, aBufCount));
+
+ // Display received raw text data
+ TThread.Queue(nil, procedure
+ begin
+
+ Log(Format('[%s] OnReadData fired: %d bytes', [TimeToStr(Now), aBufCount]));
+ Log(Format('[%s] Raw text from server: %s', [TimeToStr(Now), dataReceived]));
+
+
+ // Send response back to server
+ try
+ ClientSocket.Send(Format('CLIENT_RESPONSE: %s', [dataReceived]));
+ Log(Format('[%s] Sent response back to server', [TimeToStr(Now)]));
+ except
+ on E: Exception do
+ Log(Format('[%s] Error sending response: %s', [TimeToStr(Now), E.Message]));
+ end;
+ end);
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ Memo1.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ Memo1.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ Memo1.CopyToClipboard;
+end;
+
+end.
+
+
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dpr b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dpr
new file mode 100644
index 0000000..c7abc8b
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dpr
@@ -0,0 +1,17 @@
+program Server;
+
+uses
+ Vcl.Forms,
+ uMainServer in 'uMainServer.pas' {Form1},
+ Vcl.Themes,
+ Vcl.Styles;
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ TStyleManager.TrySetStyle('Carbon');
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dproj b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dproj
new file mode 100644
index 0000000..4282122
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dproj
@@ -0,0 +1,1118 @@
+
+
+ {643E0350-1175-43AC-972A-F5DD8A0BC559}
+ 20.2
+ VCL
+ True
+ Release
+ Win32
+ Server
+ 3
+ Application
+ Server.dpr
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ Server
+ Carbon|VCLSTYLE|$(BDSCOMMONDIR)\Styles\Carbon.vsf
+
+
+ JvNet;RaizeComponentsVcl;vclwinx;DataSnapServer;TMSVCLUIPackPkgDXE12;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;dbxcds;vcledge;sed12Athens;VCLTMSFNCMapsPkgDXE12;DBXFirebirdDriver;JvAppFrm;dacvcl290;FireDACSqliteDriver;DbxClientDriver;JclVcl;soapmidas;TMSCryptoPkgDEDXE12;Jcl;dbexpress;JvManagedThreads;clinetsuite_12;TMSVCLUIPackPkgExDXE12;vquery290;inet;vcltouch;GLibWMI;JvDB;FireDACDBXDriver;fmxdae;MSICS_Rtl;JvCustom;CustomIPTransport;FireDACMSSQLDriver;LockBox3DR;JvSystem;JvControls;PKIEDB29;acntDX12_R;JvCrypt;JvJans;JvMM;IndySystem;JvGlobus;VirtualTreesR;JclContainers;JvPageComps;vclFireDAC;madDisAsm_;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IcsFmxNewRun;ResizeKitPKD29;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;IcsCommonNewRun;NxStandard6Run_d12;DBXSybaseASEDriver;JvRuntimeDesign;JvXPCtrls;NetCom7;vclimg;DataSnapFireDAC;unidacfmx290;inetdbxpress;FireDAC;JvDocking;JvDlgs;xmlrtl;TMSCryptoPkgDXE12;dsnap;JvCmp;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;StyleControls_d12Athens;DatasnapConnectorsFreePascal;vc2;emshosting;FireDACCommonDriver;VCLTMSFNCCorePkgDXE12;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;madBasic_;JvBands;crcontrols290;inetdb;GR32_R;FireDACASADriver;vclactnband;fmxFireDAC;FireDACInfxDriver;AcmComponents;DBXMySQLDriver;VclSmp;DataSnapCommon;JvPascalInterpreter;EurekaLogCore;fmxase;JvPluginSystem;DBXOdbcDriver;JvTimeFramework;dbrtl;FireDACOracleDriver;FMXTMSFNCUIPackPkgDXE12;Skia.Package.FMX;FireDACMSAccDriver;DataSnapIndy10ServerTransport;JclDeveloperTools;PKIECtrl29;DataSnapConnectors;MiTeC_Common;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;CnPack_D120A;JvWizards;FMXTMSFNCMapsPkgDXE12;FireDACTDataDriver;Skia.Package.VCL;vcldb;SynEditDR;VCLTMSFNCUIPackPkgDXE12;JvCore;unidacvcl290;dacfmx290;bindcomp;inetstn;MfPackX317;IndyCore;RESTBackendComponents;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;JvDotNetCtrls;JvHMI;mORMot2Components;IcsVclNewRun;DBXDb2Driver;FMXTMSFNCCorePkgDXE12;dac290;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;JvPrintPreview;tethering;JvStdCtrls;bindcompvcl;CloudService;DBXSybaseASADriver;TMSMemInsightPkgDXE12;mORMot2wsComponents;soaprtl;unidac290;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ RaizeComponentsVcl;vclwinx;DataSnapServer;TMSVCLUIPackPkgDXE12;fmx;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;appanalytics;IndyProtocols;vclx;dbxcds;vcledge;VCLTMSFNCMapsPkgDXE12;DBXFirebirdDriver;FireDACSqliteDriver;DbxClientDriver;soapmidas;dbexpress;clinetsuite_12;TMSVCLUIPackPkgExDXE12;inet;vcltouch;FireDACDBXDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;LockBox3DR;PKIEDB29;IndySystem;VirtualTreesR;vclFireDAC;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IcsFmxNewRun;ResizeKitPKD29;bindcompdbx;rtl;FireDACMySQLDriver;DBXSqliteDriver;IcsCommonNewRun;NxStandard6Run_d12;DBXSybaseASEDriver;NetCom7;vclimg;DataSnapFireDAC;inetdbxpress;FireDAC;xmlrtl;TMSCryptoPkgDXE12;dsnap;FireDACDb2Driver;DBXOracleDriver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;StyleControls_d12Athens;DatasnapConnectorsFreePascal;emshosting;FireDACCommonDriver;VCLTMSFNCCorePkgDXE12;IndyIPClient;bindcompvclwinx;emsedge;bindcompfmx;inetdb;FireDACASADriver;vclactnband;fmxFireDAC;FireDACInfxDriver;DBXMySQLDriver;VclSmp;DataSnapCommon;fmxase;DBXOdbcDriver;dbrtl;FireDACOracleDriver;FMXTMSFNCUIPackPkgDXE12;FireDACMSAccDriver;DataSnapIndy10ServerTransport;PKIECtrl29;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;FMXTMSFNCMapsPkgDXE12;FireDACTDataDriver;Skia.Package.VCL;vcldb;SynEditDR;VCLTMSFNCUIPackPkgDXE12;bindcomp;inetstn;IndyCore;RESTBackendComponents;FireDACADSDriver;RaizeComponentsVclDb;RESTComponents;IndyIPServer;vcl;dsnapxml;adortl;dsnapcon;DataSnapClient;DataSnapProviderClient;IcsVclNewRun;DBXDb2Driver;FMXTMSFNCCorePkgDXE12;emsclientfiredac;FireDACPgDriver;FireDACDSDriver;tethering;bindcompvcl;CloudService;DBXSybaseASADriver;TMSMemInsightPkgDXE12;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+ true
+ true
+
+
+ false
+ PerMonitorV2
+ true
+ 1033
+
+
+ PerMonitorV2
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ PerMonitorV2
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Server.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+
+
+ Server.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dproj.local b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dproj.local
new file mode 100644
index 0000000..d07c108
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.dproj.local
@@ -0,0 +1,13 @@
+
+
+
+ 2025/06/27 10:23:15.000.944,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/06/27 10:25:54.000.288,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/12 15:36:10.000.674,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/15 19:57:51.000.682,=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/15 19:59:32.000.056,D:\_Delphi\_Library\Netcom7\NetCom7-Templates\NeCom7-Multi-Socket_ncSocketsPro_v2.0\Server\uMainServer.pas=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.pas
+ 2025/07/15 19:59:32.000.056,D:\_Delphi\_Library\Netcom7\NetCom7-Templates\NeCom7-Multi-Socket_ncSocketsPro_v2.0\Server\uMainServer.dfm=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Unit1.dfm
+ 2025/07/15 19:59:49.000.795,C:\Users\leet\Documents\Embarcadero\Studio\Projects\Server.dproj=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Project1.dproj
+ 2025/07/15 19:59:59.000.250,D:\_Delphi\_Library\Netcom7\NetCom7-Templates\NeCom7-Multi-Socket_ncSocketsPro_v2.0\Server\Server.dproj=C:\Users\leet\Documents\Embarcadero\Studio\Projects\Server.dproj
+
+
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.identcache b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.identcache
new file mode 100644
index 0000000..59bdb00
Binary files /dev/null and b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.identcache differ
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.res b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.res
new file mode 100644
index 0000000..45cdbdf
Binary files /dev/null and b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Server.res differ
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Win32/Release/server.pfx b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Win32/Release/server.pfx
new file mode 100644
index 0000000..0b1ad11
Binary files /dev/null and b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/Win32/Release/server.pfx differ
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/uMainServer.dfm b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/uMainServer.dfm
new file mode 100644
index 0000000..cb2cefd
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/uMainServer.dfm
@@ -0,0 +1,110 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'Server - ncSocketsPro Demo'
+ ClientHeight = 283
+ ClientWidth = 780
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -12
+ Font.Name = 'Segoe UI'
+ Font.Style = []
+ Position = poDesktopCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 15
+ object Image1: TImage
+ Left = 578
+ Top = 8
+ Width = 192
+ Height = 145
+ end
+ object ListView1: TListView
+ Left = 8
+ Top = 8
+ Width = 564
+ Height = 145
+ Columns = <
+ item
+ Caption = 'IP Address'
+ Width = 150
+ end
+ item
+ AutoSize = True
+ Caption = 'NickName'
+ end
+ item
+ AutoSize = True
+ Caption = 'Status'
+ end
+ item
+ AutoSize = True
+ Caption = 'Connected At'
+ end>
+ ReadOnly = True
+ RowSelect = True
+ PopupMenu = PopupMenu1
+ TabOrder = 0
+ ViewStyle = vsReport
+ end
+ object Memo1: TMemo
+ Left = 8
+ Top = 159
+ Width = 762
+ Height = 90
+ Lines.Strings = (
+ '')
+ TabOrder = 1
+ end
+ object StatusBar1: TStatusBar
+ Left = 0
+ Top = 264
+ Width = 780
+ Height = 19
+ Panels = <
+ item
+ Text = 'Status: Offline!'
+ Width = 150
+ end
+ item
+ Text = 'Clients Connected: 0'
+ Width = 150
+ end>
+ end
+ object PopupMenu1: TPopupMenu
+ Left = 96
+ Top = 64
+ object S1: TMenuItem
+ Caption = 'Send To All'
+ OnClick = S1Click
+ end
+ object S2: TMenuItem
+ Caption = 'Send To Selected'
+ OnClick = S2Click
+ end
+ object S3: TMenuItem
+ Caption = 'Send Raw To Selected'
+ OnClick = S3Click
+ end
+ object N1: TMenuItem
+ Caption = '-'
+ end
+ object G1: TMenuItem
+ Caption = 'GetScreenShot'
+ OnClick = G1Click
+ end
+ object C1: TMenuItem
+ Caption = 'Change Window Title'
+ OnClick = C1Click
+ end
+ end
+ object ServerSocket: TncTCPServerDual
+ OnConnected = ServerSocketConnected
+ OnDisconnected = ServerSocketDisconnected
+ OnCommand = ServerSocketCommand
+ Left = 200
+ Top = 72
+ end
+end
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/Server/uMainServer.pas b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/uMainServer.pas
new file mode 100644
index 0000000..9f21246
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/Server/uMainServer.pas
@@ -0,0 +1,566 @@
+unit uMainServer;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Forms,
+ Vcl.ComCtrls, Vcl.Controls, Vcl.Menus, Vcl.Graphics,
+ Vcl.Imaging.jpeg, System.Generics.Collections, System.SyncObjs, Vcl.ExtCtrls,
+ ncSocketList,Vcl.StdCtrls, ncSocketsDual;
+
+type
+ TConnectedUserData = class
+ private
+ FLine: TncLine;
+ FID: string;
+ FConnectedAt: TDateTime;
+ public
+ constructor Create(ALine: TncLine; const AID: string);
+ property Line: TncLine read FLine;
+ property ID: string read FID;
+ property ConnectedAt: TDateTime read FConnectedAt;
+ end;
+
+type
+ TForm1 = class(TForm)
+ StatusBar1: TStatusBar;
+ ListView1: TListView;
+ ServerSocket: TncTCPServerDual;
+ PopupMenu1: TPopupMenu;
+ S1: TMenuItem;
+ S2: TMenuItem;
+ G1: TMenuItem;
+ Memo1: TMemo;
+ S3: TMenuItem;
+ Image1: TImage;
+ N1: TMenuItem;
+ C1: TMenuItem;
+ procedure FormCreate(Sender: TObject);
+ procedure ServerSocketConnected(Sender: TObject; aLine: TncLine);
+ procedure ServerSocketDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ServerSocketCommand(Sender: TObject; aLine: TncLine;
+ aCmd: Integer; const aData: TBytes);
+ procedure ServerSocketReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure S1Click(Sender: TObject);
+ procedure S2Click(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure DisplayScreenShot(const aData: TBytes);
+ procedure G1Click(Sender: TObject);
+ procedure S3Click(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+ procedure C1Click(Sender: TObject);
+ private
+ connectedclients: Integer; // Raw TCP connection count
+ // New optimized data structures
+ FClientsByLine: TDictionary;
+ FClientsByID: TDictionary;
+ FCommandParser: TStringList; // Pre-allocated for command parsing
+ FClientDataLock: TCriticalSection; // Thread safety for client data
+
+ procedure UpdateClientCount;
+ function GetClientCount: Integer;
+ function GetAuthenticatedClientCount: Integer;
+ function GetClientByID(const AID: string): TConnectedUserData;
+ function GetClientByLine(aLine: TncLine): TConnectedUserData;
+ procedure AddClientToUI(AUserData: TConnectedUserData);
+ procedure RemoveClientFromUI(const ClientID: string);
+ procedure SendToAllClients(const AMessage: string);
+ procedure SendToSelectedClient(const AMessage: string);
+ public
+ { Public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+{ TConnectedUserData }
+
+constructor TConnectedUserData.Create(ALine: TncLine; const AID: string);
+begin
+ inherited Create;
+ FLine := ALine;
+ FID := AID;
+ FConnectedAt := Now;
+end;
+
+{ TForm1 }
+
+procedure TForm1.AddClientToUI(AUserData: TConnectedUserData);
+var
+ Item: TListItem;
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ Item := Form1.ListView1.Items.Add;
+ Item.Caption := AUserData.Line.PeerIP; // Column 1: IP Address
+ Item.SubItems.Add(AUserData.ID); // Column 2: NickName/ID
+ Item.SubItems.Add('Connected'); // Column 3: Status
+ Item.SubItems.Add(FormatDateTime('hh:nn:ss', AUserData.ConnectedAt)); // Column 4: Connected At
+ Item.Data := AUserData;
+ end);
+end;
+
+procedure TForm1.RemoveClientFromUI(const ClientID: string);
+var
+ I: Integer;
+begin
+ for I := ListView1.Items.Count - 1 downto 0 do
+ begin
+ if ListView1.Items[I].SubItems[0] = ClientID then
+ begin
+ ListView1.Items.Delete(I);
+ Break;
+ end;
+ end;
+end;
+
+function TForm1.GetClientByID(const AID: string): TConnectedUserData;
+begin
+ FClientDataLock.Enter;
+ try
+ if not FClientsByID.TryGetValue(AID, Result) then
+ Result := nil;
+ finally
+ FClientDataLock.Leave;
+ end;
+end;
+
+procedure TForm1.SendToAllClients(const AMessage: string);
+var
+ SocketList: TSocketList;
+ I: Integer;
+begin
+ // Use the optimized built-in broadcast mechanism (same as ncSources)
+ SocketList := ServerSocket.Lines.LockList;
+ try
+ for I := 0 to SocketList.Count - 1 do
+ begin
+ ServerSocket.SendCommand(SocketList.Lines[I], 0, BytesOf(AMessage));
+ end;
+ finally
+ ServerSocket.Lines.UnlockList;
+ end;
+end;
+
+procedure TForm1.SendToSelectedClient(const AMessage: string);
+var
+ NickName: string;
+ UserData: TConnectedUserData;
+begin
+ if Assigned(Form1.ListView1.Selected) then
+ begin
+ NickName := Form1.ListView1.Selected.SubItems[0];
+ UserData := Form1.GetClientByID(NickName);
+
+ if Assigned(UserData) then
+ begin
+ ServerSocket.SendCommand(UserData.Line, 0, BytesOf(AMessage));
+ end;
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+var
+ CertPath: string;
+begin
+ // Initialize raw TCP connection counter
+ connectedclients := 0;
+
+ // Initialize optimized data structures
+ FClientsByLine := TDictionary.Create;
+ FClientsByID := TDictionary.Create;
+ FCommandParser := TStringList.Create;
+ FCommandParser.Delimiter := '|';
+ FCommandParser.StrictDelimiter := True;
+ FClientDataLock := TCriticalSection.Create;
+
+ // Configure TLS settings for the server
+ ServerSocket.UseTLS := True;
+ ServerSocket.TlsProvider := tpSChannel;
+ CertPath := ExtractFilePath(Application.ExeName) + 'server.pfx';
+ ServerSocket.CertificateFile := CertPath;
+ ServerSocket.PrivateKeyPassword := 'test';
+ ServerSocket.IgnoreCertificateErrors := True; // Changed to True for demo purposes
+
+ // Start server with dual protocol support
+ ServerSocket.Port := 3434;
+ ServerSocket.OnCommand := ServerSocketCommand; // Binary protocol handler
+ ServerSocket.OnReadData := ServerSocketReadData; // Raw text protocol handler
+ ServerSocket.Active := True;
+ StatusBar1.Panels[0].Text := 'Status: Active';
+
+ Image1.Picture.Bitmap.SetSize(Image1.Width, Image1.Height);
+ Image1.Picture.Bitmap.Canvas.Brush.Color := clBlack;
+ Image1.Picture.Bitmap.Canvas.FillRect(Rect(0, 0, Image1.Width, Image1.Height));
+
+end;
+
+procedure TForm1.S1Click(Sender: TObject);
+begin
+ SendToAllClients('Hello ALL');
+end;
+
+procedure TForm1.S2Click(Sender: TObject);
+begin
+ SendToSelectedClient('MSG to you');
+end;
+
+procedure TForm1.S3Click(Sender: TObject);
+var
+ NickName: string;
+ UserData: TConnectedUserData;
+begin
+ // Send raw text using regular Send method - triggers OnReadData event
+ if Assigned(Form1.ListView1.Selected) then
+ begin
+ NickName := Form1.ListView1.Selected.SubItems[0];
+ UserData := Form1.GetClientByID(NickName);
+
+ if Assigned(UserData) then
+ begin
+ ServerSocket.Send(UserData.Line, 'RAW TEXT MESSAGE from server - This should trigger OnReadData!');
+ Log(Format('[%s] Sent raw text to %s', [TimeToStr(Now), NickName]));
+ end;
+ end;
+end;
+
+procedure TForm1.G1Click(Sender: TObject);
+begin
+ SendToSelectedClient('ScreenShot');
+end;
+
+procedure TForm1.C1Click(Sender: TObject);
+var
+ NickName: string;
+ UserData: TConnectedUserData;
+begin
+ if Assigned(Form1.ListView1.Selected) then
+ begin
+ NickName := Form1.ListView1.Selected.SubItems[0];
+ UserData := Form1.GetClientByID(NickName);
+
+ if Assigned(UserData) then
+ begin
+ ServerSocket.SendCommand(UserData.Line,0, BytesOf('TITLE|'+ 'THIS IS A NEW TITLE'));
+ end;
+ end;
+end;
+
+procedure TForm1.ServerSocketConnected(Sender: TObject; aLine: TncLine);
+begin
+ Inc(connectedclients);
+ UpdateClientCount;
+end;
+
+procedure TForm1.ServerSocketDisconnected(Sender: TObject; aLine: TncLine);
+var
+ UserData: TConnectedUserData;
+ ClientID: string;
+begin
+ // Decrement raw TCP connection counter
+ Dec(connectedclients);
+
+ FClientDataLock.Enter;
+ try
+ // O(1) lookup by line reference
+ if FClientsByLine.TryGetValue(aLine, UserData) then
+ begin
+ ClientID := UserData.ID;
+
+ // Remove from both dictionaries - O(1) operations
+ FClientsByLine.Remove(aLine);
+ FClientsByID.Remove(ClientID);
+
+ // Clean up the user data object
+ UserData.Free;
+ end;
+ finally
+ FClientDataLock.Leave;
+ end;
+
+ // Update UI (outside of lock to avoid deadlock)
+ if ClientID <> '' then
+ begin
+ RemoveClientFromUI(ClientID);
+ end;
+
+ UpdateClientCount;
+end;
+
+procedure TForm1.ServerSocketCommand(Sender: TObject; aLine: TncLine;
+ aCmd: Integer; const aData: TBytes);
+var
+ datarecieved: String;
+ ClientAdded: Boolean;
+ CommandName: string;
+ UserData: TConnectedUserData;
+begin
+ // Convert bytes to string - exact same as ncSources!
+ datarecieved := StringOf(aData);
+ ClientAdded := False;
+
+ // Parse command first (no lock needed for parsing)
+ FCommandParser.Clear;
+ FCommandParser.DelimitedText := datarecieved;
+
+ if FCommandParser.Count > 0 then
+ begin
+ CommandName := FCommandParser[0];
+
+ Log(Format('[%s] Parsed command: %s', [TimeToStr(Now), CommandName]));
+
+ // Lock per command for better concurrency
+ FClientDataLock.Enter;
+ try
+////////////////////////////////////////////////////////////////////////////////
+/// Handle command NewAuth - EXACT same logic as ncSources
+////////////////////////////////////////////////////////////////////////////////
+ if CommandName = 'NewAuth' then
+ begin
+ Log(Format('[%s] Processing NewAuth command', [TimeToStr(Now)]));
+
+ // Check if we have a client ID
+ if FCommandParser.Count > 1 then
+ begin
+ Log(Format('[%s] Client ID: %s', [TimeToStr(Now), FCommandParser[1]]));
+
+ // Check if client ID already exists to prevent duplicates
+ if not FClientsByID.ContainsKey(FCommandParser[1]) then
+ begin
+ UserData := TConnectedUserData.Create(aLine, FCommandParser[1]);
+
+ // Add to both dictionaries for O(1) lookup
+ FClientsByLine.Add(aLine, UserData);
+ FClientsByID.Add(FCommandParser[1], UserData);
+ ClientAdded := True;
+
+ Log(Format('[%s] Client %s authenticated successfully', [TimeToStr(Now), FCommandParser[1]]));
+ end
+ else
+ begin
+ Log(Format('[%s] Client %s already exists', [TimeToStr(Now), FCommandParser[1]]));
+ end;
+ end
+ else
+ begin
+ Log(Format('[%s] NewAuth command missing client ID', [TimeToStr(Now)]));
+ end;
+ end
+////////////////////////////////////////////////////////////////////////////////
+/// Handle command ScreenShot (server requesting screenshot)
+////////////////////////////////////////////////////////////////////////////////
+ else if CommandName = 'ScreenShot' then
+ begin
+
+ if FCommandParser.Count > 1 then
+ begin
+
+ TThread.Queue(nil,
+ procedure
+ var
+ imageData: TBytes;
+ begin
+ try
+ // Extract image data from command - skip "ScreenShot|" (10 bytes)
+ // aData contains: "ScreenShot|" + JPEG binary data
+ imageData := Copy(aData, 11, Length(aData));
+
+ Form1.DisplayScreenShot(imageData);
+ Log('RECEIVE SCREENSHOT');
+
+ except
+ on E: Exception do
+ begin
+ Log(Format('[%s] Error processing screenshot: %s', [TimeToStr(Now), E.Message]));
+ end;
+ end;
+ end);
+ end
+ end
+////////////////////////////////////////////////////////////////////////////////
+/// Handle unknown commands
+////////////////////////////////////////////////////////////////////////////////
+ else
+ begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ Log(Format('[%s] Unknown command received: %s', [TimeToStr(Now), CommandName]));
+ end);
+ end;
+ finally
+ FClientDataLock.Leave;
+ end;
+ end
+ else
+ begin
+ Log(Format('[%s] Failed to parse command data', [TimeToStr(Now)]));
+ end;
+
+ // Update UI outside of lock to prevent deadlock
+ if ClientAdded then
+ begin
+ FClientDataLock.Enter;
+ try
+ if FCommandParser.Count > 1 then
+ begin
+ if FClientsByID.TryGetValue(FCommandParser[1], UserData) then
+ AddClientToUI(UserData);
+ end;
+ finally
+ FClientDataLock.Leave;
+ end;
+
+ // Update status bar after authentication
+ UpdateClientCount;
+ Log(Format('[%s] UI updated - Auth count: %d', [TimeToStr(Now), GetAuthenticatedClientCount]));
+ end;
+end;
+
+procedure TForm1.ServerSocketReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ dataReceived: String;
+ UserData: TConnectedUserData;
+begin
+ // Convert raw bytes to string
+ dataReceived := StringOf(Copy(aBuf, 0, aBufCount));
+
+ // Display received raw text data
+ TThread.Queue(nil, procedure
+ begin
+ Log(Format('[%s] OnReadData fired: %d bytes', [TimeToStr(Now), aBufCount]));
+ Log(Format(' Raw data: %s', [dataReceived]));
+
+ // Find the user data for this line to get client info
+ UserData := GetClientByLine(aLine);
+ if Assigned(UserData) then
+ begin
+ Log(Format('[%s] Raw text received from %s', [TimeToStr(Now), UserData.ID]));
+ end
+ else
+ begin
+ Log(Format('[%s] Raw text received from unknown client', [TimeToStr(Now)]));
+ end;
+ end);
+end;
+
+procedure TForm1.UpdateClientCount;
+begin
+ FClientDataLock.Enter;
+ try
+ StatusBar1.Panels[1].Text := Format('Raw: %d | Auth: %d',
+ [connectedclients, FClientsByID.Count]);
+ finally
+ FClientDataLock.Leave;
+ end;
+end;
+
+function TForm1.GetClientCount: Integer;
+begin
+ Result := connectedclients;
+end;
+
+function TForm1.GetAuthenticatedClientCount: Integer;
+begin
+ FClientDataLock.Enter;
+ try
+ Result := FClientsByID.Count;
+ finally
+ FClientDataLock.Leave;
+ end;
+end;
+
+function TForm1.GetClientByLine(aLine: TncLine): TConnectedUserData;
+begin
+ FClientDataLock.Enter;
+ try
+ if not FClientsByLine.TryGetValue(aLine, Result) then
+ Result := nil;
+ finally
+ FClientDataLock.Leave;
+ end;
+end;
+
+procedure TForm1.DisplayScreenShot(const aData: TBytes);
+var
+ MS: TMemoryStream;
+ jpgImage: TJPEGImage;
+begin
+ // Create streams for JPEG loading
+ MS := TMemoryStream.Create;
+ jpgImage := TJPEGImage.Create;
+ try
+ // Load JPEG data directly into stream
+ MS.WriteBuffer(aData[0], Length(aData));
+ MS.Position := 0;
+
+ // Load JPEG from data stream
+ jpgImage.LoadFromStream(MS);
+
+ // Display in TImage component
+ if Assigned(Form1) and Assigned(Form1.Image1) then
+ begin
+ Form1.Image1.Picture.Assign(jpgImage);
+ Form1.Image1.Stretch := True;
+ end;
+
+ finally
+ MS.Free;
+ jpgImage.Free;
+ end;
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ if ServerSocket.Active then
+ ServerSocket.Active := False;
+
+ FClientDataLock.Enter;
+ try
+ for var UserData in FClientsByLine.Values do
+ UserData.Free;
+ FClientsByLine.Free;
+ FClientsByID.Free;
+ finally
+ FClientDataLock.Leave;
+ end;
+
+ FCommandParser.Free;
+ FClientDataLock.Free;
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ Memo1.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ Memo1.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ Memo1.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/ncSocketsDual_Multi-Socket/ncSocketsDual_Multi-Socket.groupproj b/Demos/TCP/ncSocketsDual_Multi-Socket/ncSocketsDual_Multi-Socket.groupproj
new file mode 100644
index 0000000..483ba6a
--- /dev/null
+++ b/Demos/TCP/ncSocketsDual_Multi-Socket/ncSocketsDual_Multi-Socket.groupproj
@@ -0,0 +1,48 @@
+
+
+ {CC772AFE-3A20-48E0-B003-EBCEAE976C71}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dpr b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dpr
new file mode 100644
index 0000000..2f8f3e0
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dpr
@@ -0,0 +1,14 @@
+program ThreadedClient;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dproj b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dproj
new file mode 100644
index 0000000..2a83196
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dproj
@@ -0,0 +1,190 @@
+
+
+ {ECD6784B-722C-4CA2-BC1E-5A3CA0052F74}
+ ThreadedClient.dpr
+ True
+ Release
+ ThreadedClient
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ ThreadedClient
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ ThreadedClient.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dproj.local b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.identcache b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.identcache
new file mode 100644
index 0000000..899a96f
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.identcache differ
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.res b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.res
new file mode 100644
index 0000000..d8a8600
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_Benchmark/Client/ThreadedClient.res differ
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ufrmMain.dfm b/Demos/TCP/ncSocketsThd_Benchmark/Client/ufrmMain.dfm
new file mode 100644
index 0000000..23b8590
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Client/ufrmMain.dfm
@@ -0,0 +1,323 @@
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'NetCom7 Threaded Client Demo'
+ ClientHeight = 700
+ ClientWidth = 900
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object Panel1: TPanel
+ Left = 0
+ Top = 0
+ Width = 900
+ Height = 89
+ Align = alTop
+ TabOrder = 0
+ object Label1: TLabel
+ Left = 16
+ Top = 16
+ Width = 26
+ Height = 13
+ Caption = 'Host:'
+ end
+ object Label2: TLabel
+ Left = 16
+ Top = 48
+ Width = 24
+ Height = 13
+ Caption = 'Port:'
+ end
+ object btnConnect: TButton
+ Left = 256
+ Top = 16
+ Width = 121
+ Height = 25
+ Caption = 'Connect'
+ TabOrder = 0
+ OnClick = btnConnectClick
+ end
+ object edtHost: TEdit
+ Left = 47
+ Top = 13
+ Width = 121
+ Height = 21
+ TabOrder = 1
+ Text = 'localhost'
+ end
+ object edtPort: TEdit
+ Left = 47
+ Top = 45
+ Width = 121
+ Height = 21
+ TabOrder = 2
+ Text = '8080'
+ end
+ object btnClearLog: TButton
+ Left = 400
+ Top = 16
+ Width = 75
+ Height = 25
+ Caption = 'Clear Log'
+ TabOrder = 3
+ OnClick = btnClearLogClick
+ end
+ end
+ object Panel2: TPanel
+ Left = 0
+ Top = 89
+ Width = 900
+ Height = 320
+ Align = alClient
+ TabOrder = 1
+ DesignSize = (
+ 900
+ 320)
+ object Label3: TLabel
+ Left = 16
+ Top = 8
+ Width = 47
+ Height = 13
+ Caption = 'Client Log'
+ end
+ object memoLog: TMemo
+ Left = 16
+ Top = 27
+ Width = 867
+ Height = 281
+ Anchors = [akLeft, akTop, akRight, akBottom]
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Consolas'
+ Font.Style = []
+ ParentFont = False
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ end
+ end
+ object Panel3: TPanel
+ Left = 0
+ Top = 409
+ Width = 900
+ Height = 145
+ Align = alBottom
+ TabOrder = 2
+ object Label4: TLabel
+ Left = 16
+ Top = 16
+ Width = 27
+ Height = 13
+ Caption = 'Echo:'
+ end
+ object Label5: TLabel
+ Left = 16
+ Top = 48
+ Width = 44
+ Height = 13
+ Caption = 'Reverse:'
+ end
+ object Label6: TLabel
+ Left = 16
+ Top = 80
+ Width = 28
+ Height = 13
+ Caption = 'Hash:'
+ end
+ object btnPing: TButton
+ Left = 16
+ Top = 112
+ Width = 75
+ Height = 25
+ Caption = 'PING'
+ TabOrder = 0
+ OnClick = btnPingClick
+ end
+ object edtEcho: TEdit
+ Left = 63
+ Top = 13
+ Width = 121
+ Height = 21
+ TabOrder = 1
+ Text = 'Hello World'
+ OnKeyPress = edtEchoKeyPress
+ end
+ object btnEcho: TButton
+ Left = 200
+ Top = 13
+ Width = 75
+ Height = 25
+ Caption = 'ECHO'
+ TabOrder = 2
+ OnClick = btnEchoClick
+ end
+ object edtReverse: TEdit
+ Left = 63
+ Top = 45
+ Width = 121
+ Height = 21
+ TabOrder = 3
+ Text = 'Hello World'
+ OnKeyPress = edtReverseKeyPress
+ end
+ object btnReverse: TButton
+ Left = 200
+ Top = 45
+ Width = 75
+ Height = 25
+ Caption = 'REVERSE'
+ TabOrder = 4
+ OnClick = btnReverseClick
+ end
+ object edtHash: TEdit
+ Left = 63
+ Top = 77
+ Width = 121
+ Height = 21
+ TabOrder = 5
+ Text = 'TestData'
+ OnKeyPress = edtHashKeyPress
+ end
+ object btnHash: TButton
+ Left = 200
+ Top = 77
+ Width = 75
+ Height = 25
+ Caption = 'HASH'
+ TabOrder = 6
+ OnClick = btnHashClick
+ end
+ object btnCompute: TButton
+ Left = 97
+ Top = 112
+ Width = 75
+ Height = 25
+ Caption = 'COMPUTE'
+ TabOrder = 7
+ OnClick = btnComputeClick
+ end
+ object btnTime: TButton
+ Left = 178
+ Top = 112
+ Width = 75
+ Height = 25
+ Caption = 'TIME'
+ TabOrder = 8
+ OnClick = btnTimeClick
+ end
+ end
+ object Panel4: TPanel
+ Left = 0
+ Top = 554
+ Width = 900
+ Height = 41
+ Align = alBottom
+ TabOrder = 3
+ object Label7: TLabel
+ Left = 16
+ Top = 16
+ Width = 35
+ Height = 13
+ Caption = 'Status:'
+ end
+ object lblStatus: TLabel
+ Left = 55
+ Top = 16
+ Width = 76
+ Height = 13
+ Caption = 'Disconnected'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clRed
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ end
+ object Panel5: TPanel
+ Left = 0
+ Top = 595
+ Width = 900
+ Height = 105
+ Align = alBottom
+ TabOrder = 4
+ object Label8: TLabel
+ Left = 16
+ Top = 16
+ Width = 114
+ Height = 13
+ Caption = 'Stress Test Settings'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblConcurrency: TLabel
+ Left = 200
+ Top = 40
+ Width = 7
+ Height = 13
+ Caption = '5'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clBlue
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblStressStatus: TLabel
+ Left = 400
+ Top = 72
+ Width = 3
+ Height = 13
+ end
+ object trackConcurrency: TTrackBar
+ Left = 16
+ Top = 35
+ Width = 177
+ Height = 33
+ Max = 20
+ Min = 1
+ Position = 5
+ TabOrder = 0
+ OnChange = trackConcurrencyChange
+ end
+ object btnStressTest: TButton
+ Left = 256
+ Top = 35
+ Width = 121
+ Height = 25
+ Caption = 'Start Stress Test'
+ TabOrder = 1
+ OnClick = btnStressTestClick
+ end
+ object progressStress: TProgressBar
+ Left = 400
+ Top = 35
+ Width = 350
+ Height = 25
+ TabOrder = 2
+ end
+ object btnStopStress: TButton
+ Left = 256
+ Top = 67
+ Width = 121
+ Height = 25
+ Caption = 'Stop Stress Test'
+ Enabled = False
+ TabOrder = 3
+ OnClick = btnStopStressClick
+ end
+ end
+end
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Client/ufrmMain.pas b/Demos/TCP/ncSocketsThd_Benchmark/Client/ufrmMain.pas
new file mode 100644
index 0000000..480f33b
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Client/ufrmMain.pas
@@ -0,0 +1,543 @@
+unit ufrmMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
+ System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
+ Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ComCtrls, System.DateUtils,
+ System.Threading, System.SyncObjs, System.Diagnostics, System.Math,
+ ncSocketsThd, ncLines, ncThreads;
+
+type
+ TfrmMain = class(TForm)
+ Panel1: TPanel;
+ btnConnect: TButton;
+ edtHost: TEdit;
+ edtPort: TEdit;
+ Label1: TLabel;
+ Label2: TLabel;
+ Panel2: TPanel;
+ memoLog: TMemo;
+ Label3: TLabel;
+ Panel3: TPanel;
+ btnPing: TButton;
+ edtEcho: TEdit;
+ btnEcho: TButton;
+ Label4: TLabel;
+ edtReverse: TEdit;
+ btnReverse: TButton;
+ Label5: TLabel;
+ edtHash: TEdit;
+ btnHash: TButton;
+ Label6: TLabel;
+ btnCompute: TButton;
+ btnTime: TButton;
+ Panel4: TPanel;
+ Label7: TLabel;
+ lblStatus: TLabel;
+ btnClearLog: TButton;
+ Panel5: TPanel;
+ Label8: TLabel;
+ trackConcurrency: TTrackBar;
+ lblConcurrency: TLabel;
+ btnStressTest: TButton;
+ progressStress: TProgressBar;
+ lblStressStatus: TLabel;
+ btnStopStress: TButton;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnConnectClick(Sender: TObject);
+ procedure btnPingClick(Sender: TObject);
+ procedure btnEchoClick(Sender: TObject);
+ procedure btnReverseClick(Sender: TObject);
+ procedure btnHashClick(Sender: TObject);
+ procedure btnComputeClick(Sender: TObject);
+ procedure btnTimeClick(Sender: TObject);
+ procedure btnClearLogClick(Sender: TObject);
+ procedure trackConcurrencyChange(Sender: TObject);
+ procedure btnStressTestClick(Sender: TObject);
+ procedure btnStopStressClick(Sender: TObject);
+ procedure edtEchoKeyPress(Sender: TObject; var Key: Char);
+ procedure edtReverseKeyPress(Sender: TObject; var Key: Char);
+ procedure edtHashKeyPress(Sender: TObject; var Key: Char);
+ private
+ FClient: TncTCPClientThd;
+ FStressTestRunning: Boolean;
+ FStressTestTask: ITask;
+ FStressTestLock: TCriticalSection;
+ FRequestCount: Integer;
+ FResponseCount: Integer;
+ FErrorCount: Integer;
+
+ procedure ClientConnected(Sender: TObject; aLine: TncLine);
+ procedure ClientDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ClientReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+ procedure LogMessage(const aMessage: string);
+ procedure UpdateStatus;
+ procedure SendCommand(const aCommand: string);
+ procedure UpdateStressTestProgress(aProgress: Integer; const aStatus: string);
+ procedure StressTestWorker;
+ procedure EnableControls(aEnabled: Boolean);
+ public
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.dfm}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ FStressTestRunning := False;
+ FStressTestLock := TCriticalSection.Create;
+ FRequestCount := 0;
+ FResponseCount := 0;
+ FErrorCount := 0;
+
+ // Create TncClient
+ FClient := TncTCPClientThd.Create(Self);
+ FClient.EventsUseMainThread := True;
+ FClient.OnConnected := ClientConnected;
+ FClient.OnDisconnected := ClientDisconnected;
+ FClient.OnReadData := ClientReadData;
+
+ // Initialize UI
+ edtHost.Text := 'localhost';
+ edtPort.Text := '8080';
+ trackConcurrency.Position := 5;
+ lblConcurrency.Caption := IntToStr(trackConcurrency.Position);
+
+ UpdateStatus;
+ LogMessage('Client initialized');
+ LogMessage('Ready to connect to server...');
+end;
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ if FStressTestRunning then
+ begin
+ FStressTestRunning := False;
+ if Assigned(FStressTestTask) then
+ FStressTestTask.Wait;
+ end;
+
+ if Assigned(FClient) then
+ begin
+ FClient.Active := False;
+ FClient.Free;
+ end;
+
+ FStressTestLock.Free;
+end;
+
+procedure TfrmMain.btnConnectClick(Sender: TObject);
+begin
+ if FClient.Active then
+ begin
+ // Disconnect
+ FClient.Active := False;
+ btnConnect.Caption := 'Connect';
+ LogMessage('Disconnecting from server...');
+ end
+ else
+ begin
+ // Connect
+ try
+ FClient.Host := edtHost.Text;
+ FClient.Port := StrToInt(edtPort.Text);
+ FClient.Active := True;
+ btnConnect.Caption := 'Disconnect';
+ LogMessage('Connecting to ' + edtHost.Text + ':' + edtPort.Text + '...');
+ except
+ on E: Exception do
+ begin
+ LogMessage('Error connecting: ' + E.Message);
+ ShowMessage('Error connecting: ' + E.Message);
+ end;
+ end;
+ end;
+end;
+
+procedure TfrmMain.btnPingClick(Sender: TObject);
+begin
+ SendCommand('PING');
+end;
+
+procedure TfrmMain.btnEchoClick(Sender: TObject);
+begin
+ if Trim(edtEcho.Text) = '' then
+ begin
+ ShowMessage('Please enter text to echo');
+ edtEcho.SetFocus;
+ Exit;
+ end;
+ SendCommand('ECHO ' + edtEcho.Text);
+end;
+
+procedure TfrmMain.btnReverseClick(Sender: TObject);
+begin
+ if Trim(edtReverse.Text) = '' then
+ begin
+ ShowMessage('Please enter text to reverse');
+ edtReverse.SetFocus;
+ Exit;
+ end;
+ SendCommand('REVERSE ' + edtReverse.Text);
+end;
+
+procedure TfrmMain.btnHashClick(Sender: TObject);
+begin
+ if Trim(edtHash.Text) = '' then
+ begin
+ ShowMessage('Please enter text to hash');
+ edtHash.SetFocus;
+ Exit;
+ end;
+ SendCommand('HASH ' + edtHash.Text);
+end;
+
+procedure TfrmMain.btnComputeClick(Sender: TObject);
+begin
+ SendCommand('COMPUTE');
+end;
+
+procedure TfrmMain.btnTimeClick(Sender: TObject);
+begin
+ SendCommand('TIME');
+end;
+
+procedure TfrmMain.btnClearLogClick(Sender: TObject);
+begin
+ memoLog.Clear;
+end;
+
+procedure TfrmMain.trackConcurrencyChange(Sender: TObject);
+begin
+ lblConcurrency.Caption := IntToStr(trackConcurrency.Position);
+end;
+
+procedure TfrmMain.btnStressTestClick(Sender: TObject);
+begin
+ if not FClient.Active then
+ begin
+ ShowMessage('Please connect to server first');
+ Exit;
+ end;
+
+ FStressTestRunning := True;
+ FRequestCount := 0;
+ FResponseCount := 0;
+ FErrorCount := 0;
+
+ EnableControls(False);
+ btnStopStress.Enabled := True;
+ progressStress.Position := 0;
+
+ // Disable event synchronization for better performance during stress test
+ FClient.EventsUseMainThread := False;
+
+ LogMessage('Starting stress test with ' + IntToStr(trackConcurrency.Position) + ' concurrent tasks...');
+
+ // Start stress test in background task
+ FStressTestTask := TTask.Create(StressTestWorker);
+ FStressTestTask.Start;
+end;
+
+procedure TfrmMain.btnStopStressClick(Sender: TObject);
+begin
+ FStressTestRunning := False;
+ // Restore event synchronization
+ FClient.EventsUseMainThread := True;
+ LogMessage('Stopping stress test...');
+end;
+
+procedure TfrmMain.edtEchoKeyPress(Sender: TObject; var Key: Char);
+begin
+ if Key = #13 then
+ begin
+ btnEchoClick(nil);
+ Key := #0;
+ end;
+end;
+
+procedure TfrmMain.edtReverseKeyPress(Sender: TObject; var Key: Char);
+begin
+ if Key = #13 then
+ begin
+ btnReverseClick(nil);
+ Key := #0;
+ end;
+end;
+
+procedure TfrmMain.edtHashKeyPress(Sender: TObject; var Key: Char);
+begin
+ if Key = #13 then
+ begin
+ btnHashClick(nil);
+ Key := #0;
+ end;
+end;
+
+procedure TfrmMain.ClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ LogMessage('Connected to server at ' + aLine.PeerIP);
+ UpdateStatus;
+ EnableControls(True);
+end;
+
+procedure TfrmMain.ClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ LogMessage('Disconnected from server');
+ UpdateStatus;
+ EnableControls(False);
+ btnConnect.Caption := 'Connect';
+end;
+
+procedure TfrmMain.ClientReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+var
+ Response: string;
+begin
+ Response := TEncoding.UTF8.GetString(aBuf, 0, aBufCount);
+ Response := Trim(Response);
+
+ if Response <> '' then
+ begin
+ LogMessage('Response: ' + Response);
+
+ // Update stress test counter
+ if FStressTestRunning then
+ begin
+ FStressTestLock.Acquire;
+ try
+ Inc(FResponseCount);
+ finally
+ FStressTestLock.Release;
+ end;
+ end;
+ end;
+end;
+
+procedure TfrmMain.LogMessage(const aMessage: string);
+begin
+ if memoLog.Lines.Count > 1000 then
+ memoLog.Clear;
+
+ memoLog.Lines.Add(FormatDateTime('hh:nn:ss.zzz', Now) + ' - ' + aMessage);
+
+ // Auto-scroll to bottom
+ SendMessage(memoLog.Handle, WM_VSCROLL, SB_BOTTOM, 0);
+end;
+
+procedure TfrmMain.UpdateStatus;
+begin
+ if FClient.Active then
+ begin
+ lblStatus.Caption := 'Connected to ' + FClient.Host + ':' + IntToStr(FClient.Port);
+ lblStatus.Font.Color := clGreen;
+ end
+ else
+ begin
+ lblStatus.Caption := 'Disconnected';
+ lblStatus.Font.Color := clRed;
+ end;
+end;
+
+procedure TfrmMain.SendCommand(const aCommand: string);
+var
+ CommandBytes: TBytes;
+begin
+ if not FClient.Active then
+ begin
+ ShowMessage('Not connected to server');
+ Exit;
+ end;
+
+ try
+ // Only log individual commands when not stress testing to avoid UI blocking
+ if not FStressTestRunning then
+ LogMessage('Sending: ' + aCommand);
+
+ CommandBytes := TEncoding.UTF8.GetBytes(aCommand + #13#10);
+ FClient.Send(CommandBytes);
+
+ // Update stress test counter
+ if FStressTestRunning then
+ begin
+ FStressTestLock.Acquire;
+ try
+ Inc(FRequestCount);
+ finally
+ FStressTestLock.Release;
+ end;
+ end;
+
+ except
+ on E: Exception do
+ begin
+ // Only log individual errors when not stress testing
+ if not FStressTestRunning then
+ LogMessage('Error sending command: ' + E.Message);
+
+ // Update stress test error counter
+ if FStressTestRunning then
+ begin
+ FStressTestLock.Acquire;
+ try
+ Inc(FErrorCount);
+ finally
+ FStressTestLock.Release;
+ end;
+ end;
+ end;
+ end;
+end;
+
+procedure TfrmMain.UpdateStressTestProgress(aProgress: Integer; const aStatus: string);
+begin
+ TThread.Synchronize(nil, procedure
+ begin
+ progressStress.Position := aProgress;
+ lblStressStatus.Caption := aStatus;
+ end);
+end;
+
+procedure TfrmMain.StressTestWorker;
+var
+ i, j: Integer;
+ Tasks: array of ITask;
+ Commands: array[0..5] of string;
+ TotalRequests: Integer;
+ StartTime: TStopwatch;
+begin
+ // Initialize the commands array
+ Commands[0] := 'PING';
+ Commands[1] := 'ECHO StressTest';
+ Commands[2] := 'REVERSE Hello';
+ Commands[3] := 'HASH TestData';
+ Commands[4] := 'COMPUTE';
+ Commands[5] := 'TIME';
+ try
+ TotalRequests := 100; // Total requests to send
+ SetLength(Tasks, trackConcurrency.Position);
+ StartTime := TStopwatch.StartNew;
+
+ // Create concurrent tasks with shared counter approach
+ for i := 0 to trackConcurrency.Position - 1 do
+ begin
+ Tasks[i] := TTask.Create(procedure
+ var
+ LocalRequestCount: Integer;
+ begin
+ LocalRequestCount := 0;
+
+ // Keep sending until we reach total or test stops
+ while FStressTestRunning and (LocalRequestCount < TotalRequests) do
+ begin
+ // Check if we should send another request
+ FStressTestLock.Acquire;
+ try
+ if FRequestCount < TotalRequests then
+ begin
+ Inc(LocalRequestCount);
+ end
+ else
+ Break; // Total reached, exit
+ finally
+ FStressTestLock.Release;
+ end;
+
+ // Send random command directly from background thread
+ SendCommand(Commands[Random(Length(Commands))]);
+
+ // Small delay to prevent overwhelming
+ Sleep(50 + Random(100));
+ end;
+ end);
+ end;
+
+ // Start all tasks
+ for i := 0 to High(Tasks) do
+ Tasks[i].Start;
+
+ // Monitor progress
+ while FStressTestRunning do
+ begin
+ Sleep(100);
+
+ FStressTestLock.Acquire;
+ try
+ if FRequestCount > 0 then
+ begin
+ UpdateStressTestProgress(
+ Min(100, (FRequestCount * 100) div TotalRequests),
+ Format('Requests: %d, Responses: %d, Errors: %d, Time: %ds',
+ [FRequestCount, FResponseCount, FErrorCount, StartTime.ElapsedMilliseconds div 1000])
+ );
+ end;
+
+ // Check if all requests completed
+ if FRequestCount >= TotalRequests then
+ Break;
+ finally
+ FStressTestLock.Release;
+ end;
+ end;
+
+ // Wait for all tasks to complete
+ for i := 0 to High(Tasks) do
+ Tasks[i].Wait;
+
+ // Final update
+ TThread.Synchronize(nil, procedure
+ begin
+ // Restore event synchronization
+ FClient.EventsUseMainThread := True;
+
+ UpdateStressTestProgress(100,
+ Format('Completed! Requests: %d, Responses: %d, Errors: %d, Time: %ds',
+ [FRequestCount, FResponseCount, FErrorCount, StartTime.ElapsedMilliseconds div 1000]));
+
+ LogMessage('Stress test completed');
+ LogMessage(Format('Total time: %d seconds', [StartTime.ElapsedMilliseconds div 1000]));
+ LogMessage(Format('Requests per second: %.2f', [FRequestCount / (StartTime.ElapsedMilliseconds / 1000)]));
+
+ EnableControls(True);
+ btnStopStress.Enabled := False;
+ end);
+
+ except
+ on E: Exception do
+ begin
+ TThread.Synchronize(nil, procedure
+ begin
+ // Restore event synchronization
+ FClient.EventsUseMainThread := True;
+ LogMessage('Stress test error: ' + E.Message);
+ EnableControls(True);
+ btnStopStress.Enabled := False;
+ end);
+ end;
+ end;
+
+ FStressTestRunning := False;
+end;
+
+procedure TfrmMain.EnableControls(aEnabled: Boolean);
+begin
+ btnPing.Enabled := aEnabled;
+ btnEcho.Enabled := aEnabled;
+ btnReverse.Enabled := aEnabled;
+ btnHash.Enabled := aEnabled;
+ btnCompute.Enabled := aEnabled;
+ btnTime.Enabled := aEnabled;
+ btnStressTest.Enabled := aEnabled;
+ edtEcho.Enabled := aEnabled;
+ edtReverse.Enabled := aEnabled;
+ edtHash.Enabled := aEnabled;
+ trackConcurrency.Enabled := aEnabled;
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dpr b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dpr
new file mode 100644
index 0000000..aa49683
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dpr
@@ -0,0 +1,14 @@
+program ThreadedServer;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TfrmMain, frmMain);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dproj b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dproj
new file mode 100644
index 0000000..cdd351f
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dproj
@@ -0,0 +1,190 @@
+
+
+ {6901B784-E921-432D-A63A-5F77E2A991CD}
+ ThreadedServer.dpr
+ True
+ Release
+ ThreadedServer
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ ThreadedServer
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ ThreadedServer.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dproj.local b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.identcache b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.identcache
new file mode 100644
index 0000000..547e629
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.identcache differ
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.res b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.res
new file mode 100644
index 0000000..49a440c
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_Benchmark/Server/ThreadedServer.res differ
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ufrmMain.dfm b/Demos/TCP/ncSocketsThd_Benchmark/Server/ufrmMain.dfm
new file mode 100644
index 0000000..418d4dc
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server/ufrmMain.dfm
@@ -0,0 +1,328 @@
+object frmMain: TfrmMain
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'NetCom7 Threaded Server Demo'
+ ClientHeight = 600
+ ClientWidth = 800
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object Panel1: TPanel
+ Left = 0
+ Top = 0
+ Width = 800
+ Height = 89
+ Align = alTop
+ TabOrder = 0
+ object Label1: TLabel
+ Left = 16
+ Top = 16
+ Width = 24
+ Height = 13
+ Caption = 'Port:'
+ end
+ object btnStartStop: TButton
+ Left = 16
+ Top = 48
+ Width = 121
+ Height = 25
+ Caption = 'Start Server'
+ TabOrder = 0
+ OnClick = btnStartStopClick
+ end
+ object edtPort: TEdit
+ Left = 46
+ Top = 13
+ Width = 91
+ Height = 21
+ TabOrder = 1
+ Text = '8080'
+ end
+ object btnClearLog: TButton
+ Left = 168
+ Top = 48
+ Width = 75
+ Height = 25
+ Caption = 'Clear Log'
+ TabOrder = 2
+ OnClick = btnClearLogClick
+ end
+ end
+ object Panel2: TPanel
+ Left = 0
+ Top = 89
+ Width = 800
+ Height = 320
+ Align = alClient
+ TabOrder = 1
+ DesignSize = (
+ 800
+ 320)
+ object Label2: TLabel
+ Left = 16
+ Top = 8
+ Width = 52
+ Height = 13
+ Caption = 'Server Log'
+ end
+ object memoLog: TMemo
+ Left = 16
+ Top = 27
+ Width = 769
+ Height = 281
+ Anchors = [akLeft, akTop, akRight, akBottom]
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Consolas'
+ Font.Style = []
+ ParentFont = False
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ end
+ end
+ object Panel3: TPanel
+ Left = 0
+ Top = 409
+ Width = 800
+ Height = 191
+ Align = alBottom
+ TabOrder = 2
+ object Label3: TLabel
+ Left = 16
+ Top = 16
+ Width = 63
+ Height = 13
+ Caption = 'Connections:'
+ end
+ object lblConnections: TLabel
+ Left = 86
+ Top = 16
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clBlue
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object Label4: TLabel
+ Left = 16
+ Top = 40
+ Width = 85
+ Height = 13
+ Caption = 'Threads per CPU:'
+ end
+ object lblThreadsPerCPU: TLabel
+ Left = 105
+ Top = 40
+ Width = 7
+ Height = 13
+ Caption = '4'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clBlue
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object Label5: TLabel
+ Left = 16
+ Top = 64
+ Width = 66
+ Height = 13
+ Caption = 'Max Threads:'
+ end
+ object lblMaxThreads: TLabel
+ Left = 89
+ Top = 64
+ Width = 14
+ Height = 13
+ Caption = '32'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clBlue
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object Label6: TLabel
+ Left = 200
+ Top = 16
+ Width = 76
+ Height = 13
+ Caption = 'Total Requests:'
+ end
+ object lblTotalRequests: TLabel
+ Left = 283
+ Top = 16
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object Label7: TLabel
+ Left = 200
+ Top = 40
+ Width = 88
+ Height = 13
+ Caption = 'Requests/Second:'
+ end
+ object lblRequestsPerSecond: TLabel
+ Left = 288
+ Top = 40
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object Label8: TLabel
+ Left = 200
+ Top = 64
+ Width = 76
+ Height = 13
+ Caption = 'Active Threads:'
+ end
+ object lblActiveThreads: TLabel
+ Left = 283
+ Top = 64
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clMaroon
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblLastTestResults: TLabel
+ Left = 400
+ Top = 16
+ Width = 100
+ Height = 13
+ Caption = 'Last Test Results:'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clNavy
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestTotalRequests: TLabel
+ Left = 400
+ Top = 40
+ Width = 76
+ Height = 13
+ Caption = 'Total Requests:'
+ end
+ object lblTestTotalRequestsValue: TLabel
+ Left = 490
+ Top = 40
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestPeakReqSec: TLabel
+ Left = 400
+ Top = 64
+ Width = 70
+ Height = 13
+ Caption = 'Peak Req/Sec:'
+ end
+ object lblTestPeakReqSecValue: TLabel
+ Left = 490
+ Top = 64
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestDuration: TLabel
+ Left = 400
+ Top = 88
+ Width = 69
+ Height = 13
+ Caption = 'Test Duration:'
+ end
+ object lblTestDurationValue: TLabel
+ Left = 490
+ Top = 88
+ Width = 13
+ Height = 13
+ Caption = '0s'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestAvgReqSec: TLabel
+ Left = 400
+ Top = 112
+ Width = 66
+ Height = 13
+ Caption = 'Avg Req/Sec:'
+ end
+ object lblTestAvgReqSecValue: TLabel
+ Left = 490
+ Top = 112
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object btnResetStats: TButton
+ Left = 400
+ Top = 144
+ Width = 75
+ Height = 25
+ Caption = 'Reset Stats'
+ TabOrder = 0
+ OnClick = btnResetStatsClick
+ end
+ end
+ object Timer1: TTimer
+ OnTimer = Timer1Timer
+ Left = 720
+ Top = 48
+ end
+end
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server/ufrmMain.pas b/Demos/TCP/ncSocketsThd_Benchmark/Server/ufrmMain.pas
new file mode 100644
index 0000000..2adc2fd
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server/ufrmMain.pas
@@ -0,0 +1,452 @@
+unit ufrmMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
+ System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
+ Vcl.StdCtrls, Vcl.ExtCtrls, System.StrUtils, System.DateUtils,
+ System.Diagnostics, System.SyncObjs, System.Math,
+ ncSocketsThd, ncLines, ncThreads;
+
+type
+ TfrmMain = class(TForm)
+ Panel1: TPanel;
+ btnStartStop: TButton;
+ edtPort: TEdit;
+ Label1: TLabel;
+ Panel2: TPanel;
+ memoLog: TMemo;
+ Label2: TLabel;
+ Panel3: TPanel;
+ Label3: TLabel;
+ lblConnections: TLabel;
+ Label4: TLabel;
+ lblThreadsPerCPU: TLabel;
+ Label5: TLabel;
+ lblMaxThreads: TLabel;
+ Label6: TLabel;
+ lblTotalRequests: TLabel;
+ btnClearLog: TButton;
+ Label7: TLabel;
+ lblRequestsPerSecond: TLabel;
+ Timer1: TTimer;
+ Label8: TLabel;
+ lblActiveThreads: TLabel;
+ lblLastTestResults: TLabel;
+ lblTestTotalRequests: TLabel;
+ lblTestTotalRequestsValue: TLabel;
+ lblTestPeakReqSec: TLabel;
+ lblTestPeakReqSecValue: TLabel;
+ lblTestDuration: TLabel;
+ lblTestDurationValue: TLabel;
+ lblTestAvgReqSec: TLabel;
+ lblTestAvgReqSecValue: TLabel;
+ btnResetStats: TButton;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnStartStopClick(Sender: TObject);
+ procedure btnClearLogClick(Sender: TObject);
+ procedure Timer1Timer(Sender: TObject);
+ procedure btnResetStatsClick(Sender: TObject);
+ private
+ FServer: TncTCPServerThd;
+ FRequestCount: Integer;
+ FLastRequestCount: Integer;
+ FRequestCountLock: TCriticalSection;
+ FConnectionCount: Integer;
+ FConnectionCountLock: TCriticalSection;
+ FMaxRequestsPerSecond: Integer;
+ FTestStartTime: TDateTime;
+ FTestStartRequestCount: Integer;
+ FTestInProgress: Boolean;
+
+ procedure ServerConnected(Sender: TObject; aLine: TncLine);
+ procedure ServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ServerReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+ procedure LogMessage(const aMessage: string);
+ procedure ProcessDataRequest(aLine: TncLine; const aRequest: string);
+ procedure UpdateConnectionCount(aDelta: Integer);
+ procedure UpdateRequestCount;
+ procedure UpdateStatistics;
+ procedure DisplayFinalTestResults(CurrentRequestCount: Integer);
+ public
+ end;
+
+var
+ frmMain: TfrmMain;
+
+implementation
+
+{$R *.dfm}
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+ FRequestCount := 0;
+ FLastRequestCount := 0;
+ FConnectionCount := 0;
+ FMaxRequestsPerSecond := 0;
+ FTestStartTime := 0;
+ FTestStartRequestCount := 0;
+ FTestInProgress := False;
+ FRequestCountLock := TCriticalSection.Create;
+ FConnectionCountLock := TCriticalSection.Create;
+
+ // Create TncServer with optimal thread pool settings
+ FServer := TncTCPServerThd.Create(Self);
+
+ // Configure thread pool for demonstration
+ FServer.DataProcessorThreadsPerCPU := 4; // 4 threads per CPU core
+ FServer.DataProcessorThreadsGrowUpto := 32; // Maximum 32 threads
+ FServer.DataProcessorThreadPriority := ntpNormal;
+ FServer.EventsUseMainThread := False; // Use thread pool for processing - UI updates handled separately
+
+ // Configure socket properties
+ FServer.NoDelay := True;
+ FServer.KeepAlive := True;
+ FServer.ReadBufferLen := 8192;
+
+ // Set event handlers
+ FServer.OnConnected := ServerConnected;
+ FServer.OnDisconnected := ServerDisconnected;
+ FServer.OnReadData := ServerReadData;
+
+ // Initialize UI
+ edtPort.Text := '8080';
+ lblThreadsPerCPU.Caption := IntToStr(FServer.DataProcessorThreadsPerCPU);
+ lblMaxThreads.Caption := IntToStr(FServer.DataProcessorThreadsGrowUpto);
+
+ UpdateStatistics;
+
+ LogMessage('Server initialized with thread pool configuration');
+ LogMessage('Threads per CPU: ' + IntToStr(FServer.DataProcessorThreadsPerCPU));
+ LogMessage('Max threads: ' + IntToStr(FServer.DataProcessorThreadsGrowUpto));
+end;
+
+procedure TfrmMain.FormDestroy(Sender: TObject);
+begin
+ if Assigned(FServer) then
+ begin
+ FServer.Active := False;
+ FServer.Free;
+ end;
+
+ FRequestCountLock.Free;
+ FConnectionCountLock.Free;
+end;
+
+procedure TfrmMain.btnStartStopClick(Sender: TObject);
+begin
+ if FServer.Active then
+ begin
+ // Stop server
+ FServer.Active := False;
+ btnStartStop.Caption := 'Start Server';
+ LogMessage('Server stopped');
+ end
+ else
+ begin
+ // Start server
+ try
+ FServer.Port := StrToInt(edtPort.Text);
+ FServer.Active := True;
+ btnStartStop.Caption := 'Stop Server';
+ LogMessage('Server started on port ' + edtPort.Text);
+ LogMessage('Ready to accept connections...');
+ except
+ on E: Exception do
+ begin
+ LogMessage('Error starting server: ' + E.Message);
+ ShowMessage('Error starting server: ' + E.Message);
+ end;
+ end;
+ end;
+end;
+
+procedure TfrmMain.btnClearLogClick(Sender: TObject);
+begin
+ memoLog.Clear;
+end;
+
+procedure TfrmMain.Timer1Timer(Sender: TObject);
+begin
+ UpdateStatistics;
+end;
+
+procedure TfrmMain.ServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ UpdateConnectionCount(1);
+ LogMessage('Client connected: ' + aLine.PeerIP);
+end;
+
+procedure TfrmMain.ServerDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ UpdateConnectionCount(-1);
+ LogMessage('Client disconnected: ' + aLine.PeerIP);
+end;
+
+// This runs in a processing thread from the thread pool
+procedure TfrmMain.ServerReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+var
+ Request: string;
+ ThreadID: TThreadID;
+begin
+ try
+ ThreadID := GetCurrentThreadId;
+
+ // Convert received data to string
+ Request := TEncoding.UTF8.GetString(aBuf, 0, aBufCount);
+ Request := Trim(Request);
+
+ if Request <> '' then
+ begin
+ UpdateRequestCount;
+
+ // Only log occasionally to avoid UI bottleneck during stress tests
+ if (ThreadID mod 7 = 0) then // Log roughly 1 in 7 requests based on thread ID
+ begin
+ TThread.Synchronize(nil, procedure
+ begin
+ LogMessage(Format('Processing request from %s in thread %d: %s',
+ [aLine.PeerIP, ThreadID, Copy(Request, 1, 50)]));
+ end);
+ end;
+
+ // Process the request (this can be CPU-intensive)
+ ProcessDataRequest(aLine, Request);
+ end;
+
+ except
+ on E: Exception do
+ begin
+ TThread.Synchronize(nil, procedure
+ begin
+ LogMessage('Error processing request: ' + E.Message);
+ end);
+ end;
+ end;
+end;
+
+procedure TfrmMain.ProcessDataRequest(aLine: TncLine; const aRequest: string);
+var
+ Response: string;
+ ResponseBytes: TBytes;
+ ProcessingTime: Integer;
+ StartTime: TStopwatch;
+ ThreadID: TThreadID;
+ Command, Data: string;
+ Parts: TArray;
+begin
+ ThreadID := GetCurrentThreadId;
+ StartTime := TStopwatch.StartNew;
+
+ try
+ // Parse command from request
+ Parts := aRequest.Split([' '], 2);
+ Command := UpperCase(Parts[0]);
+
+ if Length(Parts) > 1 then
+ Data := Parts[1]
+ else
+ Data := '';
+
+ // Process different commands
+ case IndexText(Command, ['PING', 'ECHO', 'REVERSE', 'HASH', 'COMPUTE', 'TIME']) of
+ 0: // PING
+ begin
+ Response := 'PONG';
+ end;
+ 1: // ECHO
+ begin
+ Response := 'ECHO: ' + Data;
+ end;
+ 2: // REVERSE
+ begin
+ Response := 'REVERSED: ' + ReverseString(Data);
+ end;
+ 3: // HASH
+ begin
+ // Simulate CPU-intensive hashing
+ Sleep(100 + Random(200)); // Variable processing time
+ Response := 'HASH: ' + IntToStr(Data.GetHashCode);
+ end;
+ 4: // COMPUTE
+ begin
+ // Simulate heavy computation
+ Sleep(500 + Random(1000)); // 0.5-1.5 seconds
+ Response := 'COMPUTED: ' + IntToStr(Random(1000000));
+ end;
+ 5: // TIME
+ begin
+ Response := 'TIME: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Now);
+ end;
+ else
+ Response := 'ERROR: Unknown command. Available: PING, ECHO , REVERSE , HASH , COMPUTE, TIME';
+ end;
+
+ // Add thread and timing information
+ ProcessingTime := StartTime.ElapsedMilliseconds;
+ Response := Response + #13#10 + Format('Thread: %d, Processing time: %dms', [ThreadID, ProcessingTime]);
+
+ // Send response
+ ResponseBytes := TEncoding.UTF8.GetBytes(Response + #13#10);
+ FServer.Send(aLine, ResponseBytes);
+
+ except
+ on E: Exception do
+ begin
+ Response := 'ERROR: ' + E.Message;
+ ResponseBytes := TEncoding.UTF8.GetBytes(Response + #13#10);
+ FServer.Send(aLine, ResponseBytes);
+ end;
+ end;
+end;
+
+procedure TfrmMain.LogMessage(const aMessage: string);
+begin
+ if memoLog.Lines.Count > 1000 then
+ memoLog.Clear;
+
+ memoLog.Lines.Add(FormatDateTime('hh:nn:ss.zzz', Now) + ' - ' + aMessage);
+
+ // Auto-scroll to bottom
+ SendMessage(memoLog.Handle, WM_VSCROLL, SB_BOTTOM, 0);
+end;
+
+procedure TfrmMain.UpdateConnectionCount(aDelta: Integer);
+begin
+ FConnectionCountLock.Acquire;
+ try
+ FConnectionCount := FConnectionCount + aDelta;
+ finally
+ FConnectionCountLock.Release;
+ end;
+end;
+
+procedure TfrmMain.UpdateRequestCount;
+begin
+ FRequestCountLock.Acquire;
+ try
+ Inc(FRequestCount);
+ finally
+ FRequestCountLock.Release;
+ end;
+end;
+
+procedure TfrmMain.UpdateStatistics;
+var
+ CurrentRequests: Integer;
+ RequestsPerSecond: Integer;
+begin
+ // Update connection count
+ FConnectionCountLock.Acquire;
+ try
+ lblConnections.Caption := IntToStr(FConnectionCount);
+ finally
+ FConnectionCountLock.Release;
+ end;
+
+ // Update request statistics
+ FRequestCountLock.Acquire;
+ try
+ CurrentRequests := FRequestCount;
+ lblTotalRequests.Caption := IntToStr(CurrentRequests);
+
+ // Calculate requests per second
+ RequestsPerSecond := CurrentRequests - FLastRequestCount;
+ lblRequestsPerSecond.Caption := IntToStr(RequestsPerSecond);
+ FLastRequestCount := CurrentRequests;
+ finally
+ FRequestCountLock.Release;
+ end;
+
+ // Detect test start (first time we see incoming requests)
+ if not FTestInProgress and (RequestsPerSecond > 0) then
+ begin
+ FTestInProgress := True;
+ FTestStartTime := Now;
+ FTestStartRequestCount := CurrentRequests - RequestsPerSecond;
+ FMaxRequestsPerSecond := RequestsPerSecond;
+ LogMessage('Test started - tracking performance...');
+ end;
+
+ // Track peak performance during test
+ if FTestInProgress and (RequestsPerSecond > FMaxRequestsPerSecond) then
+ begin
+ FMaxRequestsPerSecond := RequestsPerSecond;
+ end;
+
+ // Detect test end (no requests for 2 seconds after test was active)
+ if FTestInProgress and (RequestsPerSecond = 0) then
+ begin
+ // Wait for a confirmation period (2 more timer ticks = 2 seconds)
+ if Timer1.Tag = 0 then
+ Timer1.Tag := GetTickCount;
+
+ if (GetTickCount - Cardinal(Timer1.Tag)) >= 2000 then
+ begin
+ // Test ended - calculate final results
+ FTestInProgress := False;
+ Timer1.Tag := 0;
+ DisplayFinalTestResults(CurrentRequests);
+ LogMessage('Test completed - final results calculated');
+ end;
+ end
+ else
+ begin
+ // Reset the end-test timer if we're still getting requests
+ Timer1.Tag := 0;
+ end;
+
+ // Update active threads info - show thread pool threads (not connections)
+ var ThreadPoolThreads := FServer.GetThreadPoolThreadCount;
+ var ActiveProcessingThreads := FServer.GetThreadPoolActiveThreadCount;
+ var ConnectionCount := FServer.Lines.LockList.Count;
+ FServer.Lines.UnlockList;
+
+ lblActiveThreads.Caption := Format('%d pool (%d active)', [ThreadPoolThreads, ActiveProcessingThreads]);
+end;
+
+procedure TfrmMain.DisplayFinalTestResults(CurrentRequestCount: Integer);
+var
+ TotalTestRequests: Integer;
+ TestDuration: Double;
+ AvgRequestsPerSecond: Double;
+begin
+ TotalTestRequests := CurrentRequestCount - FTestStartRequestCount;
+ TestDuration := (Now - FTestStartTime) * 24 * 60 * 60; // Convert to seconds
+
+ if TestDuration > 0 then
+ AvgRequestsPerSecond := TotalTestRequests / TestDuration
+ else
+ AvgRequestsPerSecond := 0;
+
+ // Display final test results
+ lblTestTotalRequestsValue.Caption := Format('%d', [TotalTestRequests]);
+ lblTestPeakReqSecValue.Caption := Format('%d', [FMaxRequestsPerSecond]);
+ lblTestDurationValue.Caption := Format('%.1fs', [TestDuration]);
+ lblTestAvgReqSecValue.Caption := Format('%.1f', [AvgRequestsPerSecond]);
+
+ LogMessage(Format('Final Results: %d requests, %.1fs duration, %d peak req/sec, %.1f avg req/sec',
+ [TotalTestRequests, TestDuration, FMaxRequestsPerSecond, AvgRequestsPerSecond]));
+end;
+
+procedure TfrmMain.btnResetStatsClick(Sender: TObject);
+begin
+ // Reset final test results display
+ lblTestTotalRequestsValue.Caption := '0';
+ lblTestPeakReqSecValue.Caption := '0';
+ lblTestDurationValue.Caption := '0s';
+ lblTestAvgReqSecValue.Caption := '0';
+
+ // Reset internal tracking variables
+ FMaxRequestsPerSecond := 0;
+ FTestStartTime := 0;
+ FTestStartRequestCount := 0;
+ FTestInProgress := False;
+ Timer1.Tag := 0;
+
+ LogMessage('Test statistics reset');
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dpr b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dpr
new file mode 100644
index 0000000..1d7548a
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dpr
@@ -0,0 +1,14 @@
+program TCPServerComparison;
+
+uses
+ Vcl.Forms,
+ ufrmTCPServer in 'ufrmTCPServer.pas' {frmTCPServer};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TfrmTCPServer, frmTCPServer);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dproj b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dproj
new file mode 100644
index 0000000..b23c98d
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dproj
@@ -0,0 +1,1139 @@
+
+
+ {252F2870-DA5D-4BFD-AFF0-496E121AFCC0}
+ TCPServerComparison.dpr
+ True
+ Debug
+ TCPServerComparison
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ TCPServerComparison
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ TCPServerComparison.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+
+
+ TCPServerComparison.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12
+
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dproj.local b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.identcache b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.identcache
new file mode 100644
index 0000000..11b7479
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.identcache differ
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.res b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.res
new file mode 100644
index 0000000..169fc58
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_Benchmark/Server2/TCPServerComparison.res differ
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/ufrmTCPServer.dfm b/Demos/TCP/ncSocketsThd_Benchmark/Server2/ufrmTCPServer.dfm
new file mode 100644
index 0000000..baed1f9
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server2/ufrmTCPServer.dfm
@@ -0,0 +1,274 @@
+object frmTCPServer: TfrmTCPServer
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'NetCom7 TncTCPServer Demo - Raw Socket (No Thread Pool)'
+ ClientHeight = 600
+ ClientWidth = 800
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object pnlTop: TPanel
+ Left = 0
+ Top = 0
+ Width = 800
+ Height = 89
+ Align = alTop
+ TabOrder = 0
+ object lblPort: TLabel
+ Left = 16
+ Top = 16
+ Width = 24
+ Height = 13
+ Caption = 'Port:'
+ end
+ object btnStartStop: TButton
+ Left = 16
+ Top = 48
+ Width = 121
+ Height = 25
+ Caption = 'Start Server'
+ TabOrder = 0
+ OnClick = btnStartStopClick
+ end
+ object edtPort: TEdit
+ Left = 46
+ Top = 13
+ Width = 91
+ Height = 21
+ TabOrder = 1
+ Text = '8080'
+ end
+ end
+ object memoLog: TMemo
+ Left = 0
+ Top = 89
+ Width = 800
+ Height = 320
+ Align = alClient
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Consolas'
+ Font.Style = []
+ ParentFont = False
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ end
+ object pnlStats: TPanel
+ Left = 0
+ Top = 409
+ Width = 800
+ Height = 191
+ Align = alBottom
+ TabOrder = 2
+ object lblConnections: TLabel
+ Left = 16
+ Top = 16
+ Width = 63
+ Height = 13
+ Caption = 'Connections:'
+ end
+ object lblRequests: TLabel
+ Left = 16
+ Top = 40
+ Width = 76
+ Height = 13
+ Caption = 'Total Requests:'
+ end
+ object lblRequestsPerSec: TLabel
+ Left = 16
+ Top = 64
+ Width = 88
+ Height = 13
+ Caption = 'Requests/Second:'
+ end
+ object lblThreads: TLabel
+ Left = 16
+ Top = 88
+ Width = 76
+ Height = 13
+ Caption = 'Active Threads:'
+ end
+ object lblConnectionsValue: TLabel
+ Left = 120
+ Top = 16
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clBlue
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblRequestsValue: TLabel
+ Left = 120
+ Top = 40
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblRequestsPerSecValue: TLabel
+ Left = 120
+ Top = 64
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblThreadsValue: TLabel
+ Left = 120
+ Top = 88
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clRed
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblLastTestResults: TLabel
+ Left = 400
+ Top = 16
+ Width = 100
+ Height = 13
+ Caption = 'Last Test Results:'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clNavy
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestTotalRequests: TLabel
+ Left = 400
+ Top = 40
+ Width = 76
+ Height = 13
+ Caption = 'Total Requests:'
+ end
+ object lblTestTotalRequestsValue: TLabel
+ Left = 490
+ Top = 40
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestPeakReqSec: TLabel
+ Left = 400
+ Top = 64
+ Width = 70
+ Height = 13
+ Caption = 'Peak Req/Sec:'
+ end
+ object lblTestPeakReqSecValue: TLabel
+ Left = 490
+ Top = 64
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestDuration: TLabel
+ Left = 400
+ Top = 88
+ Width = 69
+ Height = 13
+ Caption = 'Test Duration:'
+ end
+ object lblTestDurationValue: TLabel
+ Left = 490
+ Top = 88
+ Width = 13
+ Height = 13
+ Caption = '0s'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblTestAvgReqSec: TLabel
+ Left = 400
+ Top = 112
+ Width = 66
+ Height = 13
+ Caption = 'Avg Req/Sec:'
+ end
+ object lblTestAvgReqSecValue: TLabel
+ Left = 490
+ Top = 112
+ Width = 7
+ Height = 13
+ Caption = '0'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clGreen
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object lblLog: TLabel
+ Left = 16
+ Top = 152
+ Width = 161
+ Height = 13
+ Caption = 'Raw Socket - No Thread Pool'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clMaroon
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ end
+ object btnResetStats: TButton
+ Left = 400
+ Top = 144
+ Width = 75
+ Height = 25
+ Caption = 'Reset Stats'
+ TabOrder = 0
+ OnClick = btnResetStatsClick
+ end
+ end
+ object tmrStats: TTimer
+ OnTimer = tmrStatsTimer
+ Left = 720
+ Top = 48
+ end
+end
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/Server2/ufrmTCPServer.pas b/Demos/TCP/ncSocketsThd_Benchmark/Server2/ufrmTCPServer.pas
new file mode 100644
index 0000000..eefbf7d
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/Server2/ufrmTCPServer.pas
@@ -0,0 +1,352 @@
+unit ufrmTCPServer;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, System.Math,
+ System.Hash, System.DateUtils, System.Diagnostics, System.Types, System.SyncObjs, System.StrUtils,
+ ncSockets, ncLines;
+
+type
+ TfrmTCPServer = class(TForm)
+ pnlTop: TPanel;
+ btnStartStop: TButton;
+ edtPort: TEdit;
+ lblPort: TLabel;
+ memoLog: TMemo;
+ lblLog: TLabel;
+ pnlStats: TPanel;
+ lblConnections: TLabel;
+ lblRequests: TLabel;
+ lblRequestsPerSec: TLabel;
+ lblThreads: TLabel;
+ lblConnectionsValue: TLabel;
+ lblRequestsValue: TLabel;
+ lblRequestsPerSecValue: TLabel;
+ lblThreadsValue: TLabel;
+ lblLastTestResults: TLabel;
+ lblTestTotalRequests: TLabel;
+ lblTestTotalRequestsValue: TLabel;
+ lblTestPeakReqSec: TLabel;
+ lblTestPeakReqSecValue: TLabel;
+ lblTestDuration: TLabel;
+ lblTestDurationValue: TLabel;
+ lblTestAvgReqSec: TLabel;
+ lblTestAvgReqSecValue: TLabel;
+ btnResetStats: TButton;
+ tmrStats: TTimer;
+ procedure btnStartStopClick(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure tmrStatsTimer(Sender: TObject);
+ procedure btnResetStatsClick(Sender: TObject);
+ private
+ FServer: TncTCPServer;
+ FStartTime: TDateTime;
+ FRequestCount: Integer;
+ FLastRequestCount: Integer;
+ FMaxRequestsPerSecond: Integer;
+ FRequestCountLock: TCriticalSection;
+ FTestStartTime: TDateTime;
+ FTestStartRequestCount: Integer;
+ FTestInProgress: Boolean;
+
+ procedure ServerConnected(Sender: TObject; aLine: TncLine);
+ procedure ServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure ServerReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+ procedure ProcessCommandDirectly(aLine: TncLine; const aCommand: string);
+ procedure LogMessage(const aMessage: string);
+ procedure IncrementRequestCount;
+ procedure DisplayFinalTestResults(CurrentRequestCount: Integer);
+ public
+ { Public declarations }
+ end;
+
+var
+ frmTCPServer: TfrmTCPServer;
+
+implementation
+
+{$R *.dfm}
+
+procedure TfrmTCPServer.FormCreate(Sender: TObject);
+begin
+ FRequestCountLock := TCriticalSection.Create;
+ FRequestCount := 0;
+ FLastRequestCount := 0;
+ FMaxRequestsPerSecond := 0;
+ FStartTime := Now;
+ FTestStartTime := 0;
+ FTestStartRequestCount := 0;
+ FTestInProgress := False;
+
+ // Create TncTCPServer (raw socket without any thread pool)
+ FServer := TncTCPServer.Create(Self);
+ FServer.Port := 8080;
+ FServer.EventsUseMainThread := False; // Process in reader thread - no thread pool
+ FServer.OnConnected := ServerConnected;
+ FServer.OnDisconnected := ServerDisconnected;
+ FServer.OnReadData := ServerReadData;
+
+ edtPort.Text := '8080';
+
+ LogMessage('TncTCPServer Demo - RAW Socket (No Thread Pool)');
+ LogMessage('All processing happens directly in reader thread');
+ LogMessage('Ready to start server...');
+end;
+
+procedure TfrmTCPServer.FormDestroy(Sender: TObject);
+begin
+ if Assigned(FServer) then
+ FServer.Active := False;
+
+ FRequestCountLock.Free;
+end;
+
+procedure TfrmTCPServer.btnStartStopClick(Sender: TObject);
+begin
+ if not FServer.Active then
+ begin
+ // Start server
+ FServer.Port := StrToIntDef(edtPort.Text, 8080);
+ FServer.Active := True;
+ FStartTime := Now;
+ FRequestCount := 0;
+ FLastRequestCount := 0;
+
+ btnStartStop.Caption := 'Stop Server';
+ edtPort.Enabled := False;
+ tmrStats.Enabled := True;
+
+ LogMessage(Format('Server started on port %d', [FServer.Port]));
+ LogMessage('Using TncTCPServer - RAW socket processing');
+ end
+ else
+ begin
+ // Stop server
+ FServer.Active := False;
+
+ btnStartStop.Caption := 'Start Server';
+ edtPort.Enabled := True;
+ tmrStats.Enabled := False;
+
+ LogMessage('Server stopped');
+ end;
+end;
+
+procedure TfrmTCPServer.ServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ LogMessage(Format('Client connected: %s', [aLine.PeerIP]));
+end;
+
+procedure TfrmTCPServer.ServerDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ LogMessage(Format('Client disconnected: %s', [aLine.PeerIP]));
+end;
+
+procedure TfrmTCPServer.ServerReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+var
+ Command: string;
+begin
+ // This runs directly in the reader thread - NO thread pool involved
+ try
+ Command := TEncoding.UTF8.GetString(aBuf, 0, aBufCount).Trim;
+
+ // Process command directly in reader thread (this is the RAW approach)
+ ProcessCommandDirectly(aLine, Command);
+ except
+ on E: Exception do
+ LogMessage(Format('Error processing data: %s', [E.Message]));
+ end;
+end;
+
+procedure TfrmTCPServer.ProcessCommandDirectly(aLine: TncLine; const aCommand: string);
+var
+ Response: string;
+ ThreadID: Cardinal;
+begin
+ // This runs directly in reader thread - no thread pool queuing
+ ThreadID := GetCurrentThreadId;
+ IncrementRequestCount;
+
+ try
+ if aCommand = 'PING' then
+ begin
+ Response := 'PONG';
+ end
+ else if aCommand = 'TIME' then
+ begin
+ Response := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now);
+ end
+ else if StartsText('ECHO:', aCommand) then
+ begin
+ Response := Copy(aCommand, 6, Length(aCommand));
+ end
+ else if StartsText('REVERSE:', aCommand) then
+ begin
+ Response := ReverseString(Copy(aCommand, 9, Length(aCommand)));
+ end
+ else if StartsText('HASH:', aCommand) then
+ begin
+ Response := THashMD5.GetHashString(Copy(aCommand, 6, Length(aCommand)));
+ end
+ else if aCommand = 'COMPUTE' then
+ begin
+ // Simulate CPU-intensive work
+ Sleep(Random(1000) + 500); // 0.5-1.5 seconds
+ Response := Format('COMPUTED[%d]', [ThreadID]);
+ end
+ else
+ begin
+ Response := 'UNKNOWN_COMMAND';
+ end;
+
+ // Send response
+ Response := Response + Format('[T:%d]', [ThreadID]);
+ FServer.Send(aLine, TEncoding.UTF8.GetBytes(Response));
+
+ // Log approximately 1 in 7 requests to avoid spam
+ if (FRequestCount mod 7) = 0 then
+ LogMessage(Format('Processed: %s -> %s', [aCommand, Response]));
+ except
+ on E: Exception do
+ begin
+ LogMessage(Format('Error processing command "%s": %s', [aCommand, E.Message]));
+ try
+ FServer.Send(aLine, TEncoding.UTF8.GetBytes('ERROR: ' + E.Message));
+ except
+ // Ignore send errors
+ end;
+ end;
+ end;
+end;
+
+procedure TfrmTCPServer.LogMessage(const aMessage: string);
+begin
+ if memoLog.Lines.Count > 1000 then
+ memoLog.Lines.Delete(0);
+ memoLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss', Now), aMessage]));
+end;
+
+procedure TfrmTCPServer.IncrementRequestCount;
+begin
+ FRequestCountLock.Acquire;
+ try
+ Inc(FRequestCount);
+ finally
+ FRequestCountLock.Release;
+ end;
+end;
+
+procedure TfrmTCPServer.tmrStatsTimer(Sender: TObject);
+var
+ CurrentRequestCount: Integer;
+ RequestsPerSecond: Integer;
+begin
+ // Get current request count
+ FRequestCountLock.Acquire;
+ try
+ CurrentRequestCount := FRequestCount;
+ finally
+ FRequestCountLock.Release;
+ end;
+
+ // Calculate requests per second (same method as thread pool demo)
+ RequestsPerSecond := CurrentRequestCount - FLastRequestCount;
+ FLastRequestCount := CurrentRequestCount;
+
+ // Detect test start (first time we see incoming requests)
+ if not FTestInProgress and (RequestsPerSecond > 0) then
+ begin
+ FTestInProgress := True;
+ FTestStartTime := Now;
+ FTestStartRequestCount := CurrentRequestCount - RequestsPerSecond;
+ FMaxRequestsPerSecond := RequestsPerSecond;
+ LogMessage('Test started - tracking performance...');
+ end;
+
+ // Track peak performance during test
+ if FTestInProgress and (RequestsPerSecond > FMaxRequestsPerSecond) then
+ begin
+ FMaxRequestsPerSecond := RequestsPerSecond;
+ end;
+
+ // Detect test end (no requests for 2 seconds after test was active)
+ if FTestInProgress and (RequestsPerSecond = 0) then
+ begin
+ // Wait for a confirmation period (2 more timer ticks = 2 seconds)
+ if tmrStats.Tag = 0 then
+ tmrStats.Tag := GetTickCount;
+
+ if (GetTickCount - Cardinal(tmrStats.Tag)) >= 2000 then
+ begin
+ // Test ended - calculate final results
+ FTestInProgress := False;
+ tmrStats.Tag := 0;
+ DisplayFinalTestResults(CurrentRequestCount);
+ LogMessage('Test completed - final results calculated');
+ end;
+ end
+ else
+ begin
+ // Reset the end-test timer if we're still getting requests
+ tmrStats.Tag := 0;
+ end;
+
+ // Get connection count safely with thread-safe locking
+ var SocketList := FServer.Lines.LockList;
+ try
+ lblConnectionsValue.Caption := Format('%d', [SocketList.Count]);
+ finally
+ FServer.Lines.UnlockList;
+ end;
+
+ lblRequestsValue.Caption := Format('%d', [CurrentRequestCount]);
+ lblRequestsPerSecValue.Caption := Format('%d', [RequestsPerSecond]);
+ lblThreadsValue.Caption := '1 (Reader Only)'; // No thread pool - just reader thread
+end;
+
+procedure TfrmTCPServer.DisplayFinalTestResults(CurrentRequestCount: Integer);
+var
+ TotalTestRequests: Integer;
+ TestDuration: Double;
+ AvgRequestsPerSecond: Double;
+begin
+ TotalTestRequests := CurrentRequestCount - FTestStartRequestCount;
+ TestDuration := (Now - FTestStartTime) * 24 * 60 * 60; // Convert to seconds
+
+ if TestDuration > 0 then
+ AvgRequestsPerSecond := TotalTestRequests / TestDuration
+ else
+ AvgRequestsPerSecond := 0;
+
+ // Display final test results
+ lblTestTotalRequestsValue.Caption := Format('%d', [TotalTestRequests]);
+ lblTestPeakReqSecValue.Caption := Format('%d', [FMaxRequestsPerSecond]);
+ lblTestDurationValue.Caption := Format('%.1fs', [TestDuration]);
+ lblTestAvgReqSecValue.Caption := Format('%.1f', [AvgRequestsPerSecond]);
+
+ LogMessage(Format('Final Results: %d requests, %.1fs duration, %d peak req/sec, %.1f avg req/sec',
+ [TotalTestRequests, TestDuration, FMaxRequestsPerSecond, AvgRequestsPerSecond]));
+end;
+
+procedure TfrmTCPServer.btnResetStatsClick(Sender: TObject);
+begin
+ // Reset final test results display
+ lblTestTotalRequestsValue.Caption := '0';
+ lblTestPeakReqSecValue.Caption := '0';
+ lblTestDurationValue.Caption := '0s';
+ lblTestAvgReqSecValue.Caption := '0';
+
+ // Reset internal tracking variables
+ FMaxRequestsPerSecond := 0;
+ FTestStartTime := 0;
+ FTestStartRequestCount := 0;
+ FTestInProgress := False;
+ tmrStats.Tag := 0;
+
+ LogMessage('Test statistics reset');
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/TCP/ncSocketsThd_Benchmark/ncSocketsThd_Benchmark.groupproj b/Demos/TCP/ncSocketsThd_Benchmark/ncSocketsThd_Benchmark.groupproj
new file mode 100644
index 0000000..24ab1be
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_Benchmark/ncSocketsThd_Benchmark.groupproj
@@ -0,0 +1,60 @@
+
+
+ {344BDD54-D641-46CD-A8CE-D73D6EB92681}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/Client.dpr b/Demos/TCP/ncSocketsThd_TLS/Client/Client.dpr
new file mode 100644
index 0000000..aa89c08
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Client/Client.dpr
@@ -0,0 +1,17 @@
+program Client;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/Client.dproj b/Demos/TCP/ncSocketsThd_TLS/Client/Client.dproj
new file mode 100644
index 0000000..e682265
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Client/Client.dproj
@@ -0,0 +1,236 @@
+
+
+ {A7946007-4A7F-492A-BC3D-79264B590A5A}
+ Client.dpr
+ True
+ Release
+ Client
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ Client
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Client.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/Client.dproj.local b/Demos/TCP/ncSocketsThd_TLS/Client/Client.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Client/Client.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/Client.identcache b/Demos/TCP/ncSocketsThd_TLS/Client/Client.identcache
new file mode 100644
index 0000000..6de9c7b
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_TLS/Client/Client.identcache differ
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/Client.res b/Demos/TCP/ncSocketsThd_TLS/Client/Client.res
new file mode 100644
index 0000000..cb6ea46
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_TLS/Client/Client.res differ
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/ufrmMain.dfm b/Demos/TCP/ncSocketsThd_TLS/Client/ufrmMain.dfm
new file mode 100644
index 0000000..88de4d4
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Client/ufrmMain.dfm
@@ -0,0 +1,172 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ ActiveControl = edtDataToSend
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'TCPClient'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 169
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start TCP Client'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pnlAddress: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtHost: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 281
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ TextHint = 'Enter host address'
+ OnChange = edtHostChange
+ end
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 291
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 211
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendData: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send'
+ Default = True
+ TabOrder = 0
+ OnClick = btnSendDataClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtDataToSend: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 407
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'This is some text data'
+ TextHint = 'Enter data to send here'
+ OnEnter = edtDataToSendEnter
+ OnExit = edtDataToSendExit
+ end
+ end
+ end
+ object ClientSocket: TncTCPClientThd
+ OnConnected = TCPClientConnected
+ OnDisconnected = TCPClientDisconnected
+ OnReadData = TCPClientReadData
+ Left = 160
+ Top = 88
+ end
+end
diff --git a/Demos/TCP/ncSocketsThd_TLS/Client/ufrmMain.pas b/Demos/TCP/ncSocketsThd_TLS/Client/ufrmMain.pas
new file mode 100644
index 0000000..545cc2e
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Client/ufrmMain.pas
@@ -0,0 +1,247 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin,
+ System.Diagnostics, ncLines, ncSockets, ncSocketsThd;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pnlAddress: TPanel;
+ edtHost: TEdit;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendData: TButton;
+ Panel2: TPanel;
+ edtDataToSend: TEdit;
+ ClientSocket: TncTCPClientThd;
+ procedure btnActivateClick(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure TCPClientConnected(Sender: TObject; aLine: TncLine);
+ procedure TCPClientDisconnected(Sender: TObject; aLine: TncLine);
+ procedure TCPClientReconnected(Sender: TObject; aLine: TncLine);
+ procedure edtHostChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnSendDataClick(Sender: TObject);
+ procedure edtDataToSendEnter(Sender: TObject);
+ procedure edtDataToSendExit(Sender: TObject);
+ procedure TCPClientReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure FormCreate(Sender: TObject);
+ private
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ // Configure TLS settings for the client
+ ClientSocket.UseTLS := True; // Enable TLS encryption
+ ClientSocket.TlsProvider := tpSChannel; // Use Windows SChannel (Windows built-in TLS)
+ ClientSocket.IgnoreCertificateErrors := True; // For demo purposes with self-signed certificates
+
+ // Set initial button caption
+ btnActivate.Caption := 'Start TLS Client';
+
+ Log('TLS Client configured with SChannel provider');
+ Log('Note: Certificate errors are ignored for demo purposes');
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ ClientSocket.Active := False;
+ Log('TLS Client shutdown complete');
+end;
+
+// *****************************************************************************
+// Start/Stop Main CLient
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if ClientSocket.Active then
+ begin
+ // Deactivate the TCP client
+ ClientSocket.Active := False;
+ btnActivate.Caption := 'Start TLS Client';
+ Log('TLS Client Deactivated');
+ end
+ else
+ begin
+ // Check if the host field is blank
+ if Trim(edtHost.Text) = '' then
+ begin
+ Log('Host field cannot be blank.');
+ Exit; // Exit the procedure if the host field is blank
+ end;
+
+ try
+ // Set the host from the text field
+ ClientSocket.Host := edtHost.Text;
+
+ // Activate the TCP client
+ ClientSocket.Port := edtPort.Value;
+ ClientSocket.Active := True;
+ btnActivate.Caption := 'Stop TLS Client';
+ Log('TLS Client Activated - attempting secure connection...');
+ except
+ on E: Exception do
+ Log('Failed to activate TLS Client: ' + E.Message);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change host (server)
+// *****************************************************************************
+procedure TForm1.edtHostChange(Sender: TObject);
+begin
+ try
+ ClientSocket.Host := edtHost.Text;
+ except
+ edtHost.OnChange := nil;
+ try
+ edtHost.Text := ClientSocket.Host;
+ finally
+ edtHost.OnChange := edtHostChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ ClientSocket.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := ClientSocket.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Data to send
+// *****************************************************************************
+procedure TForm1.edtDataToSendEnter(Sender: TObject);
+begin
+ btnSendData.Default := True;
+end;
+
+procedure TForm1.edtDataToSendExit(Sender: TObject);
+begin
+ btnSendData.Default := False;
+end;
+
+procedure TForm1.btnSendDataClick(Sender: TObject);
+begin
+ // Check if the data field is blank
+ if Trim(edtDataToSend.Text) = '' then
+ begin
+ Log('Cannot send - Data field cannot be blank.');
+ Exit; // Exit the procedure if the data field is blank
+ end;
+
+ try
+ // Send the data
+ ClientSocket.Send(edtDataToSend.Text);
+ Log('Data sent via TLS: ' + edtDataToSend.Text);
+ except
+ on E: Exception do
+ Log('Failed to send data via TLS: ' + E.Message);
+ end;
+end;
+
+// *****************************************************************************
+// TCPClientConnected
+// *****************************************************************************
+procedure TForm1.TCPClientConnected(Sender: TObject; aLine: TncLine);
+begin
+ if ClientSocket.UseTLS then
+ Log('Connected with TLS encryption (SChannel)')
+ else
+ Log('Connected without encryption');
+ btnActivate.Caption := 'Deactivate';
+end;
+
+// *****************************************************************************
+// TCPClientDisconnected
+// *****************************************************************************
+procedure TForm1.TCPClientDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('TLS Connection Disconnected');
+ btnActivate.Caption := 'Start TLS Client';
+end;
+
+// *****************************************************************************
+// TCPClientReconnected
+// *****************************************************************************
+procedure TForm1.TCPClientReconnected(Sender: TObject; aLine: TncLine);
+begin
+ Log('TLS Connection Reconnected');
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.TCPClientReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ BytesReceived: TBytes;
+begin
+ BytesReceived := Copy(aBuf, 0, aBufCount);
+
+ Log('Received via TLS: ' + StringOf(BytesReceived));
+
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/Server.dpr b/Demos/TCP/ncSocketsThd_TLS/Server/Server.dpr
new file mode 100644
index 0000000..63d6f38
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Server/Server.dpr
@@ -0,0 +1,17 @@
+program Server;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/Server.dproj b/Demos/TCP/ncSocketsThd_TLS/Server/Server.dproj
new file mode 100644
index 0000000..65e5b01
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Server/Server.dproj
@@ -0,0 +1,236 @@
+
+
+ {0B2EB3CC-F54E-41A8-A712-8771BC0FC4AD}
+ Server.dpr
+ True
+ Release
+ Server
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ Server
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+ true
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Server.dpr
+
+
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/Server.dproj.local b/Demos/TCP/ncSocketsThd_TLS/Server/Server.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Server/Server.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/Server.identcache b/Demos/TCP/ncSocketsThd_TLS/Server/Server.identcache
new file mode 100644
index 0000000..090a4c4
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_TLS/Server/Server.identcache differ
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/Server.res b/Demos/TCP/ncSocketsThd_TLS/Server/Server.res
new file mode 100644
index 0000000..9f173a9
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_TLS/Server/Server.res differ
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/server.key b/Demos/TCP/ncSocketsThd_TLS/Server/server.key
new file mode 100644
index 0000000..be9053f
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Server/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCZF6wX9HCEqm0K
+yByBjMqIzbN9dpOc9kX5tJSMF2TLuSFxjQqL8qiTJsY5lFevpZ6OvA7kI+X5u5AV
+Fu15Epl9GSdSuYxVYj33NGWTyLUEb4ctwF5ado86D+ezQP8Dnlg5bhPPimhBQTpv
+/Fl/FptrcyzzYEBWCyeSbzy8hPQLEomJc8A5OX7l+wm5dhFM6tWTHRR0gV1ZXIIk
+1nQgXdF+HcUeamHY2+xpF0wLdCSTTj/em21blPmEE7JtmxYuAXFqo3H9YPlTNwJv
+6Ztsl59XRJFOFiWm8PINB23oDwDI+yTqXbzSRIX0BpZs3B/TSSneVjKOFZVxYdnM
+lr1UMeefAgMBAAECggEANbCfoicP7vb2FvnnRWfi/+dkM3QKgNm94Lz7+8WYi/n5
+SKF2OW54wGKw0jC8L9WdreE2N7x/Qv4ModjQn81uFvljWRfJp4g0wyWVGichlNSo
+S9tTO9aolGxPjgYVaWd2+W0pdXfM6FW/8NZHbNK43w4djZ0L8yEmV6y7WEIodFkY
+8jDmU3OBjdJ0/bdh5zQe/g+IY2RF6+JIYUM4qsxWiWWvtLXIL5npVo0oMOAlNI+/
+iR6i3fXrvR3HvHBK9n/aLeXg4Qei2buNVSbVhM7zOjf1ziDypb7/VGJLf/Kkv8wB
+qrHTNa5d8N6JsmDNRNhtw01TmezHFMrGmEDrMQBXwQKBgQDPOwqPBUAD4/1rAp9/
+QvZQAiU443E+20I9eQlewCNc+/vbNHF9N8lqNm03LR0o/JIHCbU+w+POFXqyvoRG
+3Zj3j3lfpR3kO8ED3qy2o3LRi3/Rdu10XyAC6DCTc5HDtY26SGiM4LMSiYJKcxyT
+AA0BPi7RuaEEdAByFnTfUwbFzQKBgQC9Hvx6T2YLWAWbrsUcKwkJPWdYjI5HH3hn
+vTnFSsmLKpV4olwDT4R2yYlk0Wpt29Nu0ePSI5QxAwfKuwdmt701LkyRsErhZS29
+gzOvo2cCRB1R59Xnpj/nLQTVQw5tnHaT/fb+I6C8lIZRT8vZv9Xs+PUijbONf0aL
+8ZIw2ew3GwKBgQCEY2efbu8yjRh8oLRcjN7mxjgZW9QhH9n1g7mkuoLdCG4h4CMQ
+p+8Y16R2N3AFmzV/IYiUjHigU8CLKINA8piirxoPLGEoSbRJUJxuIYVcsQ37N0sD
+qTG+Ka++w3o/2WCtvUxtk69TDF4cSeXbU5D7Vkp62WgwfBs8x3PqqBQPkQKBgEM/
+qXe0lAykmBnr45tIkkX+16jdEhqoTiBVYR2OomwiEFR9J0rmE6xJrdlzveyipmRZ
+rjEjBacH9NVZ/B/CZj1q4T9M+NN9Lu6coNxrtk1P+z0MuztMGp0RnQ5YceD4KhIl
+1JY6BQYJqllvjoU3edJyFHjc+mPuRh+tHtbQJvbRAoGAR1T9fGCYn+uDwBq2B9Jt
+wMMXDD6homo+OiqEALAjUt2dOxCDH84IhGnSYP27M/pAwsMI416oskPXXEPV4nB+
+GNxbI9eKnAwiWkktbY610j6pSmHu1T0Z1GBm5HnXYrtFUHi9k+1LU/iuj2mouNus
+XpqwE8eeQQeaqJP7BmuwJXk=
+-----END PRIVATE KEY-----
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/server.pfx b/Demos/TCP/ncSocketsThd_TLS/Server/server.pfx
new file mode 100644
index 0000000..0b1ad11
Binary files /dev/null and b/Demos/TCP/ncSocketsThd_TLS/Server/server.pfx differ
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/ufrmMain.dfm b/Demos/TCP/ncSocketsThd_TLS/Server/ufrmMain.dfm
new file mode 100644
index 0000000..730387d
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Server/ufrmMain.dfm
@@ -0,0 +1,122 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'TCPServer'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 182
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Activate'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pblPort: TPanel
+ AlignWithMargins = True
+ Left = 115
+ Top = 3
+ Width = 412
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ object btnShutdownAllClients: TButton
+ AlignWithMargins = True
+ Left = 256
+ Top = 5
+ Width = 151
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ Caption = 'Shutdown all clients'
+ TabOrder = 1
+ OnClick = btnShutdownAllClientsClick
+ end
+ end
+ end
+ object StatusBar1: TStatusBar
+ Left = 0
+ Top = 224
+ Width = 527
+ Height = 19
+ Panels = <
+ item
+ Text = 'Connections: 0'
+ Width = 150
+ end>
+ end
+ object ServerSocket: TncTCPServerThd
+ OnConnected = TCPServerConnected
+ OnDisconnected = TCPServerDisconnected
+ OnReadData = TCPServerReadData
+ Left = 216
+ Top = 80
+ end
+end
diff --git a/Demos/TCP/ncSocketsThd_TLS/Server/ufrmMain.pas b/Demos/TCP/ncSocketsThd_TLS/Server/ufrmMain.pas
new file mode 100644
index 0000000..0e66f84
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/Server/ufrmMain.pas
@@ -0,0 +1,294 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.ComCtrls,
+ System.Diagnostics, ncLines, ncSocketList, ncSockets, ncSocketsThd;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pblPort: TPanel;
+ edtPort: TSpinEdit;
+ btnShutdownAllClients: TButton;
+ StatusBar1: TStatusBar;
+ ServerSocket: TncTCPServerThd;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure TCPServerConnected(Sender: TObject; aLine: TncLine);
+ procedure TCPServerDisconnected(Sender: TObject; aLine: TncLine);
+ procedure btnActivateClick(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnShutdownAllClientsClick(Sender: TObject);
+ procedure TCPServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ private
+ FConnectionCount: Integer;
+ procedure UpdateConnectionCount;
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+function FileSize(const AFilename: string): Int64;
+var
+ FileStream: TFileStream;
+begin
+ Result := 0;
+ if FileExists(AFilename) then
+ try
+ FileStream := TFileStream.Create(AFilename, fmOpenRead or fmShareDenyNone);
+ try
+ Result := FileStream.Size;
+ finally
+ FileStream.Free;
+ end;
+ except
+ Result := 0;
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+var
+ CertPath: string;
+begin
+ FConnectionCount := 0;
+ UpdateConnectionCount;
+
+ // Configure TLS settings for the server
+ ServerSocket.UseTLS := True; // Enable TLS encryption
+ ServerSocket.TlsProvider := tpSChannel; // Use Windows SChannel (Windows built-in TLS)
+
+ // Verify certificate file exists
+ CertPath := ExtractFilePath(Application.ExeName) + 'server.pfx';
+ if FileExists(CertPath) then
+ begin
+ ServerSocket.CertificateFile := CertPath; // Certificate file path
+ ServerSocket.PrivateKeyPassword := 'test'; // Certificate password
+ ServerSocket.IgnoreCertificateErrors := True; // For demo purposes
+
+ Log('Certificate file found: ' + CertPath);
+ Log('Certificate file size: ' + IntToStr(FileSize(CertPath)) + ' bytes');
+ end
+ else
+ begin
+ Log('ERROR: Certificate file not found: ' + CertPath);
+ Log('Please ensure server.pfx is in the same directory as the executable');
+ // Still configure TLS but it will fail
+ ServerSocket.CertificateFile := CertPath;
+ ServerSocket.PrivateKeyPassword := 'test';
+ ServerSocket.IgnoreCertificateErrors := False;
+ end;
+
+ // Set initial button caption
+ btnActivate.Caption := 'Start TLS Server';
+
+ Log('TLS Server configured with SChannel provider');
+ Log('Note: Certificate errors are ignored for demo purposes');
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ ServerSocket.Active := False;
+ Log('TLS Server shutdown complete');
+end;
+
+// *****************************************************************************
+// Start/Stop Main Server
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if ServerSocket.Active then
+ begin
+ // Deactivate the TCP Server
+ ServerSocket.Active := False;
+ btnActivate.Caption := 'Start TLS Server';
+ Log('TLS Server Deactivated');
+ end
+ else
+ begin
+ try
+ // Validate TLS configuration before starting
+ if not FileExists(ServerSocket.CertificateFile) then
+ begin
+ Log('ERROR: Certificate file not found: ' + ServerSocket.CertificateFile);
+ Log('Cannot start TLS server without valid certificate');
+ Exit;
+ end;
+
+ Log('Starting TLS server with configuration:');
+ Log(' UseTLS: ' + BoolToStr(ServerSocket.UseTLS, True));
+ Log(' TlsProvider: ' + IntToStr(Ord(ServerSocket.TlsProvider)));
+ Log(' Certificate: ' + ServerSocket.CertificateFile);
+ Log(' IgnoreCertErrors: ' + BoolToStr(ServerSocket.IgnoreCertificateErrors, True));
+
+ // Activate the TCP Server
+ ServerSocket.Port := edtPort.Value;
+ ServerSocket.Active := True;
+ btnActivate.Caption := 'Stop TLS Server';
+ Log('TLS Server Activated at port: ' + IntToStr(ServerSocket.Port));
+ Log('Server ready to accept TLS connections');
+
+ except
+ on E: Exception do
+ begin
+ Log('Failed to activate TLS Server: ' + E.Message);
+ Log('Exception class: ' + E.ClassName);
+ end;
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ ServerSocket.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := ServerSocket.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Shutdown all Clients
+// *****************************************************************************
+procedure TForm1.btnShutdownAllClientsClick(Sender: TObject);
+var
+ SocketList: TSocketList;
+ i: Integer;
+begin
+ SocketList := ServerSocket.Lines.LockList;
+ try
+ Log('Shutting down all TLS clients...');
+ for i := 0 to SocketList.Count - 1 do
+ ServerSocket.ShutDownLine(SocketList.Lines[i]);
+ Log('All TLS clients shutdown requested');
+ finally
+ ServerSocket.Lines.UnlockList;
+ end;
+end;
+
+procedure TForm1.UpdateConnectionCount;
+begin
+ StatusBar1.Panels[0].Text := 'TLS Connections: ' + IntToStr(FConnectionCount);
+end;
+
+// *****************************************************************************
+// TCPServerConnected
+// *****************************************************************************
+procedure TForm1.TCPServerConnected(Sender: TObject; aLine: TncLine);
+begin
+ Inc(FConnectionCount);
+ UpdateConnectionCount;
+
+ Log('TLS Client Connected: ' + aLine.PeerIP + ' (Handle: ' + IntToStr(aLine.Handle) + ')');
+ Log('Starting TLS handshake...');
+
+ try
+ // Send welcome message
+ ServerSocket.Send(aLine, BytesOf('Hello mr. ' + IntToStr(aLine.Handle) + ' - TLS connection established'));
+ Log('Welcome message sent to: ' + aLine.PeerIP);
+ Log('TLS handshake completed successfully');
+ except
+ on E: Exception do
+ begin
+ Log('ERROR during TLS handshake with ' + aLine.PeerIP + ': ' + E.Message);
+ Log('Exception class: ' + E.ClassName);
+ // Don't re-raise - let the connection continue to see what happens
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// TCPServerDisconnected
+// *****************************************************************************
+procedure TForm1.TCPServerDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ Dec(FConnectionCount);
+ UpdateConnectionCount;
+
+ Log('TLS Client Disconnected: ' + aLine.PeerIP + ' (Handle: ' + IntToStr(aLine.Handle) + ')');
+ Log('Connection duration: Client was connected');
+
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.TCPServerReadData(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ BytesReceived: TBytes;
+ ReceivedText: string;
+begin
+ try
+ BytesReceived := Copy(aBuf, 0, aBufCount);
+
+ // Convert bytes to string using proper UTF-8 decoding
+ ReceivedText := TEncoding.UTF8.GetString(BytesReceived);
+
+ Log('Received via TLS: "' + ReceivedText + '" from: ' + aLine.PeerIP + ' (Handle: ' + IntToStr(aLine.Handle) + ')');
+
+ // Send back the buffer received
+ ServerSocket.Send(aLine, BytesReceived);
+
+ Log('Data sent via TLS: ' + ReceivedText + ' to: ' + aLine.PeerIP);
+ except
+ on E: Exception do
+ begin
+ Log('ERROR in TLS data handling with ' + aLine.PeerIP + ': ' + E.Message);
+ Log('Exception class: ' + E.ClassName);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/TCP/ncSocketsThd_TLS/SimpleThreadedSockets_TLS.groupproj b/Demos/TCP/ncSocketsThd_TLS/SimpleThreadedSockets_TLS.groupproj
new file mode 100644
index 0000000..3122a45
--- /dev/null
+++ b/Demos/TCP/ncSocketsThd_TLS/SimpleThreadedSockets_TLS.groupproj
@@ -0,0 +1,48 @@
+
+
+ {A9A55D39-6A58-48E9-AA5F-4DED5B38E8A8}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/UDP/ncUDPSockets/Client/Client.dpr b/Demos/UDP/ncUDPSockets/Client/Client.dpr
new file mode 100644
index 0000000..aa89c08
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Client/Client.dpr
@@ -0,0 +1,17 @@
+program Client;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
diff --git a/Demos/UDP/ncUDPSockets/Client/Client.dproj b/Demos/UDP/ncUDPSockets/Client/Client.dproj
new file mode 100644
index 0000000..2a5f98a
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Client/Client.dproj
@@ -0,0 +1,1165 @@
+
+
+ {2F2F33BE-2A99-4B2A-A206-E1E4DE8915A3}
+ 20.2
+ Client.dpr
+ Release
+ DCC32
+ VCL
+ True
+ Win64
+ 3
+ Application
+ Client
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ Client.exe
+ off
+ vclx;vcl;vclimg;dbrtl;Rave77VCL;bdertl;rtl;vclactnband;xmlrtl;vcldb;vcldbx;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dclOfficeXP;$(DCC_UsePackage)
+ $(BDSCOMMONDIR)\DCP
+ $(BDSCOMMONDIR)\DCU
+ x86
+ 00400000
+ Client
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace)
+ true
+ 1032
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+
+
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+
+
+ System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+
+
+ Debug
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ Client.dpr
+
+
+ False
+ True
+ False
+
+
+ True
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ False
+ 1032
+ 1253
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+
+
+
+ False
+ True
+ True
+
+
+
+
+ Client.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12
+
+
+
+
diff --git a/Demos/UDP/ncUDPSockets/Client/Client.dproj.local b/Demos/UDP/ncUDPSockets/Client/Client.dproj.local
new file mode 100644
index 0000000..8b0113d
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Client/Client.dproj.local
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+ 2025/01/14 21:49:41.000.186,=D:\_Delphi\_Library\Netcom7\Demos\SimpleSockets_UDP\Client\Unit1.pas
+ 2025/01/14 21:49:56.000.966,D:\_Delphi\_Library\Netcom7\Demos\SimpleSockets_UDP\Client\uMainClient.pas=D:\_Delphi\_Library\Netcom7\Demos\SimpleSockets_UDP\Client\Unit1.pas
+ 2025/01/16 20:06:27.000.079,D:\_Delphi\_Library\NetCom7\Demos\SimpleSockets_UDP_v2\Client\uMainClient.pas=
+
+
diff --git a/Demos/SimpleSockets/Client.dsk b/Demos/UDP/ncUDPSockets/Client/Client.dsk
similarity index 94%
rename from Demos/SimpleSockets/Client.dsk
rename to Demos/UDP/ncUDPSockets/Client/Client.dsk
index 50e13fa..38e48cb 100644
--- a/Demos/SimpleSockets/Client.dsk
+++ b/Demos/UDP/ncUDPSockets/Client/Client.dsk
@@ -1,769 +1,769 @@
-[Closed Files]
-File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.Forms.pas',0,1,1,6,10,0,0,{{1755,4}
-File_1=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas',0,1,9,1,59,0,0,,
-File_2=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPIHelpers.pas',0,1,1,1,5,0,0,,{1
-File_3=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncThreads.pas',0,1,88,13,95,0,0,,
-File_4=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPI.pas',0,1,1,1,1,0,0,,{1
-File_5=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectX9\uD3DX9.pas',0,1,5404,1,5435,0,0,,
-File_6=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectX9\uDirect3D9.pas',0,1,3093,1,3112,0,0,,
-File_7=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpTypes.pas',0,1,404,1,417,0,0,,
-File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDirectPanel.pas',0,1,2514,5,2533,0,0,,{1
-File_9=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\Forms.pas',0,1,9739,51,9749,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dproj
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dproj]
-ModuleType=TBaseProject
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dpr
-CursorX=11
-CursorY=12
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas
-CursorX=35
-CursorY=130
-TopLine=118
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=1
-Breakpoint0='C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncSources.pas',973,'',0,1,'',1,0,0,'',1,'','','',0,''
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Action,
-ExpandedItems=LiveBindings=0,"LiveBindings Designer=0",Margins=0,ActiveControl=0,Anchors=0,BorderIcons=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-318
-Top=-363
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.Forms.pas',0,1,1,6,10,0,0,{{1755,4}
+File_1=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas',0,1,9,1,59,0,0,,
+File_2=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPIHelpers.pas',0,1,1,1,5,0,0,,{1
+File_3=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncThreads.pas',0,1,88,13,95,0,0,,
+File_4=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPI.pas',0,1,1,1,1,0,0,,{1
+File_5=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectX9\uD3DX9.pas',0,1,5404,1,5435,0,0,,
+File_6=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectX9\uDirect3D9.pas',0,1,3093,1,3112,0,0,,
+File_7=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpTypes.pas',0,1,404,1,417,0,0,,
+File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDirectPanel.pas',0,1,2514,5,2533,0,0,,{1
+File_9=TSourceModule,'c:\program files (x86)\embarcadero\rad studio\7.0\SOURCE\WIN32\VCL\Forms.pas',0,1,9739,51,9749,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dproj
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dproj]
+ModuleType=TBaseProject
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dpr
+CursorX=11
+CursorY=12
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Client.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\ufrmMain.pas
+CursorX=35
+CursorY=130
+TopLine=118
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=1
+Breakpoint0='C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncSources.pas',973,'',0,1,'',1,0,0,'',1,'','','',0,''
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Action,
+ExpandedItems=LiveBindings=0,"LiveBindings Designer=0",Margins=0,ActiveControl=0,Anchors=0,BorderIcons=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-318
+Top=-363
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/UDP/ncUDPSockets/Client/Client.identcache b/Demos/UDP/ncUDPSockets/Client/Client.identcache
new file mode 100644
index 0000000..732fa09
Binary files /dev/null and b/Demos/UDP/ncUDPSockets/Client/Client.identcache differ
diff --git a/Demos/UDP/ncUDPSockets/Client/Client.res b/Demos/UDP/ncUDPSockets/Client/Client.res
new file mode 100644
index 0000000..d4b6e46
Binary files /dev/null and b/Demos/UDP/ncUDPSockets/Client/Client.res differ
diff --git a/Demos/SimpleSockets/Client.skincfg b/Demos/UDP/ncUDPSockets/Client/Client.skincfg
similarity index 94%
rename from Demos/SimpleSockets/Client.skincfg
rename to Demos/UDP/ncUDPSockets/Client/Client.skincfg
index 9e7a05b..0f00ce7 100644
--- a/Demos/SimpleSockets/Client.skincfg
+++ b/Demos/UDP/ncUDPSockets/Client/Client.skincfg
@@ -1,33 +1,33 @@
-[ExpressSkins]
-Default=1
-ShowNotifications=1
-Enabled=1
-dxSkinBlack=1
-dxSkinBlue=0
-dxSkinCaramel=0
-dxSkinCoffee=0
-dxSkinDarkRoom=0
-dxSkinDarkSide=1
-dxSkinFoggy=0
-dxSkinGlassOceans=0
-dxSkiniMaginary=0
-dxSkinLilian=0
-dxSkinLiquidSky=0
-dxSkinLondonLiquidSky=0
-dxSkinMcSkin=0
-dxSkinMoneyTwins=0
-dxSkinOffice2007Black=1
-dxSkinOffice2007Blue=0
-dxSkinOffice2007Green=0
-dxSkinOffice2007Pink=0
-dxSkinOffice2007Silver=1
-dxSkinPumpkin=0
-dxSkinSeven=0
-dxSkinSharp=0
-dxSkinSilver=0
-dxSkinSpringTime=0
-dxSkinStardust=0
-dxSkinSummer2008=0
-dxSkinsDefaultPainters=0
-dxSkinValentine=0
-dxSkinXmas2008Blue=0
+[ExpressSkins]
+Default=1
+ShowNotifications=1
+Enabled=1
+dxSkinBlack=1
+dxSkinBlue=0
+dxSkinCaramel=0
+dxSkinCoffee=0
+dxSkinDarkRoom=0
+dxSkinDarkSide=1
+dxSkinFoggy=0
+dxSkinGlassOceans=0
+dxSkiniMaginary=0
+dxSkinLilian=0
+dxSkinLiquidSky=0
+dxSkinLondonLiquidSky=0
+dxSkinMcSkin=0
+dxSkinMoneyTwins=0
+dxSkinOffice2007Black=1
+dxSkinOffice2007Blue=0
+dxSkinOffice2007Green=0
+dxSkinOffice2007Pink=0
+dxSkinOffice2007Silver=1
+dxSkinPumpkin=0
+dxSkinSeven=0
+dxSkinSharp=0
+dxSkinSilver=0
+dxSkinSpringTime=0
+dxSkinStardust=0
+dxSkinSummer2008=0
+dxSkinsDefaultPainters=0
+dxSkinValentine=0
+dxSkinXmas2008Blue=0
diff --git a/Demos/SimpleSockets/Client_Icon.ico b/Demos/UDP/ncUDPSockets/Client/Client_Icon.ico
similarity index 100%
rename from Demos/SimpleSockets/Client_Icon.ico
rename to Demos/UDP/ncUDPSockets/Client/Client_Icon.ico
diff --git a/Demos/UDP/ncUDPSockets/Client/ufrmMain.dfm b/Demos/UDP/ncUDPSockets/Client/ufrmMain.dfm
new file mode 100644
index 0000000..7c429a6
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Client/ufrmMain.dfm
@@ -0,0 +1,171 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ ActiveControl = edtDataToSend
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'UDPClient'
+ ClientHeight = 243
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 169
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start UDP Client'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pnlAddress: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtHost: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 281
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ TextHint = 'Enter host address'
+ OnChange = edtHostChange
+ end
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 291
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 211
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendData: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send'
+ Default = True
+ TabOrder = 0
+ OnClick = btnSendDataClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtDataToSend: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 407
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'This is some text data'
+ TextHint = 'Enter data to send here'
+ OnEnter = edtDataToSendEnter
+ OnExit = edtDataToSendExit
+ end
+ end
+ end
+ object UDPClient: TncUDPClient
+ Broadcast = True
+ OnReadDatagram = UDPClientReadDatagram
+ Left = 216
+ Top = 96
+ end
+end
diff --git a/Demos/UDP/ncUDPSockets/Client/ufrmMain.pas b/Demos/UDP/ncUDPSockets/Client/ufrmMain.pas
new file mode 100644
index 0000000..64a8645
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Client/ufrmMain.pas
@@ -0,0 +1,225 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin,
+ System.Diagnostics, ncLines, ncUDPSockets, ncIPUtils;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pnlAddress: TPanel;
+ edtHost: TEdit;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendData: TButton;
+ Panel2: TPanel;
+ edtDataToSend: TEdit;
+ UDPClient: TncUDPClient;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnActivateClick(Sender: TObject);
+ procedure edtHostChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure edtDataToSendEnter(Sender: TObject);
+ procedure edtDataToSendExit(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure btnSendDataClick(Sender: TObject);
+ procedure UDPClientReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer;
+ const SenderAddr: TSockAddrStorage);
+
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ //
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ UDPClient.Active := False;
+end;
+
+// *****************************************************************************
+// Start/Stop Main CLient
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if UDPClient.Active then
+ begin
+ // Deactivate the UDP client
+ UDPClient.Active := False;
+ btnActivate.Caption := 'Start UDP Client';
+ Log('UDP Client Deactivated');
+ end
+ else
+ begin
+ // Check if the host field is blank
+ if Trim(edtHost.Text) = '' then
+ begin
+ Log('Host field cannot be blank.');
+ Exit; // Exit the procedure if the host field is blank
+ end;
+
+ try
+ // Set the host from the text field
+ UDPClient.Host := edtHost.Text;
+
+ // Activate the UDP client
+ UDPClient.Active := True;
+ btnActivate.Caption := 'Stop UDP Client';
+ Log('UDP Client Activated');
+ except
+ on E: Exception do
+ Log('Failed to activate UDP Client: ' + E.Message);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change host (server)
+// *****************************************************************************
+procedure TForm1.edtHostChange(Sender: TObject);
+begin
+ try
+ UDPClient.Host := edtHost.Text;
+ except
+ edtHost.OnChange := nil;
+ try
+ edtHost.Text := UDPClient.Host;
+ finally
+ edtHost.OnChange := edtHostChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Client port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ UDPClient.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := UDPClient.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// Data to send
+// *****************************************************************************
+procedure TForm1.edtDataToSendEnter(Sender: TObject);
+begin
+ btnSendData.Default := True;
+end;
+
+procedure TForm1.edtDataToSendExit(Sender: TObject);
+begin
+ btnSendData.Default := False;
+end;
+
+procedure TForm1.btnSendDataClick(Sender: TObject);
+begin
+ try
+ // Ensure the client is active
+ if not UDPClient.Active then
+ begin
+ Log('Cannot send - client not active');
+ Exit;
+ end;
+
+ // Ensure the input field is not empty
+ if Trim(edtDataToSend.Text) = '' then
+ begin
+ Log('Cannot send - Data field cannot be blank.');
+ Exit;
+ end;
+
+ // Send the data if all conditions are met
+ UDPClient.Send(edtDataToSend.Text);
+ Log(Format('Data sent: %s', [edtDataToSend.Text]));
+ except
+ on E: Exception do
+ Log('Error sending: ' + E.Message);
+ end;
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.UDPClientReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer; const SenderAddr: TSockAddrStorage);
+var
+ ReceivedData: string;
+ BytesReceived: TBytes;
+ SenderIP: string;
+begin
+ // Convert received data to string
+ ReceivedData := StringOf(Copy(aBuf, 0, aBufCount));
+
+ // Get sender IP address using our utils
+ try
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ except
+ on E: EIPError do
+ SenderIP := Format('Invalid Address: %s', [E.Message]);
+ end;
+
+ Form1.Log(Format('Received from %s: %s', [SenderIP, ReceivedData]));
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word;
+Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/SimpleSockets/Srv/Server.dpr b/Demos/UDP/ncUDPSockets/Server/Server.dpr
similarity index 80%
rename from Demos/SimpleSockets/Srv/Server.dpr
rename to Demos/UDP/ncUDPSockets/Server/Server.dpr
index 2ea1536..5062c31 100644
--- a/Demos/SimpleSockets/Srv/Server.dpr
+++ b/Demos/UDP/ncUDPSockets/Server/Server.dpr
@@ -1,17 +1,19 @@
-program Server;
-
-uses
- Vcl.Forms,
- ufrmMain in 'ufrmMain.pas' {frmMain};
-
-{$R *.res}
-
-begin
- {$IFDEF DEBUG}
- ReportMemoryLeaksOnShutdown := True;
- {$ENDIF}
- Application.Initialize;
- Application.MainFormOnTaskbar := True;
- Application.CreateForm(TfrmMain, frmMain);
- Application.Run;
-end.
+program Server;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {frmMain};
+
+{$R *.res}
+
+begin
+ {$IFDEF DEBUG}
+ ReportMemoryLeaksOnShutdown := True;
+ {$ENDIF}
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
+
+
diff --git a/Demos/UDP/ncUDPSockets/Server/Server.dproj b/Demos/UDP/ncUDPSockets/Server/Server.dproj
new file mode 100644
index 0000000..5dca099
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Server/Server.dproj
@@ -0,0 +1,1170 @@
+
+
+ {B76A70BC-BC2B-42B3-990D-FEC6939EAFD9}
+ 20.2
+ Server.dpr
+ Release
+ DCC32
+ VCL
+ True
+ Win64
+ 3
+ Application
+ Server
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ Server.exe
+ off
+ vclx;vcl;vclimg;dbrtl;Rave77VCL;bdertl;rtl;vclactnband;xmlrtl;vcldb;vcldbx;vcltouch;dsnap;dsnapcon;TeeUI;TeeDB;Tee;vclib;ibxpress;adortl;IndyCore;IndySystem;IndyProtocols;inet;intrawebdb_100_140;Intraweb_100_140;VclSmp;vclie;websnap;webdsnap;inetdb;inetdbbde;inetdbxpress;soaprtl;vclribbon;dbexpress;DbxCommonDriver;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;dbxcds;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;dclOfficeXP;$(DCC_UsePackage)
+ $(BDSCOMMONDIR)\DCP
+ $(BDSCOMMONDIR)\DCU
+ x86
+ 00400000
+ Server
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace)
+ true
+ 1032
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ EUREKALOG;$(DCC_Define)
+ 3
+ true
+
+
+ android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+
+
+ System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ true
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+ System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+ 1033
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\delphi_PROJECTICON.ico
+
+
+ false
+ DEBUG;$(DCC_Define)
+
+
+ Debug
+
+
+ true
+ PerMonitorV2
+
+
+ true
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ False
+ True
+ False
+
+
+ True
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ False
+ 1032
+ 1253
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+
+
+ Server.dpr
+
+
+
+ False
+ True
+ True
+
+
+
+
+ Server.exe
+ true
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ res\xml
+ 1
+
+
+ res\xml
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-v21
+ 1
+
+
+ res\values-v21
+ 1
+
+
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+ res\drawable-xxxhdpi
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+ 0
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .dll;.bpl
+
+
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 0
+ .bpl
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+ Contents
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ library\lib\arm64-v8a
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+ ..\$(PROJECTNAME).launchscreen
+ 64
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ Assets
+ 1
+
+
+ Assets
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12
+
+
+
+
diff --git a/Demos/UDP/ncUDPSockets/Server/Server.dproj.local b/Demos/UDP/ncUDPSockets/Server/Server.dproj.local
new file mode 100644
index 0000000..c6ab0d5
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Server/Server.dproj.local
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+ 2025/01/14 22:17:15.000.403,=D:\_Delphi\_Library\Netcom7\Demos\SimpleSockets_UDP\Server\Unit1.pas
+ 2025/01/14 22:17:30.000.252,D:\_Delphi\_Library\Netcom7\Demos\SimpleSockets_UDP\Server\uMainServer.pas=D:\_Delphi\_Library\Netcom7\Demos\SimpleSockets_UDP\Server\Unit1.pas
+ 2025/01/16 20:08:59.000.762,D:\_Delphi\_Library\NetCom7\Demos\SimpleSockets_UDP_v2\Server\uMainServer.pas=
+
+
diff --git a/Demos/UDP/ncUDPSockets/Server/Server.drc b/Demos/UDP/ncUDPSockets/Server/Server.drc
new file mode 100644
index 0000000..599b1e6
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Server/Server.drc
@@ -0,0 +1,769 @@
+/* VER360
+ Generated by the Embarcadero Delphi Pascal Compiler
+ because -GD or --drc was supplied to the compiler.
+
+ This file contains compiler-generated resources that
+ were bound to the executable.
+ If this file is empty, then no compiler-generated
+ resources were bound to the produced executable.
+*/
+
+#define System_Win_ComConst_SVarNotObject 65152
+#define System_Win_ComConst_STooManyParams 65153
+#define ncUDPSockets_ECannotSetPortWhileSocketActiveStr 65154
+#define ncUDPSockets_ECannotSendWhileSocketInactiveStr 65155
+#define ncUDPSockets_ECannotSetUseReaderThreadWhileSocketActiveStr 65156
+#define ncUDPSockets_ECannotSetFamilyWhileConnectionIsActiveStr 65157
+#define Vcl_Consts_SStyleRegisterError 65168
+#define Vcl_Consts_SStyleClassRegisterError 65169
+#define Vcl_Consts_SStyleNotFound 65170
+#define Vcl_Consts_SStyleClassNotFound 65171
+#define Vcl_Consts_SStyleInvalidHandle 65172
+#define Vcl_Consts_SStyleFormatError 65173
+#define Vcl_Consts_SStyleHookClassRegistered 65174
+#define Vcl_Consts_SStyleHookClassNotRegistered 65175
+#define Vcl_Consts_SStyleInvalidParameter 65176
+#define Vcl_Consts_SStyleFeatureNotSupported 65177
+#define Vcl_Consts_SStyleNotRegistered 65178
+#define Vcl_Consts_SStyleUnregisterError 65179
+#define Vcl_Consts_SStyleNotRegisteredNoName 65180
+#define Vcl_Consts_sBeginInvokeNoHandle 65181
+#define System_Win_ComConst_SOleError 65182
+#define System_Win_ComConst_SNoMethod 65183
+#define Vcl_Consts_SDockZoneNotFound 65184
+#define Vcl_Consts_SDockZoneHasNoCtl 65185
+#define Vcl_Consts_SDockZoneVersionConflict 65186
+#define Vcl_Consts_SPromptArrayTooShort 65187
+#define Vcl_Consts_SPromptArrayEmpty 65188
+#define Vcl_Consts_SUsername 65189
+#define Vcl_Consts_SPassword 65190
+#define Vcl_Consts_SDomain 65191
+#define Vcl_Consts_SLogin 65192
+#define Vcl_Consts_STrayIconRemoveError 65193
+#define Vcl_Consts_SWindowsVistaRequired 65194
+#define Vcl_Consts_STaskDlgButtonCaption 65195
+#define Vcl_Consts_STaskDlgRadioButtonCaption 65196
+#define Vcl_Consts_SInvalidTaskDlgButtonCaption 65197
+#define Vcl_Consts_SStyleLoadError 65198
+#define Vcl_Consts_SStyleLoadErrors 65199
+#define Vcl_Consts_SmkcDown 65200
+#define Vcl_Consts_SmkcIns 65201
+#define Vcl_Consts_SmkcDel 65202
+#define Vcl_Consts_SmkcShift 65203
+#define Vcl_Consts_SmkcCtrl 65204
+#define Vcl_Consts_SmkcAlt 65205
+#define Vcl_Consts_SOutOfRange 65206
+#define Vcl_Consts_sAllFilter 65207
+#define Vcl_Consts_SIconToClipboard 65208
+#define Vcl_Consts_SCannotOpenClipboard 65209
+#define Vcl_Consts_SInvalidMemoSize 65210
+#define Vcl_Consts_SInvalidPrinterOp 65211
+#define Vcl_Consts_SNoDefaultPrinter 65212
+#define Vcl_Consts_SDuplicateMenus 65213
+#define Vcl_Consts_SDockedCtlNeedsName 65214
+#define Vcl_Consts_SDockTreeRemoveError 65215
+#define Vcl_Consts_SMsgDlgAll 65216
+#define Vcl_Consts_SMsgDlgNoToAll 65217
+#define Vcl_Consts_SMsgDlgYesToAll 65218
+#define Vcl_Consts_SMsgDlgClose 65219
+#define Vcl_Consts_SmkcBkSp 65220
+#define Vcl_Consts_SmkcTab 65221
+#define Vcl_Consts_SmkcEsc 65222
+#define Vcl_Consts_SmkcEnter 65223
+#define Vcl_Consts_SmkcSpace 65224
+#define Vcl_Consts_SmkcPgUp 65225
+#define Vcl_Consts_SmkcPgDn 65226
+#define Vcl_Consts_SmkcEnd 65227
+#define Vcl_Consts_SmkcHome 65228
+#define Vcl_Consts_SmkcLeft 65229
+#define Vcl_Consts_SmkcUp 65230
+#define Vcl_Consts_SmkcRight 65231
+#define Vcl_Consts_SVEnhMetafiles 65232
+#define Vcl_Consts_SVIcons 65233
+#define Vcl_Consts_SVBitmaps 65234
+#define Vcl_Consts_SVTIFFImages 65235
+#define Vcl_Consts_SMsgDlgWarning 65236
+#define Vcl_Consts_SMsgDlgError 65237
+#define Vcl_Consts_SMsgDlgInformation 65238
+#define Vcl_Consts_SMsgDlgConfirm 65239
+#define Vcl_Consts_SMsgDlgYes 65240
+#define Vcl_Consts_SMsgDlgNo 65241
+#define Vcl_Consts_SMsgDlgOK 65242
+#define Vcl_Consts_SMsgDlgCancel 65243
+#define Vcl_Consts_SMsgDlgHelp 65244
+#define Vcl_Consts_SMsgDlgAbort 65245
+#define Vcl_Consts_SMsgDlgRetry 65246
+#define Vcl_Consts_SMsgDlgIgnore 65247
+#define Vcl_Consts_SNoMDIForm 65248
+#define Vcl_Consts_SImageCanvasNeedsBitmap 65249
+#define Vcl_Consts_SControlParentSetToSelf 65250
+#define Vcl_Consts_SControlNonMainThreadUsage 65251
+#define Vcl_Consts_SOKButton 65252
+#define Vcl_Consts_SCancelButton 65253
+#define Vcl_Consts_SYesButton 65254
+#define Vcl_Consts_SNoButton 65255
+#define Vcl_Consts_SHelpButton 65256
+#define Vcl_Consts_SCloseButton 65257
+#define Vcl_Consts_SIgnoreButton 65258
+#define Vcl_Consts_SRetryButton 65259
+#define Vcl_Consts_SAbortButton 65260
+#define Vcl_Consts_SAllButton 65261
+#define Vcl_Consts_SCannotDragForm 65262
+#define Vcl_Consts_SVMetafiles 65263
+#define Vcl_Consts_SParentGivenNotAParent 65264
+#define Vcl_Consts_SMDIChildNotVisible 65265
+#define Vcl_Consts_SVisibleChanged 65266
+#define Vcl_Consts_SCannotShowModal 65267
+#define Vcl_Consts_SScrollBarRange 65268
+#define Vcl_Consts_SPropertyOutOfRange 65269
+#define Vcl_Consts_SMenuIndexError 65270
+#define Vcl_Consts_SMenuReinserted 65271
+#define Vcl_Consts_SMenuNotFound 65272
+#define Vcl_Consts_SNoTimers 65273
+#define Vcl_Consts_SNotPrinting 65274
+#define Vcl_Consts_SPrinting 65275
+#define Vcl_Consts_SPrinterIndexError 65276
+#define Vcl_Consts_SInvalidPrinter 65277
+#define Vcl_Consts_SDeviceOnPort 65278
+#define Vcl_Consts_SGroupIndexTooLow 65279
+#define Vcl_Consts_SOutOfResources 65280
+#define Vcl_Consts_SNoCanvasHandle 65281
+#define Vcl_Consts_SInvalidTextFormatFlag 65282
+#define Vcl_Consts_SInvalidFrameIndex 65283
+#define Vcl_Consts_SInvalidImageSize 65284
+#define Vcl_Consts_SInvalidImageList 65285
+#define Vcl_Consts_SReplaceImage 65286
+#define Vcl_Consts_SInsertImage 65287
+#define Vcl_Consts_SImageIndexError 65288
+#define Vcl_Consts_SImageReadFail 65289
+#define Vcl_Consts_SImageWriteFail 65290
+#define Vcl_Consts_SWindowDCError 65291
+#define Vcl_Consts_SWindowClass 65292
+#define Vcl_Consts_SCannotFocus 65293
+#define Vcl_Consts_SParentRequired 65294
+#define Vcl_Consts_SControlPath 65295
+#define System_RTLConsts_sObserverNoSinglecastFound 65296
+#define System_RTLConsts_sObserverNoMulticastFound 65297
+#define System_RTLConsts_sObserverNotAvailable 65298
+#define System_RTLConsts_sMustWaitOnOneEvent 65299
+#define System_RTLConsts_sBeginInvokeDestroying 65300
+#define Vcl_Consts_SInvalidBitmap 65301
+#define Vcl_Consts_SInvalidIcon 65302
+#define Vcl_Consts_SInvalidMetafile 65303
+#define Vcl_Consts_SInvalidPixelFormat 65304
+#define Vcl_Consts_SInvalidImage 65305
+#define Vcl_Consts_SScanLine 65306
+#define Vcl_Consts_SChangeIconSize 65307
+#define Vcl_Consts_SChangeWicSize 65308
+#define Vcl_Consts_SUnknownExtension 65309
+#define Vcl_Consts_SUnknownClipboardFormat 65310
+#define Vcl_Consts_SUnknownStreamFormat 65311
+#define System_RTLConsts_SWindowsXP 65312
+#define System_RTLConsts_SWindowsServer2003 65313
+#define System_RTLConsts_SWindowsServer2003R2 65314
+#define System_RTLConsts_SWindowsServer2012 65315
+#define System_RTLConsts_SWindowsServer2012R2 65316
+#define System_RTLConsts_SWindowsServer2016 65317
+#define System_RTLConsts_SWindowsServer2019 65318
+#define System_RTLConsts_SWindowsServer2022 65319
+#define System_RTLConsts_SWindows8 65320
+#define System_RTLConsts_SWindows8Point1 65321
+#define System_RTLConsts_SWindows10 65322
+#define System_RTLConsts_SWindows11 65323
+#define System_RTLConsts_SWinRTInstanceError 65324
+#define System_RTLConsts_sObserverUnsupported 65325
+#define System_RTLConsts_sObserverMultipleSingleCast 65326
+#define System_RTLConsts_sObserverNoInterface 65327
+#define System_RTLConsts_SNonPublicType 65328
+#define System_RTLConsts_SByRefArgMismatch 65329
+#define System_RTLConsts_SPropIsReadOnly 65330
+#define System_RTLConsts_SPropIsWriteOnly 65331
+#define System_RTLConsts_SInvalidRttiDestroy 65332
+#define System_RTLConsts_SServiceNotFound 65333
+#define System_RTLConsts_SVersionStr 65334
+#define System_RTLConsts_SSPVersionStr 65335
+#define System_RTLConsts_SVersion32 65336
+#define System_RTLConsts_SVersion64 65337
+#define System_RTLConsts_SWindows 65338
+#define System_RTLConsts_SWindowsVista 65339
+#define System_RTLConsts_SWindowsServer2008 65340
+#define System_RTLConsts_SWindows7 65341
+#define System_RTLConsts_SWindowsServer2008R2 65342
+#define System_RTLConsts_SWindows2000 65343
+#define System_RTLConsts_sInvalidTimespanFormat 65344
+#define System_RTLConsts_sTimespanElementTooLong 65345
+#define System_RTLConsts_SNoContext 65346
+#define System_RTLConsts_SNoContextFound 65347
+#define System_RTLConsts_SNoIndex 65348
+#define System_RTLConsts_SNoSearch 65349
+#define System_RTLConsts_SNoTableOfContents 65350
+#define System_RTLConsts_SNoTopics 65351
+#define System_RTLConsts_SNothingFound 65352
+#define System_RTLConsts_SArgumentOutOfRange 65353
+#define System_RTLConsts_SArgumentNil 65354
+#define System_RTLConsts_SGenericItemNotFound 65355
+#define System_RTLConsts_SGenericDuplicateItem 65356
+#define System_RTLConsts_SInsufficientRtti 65357
+#define System_RTLConsts_SParameterCountMismatch 65358
+#define System_RTLConsts_SParameterCountExceeded 65359
+#define System_RTLConsts_SThreadExternalSetReturnValue 65360
+#define System_RTLConsts_SParamIsNil 65361
+#define System_RTLConsts_SParamIsNegative 65362
+#define System_RTLConsts_SInputBufferExceed 65363
+#define System_RTLConsts_SInvalidCharsInPath 65364
+#define System_RTLConsts_hNoFilterViewer 65365
+#define System_RTLConsts_sArgumentInvalid 65366
+#define System_RTLConsts_sInvalidStringAndObjectArrays 65367
+#define System_RTLConsts_sSameArrays 65368
+#define System_RTLConsts_sNoConstruct 65369
+#define System_RTLConsts_sInvalidTimeoutValue 65370
+#define System_RTLConsts_sSpinCountOutOfRange 65371
+#define System_RTLConsts_sTimespanTooLong 65372
+#define System_RTLConsts_sInvalidTimespanDuration 65373
+#define System_RTLConsts_sTimespanValueCannotBeNan 65374
+#define System_RTLConsts_sCannotNegateTimespan 65375
+#define System_RTLConsts_SReadOnlyProperty 65376
+#define System_RTLConsts_SRegCreateFailed 65377
+#define System_RTLConsts_SRegGetDataFailed 65378
+#define System_RTLConsts_SRegSetDataFailed 65379
+#define System_RTLConsts_SResNotFound 65380
+#define System_RTLConsts_SSeekNotImplemented 65381
+#define System_RTLConsts_SSortedListError 65382
+#define System_RTLConsts_SUnknownGroup 65383
+#define System_RTLConsts_SUnknownProperty 65384
+#define System_RTLConsts_SWriteError 65385
+#define System_RTLConsts_SThreadCreateError 65386
+#define System_RTLConsts_SThreadError 65387
+#define System_RTLConsts_SThreadExternalTerminate 65388
+#define System_RTLConsts_SThreadExternalWait 65389
+#define System_RTLConsts_SThreadStartError 65390
+#define System_RTLConsts_SThreadExternalCheckTerminated 65391
+#define System_RTLConsts_SFOpenErrorEx 65392
+#define System_RTLConsts_SInvalidImage 65393
+#define System_RTLConsts_SInvalidName 65394
+#define System_RTLConsts_SInvalidProperty 65395
+#define System_RTLConsts_SInvalidPropertyPath 65396
+#define System_RTLConsts_SInvalidPropertyValue 65397
+#define System_RTLConsts_SInvalidRegType 65398
+#define System_RTLConsts_SListCapacityError 65399
+#define System_RTLConsts_SListCountError 65400
+#define System_RTLConsts_SListIndexError 65401
+#define System_RTLConsts_SListIndexErrorRangeReason 65402
+#define System_RTLConsts_SListIndexErrorEmptyReason 65403
+#define System_RTLConsts_SMemoryStreamError 65404
+#define System_RTLConsts_SNoComSupport 65405
+#define System_RTLConsts_SPropertyException 65406
+#define System_RTLConsts_SReadError 65407
+#define System_SysConst_SInvalidDestinationIndex 65408
+#define System_SysConst_SInvalidCodePage 65409
+#define System_SysConst_SInvalidEncodingName 65410
+#define System_SysConst_SNoMappingForUnicodeCharacter 65411
+#define System_SysConst_SInvalidStringBaseIndex 65412
+#define System_RTLConsts_SAncestorNotFound 65413
+#define System_RTLConsts_SAssignError 65414
+#define System_RTLConsts_SBitsIndexError 65415
+#define System_RTLConsts_SCantWriteResourceStreamError 65416
+#define System_RTLConsts_SCheckSynchronizeError 65417
+#define System_RTLConsts_SClassNotFound 65418
+#define System_RTLConsts_SDuplicateClass 65419
+#define System_RTLConsts_SDuplicateItem 65420
+#define System_RTLConsts_SDuplicateName 65421
+#define System_RTLConsts_SDuplicateString 65422
+#define System_RTLConsts_SFCreateErrorEx 65423
+#define System_SysConst_SShortDayNameWed 65424
+#define System_SysConst_SShortDayNameThu 65425
+#define System_SysConst_SShortDayNameFri 65426
+#define System_SysConst_SShortDayNameSat 65427
+#define System_SysConst_SLongDayNameSun 65428
+#define System_SysConst_SLongDayNameMon 65429
+#define System_SysConst_SLongDayNameTue 65430
+#define System_SysConst_SLongDayNameWed 65431
+#define System_SysConst_SLongDayNameThu 65432
+#define System_SysConst_SLongDayNameFri 65433
+#define System_SysConst_SLongDayNameSat 65434
+#define System_SysConst_SInvalidSourceArray 65435
+#define System_SysConst_SInvalidDestinationArray 65436
+#define System_SysConst_SCharIndexOutOfBounds 65437
+#define System_SysConst_SByteIndexOutOfBounds 65438
+#define System_SysConst_SInvalidCharCount 65439
+#define System_SysConst_SShortMonthNameDec 65440
+#define System_SysConst_SLongMonthNameJan 65441
+#define System_SysConst_SLongMonthNameFeb 65442
+#define System_SysConst_SLongMonthNameMar 65443
+#define System_SysConst_SLongMonthNameApr 65444
+#define System_SysConst_SLongMonthNameMay 65445
+#define System_SysConst_SLongMonthNameJun 65446
+#define System_SysConst_SLongMonthNameJul 65447
+#define System_SysConst_SLongMonthNameAug 65448
+#define System_SysConst_SLongMonthNameSep 65449
+#define System_SysConst_SLongMonthNameOct 65450
+#define System_SysConst_SLongMonthNameNov 65451
+#define System_SysConst_SLongMonthNameDec 65452
+#define System_SysConst_SShortDayNameSun 65453
+#define System_SysConst_SShortDayNameMon 65454
+#define System_SysConst_SShortDayNameTue 65455
+#define System_SysConst_SAssertError 65456
+#define System_SysConst_SAbstractError 65457
+#define System_SysConst_SModuleAccessViolation 65458
+#define System_SysConst_SOSError 65459
+#define System_SysConst_SUnkOSError 65460
+#define System_SysConst_SShortMonthNameJan 65461
+#define System_SysConst_SShortMonthNameFeb 65462
+#define System_SysConst_SShortMonthNameMar 65463
+#define System_SysConst_SShortMonthNameApr 65464
+#define System_SysConst_SShortMonthNameMay 65465
+#define System_SysConst_SShortMonthNameJun 65466
+#define System_SysConst_SShortMonthNameJul 65467
+#define System_SysConst_SShortMonthNameAug 65468
+#define System_SysConst_SShortMonthNameSep 65469
+#define System_SysConst_SShortMonthNameOct 65470
+#define System_SysConst_SShortMonthNameNov 65471
+#define System_SysConst_SVarTypeTooManyCustom 65472
+#define System_SysConst_SVarTypeCouldNotConvert 65473
+#define System_SysConst_SVarTypeConvertOverflow 65474
+#define System_SysConst_SVarOverflow 65475
+#define System_SysConst_SVarInvalid 65476
+#define System_SysConst_SVarBadType 65477
+#define System_SysConst_SVarNotImplemented 65478
+#define System_SysConst_SVarUnexpected 65479
+#define System_SysConst_SExternalException 65480
+#define System_SysConst_SAssertionFailed 65481
+#define System_SysConst_SIntfCastError 65482
+#define System_SysConst_SSafecallException 65483
+#define System_SysConst_SMonitorLockException 65484
+#define System_SysConst_SNoMonitorSupportException 65485
+#define System_SysConst_SNotImplemented 65486
+#define System_SysConst_SObjectDisposed 65487
+#define System_SysConst_SArgumentMissing 65488
+#define System_SysConst_SDispatchError 65489
+#define System_SysConst_SReadAccess 65490
+#define System_SysConst_SWriteAccess 65491
+#define System_SysConst_SExecuteAccess 65492
+#define System_SysConst_SInvalidAccess 65493
+#define System_SysConst_SVarArrayCreate 65494
+#define System_SysConst_SVarArrayBounds 65495
+#define System_SysConst_SVarArrayLocked 65496
+#define System_SysConst_SInvalidVarCast 65497
+#define System_SysConst_SInvalidVarOp 65498
+#define System_SysConst_SInvalidVarNullOp 65499
+#define System_SysConst_SInvalidVarOpWithHResultWithPrefix 65500
+#define System_SysConst_SVarTypeOutOfRangeWithPrefix 65501
+#define System_SysConst_SVarTypeAlreadyUsedWithPrefix 65502
+#define System_SysConst_SVarTypeNotUsableWithPrefix 65503
+#define System_SysConst_SRangeError 65504
+#define System_SysConst_SIntOverflow 65505
+#define System_SysConst_SInvalidOp 65506
+#define System_SysConst_SZeroDivide 65507
+#define System_SysConst_SOverflow 65508
+#define System_SysConst_SUnderflow 65509
+#define System_SysConst_SInvalidPointer 65510
+#define System_SysConst_SInvalidCast 65511
+#define System_SysConst_SAccessViolationArg3 65512
+#define System_SysConst_SAccessViolationNoArg 65513
+#define System_SysConst_SStackOverflow 65514
+#define System_SysConst_SControlC 65515
+#define System_SysConst_SPrivilege 65516
+#define System_SysConst_SException 65517
+#define System_SysConst_SExceptTitle 65518
+#define System_SysConst_SInvalidFormat 65519
+#define System_SysConst_SUnknown 65520
+#define System_SysConst_SInvalidInteger 65521
+#define System_SysConst_SInvalidTimeStamp 65522
+#define System_SysConst_SInvalidGUID 65523
+#define System_SysConst_STimeEncodeError 65524
+#define System_SysConst_SDateEncodeError 65525
+#define System_SysConst_SOutOfMemory 65526
+#define System_SysConst_SInOutError 65527
+#define System_SysConst_SFileNotFound 65528
+#define System_SysConst_SInvalidUnknownFilename 65529
+#define System_SysConst_STooManyOpenFiles 65530
+#define System_SysConst_SAccessDenied 65531
+#define System_SysConst_SEndOfFile 65532
+#define System_SysConst_SDiskFull 65533
+#define System_SysConst_SInvalidInput 65534
+#define System_SysConst_SDivByZero 65535
+STRINGTABLE
+BEGIN
+ System_Win_ComConst_SVarNotObject, L"Variant does not reference an automation object"
+ System_Win_ComConst_STooManyParams, L"Dispatch methods do not support more than 64 parameters"
+ ncUDPSockets_ECannotSetPortWhileSocketActiveStr, L"Cannot set Port property while socket is active"
+ ncUDPSockets_ECannotSendWhileSocketInactiveStr, L"Cannot send data while socket is inactive"
+ ncUDPSockets_ECannotSetUseReaderThreadWhileSocketActiveStr, L"Cannot set UseReaderThread property while socket is active"
+ ncUDPSockets_ECannotSetFamilyWhileConnectionIsActiveStr, L"Cannot set Family property whilst the connection is active"
+ Vcl_Consts_SStyleRegisterError, L"Style '%s' already registered"
+ Vcl_Consts_SStyleClassRegisterError, L"Style class '%s' already registered"
+ Vcl_Consts_SStyleNotFound, L"Style '%s' not found"
+ Vcl_Consts_SStyleClassNotFound, L"Style class '%s' not found"
+ Vcl_Consts_SStyleInvalidHandle, L"Invalid style handle"
+ Vcl_Consts_SStyleFormatError, L"Invalid style format"
+ Vcl_Consts_SStyleHookClassRegistered, L"Class '%s' is already registered for '%s'"
+ Vcl_Consts_SStyleHookClassNotRegistered, L"Class '%s' is not registered for '%s'"
+ Vcl_Consts_SStyleInvalidParameter, L"%s parameter cannot be nil"
+ Vcl_Consts_SStyleFeatureNotSupported, L"Feature not supported by this style"
+ Vcl_Consts_SStyleNotRegistered, L"Style '%s' is not registered"
+ Vcl_Consts_SStyleUnregisterError, L"Cannot unregister the system style"
+ Vcl_Consts_SStyleNotRegisteredNoName, L"Style not registered"
+ Vcl_Consts_sBeginInvokeNoHandle, L"Cannot call BeginInvoke on a control with no parent or window handle"
+ System_Win_ComConst_SOleError, L"OLE error %.8x"
+ System_Win_ComConst_SNoMethod, L"Method '%s' not supported by automation object"
+ Vcl_Consts_SDockZoneNotFound, L" - Dock zone not found"
+ Vcl_Consts_SDockZoneHasNoCtl, L" - Dock zone has no control"
+ Vcl_Consts_SDockZoneVersionConflict, L"Error loading dock zone from the stream. Expecting version %d, but found %d."
+ Vcl_Consts_SPromptArrayTooShort, L"Length of value array must be >= length of prompt array"
+ Vcl_Consts_SPromptArrayEmpty, L"Prompt array must not be empty"
+ Vcl_Consts_SUsername, L"&Username"
+ Vcl_Consts_SPassword, L"&Password"
+ Vcl_Consts_SDomain, L"&Domain"
+ Vcl_Consts_SLogin, L"Login"
+ Vcl_Consts_STrayIconRemoveError, L"Cannot remove shell notification icon"
+ Vcl_Consts_SWindowsVistaRequired, L"%s requires Windows Vista or later"
+ Vcl_Consts_STaskDlgButtonCaption, L"Button%d"
+ Vcl_Consts_STaskDlgRadioButtonCaption, L"RadioButton%d"
+ Vcl_Consts_SInvalidTaskDlgButtonCaption, L"Caption cannot be empty"
+ Vcl_Consts_SStyleLoadError, L"Unable to load style '%s'"
+ Vcl_Consts_SStyleLoadErrors, L"Unable to load styles: %s"
+ Vcl_Consts_SmkcDown, L"Down"
+ Vcl_Consts_SmkcIns, L"Ins"
+ Vcl_Consts_SmkcDel, L"Del"
+ Vcl_Consts_SmkcShift, L"Shift+"
+ Vcl_Consts_SmkcCtrl, L"Ctrl+"
+ Vcl_Consts_SmkcAlt, L"Alt+"
+ Vcl_Consts_SOutOfRange, L"Value must be between %d and %d"
+ Vcl_Consts_sAllFilter, L"All"
+ Vcl_Consts_SIconToClipboard, L"Clipboard does not support Icons"
+ Vcl_Consts_SCannotOpenClipboard, L"Cannot open clipboard: %s"
+ Vcl_Consts_SInvalidMemoSize, L"Text exceeds memo capacity"
+ Vcl_Consts_SInvalidPrinterOp, L"Operation not supported on selected printer"
+ Vcl_Consts_SNoDefaultPrinter, L"There is no default printer currently selected"
+ Vcl_Consts_SDuplicateMenus, L"Menu '%s' is already being used by another form"
+ Vcl_Consts_SDockedCtlNeedsName, L"Docked control must have a name"
+ Vcl_Consts_SDockTreeRemoveError, L"Error removing control from dock tree"
+ Vcl_Consts_SMsgDlgAll, L"&All"
+ Vcl_Consts_SMsgDlgNoToAll, L"N&o to All"
+ Vcl_Consts_SMsgDlgYesToAll, L"Yes to &All"
+ Vcl_Consts_SMsgDlgClose, L"&Close"
+ Vcl_Consts_SmkcBkSp, L"BkSp"
+ Vcl_Consts_SmkcTab, L"Tab"
+ Vcl_Consts_SmkcEsc, L"Esc"
+ Vcl_Consts_SmkcEnter, L"Enter"
+ Vcl_Consts_SmkcSpace, L"Space"
+ Vcl_Consts_SmkcPgUp, L"PgUp"
+ Vcl_Consts_SmkcPgDn, L"PgDn"
+ Vcl_Consts_SmkcEnd, L"End"
+ Vcl_Consts_SmkcHome, L"Home"
+ Vcl_Consts_SmkcLeft, L"Left"
+ Vcl_Consts_SmkcUp, L"Up"
+ Vcl_Consts_SmkcRight, L"Right"
+ Vcl_Consts_SVEnhMetafiles, L"Enhanced Metafiles"
+ Vcl_Consts_SVIcons, L"Icons"
+ Vcl_Consts_SVBitmaps, L"Bitmaps"
+ Vcl_Consts_SVTIFFImages, L"TIFF Images"
+ Vcl_Consts_SMsgDlgWarning, L"Warning"
+ Vcl_Consts_SMsgDlgError, L"Error"
+ Vcl_Consts_SMsgDlgInformation, L"Information"
+ Vcl_Consts_SMsgDlgConfirm, L"Confirm"
+ Vcl_Consts_SMsgDlgYes, L"&Yes"
+ Vcl_Consts_SMsgDlgNo, L"&No"
+ Vcl_Consts_SMsgDlgOK, L"OK"
+ Vcl_Consts_SMsgDlgCancel, L"Cancel"
+ Vcl_Consts_SMsgDlgHelp, L"&Help"
+ Vcl_Consts_SMsgDlgAbort, L"&Abort"
+ Vcl_Consts_SMsgDlgRetry, L"&Retry"
+ Vcl_Consts_SMsgDlgIgnore, L"&Ignore"
+ Vcl_Consts_SNoMDIForm, L"Cannot create form. No MDI forms are currently active"
+ Vcl_Consts_SImageCanvasNeedsBitmap, L"Can only modify an image if it contains a bitmap"
+ Vcl_Consts_SControlParentSetToSelf, L"A control cannot have itself as its parent"
+ Vcl_Consts_SControlNonMainThreadUsage, L"Control '%s' is used on a not main thread"
+ Vcl_Consts_SOKButton, L"OK"
+ Vcl_Consts_SCancelButton, L"Cancel"
+ Vcl_Consts_SYesButton, L"&Yes"
+ Vcl_Consts_SNoButton, L"&No"
+ Vcl_Consts_SHelpButton, L"&Help"
+ Vcl_Consts_SCloseButton, L"&Close"
+ Vcl_Consts_SIgnoreButton, L"&Ignore"
+ Vcl_Consts_SRetryButton, L"&Retry"
+ Vcl_Consts_SAbortButton, L"Abort"
+ Vcl_Consts_SAllButton, L"&All"
+ Vcl_Consts_SCannotDragForm, L"Cannot drag a form"
+ Vcl_Consts_SVMetafiles, L"Metafiles"
+ Vcl_Consts_SParentGivenNotAParent, L"Parent given is not a parent of '%s'"
+ Vcl_Consts_SMDIChildNotVisible, L"Cannot hide an MDI Child Form"
+ Vcl_Consts_SVisibleChanged, L"Cannot change Visible in OnShow or OnHide"
+ Vcl_Consts_SCannotShowModal, L"Cannot make a visible window modal"
+ Vcl_Consts_SScrollBarRange, L"Scrollbar property out of range"
+ Vcl_Consts_SPropertyOutOfRange, L"%s property out of range"
+ Vcl_Consts_SMenuIndexError, L"Menu index out of range"
+ Vcl_Consts_SMenuReinserted, L"Menu inserted twice"
+ Vcl_Consts_SMenuNotFound, L"Sub-menu is not in menu"
+ Vcl_Consts_SNoTimers, L"Not enough timers available"
+ Vcl_Consts_SNotPrinting, L"Printer is not currently printing"
+ Vcl_Consts_SPrinting, L"Printing in progress"
+ Vcl_Consts_SPrinterIndexError, L"Printer index out of range"
+ Vcl_Consts_SInvalidPrinter, L"Printer selected is not valid"
+ Vcl_Consts_SDeviceOnPort, L"%s on %s"
+ Vcl_Consts_SGroupIndexTooLow, L"GroupIndex cannot be less than a previous menu item's GroupIndex"
+ Vcl_Consts_SOutOfResources, L"Out of system resources"
+ Vcl_Consts_SNoCanvasHandle, L"Canvas does not allow drawing"
+ Vcl_Consts_SInvalidTextFormatFlag, L"Text format flag '%s' not supported"
+ Vcl_Consts_SInvalidFrameIndex, L"Invalid image frame index %d: there are %d frames (0-%d)"
+ Vcl_Consts_SInvalidImageSize, L"Invalid image size"
+ Vcl_Consts_SInvalidImageList, L"Invalid ImageList"
+ Vcl_Consts_SReplaceImage, L"Unable to Replace Image"
+ Vcl_Consts_SInsertImage, L"Unable to Insert Image"
+ Vcl_Consts_SImageIndexError, L"Invalid ImageList Index"
+ Vcl_Consts_SImageReadFail, L"Failed to read ImageList data from stream"
+ Vcl_Consts_SImageWriteFail, L"Failed to write ImageList data to stream"
+ Vcl_Consts_SWindowDCError, L"Error creating window device context"
+ Vcl_Consts_SWindowClass, L"Error creating window class"
+ Vcl_Consts_SCannotFocus, L"Cannot focus a disabled or invisible window"
+ Vcl_Consts_SParentRequired, L"Control '%s' has no parent window"
+ Vcl_Consts_SControlPath, L". Path:\r\n%s"
+ System_RTLConsts_sObserverNoSinglecastFound, L"No single cast observer with ID %d was added to the observer collection"
+ System_RTLConsts_sObserverNoMulticastFound, L"No multi cast observer with ID %d was added to the observer collection"
+ System_RTLConsts_sObserverNotAvailable, L"Observer is not available"
+ System_RTLConsts_sMustWaitOnOneEvent, L"Must wait on at least one event"
+ System_RTLConsts_sBeginInvokeDestroying, L"Cannot call BeginInvoke on a TComponent in the process of destruction"
+ Vcl_Consts_SInvalidBitmap, L"Bitmap image is not valid"
+ Vcl_Consts_SInvalidIcon, L"Icon image is not valid"
+ Vcl_Consts_SInvalidMetafile, L"Metafile is not valid"
+ Vcl_Consts_SInvalidPixelFormat, L"Invalid pixel format"
+ Vcl_Consts_SInvalidImage, L"Invalid image"
+ Vcl_Consts_SScanLine, L"Scan line index out of range"
+ Vcl_Consts_SChangeIconSize, L"Cannot change the size of an icon"
+ Vcl_Consts_SChangeWicSize, L"Cannot change the size of a WIC Image"
+ Vcl_Consts_SUnknownExtension, L"Unknown picture file extension (.%s)"
+ Vcl_Consts_SUnknownClipboardFormat, L"Unsupported clipboard format"
+ Vcl_Consts_SUnknownStreamFormat, L"Unsupported stream format"
+ System_RTLConsts_SWindowsXP, L"Windows XP"
+ System_RTLConsts_SWindowsServer2003, L"Windows Server 2003"
+ System_RTLConsts_SWindowsServer2003R2, L"Windows Server 2003 R2"
+ System_RTLConsts_SWindowsServer2012, L"Windows Server 2012"
+ System_RTLConsts_SWindowsServer2012R2, L"Windows Server 2012 R2"
+ System_RTLConsts_SWindowsServer2016, L"Windows Server 2016"
+ System_RTLConsts_SWindowsServer2019, L"Windows Server 2019"
+ System_RTLConsts_SWindowsServer2022, L"Windows Server 2022"
+ System_RTLConsts_SWindows8, L"Windows 8"
+ System_RTLConsts_SWindows8Point1, L"Windows 8.1"
+ System_RTLConsts_SWindows10, L"Windows 10"
+ System_RTLConsts_SWindows11, L"Windows 11"
+ System_RTLConsts_SWinRTInstanceError, L"Cannot create instance of class %s"
+ System_RTLConsts_sObserverUnsupported, L"Observer is not supported"
+ System_RTLConsts_sObserverMultipleSingleCast, L"Cannot have multiple single cast observers added to the observers collection"
+ System_RTLConsts_sObserverNoInterface, L"The object does not implement the observer interface"
+ System_RTLConsts_SNonPublicType, L"Type '%s' is not declared in the interface section of a unit"
+ System_RTLConsts_SByRefArgMismatch, L"VAR and OUT arguments must match parameter type exactly"
+ System_RTLConsts_SPropIsReadOnly, L"Property '%s' is read-only"
+ System_RTLConsts_SPropIsWriteOnly, L"Property '%s' is write-only"
+ System_RTLConsts_SInvalidRttiDestroy, L"RTTI objects cannot be manually destroyed by application code"
+ System_RTLConsts_SServiceNotFound, L"Specified Login Credential Service not found"
+ System_RTLConsts_SVersionStr, L"%s (Version %d.%d, Build %d, %5:s)"
+ System_RTLConsts_SSPVersionStr, L"%s Service Pack %4:d (Version %1:d.%2:d, Build %3:d, %5:s)"
+ System_RTLConsts_SVersion32, L"32-bit Edition"
+ System_RTLConsts_SVersion64, L"64-bit Edition"
+ System_RTLConsts_SWindows, L"Windows"
+ System_RTLConsts_SWindowsVista, L"Windows Vista"
+ System_RTLConsts_SWindowsServer2008, L"Windows Server 2008"
+ System_RTLConsts_SWindows7, L"Windows 7"
+ System_RTLConsts_SWindowsServer2008R2, L"Windows Server 2008 R2"
+ System_RTLConsts_SWindows2000, L"Windows 2000"
+ System_RTLConsts_sInvalidTimespanFormat, L"Invalid Timespan format"
+ System_RTLConsts_sTimespanElementTooLong, L"Timespan element too long"
+ System_RTLConsts_SNoContext, L"No context-sensitive help installed"
+ System_RTLConsts_SNoContextFound, L"No help found for context %d"
+ System_RTLConsts_SNoIndex, L"Unable to open Index"
+ System_RTLConsts_SNoSearch, L"Unable to open Search"
+ System_RTLConsts_SNoTableOfContents, L"Unable to find a Table of Contents"
+ System_RTLConsts_SNoTopics, L"No topic-based help system installed"
+ System_RTLConsts_SNothingFound, L"No help found for %s"
+ System_RTLConsts_SArgumentOutOfRange, L"Argument out of range"
+ System_RTLConsts_SArgumentNil, L"Argument must not be nil"
+ System_RTLConsts_SGenericItemNotFound, L"Item not found"
+ System_RTLConsts_SGenericDuplicateItem, L"Duplicates not allowed"
+ System_RTLConsts_SInsufficientRtti, L"Insufficient RTTI available to support this operation"
+ System_RTLConsts_SParameterCountMismatch, L"Parameter count mismatch"
+ System_RTLConsts_SParameterCountExceeded, L"Parameter count exceeded"
+ System_RTLConsts_SThreadExternalSetReturnValue, L"Cannot call SetReturnValue on an externally create thread"
+ System_RTLConsts_SParamIsNil, L"Parameter %s cannot be nil"
+ System_RTLConsts_SParamIsNegative, L"Parameter %s cannot be a negative value"
+ System_RTLConsts_SInputBufferExceed, L"Input buffer exceeded for %s = %d, %s = %d"
+ System_RTLConsts_SInvalidCharsInPath, L"Invalid characters in path"
+ System_RTLConsts_hNoFilterViewer, L"No help viewer that supports filters"
+ System_RTLConsts_sArgumentInvalid, L"Invalid argument"
+ System_RTLConsts_sInvalidStringAndObjectArrays, L"Length of Strings and Objects arrays must be equal"
+ System_RTLConsts_sSameArrays, L"Source and Destination arrays must not be the same"
+ System_RTLConsts_sNoConstruct, L"Class %s is not intended to be constructed"
+ System_RTLConsts_sInvalidTimeoutValue, L"Invalid Timeout value: %s"
+ System_RTLConsts_sSpinCountOutOfRange, L"SpinCount out of range. Must be between 0 and %d"
+ System_RTLConsts_sTimespanTooLong, L"Timespan too long"
+ System_RTLConsts_sInvalidTimespanDuration, L"The duration cannot be returned because the absolute value exceeds the value of TTimeSpan.MaxValue"
+ System_RTLConsts_sTimespanValueCannotBeNan, L"Value cannot be NaN"
+ System_RTLConsts_sCannotNegateTimespan, L"Negating the minimum value of a Timespan is invalid"
+ System_RTLConsts_SReadOnlyProperty, L"Property is read-only"
+ System_RTLConsts_SRegCreateFailed, L"Failed to create key %s"
+ System_RTLConsts_SRegGetDataFailed, L"Failed to get data for '%s'"
+ System_RTLConsts_SRegSetDataFailed, L"Failed to set data for '%s'"
+ System_RTLConsts_SResNotFound, L"Resource %s not found"
+ System_RTLConsts_SSeekNotImplemented, L"%s.Seek not implemented"
+ System_RTLConsts_SSortedListError, L"Operation not allowed on sorted list"
+ System_RTLConsts_SUnknownGroup, L"%s not in a class registration group"
+ System_RTLConsts_SUnknownProperty, L"Property %s does not exist"
+ System_RTLConsts_SWriteError, L"Stream write error"
+ System_RTLConsts_SThreadCreateError, L"Thread creation error: %s"
+ System_RTLConsts_SThreadError, L"Thread Error: %s (%d)"
+ System_RTLConsts_SThreadExternalTerminate, L"Cannot terminate an externally created thread"
+ System_RTLConsts_SThreadExternalWait, L"Cannot wait for an externally created thread"
+ System_RTLConsts_SThreadStartError, L"Cannot call Start on a running or suspended thread"
+ System_RTLConsts_SThreadExternalCheckTerminated, L"Cannot call CheckTerminated on an externally created thread"
+ System_RTLConsts_SFOpenErrorEx, L"Cannot open file \"%s\". %s"
+ System_RTLConsts_SInvalidImage, L"Invalid stream format"
+ System_RTLConsts_SInvalidName, L"''%s'' is not a valid component name"
+ System_RTLConsts_SInvalidProperty, L"Invalid property value"
+ System_RTLConsts_SInvalidPropertyPath, L"Invalid property path"
+ System_RTLConsts_SInvalidPropertyValue, L"Invalid property value"
+ System_RTLConsts_SInvalidRegType, L"Invalid data type for '%s'"
+ System_RTLConsts_SListCapacityError, L"List capacity out of bounds (%d)"
+ System_RTLConsts_SListCountError, L"List count out of bounds (%d)"
+ System_RTLConsts_SListIndexError, L"List index out of bounds (%d)"
+ System_RTLConsts_SListIndexErrorRangeReason, L". %s range is 0..%d"
+ System_RTLConsts_SListIndexErrorEmptyReason, L". %s is empty"
+ System_RTLConsts_SMemoryStreamError, L"Out of memory while expanding memory stream"
+ System_RTLConsts_SNoComSupport, L"%s has not been registered as a COM class"
+ System_RTLConsts_SPropertyException, L"Error reading %s%s%s: %s"
+ System_RTLConsts_SReadError, L"Stream read error"
+ System_SysConst_SInvalidDestinationIndex, L"Invalid destination index (%d)"
+ System_SysConst_SInvalidCodePage, L"Invalid code page"
+ System_SysConst_SInvalidEncodingName, L"Invalid encoding name"
+ System_SysConst_SNoMappingForUnicodeCharacter, L"No mapping for the Unicode character exists in the target multi-byte code page"
+ System_SysConst_SInvalidStringBaseIndex, L"Invalid StringBaseIndex"
+ System_RTLConsts_SAncestorNotFound, L"Ancestor for '%s' not found"
+ System_RTLConsts_SAssignError, L"Cannot assign a %s to a %s"
+ System_RTLConsts_SBitsIndexError, L"Bits index out of range"
+ System_RTLConsts_SCantWriteResourceStreamError, L"Can't write to a read-only resource stream"
+ System_RTLConsts_SCheckSynchronizeError, L"CheckSynchronize called from thread $%x, which is NOT the main thread"
+ System_RTLConsts_SClassNotFound, L"Class %s not found"
+ System_RTLConsts_SDuplicateClass, L"A class named %s already exists"
+ System_RTLConsts_SDuplicateItem, L"List does not allow duplicates ($0%x)"
+ System_RTLConsts_SDuplicateName, L"A component named %s already exists"
+ System_RTLConsts_SDuplicateString, L"String list does not allow duplicates"
+ System_RTLConsts_SFCreateErrorEx, L"Cannot create file \"%s\". %s"
+ System_SysConst_SShortDayNameWed, L"Wed"
+ System_SysConst_SShortDayNameThu, L"Thu"
+ System_SysConst_SShortDayNameFri, L"Fri"
+ System_SysConst_SShortDayNameSat, L"Sat"
+ System_SysConst_SLongDayNameSun, L"Sunday"
+ System_SysConst_SLongDayNameMon, L"Monday"
+ System_SysConst_SLongDayNameTue, L"Tuesday"
+ System_SysConst_SLongDayNameWed, L"Wednesday"
+ System_SysConst_SLongDayNameThu, L"Thursday"
+ System_SysConst_SLongDayNameFri, L"Friday"
+ System_SysConst_SLongDayNameSat, L"Saturday"
+ System_SysConst_SInvalidSourceArray, L"Invalid source array"
+ System_SysConst_SInvalidDestinationArray, L"Invalid destination array"
+ System_SysConst_SCharIndexOutOfBounds, L"Character index out of bounds (%d)"
+ System_SysConst_SByteIndexOutOfBounds, L"Start index out of bounds (%d)"
+ System_SysConst_SInvalidCharCount, L"Invalid count (%d)"
+ System_SysConst_SShortMonthNameDec, L"Dec"
+ System_SysConst_SLongMonthNameJan, L"January"
+ System_SysConst_SLongMonthNameFeb, L"February"
+ System_SysConst_SLongMonthNameMar, L"March"
+ System_SysConst_SLongMonthNameApr, L"April"
+ System_SysConst_SLongMonthNameMay, L"May"
+ System_SysConst_SLongMonthNameJun, L"June"
+ System_SysConst_SLongMonthNameJul, L"July"
+ System_SysConst_SLongMonthNameAug, L"August"
+ System_SysConst_SLongMonthNameSep, L"September"
+ System_SysConst_SLongMonthNameOct, L"October"
+ System_SysConst_SLongMonthNameNov, L"November"
+ System_SysConst_SLongMonthNameDec, L"December"
+ System_SysConst_SShortDayNameSun, L"Sun"
+ System_SysConst_SShortDayNameMon, L"Mon"
+ System_SysConst_SShortDayNameTue, L"Tue"
+ System_SysConst_SAssertError, L"%s (%s, line %d)"
+ System_SysConst_SAbstractError, L"Abstract Error"
+ System_SysConst_SModuleAccessViolation, L"Access violation at address %p in module '%s' (offset %x). %s of address %p"
+ System_SysConst_SOSError, L"System Error. Code: %d.\r\n%s%s"
+ System_SysConst_SUnkOSError, L"A call to an OS function failed"
+ System_SysConst_SShortMonthNameJan, L"Jan"
+ System_SysConst_SShortMonthNameFeb, L"Feb"
+ System_SysConst_SShortMonthNameMar, L"Mar"
+ System_SysConst_SShortMonthNameApr, L"Apr"
+ System_SysConst_SShortMonthNameMay, L"May"
+ System_SysConst_SShortMonthNameJun, L"Jun"
+ System_SysConst_SShortMonthNameJul, L"Jul"
+ System_SysConst_SShortMonthNameAug, L"Aug"
+ System_SysConst_SShortMonthNameSep, L"Sep"
+ System_SysConst_SShortMonthNameOct, L"Oct"
+ System_SysConst_SShortMonthNameNov, L"Nov"
+ System_SysConst_SVarTypeTooManyCustom, L"Too many custom variant types have been registered"
+ System_SysConst_SVarTypeCouldNotConvert, L"Could not convert variant of type (%s) into type (%s)"
+ System_SysConst_SVarTypeConvertOverflow, L"Overflow while converting variant of type (%s) into type (%s)"
+ System_SysConst_SVarOverflow, L"Variant overflow"
+ System_SysConst_SVarInvalid, L"Invalid argument"
+ System_SysConst_SVarBadType, L"Invalid variant type"
+ System_SysConst_SVarNotImplemented, L"Operation not supported"
+ System_SysConst_SVarUnexpected, L"Unexpected variant error"
+ System_SysConst_SExternalException, L"External exception %x"
+ System_SysConst_SAssertionFailed, L"Assertion failed"
+ System_SysConst_SIntfCastError, L"Interface not supported"
+ System_SysConst_SSafecallException, L"Exception in safecall method"
+ System_SysConst_SMonitorLockException, L"Object lock not owned"
+ System_SysConst_SNoMonitorSupportException, L"Monitor support function not initialized"
+ System_SysConst_SNotImplemented, L"Feature not implemented"
+ System_SysConst_SObjectDisposed, L"Method called on disposed object"
+ System_SysConst_SArgumentMissing, L"No argument for format '%s'"
+ System_SysConst_SDispatchError, L"Variant method calls not supported"
+ System_SysConst_SReadAccess, L"Read"
+ System_SysConst_SWriteAccess, L"Write"
+ System_SysConst_SExecuteAccess, L"Execution"
+ System_SysConst_SInvalidAccess, L"Invalid access"
+ System_SysConst_SVarArrayCreate, L"Error creating variant or safe array"
+ System_SysConst_SVarArrayBounds, L"Variant or safe array index out of bounds"
+ System_SysConst_SVarArrayLocked, L"Variant or safe array is locked"
+ System_SysConst_SInvalidVarCast, L"Invalid variant type conversion"
+ System_SysConst_SInvalidVarOp, L"Invalid variant operation"
+ System_SysConst_SInvalidVarNullOp, L"Invalid NULL variant operation"
+ System_SysConst_SInvalidVarOpWithHResultWithPrefix, L"Invalid variant operation (%s%.8x)\n%s"
+ System_SysConst_SVarTypeOutOfRangeWithPrefix, L"Custom variant type (%s%.4x) is out of range"
+ System_SysConst_SVarTypeAlreadyUsedWithPrefix, L"Custom variant type (%s%.4x) already used by %s"
+ System_SysConst_SVarTypeNotUsableWithPrefix, L"Custom variant type (%s%.4x) is not usable"
+ System_SysConst_SRangeError, L"Range check error"
+ System_SysConst_SIntOverflow, L"Integer overflow"
+ System_SysConst_SInvalidOp, L"Invalid floating point operation"
+ System_SysConst_SZeroDivide, L"Floating point division by zero"
+ System_SysConst_SOverflow, L"Floating point overflow"
+ System_SysConst_SUnderflow, L"Floating point underflow"
+ System_SysConst_SInvalidPointer, L"Invalid pointer operation"
+ System_SysConst_SInvalidCast, L"Invalid class typecast"
+ System_SysConst_SAccessViolationArg3, L"Access violation at address %p. %s of address %p"
+ System_SysConst_SAccessViolationNoArg, L"Access violation"
+ System_SysConst_SStackOverflow, L"Stack overflow"
+ System_SysConst_SControlC, L"Control-C hit"
+ System_SysConst_SPrivilege, L"Privileged instruction"
+ System_SysConst_SException, L"Exception %s in module %s at %p.\r\n%s%s\r\n"
+ System_SysConst_SExceptTitle, L"Application Error"
+ System_SysConst_SInvalidFormat, L"Format '%s' invalid or incompatible with argument"
+ System_SysConst_SUnknown, L""
+ System_SysConst_SInvalidInteger, L"'%s' is not a valid integer value"
+ System_SysConst_SInvalidTimeStamp, L"'%d.%d' is not a valid timestamp"
+ System_SysConst_SInvalidGUID, L"'%s' is not a valid GUID value"
+ System_SysConst_STimeEncodeError, L"Invalid argument to time encode"
+ System_SysConst_SDateEncodeError, L"Invalid argument to date encode"
+ System_SysConst_SOutOfMemory, L"Out of memory"
+ System_SysConst_SInOutError, L"I/O error %d"
+ System_SysConst_SFileNotFound, L"File not found"
+ System_SysConst_SInvalidUnknownFilename, L"Invalid filename"
+ System_SysConst_STooManyOpenFiles, L"Too many open files"
+ System_SysConst_SAccessDenied, L"File access denied"
+ System_SysConst_SEndOfFile, L"Read beyond end of file"
+ System_SysConst_SDiskFull, L"Disk full"
+ System_SysConst_SInvalidInput, L"Invalid numeric input"
+ System_SysConst_SDivByZero, L"Division by zero"
+END
+
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win64\release\Controls.res */
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win64\release\Dialogs.res */
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win64\release\Buttons.res */
+/* c:\program files (x86)\embarcadero\studio\23.0\lib\Win64\release\SPIN.RES */
+/* D:\_Delphi\_Library\Netcom7\Demos\UDP\ncUDPSockets\Server\ufrmMain.dfm */
+/* D:\_Delphi\_Library\Netcom7\Demos\UDP\ncUDPSockets\Server\Server.res */
+/* D:\_Delphi\_Library\Netcom7\Demos\UDP\ncUDPSockets\Server\Server.drf */
diff --git a/Demos/SimpleSockets/Srv/Server.dsk b/Demos/UDP/ncUDPSockets/Server/Server.dsk
similarity index 94%
rename from Demos/SimpleSockets/Srv/Server.dsk
rename to Demos/UDP/ncUDPSockets/Server/Server.dsk
index 1fc1133..78670b2 100644
--- a/Demos/SimpleSockets/Srv/Server.dsk
+++ b/Demos/UDP/ncUDPSockets/Server/Server.dsk
@@ -1,768 +1,768 @@
-[Closed Files]
-File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,1081,1,1097,0,0,,
-File_1=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.Forms.pas',0,1,1,15,10,0,0,{{1755,4}
-File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.StdCtrls.pas',0,1,1,6,10,0,0,{{1657,4}
-File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,1,6,10,0,0,,
-File_4=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\RTL\SYS\System.SysUtils.pas',0,1,1,6,16,0,0,,
-File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Messages.pas',0,1,1,6,19,0,0,,
-File_6=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncSockets.pas',0,1,1241,1,1260,0,0,,{1
-File_7=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncSources.pas',0,1,738,3,762,0,0,,{1
-File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPIHelpers.pas',0,1,1,1,5,0,0,,{1
-File_9=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncThreads.pas',0,1,88,13,95,0,0,,
-
-[Modules]
-Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas
-Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dproj
-Count=2
-EditWindowCount=1
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas]
-ModuleType=TSourceModule
-
-[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dproj]
-ModuleType=TBaseProject
-
-[EditWindow0]
-ViewCount=2
-CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas
-View0=0
-View1=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=9900
-Height=8837
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=9900
-ClientHeight=8837
-DockedToMainForm=1
-BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
-TopPanelSize=0
-LeftPanelSize=1894
-LeftPanelClients=PropertyInspector,DockSite3
-LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
-RightPanelSize=1525
-RightPanelClients=DockSite2,DockSite4
-RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
-BottomPanelSize=0
-BottomPanelClients=DockSite1,MessageView
-BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
-BottomMiddlePanelSize=0
-BottomMiddlePanelClients=DockSite0,GraphDrawingModel
-BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
-
-[View0]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dpr
-CursorX=20
-CursorY=5
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dpr
-
-[View1]
-CustomEditViewType=TEditView
-Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas
-CursorX=11
-CursorY=6
-TopLine=1
-LeftCol=1
-Elisions=
-Bookmarks=
-EditViewName=Borland.FormDesignerView
-
-[UndockedDesigner]
-Count=0
-
-[Watches]
-Count=0
-
-[WatchWindow]
-WatchColumnWidth=120
-WatchShowColumnHeaders=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=13600
-Dockable=1
-StayOnTop=0
-
-[Breakpoints]
-Count=0
-
-[EmbarcaderoWin32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoWin64Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
-Count=0
-
-[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
-Count=0
-
-[Main Window]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=0
-State=2
-Left=144
-Top=279
-Width=8931
-Height=8523
-MaxLeft=-6
-MaxTop=-12
-MaxWidth=8931
-MaxHeight=8523
-ClientWidth=10025
-ClientHeight=9744
-BottomPanelSize=8444
-BottomPanelClients=EditWindow0
-BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
-
-[ProjectManager]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5895
-LRDockWidth=2350
-Dockable=1
-StayOnTop=0
-
-[MessageView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2769
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2769
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=2769
-Dockable=1
-StayOnTop=0
-
-[ToolForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=7151
-LRDockWidth=2000
-Dockable=1
-StayOnTop=0
-
-[ClipboardHistory]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2338
-Height=5174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2262
-ClientHeight=4733
-TBDockHeight=5174
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-
-[PropertyInspector]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=358
-Width=1894
-Height=4674
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=4674
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-SplitPos=111
-
-[PropInspDesignerSelection]
-ArrangeBy=Name
-SelectedItem=Action,
-ExpandedItems=LiveBindings=0,"LiveBindings Designer=0",Margins=0,ActiveControl=0,Anchors=0,BorderIcons=0
-
-[frmDesignPreview]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=5953
-LRDockWidth=2512
-Dockable=1
-StayOnTop=0
-
-[TemplateView]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=275
-Height=360
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=275
-ClientHeight=360
-TBDockHeight=360
-LRDockWidth=275
-Dockable=1
-StayOnTop=0
-Name=120
-Description=334
-filter=1
-
-[DebugLogView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=407
-LRDockWidth=4950
-Dockable=1
-StayOnTop=0
-
-[ThreadStatusWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=209
-LRDockWidth=7406
-Dockable=1
-StayOnTop=0
-Column0Width=145
-Column1Width=100
-Column2Width=115
-Column3Width=252
-
-[LocalVarsWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1535
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[CallStackWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=2070
-LRDockWidth=3481
-Dockable=1
-StayOnTop=0
-
-[PatchForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2500
-LRDockWidth=3400
-Dockable=1
-StayOnTop=0
-
-[FindReferencsForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=2314
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[RefactoringForm]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1151
-TBDockHeight=3209
-LRDockWidth=2825
-Dockable=1
-StayOnTop=0
-
-[ToDo List]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1140
-TBDockHeight=1151
-LRDockWidth=3675
-Dockable=1
-StayOnTop=0
-Column0Width=314
-Column1Width=30
-Column2Width=150
-Column3Width=172
-Column4Width=129
-SortOrder=4
-ShowHints=1
-ShowChecked=1
-
-[DataExplorerContainer]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=7150
-Dockable=1
-StayOnTop=0
-
-[GraphDrawingModel]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2856
-Height=3209
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2856
-ClientHeight=3209
-TBDockHeight=3209
-LRDockWidth=2856
-Dockable=1
-StayOnTop=0
-
-[ClassBrowserTool]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=-318
-Top=-363
-Width=1850
-Height=3140
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1850
-ClientHeight=3140
-TBDockHeight=3140
-LRDockWidth=1850
-Dockable=1
-StayOnTop=0
-
-[MetricsView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[QAView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=2338
-Height=1163
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1163
-TBDockHeight=4837
-LRDockWidth=3562
-Dockable=1
-StayOnTop=0
-
-[BreakpointWindow]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=3825
-Height=1093
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1093
-TBDockHeight=1547
-LRDockWidth=8744
-Dockable=1
-StayOnTop=0
-Column0Width=200
-Column1Width=75
-Column2Width=200
-Column3Width=200
-Column4Width=200
-Column5Width=75
-Column6Width=75
-
-[StructureView]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=3674
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-
-[fmGrepResults]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=2575
-Height=4372
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=2475
-ClientHeight=3919
-TBDockHeight=4372
-LRDockWidth=2575
-Dockable=1
-StayOnTop=0
-
-[ModelViewTool]
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=0
-Width=1525
-Height=4151
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4151
-TBDockHeight=4884
-LRDockWidth=5306
-Dockable=1
-StayOnTop=0
-
-[BorlandEditorCodeExplorer@EditWindow0]
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=0
-State=0
-Left=0
-Top=0
-Width=1825
-Height=6174
-MaxLeft=-6
-MaxTop=-12
-ClientWidth=1725
-ClientHeight=5721
-TBDockHeight=6174
-LRDockWidth=1825
-Dockable=1
-StayOnTop=0
-
-[DockHosts]
-DockHostCount=5
-
-[DockSite0]
-HostDockSite=DockBottomCenterPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=2338
-Height=1477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=2338
-ClientHeight=1477
-TBDockHeight=1477
-LRDockWidth=2338
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=RefactoringForm
-TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
-
-[DockSite1]
-HostDockSite=DockBottomPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=0
-Docked=1
-State=0
-Left=8
-Top=8
-Width=3825
-Height=1419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=3825
-ClientHeight=1419
-TBDockHeight=1419
-LRDockWidth=3825
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=DebugLogView
-TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
-
-[DockSite2]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1525
-Height=4477
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=4477
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ProjectManager
-TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
-
-[DockSite3]
-HostDockSite=DockLeftPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=28
-Width=1894
-Height=3419
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1894
-ClientHeight=3419
-TBDockHeight=9012
-LRDockWidth=1894
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=StructureView
-TabDockClients=StructureView,ClassBrowserTool
-
-[DockSite4]
-HostDockSite=DockRightPanel
-DockSiteType=1
-PercentageSizes=1
-Create=1
-Visible=1
-Docked=1
-State=0
-Left=0
-Top=449
-Width=1525
-Height=3616
-MaxLeft=-1
-MaxTop=-1
-ClientWidth=1525
-ClientHeight=3616
-TBDockHeight=9012
-LRDockWidth=1525
-Dockable=1
-StayOnTop=0
-TabPosition=1
-ActiveTabID=ToolForm
-TabDockClients=ToolForm,TemplateView
-
+[Closed Files]
+File_0=TSourceModule,'C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSockets.pas',0,1,1081,1,1097,0,0,,
+File_1=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.Forms.pas',0,1,1,15,10,0,0,{{1755,4}
+File_2=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\VCL\Vcl.StdCtrls.pas',0,1,1,6,10,0,0,{{1657,4}
+File_3=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\common\System.Classes.pas',0,1,1,6,10,0,0,,
+File_4=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\SOURCE\RTL\SYS\System.SysUtils.pas',0,1,1,6,16,0,0,,
+File_5=TSourceModule,'c:\program files (x86)\embarcadero\studio\20.0\source\rtl\win\Winapi.Messages.pas',0,1,1,6,19,0,0,,
+File_6=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncSockets.pas',0,1,1241,1,1260,0,0,,{1
+File_7=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncSources.pas',0,1,738,3,762,0,0,,{1
+File_8=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\DirectPanel\dpDXAPIHelpers.pas',0,1,1,1,5,0,0,,{1
+File_9=TSourceModule,'C:\Users\BDemos\Documents\RAD Studio\Components\NetCom7\Source\ncThreads.pas',0,1,88,13,95,0,0,,
+
+[Modules]
+Module0=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas
+Module1=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dproj
+Count=2
+EditWindowCount=1
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas]
+ModuleType=TSourceModule
+
+[C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dproj]
+ModuleType=TBaseProject
+
+[EditWindow0]
+ViewCount=2
+CurrentEditView=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas
+View0=0
+View1=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=9900
+Height=8837
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=9900
+ClientHeight=8837
+DockedToMainForm=1
+BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0
+TopPanelSize=0
+LeftPanelSize=1894
+LeftPanelClients=PropertyInspector,DockSite3
+LeftPanelData=000008000101000000008E120000000000000166070000000000000100000000530E000009000000446F636B53697465330100000000FC2000001100000050726F7065727479496E73706563746F72FFFFFFFF
+RightPanelSize=1525
+RightPanelClients=DockSite2,DockSite4
+RightPanelData=000008000101000000008E1200000000000001F50500000000000001000000004612000009000000446F636B53697465320100000000FC20000009000000446F636B5369746534FFFFFFFF
+BottomPanelSize=0
+BottomPanelClients=DockSite1,MessageView
+BottomPanelData=0000080001020200000009000000446F636B53697465310F0000004D65737361676556696577466F726D1534000000000000022A06000000000000FFFFFFFF
+BottomMiddlePanelSize=0
+BottomMiddlePanelClients=DockSite0,GraphDrawingModel
+BottomMiddelPanelData=0000080001020200000009000000446F636B536974653010000000477261706844726177696E67566965779A1D00000000000002F206000000000000FFFFFFFF
+
+[View0]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dpr
+CursorX=20
+CursorY=5
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\Server.dpr
+
+[View1]
+CustomEditViewType=TEditView
+Module=C:\Users\Programmer\Documents\Development\Components\NetCom7\Demos\SimpleSockets\Srv\ufrmMain.pas
+CursorX=11
+CursorY=6
+TopLine=1
+LeftCol=1
+Elisions=
+Bookmarks=
+EditViewName=Borland.FormDesignerView
+
+[UndockedDesigner]
+Count=0
+
+[Watches]
+Count=0
+
+[WatchWindow]
+WatchColumnWidth=120
+WatchShowColumnHeaders=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=13600
+Dockable=1
+StayOnTop=0
+
+[Breakpoints]
+Count=0
+
+[EmbarcaderoWin32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoWin64Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid32Debugger_AddressBreakpoints]
+Count=0
+
+[EmbarcaderoAndroid64Debugger_AddressBreakpoints]
+Count=0
+
+[Main Window]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=0
+State=2
+Left=144
+Top=279
+Width=8931
+Height=8523
+MaxLeft=-6
+MaxTop=-12
+MaxWidth=8931
+MaxHeight=8523
+ClientWidth=10025
+ClientHeight=9744
+BottomPanelSize=8444
+BottomPanelClients=EditWindow0
+BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF
+
+[ProjectManager]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5895
+LRDockWidth=2350
+Dockable=1
+StayOnTop=0
+
+[MessageView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2769
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2769
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=2769
+Dockable=1
+StayOnTop=0
+
+[ToolForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=7151
+LRDockWidth=2000
+Dockable=1
+StayOnTop=0
+
+[ClipboardHistory]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2338
+Height=5174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2262
+ClientHeight=4733
+TBDockHeight=5174
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+
+[PropertyInspector]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=358
+Width=1894
+Height=4674
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=4674
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+SplitPos=111
+
+[PropInspDesignerSelection]
+ArrangeBy=Name
+SelectedItem=Action,
+ExpandedItems=LiveBindings=0,"LiveBindings Designer=0",Margins=0,ActiveControl=0,Anchors=0,BorderIcons=0
+
+[frmDesignPreview]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=5953
+LRDockWidth=2512
+Dockable=1
+StayOnTop=0
+
+[TemplateView]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=275
+Height=360
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=275
+ClientHeight=360
+TBDockHeight=360
+LRDockWidth=275
+Dockable=1
+StayOnTop=0
+Name=120
+Description=334
+filter=1
+
+[DebugLogView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=407
+LRDockWidth=4950
+Dockable=1
+StayOnTop=0
+
+[ThreadStatusWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=209
+LRDockWidth=7406
+Dockable=1
+StayOnTop=0
+Column0Width=145
+Column1Width=100
+Column2Width=115
+Column3Width=252
+
+[LocalVarsWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1535
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[CallStackWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=2070
+LRDockWidth=3481
+Dockable=1
+StayOnTop=0
+
+[PatchForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2500
+LRDockWidth=3400
+Dockable=1
+StayOnTop=0
+
+[FindReferencsForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=2314
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[RefactoringForm]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1151
+TBDockHeight=3209
+LRDockWidth=2825
+Dockable=1
+StayOnTop=0
+
+[ToDo List]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1140
+TBDockHeight=1151
+LRDockWidth=3675
+Dockable=1
+StayOnTop=0
+Column0Width=314
+Column1Width=30
+Column2Width=150
+Column3Width=172
+Column4Width=129
+SortOrder=4
+ShowHints=1
+ShowChecked=1
+
+[DataExplorerContainer]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=7150
+Dockable=1
+StayOnTop=0
+
+[GraphDrawingModel]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2856
+Height=3209
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2856
+ClientHeight=3209
+TBDockHeight=3209
+LRDockWidth=2856
+Dockable=1
+StayOnTop=0
+
+[ClassBrowserTool]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=-318
+Top=-363
+Width=1850
+Height=3140
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1850
+ClientHeight=3140
+TBDockHeight=3140
+LRDockWidth=1850
+Dockable=1
+StayOnTop=0
+
+[MetricsView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[QAView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=2338
+Height=1163
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1163
+TBDockHeight=4837
+LRDockWidth=3562
+Dockable=1
+StayOnTop=0
+
+[BreakpointWindow]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=3825
+Height=1093
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1093
+TBDockHeight=1547
+LRDockWidth=8744
+Dockable=1
+StayOnTop=0
+Column0Width=200
+Column1Width=75
+Column2Width=200
+Column3Width=200
+Column4Width=200
+Column5Width=75
+Column6Width=75
+
+[StructureView]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=3674
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+
+[fmGrepResults]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=2575
+Height=4372
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=2475
+ClientHeight=3919
+TBDockHeight=4372
+LRDockWidth=2575
+Dockable=1
+StayOnTop=0
+
+[ModelViewTool]
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=0
+Width=1525
+Height=4151
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4151
+TBDockHeight=4884
+LRDockWidth=5306
+Dockable=1
+StayOnTop=0
+
+[BorlandEditorCodeExplorer@EditWindow0]
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=0
+State=0
+Left=0
+Top=0
+Width=1825
+Height=6174
+MaxLeft=-6
+MaxTop=-12
+ClientWidth=1725
+ClientHeight=5721
+TBDockHeight=6174
+LRDockWidth=1825
+Dockable=1
+StayOnTop=0
+
+[DockHosts]
+DockHostCount=5
+
+[DockSite0]
+HostDockSite=DockBottomCenterPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=2338
+Height=1477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=2338
+ClientHeight=1477
+TBDockHeight=1477
+LRDockWidth=2338
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=RefactoringForm
+TabDockClients=RefactoringForm,PatchForm,FindReferencsForm,ToDo List,MetricsView,QAView
+
+[DockSite1]
+HostDockSite=DockBottomPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=0
+Docked=1
+State=0
+Left=8
+Top=8
+Width=3825
+Height=1419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=3825
+ClientHeight=1419
+TBDockHeight=1419
+LRDockWidth=3825
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=DebugLogView
+TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow
+
+[DockSite2]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1525
+Height=4477
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=4477
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ProjectManager
+TabDockClients=ProjectManager,ModelViewTool,DataExplorerContainer,frmDesignPreview
+
+[DockSite3]
+HostDockSite=DockLeftPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=28
+Width=1894
+Height=3419
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1894
+ClientHeight=3419
+TBDockHeight=9012
+LRDockWidth=1894
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=StructureView
+TabDockClients=StructureView,ClassBrowserTool
+
+[DockSite4]
+HostDockSite=DockRightPanel
+DockSiteType=1
+PercentageSizes=1
+Create=1
+Visible=1
+Docked=1
+State=0
+Left=0
+Top=449
+Width=1525
+Height=3616
+MaxLeft=-1
+MaxTop=-1
+ClientWidth=1525
+ClientHeight=3616
+TBDockHeight=9012
+LRDockWidth=1525
+Dockable=1
+StayOnTop=0
+TabPosition=1
+ActiveTabID=ToolForm
+TabDockClients=ToolForm,TemplateView
+
diff --git a/Demos/UDP/ncUDPSockets/Server/Server.identcache b/Demos/UDP/ncUDPSockets/Server/Server.identcache
new file mode 100644
index 0000000..3ab5b2f
Binary files /dev/null and b/Demos/UDP/ncUDPSockets/Server/Server.identcache differ
diff --git a/Demos/UDP/ncUDPSockets/Server/Server.res b/Demos/UDP/ncUDPSockets/Server/Server.res
new file mode 100644
index 0000000..0af1ebd
Binary files /dev/null and b/Demos/UDP/ncUDPSockets/Server/Server.res differ
diff --git a/Demos/SimpleSockets/Srv/Server.skincfg b/Demos/UDP/ncUDPSockets/Server/Server.skincfg
similarity index 94%
rename from Demos/SimpleSockets/Srv/Server.skincfg
rename to Demos/UDP/ncUDPSockets/Server/Server.skincfg
index 9e7a05b..0f00ce7 100644
--- a/Demos/SimpleSockets/Srv/Server.skincfg
+++ b/Demos/UDP/ncUDPSockets/Server/Server.skincfg
@@ -1,33 +1,33 @@
-[ExpressSkins]
-Default=1
-ShowNotifications=1
-Enabled=1
-dxSkinBlack=1
-dxSkinBlue=0
-dxSkinCaramel=0
-dxSkinCoffee=0
-dxSkinDarkRoom=0
-dxSkinDarkSide=1
-dxSkinFoggy=0
-dxSkinGlassOceans=0
-dxSkiniMaginary=0
-dxSkinLilian=0
-dxSkinLiquidSky=0
-dxSkinLondonLiquidSky=0
-dxSkinMcSkin=0
-dxSkinMoneyTwins=0
-dxSkinOffice2007Black=1
-dxSkinOffice2007Blue=0
-dxSkinOffice2007Green=0
-dxSkinOffice2007Pink=0
-dxSkinOffice2007Silver=1
-dxSkinPumpkin=0
-dxSkinSeven=0
-dxSkinSharp=0
-dxSkinSilver=0
-dxSkinSpringTime=0
-dxSkinStardust=0
-dxSkinSummer2008=0
-dxSkinsDefaultPainters=0
-dxSkinValentine=0
-dxSkinXmas2008Blue=0
+[ExpressSkins]
+Default=1
+ShowNotifications=1
+Enabled=1
+dxSkinBlack=1
+dxSkinBlue=0
+dxSkinCaramel=0
+dxSkinCoffee=0
+dxSkinDarkRoom=0
+dxSkinDarkSide=1
+dxSkinFoggy=0
+dxSkinGlassOceans=0
+dxSkiniMaginary=0
+dxSkinLilian=0
+dxSkinLiquidSky=0
+dxSkinLondonLiquidSky=0
+dxSkinMcSkin=0
+dxSkinMoneyTwins=0
+dxSkinOffice2007Black=1
+dxSkinOffice2007Blue=0
+dxSkinOffice2007Green=0
+dxSkinOffice2007Pink=0
+dxSkinOffice2007Silver=1
+dxSkinPumpkin=0
+dxSkinSeven=0
+dxSkinSharp=0
+dxSkinSilver=0
+dxSkinSpringTime=0
+dxSkinStardust=0
+dxSkinSummer2008=0
+dxSkinsDefaultPainters=0
+dxSkinValentine=0
+dxSkinXmas2008Blue=0
diff --git a/Demos/SimpleSockets/Srv/Server_Icon.ico b/Demos/UDP/ncUDPSockets/Server/Server_Icon.ico
similarity index 100%
rename from Demos/SimpleSockets/Srv/Server_Icon.ico
rename to Demos/UDP/ncUDPSockets/Server/Server_Icon.ico
diff --git a/Demos/UDP/ncUDPSockets/Server/ufrmMain.dfm b/Demos/UDP/ncUDPSockets/Server/ufrmMain.dfm
new file mode 100644
index 0000000..24aaa69
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Server/ufrmMain.dfm
@@ -0,0 +1,94 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'UDPServer'
+ ClientHeight = 244
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 202
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start UDP Server'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pblPort: TPanel
+ AlignWithMargins = True
+ Left = 115
+ Top = 3
+ Width = 412
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object UDPServer: TncUDPServer
+ OnReadDatagram = UDPServerReadDatagram
+ Left = 232
+ Top = 104
+ end
+end
diff --git a/Demos/UDP/ncUDPSockets/Server/ufrmMain.pas b/Demos/UDP/ncUDPSockets/Server/ufrmMain.pas
new file mode 100644
index 0000000..162f7f0
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/Server/ufrmMain.pas
@@ -0,0 +1,170 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, System.Diagnostics,
+ ncLines, ncUDPSockets, ncIPUtils;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pblPort: TPanel;
+ edtPort: TSpinEdit;
+ UDPServer: TncUDPServer;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnActivateClick(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure edtPortChange(Sender: TObject);
+ procedure SendToClient(const Data: string; const DestAddr: TSockAddrStorage);
+ procedure UDPServerReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer;
+ const SenderAddr: TSockAddrStorage);
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+//
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ UDPServer.Active := False;
+end;
+
+// *****************************************************************************
+// Start/Stop Main CLient
+// *****************************************************************************
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if UDPServer.Active then
+ begin
+ // Deactivate the UDP client
+ UDPServer.Active := False;
+ btnActivate.Caption := 'Start UDP Server';
+ Form1.Log('UDP Server Deactivated');
+ end
+ else
+ begin
+ try
+ // Activate the UDP client
+ UDPServer.Active := True;
+ btnActivate.Caption := 'Stop UDP Server';
+ Form1.Log('UDP Server Activated');
+ except
+ on E: Exception do
+ Form1.Log('Failed to activate UDP Server: ' + E.Message);
+ end;
+ end;
+end;
+
+// *****************************************************************************
+// Change Main Server port
+// *****************************************************************************
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ UDPServer.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := UDPServer.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+// *****************************************************************************
+// SendToClient
+// *****************************************************************************
+procedure TForm1.SendToClient(const Data: string; const DestAddr: TSockAddrStorage);
+var
+ SenderIP: string;
+begin
+ if not UDPServer.Active then
+ Exit;
+
+ try
+ // Get IP address using our utils
+ SenderIP := TncIPUtils.GetIPFromStorage(DestAddr);
+
+ // Send the data - pass TSockAddrStorage directly
+ UDPServer.SendTo(BytesOf(Data), DestAddr);
+
+ Form1.Log(Format('Sent to %s: %s', [SenderIP, Data]));
+ except
+ on E: Exception do
+ Form1.Log('Error sending data: ' + E.Message);
+ end;
+end;
+
+// *****************************************************************************
+// Read Data
+// *****************************************************************************
+procedure TForm1.UDPServerReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer; const SenderAddr: TSockAddrStorage);
+var
+ ReceivedData: string;
+ SenderIP: string;
+begin
+ try
+ // Convert received data to string
+ ReceivedData := StringOf(Copy(aBuf, 0, aBufCount));
+
+ // Get sender IP address using our utils
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+
+ // Log and echo
+ Form1.Log(Format('Received from %s: %s', [SenderIP, ReceivedData]));
+ SendToClient('Echo: ' + ReceivedData, SenderAddr);
+ except
+ on E: Exception do
+ Form1.Log(Format('Error processing datagram: %s', [E.Message]));
+ end;
+end;
+
+// *****************************************************************************
+// Memo Log
+// *****************************************************************************
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now),
+ AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
diff --git a/Demos/UDP/ncUDPSockets/UDPSockets.groupproj b/Demos/UDP/ncUDPSockets/UDPSockets.groupproj
new file mode 100644
index 0000000..29ca13f
--- /dev/null
+++ b/Demos/UDP/ncUDPSockets/UDPSockets.groupproj
@@ -0,0 +1,48 @@
+
+
+ {7EB9A25E-4A42-4DE8-919E-70124E14615F}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demos/UDP/ncUDPSockets/UDPSockets_UDPv4.PNG b/Demos/UDP/ncUDPSockets/UDPSockets_UDPv4.PNG
new file mode 100644
index 0000000..15bb068
Binary files /dev/null and b/Demos/UDP/ncUDPSockets/UDPSockets_UDPv4.PNG differ
diff --git a/Demos/UDP/ncUDPSockets/UDPSockets_UDPv6.PNG b/Demos/UDP/ncUDPSockets/UDPSockets_UDPv6.PNG
new file mode 100644
index 0000000..4abb230
Binary files /dev/null and b/Demos/UDP/ncUDPSockets/UDPSockets_UDPv6.PNG differ
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dpr b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dpr
new file mode 100644
index 0000000..a5d4cdd
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dpr
@@ -0,0 +1,14 @@
+program UDPClient;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dproj b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dproj
new file mode 100644
index 0000000..5d3cfec
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dproj
@@ -0,0 +1,190 @@
+
+
+ {97EFB123-834A-4EA4-8F07-796EBFAC98FC}
+ UDPClient.dpr
+ True
+ Debug
+ UDPClient
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ UDPClient
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ UDPClient.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dproj.local b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.identcache b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.identcache
new file mode 100644
index 0000000..9ae2096
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.identcache differ
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.res b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.res
new file mode 100644
index 0000000..9c1433c
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/UDPClient.res differ
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/ufrmMain.dfm b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/ufrmMain.dfm
new file mode 100644
index 0000000..95ccc00
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/ufrmMain.dfm
@@ -0,0 +1,264 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ ActiveControl = edtDataToSend
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'UDP Client - Image Transfer'
+ ClientHeight = 307
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 169
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start UDP Client'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pnlAddress: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtHost: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 281
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = '127.0.0.1'
+ TextHint = 'Enter host address'
+ OnChange = edtHostChange
+ end
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 291
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 211
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendData: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send Raw Data'
+ Default = True
+ TabOrder = 0
+ OnClick = btnSendDataClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtDataToSend: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 407
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'This is some text data'
+ TextHint = 'Enter data to send here'
+ OnEnter = edtDataToSendEnter
+ OnExit = edtDataToSendExit
+ end
+ end
+ end
+ object Panel3: TPanel
+ Left = 0
+ Top = 243
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 3
+ object btnSendCommand: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send Command'
+ TabOrder = 0
+ OnClick = btnSendCommandClick
+ end
+ object Panel4: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtCommandData: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 2
+ Width = 407
+ Height = 21
+ Margins.Left = 0
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ TabOrder = 0
+ Text = 'Hello Server!'
+ TextHint = 'Enter command data here'
+ end
+ end
+ end
+ object Panel6: TPanel
+ Left = 0
+ Top = 275
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 4
+ object btnSendScreenshot: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 517
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ Caption = 'Send Screenshot'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ TabOrder = 0
+ OnClick = btnSendScreenshotClick
+ end
+ end
+ object UDPClient: TncUDPClientDual
+ Broadcast = True
+ OnReadDatagram = UDPClientReadDatagram
+ OnCommand = UDPClientCommand
+ Left = 208
+ Top = 104
+ end
+end
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/ufrmMain.pas b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/ufrmMain.pas
new file mode 100644
index 0000000..91f8066
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Client/ufrmMain.pas
@@ -0,0 +1,379 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.Graphics, Vcl.Imaging.jpeg,
+ System.Diagnostics, System.SyncObjs, ncLines, ncUDPSocketsDual, ncIPUtils;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pnlAddress: TPanel;
+ edtHost: TEdit;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendData: TButton;
+ Panel2: TPanel;
+ edtDataToSend: TEdit;
+ Panel3: TPanel;
+ btnSendCommand: TButton;
+ Panel4: TPanel;
+ edtCommandData: TEdit;
+ Panel6: TPanel;
+ btnSendScreenshot: TButton;
+ UDPClient: TncUDPClientDual;
+
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnActivateClick(Sender: TObject);
+ procedure edtHostChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure edtDataToSendEnter(Sender: TObject);
+ procedure edtDataToSendExit(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure btnSendDataClick(Sender: TObject);
+ procedure btnSendCommandClick(Sender: TObject);
+ procedure btnSendScreenshotClick(Sender: TObject);
+ procedure UDPClientReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer;
+ const SenderAddr: TSockAddrStorage);
+ procedure UDPClientCommand(Sender: TObject; aLine: TncLine;
+ const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes;
+ aFlags: Byte; aSequence: UInt16);
+
+ private
+ FCommandParser: TStringList;
+ FCommandLock: TCriticalSection;
+ function CaptureScreenshot: TBytes;
+ public
+ { Public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+function TForm1.CaptureScreenshot: TBytes;
+var
+ DC: HDC;
+ ScreenBMP: TBitmap;
+ jpgImage: TJPEGImage;
+ MS: TMemoryStream;
+begin
+ Result := nil;
+
+ // Create required objects for screen capture
+ ScreenBMP := TBitmap.Create;
+ jpgImage := TJPEGImage.Create;
+ MS := TMemoryStream.Create;
+ try
+ // Set bitmap dimensions to match screen resolution
+ ScreenBMP.Width := Screen.Width;
+ ScreenBMP.Height := Screen.Height;
+
+ // Get device context for the entire screen (0 = desktop window)
+ DC := GetDC(0);
+ try
+ // Copy screen pixels to bitmap using BitBlt
+ BitBlt(ScreenBMP.Canvas.Handle, 0, 0, Screen.Width,
+ Screen.Height, DC, 0, 0, SRCCOPY);
+ finally
+ ReleaseDC(0, DC);
+ end;
+
+ // Convert to JPEG with 30% quality for network efficiency
+ jpgImage.Assign(ScreenBMP);
+ jpgImage.CompressionQuality := 30;
+ jpgImage.SaveToStream(MS);
+
+ // Return JPEG data
+ MS.Position := 0;
+ SetLength(Result, MS.Size);
+ if MS.Size > 0 then
+ MS.ReadBuffer(Result[0], MS.Size);
+
+ Log(Format('Screenshot captured: %d bytes', [Length(Result)]));
+
+ finally
+ ScreenBMP.Free;
+ jpgImage.Free;
+ MS.Free;
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ // Initialize command parsing structures
+ FCommandParser := TStringList.Create;
+ FCommandParser.Delimiter := '|';
+ FCommandParser.StrictDelimiter := True;
+ FCommandLock := TCriticalSection.Create;
+
+ // Initialize controls
+ edtCommandData.Text := 'Hello Server!';
+ edtHost.Text := '127.0.0.1';
+ edtPort.Value := 16233;
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ UDPClient.Active := False;
+
+ if Assigned(FCommandParser) then
+ FCommandParser.Free;
+ if Assigned(FCommandLock) then
+ FCommandLock.Free;
+end;
+
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if UDPClient.Active then
+ begin
+ UDPClient.Active := False;
+ btnActivate.Caption := 'Start UDP Client';
+ Log('UDP Client Deactivated');
+ end
+ else
+ begin
+ if Trim(edtHost.Text) = '' then
+ begin
+ Log('Host field cannot be blank.');
+ Exit;
+ end;
+
+ try
+ UDPClient.Host := edtHost.Text;
+ UDPClient.Port := edtPort.Value;
+ UDPClient.Active := True;
+ btnActivate.Caption := 'Stop UDP Client';
+ Log('UDP Client Activated');
+ except
+ on E: Exception do
+ Log('Failed to activate UDP Client: ' + E.Message);
+ end;
+ end;
+end;
+
+procedure TForm1.edtHostChange(Sender: TObject);
+begin
+ try
+ UDPClient.Host := edtHost.Text;
+ except
+ edtHost.OnChange := nil;
+ try
+ edtHost.Text := UDPClient.Host;
+ finally
+ edtHost.OnChange := edtHostChange;
+ end;
+ raise;
+ end;
+end;
+
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ UDPClient.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := UDPClient.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+procedure TForm1.edtDataToSendEnter(Sender: TObject);
+begin
+ btnSendData.Default := True;
+end;
+
+procedure TForm1.edtDataToSendExit(Sender: TObject);
+begin
+ btnSendData.Default := False;
+end;
+
+procedure TForm1.btnSendDataClick(Sender: TObject);
+begin
+ try
+ if not UDPClient.Active then
+ begin
+ Log('Cannot send - client not active');
+ Exit;
+ end;
+
+ if Trim(edtDataToSend.Text) = '' then
+ begin
+ Log('Cannot send - Data field cannot be blank.');
+ Exit;
+ end;
+
+ UDPClient.Send(edtDataToSend.Text);
+ Log(Format('[RAW DATA] Sent: %s', [edtDataToSend.Text]));
+ except
+ on E: Exception do
+ Log('Error sending: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.btnSendCommandClick(Sender: TObject);
+var
+ CommandData: TBytes;
+begin
+ try
+ if not UDPClient.Active then
+ begin
+ Log('Cannot send command - client not active');
+ Exit;
+ end;
+
+ if Trim(edtCommandData.Text) <> '' then
+ CommandData := BytesOf(edtCommandData.Text)
+ else
+ SetLength(CommandData, 0);
+
+ UDPClient.SendCommand(0, BytesOf('MSG|') + CommandData);
+
+ except
+ on E: Exception do
+ Log('Error sending command: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.btnSendScreenshotClick(Sender: TObject);
+var
+ ScreenshotData: TBytes;
+begin
+ try
+ if not UDPClient.Active then
+ begin
+ Log('Cannot send screenshot - client not active');
+ Exit;
+ end;
+
+ Log('Capturing screenshot...');
+ ScreenshotData := CaptureScreenshot;
+
+ if Length(ScreenshotData) = 0 then
+ begin
+ Log('Failed to capture screenshot');
+ Exit;
+ end;
+
+ UDPClient.SendCommand(0, BytesOf('ScreenShot|') + ScreenshotData);
+
+ Log('SEND SCREENSHOT')
+
+ except
+ on E: Exception do
+ Log('Error sending screenshot: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.UDPClientCommand(Sender: TObject; aLine: TncLine;
+ const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes;
+ aFlags: Byte; aSequence: UInt16);
+var
+ SenderIP: string;
+ DataStr: string;
+ CommandName: string;
+begin
+ try
+ SenderIP := TncIPUtils.GetIPFromStorage(aSenderAddr);
+ except
+ on E: EIPError do
+ SenderIP := Format('Invalid Address: %s', [E.Message]);
+ end;
+
+ if Length(aData) > 0 then
+ DataStr := StringOf(aData)
+ else
+ DataStr := '(no data)';
+
+ // Parse command using same logic as TCP demo
+ FCommandLock.Enter;
+ try
+ FCommandParser.Clear;
+ FCommandParser.DelimitedText := DataStr;
+
+ if FCommandParser.Count > 0 then
+ begin
+ CommandName := FCommandParser[0];
+
+ // Handle different commands
+ if CommandName = 'TITLE' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ Self.Caption := FCommandParser[1];
+ Log(Format('[COMMAND] Title changed to: %s', [FCommandParser[1]]));
+ end;
+ end
+ else
+ begin
+ Log(Format('[COMMAND] Received from %s: %s', [SenderIP, CommandName]));
+ end;
+ end
+ else
+ begin
+ Log(Format('[COMMAND] Received from %s: ID=%d, Data=%s, Flags=%d, Seq=%d',
+ [SenderIP, aCmd, DataStr, aFlags, aSequence]));
+ end;
+ finally
+ FCommandLock.Leave;
+ end;
+end;
+
+procedure TForm1.UDPClientReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer; const SenderAddr: TSockAddrStorage);
+var
+ ReceivedData: string;
+ SenderIP: string;
+begin
+ ReceivedData := StringOf(Copy(aBuf, 0, aBufCount));
+
+ try
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ except
+ on E: EIPError do
+ SenderIP := Format('Invalid Address: %s', [E.Message]);
+ end;
+
+ Log(Format('[RAW DATA] Received from %s: %s', [SenderIP, ReceivedData]));
+end;
+
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now), AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dpr b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dpr
new file mode 100644
index 0000000..eb591f7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dpr
@@ -0,0 +1,14 @@
+program UDPServer;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dproj b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dproj
new file mode 100644
index 0000000..21976cb
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dproj
@@ -0,0 +1,190 @@
+
+
+ {E2EAC035-B027-4E62-A982-B19AE5F74BA3}
+ UDPServer.dpr
+ True
+ Debug
+ UDPServer
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ UDPServer
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ UDPServer.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dproj.local b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.identcache b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.identcache
new file mode 100644
index 0000000..a2d7b63
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.identcache differ
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.res b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.res
new file mode 100644
index 0000000..4acd4e7
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/UDPServer.res differ
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/ufrmMain.dfm b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/ufrmMain.dfm
new file mode 100644
index 0000000..8d0d360
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/ufrmMain.dfm
@@ -0,0 +1,170 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'UDP Server - Image Display'
+ ClientHeight = 231
+ ClientWidth = 802
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object Image1: TImage
+ Left = 600
+ Top = 72
+ Width = 192
+ Height = 145
+ end
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 69
+ Width = 587
+ Height = 157
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 802
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start UDP Server'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pblPort: TPanel
+ AlignWithMargins = True
+ Left = 115
+ Top = 3
+ Width = 687
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 37
+ Width = 802
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendCommand: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send Command'
+ TabOrder = 0
+ OnClick = btnSendCommandClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 692
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object Label1: TLabel
+ AlignWithMargins = True
+ Left = 3
+ Top = 6
+ Width = 51
+ Height = 17
+ Margins.Top = 6
+ Align = alLeft
+ Caption = 'Command:'
+ ExplicitHeight = 13
+ end
+ object edtCommandData: TEdit
+ AlignWithMargins = True
+ Left = 57
+ Top = 0
+ Width = 630
+ Height = 21
+ Margins.Left = 0
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'TITLE|New Window Title'
+ TextHint = 'Enter command to send to last client'
+ end
+ end
+ end
+ object UDPServer: TncUDPServerDual
+ Broadcast = True
+ OnReadDatagram = UDPServerReadDatagram
+ OnCommand = UDPServerCommand
+ Left = 240
+ Top = 128
+ end
+end
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/ufrmMain.pas b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/ufrmMain.pas
new file mode 100644
index 0000000..48eb0f7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/Server/ufrmMain.pas
@@ -0,0 +1,360 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, System.Math, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.Graphics, Vcl.Imaging.jpeg,
+ System.Diagnostics, System.SyncObjs, ncLines, ncUDPSocketsDual, ncIPUtils;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pblPort: TPanel;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendCommand: TButton;
+ Panel2: TPanel;
+ edtCommandData: TEdit;
+ Label1: TLabel;
+ Image1: TImage;
+ UDPServer: TncUDPServerDual;
+
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnActivateClick(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnSendCommandClick(Sender: TObject);
+ procedure UDPServerReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer;
+ const SenderAddr: TSockAddrStorage);
+ procedure UDPServerCommand(Sender: TObject; aLine: TncLine;
+ const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes;
+ aFlags: Byte; aSequence: UInt16);
+
+ private
+ FCommandParser: TStringList;
+ FCommandLock: TCriticalSection;
+ FLastClientAddr: TSockAddrStorage;
+ FHasLastClient: Boolean;
+
+ procedure DisplayScreenShot(const aData: TBytes);
+ procedure SendCommandToLastClient(const AMessage: string);
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ // Initialize command parsing structures
+ FCommandParser := TStringList.Create;
+ FCommandParser.Delimiter := '|';
+ FCommandParser.StrictDelimiter := True;
+ FCommandLock := TCriticalSection.Create;
+
+ // Initialize client tracking
+ FHasLastClient := False;
+
+ // Initialize image display
+ Image1.Picture.Bitmap.SetSize(Image1.Width, Image1.Height);
+ Image1.Picture.Bitmap.Canvas.Brush.Color := clBlack;
+ Image1.Picture.Bitmap.Canvas.FillRect(Rect(0, 0, Image1.Width, Image1.Height));
+
+ edtCommandData.Text := 'TITLE|New Window Title';
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ UDPServer.Active := False;
+
+ if Assigned(FCommandParser) then
+ FCommandParser.Free;
+ if Assigned(FCommandLock) then
+ FCommandLock.Free;
+end;
+
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if UDPServer.Active then
+ begin
+ UDPServer.Active := False;
+ btnActivate.Caption := 'Start UDP Server';
+ Log('UDP Server Deactivated');
+ end
+ else
+ begin
+ try
+ UDPServer.Port := edtPort.Value;
+ UDPServer.Active := True;
+ btnActivate.Caption := 'Stop UDP Server';
+ Log('UDP Server Activated on port ' + IntToStr(edtPort.Value));
+ except
+ on E: Exception do
+ Log('Failed to activate UDP Server: ' + E.Message);
+ end;
+ end;
+end;
+
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ UDPServer.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := UDPServer.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+procedure TForm1.btnSendCommandClick(Sender: TObject);
+begin
+ if not FHasLastClient then
+ begin
+ Log('No client available - receive a packet from a client first');
+ Exit;
+ end;
+
+ if Trim(edtCommandData.Text) = '' then
+ begin
+ Log('Command data cannot be blank');
+ Exit;
+ end;
+
+ SendCommandToLastClient(edtCommandData.Text);
+end;
+
+procedure TForm1.SendCommandToLastClient(const AMessage: string);
+var
+ ClientIP: string;
+begin
+ if not UDPServer.Active then
+ Exit;
+
+ if not FHasLastClient then
+ begin
+ Log('No client address available');
+ Exit;
+ end;
+
+ try
+ ClientIP := TncIPUtils.GetIPFromStorage(FLastClientAddr);
+ UDPServer.SendCommand(FLastClientAddr, 0, BytesOf(AMessage));
+ Log(Format('[COMMAND] Sent to %s: %s', [ClientIP, AMessage]));
+ except
+ on E: Exception do
+ Log('Error sending command: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.UDPServerReadDatagram(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer; const SenderAddr: TSockAddrStorage);
+var
+ ReceivedData: string;
+ SenderIP: string;
+begin
+ try
+ ReceivedData := StringOf(Copy(aBuf, 0, aBufCount));
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+
+ // Remember last client for sending responses
+ FLastClientAddr := SenderAddr;
+ FHasLastClient := True;
+
+ Log(Format('[RAW DATA] Received from %s: %s', [SenderIP, ReceivedData]));
+
+ // Echo back the data
+ UDPServer.SendTo(BytesOf('Echo: ' + ReceivedData), SenderAddr);
+ Log(Format('[RAW DATA] Sent echo to %s', [SenderIP]));
+ except
+ on E: Exception do
+ Log(Format('Error processing datagram: %s', [E.Message]));
+ end;
+end;
+
+procedure TForm1.UDPServerCommand(Sender: TObject; aLine: TncLine; const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ SenderIP: string;
+begin
+ try
+ // Get sender IP for logging
+ SenderIP := TncIPUtils.GetIPFromStorage(aSenderAddr);
+
+ // Store last client info for sending commands back
+ FLastClientAddr := aSenderAddr;
+ FHasLastClient := True;
+
+ // Log command reception with size info
+ Log(Format('[COMMAND] Received from %s: Cmd=%d, DataSize=%d bytes, Flags=%d, Seq=%d',
+ [SenderIP, aCmd, Length(aData), aFlags, aSequence]));
+
+ // Parse command data as string for processing
+ var DataStr: string;
+ if Length(aData) > 0 then
+ DataStr := StringOf(aData)
+ else
+ DataStr := '';
+
+ FCommandLock.Enter;
+ try
+ FCommandParser.Clear;
+ FCommandParser.DelimitedText := DataStr;
+
+ if FCommandParser.Count > 0 then
+ begin
+ var CommandName := FCommandParser[0];
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle command ScreenShot (client sending image)
+ ////////////////////////////////////////////////////////////////////////////////
+ if CommandName = 'ScreenShot' then
+ begin
+
+ if FCommandParser.Count > 1 then
+ begin
+
+ TThread.Queue(nil,
+ procedure
+ var
+ imageData: TBytes;
+ begin
+ try
+ // Extract image data from command - skip "ScreenShot|" (10 bytes)
+ // aData contains: "ScreenShot|" + JPEG binary data
+ imageData := Copy(aData, 11, Length(aData));
+
+ Form1.DisplayScreenShot(imageData);
+
+ Log('RECEIVE SCREENSHOT');
+
+ // Send acknowledgment back to client
+ UDPServer.SendCommand(aSenderAddr, 0, BytesOf('TITLE|Screenshot Received!'));
+
+ except
+ on E: Exception do
+ begin
+ Log(Format('[%s] Error processing screenshot: %s', [TimeToStr(Now), E.Message]));
+ end;
+ end;
+ end);
+ end
+ end
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle command TITLE (changing client window title)
+ ////////////////////////////////////////////////////////////////////////////////
+ else if CommandName = 'TITLE' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ Log(Format('[TITLE] Setting title from %s: %s', [SenderIP, FCommandParser[1]]));
+ TThread.Queue(nil, procedure
+ begin
+ Caption := FCommandParser[1];
+ end);
+ end;
+ end
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle command MSG (general message)
+ ////////////////////////////////////////////////////////////////////////////////
+ else if CommandName = 'MSG' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ Log(Format('[MSG] Message from %s: %s', [SenderIP, FCommandParser[1]]));
+ end;
+ end
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle unknown commands
+ ////////////////////////////////////////////////////////////////////////////////
+ else
+ begin
+ Log(Format('[COMMAND] Unknown command from %s: %s', [SenderIP, CommandName]));
+
+ // Echo the command back to the client
+ UDPServer.SendCommand(aSenderAddr, 100, BytesOf('Echo: ' + DataStr));
+ end;
+ end
+ else
+ begin
+ Log(Format('[COMMAND] Raw command from %s: %s', [SenderIP, DataStr]));
+
+ // Send response for unstructured commands
+ UDPServer.SendCommand(aSenderAddr, 101, BytesOf('Received: ' + DataStr));
+ end;
+ finally
+ FCommandLock.Leave;
+ end;
+ except
+ on E: Exception do
+ Log(Format('Error processing command: %s', [E.Message]));
+ end;
+end;
+
+procedure TForm1.DisplayScreenShot(const aData: TBytes);
+var
+ MS: TMemoryStream;
+ jpgImage: TJPEGImage;
+begin
+ // Create streams for JPEG loading
+ MS := TMemoryStream.Create;
+ jpgImage := TJPEGImage.Create;
+ try
+ // Load JPEG data directly into stream
+ MS.WriteBuffer(aData[0], Length(aData));
+ MS.Position := 0;
+
+ // Load JPEG from data stream
+ jpgImage.LoadFromStream(MS);
+
+ // Display in TImage component
+ if Assigned(Form1) and Assigned(Form1.Image1) then
+ begin
+ Form1.Image1.Picture.Assign(jpgImage);
+ Form1.Image1.Stretch := True;
+ end;
+
+ finally
+ MS.Free;
+ jpgImage.Free;
+ end;
+end;
+
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now), AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsDual_ImageDisplay/UDPSocketsDual_ImageDisplay.groupproj b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/UDPSocketsDual_ImageDisplay.groupproj
new file mode 100644
index 0000000..d92f069
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsDual_ImageDisplay/UDPSocketsDual_ImageDisplay.groupproj
@@ -0,0 +1,48 @@
+
+
+ {E7EA7F9E-9B7A-4F4D-9B5C-8F4B6A5E2D1C}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dpr b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dpr
new file mode 100644
index 0000000..a5d4cdd
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dpr
@@ -0,0 +1,14 @@
+program UDPClient;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dproj b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dproj
new file mode 100644
index 0000000..5d3cfec
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dproj
@@ -0,0 +1,190 @@
+
+
+ {97EFB123-834A-4EA4-8F07-796EBFAC98FC}
+ UDPClient.dpr
+ True
+ Debug
+ UDPClient
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ UDPClient
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ UDPClient.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dproj.local b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.identcache b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.identcache
new file mode 100644
index 0000000..6ecc560
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.identcache differ
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.res b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.res
new file mode 100644
index 0000000..9c1433c
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/UDPClient.res differ
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/ufrmMain.dfm b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/ufrmMain.dfm
new file mode 100644
index 0000000..cd2050a
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/ufrmMain.dfm
@@ -0,0 +1,229 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'UDP Client - Image Transfer'
+ ClientHeight = 307
+ ClientWidth = 527
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 37
+ Width = 517
+ Height = 169
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 1
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 527
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start UDP Client'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pnlAddress: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtHost: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 281
+ Height = 21
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = '127.0.0.1'
+ TextHint = 'Enter host address'
+ OnChange = edtHostChange
+ end
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 291
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alRight
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 1
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 211
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 0
+ Top = 3
+ Width = 527
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 0
+ end
+ end
+ object Panel3: TPanel
+ Left = 0
+ Top = 243
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 3
+ object btnSendCommand: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send Command'
+ TabOrder = 0
+ OnClick = btnSendCommandClick
+ end
+ object Panel4: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 417
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtCommandData: TEdit
+ AlignWithMargins = True
+ Left = 5
+ Top = 2
+ Width = 407
+ Height = 21
+ Margins.Left = 0
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ TabOrder = 0
+ Text = 'Hello Server!'
+ TextHint = 'Enter command data here'
+ end
+ end
+ end
+ object Panel6: TPanel
+ Left = 0
+ Top = 275
+ Width = 527
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alBottom
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 4
+ object btnSendScreenshot: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 517
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ Caption = 'Send Screenshot'
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = [fsBold]
+ ParentFont = False
+ TabOrder = 0
+ OnClick = btnSendScreenshotClick
+ end
+ end
+ object UDPClient: TncUDPClientLCP
+ Broadcast = True
+ OnCommand = UDPClientCommand
+ Left = 200
+ Top = 96
+ end
+end
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/ufrmMain.pas b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/ufrmMain.pas
new file mode 100644
index 0000000..187a48b
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Client/ufrmMain.pas
@@ -0,0 +1,323 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.Graphics, Vcl.Imaging.jpeg,
+ System.Diagnostics, System.SyncObjs, ncLines, ncIPUtils,
+ ncUDPSocketsLCP;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pnlAddress: TPanel;
+ edtHost: TEdit;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ Panel2: TPanel;
+ Panel3: TPanel;
+ btnSendCommand: TButton;
+ Panel4: TPanel;
+ edtCommandData: TEdit;
+ Panel6: TPanel;
+ btnSendScreenshot: TButton;
+ UDPClient: TncUDPClientLCP;
+
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnActivateClick(Sender: TObject);
+ procedure edtHostChange(Sender: TObject);
+ procedure edtPortChange(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure btnSendCommandClick(Sender: TObject);
+ procedure btnSendScreenshotClick(Sender: TObject);
+ procedure UDPClientCommand(Sender: TObject; aLine: TncLine;
+ const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes;
+ aFlags: Byte; aSequence: UInt16);
+
+ private
+ FCommandParser: TStringList;
+ FCommandLock: TCriticalSection;
+ function CaptureScreenshot: TBytes;
+ public
+ { Public declarations }
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+function TForm1.CaptureScreenshot: TBytes;
+var
+ DC: HDC;
+ ScreenBMP: TBitmap;
+ jpgImage: TJPEGImage;
+ MS: TMemoryStream;
+begin
+ Result := nil;
+
+ // Create required objects for screen capture
+ ScreenBMP := TBitmap.Create;
+ jpgImage := TJPEGImage.Create;
+ MS := TMemoryStream.Create;
+ try
+ // Set bitmap dimensions to match screen resolution
+ ScreenBMP.Width := Screen.Width;
+ ScreenBMP.Height := Screen.Height;
+
+ // Get device context for the entire screen (0 = desktop window)
+ DC := GetDC(0);
+ try
+ // Copy screen pixels to bitmap using BitBlt
+ BitBlt(ScreenBMP.Canvas.Handle, 0, 0, Screen.Width,
+ Screen.Height, DC, 0, 0, SRCCOPY);
+ finally
+ ReleaseDC(0, DC);
+ end;
+
+ // Convert to JPEG with 30% quality for network efficiency
+ jpgImage.Assign(ScreenBMP);
+ jpgImage.CompressionQuality := 30;
+ jpgImage.SaveToStream(MS);
+
+ // Return JPEG data
+ MS.Position := 0;
+ SetLength(Result, MS.Size);
+ if MS.Size > 0 then
+ MS.ReadBuffer(Result[0], MS.Size);
+
+ Log(Format('Screenshot captured: %d bytes', [Length(Result)]));
+
+ finally
+ ScreenBMP.Free;
+ jpgImage.Free;
+ MS.Free;
+ end;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ // Initialize command parsing structures
+ FCommandParser := TStringList.Create;
+ FCommandParser.Delimiter := '|';
+ FCommandParser.StrictDelimiter := True;
+ FCommandLock := TCriticalSection.Create;
+
+ // Initialize controls
+ edtCommandData.Text := 'Hello Server!';
+ edtHost.Text := '127.0.0.1';
+ edtPort.Value := 16233;
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ UDPClient.Active := False;
+
+ if Assigned(FCommandParser) then
+ FCommandParser.Free;
+ if Assigned(FCommandLock) then
+ FCommandLock.Free;
+end;
+
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if UDPClient.Active then
+ begin
+ UDPClient.Active := False;
+ btnActivate.Caption := 'Start UDP Client';
+ Log('UDP Client Deactivated');
+ end
+ else
+ begin
+ if Trim(edtHost.Text) = '' then
+ begin
+ Log('Host field cannot be blank.');
+ Exit;
+ end;
+
+ try
+ UDPClient.Host := edtHost.Text;
+ UDPClient.Port := edtPort.Value;
+ UDPClient.Active := True;
+ btnActivate.Caption := 'Stop UDP Client';
+ Log('UDP Client Activated');
+ except
+ on E: Exception do
+ Log('Failed to activate UDP Client: ' + E.Message);
+ end;
+ end;
+end;
+
+procedure TForm1.edtHostChange(Sender: TObject);
+begin
+ try
+ UDPClient.Host := edtHost.Text;
+ except
+ edtHost.OnChange := nil;
+ try
+ edtHost.Text := UDPClient.Host;
+ finally
+ edtHost.OnChange := edtHostChange;
+ end;
+ raise;
+ end;
+end;
+
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ UDPClient.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := UDPClient.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+
+
+procedure TForm1.btnSendCommandClick(Sender: TObject);
+var
+ CommandData: TBytes;
+begin
+ try
+ if not UDPClient.Active then
+ begin
+ Log('Cannot send command - client not active');
+ Exit;
+ end;
+
+ if Trim(edtCommandData.Text) <> '' then
+ CommandData := BytesOf(edtCommandData.Text)
+ else
+ SetLength(CommandData, 0);
+
+ UDPClient.SendCommand(0, BytesOf('MSG|') + CommandData);
+
+ except
+ on E: Exception do
+ Log('Error sending command: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.btnSendScreenshotClick(Sender: TObject);
+var
+ ScreenshotData: TBytes;
+begin
+ try
+ if not UDPClient.Active then
+ begin
+ Log('Cannot send screenshot - client not active');
+ Exit;
+ end;
+
+ Log('Capturing screenshot...');
+ ScreenshotData := CaptureScreenshot;
+
+ if Length(ScreenshotData) = 0 then
+ begin
+ Log('Failed to capture screenshot');
+ Exit;
+ end;
+
+ UDPClient.SendCommand(0, BytesOf('ScreenShot|') + ScreenshotData);
+
+ Log('SEND SCREENSHOT')
+
+ except
+ on E: Exception do
+ Log('Error sending screenshot: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.UDPClientCommand(Sender: TObject; aLine: TncLine;
+ const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes;
+ aFlags: Byte; aSequence: UInt16);
+var
+ SenderIP: string;
+ DataStr: string;
+ CommandName: string;
+begin
+ try
+ SenderIP := TncIPUtils.GetIPFromStorage(aSenderAddr);
+ except
+ on E: EIPError do
+ SenderIP := Format('Invalid Address: %s', [E.Message]);
+ end;
+
+ if Length(aData) > 0 then
+ DataStr := StringOf(aData)
+ else
+ DataStr := '(no data)';
+
+ // Parse command using same logic as TCP demo
+ FCommandLock.Enter;
+ try
+ FCommandParser.Clear;
+ FCommandParser.DelimitedText := DataStr;
+
+ if FCommandParser.Count > 0 then
+ begin
+ CommandName := FCommandParser[0];
+
+ // Handle different commands
+ if CommandName = 'TITLE' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ Self.Caption := FCommandParser[1];
+ Log(Format('[COMMAND] Title changed to: %s', [FCommandParser[1]]));
+ end;
+ end
+ else
+ begin
+ Log(Format('[COMMAND] Received from %s: %s', [SenderIP, CommandName]));
+ end;
+ end
+ else
+ begin
+ Log(Format('[COMMAND] Received from %s: ID=%d, Data=%s, Flags=%d, Seq=%d',
+ [SenderIP, aCmd, DataStr, aFlags, aSequence]));
+ end;
+ finally
+ FCommandLock.Leave;
+ end;
+end;
+
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now), AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dpr b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dpr
new file mode 100644
index 0000000..eb591f7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dpr
@@ -0,0 +1,14 @@
+program UDPServer;
+
+uses
+ Vcl.Forms,
+ ufrmMain in 'ufrmMain.pas' {Form1};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TForm1, Form1);
+ Application.Run;
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dproj b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dproj
new file mode 100644
index 0000000..21976cb
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dproj
@@ -0,0 +1,190 @@
+
+
+ {E2EAC035-B027-4E62-A982-B19AE5F74BA3}
+ UDPServer.dpr
+ True
+ Debug
+ UDPServer
+ 693377
+ Application
+ VCL
+ 20.2
+ Win32
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ true
+ Cfg_2
+ true
+ true
+
+
+ false
+ false
+ false
+ false
+ false
+ 00400000
+ UDPServer
+ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ 1036
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
+ activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ Debug
+ true
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName)
+ 1033
+ $(BDS)\bin\default_app.manifest
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png
+ $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png
+
+
+ RELEASE;$(DCC_Define)
+ 0
+ false
+ 0
+
+
+ PerMonitorV2
+
+
+ DEBUG;$(DCC_Define)
+ false
+ true
+ true
+ true
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ Debug
+
+
+ PerMonitorV2
+
+
+
+ MainSource
+
+
+
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+ Cfg_2
+ Base
+
+
+
+ Delphi.Personality.12
+
+
+
+
+ UDPServer.dpr
+
+
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+
+
+ 12
+
+
+
+
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dproj.local b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dproj.local
new file mode 100644
index 0000000..b3811b7
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.identcache b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.identcache
new file mode 100644
index 0000000..9360d5f
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.identcache differ
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.res b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.res
new file mode 100644
index 0000000..4acd4e7
Binary files /dev/null and b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/UDPServer.res differ
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/ufrmMain.dfm b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/ufrmMain.dfm
new file mode 100644
index 0000000..cbaf777
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/ufrmMain.dfm
@@ -0,0 +1,169 @@
+object Form1: TForm1
+ Left = 0
+ Top = 0
+ BorderIcons = [biSystemMenu, biMinimize]
+ Caption = 'UDP Server - Image Display'
+ ClientHeight = 231
+ ClientWidth = 802
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Position = poScreenCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ TextHeight = 13
+ object Image1: TImage
+ Left = 600
+ Top = 72
+ Width = 192
+ Height = 145
+ end
+ object memLog: TMemo
+ AlignWithMargins = True
+ Left = 5
+ Top = 69
+ Width = 587
+ Height = 157
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ ReadOnly = True
+ ScrollBars = ssVertical
+ TabOrder = 0
+ OnKeyDown = memLogKeyDown
+ end
+ object pnlToolbar: TPanel
+ Left = 0
+ Top = 0
+ Width = 802
+ Height = 37
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object btnActivate: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 5
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Start UDP Server'
+ TabOrder = 0
+ OnClick = btnActivateClick
+ end
+ object pblPort: TPanel
+ AlignWithMargins = True
+ Left = 115
+ Top = 3
+ Width = 687
+ Height = 31
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object edtPort: TSpinEdit
+ AlignWithMargins = True
+ Left = 0
+ Top = 5
+ Width = 121
+ Height = 22
+ Margins.Left = 0
+ Margins.Top = 5
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alLeft
+ MaxValue = 0
+ MinValue = 0
+ TabOrder = 0
+ Value = 16233
+ OnChange = edtPortChange
+ end
+ end
+ end
+ object Panel1: TPanel
+ Left = 0
+ Top = 37
+ Width = 802
+ Height = 32
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alTop
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 2
+ object btnSendCommand: TButton
+ AlignWithMargins = True
+ Left = 5
+ Top = 0
+ Width = 105
+ Height = 27
+ Margins.Left = 5
+ Margins.Top = 0
+ Margins.Right = 0
+ Margins.Bottom = 5
+ Align = alLeft
+ Caption = 'Send Command'
+ TabOrder = 0
+ OnClick = btnSendCommandClick
+ end
+ object Panel2: TPanel
+ AlignWithMargins = True
+ Left = 110
+ Top = 3
+ Width = 692
+ Height = 26
+ Margins.Left = 0
+ Margins.Right = 0
+ Align = alClient
+ BevelOuter = bvNone
+ FullRepaint = False
+ TabOrder = 1
+ object Label1: TLabel
+ AlignWithMargins = True
+ Left = 3
+ Top = 6
+ Width = 51
+ Height = 17
+ Margins.Top = 6
+ Align = alLeft
+ Caption = 'Command:'
+ ExplicitHeight = 13
+ end
+ object edtCommandData: TEdit
+ AlignWithMargins = True
+ Left = 57
+ Top = 0
+ Width = 630
+ Height = 21
+ Margins.Left = 0
+ Margins.Top = 0
+ Margins.Right = 5
+ Margins.Bottom = 5
+ Align = alClient
+ TabOrder = 0
+ Text = 'TITLE|New Window Title'
+ TextHint = 'Enter command to send to last client'
+ end
+ end
+ end
+ object UDPServer: TncUDPServerLCP
+ Broadcast = True
+ OnCommand = UDPServerCommand
+ Left = 224
+ Top = 120
+ end
+end
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/ufrmMain.pas b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/ufrmMain.pas
new file mode 100644
index 0000000..8c3ebd2
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/Server/ufrmMain.pas
@@ -0,0 +1,333 @@
+unit ufrmMain;
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ WinApi.Windows, WinApi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, System.Math, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls,
+ Vcl.ExtCtrls, Vcl.Samples.Spin, Vcl.Graphics, Vcl.Imaging.jpeg,
+ System.Diagnostics, System.SyncObjs, ncLines, ncIPUtils,
+ ncUDPSocketsLCP;
+
+type
+ TForm1 = class(TForm)
+ memLog: TMemo;
+ pnlToolbar: TPanel;
+ btnActivate: TButton;
+ pblPort: TPanel;
+ edtPort: TSpinEdit;
+ Panel1: TPanel;
+ btnSendCommand: TButton;
+ Panel2: TPanel;
+ edtCommandData: TEdit;
+ Label1: TLabel;
+ Image1: TImage;
+ UDPServer: TncUDPServerLCP;
+
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure btnActivateClick(Sender: TObject);
+ procedure Log(const AMessage: string);
+ procedure memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+ procedure edtPortChange(Sender: TObject);
+ procedure btnSendCommandClick(Sender: TObject);
+ procedure UDPServerCommand(Sender: TObject; aLine: TncLine;
+ const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes;
+ aFlags: Byte; aSequence: UInt16);
+
+ private
+ FCommandParser: TStringList;
+ FCommandLock: TCriticalSection;
+ FLastClientAddr: TSockAddrStorage;
+ FHasLastClient: Boolean;
+
+ procedure DisplayScreenShot(const aData: TBytes);
+ procedure SendCommandToLastClient(const AMessage: string);
+ public
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.dfm}
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ // Initialize command parsing structures
+ FCommandParser := TStringList.Create;
+ FCommandParser.Delimiter := '|';
+ FCommandParser.StrictDelimiter := True;
+ FCommandLock := TCriticalSection.Create;
+
+ // Initialize client tracking
+ FHasLastClient := False;
+
+ // Initialize image display
+ Image1.Picture.Bitmap.SetSize(Image1.Width, Image1.Height);
+ Image1.Picture.Bitmap.Canvas.Brush.Color := clBlack;
+ Image1.Picture.Bitmap.Canvas.FillRect(Rect(0, 0, Image1.Width, Image1.Height));
+
+ edtCommandData.Text := 'TITLE|New Window Title';
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+ UDPServer.Active := False;
+
+ if Assigned(FCommandParser) then
+ FCommandParser.Free;
+ if Assigned(FCommandLock) then
+ FCommandLock.Free;
+end;
+
+procedure TForm1.btnActivateClick(Sender: TObject);
+begin
+ if UDPServer.Active then
+ begin
+ UDPServer.Active := False;
+ btnActivate.Caption := 'Start UDP Server';
+ Log('UDP Server Deactivated');
+ end
+ else
+ begin
+ try
+ UDPServer.Port := edtPort.Value;
+ UDPServer.Active := True;
+ btnActivate.Caption := 'Stop UDP Server';
+ Log('UDP Server Activated on port ' + IntToStr(edtPort.Value));
+ except
+ on E: Exception do
+ Log('Failed to activate UDP Server: ' + E.Message);
+ end;
+ end;
+end;
+
+procedure TForm1.edtPortChange(Sender: TObject);
+begin
+ try
+ UDPServer.Port := edtPort.Value;
+ except
+ edtPort.OnChange := nil;
+ try
+ edtPort.Value := UDPServer.Port;
+ finally
+ edtPort.OnChange := edtPortChange;
+ end;
+ raise;
+ end;
+end;
+
+procedure TForm1.btnSendCommandClick(Sender: TObject);
+begin
+ if not FHasLastClient then
+ begin
+ Log('No client available - receive a packet from a client first');
+ Exit;
+ end;
+
+ if Trim(edtCommandData.Text) = '' then
+ begin
+ Log('Command data cannot be blank');
+ Exit;
+ end;
+
+ SendCommandToLastClient(edtCommandData.Text);
+end;
+
+procedure TForm1.SendCommandToLastClient(const AMessage: string);
+var
+ ClientIP: string;
+begin
+ if not UDPServer.Active then
+ Exit;
+
+ if not FHasLastClient then
+ begin
+ Log('No client address available');
+ Exit;
+ end;
+
+ try
+ ClientIP := TncIPUtils.GetIPFromStorage(FLastClientAddr);
+ UDPServer.SendCommand(FLastClientAddr, 0, BytesOf(AMessage));
+ Log(Format('[COMMAND] Sent to %s: %s', [ClientIP, AMessage]));
+ except
+ on E: Exception do
+ Log('Error sending command: ' + E.Message);
+ end;
+end;
+
+procedure TForm1.UDPServerCommand(Sender: TObject; aLine: TncLine; const aSenderAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ SenderIP: string;
+begin
+ try
+ // Get sender IP for logging
+ SenderIP := TncIPUtils.GetIPFromStorage(aSenderAddr);
+
+ // Store last client info for sending commands back
+ FLastClientAddr := aSenderAddr;
+ FHasLastClient := True;
+
+ // Log command reception with size info
+ Log(Format('[COMMAND] Received from %s: Cmd=%d, DataSize=%d bytes, Flags=%d, Seq=%d',
+ [SenderIP, aCmd, Length(aData), aFlags, aSequence]));
+
+ // Parse command data as string for processing
+ var DataStr: string;
+ if Length(aData) > 0 then
+ DataStr := StringOf(aData)
+ else
+ DataStr := '';
+
+ FCommandLock.Enter;
+ try
+ FCommandParser.Clear;
+ FCommandParser.DelimitedText := DataStr;
+
+ if FCommandParser.Count > 0 then
+ begin
+ var CommandName := FCommandParser[0];
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle command ScreenShot (client sending image)
+ ////////////////////////////////////////////////////////////////////////////////
+ if CommandName = 'ScreenShot' then
+ begin
+
+ if FCommandParser.Count > 1 then
+ begin
+
+ TThread.Queue(nil,
+ procedure
+ var
+ imageData: TBytes;
+ begin
+ try
+ // Extract image data from command - skip "ScreenShot|" (10 bytes)
+ // aData contains: "ScreenShot|" + JPEG binary data
+ imageData := Copy(aData, 11, Length(aData));
+
+ Form1.DisplayScreenShot(imageData);
+
+ Log('RECEIVE SCREENSHOT');
+
+ // Send acknowledgment back to client
+ UDPServer.SendCommand(aSenderAddr, 0, BytesOf('TITLE|Screenshot Received!'));
+
+ except
+ on E: Exception do
+ begin
+ Log(Format('[%s] Error processing screenshot: %s', [TimeToStr(Now), E.Message]));
+ end;
+ end;
+ end);
+ end
+ end
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle command TITLE (changing client window title)
+ ////////////////////////////////////////////////////////////////////////////////
+ else if CommandName = 'TITLE' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ Log(Format('[TITLE] Setting title from %s: %s', [SenderIP, FCommandParser[1]]));
+ TThread.Queue(nil, procedure
+ begin
+ Caption := FCommandParser[1];
+ end);
+ end;
+ end
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle command MSG (general message)
+ ////////////////////////////////////////////////////////////////////////////////
+ else if CommandName = 'MSG' then
+ begin
+ if FCommandParser.Count > 1 then
+ begin
+ Log(Format('[MSG] Message from %s: %s', [SenderIP, FCommandParser[1]]));
+ end;
+ end
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Handle unknown commands
+ ////////////////////////////////////////////////////////////////////////////////
+ else
+ begin
+ Log(Format('[COMMAND] Unknown command from %s: %s', [SenderIP, CommandName]));
+
+ // Echo the command back to the client
+ UDPServer.SendCommand(aSenderAddr, 100, BytesOf('Echo: ' + DataStr));
+ end;
+ end
+ else
+ begin
+ Log(Format('[COMMAND] Raw command from %s: %s', [SenderIP, DataStr]));
+
+ // Send response for unstructured commands
+ UDPServer.SendCommand(aSenderAddr, 101, BytesOf('Received: ' + DataStr));
+ end;
+ finally
+ FCommandLock.Leave;
+ end;
+ except
+ on E: Exception do
+ Log(Format('Error processing command: %s', [E.Message]));
+ end;
+end;
+
+procedure TForm1.DisplayScreenShot(const aData: TBytes);
+var
+ MS: TMemoryStream;
+ jpgImage: TJPEGImage;
+begin
+ // Create streams for JPEG loading
+ MS := TMemoryStream.Create;
+ jpgImage := TJPEGImage.Create;
+ try
+ // Load JPEG data directly into stream
+ MS.WriteBuffer(aData[0], Length(aData));
+ MS.Position := 0;
+
+ // Load JPEG from data stream
+ jpgImage.LoadFromStream(MS);
+
+ // Display in TImage component
+ if Assigned(Form1) and Assigned(Form1.Image1) then
+ begin
+ Form1.Image1.Picture.Assign(jpgImage);
+ Form1.Image1.Stretch := True;
+ end;
+
+ finally
+ MS.Free;
+ jpgImage.Free;
+ end;
+end;
+
+procedure TForm1.Log(const AMessage: string);
+begin
+ TThread.Queue(nil,
+ procedure
+ begin
+ try
+ memLog.Lines.Add(Format('[%s] %s', [FormatDateTime('hh:nn:ss.zzz', Now), AMessage]));
+ finally
+ end;
+ end);
+end;
+
+procedure TForm1.memLogKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+begin
+ if (Shift = [ssCtrl]) and (Key = Ord('A')) then
+ memLog.SelectAll
+ else if (Shift = [ssCtrl]) and (Key = Ord('C')) then
+ memLog.CopyToClipboard;
+end;
+
+end.
\ No newline at end of file
diff --git a/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/UDPSocketsLCP_ImageDisplay.groupproj b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/UDPSocketsLCP_ImageDisplay.groupproj
new file mode 100644
index 0000000..d92f069
--- /dev/null
+++ b/Demos/UDP/ncUDPSocketsLCP_ImageDisplay/UDPSocketsLCP_ImageDisplay.groupproj
@@ -0,0 +1,48 @@
+
+
+ {E7EA7F9E-9B7A-4F4D-9B5C-8F4B6A5E2D1C}
+
+
+
+
+
+
+
+
+
+
+ Default.Personality.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/NetCom7.dpk b/NetCom7.dpk
index 6dccda7..58de86d 100644
--- a/NetCom7.dpk
+++ b/NetCom7.dpk
@@ -42,6 +42,7 @@ contains
ncLines in 'Source\ncLines.pas',
ncSocketList in 'Source\ncSocketList.pas',
ncSockets in 'Source\ncSockets.pas',
+ ncSocketsThd in 'Source\ncSocketsThd.pas',
ncCommandPacking in 'Source\ncCommandPacking.pas',
ncCommandHandlers in 'Source\ncCommandHandlers.pas',
ncSources in 'Source\ncSources.pas',
@@ -78,7 +79,13 @@ contains
ncEncTea in 'Source\Encryption\ncEncTea.pas',
ncEncTiger in 'Source\Encryption\ncEncTiger.pas',
ncEncTwofish in 'Source\Encryption\ncEncTwofish.pas',
- ncPendingCommandsList in 'Source\ncPendingCommandsList.pas';
+ ncPendingCommandsList in 'Source\ncPendingCommandsList.pas',
+ ncUDPSockets in 'Source\ncUDPSockets.pas',
+ ncUDPSocketsLCP in 'Source\ncUDPSocketsLCP.pas',
+ ncUDPSocketsDual in 'Source\ncUDPSocketsDual.pas',
+ ncIPUtils in 'Source\ncIPUtils.pas',
+ ncSChannel in 'Source\ncSChannel.pas',
+ ncSocketsDual in 'Source\ncSocketsDual.pas';
end.
diff --git a/NetCom7.dproj b/NetCom7.dproj
index 5dfc635..32d07cc 100644
--- a/NetCom7.dproj
+++ b/NetCom7.dproj
@@ -2,14 +2,15 @@
{57C69AC0-7B5F-43DD-957C-8CC07D9D9092}
NetCom7.dpk
- 19.5
+ 20.2
Release
DCC32
None
True
Win32
- 693267
+ 1741843
Package
+ NetCom7
true
@@ -54,6 +55,11 @@
Base
true
+
+ true
+ Base
+ true
+
true
Base
@@ -142,13 +148,13 @@
android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar
rtl;dbrtl;$(DCC_UsePackage)
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34
$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png
Debug
false
- package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=
+ package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34
Debug
false
true
@@ -172,12 +178,12 @@
$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png
- CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false
+ CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface
Debug
false
- CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false
+ CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple's speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface
Debug
false
@@ -204,6 +210,13 @@
false
true
+
+ Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ Debug
+ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=
+ 1033
+ true
+
false
false
@@ -221,8 +234,8 @@
1033
- CompanyName=;FileVersion=7.2.0.577;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=7.2;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
- 577
+ CompanyName=;FileVersion=7.2.0.636;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=7.2;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)
+ 636
2
false
true
@@ -275,6 +288,7 @@
+
@@ -312,10 +326,56 @@
+
+
+
+
+
+
BITMAP
TNCICON
+
+ BITMAP
+ TNCUDPCLIENT
+
+
+ BITMAP
+ TNCUDPSERVER
+
+
+ BITMAP
+ TNCTCPCLIENTDUAL
+
+
+ BITMAP
+ TNCTCPCLIENTTHD
+
+
+ BITMAP
+ TNCTCPSERVERDUAL
+
+
+ BITMAP
+ TNCTCPSERVERTHD
+
+
+ BITMAP
+ TNCUDPCLIENTDUAL
+
+
+ BITMAP
+ TNCUDPCLIENTLCP
+
+
+ BITMAP
+ TNCUDPSERVERDUAL
+
+
+ BITMAP
+ TNCUDPSERVERLCP
+
Base
@@ -367,7 +427,10 @@
- Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Embarcadero C++Builder Office 2000 Servers Package
+ Embarcadero C++Builder Office XP Servers Package
+ Microsoft Office 2000 Sample Automation Server Wrapper Components
+ Microsoft Office XP Sample Automation Server Wrapper Components
NetCom7.dpk
@@ -378,12 +441,14 @@
True
True
True
+ False
True
True
True
True
+ True
-
+
true
@@ -400,6 +465,12 @@
+
+
+ NetCom7.bpl
+ true
+
+
1
@@ -408,16 +479,6 @@
0
-
-
- classes
- 64
-
-
- classes
- 64
-
-
res\xml
@@ -428,12 +489,6 @@
1
-
-
- library\lib\armeabi-v7a
- 1
-
-
library\lib\armeabi
@@ -486,6 +541,16 @@
1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
+ res\drawable-anydpi-v21
+ 1
+
+
res\values
@@ -506,6 +571,66 @@
1
+
+
+ res\values-v31
+ 1
+
+
+ res\values-v31
+ 1
+
+
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+ res\drawable-anydpi-v26
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
+ res\drawable-anydpi-v33
+ 1
+
+
res\values
@@ -516,6 +641,16 @@
1
+
+
+ res\values-night-v21
+ 1
+
+
+ res\values-night-v21
+ 1
+
+
res\drawable
@@ -686,6 +821,56 @@
1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+ res\drawable-anydpi-v24
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+ res\drawable
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+ res\drawable-night-anydpi-v21
+ 1
+
+
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+ res\drawable-anydpi-v31
+ 1
+
+
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
+ res\drawable-night-anydpi-v31
+ 1
+
+
1
@@ -863,6 +1048,9 @@
1
+
+ 1
+
@@ -1124,6 +1312,7 @@
+
12
diff --git a/NetCom7.dproj.local b/NetCom7.dproj.local
index 6a2e1d7..d576f03 100644
--- a/NetCom7.dproj.local
+++ b/NetCom7.dproj.local
@@ -1,19 +1,2 @@

-
-
-
-
-
- 2020/08/08 06:05:23.000.402,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncSocketList.pas
- 2020/08/08 06:14:41.000.027,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Unit1.pas
- 2020/08/08 06:15:03.000.683,C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLine.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Unit1.pas
- 2020/08/08 07:50:30.000.380,C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLine.pas=C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncLines.pas
- 2020/08/10 13:33:07.000.316,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Icons\TncClientSource.png
- 2020/08/10 13:45:09.000.739,C:\Users\Programmer\Documents\Development\Components\NetCom7\Icons\TncClientSource.png=
- 2020/08/10 13:45:27.000.192,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Icons\TncClientSource.png
- 2020/08/10 13:48:53.000.848,C:\Users\Programmer\Documents\Development\Components\NetCom7\Icons\TncClientSource.png=
- 2020/08/10 13:50:07.000.192,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Icons\TncIcon.bmp
- 2020/08/10 14:10:53.000.681,=C:\Users\Programmer\Documents\Development\Components\NetCom7\PaletteIcons\TncIcon.bmp
- 2020/08/11 19:21:43.000.342,=C:\Users\Programmer\Documents\Development\Components\NetCom7\Source\ncPendingCommandsList.pas
-
-
+
diff --git a/NetCom7.dres b/NetCom7.dres
index 42500fd..0bf391e 100644
Binary files a/NetCom7.dres and b/NetCom7.dres differ
diff --git a/NetCom7.identcache b/NetCom7.identcache
index ae7acea..2afdd9a 100644
Binary files a/NetCom7.identcache and b/NetCom7.identcache differ
diff --git a/NetCom7.otares b/NetCom7.otares
new file mode 100644
index 0000000..0e321c6
Binary files /dev/null and b/NetCom7.otares differ
diff --git a/NetCom7.res b/NetCom7.res
index 762c09e..f4e99c1 100644
Binary files a/NetCom7.res and b/NetCom7.res differ
diff --git a/NetCom7Resource.rc b/NetCom7Resource.rc
index 5ccefa7..68e5906 100644
--- a/NetCom7Resource.rc
+++ b/NetCom7Resource.rc
@@ -1 +1,11 @@
TNCICON BITMAP "PaletteIcons\\TncIcon.bmp"
+TNCUDPCLIENT BITMAP "PaletteIcons\\tncudpclient.bmp"
+TNCUDPSERVER BITMAP "PaletteIcons\\tncudpserver.bmp"
+TNCTCPCLIENTDUAL BITMAP "PaletteIcons\\tnctcpclientdual.bmp"
+TNCTCPCLIENTTHD BITMAP "PaletteIcons\\tnctcpclientthd.bmp"
+TNCTCPSERVERDUAL BITMAP "PaletteIcons\\tnctcpserverdual.bmp"
+TNCTCPSERVERTHD BITMAP "PaletteIcons\\tnctcpserverthd.bmp"
+TNCUDPCLIENTDUAL BITMAP "PaletteIcons\\tncudpclientdual.bmp"
+TNCUDPCLIENTLCP BITMAP "PaletteIcons\\tncudpclientlcp.bmp"
+TNCUDPSERVERDUAL BITMAP "PaletteIcons\\tncudpserverdual.bmp"
+TNCUDPSERVERLCP BITMAP "PaletteIcons\\tncudpserverlcp.bmp"
diff --git a/PaletteIcons/tnctcpclientdual.bmp b/PaletteIcons/tnctcpclientdual.bmp
new file mode 100644
index 0000000..d66b1fb
Binary files /dev/null and b/PaletteIcons/tnctcpclientdual.bmp differ
diff --git a/PaletteIcons/tnctcpclientthd.bmp b/PaletteIcons/tnctcpclientthd.bmp
new file mode 100644
index 0000000..13a2763
Binary files /dev/null and b/PaletteIcons/tnctcpclientthd.bmp differ
diff --git a/PaletteIcons/tnctcpserverdual.bmp b/PaletteIcons/tnctcpserverdual.bmp
new file mode 100644
index 0000000..8a63a8f
Binary files /dev/null and b/PaletteIcons/tnctcpserverdual.bmp differ
diff --git a/PaletteIcons/tnctcpserverthd.bmp b/PaletteIcons/tnctcpserverthd.bmp
new file mode 100644
index 0000000..0c68ca5
Binary files /dev/null and b/PaletteIcons/tnctcpserverthd.bmp differ
diff --git a/PaletteIcons/tncudpclient.bmp b/PaletteIcons/tncudpclient.bmp
new file mode 100644
index 0000000..e7b7e39
Binary files /dev/null and b/PaletteIcons/tncudpclient.bmp differ
diff --git a/PaletteIcons/tncudpclientdual.bmp b/PaletteIcons/tncudpclientdual.bmp
new file mode 100644
index 0000000..dbc10bf
Binary files /dev/null and b/PaletteIcons/tncudpclientdual.bmp differ
diff --git a/PaletteIcons/tncudpclientlcp.bmp b/PaletteIcons/tncudpclientlcp.bmp
new file mode 100644
index 0000000..4dc5408
Binary files /dev/null and b/PaletteIcons/tncudpclientlcp.bmp differ
diff --git a/PaletteIcons/tncudpserver.bmp b/PaletteIcons/tncudpserver.bmp
new file mode 100644
index 0000000..aa3e078
Binary files /dev/null and b/PaletteIcons/tncudpserver.bmp differ
diff --git a/PaletteIcons/tncudpserverdual.bmp b/PaletteIcons/tncudpserverdual.bmp
new file mode 100644
index 0000000..11ffb02
Binary files /dev/null and b/PaletteIcons/tncudpserverdual.bmp differ
diff --git a/PaletteIcons/tncudpserverlcp.bmp b/PaletteIcons/tncudpserverlcp.bmp
new file mode 100644
index 0000000..668ffaa
Binary files /dev/null and b/PaletteIcons/tncudpserverlcp.bmp differ
diff --git a/README.md b/README.md
index 3daf62b..22d8949 100644
--- a/README.md
+++ b/README.md
@@ -1,84 +1,44 @@
# NetCom7
-The fastest communications possible.
-This is version 7.2 of the NetCom package. In this version, the NetCom package is now multi-platform!
-You can compile your apps under all platforms in FireMonkey!
+**The fastest communications possible.**
-This set of components is the fastest possible implementation of socket communications, in any language; this is an extremely optimised code on TCP/IP sockets. Forget using a thread per connection: With this suite you can have as many concurrent connections to your server as you like. Threads are used per request and not per connection, and are maintained in a very fast thread pool class.
+This is an updated version of NetCom7 with **IPv6 support**, **TLS/SSL security**, **new UDP components**, **threaded socket support**, and **dual protocol capabilities**. The library now offers a complete range of networking solutions while maintaining full backward compatibility with existing code.
-The implementation begins with TncTCPServer and TncTCPClient which implements the basic socket communications.
-You can use TncTCPClient and TncTCPServer if all you want is to implement standard (but very fast) socket comms.
+## 🎯 **Latest Updates**
+- **New UDP Support**: Complete UDP component family with three specialized types
+- **Threaded Components**: High-performance TCP components with thread pool processing
+- **Dual Protocol**: Universal components supporting both raw data and structured commands
+- **TLS/SSL Support**: Secure communications across all component types (Windows)
+- **IPv6 Support**: Full IPv4/IPv6 compatibility (client and server must use same family)
+- **New Demos**: Added comprehensive examples showcasing all new features and components
-On top of the TCP/IP sockets, a lightweight protocol is implemented to be able to pack and unpack buffers (simple TCP/IP is streaming and has no notion of a well defined buffer). The set of components implementing this functionality is TncServerSource and TncClientSource. Both of these components implement an ExecCommand (aCmd, aData) which triggers an OnHandleCommand event on the other side (a client can ExecCommand to a server, or a server can ExecCommand to any client). ExecCommand can be blocking or non-blocking (async) depending on how you set its aRequiresResult parameter. If you use the blocking behaviour, the component still handles incoming requests from its peer(s). For example, a ClientSource could be waiting on an ExecCommand to the server, but while waiting it can serve ExecCommand requests from the server!
+## 📋 **Component Overview**
-Simple senario:
- Server:
-
- - You put a TncServerSource on your form.
- If you want you can change the port it is listening to via the
- Port property.
-
- - You implement an OnHandleCommand event handler and,
- depending on aCmd parameter (integer), you respond the result of
- the command via setting the Result of the OnHandleCommand to
- anything you like (TBytes). If an exception is raised while in
- HandleCommand, it is trapped, packed, transfered accross to the
- calling peer, and raised at the peer's issued ExecCommand.
- This way exceptions can be handled as if they were raised locally.
-
- - You set the Active property to true. Your server is ready.
-
- Client:
-
- - You put a TncClientSource on your form.
- You can set Host and Port to whatever you want.
-
- - You set Active property to true.
- Your client is now connected to the server.
-
- - You call ExecCommand (on your TncClientSource), with any
- command number and data that you like. This will send your
- command and data over to the server, call its OnHandleCommand,
- pack the response, and return it as a result to your ExecCommand.
-
- - ExecCommand is blocking (if aRequiresResult parameter is set to true),
- but only for the current command issued.
- The TncClientSource's OnHandleCommand still executes, so,
- while waiting for a command to return, your client socket may be
- processing requests from your server (a server can also
- ExecCommand to a client).
-
- - If you have forgotten to set Active to true and call ExecCommand,
- the TncClientSource will first try to connect, so you can ommit
- setting this property. It will also try to connect if it knows
- it has been disconnected (and the Reconnect property is set to true).
-
-This set of components promises unrivalled speed and that is not just in words:
+### **TCP Components**
-A simple timing test with the NetComVSIndy demo gives the following results:
+| Component | Classes | Description | Best For |
+|-----------|---------|-------------|----------|
+| **Raw TCP** | `TncTCPServer`
`TncTCPClient` | Basic socket functionality | Simple protocols, learning, full control |
+| **Threaded TCP** 🆕 | `TncTCPServerThd`
`TncTCPClientThd` | Raw sockets + thread pool processing | High-performance custom protocols |
+| **Dual TCP** 🆕 | `TncTCPServerDual`
`TncTCPClientDual` | Raw data + command protocol support | Universal applications, maximum flexibility |
+| **Command Sources** | `TncServerSource`
`TncClientSource` | Command-based communication | RPC systems, legacy applications |
+| **Database** | `TncDBServer`
`TncDBDataset` | Database connectivity | Data synchronization, legacy support |
-* Testing Indy... Time taken: 32468 msec
-* Testing NetCom... Time taken: 25109 msec
+### **UDP Components**
-Starting with the base unit, ncSockets.pas, you will see that the implementation does not suffer from slack code, it is rather immediate. The **inline** calling convention has been used wherever deemed appropriate. The very core functions have been tested and optimised by monitoring the performance via timing of large loops and assembly inspection to squeeze out every last bit of performance.
+| Component | Classes | Description | Best For |
+|-----------|---------|-------------|----------|
+| **Raw UDP** 🆕 | `TncUDPServer`
`TncUDPClient` | Basic UDP functionality | Custom protocols, maximum performance |
+| **LCP UDP** 🆕 | `TncUDPServerLCP`
`TncUDPClientLCP` | Command protocol only | RPC systems, structured communication |
+| **Dual UDP** 🆕 | `TncUDPServerDual`
`TncUDPClientDual` | Raw data + command protocol support | Universal UDP applications |
-The biggest difference though in speed gain is due to the architecture. Unlike most typical sockets:
+**Legend:** 🆕 New in this version
-**this set of sockets does neither spawn nor use a thread per connection.**
-This means **you can have as many live connections as you like and you will see NO difference in performance!** A thread pool just waits for any requests; if a thread was to be created per request or per connection, the speed would suffer a lot, as creating a thread is quite heavy time-wise. If the number of requests per second cannot be handled by the thread pool, the thread pool grows up to a maximum defined size, and if it still cannot cope, the client just waits until the server gets a ready thread to process its request.
-
-Particular attention has been given to connection issues also. For example, the disconnects are picked up immediately, and if a line is so bad that the disconnect cannot be picked up, it tackles this by a keep alive packet by which it gets to know the actual status. There is a **Reconnect property** and a KeepAlive property. When a client gets disconnected, for whatever reason, it tries to reconnect transparently and without affecting the main application's performance. This way you do not have to worry about keeping your clients connected.
-
-Compression and encryption are also standard with these components with no extra libraries required. Ofcourse you can use your own compression or encryption if you prefer, but it is rather handy to have just a property you can set on the component.
-
-This set of components can also deal with garbage data thrown at them, they have been used and tested in huge, country-wide projects where all sorts of attacks can be seen.
-
-The effort a programmer has to make to use these components is minimal compared to other frameworks. Please refer to the demos for a better understanding on how to use these components.
-
-Written by Bill Anastasios Demos.
-Special thanks to Daniel Mauric, Tommi Prami, Roland Bengtsson for the extensive testing and suggestions. Thank you so much!
-
-VasDemos[at]yahoo[dot]co[dot]uk
-
-** Delphi RULES **
+## âš¡ **Key Features**
+- **Auto-chunking**: Large data automatically split and reassembled
+- **TLS/SSL**: Secure communications with certificate support
+- **Thread pools**: High-performance concurrent processing
+- **Protocol detection**: Automatic routing of raw vs command data
+- **IPv4/IPv6**: Full IPv4 and IPv6 support (client/server must use same family, no dual-stack sockets)
+- **Cross-platform**: Windows, macOS, Linux compatibility
\ No newline at end of file
diff --git a/Source/NetComRegister.pas b/Source/NetComRegister.pas
index e341655..12fa95a 100644
--- a/Source/NetComRegister.pas
+++ b/Source/NetComRegister.pas
@@ -1,168 +1,240 @@
-unit NetComRegister;
-
-// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// NetCom7 Package
-// 13 Dec 2010, 12/8/2020
-//
-// Written by Demos Bill
-// VasDemos@yahoo.co.uk
-//
-// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-interface
-
-uses
- WinApi.Windows, System.Classes, System.SysUtils, ToolsAPI, DesignIntf, DesignEditors,
-
- ncSockets, ncSources, ncCommandHandlers, ncDBSrv, ncDBCnt;
-
-type
- TncTCPSocketDefaultEditor = class(TDefaultEditor)
- public
- procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
- end;
-
- TncSourceDefaultEditor = class(TDefaultEditor)
- public
- procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
- end;
-
-procedure Register;
-
-implementation
-
-procedure Register;
-begin
- RegisterComponents('NetCom7', [TncTCPServer, TncTCPClient, TncServerSource, TncClientSource, TncCommandHandler, TncDBServer, TncDBDataset]);
-
- RegisterComponentEditor(TncTCPServer, TncTCPSocketDefaultEditor);
- RegisterComponentEditor(TncTCPClient, TncTCPSocketDefaultEditor);
- RegisterComponentEditor(TncServerSource, TncSourceDefaultEditor);
- RegisterComponentEditor(TncClientSource, TncSourceDefaultEditor);
-
- UnlistPublishedProperty(TncDBDataset, 'Connection');
- UnlistPublishedProperty(TncDBDataset, 'ConnectionString');
- RegisterPropertyEditor(TypeInfo(string), TncDBDataset, 'ConnectionString', nil);
-
- ForceDemandLoadState(dlDisable);
-end;
-
-function GetVersion(aMinor: Boolean = True; aRelease: Boolean = True; aBuild: Boolean = True): string;
-var
- VerInfoSize: DWORD;
- VerInfo: Pointer;
- VerValueSize: DWORD;
- VerValue: PVSFixedFileInfo;
- Dummy: DWORD;
- strBuffer: array [0 .. MAX_PATH] of Char;
-begin
- GetModuleFileName(hInstance, strBuffer, MAX_PATH);
- VerInfoSize := GetFileVersionInfoSize(strBuffer, Dummy);
- if VerInfoSize <> 0 then
- begin
- GetMem(VerInfo, VerInfoSize);
- try
- GetFileVersionInfo(strBuffer, 0, VerInfoSize, VerInfo);
- VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
- with VerValue^ do
- begin
- Result := IntToStr(dwFileVersionMS shr 16); // Major always there
- if aMinor then
- Result := Result + '.' + IntToStr(dwFileVersionMS and $FFFF);
- if aRelease then
- Result := Result + '.' + IntToStr(dwFileVersionLS shr 16);
- if aBuild then
- Result := Result + '.' + IntToStr(dwFileVersionLS and $FFFF);
- end;
- finally
- FreeMem(VerInfo, VerInfoSize);
- end;
- end
- else
- Result := '1.0.0.0';
-end;
-
-const
- ICON_SPLASH = 'TNCICON';
- ICON_ABOUT = 'TNCICON';
-
-var
- AboutBoxServices: IOTAAboutBoxServices = nil;
- AboutBoxIndex: Integer = 0;
-
-resourcestring
- resPackageName = 'NetCom7 Network Communications Framework';
- resLicence = 'Full Edition for RAD Studio';
- resAboutCopyright = 'Copyright © 2020 Bill Demos (VasDemos@yahoo.co.uk)';
- resAboutDescription =
- 'Netcom7 Communicatios Framework enables you to use communication components with the ease of use of the Delphi programming language. Create and handle client/server sockets, sources and DB elements with no single line of API calls.';
-
-procedure RegisterSplashScreen;
-var
- SplashScreenHandle: HBitmap;
-begin
- SplashScreenHandle := LoadBitmap(hInstance, ICON_SPLASH);
- try
- SplashScreenServices.AddPluginBitmap(resPackageName + ' ' + GetVersion, SplashScreenHandle, False, resLicence);
- finally
- DeleteObject(SplashScreenHandle);
- end;
-end;
-
-procedure RegisterAboutBox;
-var
- ProductImage: HBitmap;
-begin
- Supports(BorlandIDEServices, IOTAAboutBoxServices, AboutBoxServices);
- ProductImage := LoadBitmap(FindResourceHInstance(hInstance), ICON_ABOUT);
- AboutBoxIndex := AboutBoxServices.AddPluginInfo(resPackageName + GetVersion,
- resAboutCopyright + #13#10 + resAboutDescription, ProductImage, False, resLicence);
-end;
-
-procedure UnregisterAboutBox;
-begin
- if (AboutBoxIndex <> 0) and Assigned(AboutBoxServices) then
- begin
- AboutBoxServices.RemovePluginInfo(AboutBoxIndex);
- AboutBoxIndex := 0;
- AboutBoxServices := nil;
- end;
-end;
-
-{ TncTCPSocketDefaultEditor }
-
-procedure TncTCPSocketDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
-begin
- if CompareText(Prop.GetName, 'ONREADDATA') = 0 then
- begin
- Prop.Edit;
- Continue := False;
- end
- else
- inherited;
-end;
-
-{ TncCustomPeerSourceDefaultEditor }
-
-procedure TncSourceDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
-begin
- if CompareText(Prop.GetName, 'ONHANDLECOMMAND') = 0 then
- begin
- Prop.Edit;
- Continue := False;
- end
- else
- inherited;
-end;
-
-initialization
-
-RegisterSplashScreen;
-RegisterAboutBox;
-
-finalization
-
-UnregisterAboutBox;
-
-end.
+unit NetComRegister;
+
+interface
+
+uses
+ WinApi.Windows, System.Classes, System.SysUtils, ToolsAPI, DesignIntf, DesignEditors,
+ ncSockets, ncSocketsDual, ncSources, ncSocketsThd, ncCommandHandlers, ncDBSrv, ncDBCnt,
+ ncUDPSockets, ncUDPSocketsLCP, ncUDPSocketsDual;
+
+type
+ TncTCPSocketDefaultEditor = class(TDefaultEditor)
+ public
+ procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
+ end;
+
+ TncUDPSocketDefaultEditor = class(TDefaultEditor) // Added UDP editor
+ public
+ procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
+ end;
+
+ TncUDPSocketLCPDefaultEditor = class(TDefaultEditor) // Added UDP LCP editor
+ public
+ procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
+ end;
+
+ TncUDPSocketDualDefaultEditor = class(TDefaultEditor) // Added UDP Dual editor
+ public
+ procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
+ end;
+
+ TncSourceDefaultEditor = class(TDefaultEditor)
+ public
+ procedure EditProperty(const Prop: IProperty; var Continue: Boolean); override;
+ end;
+
+procedure Register;
+
+implementation
+
+procedure Register;
+begin
+ RegisterComponents('NetCom7', [
+ TncTCPServer,
+ TncTCPClient,
+ TncTCPServerDual, // Dual enhanced socket components
+ TncTCPClientDual,
+ TncTCPServerThd, // Threaded socket components
+ TncTCPClientThd,
+ TncUDPServer, // Raw UDP components
+ TncUDPClient,
+ TncUDPServerLCP, // LCP-only UDP components
+ TncUDPClientLCP,
+ TncUDPServerDual, // Dual-mode UDP components
+ TncUDPClientDual,
+ TncServerSource,
+ TncClientSource,
+ TncCommandHandler,
+ TncDBServer,
+ TncDBDataset
+ ]);
+
+ RegisterComponentEditor(TncTCPServer, TncTCPSocketDefaultEditor);
+ RegisterComponentEditor(TncTCPClient, TncTCPSocketDefaultEditor);
+ RegisterComponentEditor(TncTCPServerDual, TncTCPSocketDefaultEditor); // Dual enhanced socket editors
+ RegisterComponentEditor(TncTCPClientDual, TncTCPSocketDefaultEditor);
+ RegisterComponentEditor(TncTCPServerThd, TncTCPSocketDefaultEditor); // Threaded socket editors
+ RegisterComponentEditor(TncTCPClientThd, TncTCPSocketDefaultEditor);
+ RegisterComponentEditor(TncUDPServer, TncUDPSocketDefaultEditor); // Raw UDP editors
+ RegisterComponentEditor(TncUDPClient, TncUDPSocketDefaultEditor);
+ RegisterComponentEditor(TncUDPServerLCP, TncUDPSocketLCPDefaultEditor); // LCP UDP editors
+ RegisterComponentEditor(TncUDPClientLCP, TncUDPSocketLCPDefaultEditor);
+ RegisterComponentEditor(TncUDPServerDual, TncUDPSocketDualDefaultEditor); // Dual UDP editors
+ RegisterComponentEditor(TncUDPClientDual, TncUDPSocketDualDefaultEditor);
+ RegisterComponentEditor(TncServerSource, TncSourceDefaultEditor);
+ RegisterComponentEditor(TncClientSource, TncSourceDefaultEditor);
+
+ UnlistPublishedProperty(TncDBDataset, 'Connection');
+ UnlistPublishedProperty(TncDBDataset, 'ConnectionString');
+ RegisterPropertyEditor(TypeInfo(string), TncDBDataset, 'ConnectionString', nil);
+
+ ForceDemandLoadState(dlDisable);
+end;
+
+function GetVersion(aMinor: Boolean = True; aRelease: Boolean = True; aBuild: Boolean = True): string;
+var
+ VerInfoSize: DWORD;
+ VerInfo: Pointer;
+ VerValueSize: DWORD;
+ VerValue: PVSFixedFileInfo;
+ Dummy: DWORD;
+ strBuffer: array [0 .. MAX_PATH] of Char;
+begin
+ GetModuleFileName(hInstance, strBuffer, MAX_PATH);
+ VerInfoSize := GetFileVersionInfoSize(strBuffer, Dummy);
+ if VerInfoSize <> 0 then
+ begin
+ GetMem(VerInfo, VerInfoSize);
+ try
+ GetFileVersionInfo(strBuffer, 0, VerInfoSize, VerInfo);
+ VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
+ with VerValue^ do
+ begin
+ Result := IntToStr(dwFileVersionMS shr 16); // Major always there
+ if aMinor then
+ Result := Result + '.' + IntToStr(dwFileVersionMS and $FFFF);
+ if aRelease then
+ Result := Result + '.' + IntToStr(dwFileVersionLS shr 16);
+ if aBuild then
+ Result := Result + '.' + IntToStr(dwFileVersionLS and $FFFF);
+ end;
+ finally
+ FreeMem(VerInfo, VerInfoSize);
+ end;
+ end
+ else
+ Result := '1.0.0.0';
+end;
+
+const
+ ICON_SPLASH = 'TNCICON';
+ ICON_ABOUT = 'TNCICON';
+
+var
+ AboutBoxServices: IOTAAboutBoxServices = nil;
+ AboutBoxIndex: Integer = 0;
+
+resourcestring
+ resPackageName = 'NetCom7 Network Communications Framework';
+ resLicence = 'Full Edition for RAD Studio';
+ resAboutCopyright = 'Copyright @ 2020 Bill Demos (VasDemos@yahoo.co.uk)';
+ resAboutDescription =
+ 'Netcom7 Communicatios Framework enables you to use communication components with the ease of use of the Delphi programming language. Create and handle client/server sockets, sources and DB elements with no single line of API calls.';
+
+procedure RegisterSplashScreen;
+var
+ SplashScreenHandle: HBitmap;
+begin
+ SplashScreenHandle := LoadBitmap(hInstance, ICON_SPLASH);
+ try
+ SplashScreenServices.AddPluginBitmap(resPackageName + ' ' + GetVersion, SplashScreenHandle, False, resLicence);
+ finally
+ DeleteObject(SplashScreenHandle);
+ end;
+end;
+
+procedure RegisterAboutBox;
+var
+ ProductImage: HBitmap;
+begin
+ Supports(BorlandIDEServices, IOTAAboutBoxServices, AboutBoxServices);
+ ProductImage := LoadBitmap(FindResourceHInstance(hInstance), ICON_ABOUT);
+ AboutBoxIndex := AboutBoxServices.AddPluginInfo(resPackageName + GetVersion,
+ resAboutCopyright + #13#10 + resAboutDescription, ProductImage, False, resLicence);
+end;
+
+procedure UnregisterAboutBox;
+begin
+ if (AboutBoxIndex <> 0) and Assigned(AboutBoxServices) then
+ begin
+ AboutBoxServices.RemovePluginInfo(AboutBoxIndex);
+ AboutBoxIndex := 0;
+ AboutBoxServices := nil;
+ end;
+end;
+
+{ TncTCPSocketDefaultEditor }
+
+procedure TncTCPSocketDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
+begin
+ if CompareText(Prop.GetName, 'ONREADDATA') = 0 then
+ begin
+ Prop.Edit;
+ Continue := False;
+ end
+ else
+ inherited;
+end;
+
+{ TncUDPSocketDefaultEditor } // Added UDP editor implementation
+
+procedure TncUDPSocketDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
+begin
+ if CompareText(Prop.GetName, 'ONREADDATAGRAM') = 0 then
+ begin
+ Prop.Edit;
+ Continue := False;
+ end
+ else
+ inherited;
+end;
+
+{ TncUDPSocketLCPDefaultEditor } // Added UDP LCP editor implementation
+
+procedure TncUDPSocketLCPDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
+begin
+ if CompareText(Prop.GetName, 'ONCOMMAND') = 0 then
+ begin
+ Prop.Edit;
+ Continue := False;
+ end
+ else
+ inherited;
+end;
+
+{ TncUDPSocketDualDefaultEditor } // Added UDP Dual editor implementation
+
+procedure TncUDPSocketDualDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
+begin
+ if (CompareText(Prop.GetName, 'ONREADDATAGRAM') = 0) or
+ (CompareText(Prop.GetName, 'ONCOMMAND') = 0) then
+ begin
+ Prop.Edit;
+ Continue := False;
+ end
+ else
+ inherited;
+end;
+
+{ TncSourceDefaultEditor }
+
+procedure TncSourceDefaultEditor.EditProperty(const Prop: IProperty; var Continue: Boolean);
+begin
+ if CompareText(Prop.GetName, 'ONHANDLECOMMAND') = 0 then
+ begin
+ Prop.Edit;
+ Continue := False;
+ end
+ else
+ inherited;
+end;
+
+initialization
+ RegisterSplashScreen;
+ RegisterAboutBox;
+
+finalization
+ UnregisterAboutBox;
+
+end.
+
diff --git a/Source/ncDBSrv.pas b/Source/ncDBSrv.pas
index 5280b10..9373b8d 100644
--- a/Source/ncDBSrv.pas
+++ b/Source/ncDBSrv.pas
@@ -1,4 +1,8 @@
// This is the DB server part of netcom7
+//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
// Written by Demos Bill
//
// Date completed: 2011 / 5 / 5
@@ -34,7 +38,7 @@ interface
// Add an array of tables and if one of them is altered then void all the ReadyResults.
TReadyQueryItem = class
private
- FSerialiser: TCriticalSection;
+ FSerialiser: TObject; // TMonitor synchronization object
// Ready results holds a string list of Parameters, and the Objects are TBytes
ReadyResults: TStringList;
protected
@@ -43,7 +47,7 @@ TReadyQueryItem = class
public
ADOQuery: TADOQuery;
- constructor Create(const aConnectionString, aSQL: string; aSerialiser: TCriticalSection);
+ constructor Create(const aConnectionString, aSQL: string; aSerialiser: TObject);
destructor Destroy; override;
function GetResult(aParams: TBytes; aUseCache: Boolean): TBytes;
function Update(aUpdates: _recordset): TBytes;
@@ -52,7 +56,7 @@ TReadyQueryItem = class
TReadyQueryList = class
private
- Serialiser: TCriticalSection;
+ Serialiser: TObject; // TMonitor synchronization object
// A Sorted String List of SQL statements
// The Data contains a TReadyQueryItem
ReadyQueries: TStringList;
@@ -68,7 +72,7 @@ TReadyQueryList = class
TncDBServer = class(TncCustomCommandHandler)
private
- PropertyLock: TCriticalSection;
+ PropertyLock: TObject; // TMonitor synchronization object
ReadyQueryList: TReadyQueryList;
FCacheResponses: Boolean;
@@ -101,7 +105,7 @@ implementation
constructor TncDBServer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
- PropertyLock := TCriticalSection.Create;
+ PropertyLock := TObject.Create;
ReadyQueryList := TReadyQueryList.Create;
FCacheResponses := True;
@@ -146,7 +150,7 @@ function TncDBServer.DBServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd
begin
SetLength(Result, 0);
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
if Assigned(FADOConnection) then
begin
@@ -162,7 +166,7 @@ function TncDBServer.DBServerHandleCommand(Sender: TObject; aLine: TncLine; aCmd
end;
end;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
case aCmd of
@@ -263,47 +267,47 @@ procedure TncDBServer.Notification(AComponent: TComponent; Operation: TOperation
function TncDBServer.GetADOConnection: TADOConnection;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FADOConnection;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncDBServer.SetADOConnection(const Value: TADOConnection);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FADOConnection := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncDBServer.GetCacheResponses: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCacheResponses;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncDBServer.SetCacheResponses(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCacheResponses := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
{ TReadyQueryItem }
-constructor TReadyQueryItem.Create(const aConnectionString, aSQL: string; aSerialiser: TCriticalSection);
+constructor TReadyQueryItem.Create(const aConnectionString, aSQL: string; aSerialiser: TObject);
begin
FSerialiser := aSerialiser;
@@ -360,7 +364,7 @@ function TReadyQueryItem.GetResult(aParams: TBytes; aUseCache: Boolean): TBytes;
Ndx: Integer;
ResObj: TResObj;
begin
- FSerialiser.Acquire;
+ TMonitor.Enter(FSerialiser);
try
strParams := StringOf(aParams);
@@ -394,7 +398,7 @@ function TReadyQueryItem.GetResult(aParams: TBytes; aUseCache: Boolean): TBytes;
Result := TResObj(ReadyResults.Objects[Ndx]).Content;
finally
- FSerialiser.Release;
+ TMonitor.Exit(FSerialiser);
end;
end;
@@ -413,7 +417,7 @@ function TReadyQueryItem.Update(aUpdates: _recordset): TBytes;
var
tmpDS: TADODataSet;
begin
- FSerialiser.Acquire;
+ TMonitor.Enter(FSerialiser);
try
tmpDS := TADODataSet.Create(nil);
try
@@ -426,7 +430,7 @@ function TReadyQueryItem.Update(aUpdates: _recordset): TBytes;
tmpDS.Free;
end;
finally
- FSerialiser.Release;
+ TMonitor.Exit(FSerialiser);
end;
end;
@@ -444,7 +448,7 @@ procedure TReadyQueryItem.ClearCachedResults;
constructor TReadyQueryList.Create;
begin
- Serialiser := TCriticalSection.Create;
+ Serialiser := TObject.Create;
ReadyQueries := TStringList.Create;
ReadyQueries.CaseSensitive := False;
ReadyQueries.Sorted := True;
@@ -468,7 +472,7 @@ function TReadyQueryList.GetQuery(const aSQL: string): TReadyQueryItem;
var
Ndx: Integer;
begin
- Serialiser.Acquire;
+ TMonitor.Enter(Serialiser);
try
Ndx := ReadyQueries.IndexOf(aSQL);
if (Ndx < 0) then // not found
@@ -479,17 +483,17 @@ function TReadyQueryList.GetQuery(const aSQL: string): TReadyQueryItem;
else
Result := TReadyQueryItem(ReadyQueries.Objects[Ndx]);
finally
- Serialiser.Release;
+ TMonitor.Exit(Serialiser);
end;
end;
procedure TReadyQueryList.SetConnectionString(const aConnectionString: string);
begin
- Serialiser.Acquire;
+ TMonitor.Enter(Serialiser);
try
FConnectionString := aConnectionString;
finally
- Serialiser.Release;
+ TMonitor.Exit(Serialiser);
end;
end;
diff --git a/Source/ncIPUtils.pas b/Source/ncIPUtils.pas
new file mode 100644
index 0000000..b6af661
--- /dev/null
+++ b/Source/ncIPUtils.pas
@@ -0,0 +1,300 @@
+unit ncIPUtils;
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 Package - IP Address utils
+//
+//
+//
+// 21/01/2025
+// - Initial creation
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+interface
+
+uses
+ {$IFDEF MSWINDOWS}
+ Winapi.Windows, Winapi.Winsock2,
+ {$ELSE}
+ Posix.SysSocket, Posix.NetDB, Posix.NetIf, Posix.ArpaInet,
+ {$ENDIF}
+ System.SysUtils, System.Classes;
+
+const
+ IPV6_ADDR_LEN = 16; // IPv6 address length in bytes
+ IPV6_STR_MAX_LEN = 46; // Maximum string length for IPv6 address including null terminator
+ SOCKADDR_STORAGE_SIZE = 128; // Size of sockaddr_storage structure
+
+ {$IFDEF MSWINDOWS}
+ AF_INET6 = 23;
+ {$ENDIF}
+
+type
+ TIn6Addr = record
+ case Integer of
+ 0: (s6_bytes: array[0..15] of Byte);
+ 1: (s6_words: array[0..7] of Word);
+ end;
+ PIn6Addr = ^TIn6Addr;
+
+ TSockAddrIn6 = record
+ sin6_family: Word; // AF_INET6
+ sin6_port: Word; // Transport layer port #
+ sin6_flowinfo: Cardinal; // IPv6 flow information
+ sin6_addr: TIn6Addr; // IPv6 address
+ sin6_scope_id: Cardinal; // Set of interfaces for scope
+ end;
+ PSockAddrIn6 = ^TSockAddrIn6;
+
+ // Socket storage structure - used for both IPv4 and IPv6
+ TSockAddrStorage = record
+ ss_family: Word; // Address family
+ __ss_pad1: array [0..5] of Byte; // 6 bytes of padding
+ __ss_align: Int64; // Force alignment
+ __ss_pad2: array [0..111] of Byte; // 112 bytes of padding
+ end;
+ PSockAddrStorage = ^TSockAddrStorage;
+
+ {$IFNDEF MSWINDOWS}
+ // Define Windows-compatible types for Linux
+ TSockAddrIn = packed record
+ sin_family: Word;
+ sin_port: Word;
+ sin_addr: record
+ S_un_b: record
+ s_b1, s_b2, s_b3, s_b4: Byte;
+ end;
+ end;
+ sin_zero: array[0..7] of Byte;
+ end;
+ PSockAddrIn = ^TSockAddrIn;
+ {$ENDIF}
+
+ EIPError = class(Exception);
+
+ // Function types for dynamic loading
+ {$IFDEF MSWINDOWS}
+ TInetPton = function(Family: Integer; const pszAddrString: PAnsiChar;
+ pAddrBuf: Pointer): Integer; stdcall;
+ TInetNtop = function(Family: Integer; pAddr: Pointer;
+ pStringBuf: PAnsiChar; StringBufSize: size_t): PAnsiChar; stdcall;
+ {$ENDIF}
+
+ TncIPUtils = class
+ private
+ {$IFDEF MSWINDOWS}
+ class var
+ InetPton: TInetPton;
+ InetNtop: TInetNtop;
+ class function LoadIPv6Functions: Boolean;
+ {$ENDIF}
+ public
+ class constructor Create;
+
+ // SockAddrStorage methods
+ class function StorageToString(const Storage: TSockAddrStorage): string;
+ class function IsIPv6Storage(const Storage: TSockAddrStorage): Boolean;
+ class function GetStorageFamily(const Storage: TSockAddrStorage): Word;
+ class function StorageToIPv6Address(const Storage: TSockAddrStorage;
+ out Addr: TSockAddrIn6): Boolean;
+ class function GetIPFromStorage(const Storage: TSockAddrStorage): string;
+ class function GetPortFromStorage(const Storage: TSockAddrStorage): Word;
+
+ // Existing IPv6 methods
+ class function IsIPv6ValidAddress(const AddrStr: string): Boolean;
+ class function AddressToString(const Addr: TIn6Addr): string;
+ class function StringToAddress(const AddrStr: string; out Addr: TIn6Addr): Boolean;
+ class function IsLinkLocal(const AddrStr: string): Boolean;
+ class function NormalizeAddress(const AddrStr: string): string;
+ class function AddressToPresentation(const Addr: TIn6Addr): string;
+ class function PresentationToAddress(const Present: string; var Addr: TIn6Addr): Boolean;
+ end;
+
+implementation
+
+{$IFDEF MSWINDOWS}
+var
+ Ws2_32DllHandle: THandle;
+
+
+class function TncIPUtils.LoadIPv6Functions: Boolean;
+begin
+ Result := False;
+
+ if Ws2_32DllHandle = 0 then
+ Ws2_32DllHandle := LoadLibrary('ws2_32.dll');
+
+ if Ws2_32DllHandle <> 0 then
+ begin
+ InetPton := GetProcAddress(Ws2_32DllHandle, 'inet_pton');
+ InetNtop := GetProcAddress(Ws2_32DllHandle, 'inet_ntop');
+ Result := Assigned(InetPton) and Assigned(InetNtop);
+ end;
+end;
+{$ENDIF}
+
+class constructor TncIPUtils.Create;
+begin
+ {$IFDEF MSWINDOWS}
+ if not LoadIPv6Functions then
+ raise EIPError.Create('Failed to load IPv6 functions from ws2_32.dll');
+ {$ENDIF}
+end;
+
+class function TncIPUtils.StorageToString(const Storage: TSockAddrStorage): string;
+begin
+ case Storage.ss_family of
+ AF_INET:
+ begin
+ var addr_in := PSockAddrIn(@Storage)^;
+ with addr_in.sin_addr.S_un_b do
+ Result := Format('%d.%d.%d.%d', [s_b1, s_b2, s_b3, s_b4]);
+ end;
+
+ AF_INET6:
+ begin
+ var addr_in6 := PSockAddrIn6(@Storage)^;
+ Result := AddressToString(addr_in6.sin6_addr);
+ if IsLinkLocal(Result) then
+ Result := Format('%s%%%d', [Result, addr_in6.sin6_scope_id]);
+ end;
+ else
+ Result := '';
+ end;
+end;
+
+class function TncIPUtils.IsIPv6Storage(const Storage: TSockAddrStorage): Boolean;
+begin
+ Result := Storage.ss_family = AF_INET6;
+end;
+
+class function TncIPUtils.GetStorageFamily(const Storage: TSockAddrStorage): Word;
+begin
+ Result := Storage.ss_family;
+end;
+
+class function TncIPUtils.StorageToIPv6Address(const Storage: TSockAddrStorage;
+ out Addr: TSockAddrIn6): Boolean;
+begin
+ Result := Storage.ss_family = AF_INET6;
+ if Result then
+ Addr := PSockAddrIn6(@Storage)^;
+end;
+
+class function TncIPUtils.GetIPFromStorage(const Storage: TSockAddrStorage): string;
+begin
+ Result := StorageToString(Storage);
+end;
+
+class function TncIPUtils.GetPortFromStorage(const Storage: TSockAddrStorage): Word;
+begin
+ case Storage.ss_family of
+ AF_INET: Result := ntohs(PSockAddrIn(@Storage)^.sin_port);
+ AF_INET6: Result := ntohs(PSockAddrIn6(@Storage)^.sin6_port);
+ else
+ Result := 0;
+ end;
+end;
+
+class function TncIPUtils.IsIPv6ValidAddress(const AddrStr: string): Boolean;
+var
+ Addr: TIn6Addr;
+begin
+ Result := StringToAddress(AddrStr, Addr);
+end;
+
+class function TncIPUtils.AddressToString(const Addr: TIn6Addr): string;
+var
+ StringBuffer: array[0..IPV6_STR_MAX_LEN-1] of AnsiChar;
+begin
+ {$IFDEF MSWINDOWS}
+ if InetNtop(AF_INET6, @Addr, StringBuffer, IPV6_STR_MAX_LEN) = nil then
+ raise EIPError.Create('Failed to convert IPv6 address to string: ' +
+ SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ if Posix.ArpaInet.inet_ntop(AF_INET6, @Addr, StringBuffer, IPV6_STR_MAX_LEN) = nil then
+ raise EIPError.Create('Failed to convert IPv6 address to string: ' +
+ SysErrorMessage(GetLastError));
+ {$ENDIF}
+
+ Result := string(AnsiString(StringBuffer));
+end;
+
+class function TncIPUtils.StringToAddress(const AddrStr: string; out Addr: TIn6Addr): Boolean;
+var
+ AnsiAddr: AnsiString;
+begin
+ AnsiAddr := AnsiString(AddrStr);
+ {$IFDEF MSWINDOWS}
+ Result := InetPton(AF_INET6, PAnsiChar(AnsiAddr), @Addr) = 1;
+ {$ELSE}
+ Result := Posix.ArpaInet.inet_pton(AF_INET6, PAnsiChar(AnsiAddr), @Addr) = 1;
+ {$ENDIF}
+end;
+
+class function TncIPUtils.IsLinkLocal(const AddrStr: string): Boolean;
+begin
+ // Link-local addresses start with fe80::/10
+ Result := (Length(AddrStr) >= 4) and
+ (LowerCase(Copy(AddrStr, 1, 4)) = 'fe80');
+end;
+
+class function TncIPUtils.NormalizeAddress(const AddrStr: string): string;
+var
+ Addr: TIn6Addr;
+begin
+ if StringToAddress(AddrStr, Addr) then
+ Result := AddressToString(Addr)
+ else
+ raise EIPError.CreateFmt('Invalid IPv6 address: %s', [AddrStr]);
+end;
+
+class function TncIPUtils.AddressToPresentation(const Addr: TIn6Addr): string;
+var
+ i: Integer;
+ NonZeroFound: Boolean;
+begin
+ Result := '';
+ NonZeroFound := False;
+
+ // Convert words to hex representation
+ for i := 0 to 7 do
+ begin
+ if (Addr.s6_words[i] <> 0) or NonZeroFound then
+ begin
+ if Result <> '' then
+ Result := Result + ':';
+ Result := Result + IntToHex(Addr.s6_words[i], 1);
+ NonZeroFound := True;
+ end;
+ end;
+
+ // Handle all-zero case
+ if Result = '' then
+ Result := '::'
+ else if not NonZeroFound then
+ Result := Result + ':';
+end;
+
+class function TncIPUtils.PresentationToAddress(const Present: string;
+ var Addr: TIn6Addr): Boolean;
+begin
+ FillChar(Addr, SizeOf(Addr), 0);
+ Result := StringToAddress(Present, Addr);
+end;
+
+initialization
+ {$IFDEF MSWINDOWS}
+ Ws2_32DllHandle := 0;
+ {$ENDIF}
+
+finalization
+ {$IFDEF MSWINDOWS}
+ if Ws2_32DllHandle <> 0 then
+ FreeLibrary(Ws2_32DllHandle);
+ {$ENDIF}
+
+end.
+
+
diff --git a/Source/ncLines.pas b/Source/ncLines.pas
index d6bf8d7..833a86e 100644
--- a/Source/ncLines.pas
+++ b/Source/ncLines.pas
@@ -6,6 +6,21 @@
// socket, organised in an object which contains the handle of the socket,
// and also makes sure it checks every API command for errors
//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 13/07/2025 - by J.Pauwels
+// - Added TLS handshake callback integration through OnBeforeConnected architecture
+// - Integrated TLS support into line-level socket operations
+// - Added secure communication layer for both server and client connections
+//
+// 14/01/2025 - by J.Pauwels
+// - Fix Linux compilation
+// - Added UDP support
+// - Added IPV6 support
+// - Removed problematic threading approach from CreateClientHandle
+// - Implemented socket-level timeout control for more reliable connection handling
+//
// 9/8/2020
// - Completed multiplatform support, now NetCom can be compiled in all
// platforms
@@ -33,27 +48,58 @@ interface
Winapi.Windows, Winapi.Winsock2,
{$ELSE}
Posix.SysTypes, Posix.SysSelect, Posix.SysSocket, Posix.NetDB, Posix.SysTime,
- Posix.Unistd, {Posix.ArpaInet,}
+ Posix.Unistd, Posix.Errno,
{$ENDIF}
System.SyncObjs,
System.Math,
System.SysUtils,
System.Diagnostics,
- ncThreads;
+ System.IOUtils,
+ System.Classes,
+ ncIPUtils;
const
// Flag that indicates that the socket is intended for bind() + listen() when constructing it
AI_PASSIVE = 1;
+ IPV6_V6ONLY = 27;
+ AI_ADDRCONFIG = $0020; // Return only if local system configured
+ AI_NUMERICHOST = $0004; // Don't use name resolution
+ INET6_ADDRSTRLEN = 46;
+ // Maximum length of IPv6 address string including null terminator
{$IFDEF MSWINDOWS}
InvalidSocket = Winapi.Winsock2.INVALID_SOCKET;
SocketError = SOCKET_ERROR;
+ WSAETIMEDOUT = 10060;
{$ELSE}
InvalidSocket = -1;
SocketError = -1;
IPPROTO_TCP = 6;
+ IPPROTO_UDP = 17;
+ IPPROTO_IPV6 = 41;
TCP_NODELAY = $0001;
+ ETIMEDOUT = 110;
+ ECONNREFUSED = 111;
{$ENDIF}
+type
+ TSocketType = (stUDP, stTCP);
+
+const
+ CSocketTypeNames: array [TSocketType] of string = ('UDP', 'TCP');
+
+ CRawSocketTypes: array [TSocketType] of Integer = (SOCK_DGRAM, // UDP datagram
+ SOCK_STREAM // TCP stream
+ );
+
+ CRawProtocolTypes: array [TSocketType] of Integer = (IPPROTO_UDP,
+ IPPROTO_TCP);
+
+type
+ TAddressType = (afIPv4, afIPv6);
+
+const
+ CAddressTypeNames: array [TAddressType] of string = ('IPv4', 'IPv6');
+
type
{$IFDEF MSWINDOWS}
TSocketHandle = Winapi.Winsock2.TSocket;
@@ -72,7 +118,8 @@ TAddrInfoW = record
ai_next: PAddrInfoW;
end;
- TGetAddrInfoW = function(NodeName: PWideChar; ServiceName: PWideChar; Hints: PAddrInfoW; ppResult: PPAddrInfoW): Integer; stdcall;
+ TGetAddrInfoW = function(NodeName: PWideChar; ServiceName: PWideChar;
+ Hints: PAddrInfoW; ppResult: PPAddrInfoW): Integer; stdcall;
TFreeAddrInfoW = procedure(ai: PAddrInfoW); stdcall;
{$ELSE}
TSocketHandle = Integer;
@@ -85,12 +132,6 @@ TncLine = class; // Forward declaration
TncLineOnConnectDisconnect = procedure(aLine: TncLine) of object;
- TConnectThread = class(TncReadyThread)
- public
- Line: TncLine;
- ConnectResult: Integer;
- procedure ProcessEvent; override;
- end;
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TncLine
// Bring in all functionality from WinSock API, with appropriate exception raising on errors
@@ -99,6 +140,9 @@ TncLine = class(TObject)
private const
DefaultConnectTimeout = 100; // msec
private
+ FKind: TSocketType;
+ FFamily: TAddressType;
+ FMaxPort: Integer;
FActive: Boolean;
FLastSent: Int64;
FLastReceived: Int64;
@@ -106,15 +150,19 @@ TncLine = class(TObject)
FDataObject: TObject;
FOnConnected: TncLineOnConnectDisconnect;
FOnDisconnected: TncLineOnConnectDisconnect;
+ FOnBeforeConnected: TncLineOnConnectDisconnect; // Called before OnConnected for TLS setup
+ FOnBeforeDisconnected: TncLineOnConnectDisconnect; // Called before OnDisconnected for TLS cleanup
private
- PropertyLock: TCriticalSection;
+ PropertyLock: TObject; // TMonitor synchronization object
FHandle: TSocketHandle;
FConnectTimeout: Integer;
+
{$IFDEF MSWINDOWS}
AddrResult: PAddrInfoW;
{$ELSE}
AddrResult: Paddrinfo;
{$ENDIF}
+ function IsConnectionBased: Boolean;
procedure SetConnected;
procedure SetDisconnected;
function GetReceiveTimeout: Integer;
@@ -125,12 +173,20 @@ TncLine = class(TObject)
procedure SetLastReceived(const Value: Int64);
function GetLastSent: Int64;
procedure SetLastSent(const Value: Int64);
+ protected const
+ DefaultKind = stTCP;
+
+ const
+ DefaultFamily = afIPv4;
protected
+ procedure SetKind(const AKind: TSocketType);
+ procedure SetFamily(const Value: TAddressType);
function CreateLineObject: TncLine; virtual;
procedure Check(aCmdRes: Integer); inline;
// API functions
- procedure CreateClientHandle(const aHost: string; const aPort: Integer);
+ procedure CreateClientHandle(const aHost: string; const aPort: Integer;
+ const aBroadcast: Boolean = False);
procedure CreateServerHandle(const aPort: Integer);
procedure DestroyHandle;
@@ -141,35 +197,51 @@ TncLine = class(TObject)
procedure EnableNoDelay; inline;
procedure EnableKeepAlive; inline;
+ procedure EnableBroadcast; inline;
+ procedure EnableIPv6Only; inline;
+
procedure EnableReuseAddress; inline;
procedure SetReceiveSize(const aBufferSize: Integer);
procedure SetWriteSize(const aBufferSize: Integer);
- property OnConnected: TncLineOnConnectDisconnect read FOnConnected write FOnConnected;
- property OnDisconnected: TncLineOnConnectDisconnect read FOnDisconnected write FOnDisconnected;
+ property OnConnected: TncLineOnConnectDisconnect read FOnConnected
+ write FOnConnected;
+ property OnDisconnected: TncLineOnConnectDisconnect read FOnDisconnected
+ write FOnDisconnected;
+ property OnBeforeConnected: TncLineOnConnectDisconnect read FOnBeforeConnected
+ write FOnBeforeConnected;
+ property OnBeforeDisconnected: TncLineOnConnectDisconnect read FOnBeforeDisconnected
+ write FOnBeforeDisconnected;
public
constructor Create; overload; virtual;
destructor Destroy; override;
+ property Kind: TSocketType read FKind;
+ property Family: TAddressType read FFamily;
property Handle: TSocketHandle read FHandle;
property Active: Boolean read FActive;
property LastSent: Int64 read GetLastSent write SetLastSent;
property LastReceived: Int64 read GetLastReceived write SetLastReceived;
property PeerIP: string read FPeerIP;
property DataObject: TObject read FDataObject write FDataObject;
- property ConnectTimeout: Integer read FConnectTimeout write FConnectTimeout default DefaultConnectTimeout;
- property ReceiveTimeout: Integer read GetReceiveTimeout write SetReceiveTimeout;
+ property ConnectTimeout: Integer read FConnectTimeout write FConnectTimeout
+ default DefaultConnectTimeout;
+ property ReceiveTimeout: Integer read GetReceiveTimeout
+ write SetReceiveTimeout;
property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
end;
-function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout: Cardinal): TSocketHandleArray;
-function ReadableAnySocket(const aSocketHandleArray: TSocketHandleArray; const aTimeout: Cardinal): Boolean; inline;
+function Readable(const aSocketHandleArray: TSocketHandleArray;
+ const aTimeout: Cardinal): TSocketHandleArray;
+function ReadableAnySocket(const aSocketHandleArray: TSocketHandleArray;
+ const aTimeout: Cardinal): Boolean; inline;
implementation
// Readable checks to see if any socket handles have data
// and if so, overwrites aReadFDS with the data
-function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout: Cardinal): TSocketHandleArray;
+function Readable(const aSocketHandleArray: TSocketHandleArray;
+ const aTimeout: Cardinal): TSocketHandleArray;
{$IFDEF MSWINDOWS}
var
TimeoutValue: timeval;
@@ -193,7 +265,8 @@ function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout:
if FDSetPtr^.fd_count > 0 then
begin
SetLength(Result, FDSetPtr^.fd_count);
- move(FDSetPtr^.fd_array[0], Result[0], FDSetPtr^.fd_count * SizeOf(TSocketHandle));
+ move(FDSetPtr^.fd_array[0], Result[0], FDSetPtr^.fd_count *
+ SizeOf(TSocketHandle));
end
else
SetLength(Result, 0); // This is needed with newer compilers
@@ -201,6 +274,7 @@ function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout:
FreeMem(FDSetPtr);
end;
end;
+
{$ELSE}
var
@@ -228,10 +302,12 @@ function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout:
begin
SocketHandle := aSocketHandleArray[i];
FDNdx := SocketHandle div NFDBITS;
- FDSetPtr.fds_bits[FDNdx] := FDSetPtr.fds_bits[FDNdx] or (1 shl (SocketHandle mod NFDBITS));
+ FDSetPtr.fds_bits[FDNdx] := FDSetPtr.fds_bits[FDNdx] or
+ (1 shl (SocketHandle mod NFDBITS));
end;
- ReadySockets := Select(FDArrayLen * NFDBITS, FDSetPtr, nil, nil, @TimeoutValue);
+ ReadySockets := Select(FDArrayLen * NFDBITS, FDSetPtr, nil, nil,
+ @TimeoutValue);
if ReadySockets > 0 then
begin
@@ -242,7 +318,8 @@ function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout:
begin
SocketHandle := aSocketHandleArray[i];
FDNdx := SocketHandle div NFDBITS;
- if FDSetPtr.fds_bits[FDNdx] and (1 shl (SocketHandle mod NFDBITS)) <> 0 then
+ if FDSetPtr.fds_bits[FDNdx] and (1 shl (SocketHandle mod NFDBITS)) <> 0
+ then
begin
Result[ResultNdx] := SocketHandle;
ResultNdx := ResultNdx + 1;
@@ -257,18 +334,45 @@ function Readable(const aSocketHandleArray: TSocketHandleArray; const aTimeout:
end;
{$ENDIF}
-function ReadableAnySocket(const aSocketHandleArray: TSocketHandleArray; const aTimeout: Cardinal): Boolean;
+function ReadableAnySocket(const aSocketHandleArray: TSocketHandleArray;
+ const aTimeout: Cardinal): Boolean;
begin
Result := Length(Readable(aSocketHandleArray, aTimeout)) > 0;
end;
+function IsBroadcastAddress(const aHost: string): Boolean;
+var
+ Octets: TArray;
+ LastOctet: Integer;
+begin
+ // Split the IP into octets
+ Octets := aHost.Split(['.']);
+
+ // Basic validation
+ if Length(Octets) <> 4 then
+ Exit(False);
+
+ // Try to parse last octet
+ if not TryStrToInt(Octets[3], LastOctet) then
+ Exit(False);
+
+ Result :=
+ // Global broadcast
+ (aHost = '255.255.255.255') or
+ // Limited broadcast
+ (aHost = '0.0.0.0') or
+ // Subnet broadcast (last octet is 255)
+ (LastOctet = 255);
+end;
+
{$IFDEF MSWINDOWS}
var
DllGetAddrInfo: TGetAddrInfoW = nil;
DllFreeAddrInfo: TFreeAddrInfoW = nil;
-procedure GetAddressInfo(NodeName: PWideChar; ServiceName: PWideChar; Hints: PAddrInfoW; ppResult: PPAddrInfoW);
+procedure GetAddressInfo(NodeName: PWideChar; ServiceName: PWideChar;
+ Hints: PAddrInfoW; ppResult: PPAddrInfoW);
var
iRes: Integer;
begin
@@ -294,9 +398,10 @@ constructor TncLine.Create;
begin
inherited Create;
- PropertyLock := TCriticalSection.Create;
-
+ PropertyLock := TObject.Create;
FHandle := InvalidSocket;
+ FKind := DefaultKind;
+ FFamily := DefaultFamily;
FConnectTimeout := DefaultConnectTimeout;
FActive := False;
@@ -307,6 +412,8 @@ constructor TncLine.Create;
FOnConnected := nil;
FOnDisconnected := nil;
+ FOnBeforeConnected := nil;
+ FOnBeforeDisconnected := nil;
end;
destructor TncLine.Destroy;
@@ -315,13 +422,14 @@ destructor TncLine.Destroy;
DestroyHandle;
PropertyLock.Free;
-
inherited Destroy;
end;
function TncLine.CreateLineObject: TncLine;
begin
Result := TncLine.Create;
+ Result.SetKind(Kind);
+ Result.SetFamily(Family);
end;
/// /////////////////////////////////////////////////////////////////////////////
@@ -336,30 +444,76 @@ procedure TncLine.Check(aCmdRes: Integer);
{$ENDIF}
end;
-procedure TncLine.CreateClientHandle(const aHost: string; const aPort: Integer);
+procedure TncLine.CreateClientHandle(const aHost: string; const aPort: Integer;
+ const aBroadcast: Boolean = False);
var
- ConnectThread: TConnectThread;
{$IFDEF MSWINDOWS}
Hints: TAddrInfoW;
+ ErrorCode: Integer;
{$ELSE}
Hints: addrinfo;
AnsiHost, AnsiPort: RawByteString;
{$ENDIF}
+ ResolveHost: string;
+ ConnectResult: Integer;
begin
try
+ // Validate host for IPv6 if applicable
+ if (FFamily = afIPv6) and (aHost <> '') and (LowerCase(aHost) <> 'localhost') then
+ begin
+ // Validate IPv6 address format if it looks like an IPv6 address
+ if (Pos(':', aHost) > 0) and not TncIPUtils.IsIPv6ValidAddress(aHost) then
+ raise EIPError.CreateFmt('Invalid IPv6 address format: %s', [aHost]);
+ end;
+
+ if IsBroadcastAddress(aHost) and not aBroadcast then
+ raise Exception.Create('Cannot use broadcast address when Broadcast is False');
+
FillChar(Hints, SizeOf(Hints), 0);
- Hints.ai_family := AF_INET;
- Hints.ai_socktype := SOCK_STREAM;
- Hints.ai_protocol := IPPROTO_TCP;
+
+ // Set address family and related flags based on FFamily
+ case FFamily of
+ afIPv4:
+ begin
+ Hints.ai_family := AF_INET;
+ if LowerCase(aHost) = 'localhost' then
+ ResolveHost := '127.0.0.1'
+ else
+ ResolveHost := aHost;
+ end;
+ afIPv6:
+ begin
+ Hints.ai_family := AF_INET6;
+ Hints.ai_flags := AI_ADDRCONFIG;
+ // If it's a valid IPv6 address, normalize it
+ if (Pos(':', aHost) > 0) and TncIPUtils.IsIPv6ValidAddress(aHost) then
+ ResolveHost := TncIPUtils.NormalizeAddress(aHost)
+ else
+ ResolveHost := aHost;
+
+ // Handle link-local addresses correctly
+ if TncIPUtils.IsLinkLocal(ResolveHost) then
+ begin
+ // Extract scope ID if present in the address
+ var ScopePos := Pos('%', ResolveHost);
+ if ScopePos > 0 then
+ ResolveHost := Copy(ResolveHost, 1, ScopePos - 1);
+ end;
+ end;
+ end;
+
+ Hints.ai_socktype := CRawSocketTypes[FKind];
+ Hints.ai_protocol := CRawProtocolTypes[FKind];
// Resolve the server address and port
{$IFDEF MSWINDOWS}
- GetAddressInfo(PChar(aHost), PChar(IntToStr(aPort)), @Hints, @AddrResult);
+ GetAddressInfo(PChar(ResolveHost), PChar(IntToStr(aPort)), @Hints,
+ @AddrResult);
{$ELSE}
- AnsiHost := RawByteString(aHost);
+ AnsiHost := RawByteString(ResolveHost);
AnsiPort := RawByteString(IntToStr(aPort));
-
- GetAddrInfo(MarshaledAString(AnsiHost), MarshaledAString(AnsiPort), Hints, AddrResult);
+ GetAddrInfo(MarshaledAString(AnsiHost), MarshaledAString(AnsiPort), Hints,
+ AddrResult);
{$ENDIF}
try
// Create a SOCKET for connecting to server
@@ -369,27 +523,62 @@ procedure TncLine.CreateClientHandle(const aHost: string; const aPort: Integer);
{$IFNDEF MSWINDOWS}
EnableReuseAddress;
{$ENDIF}
- ConnectThread := TConnectThread.Create;
- try
- ConnectThread.Line := Self;
- ConnectThread.ConnectResult := -1;
-
- // Connect to server
- ConnectThread.ReadyEvent.WaitFor;
- ConnectThread.ReadyEvent.ResetEvent;
- ConnectThread.WakeupEvent.SetEvent;
- ConnectThread.WaitForReady(FConnectTimeout);
-
- if ConnectThread.ConnectResult = -1 then
+ if IsConnectionBased then
+ begin
+ ConnectResult := Connect(FHandle, AddrResult^.ai_addr^, AddrResult^.ai_addrlen);
+ if ConnectResult = -1 then
raise EncLineException.Create('Connect timeout');
-
- Check(ConnectThread.ConnectResult);
- SetConnected;
- finally
- ConnectThread.FreeOnTerminate := True;
- ConnectThread.Terminate;
- ConnectThread.WakeupEvent.SetEvent;
+ Check(ConnectResult);
+
+ // For TLS connections, perform handshake BEFORE triggering OnConnected
+ if Assigned(FOnBeforeConnected) then
+ begin
+ try
+ FOnBeforeConnected(Self); // This will do TLS handshake
+ except
+ on E: Exception do
+ begin
+ DestroyHandle;
+ raise EncLineException.CreateFmt('TLS handshake failed: %s', [E.Message]);
+ end;
+ end;
+ end;
+
+ SetConnected; // Only triggers OnConnected AFTER TLS is ready
+ end
+ else
+ begin
+ // For UDP, handle IPv4 and IPv6 differently
+ case FFamily of
+ afIPv4:
+ begin
+ // IPv4 UDP: connect if not broadcast mode
+ if not aBroadcast then
+ begin
+ ConnectResult := Connect(FHandle, AddrResult^.ai_addr^, AddrResult^.ai_addrlen);
+ Check(ConnectResult);
+ end
+ else
+ begin
+ // Enable broadcast option for UDP broadcast
+ EnableBroadcast;
+ end;
+ SetConnected;
+ end;
+ afIPv6:
+ begin
+ // For IPv6 UDP with link-local addresses, ensure scope ID is set
+ if TncIPUtils.IsLinkLocal(ResolveHost) then
+ begin
+ var AddrIn6 := PSockAddrIn6(AddrResult^.ai_addr)^;
+ // Set appropriate scope ID if needed
+ // This could be enhanced with interface detection
+ end;
+ SetConnected;
+ end;
+ end;
end;
+
except
DestroyHandle;
raise;
@@ -417,9 +606,18 @@ procedure TncLine.CreateServerHandle(const aPort: Integer);
{$ENDIF}
begin
FillChar(Hints, SizeOf(Hints), 0);
- Hints.ai_family := AF_INET;
- Hints.ai_socktype := SOCK_STREAM;
- Hints.ai_protocol := IPPROTO_TCP;
+ case FFamily of
+ afIPv4:
+ begin
+ Hints.ai_family := AF_INET;
+ end;
+ afIPv6:
+ begin
+ Hints.ai_family := AF_INET6;
+ end;
+ end;
+ Hints.ai_socktype := CRawSocketTypes[FKind];
+ Hints.ai_protocol := CRawProtocolTypes[FKind];
Hints.ai_flags := AI_PASSIVE; // Inform GetAddrInfo to return a server socket
// Resolve the server address and port
@@ -431,15 +629,22 @@ procedure TncLine.CreateServerHandle(const aPort: Integer);
{$ENDIF}
try
// Create a server listener socket
- FHandle := Socket(AddrResult^.ai_family, AddrResult^.ai_socktype, AddrResult^.ai_protocol);
+ FHandle := Socket(AddrResult^.ai_family, AddrResult^.ai_socktype,
+ AddrResult^.ai_protocol);
Check(FHandle);
try
+ EnableIPv6Only;
+
{$IFNDEF MSWINDOWS}
EnableReuseAddress;
{$ENDIF}
- // Setup the TCP listening socket
- Check(Bind(FHandle, AddrResult^.ai_addr^, AddrResult^.ai_addrlen));
- Check(Listen(FHandle, SOMAXCONN));
+ // Bind the socket
+ Check(bind(FHandle, AddrResult^.ai_addr^, AddrResult^.ai_addrlen));
+
+ // For TCP, we need to listen for incoming connections
+ if IsConnectionBased then
+ Check(Listen(FHandle, SOMAXCONN));
+
SetConnected;
except
DestroyHandle;
@@ -458,6 +663,17 @@ procedure TncLine.DestroyHandle;
begin
if FActive then
begin
+ // CRITICAL: Call TLS cleanup BEFORE destroying socket
+ if Assigned(FOnBeforeDisconnected) then
+ begin
+ try
+ FOnBeforeDisconnected(Self); // TLS cleanup while socket is still active
+ except
+ on E: Exception do
+ // Continue with socket cleanup even if TLS cleanup fails
+ end;
+ end;
+
try
{$IFDEF MSWINDOWS}
Shutdown(FHandle, SD_BOTH);
@@ -467,12 +683,15 @@ procedure TncLine.DestroyHandle;
Posix.Unistd.__Close(FHandle);
{$ENDIF}
except
+ on E: Exception do
+ //
end;
try
SetDisconnected;
except
+ on E: Exception do
+ //
end;
-
FHandle := InvalidSocket;
end;
end;
@@ -481,14 +700,14 @@ function TncLine.AcceptLine: TncLine;
var
NewHandle: TSocketHandle;
{$IFNDEF MSWINDOWS}
- Addr: sockaddr;
+ addr: sockaddr;
AddrLen: socklen_t;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
NewHandle := Accept(FHandle, nil, nil);
{$ELSE}
- NewHandle := Accept(FHandle, Addr, AddrLen);
+ NewHandle := Accept(FHandle, addr, AddrLen);
{$ENDIF}
if NewHandle = InvalidSocket then
Abort; // raise silent exception
@@ -498,36 +717,66 @@ function TncLine.AcceptLine: TncLine;
Result.FHandle := NewHandle;
Result.OnConnected := OnConnected;
Result.OnDisconnected := OnDisconnected;
+ Result.OnBeforeConnected := OnBeforeConnected;
+ Result.OnBeforeDisconnected := OnBeforeDisconnected;
+
+ // For server-side TLS connections, perform handshake BEFORE triggering OnConnected
+ if Assigned(Result.OnBeforeConnected) then
+ begin
+ try
+ Result.OnBeforeConnected(Result); // This will do TLS handshake for server
+ except
+ on E: Exception do
+ begin
+ Result.DestroyHandle;
+ Result.Free;
+ raise EncLineException.CreateFmt('Server TLS handshake failed: %s', [E.Message]);
+ end;
+ end;
+ end;
+
Result.SetConnected;
end;
function TncLine.SendBuffer(const aBuf; aLen: Integer): Integer;
begin
- // Send all buffer in one go, the most optimal by far
Result := Send(FHandle, aBuf, aLen, 0);
- try
- if Result = SocketError then
- Abort; // raise silent exception instead of Check
+ if Result = SocketError then
+ begin
+ if IsConnectionBased then
+ try
+ Abort; // TCP: raise silent exception
+ except
+ DestroyHandle;
+ raise;
+ end
+ else
+ Check(Result); // UDP: normal error check
+ end
+ else
LastSent := TStopWatch.GetTimeStamp;
- except
- DestroyHandle;
- raise;
- end;
end;
function TncLine.RecvBuffer(var aBuf; aLen: Integer): Integer;
begin
Result := recv(FHandle, aBuf, aLen, 0);
- try
- if (Result = SocketError) or (Result = 0) then
- Abort; // raise silent exception instead of Check, something has disconnected
+ if (Result = SocketError) or
+ (IsConnectionBased and (Result = 0)) then // TCP: 0 means disconnected
+ begin
+ if IsConnectionBased then
+ try
+ Abort; // TCP: raise silent exception
+ except
+ DestroyHandle;
+ raise;
+ end
+ else
+ Check(Result); // UDP: normal error check
+ end
+ else
LastReceived := TStopWatch.GetTimeStamp;
- except
- DestroyHandle;
- raise;
- end;
end;
procedure TncLine.EnableNoDelay;
@@ -536,7 +785,8 @@ procedure TncLine.EnableNoDelay;
begin
optval := 1;
{$IFDEF MSWINDOWS}
- Check(SetSockOpt(FHandle, IPPROTO_TCP, TCP_NODELAY, PAnsiChar(@optval), SizeOf(optval)));
+ Check(SetSockOpt(FHandle, IPPROTO_TCP, TCP_NODELAY, PAnsiChar(@optval),
+ SizeOf(optval)));
{$ELSE}
Check(SetSockOpt(FHandle, IPPROTO_TCP, TCP_NODELAY, optval, SizeOf(optval)));
{$ENDIF}
@@ -548,73 +798,150 @@ procedure TncLine.EnableKeepAlive;
begin
optval := 1; // any non zero indicates true
{$IFDEF MSWINDOWS}
- Check(SetSockOpt(FHandle, SOL_SOCKET, SO_KEEPALIVE, PAnsiChar(@optval), SizeOf(optval)));
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_KEEPALIVE, PAnsiChar(@optval),
+ SizeOf(optval)));
{$ELSE}
Check(SetSockOpt(FHandle, SOL_SOCKET, SO_KEEPALIVE, optval, SizeOf(optval)));
{$ENDIF}
end;
+procedure TncLine.EnableBroadcast;
+var
+ optval: Integer;
+begin
+ optval := 1;
+{$IFDEF MSWINDOWS}
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_BROADCAST, PAnsiChar(@optval),
+ SizeOf(optval)));
+{$ELSE}
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_BROADCAST, optval, SizeOf(optval)));
+{$ENDIF}
+end;
+
+procedure TncLine.EnableIPv6Only;
+var
+ optval: Integer;
+begin
+ if FFamily = afIPv6 then
+ begin
+ optval := 1;
+{$IFDEF MSWINDOWS}
+ Check(SetSockOpt(FHandle, IPPROTO_IPV6, IPV6_V6ONLY, PAnsiChar(@optval),
+ SizeOf(optval)));
+{$ELSE}
+ Check(SetSockOpt(FHandle, IPPROTO_IPV6, IPV6_V6ONLY, optval,
+ SizeOf(optval)));
+{$ENDIF}
+ end;
+end;
+
procedure TncLine.EnableReuseAddress;
var
optval: Integer;
begin
optval := 1;
{$IFDEF MSWINDOWS}
- Check(SetSockOpt(FHandle, SOL_SOCKET, SO_REUSEADDR, PAnsiChar(@optval), SizeOf(optval)));
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_REUSEADDR, PAnsiChar(@optval),
+ SizeOf(optval)));
{$ELSE}
Check(SetSockOpt(FHandle, SOL_SOCKET, SO_REUSEADDR, optval, SizeOf(optval)));
{$ENDIF}
end;
+procedure TncLine.SetKind(const AKind: TSocketType);
+begin
+ if FHandle = InvalidSocket then // TODO: Raise exception otherwise???
+ begin
+ FKind := AKind;
+ end;
+end;
+
+procedure TncLine.SetFamily(const Value: TAddressType);
+begin
+ if FHandle = InvalidSocket then
+ // Only allow changing family when socket is not active
+ begin
+ FFamily := Value;
+ end
+ else
+ // Form1.Log('WARNING: Attempted to change Family while socket is active');
+end;
+
+function TncLine.IsConnectionBased: Boolean;
+begin
+ Result := FKind = stTCP;
+end;
+
procedure TncLine.SetReceiveSize(const aBufferSize: Integer);
begin
// min is 512 bytes, max is 1048576
{$IFDEF MSWINDOWS}
- Check(SetSockOpt(FHandle, SOL_SOCKET, SO_RCVBUF, PAnsiChar(@aBufferSize), SizeOf(aBufferSize)));
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_RCVBUF, PAnsiChar(@aBufferSize),
+ SizeOf(aBufferSize)));
{$ELSE}
- Check(SetSockOpt(FHandle, SOL_SOCKET, SO_RCVBUF, aBufferSize, SizeOf(aBufferSize)));
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_RCVBUF, aBufferSize,
+ SizeOf(aBufferSize)));
{$ENDIF}
end;
procedure TncLine.SetWriteSize(const aBufferSize: Integer);
begin
{$IFDEF MSWINDOWS}
- Check(SetSockOpt(FHandle, SOL_SOCKET, SO_SNDBUF, PAnsiChar(@aBufferSize), SizeOf(aBufferSize)));
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_SNDBUF, PAnsiChar(@aBufferSize),
+ SizeOf(aBufferSize)));
{$ELSE}
- Check(SetSockOpt(FHandle, SOL_SOCKET, SO_RCVBUF, aBufferSize, SizeOf(aBufferSize)));
+ Check(SetSockOpt(FHandle, SOL_SOCKET, SO_RCVBUF, aBufferSize,
+ SizeOf(aBufferSize)));
{$ENDIF}
end;
procedure TncLine.SetConnected;
var
- Addr: sockaddr;
-{$IFDEF MSWINDOWS}
- AddrSize: Integer;
-{$ELSE}
- AddrSize: socklen_t;
-{$ENDIF}
+ addr: TSockAddrStorage;
+ AddrSize: {$IFDEF MSWINDOWS}Integer{$ELSE}socklen_t{$ENDIF};
begin
if not FActive then
begin
FActive := True;
-
LastSent := TStopWatch.GetTimeStamp;
LastReceived := LastSent;
- AddrSize := SizeOf(Addr);
- if GetPeerName(FHandle, Addr, AddrSize) <> SocketError then
+ if IsConnectionBased then
begin
- // FPeerIP := IntToStr(Ord(addr.sin_addr.S_un_b.s_b1)) + '.' + IntToStr(Ord(addr.sin_addr.S_un_b.s_b2)) + '.' + IntToStr(Ord(addr.sin_addr.S_un_b.s_b3)) +
- // '.' + IntToStr(Ord(addr.sin_addr.S_un_b.s_b4));
- FPeerIP :=
-
- IntToStr(Ord(Addr.sa_data[2])) + '.' +
+ // Get peer information
+ AddrSize := SizeOf(TSockAddrStorage);
- IntToStr(Ord(Addr.sa_data[3])) + '.' +
-
- IntToStr(Ord(Addr.sa_data[4])) + '.' +
+ if GetPeerName(FHandle, PSOCKADDR(@addr)^, AddrSize) = 0 then
+ begin
+ try
+ FPeerIP := TncIPUtils.GetIPFromStorage(addr);
+ except
+ on E: EIPError do
+ FPeerIP := '';
+ end;
- IntToStr(Ord(Addr.sa_data[5]));
+ // If we got an empty string, set default values based on family
+ if FPeerIP = '' then
+ begin
+ case FFamily of
+ afIPv4: FPeerIP := '0.0.0.0';
+ afIPv6: FPeerIP := '::';
+ end;
+ end;
+ end
+ else
+ begin
+ var ErrorCode := {$IFDEF MSWINDOWS}WSAGetLastError(){$ELSE}GetLastError(){$ENDIF};
+ FPeerIP := '';
+ end;
+ end
+ else
+ begin
+ // For UDP, we're always "connected" but might not have peer info yet
+ case FFamily of
+ afIPv4: FPeerIP := '0.0.0.0';
+ afIPv6: FPeerIP := '::';
+ end;
end;
if Assigned(OnConnected) then
@@ -641,8 +968,8 @@ procedure TncLine.SetDisconnected;
function TncLine.GetReceiveTimeout: Integer;
var
- Opt: DWord;
- OptSize: Integer;
+ Opt: Cardinal;
+ OptSize: {$IFDEF MSWINDOWS}Integer{$ELSE}socklen_t{$ENDIF};
begin
OptSize := SizeOf(Opt);
{$IFDEF MSWINDOWS}
@@ -655,7 +982,7 @@ function TncLine.GetReceiveTimeout: Integer;
procedure TncLine.SetReceiveTimeout(const Value: Integer);
var
- Opt: DWord;
+ Opt: Cardinal;
OptSize: Integer;
begin
Opt := Value;
@@ -669,8 +996,8 @@ procedure TncLine.SetReceiveTimeout(const Value: Integer);
function TncLine.GetSendTimeout: Integer;
var
- Opt: DWord;
- OptSize: Integer;
+ Opt: Cardinal;
+ OptSize: {$IFDEF MSWINDOWS}Integer{$ELSE}socklen_t{$ENDIF};
begin
OptSize := SizeOf(Opt);
{$IFDEF MSWINDOWS}
@@ -683,7 +1010,7 @@ function TncLine.GetSendTimeout: Integer;
procedure TncLine.SetSendTimeout(const Value: Integer);
var
- Opt: DWord;
+ Opt: Cardinal;
OptSize: Integer;
begin
Opt := Value;
@@ -697,51 +1024,51 @@ procedure TncLine.SetSendTimeout(const Value: Integer);
function TncLine.GetLastReceived: Int64;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FLastReceived;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncLine.SetLastReceived(const Value: Int64);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FLastReceived := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncLine.GetLastSent: Int64;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FLastSent;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncLine.SetLastSent(const Value: Int64);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FLastSent := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
{$IFDEF MSWINDOWS}
+// Windows-specific types and variables
var
ExtDllHandle: THandle = 0;
procedure AttachAddrInfo;
-
procedure SafeLoadFrom(aDll: string);
begin
if not Assigned(DllGetAddrInfo) then
@@ -761,33 +1088,30 @@ procedure AttachAddrInfo;
end;
begin
- SafeLoadFrom('ws2_32.dll'); // WinSock2 dll
- SafeLoadFrom('wship6.dll'); // WshIp6 dll
+ SafeLoadFrom('ws2_32.dll');
+ SafeLoadFrom('wship6.dll');
end;
+{$ENDIF}
-var
- WSAData: TWSAData;
+initialization
- { TConnectThread }
+{$IFDEF MSWINDOWS}
-procedure TConnectThread.ProcessEvent;
+var
+ WSAData: TWSAData;
begin
- ConnectResult := Connect(Line.FHandle, Line.AddrResult^.ai_addr^, Line.AddrResult^.ai_addrlen);
+ WSAStartup(MakeWord(2, 2), WSAData);
+ AttachAddrInfo;
end;
-
-initialization
-
-WSAStartup(MakeWord(2, 2), WSAData); // Require WinSock 2 version
-
-AttachAddrInfo;
+{$ENDIF}
finalization
+{$IFDEF MSWINDOWS}
if ExtDllHandle <> 0 then
FreeLibrary(ExtDllHandle);
-
WSACleanup;
-
{$ENDIF}
end.
+
diff --git a/Source/ncSChannel.pas b/Source/ncSChannel.pas
new file mode 100644
index 0000000..11c556a
--- /dev/null
+++ b/Source/ncSChannel.pas
@@ -0,0 +1,1551 @@
+unit ncSChannel;
+
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 Package
+//
+// This unit implements TLS/SSL support for NetCom7 through Windows SChannel
+// (Secure Channel) API integration. Provides secure communication capabilities
+// for both TCP servers and clients using native Windows cryptographic services.
+//
+// 13/07/2025 - by J.Pauwels
+// - Initial creation
+//
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+interface
+
+uses
+ SysUtils,
+ Classes,
+ Windows;
+
+//******************************************************************************
+// CryptoAPI
+//******************************************************************************
+const
+ CERT_STORE_PROV_FILENAME = 8;
+ CERT_STORE_PROV_MEMORY = 2;
+ CERT_STORE_OPEN_EXISTING_FLAG = $00004000;
+ CERT_STORE_READONLY_FLAG = $00008000;
+ PKCS12_NO_PERSIST_KEY = $00008000;
+ PKCS12_INCLUDE_EXTENDED_PROPERTIES = $00000010;
+
+ CERT_FIND_ANY = 0;
+ // no check is made to determine whether memory for contexts remains allocated
+ CERT_CLOSE_STORE_DEFAULT = 0;
+ // force freeing all contexts associated with the store
+ CERT_CLOSE_STORE_FORCE_FLAG = 1;
+ // checks for nonfreed certificate, CRL, and CTL context to report an error on leak
+ CERT_CLOSE_STORE_CHECK_FLAG = 2;
+
+ CRYPT_ASN_ENCODING = $00000001;
+ CRYPT_NDR_ENCODING = $00000002;
+ X509_ASN_ENCODING = $00000001;
+ X509_NDR_ENCODING = $00000002;
+ PKCS_7_ASN_ENCODING = $00010000;
+ PKCS_7_NDR_ENCODING = $00020000;
+ // TCryptCertUsage mormot.crypt.secure
+ CERT_OFFLINE_CRL_SIGN_KEY_USAGE = $02; // cuCrlSign
+ CERT_KEY_CERT_SIGN_KEY_USAGE = $04; // cuKeyCertSign
+ CERT_KEY_AGREEMENT_KEY_USAGE = $08; // cuKeyAgreement
+ CERT_DATA_ENCIPHERMENT_KEY_USAGE = $10; // cuDataEncipherment
+ CERT_KEY_ENCIPHERMENT_KEY_USAGE = $20; // cuKeyEncipherment
+ CERT_NON_REPUDIATION_KEY_USAGE = $40; // cuNonRepudiation
+ CERT_DIGITAL_SIGNATURE_KEY_USAGE = $80; // cuDigitalSignature
+
+ CERT_KEY_PROV_INFO_PROP_ID = 2;
+ CERT_HASH_PROP_ID = 3;
+ CERT_FRIENDLY_NAME_PROP_ID = 11;
+
+ CERT_SIMPLE_NAME_STR = 1;
+ CERT_OID_NAME_STR = 2;
+ CERT_X500_NAME_STR = 3;
+
+ CRYPT_OID_INFO_OID_KEY = 1;
+
+type
+ HCRYPTPROV = pointer;
+ HCRYPTKEY = pointer;
+ HCRYPTHASH = pointer;
+ HCERTSTORE = pointer;
+
+ CRYPTOAPI_BLOB = record
+ cbData: DWORD;
+ pbData: PByteArray;
+ end;
+ CRYPT_INTEGER_BLOB = CRYPTOAPI_BLOB;
+ CERT_NAME_BLOB = CRYPTOAPI_BLOB;
+ CRYPT_OBJID_BLOB = CRYPTOAPI_BLOB;
+ CRYPT_DATA_BLOB = CRYPTOAPI_BLOB;
+ PCRYPT_DATA_BLOB = ^CRYPT_DATA_BLOB;
+
+ CRYPT_BIT_BLOB = record
+ cbData: DWORD;
+ pbData: PByteArray;
+ cUnusedBits: DWORD;
+ end;
+
+ CRYPT_ALGORITHM_IDENTIFIER = record
+ pszObjId: PAnsiChar;
+ Parameters: CRYPT_OBJID_BLOB;
+ end;
+
+ CERT_PUBLIC_KEY_INFO = record
+ Algorithm: CRYPT_ALGORITHM_IDENTIFIER;
+ PublicKey: CRYPT_BIT_BLOB;
+ end;
+
+ CERT_EXTENSION = record
+ pszObjId: PAnsiChar;
+ fCritical: BOOL;
+ Blob: CRYPT_OBJID_BLOB;
+ end;
+ PCERT_EXTENSION = ^CERT_EXTENSION;
+ CERT_EXTENSIONS = array[word] of CERT_EXTENSION;
+ PCERT_EXTENSIONS = ^CERT_EXTENSIONS;
+
+ CERT_INFO = record
+ dwVersion: DWORD;
+ SerialNumber: CRYPT_INTEGER_BLOB;
+ SignatureAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
+ Issuer: CERT_NAME_BLOB;
+ NotBefore: TFileTime;
+ NotAfter: TFileTime;
+ Subject: CERT_NAME_BLOB;
+ SubjectPublicKeyInfo: CERT_PUBLIC_KEY_INFO;
+ IssuerUniqueId: CRYPT_BIT_BLOB;
+ SubjectUniqueId: CRYPT_BIT_BLOB;
+ cExtension: DWORD;
+ rgExtension: PCERT_EXTENSIONS;
+ end;
+ PCERT_INFO = ^CERT_INFO;
+
+ CERT_CONTEXT = record
+ dwCertEncodingType: DWORD;
+ pbCertEncoded: PByte;
+ cbCertEncoded: DWORD;
+ pCertInfo: PCERT_INFO;
+ hCertStore: HCERTSTORE;
+ end;
+ PCCERT_CONTEXT = ^CERT_CONTEXT;
+ PPCCERT_CONTEXT = ^PCCERT_CONTEXT;
+
+CRYPT_KEY_PROV_PARAM = record
+ dwParam: DWORD;
+ pbData: PByte;
+ cbData: DWORD;
+ dwFlags: DWORD;
+ end;
+ PCRYPT_KEY_PROV_PARAM = ^CRYPT_KEY_PROV_PARAM;
+
+ CRYPT_KEY_PROV_INFO = record
+ pwszContainerName: PWideChar;
+ pwszProvName: PWideChar;
+ dwProvType: DWORD;
+ dwFlags: DWORD;
+ cProvParam: DWORD;
+ rgProvParam: PCRYPT_KEY_PROV_PARAM;
+ dwKeySpec: DWORD;
+ end;
+ PCRYPT_KEY_PROV_INFO = ^CRYPT_KEY_PROV_INFO;
+
+ CRYPT_OID_INFO = record
+ cbSize: DWORD;
+ pszOID: PAnsiChar;
+ pwszName: PWideChar;
+ dwGroupId: DWORD;
+ Union: record
+ case integer of
+ 0: (dwValue: DWORD);
+ 1: (Algid: DWORD);
+ 2: (dwLength: DWORD);
+ end;
+ ExtraInfo: CRYPTOAPI_BLOB;
+ end;
+ PCRYPT_OID_INFO = ^CRYPT_OID_INFO;
+
+ PCCRL_CONTEXT = pointer;
+ PPCCRL_CONTEXT = ^PCCRL_CONTEXT;
+ PCRYPT_ATTRIBUTE = pointer;
+
+ CRYPT_SIGN_MESSAGE_PARA = record
+ cbSize: DWORD;
+ dwMsgEncodingType: DWORD;
+ pSigningCert: PCCERT_CONTEXT;
+ HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
+ pvHashAuxInfo: pointer;
+ cMsgCert: DWORD;
+ rgpMsgCert: PPCCERT_CONTEXT;
+ cMsgCrl: DWORD;
+ rgpMsgCrl: PPCCRL_CONTEXT;
+ cAuthAttr: DWORD;
+ rgAuthAttr: PCRYPT_ATTRIBUTE;
+ cUnauthAttr: DWORD;
+ rgUnauthAttr: PCRYPT_ATTRIBUTE;
+ dwFlags: DWORD;
+ dwInnerContentType: DWORD;
+ HashEncryptionAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
+ pvHashEncryptionAuxInfo: pointer;
+ end;
+
+ PFN_CRYPT_GET_SIGNER_CERTIFICATE = function(pvGetArg: pointer;
+ dwCertEncodingType: DWORD; pSignerId: PCERT_INFO;
+ hMsgCertStore: HCERTSTORE): PCCERT_CONTEXT; stdcall;
+ CRYPT_VERIFY_MESSAGE_PARA = record
+ cbSize: DWORD;
+ dwMsgAndCertEncodingType: DWORD;
+ hCryptProv: HCRYPTPROV;
+ pfnGetSignerCertificate: PFN_CRYPT_GET_SIGNER_CERTIFICATE;
+ pvGetArg: pointer;
+ end;
+
+//******************************************************************************
+// Low-Level SSPI/SChannel
+//******************************************************************************
+const
+ SECBUFFER_VERSION = 0;
+
+ SECBUFFER_EMPTY = 0;
+ SECBUFFER_DATA = 1;
+ SECBUFFER_TOKEN = 2;
+ SECBUFFER_EXTRA = 5;
+ SECBUFFER_STREAM_TRAILER = 6;
+ SECBUFFER_STREAM_HEADER = 7;
+ SECBUFFER_PADDING = 9;
+ SECBUFFER_STREAM = 10;
+ SECBUFFER_ALERT = 17;
+
+ SECPKG_CRED_INBOUND = 1;
+ SECPKG_CRED_OUTBOUND = 2;
+
+ SECPKG_ATTR_SIZES = 0;
+ SECPKG_ATTR_NAMES = 1;
+ SECPKG_ATTR_STREAM_SIZES = 4;
+ SECPKG_ATTR_NEGOTIATION_INFO = 12;
+ SECPKG_ATTR_ACCESS_TOKEN = 13;
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT = $53;
+ SECPKG_ATTR_CONNECTION_INFO = $5a;
+ SECPKG_ATTR_CIPHER_INFO = $64; // Vista+ new API
+ SECPKG_ATTR_C_ACCESS_TOKEN = $80000012;
+ SECPKG_ATTR_C_FULL_ACCESS_TOKEN = $80000082;
+
+ SECPKGCONTEXT_CIPHERINFO_V1 = 1;
+
+ SECURITY_NETWORK_DREP = 0;
+ SECURITY_NATIVE_DREP = $10;
+
+ ISC_REQ_DELEGATE = $00000001;
+ ISC_REQ_MUTUAL_AUTH = $00000002;
+ ISC_REQ_REPLAY_DETECT = $00000004;
+ ISC_REQ_SEQUENCE_DETECT = $00000008;
+ ISC_REQ_CONFIDENTIALITY = $00000010;
+ ISC_REQ_USE_SESSION_KEY = $00000020;
+ ISC_REQ_PROMPT_FOR_CREDS = $00000040;
+ ISC_REQ_USE_SUPPLIED_CREDS = $00000080;
+ ISC_REQ_ALLOCATE_MEMORY = $00000100;
+ ISC_REQ_USE_DCE_STYLE = $00000200;
+ ISC_REQ_DATAGRAM = $00000400;
+ ISC_REQ_CONNECTION = $00000800;
+ ISC_REQ_CALL_LEVEL = $00001000;
+ ISC_REQ_FRAGMENT_SUPPLIED = $00002000;
+ ISC_REQ_EXTENDED_ERROR = $00004000;
+ ISC_REQ_STREAM = $00008000;
+ ISC_REQ_INTEGRITY = $00010000;
+ ISC_REQ_IDENTIFY = $00020000;
+ ISC_REQ_NULL_SESSION = $00040000;
+ ISC_REQ_MANUAL_CRED_VALIDATION = $00080000;
+ ISC_REQ_RESERVED1 = $00100000;
+ ISC_REQ_FRAGMENT_TO_FIT = $00200000;
+ ISC_REQ_FLAGS = ISC_REQ_SEQUENCE_DETECT or
+ ISC_REQ_REPLAY_DETECT or
+ ISC_REQ_CONFIDENTIALITY or
+ ISC_REQ_EXTENDED_ERROR or
+ ISC_REQ_ALLOCATE_MEMORY or
+ ISC_REQ_STREAM;
+
+ ASC_REQ_REPLAY_DETECT = $00000004;
+ ASC_REQ_SEQUENCE_DETECT = $00000008;
+ ASC_REQ_CONFIDENTIALITY = $00000010;
+ ASC_REQ_ALLOCATE_MEMORY = $00000100;
+ ASC_REQ_EXTENDED_ERROR = $00008000;
+ ASC_REQ_STREAM = $00010000;
+ ASC_REQ_FLAGS = ASC_REQ_SEQUENCE_DETECT or
+ ASC_REQ_REPLAY_DETECT or
+ ASC_REQ_CONFIDENTIALITY or
+ ASC_REQ_EXTENDED_ERROR or
+ ASC_REQ_ALLOCATE_MEMORY or
+ ASC_REQ_STREAM;
+
+ SEC_E_OK = 0;
+
+ SEC_I_CONTINUE_NEEDED = $00090312;
+ SEC_I_COMPLETE_NEEDED = $00090313;
+ SEC_I_COMPLETE_AND_CONTINUE = $00090314;
+ SEC_I_CONTEXT_EXPIRED = $00090317;
+ SEC_I_INCOMPLETE_CREDENTIALS = $00090320;
+ SEC_I_RENEGOTIATE = $00090321;
+
+ SEC_E_UNSUPPORTED_FUNCTION = $80090302;
+ SEC_E_INVALID_TOKEN = $80090308;
+ SEC_E_MESSAGE_ALTERED = $8009030F;
+ SEC_E_CONTEXT_EXPIRED = $80090317;
+ SEC_E_INCOMPLETE_MESSAGE = $80090318;
+ SEC_E_BUFFER_TOO_SMALL = $80090321;
+ SEC_E_ILLEGAL_MESSAGE = $80090326;
+ SEC_E_CERT_UNKNOWN = $80090327;
+ SEC_E_CERT_EXPIRED = $80090328;
+ SEC_E_ENCRYPT_FAILURE = $80090329;
+ SEC_E_DECRYPT_FAILURE = $80090330;
+ SEC_E_ALGORITHM_MISMATCH = $80090331;
+
+ SEC_WINNT_AUTH_IDENTITY_UNICODE = $02;
+
+ SCHANNEL_SHUTDOWN = 1;
+
+ SCHANNEL_CRED_VERSION = 4;
+ SCH_CREDENTIALS_VERSION = 5;
+
+ SCH_CRED_NO_SYSTEM_MAPPER = $00000002;
+ SCH_CRED_NO_SERVERNAME_CHECK = $00000004;
+ SCH_CRED_MANUAL_CRED_VALIDATION = $00000008;
+ SCH_CRED_NO_DEFAULT_CREDS = $00000010;
+ SCH_CRED_AUTO_CRED_VALIDATION = $00000020;
+ SCH_CRED_USE_DEFAULT_CREDS = $00000040;
+ SCH_CRED_DISABLE_RECONNECTS = $00000080;
+ SCH_CRED_REVOCATION_CHECK_END_CERT = $00000100;
+ SCH_CRED_REVOCATION_CHECK_CHAIN = $00000200;
+ SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = $00000400;
+ SCH_CRED_IGNORE_NO_REVOCATION_CHECK = $00000800;
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE = $00001000;
+ SCH_CRED_RESTRICTED_ROOTS = $00002000;
+ SCH_CRED_REVOCATION_CHECK_CACHE_ONLY = $00004000;
+ SCH_CRED_CACHE_ONLY_URL_RETRIEVAL = $00008000;
+ SCH_CRED_MEMORY_STORE_CERT = $00010000;
+ SCH_CRED_CACHE_ONLY_URL_RETRIEVAL_ON_CREATE = $00020000;
+ SCH_SEND_ROOT_CERT = $00040000;
+ SCH_USE_STRONG_CRYPTO = $00400000;
+
+ UNISP_NAME = 'Microsoft Unified Security Protocol Provider';
+
+ SP_PROT_TLS1_0_SERVER = $0040;
+ SP_PROT_TLS1_0_CLIENT = $0080;
+ SP_PROT_TLS1_1_SERVER = $0100;
+ SP_PROT_TLS1_1_CLIENT = $0200;
+ SP_PROT_TLS1_2_SERVER = $0400; // first SP_PROT_TLS_SAFE protocol
+ SP_PROT_TLS1_2_CLIENT = $0800;
+ SP_PROT_TLS1_3_SERVER = $1000; // Windows 11 or Windows Server 2022 ;)
+ SP_PROT_TLS1_3_CLIENT = $2000;
+ // SSL 2/3 protocols ($04,$08,$10,$20) are just not defined at all
+ SP_PROT_TLS1_0 = SP_PROT_TLS1_0_CLIENT or SP_PROT_TLS1_0_SERVER;
+ SP_PROT_TLS1_1 = SP_PROT_TLS1_1_CLIENT or SP_PROT_TLS1_1_SERVER;
+ SP_PROT_TLS1_2 = SP_PROT_TLS1_2_CLIENT or SP_PROT_TLS1_2_SERVER;
+ SP_PROT_TLS1_3 = SP_PROT_TLS1_3_CLIENT or SP_PROT_TLS1_3_SERVER;
+ // TLS 1.0 and TLS 1.1 are universally deprecated
+ SP_PROT_TLS_SAFE = SP_PROT_TLS1_2 or SP_PROT_TLS1_3;
+ SP_PROT_TLS_UNSAFE = pred(SP_PROT_TLS1_2_SERVER);
+
+
+type
+ {$ifdef WIN64}
+ LONG_PTR = Int64;
+ {$else}
+ LONG_PTR = integer;
+ {$endif}
+
+ ALG_ID = cardinal;
+ TALG_IDs = array[word] of ALG_ID;
+ PALG_IDs = ^TALG_IDs;
+
+ _HMAPPER = pointer;
+
+ /// SSPI context handle
+ TSecHandle = record
+ dwLower: LONG_PTR;
+ dwUpper: LONG_PTR;
+ end;
+ PSecHandle = ^TSecHandle;
+
+ // some context aliases, as defined in SSPI headers
+ TCredHandle = type TSecHandle;
+ PCredHandle = type PSecHandle;
+ TCtxtHandle = type TSecHandle;
+ PCtxtHandle = type PSecHandle;
+
+ TSChannelCred = record
+ dwVersion: cardinal;
+ cCreds: cardinal;
+ paCred: PPCCERT_CONTEXT;
+ hRootStore: HCERTSTORE;
+ cMappers: cardinal;
+ aphMappers: _HMAPPER;
+ cSupportedAlgs: cardinal;
+ palgSupportedAlgs: PALG_IDs;
+ grbitEnabledProtocols: cardinal;
+ dwMinimumCipherStrength: cardinal;
+ dwMaximumCipherStrength: cardinal;
+ dwSessionLifespan: cardinal;
+ dwFlags: cardinal;
+ dwCredFormat: cardinal;
+ end;
+ PSChannelCred = ^TSChannelCred;
+
+ TSecBuffer = record
+ cbBuffer: cardinal;
+ BufferType: cardinal;
+ pvBuffer: pointer;
+ end;
+ PSecBuffer = ^TSecBuffer;
+
+ TSecBufferDesc = record
+ ulVersion: cardinal;
+ cBuffers: cardinal;
+ pBuffers: PSecBuffer;
+ end;
+ PSecBufferDesc = ^TSecBufferDesc;
+
+ TTimeStamp = record
+ dwLowDateTime: cardinal;
+ dwHighDateTime: cardinal;
+ end;
+ PTimeStamp = ^TTimeStamp;
+
+ TSecPkgContextStreamSizes = record
+ cbHeader: cardinal;
+ cbTrailer: cardinal;
+ cbMaximumMessage: cardinal;
+ cBuffers: cardinal;
+ cbBlockSize: cardinal;
+ end;
+ PSecPkgContextStreamSizes = ^TSecPkgContextStreamSizes;
+
+ /// store information about a SSPI package
+ TSecPkgInfoW = record
+ fCapabilities: Cardinal;
+ wVersion: Word;
+ wRPCID: Word;
+ cbMaxToken: Cardinal;
+ Name: PWideChar;
+ Comment: PWideChar;
+ end;
+ /// pointer to information about a SSPI package
+ PSecPkgInfoW = ^TSecPkgInfoW;
+
+ ESChannel = class(Exception);
+
+
+ {$ifdef USERECORDWITHMETHODS}TSChannelClient = record
+ {$else}TSChannelClient = object{$endif}
+ private
+ Cred: TCredHandle;
+ Ctxt: TCtxtHandle;
+ Sizes: TSecPkgContextStreamSizes;
+ Data, Input: AnsiString;
+ InputSize, DataPos, DataCount, InputCount: integer;
+ procedure HandshakeLoop(aLine: TObject);
+ procedure AppendData(const aBuffer: TSecBuffer);
+ public
+ Initialized: boolean;
+ SessionClosed: boolean;
+ procedure AfterConnection(aLine: TObject; const aTargetHost: AnsiString; aIgnoreCertificateErrors: boolean);
+ procedure BeforeDisconnection(aLine: TObject);
+ function Receive(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+ function Send(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+ end;
+
+ // Server-side SChannel implementation
+ {$ifdef USERECORDWITHMETHODS}TSChannelServer = record
+ {$else}TSChannelServer = object{$endif}
+ private
+ Cred: TCredHandle;
+ Ctxt: TCtxtHandle;
+ Sizes: TSecPkgContextStreamSizes;
+ Data, Input: AnsiString;
+ InputSize, DataPos, DataCount, InputCount: integer;
+ procedure HandshakeLoop(aLine: TObject);
+ procedure AppendData(const aBuffer: TSecBuffer);
+ public
+ Initialized: boolean;
+ HandshakeCompleted: boolean;
+ SessionClosed: boolean;
+ procedure AfterConnection(aLine: TObject; const aCertificateFile, aPrivateKeyPassword: AnsiString);
+ procedure BeforeDisconnection(aLine: TObject);
+ function Receive(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+ function Send(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+ end;
+
+
+// crypt32.dll API calls
+
+function CertOpenStore(lpszStoreProvider: PAnsiChar; dwEncodingType: cardinal;
+ hCryptProv: HCRYPTPROV; dwFlags: cardinal; pvPara: pointer): HCERTSTORE; stdcall;
+ external 'crypt32.dll';
+
+function CertCloseStore(hCertStore: HCERTSTORE; dwFlags: cardinal): BOOL; stdcall;
+ external 'crypt32.dll';
+
+function CertEnumCertificatesInStore(hCertStore: HCERTSTORE;
+ pPrevCertContext: PCCERT_CONTEXT): PCCERT_CONTEXT; stdcall;
+ external 'crypt32.dll';
+
+function CertFreeCertificateContext(pCertContext: PCCERT_CONTEXT): BOOL; stdcall;
+ external 'crypt32.dll';
+
+function PFXImportCertStore(pPFX: pointer; szPassword: PWideChar;
+ dwFlags: cardinal): HCERTSTORE; stdcall;
+ external 'crypt32.dll';
+
+// secur32.dll API calls
+
+function AcquireCredentialsHandleW(pszPrincipal, pszPackage: PWideChar;
+ fCredentialUse: cardinal; pvLogonId: pointer; pAuthData: PSChannelCred;
+ pGetKeyFn: pointer; pvGetKeyArgument: pointer; phCredential: PCredHandle;
+ ptsExpiry: PTimeStamp): cardinal; stdcall;
+ external 'secur32.dll';
+
+function QuerySecurityPackageInfoW(pszPackageName: PWideChar;
+ var ppPackageInfo: PSecPkgInfoW): cardinal; stdcall;
+ external 'secur32.dll';
+
+function FreeCredentialsHandle(phCredential: PCredHandle): cardinal; stdcall;
+ external 'secur32.dll';
+
+function InitializeSecurityContextW(phCredential: PCredHandle; phContext: PCtxtHandle;
+ pszTargetName: PWideChar; fContextReq, Reserved1, TargetDataRep: cardinal;
+ pInput: PSecBufferDesc; Reserved2: cardinal; phNewContext: PCtxtHandle;
+ pOutput: PSecBufferDesc; var pfContextAttr: cardinal;
+ ptsExpiry: PTimeStamp): cardinal; stdcall;
+ external 'secur32.dll';
+
+function AcceptSecurityContext(phCredential: PCredHandle; phContext: PCtxtHandle;
+ pInput: PSecBufferDesc; fContextReq, TargetDataRep: cardinal;
+ phNewContext: PCtxtHandle; pOutput: PSecBufferDesc; var pfContextAttr: cardinal;
+ ptsExpiry: PTimeStamp): cardinal; stdcall;
+ external 'secur32.dll';
+
+function DeleteSecurityContext(phContext: PCtxtHandle): cardinal; stdcall;
+ external 'secur32.dll';
+
+function ApplyControlToken(phContext: PCtxtHandle;
+ pInput: PSecBufferDesc): cardinal; stdcall;
+ external 'secur32.dll';
+
+function QueryContextAttributesW(phContext: PCtxtHandle; ulAttribute: cardinal;
+ pBuffer: pointer): cardinal; stdcall;
+ external 'secur32.dll';
+
+function FreeContextBuffer(pvContextBuffer: pointer): cardinal; stdcall;
+ external 'secur32.dll';
+
+function EncryptMessage(phContext: PCtxtHandle; fQOP: cardinal;
+ pMessage: PSecBufferDesc; MessageSeqNo: cardinal): cardinal; stdcall;
+ external 'secur32.dll';
+
+function DecryptMessage(phContext: PCtxtHandle; pMessage: PSecBufferDesc;
+ MessageSeqNo: cardinal; pfQOP: PCardinal): cardinal; stdcall;
+ external 'secur32.dll';
+
+implementation
+
+// Add reference to NetCom7 lines unit
+uses ncLines;
+
+// We make a descendant of TncLine so that we can access the protected methods
+type
+ TncLineInternal = class(TncLine);
+
+{ Certificate Loading Functions }
+
+function LoadCertificateFromPFX(const FileName: AnsiString; const Password: AnsiString): PCCERT_CONTEXT;
+var
+ FileHandle: THandle;
+ FileSize: DWORD;
+ PFXData: array of Byte;
+ BytesRead: DWORD;
+ PFXBlob: CRYPT_DATA_BLOB;
+ CertStore: HCERTSTORE;
+ PasswordW: WideString;
+begin
+ Result := nil;
+
+ // Read PFX file
+ FileHandle := CreateFileA(PAnsiChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if FileHandle = INVALID_HANDLE_VALUE then
+ begin
+ // Failed to open file
+ Exit;
+ end;
+
+ try
+ FileSize := GetFileSize(FileHandle, nil);
+ if FileSize = INVALID_FILE_SIZE then
+ begin
+ // Invalid file size
+ Exit;
+ end;
+
+ SetLength(PFXData, FileSize);
+ if not ReadFile(FileHandle, PFXData[0], FileSize, BytesRead, nil) or (BytesRead <> FileSize) then
+ begin
+ // Failed to read file data
+ Exit;
+ end;
+ finally
+ CloseHandle(FileHandle);
+ end;
+
+ // Import PFX
+ PFXBlob.cbData := FileSize;
+ PFXBlob.pbData := @PFXData[0];
+ PasswordW := WideString(string(Password)); // Convert AnsiString to WideString
+
+ // Import with no flags to allow full private key access for TLS operations
+ CertStore := PFXImportCertStore(@PFXBlob, PWideChar(PasswordW), 0);
+ if CertStore = nil then
+ begin
+ // PFXImportCertStore failed
+ Exit;
+ end;
+
+ try
+ // Get first certificate from store
+ Result := CertEnumCertificatesInStore(CertStore, nil);
+ finally
+ CertCloseStore(CertStore, 0);
+ end;
+end;
+
+{ SChannel Simplified Cleanup Functions}
+
+/// Simplified cleanup for security context handles
+procedure FreeSecurityContextSafe(var handle: TCtxtHandle);
+begin
+ if (handle.dwLower <> 0) or (handle.dwUpper <> 0) then begin
+ DeleteSecurityContext(@handle);
+ FillChar(handle, SizeOf(handle), 0);
+ end;
+end;
+
+/// Simplified cleanup for credential handles
+procedure FreeCredentialsHandleSafe(var handle: TCredHandle);
+begin
+ if (handle.dwLower <> 0) or (handle.dwUpper <> 0) then begin
+ FreeCredentialsHandle(@handle);
+ FillChar(handle, SizeOf(handle), 0);
+ end;
+end;
+
+/// Check if credential handle is in uninitialized state
+function IsCredHandleInvalid(const handle: TCredHandle): Boolean;
+begin
+ Result := (handle.dwLower = 0) and (handle.dwUpper = 0);
+end;
+
+{ TSChannel Helper Functions }
+
+procedure RaiseLastError; // not defined e.g. with Delphi 5
+var
+ LastError: Integer;
+begin
+ LastError := GetLastError;
+ if LastError <> 0 then
+ raise ESChannel.CreateFmt('System Error %d [%s]', [LastError, SysErrorMessage(LastError)])
+ else
+ raise ESChannel.Create('Unknown SChannel error');
+end;
+
+function CheckSEC_E_OK(res: cardinal): cardinal;
+begin
+ if res <> SEC_E_OK then
+ begin
+ case res of
+ $80090318: raise ESChannel.Create('SEC_E_INCOMPLETE_MESSAGE');
+ $80090308: raise ESChannel.Create('SEC_E_INVALID_TOKEN');
+ $00090312: raise ESChannel.Create('SEC_I_CONTINUE_NEEDED (unexpected)');
+ $00090320: raise ESChannel.Create('SEC_I_INCOMPLETE_CREDENTIALS (unexpected)');
+ $00090321: raise ESChannel.Create('SEC_I_RENEGOTIATE (unexpected)');
+ $00090317: raise ESChannel.Create('SEC_I_CONTEXT_EXPIRED (unexpected)');
+ else
+ raise ESChannel.CreateFmt('SChannel error: 0x%08X', [res]);
+ end;
+ end;
+ result := res;
+end;
+
+function CheckSocket(res: integer): cardinal;
+begin
+ if res <= 0 then
+ raise ESChannel.CreateFmt('Socket Error %d', [res]);
+ result := res;
+end;
+
+const
+ TLSRECMAXSIZE = 19000; // stack buffers for TSChannelClient.Receive/Send
+
+type
+ {$ifdef USERECORDWITHMETHODS}THandshakeBuf = record
+ {$else}THandshakeBuf = object{$endif}
+ public
+ buf: array[0..4] of TSecBuffer;
+ input, output: TSecBufferDesc;
+ procedure Init;
+ end;
+
+procedure THandshakeBuf.Init;
+begin
+ input.ulVersion := SECBUFFER_VERSION;
+ input.cBuffers := 2;
+ input.pBuffers := @buf[0];
+ buf[0].cbBuffer := 0;
+ buf[0].BufferType := SECBUFFER_TOKEN;
+ buf[0].pvBuffer := nil;
+ buf[1].cbBuffer := 0;
+ buf[1].BufferType := SECBUFFER_EMPTY;
+ buf[1].pvBuffer := nil;
+ output.ulVersion := SECBUFFER_VERSION;
+ output.cBuffers := 1;
+ output.pBuffers := @buf[2];
+ buf[2].cbBuffer := 0;
+ buf[2].BufferType := SECBUFFER_TOKEN;
+ buf[2].pvBuffer := nil;
+end;
+
+{ TSChannelClient - Client-side SChannel implementation }
+
+procedure TSChannelClient.AppendData(const aBuffer: TSecBuffer);
+var
+ newlen: integer;
+begin
+ newlen := DataCount + integer(aBuffer.cbBuffer);
+ if newlen > Length(Data) then
+ SetLength(Data, newlen);
+ Move(aBuffer.pvBuffer^, PByteArray(Data)[DataCount], aBuffer.cbBuffer);
+ inc(DataCount, aBuffer.cbBuffer);
+end;
+
+procedure TSChannelClient.AfterConnection(aLine: TObject; const aTargetHost: AnsiString; aIgnoreCertificateErrors: boolean);
+var
+ TargetHostString: WideString;
+ f: cardinal;
+ res: cardinal;
+ schannelCred: TSChannelCred;
+ buf: THandshakeBuf;
+ trial: integer;
+ lastError: cardinal;
+
+begin
+ trial := 0;
+
+ // Retry loop for Windows 7/8 TLS bugs
+ while true do
+ try
+ // Clean up any existing TLS context from previous connection
+ if Initialized then
+ begin
+ FreeSecurityContextSafe(Ctxt);
+ FreeCredentialsHandleSafe(Cred);
+ Initialized := false;
+ SessionClosed := false;
+ DataCount := 0;
+ DataPos := 0;
+ end;
+
+ // Setup target host for handshake
+ TargetHostString := WideString(string(aTargetHost));
+
+ // Setup SChannel credentials
+ FillChar(schannelCred, SizeOf(schannelCred), 0);
+ schannelCred.dwVersion := SCHANNEL_CRED_VERSION;
+ if aIgnoreCertificateErrors then
+ schannelCred.dwFlags := SCH_CRED_MANUAL_CRED_VALIDATION or SCH_CRED_NO_DEFAULT_CREDS
+ else
+ schannelCred.dwFlags := SCH_CRED_REVOCATION_CHECK_CHAIN or SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+
+ // Direct credential acquisition
+ res := AcquireCredentialsHandleW(
+ nil, UNISP_NAME, SECPKG_CRED_OUTBOUND, nil, @schannelCred, nil, nil, @Cred, nil);
+ if res <> SEC_E_OK then
+ raise ESChannel.CreateFmt('AcquireCredentialsHandleW failed: 0x%08X', [res]);
+
+ // Initialize data buffers
+ DataPos := 0;
+ DataCount := 0;
+ SetLength(Data, TLSRECMAXSIZE);
+
+ // Setup handshake flags - simplified approach
+ f := ISC_REQ_FLAGS;
+ if aIgnoreCertificateErrors then
+ f := f or ISC_REQ_MANUAL_CRED_VALIDATION or ISC_REQ_USE_SUPPLIED_CREDS;
+
+ // Initialize handshake buffer
+ buf.Init;
+
+ // Initiate client handshake
+ res := InitializeSecurityContextW(@Cred, nil, PWideChar(TargetHostString),
+ f, 0, SECURITY_NATIVE_DREP, nil, 0, @Ctxt, @buf.output, f, nil);
+
+ if res <> SEC_I_CONTINUE_NEEDED then
+ raise ESChannel.CreateFmt('InitializeSecurityContext failed: 0x%08X', [res]);
+
+ // Send initial handshake data
+ if (buf.buf[2].cbBuffer = 0) or (buf.buf[2].pvBuffer = nil) then
+ raise ESChannel.CreateFmt('Void Hello answer to %s', [string(aTargetHost)]);
+
+ try
+ TncLineInternal(TncLine(aLine)).SendBuffer(buf.buf[2].pvBuffer^, buf.buf[2].cbBuffer);
+ finally
+ FreeContextBuffer(buf.buf[2].pvBuffer);
+ end;
+
+ // Complete the handshake
+ HandshakeLoop(aLine);
+
+ // Query stream sizes after successful handshake
+ res := QueryContextAttributesW(@Ctxt, SECPKG_ATTR_STREAM_SIZES, @Sizes);
+ if res <> SEC_E_OK then
+ raise ESChannel.CreateFmt('QueryContextAttributes failed: 0x%08X', [res]);
+
+ InputSize := Sizes.cbHeader + Sizes.cbMaximumMessage + Sizes.cbTrailer;
+ if InputSize > TLSRECMAXSIZE then
+ raise ESChannel.CreateFmt('InputSize=%d>%d', [InputSize, TLSRECMAXSIZE]);
+
+ SetLength(Input, InputSize);
+ InputCount := 0;
+ Initialized := true;
+
+ break; // Success - exit retry loop
+
+ except
+ // Retry for known Windows 7/8 TLS bugs
+ on E: ESChannel do
+ begin
+ lastError := GetLastError;
+ if (trial = 0) and
+ ((res = SEC_E_BUFFER_TOO_SMALL) or (res = SEC_E_MESSAGE_ALTERED)) then
+ begin
+ // Cleanup and retry once for Windows TLS bug
+ FreeSecurityContextSafe(Ctxt);
+ FreeCredentialsHandleSafe(Cred);
+ inc(trial);
+ // Continue retry loop
+ end
+ else
+ raise; // Re-raise if not a retryable error or already tried
+ end;
+ end;
+end;
+
+procedure TSChannelClient.HandshakeLoop(aLine: TObject);
+var
+ buf: THandshakeBuf;
+ res, f: cardinal;
+ Line: TncLine;
+ LoopCount: Integer;
+ RecvResult: Integer;
+begin
+ Line := TncLine(aLine);
+ res := SEC_I_CONTINUE_NEEDED;
+ LoopCount := 0;
+
+ while (res = SEC_I_CONTINUE_NEEDED) or (res = SEC_E_INCOMPLETE_MESSAGE) do begin
+ Inc(LoopCount);
+
+ RecvResult := TncLineInternal(Line).RecvBuffer(PByteArray(Data)[DataCount], length(Data) - DataCount);
+
+ inc(DataCount, CheckSocket(RecvResult));
+
+ buf.Init;
+ buf.buf[0].cbBuffer := DataCount;
+ buf.buf[0].BufferType := SECBUFFER_TOKEN;
+ buf.buf[0].pvBuffer := pointer(Data);
+
+ res := InitializeSecurityContextW(@Cred, @Ctxt, nil, ISC_REQ_FLAGS, 0,
+ SECURITY_NATIVE_DREP, @buf.input, 0, @Ctxt, @buf.output, f, nil);
+
+ if res = SEC_I_INCOMPLETE_CREDENTIALS then
+ begin
+ // check https://stackoverflow.com/a/47479968/458259
+ res := InitializeSecurityContextW(@Cred, @Ctxt, nil, ISC_REQ_FLAGS, 0,
+ SECURITY_NATIVE_DREP, @buf.input, 0, @Ctxt, @buf.output, f, nil);
+ end;
+
+ if (res = SEC_E_OK) or (res = SEC_I_CONTINUE_NEEDED) or
+ ((f and ISC_REQ_EXTENDED_ERROR) <> 0) then begin
+ if (buf.buf[2].cbBuffer <> 0) and (buf.buf[2].pvBuffer <> nil) then begin
+ CheckSocket(TncLineInternal(Line).SendBuffer(buf.buf[2].pvBuffer^, buf.buf[2].cbBuffer));
+ CheckSEC_E_OK(FreeContextBuffer(buf.buf[2].pvBuffer));
+ end;
+ end;
+
+ if buf.buf[1].BufferType = SECBUFFER_EXTRA then begin
+ // reuse pending Data bytes to avoid SEC_E_INVALID_TOKEN
+ Move(PByteArray(Data)[cardinal(DataCount) - buf.buf[1].cbBuffer],
+ PByteArray(Data)[0], buf.buf[1].cbBuffer);
+ DataCount := buf.buf[1].cbBuffer;
+ end else
+ if res <> SEC_E_INCOMPLETE_MESSAGE then
+ DataCount := 0;
+ end;
+
+ CheckSEC_E_OK(res);
+end;
+
+procedure TSChannelClient.BeforeDisconnection(aLine: TObject);
+var
+ desc: TSecBufferDesc;
+ buf: TSecBuffer;
+ dt, f: cardinal;
+ Line: TncLine;
+begin
+ if Initialized then
+ try
+ Line := TncLine(aLine);
+ if (Line <> nil) and Line.Active then begin
+ // Send TLS shutdown notification
+ desc.ulVersion := SECBUFFER_VERSION;
+ desc.cBuffers := 1;
+ desc.pBuffers := @buf;
+ buf.cbBuffer := 4;
+ buf.BufferType := SECBUFFER_TOKEN;
+ dt := SCHANNEL_SHUTDOWN;
+ buf.pvBuffer := @dt;
+ if ApplyControlToken(@Ctxt, @desc) = SEC_E_OK then begin
+ buf.cbBuffer := 0;
+ buf.BufferType := SECBUFFER_TOKEN;
+ buf.pvBuffer := nil;
+ if InitializeSecurityContextW(@Cred, @Ctxt, nil, ISC_REQ_FLAGS, 0,
+ SECURITY_NATIVE_DREP, nil, 0, @Ctxt, @desc, f, nil) = SEC_E_OK then begin
+ TncLineInternal(Line).SendBuffer(buf.pvBuffer^, buf.cbBuffer);
+ FreeContextBuffer(buf.pvBuffer);
+ end;
+ end;
+ end;
+ // Simple cleanup with zero-fill
+ FreeSecurityContextSafe(Ctxt);
+ FreeCredentialsHandleSafe(Cred);
+ finally
+ // Simple zero-fill
+ FillChar(Cred, SizeOf(Cred), 0);
+ FillChar(Ctxt, SizeOf(Ctxt), 0);
+ Initialized := false;
+ end;
+end;
+
+function TSChannelClient.Receive(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+var
+ desc: TSecBufferDesc;
+ buf: array[0..3] of TSecBuffer;
+ res: cardinal;
+ read, i: integer;
+ needsRenegotiate: boolean;
+ Line: TncLine;
+
+ function DecryptInput: cardinal;
+ begin
+ buf[0].cbBuffer := InputCount;
+ buf[0].BufferType := SECBUFFER_DATA;
+ buf[0].pvBuffer := pointer(Input);
+ buf[1].cbBuffer := 0;
+ buf[1].BufferType := SECBUFFER_EMPTY;
+ buf[1].pvBuffer := nil;
+ buf[2].cbBuffer := 0;
+ buf[2].BufferType := SECBUFFER_EMPTY;
+ buf[2].pvBuffer := nil;
+ buf[3].cbBuffer := 0;
+ buf[3].BufferType := SECBUFFER_EMPTY;
+ buf[3].pvBuffer := nil;
+ result := DecryptMessage(@Ctxt, @desc, 0, nil);
+ end;
+begin
+ Line := TncLine(aLine);
+
+ if not Initialized then begin // use plain socket API
+ result := TncLineInternal(Line).RecvBuffer(aBuffer^, aLength);
+ exit;
+ end;
+ result := 0;
+ if not SessionClosed then
+ while DataCount = 0 do
+ try
+ DataPos := 0;
+ desc.ulVersion := SECBUFFER_VERSION;
+ desc.cBuffers := 4;
+ desc.pBuffers := @buf[0];
+ repeat
+ read := TncLineInternal(Line).RecvBuffer(PByteArray(Input)[InputCount], InputSize - InputCount);
+ if read <= 0 then begin
+ SessionClosed := true; // Mark session as closed when recv returns <= 0
+ result := read; // return socket error
+ exit;
+ end;
+ inc(InputCount, read);
+ res := DecryptInput;
+ until res <> SEC_E_INCOMPLETE_MESSAGE;
+ needsRenegotiate := false;
+ repeat
+ case res of
+ SEC_I_RENEGOTIATE:
+ needsRenegotiate := true;
+ SEC_I_CONTEXT_EXPIRED:
+ SessionClosed := true;
+ SEC_E_INCOMPLETE_MESSAGE:
+ break;
+ else CheckSEC_E_OK(res);
+ end;
+ InputCount := 0;
+ for i := 1 to 3 do
+ case buf[i].BufferType of
+ SECBUFFER_DATA:
+ AppendData(buf[i]);
+ SECBUFFER_EXTRA:
+ begin
+ Move(buf[i].pvBuffer^, pointer(Input)^, buf[i].cbBuffer);
+ InputCount := buf[i].cbBuffer;
+ end;
+ end;
+ if InputCount = 0 then
+ break;
+ res := DecryptInput;
+ until false;
+ if needsRenegotiate then
+ HandshakeLoop(aLine);
+ except
+ on E: Exception do
+ begin
+ // CRITICAL FIX: Reset InputCount to clear corrupted TLS data from buffer
+ // Without this, corrupted data accumulates and causes repeated decryption failures
+ InputCount := 0;
+ SessionClosed := true; // Mark session as closed on exception
+ exit; // shutdown the connection on ESChannel fatal error
+ end;
+ end;
+ result := DataCount;
+ if aLength < result then
+ result := aLength;
+ Move(PByteArray(Data)[DataPos], aBuffer^, result);
+ inc(DataPos, result);
+ dec(DataCount, result);
+end;
+
+function TSChannelClient.Send(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+var
+ desc: TSecBufferDesc;
+ buf: array[0..3] of TSecBuffer;
+ res, sent, s, len, trailer, pending, templen: cardinal;
+ temp: array[0..TLSRECMAXSIZE] of byte;
+ Line: TncLine;
+
+begin
+ Line := TncLine(aLine);
+ if not Initialized then begin // use plain socket API
+ result := TncLineInternal(Line).SendBuffer(aBuffer^, aLength);
+ exit;
+ end;
+
+ // Check if Sizes has been initialized
+ if Sizes.cbMaximumMessage = 0 then
+ begin
+ if QueryContextAttributesW(@Ctxt, SECPKG_ATTR_STREAM_SIZES, @Sizes) <> SEC_E_OK then
+ begin
+ result := -1;
+ exit;
+ end;
+ end;
+
+ result := 0;
+ desc.ulVersion := SECBUFFER_VERSION;
+ desc.cBuffers := 4;
+ desc.pBuffers := @buf[0];
+ pending := aLength;
+ while pending > 0 do begin
+ templen := pending;
+ if templen > Sizes.cbMaximumMessage then
+ templen := Sizes.cbMaximumMessage;
+ Move(aBuffer^, temp[Sizes.cbHeader], templen);
+ inc(PByte(aBuffer), templen);
+ dec(pending, templen);
+ trailer := Sizes.cbHeader + templen;
+ buf[0].cbBuffer := Sizes.cbHeader;
+ buf[0].BufferType := SECBUFFER_STREAM_HEADER;
+ buf[0].pvBuffer := @temp;
+ buf[1].cbBuffer := templen;
+ buf[1].BufferType := SECBUFFER_DATA;
+ buf[1].pvBuffer := @temp[Sizes.cbHeader];
+ buf[2].cbBuffer := Sizes.cbTrailer;
+ buf[2].BufferType := SECBUFFER_STREAM_TRAILER;
+ buf[2].pvBuffer := @temp[trailer];
+ buf[3].cbBuffer := 0;
+ buf[3].BufferType := SECBUFFER_EMPTY;
+ buf[3].pvBuffer := nil;
+ if EncryptMessage(@Ctxt, 0, @desc, 0) <> SEC_E_OK then
+ begin
+ exit; // shutdown the connection on SChannel error
+ end;
+ len := buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer;
+ sent := 0;
+ repeat
+ s := TncLineInternal(Line).SendBuffer(PByteArray(@temp)[sent], len);
+ if s = len then
+ break; // whole message sent
+ if s = 0 then
+ begin
+ exit; // report connection closed
+ end;
+ if integer(s) < 0 then begin
+ result := s;
+ exit; // report socket fatal error
+ end
+ else begin
+ dec(len, s);
+ inc(sent, s);
+ end;
+ Sleep(1); // try again
+ until false;
+ end;
+ result := aLength;
+end;
+
+{ TSChannelServer - Server-side SChannel implementation }
+
+procedure TSChannelServer.AppendData(const aBuffer: TSecBuffer);
+var
+ newlen: integer;
+begin
+ newlen := DataCount + integer(aBuffer.cbBuffer);
+ if newlen > Length(Data) then
+ SetLength(Data, newlen);
+ Move(aBuffer.pvBuffer^, PByteArray(Data)[DataCount], aBuffer.cbBuffer);
+ inc(DataCount, aBuffer.cbBuffer);
+end;
+
+procedure TSChannelServer.AfterConnection(aLine: TObject; const aCertificateFile, aPrivateKeyPassword: AnsiString);
+var
+ res: cardinal;
+ Line: TncLine;
+ SchannelCred: TSChannelCred;
+ pCertContext: PCCERT_CONTEXT;
+ pCertArray: PCCERT_CONTEXT; // Array of one certificate context for paCred
+
+begin
+ // Clean up any existing TLS context from previous connection
+ if Initialized then
+ begin
+ FreeSecurityContextSafe(Ctxt);
+ FreeCredentialsHandleSafe(Cred);
+ Initialized := false;
+ HandshakeCompleted := false;
+ SessionClosed := false;
+ DataCount := 0;
+ DataPos := 0;
+ end;
+
+ Line := TncLine(aLine);
+
+ // Initialize server credentials with certificate
+ FillChar(SchannelCred, SizeOf(SchannelCred), 0);
+ SchannelCred.dwVersion := SCHANNEL_CRED_VERSION;
+ SchannelCred.grbitEnabledProtocols := SP_PROT_TLS1_2_SERVER or SP_PROT_TLS1_3_SERVER;
+ SchannelCred.dwFlags := 0; // No special flags for server
+
+ // Load certificate from PFX file
+ pCertContext := nil;
+ if aCertificateFile <> '' then
+ begin
+ pCertContext := LoadCertificateFromPFX(aCertificateFile, aPrivateKeyPassword);
+ if pCertContext <> nil then
+ begin
+ pCertArray := pCertContext; // Create array element
+ SchannelCred.cCreds := 1;
+ SchannelCred.paCred := @pCertArray; // Point to the array
+ end
+ else
+ raise ESChannel.CreateFmt('Failed to load certificate from: %s', [string(aCertificateFile)]);
+ end
+ else
+ raise ESChannel.Create('Certificate file required for TLS server');
+
+ try
+ // Direct credential acquisition
+ res := AcquireCredentialsHandleW(
+ nil, UNISP_NAME, SECPKG_CRED_INBOUND, nil, @SchannelCred, nil, nil, @Cred, nil);
+ if res <> SEC_E_OK then
+ raise ESChannel.CreateFmt('AcquireCredentialsHandleW failed: 0x%08X', [res]);
+
+ // Initialize buffers
+ DataPos := 0;
+ DataCount := 0;
+ SetLength(Data, TLSRECMAXSIZE);
+ SetLength(Input, TLSRECMAXSIZE);
+ InputCount := 0;
+ Initialized := true; // Mark as initialized but handshake not yet completed
+ HandshakeCompleted := false; // Handshake will be triggered when first TLS data arrives
+
+ finally
+ // Free certificate context
+ if pCertContext <> nil then
+ CertFreeCertificateContext(pCertContext);
+ end;
+end;
+
+procedure TSChannelServer.HandshakeLoop(aLine: TObject);
+var
+ buf: THandshakeBuf;
+ res, f: cardinal;
+ Line: TncLine;
+ fDone: boolean;
+ fInitContext: boolean;
+ LoopCount: Integer;
+ RecvResult: Integer;
+
+begin
+ Line := TncLine(aLine);
+ fDone := false;
+ fInitContext := true;
+ LoopCount := 0;
+
+ try
+ while not fDone do
+ begin
+ Inc(LoopCount);
+
+ // Read client data
+ try
+ RecvResult := TncLineInternal(Line).RecvBuffer(PByteArray(Data)[DataCount], length(Data) - DataCount);
+ inc(DataCount, CheckSocket(RecvResult));
+ except
+ on E: Exception do
+ begin
+ raise ESChannel.CreateFmt('Failed to receive client data: %s', [E.Message]);
+ end;
+ end;
+
+ buf.Init;
+ buf.buf[0].cbBuffer := DataCount;
+ buf.buf[0].BufferType := SECBUFFER_TOKEN;
+ buf.buf[0].pvBuffer := pointer(Data);
+
+ // Server-side handshake using AcceptSecurityContext
+ if fInitContext then
+ begin
+ // CRITICAL: Server must use AcceptSecurityContext, not InitializeSecurityContext
+ res := AcceptSecurityContext(@Cred, nil, @buf.input,
+ ASC_REQ_FLAGS, SECURITY_NATIVE_DREP, @Ctxt, @buf.output, f, nil);
+ fInitContext := false;
+ end
+ else
+ begin
+ res := AcceptSecurityContext(@Cred, @Ctxt, @buf.input,
+ ASC_REQ_FLAGS, SECURITY_NATIVE_DREP, @Ctxt, @buf.output, f, nil);
+ end;
+
+ case res of
+ SEC_E_OK:
+ begin
+ fDone := true;
+ end;
+ SEC_I_CONTINUE_NEEDED:
+ begin
+ // Continue handshake
+ end;
+ SEC_I_INCOMPLETE_CREDENTIALS:
+ begin
+ // Continue with current data
+ end;
+ SEC_E_INCOMPLETE_MESSAGE:
+ begin
+ // Need more data from client
+ continue;
+ end;
+ else
+ begin
+ raise ESChannel.CreateFmt('AcceptSecurityContext failed: 0x%08X', [res]);
+ end;
+ end;
+
+ // Send response to client if needed
+ if (buf.buf[2].cbBuffer <> 0) and (buf.buf[2].pvBuffer <> nil) then
+ begin
+ try
+ CheckSocket(TncLineInternal(Line).SendBuffer(buf.buf[2].pvBuffer^, buf.buf[2].cbBuffer));
+ CheckSEC_E_OK(FreeContextBuffer(buf.buf[2].pvBuffer));
+ except
+ on E: Exception do
+ begin
+ raise ESChannel.CreateFmt('Failed to send server response: %s', [E.Message]);
+ end;
+ end;
+ end;
+
+ // Handle extra data
+ if buf.buf[1].BufferType = SECBUFFER_EXTRA then
+ begin
+ Move(PByteArray(Data)[cardinal(DataCount) - buf.buf[1].cbBuffer],
+ PByteArray(Data)[0], buf.buf[1].cbBuffer);
+ DataCount := buf.buf[1].cbBuffer;
+ end
+ else if not fDone then
+ begin
+ DataCount := 0;
+ end;
+ end;
+
+ except
+ on E: Exception do
+ begin
+ raise ESChannel.CreateFmt('TLS handshake failed: %s', [E.Message]);
+ end;
+ end;
+end;
+
+procedure TSChannelServer.BeforeDisconnection(aLine: TObject);
+var
+ desc: TSecBufferDesc;
+ buf: TSecBuffer;
+ dt, f: cardinal;
+ Line: TncLine;
+begin
+ if Initialized then
+ try
+ Line := TncLine(aLine);
+ if (Line <> nil) and Line.Active then begin
+ // Send TLS shutdown notification
+ desc.ulVersion := SECBUFFER_VERSION;
+ desc.cBuffers := 1;
+ desc.pBuffers := @buf;
+ buf.cbBuffer := 4;
+ buf.BufferType := SECBUFFER_TOKEN;
+ dt := SCHANNEL_SHUTDOWN;
+ buf.pvBuffer := @dt;
+ if ApplyControlToken(@Ctxt, @desc) = SEC_E_OK then begin
+ buf.cbBuffer := 0;
+ buf.BufferType := SECBUFFER_TOKEN;
+ buf.pvBuffer := nil;
+ if AcceptSecurityContext(@Cred, @Ctxt, nil, ASC_REQ_FLAGS,
+ SECURITY_NATIVE_DREP, @Ctxt, @desc, f, nil) = SEC_E_OK then begin
+ TncLineInternal(Line).SendBuffer(buf.pvBuffer^, buf.cbBuffer);
+ FreeContextBuffer(buf.pvBuffer);
+ end;
+ end;
+ end;
+ // Simple cleanup with zero-fill
+ FreeSecurityContextSafe(Ctxt);
+ FreeCredentialsHandleSafe(Cred);
+ finally
+ // Simple zero-fill
+ FillChar(Cred, SizeOf(Cred), 0);
+ FillChar(Ctxt, SizeOf(Ctxt), 0);
+ Initialized := false;
+ HandshakeCompleted := false;
+ end;
+end;
+
+function TSChannelServer.Receive(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+var
+ desc: TSecBufferDesc;
+ buf: array[0..3] of TSecBuffer;
+ res: cardinal;
+ read, i: integer;
+ needsRenegotiate: boolean;
+ Line: TncLine;
+
+ function DecryptInput: cardinal;
+ begin
+ buf[0].cbBuffer := InputCount;
+ buf[0].BufferType := SECBUFFER_DATA;
+ buf[0].pvBuffer := pointer(Input);
+ buf[1].cbBuffer := 0;
+ buf[1].BufferType := SECBUFFER_EMPTY;
+ buf[1].pvBuffer := nil;
+ buf[2].cbBuffer := 0;
+ buf[2].BufferType := SECBUFFER_EMPTY;
+ buf[2].pvBuffer := nil;
+ buf[3].cbBuffer := 0;
+ buf[3].BufferType := SECBUFFER_EMPTY;
+ buf[3].pvBuffer := nil;
+ result := DecryptMessage(@Ctxt, @desc, 0, nil);
+ end;
+begin
+ Line := TncLine(aLine);
+
+ if not Initialized then begin // use plain socket API
+ result := TncLineInternal(Line).RecvBuffer(aBuffer^, aLength);
+ exit;
+ end;
+
+ // Check if handshake needs to be performed
+ if not HandshakeCompleted then
+ begin
+ try
+ HandshakeLoop(aLine);
+ CheckSEC_E_OK(QueryContextAttributesW(@Ctxt, SECPKG_ATTR_STREAM_SIZES, @Sizes));
+ InputSize := Sizes.cbHeader + Sizes.cbMaximumMessage + Sizes.cbTrailer;
+ if InputSize > TLSRECMAXSIZE then
+ raise ESChannel.CreateFmt('InputSize=%d>%d', [InputSize, TLSRECMAXSIZE]);
+ SetLength(Input, InputSize);
+ HandshakeCompleted := true;
+
+ // CRITICAL FIX: Clear any leftover handshake data to prevent it from being returned as application data
+ DataCount := 0;
+ DataPos := 0;
+ InputCount := 0;
+
+ // CRITICAL: Return immediately to trigger handshake completion callback
+ // We'll return 0 to indicate no application data was received,
+ // but set a special result to indicate handshake completion
+ result := 0;
+ exit;
+ except
+ on E: Exception do
+ begin
+ result := -1; // Return error
+ exit;
+ end;
+ end;
+ end;
+
+ result := 0;
+ if not SessionClosed then
+ while DataCount = 0 do
+ try
+ DataPos := 0;
+ desc.ulVersion := SECBUFFER_VERSION;
+ desc.cBuffers := 4;
+ desc.pBuffers := @buf[0];
+ repeat
+ read := TncLineInternal(Line).RecvBuffer(PByteArray(Input)[InputCount], InputSize - InputCount);
+ if read <= 0 then begin
+ SessionClosed := true; // Mark session as closed when recv returns <= 0
+ result := read; // return socket error
+ exit;
+ end;
+ inc(InputCount, read);
+ res := DecryptInput;
+ until res <> SEC_E_INCOMPLETE_MESSAGE;
+ needsRenegotiate := false;
+ repeat
+ case res of
+ SEC_I_RENEGOTIATE:
+ needsRenegotiate := true;
+ SEC_I_CONTEXT_EXPIRED:
+ SessionClosed := true;
+ SEC_E_INCOMPLETE_MESSAGE:
+ break;
+ else CheckSEC_E_OK(res);
+ end;
+ InputCount := 0;
+ for i := 1 to 3 do
+ case buf[i].BufferType of
+ SECBUFFER_DATA:
+ AppendData(buf[i]);
+ SECBUFFER_EXTRA:
+ begin
+ Move(buf[i].pvBuffer^, pointer(Input)^, buf[i].cbBuffer);
+ InputCount := buf[i].cbBuffer;
+ end;
+ end;
+ if InputCount = 0 then
+ break;
+ res := DecryptInput;
+ until false;
+ if needsRenegotiate then
+ HandshakeLoop(aLine);
+ except
+ on E: Exception do
+ begin
+ // CRITICAL FIX: Reset InputCount to clear corrupted TLS data from buffer
+ // Without this, corrupted data accumulates and causes repeated decryption failures
+ InputCount := 0;
+ SessionClosed := true; // Mark session as closed on exception
+ exit; // shutdown the connection on ESChannel fatal error
+ end;
+ end;
+ result := DataCount;
+ if aLength < result then
+ result := aLength;
+ Move(PByteArray(Data)[DataPos], aBuffer^, result);
+ inc(DataPos, result);
+ dec(DataCount, result);
+end;
+
+function TSChannelServer.Send(aLine: TObject; aBuffer: pointer; aLength: integer): integer;
+var
+ desc: TSecBufferDesc;
+ buf: array[0..3] of TSecBuffer;
+ res, sent, s, len, trailer, pending, templen: cardinal;
+ temp: array[0..TLSRECMAXSIZE] of byte;
+ Line: TncLine;
+
+begin
+ Line := TncLine(aLine);
+ if not Initialized then begin // use plain socket API
+ result := TncLineInternal(Line).SendBuffer(aBuffer^, aLength);
+ exit;
+ end;
+
+ // Check if Sizes has been initialized
+ if Sizes.cbMaximumMessage = 0 then
+ begin
+ if QueryContextAttributesW(@Ctxt, SECPKG_ATTR_STREAM_SIZES, @Sizes) <> SEC_E_OK then
+ begin
+ result := -1;
+ exit;
+ end;
+ end;
+
+ result := 0;
+ desc.ulVersion := SECBUFFER_VERSION;
+ desc.cBuffers := 4;
+ desc.pBuffers := @buf[0];
+ pending := aLength;
+ while pending > 0 do begin
+ templen := pending;
+ if templen > Sizes.cbMaximumMessage then
+ templen := Sizes.cbMaximumMessage;
+ Move(aBuffer^, temp[Sizes.cbHeader], templen);
+ inc(PByte(aBuffer), templen);
+ dec(pending, templen);
+ trailer := Sizes.cbHeader + templen;
+ buf[0].cbBuffer := Sizes.cbHeader;
+ buf[0].BufferType := SECBUFFER_STREAM_HEADER;
+ buf[0].pvBuffer := @temp;
+ buf[1].cbBuffer := templen;
+ buf[1].BufferType := SECBUFFER_DATA;
+ buf[1].pvBuffer := @temp[Sizes.cbHeader];
+ buf[2].cbBuffer := Sizes.cbTrailer;
+ buf[2].BufferType := SECBUFFER_STREAM_TRAILER;
+ buf[2].pvBuffer := @temp[trailer];
+ buf[3].cbBuffer := 0;
+ buf[3].BufferType := SECBUFFER_EMPTY;
+ buf[3].pvBuffer := nil;
+ if EncryptMessage(@Ctxt, 0, @desc, 0) <> SEC_E_OK then
+ begin
+ exit; // shutdown the connection on SChannel error
+ end;
+ len := buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer;
+ sent := 0;
+ repeat
+ s := TncLineInternal(Line).SendBuffer(PByteArray(@temp)[sent], len);
+ if s = len then
+ break; // whole message sent
+ if s = 0 then
+ begin
+ exit; // report connection closed
+ end;
+ if integer(s) < 0 then begin
+ result := s;
+ exit; // report socket fatal error
+ end
+ else begin
+ dec(len, s);
+ inc(sent, s);
+ end;
+ Sleep(1); // try again
+ until false;
+ end;
+ result := aLength;
+end;
+
+
+end.
diff --git a/Source/ncSockets.pas b/Source/ncSockets.pas
index 8d832d8..bc68d08 100644
--- a/Source/ncSockets.pas
+++ b/Source/ncSockets.pas
@@ -7,6 +7,23 @@
// This unit creates a TCP Server and TCP Client socket, along with their
// threads dealing with reading from the socket
//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 13/07/2025 - by J.Pauwels
+// - Added TLS implementation support through SChannel integration
+// - Added TLS properties (UseTLS, TlsProvider, CertificateFile) to TncTCPBase
+// - Integrated TLS handshake callbacks in OnBeforeConnected architecture
+// - Added secure communication capabilities for both server and client
+// - CRITICAL FIX: Implemented per-connection TLS context storage to support multiple concurrent TLS connections
+//
+// 14/01/2025 - by J.Pauwels
+// - Defined DefReadBufferLen as a new property
+// - Ajust TncCustomTCPServer.DataSocketDisconnected
+// - Explicitly set this unit to use TCP
+// - Update Client Send method so data cannot be send while socket is inactive
+// - Added IPV6 support
+//
// 9/8/2020
// - Added a ShutDownLine in the TCPServer component so as to allow to
// shutdown a line even when within a read operation
@@ -39,17 +56,54 @@
interface
uses
-{$IFDEF MSWINDOWS}
- Winapi.Windows, Winapi.Winsock2,
-{$ELSE}
- Posix.SysSocket, Posix.Unistd,
-{$ENDIF}
- System.Classes, System.SysUtils, System.SyncObjs, System.Math, System.Diagnostics, System.TimeSpan,
- ncLines, ncSocketList, ncThreads;
+ System.SysUtils,
+ System.Classes,
+ System.Diagnostics,
+ System.Math,
+ System.TimeSpan,
+ System.SyncObjs,
+ {$IFDEF MSWINDOWS}
+ Winapi.Windows,
+ Winapi.Winsock2,
+ ncSChannel,
+ {$ELSE}
+ Posix.SysSocket,
+ Posix.Unistd,
+ {$ENDIF}
+ ncSocketList,
+ ncLines,
+ ncThreads;
+
+type
+ // TLS Provider enumeration (declared early for use in constants)
+ TncTlsProvider = (
+ tpSChannel, // Windows SChannel (Windows only, no external dependencies)
+ tpOpenSSL // OpenSSL (cross-platform, requires OpenSSL DLLs)
+ );
+
+ {$IFDEF MSWINDOWS}
+ // Forward declarations for SChannel types (Windows only)
+ PSChannelClient = ^TSChannelClient;
+ PSChannelServer = ^TSChannelServer;
+
+ // Per-connection TLS context storage (Windows only)
+ TncTlsConnectionContext = class
+ private
+ FIsServer: Boolean;
+ FClientContext: TSChannelClient;
+ FServerContext: TSChannelServer;
+ public
+ constructor Create(aIsServer: Boolean);
+ destructor Destroy; override;
+ function GetClientContext: PSChannelClient;
+ function GetServerContext: PSChannelServer;
+ property IsServer: Boolean read FIsServer;
+ end;
+ {$ENDIF}
const
DefPort = 16233;
- DefHost = 'LocalHost';
+ DefHost = '';
DefReadBufferLen = 1024 * 1024; // 1 MB
DefReaderThreadPriority = ntpNormal;
DefCntReconnectInterval = 1000;
@@ -57,18 +111,40 @@ interface
DefUseReaderThread = True;
DefNoDelay = False;
DefKeepAlive = True;
+ DefFamily = afIPv4;
+ DefUseTLS = False;
+ DefTlsProvider = tpSChannel;
+ DefIgnoreCertificateErrors = False;
resourcestring
ECannotSetPortWhileConnectionIsActiveStr = 'Cannot set Port property whilst the connection is active';
ECannotSetHostWhileConnectionIsActiveStr = 'Cannot set Host property whilst the connection is active';
+ ECannotSendWhileSocketInactiveStr = 'Cannot send data while socket is inactive';
ECannotSetUseReaderThreadWhileActiveStr = 'Cannot set UseReaderThread property whilst the connection is active';
ECannotReceiveIfUseReaderThreadStr =
'Cannot receive data if UseReaderThread is set. Use OnReadData event handler to get the data or set UseReaderThread property to false';
+ ECannotSetFamilyWhileConnectionIsActiveStr = 'Cannot set Family property whilst the connection is active';
+ ETlsProviderNotSupportedStr = 'TLS provider not supported on this platform';
+ EOpenSSLNotAvailableStr = 'OpenSSL libraries not available';
type
EPropertySetError = class(Exception);
ENonActiveSocket = class(Exception);
ECannotReceiveIfUseReaderThread = class(Exception);
+ ETlsProviderNotSupported = class(Exception);
+ EOpenSSLNotAvailable = class(Exception);
+
+ // We bring in TncLine so that a form that uses our components does
+ // not have to reference ncLines unit to get the type
+ TncLine = ncLines.TncLine;
+
+ // We make a descendant of TncLine so that we can access the API functions.
+ // These API functions are not made puclic in TncLine so that the user cannot
+ // mangle up the line
+ TncLineInternal = class(TncLine);
+
+ // Forward declarations
+ TncCustomTCPServer = class;
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TThreadLineList
@@ -78,7 +154,6 @@ TThreadLineList = class
private
FList: TSocketList;
FListCopy: TSocketList;
- FLock: TCriticalSection;
FLockCount: Integer;
protected
procedure Add(const Item: TncLine); inline;
@@ -102,15 +177,38 @@ TThreadLineList = class
TncTCPBase = class(TComponent)
private
FInitActive: Boolean;
+ FFamily: TAddressType;
FPort: Integer;
FEventsUseMainThread: Boolean;
FNoDelay: Boolean;
FKeepAlive: Boolean;
+ FReadBufferLen: Integer; // Update
FOnConnected: TncOnConnectDisconnect;
FOnDisconnected: TncOnConnectDisconnect;
FOnReadData: TncOnReadData;
+ FLine: TncLine;
+
+ // TLS Properties
+ FUseTLS: Boolean;
+ FTlsProvider: TncTlsProvider;
+ FCertificateFile: string;
+ FPrivateKeyFile: string;
+ FPrivateKeyPassword: string;
+ FCACertificatesFile: string;
+ FIgnoreCertificateErrors: Boolean;
+ {$IFDEF MSWINDOWS}
+ FTlsContext: TSChannelClient;
+ FTlsServerContext: TSChannelServer;
+ {$ENDIF}
+ FIsServer: Boolean; // Flag to determine if this is a server or client
+
+ function GetReadBufferLen: Integer; // Update
+ procedure SetReadBufferLen(const Value: Integer); // Update
function GetActive: Boolean; virtual; abstract;
procedure SetActive(const Value: Boolean);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+
function GetPort: Integer;
procedure SetPort(const Value: Integer);
function GetReaderThreadPriority: TncThreadPriority;
@@ -121,21 +219,49 @@ TncTCPBase = class(TComponent)
procedure SetNoDelay(const Value: Boolean);
function GetKeepAlive: Boolean;
procedure SetKeepAlive(const Value: Boolean);
+
+ // TLS Property Methods
+ function GetUseTLS: Boolean;
+ procedure SetUseTLS(const Value: Boolean);
+ function GetTlsProvider: TncTlsProvider;
+ procedure SetTlsProvider(const Value: TncTlsProvider);
+ function GetCertificateFile: string;
+ procedure SetCertificateFile(const Value: string);
+ function GetPrivateKeyFile: string;
+ procedure SetPrivateKeyFile(const Value: string);
+ function GetPrivateKeyPassword: string;
+ procedure SetPrivateKeyPassword(const Value: string);
+ function GetCACertificatesFile: string;
+ procedure SetCACertificatesFile(const Value: string);
+ function GetIgnoreCertificateErrors: Boolean;
+ procedure SetIgnoreCertificateErrors(const Value: Boolean);
+
private
FUseReaderThread: Boolean;
+ PropertyLock, ShutDownLock: TObject; // TMonitor synchronization objects
+ ReadBuf: TBytes;
procedure DoActivate(aActivate: Boolean); virtual; abstract;
procedure SetUseReaderThread(const Value: Boolean);
protected
- PropertyLock, ShutDownLock: TCriticalSection;
- ReadBuf: TBytes;
procedure Loaded; override;
function CreateLineObject: TncLine; virtual;
+ function GetHost: string; virtual; // Virtual method for TLS
+ procedure InitializeTLS(aLine: TncLine); virtual;
+ procedure FinalizeTLS(aLine: TncLine); virtual;
+ function SendTLS(aLine: TncLine; const aBuf; aBufSize: Integer): Integer; virtual;
+ function ReceiveTLS(aLine: TncLine; var aBuf; aBufSize: Integer): Integer; virtual;
+ procedure HandleTLSHandshake(aLine: TncLine); virtual;
+ procedure HandleTLSHandshakeComplete(aLine: TncLine); virtual;
+ property Line: TncLine read FLine;
public
LineProcessor: TncReadyThread;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
+ function Kind: TSocketType; virtual;
+
property Active: Boolean read GetActive write SetActive default False;
+ property Family: TAddressType read GetFamily write SetFamily default afIPv4;
property Port: Integer read GetPort write SetPort default DefPort;
property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
property EventsUseMainThread: Boolean read GetEventsUseMainThread write SetEventsUseMainThread default DefEventsUseMainThread;
@@ -145,6 +271,16 @@ TncTCPBase = class(TComponent)
property OnConnected: TncOnConnectDisconnect read FOnConnected write FOnConnected;
property OnDisconnected: TncOnConnectDisconnect read FOnDisconnected write FOnDisconnected;
property OnReadData: TncOnReadData read FOnReadData write FOnReadData;
+ property ReadBufferLen: Integer read GetReadBufferLen write SetReadBufferLen default DefReadBufferLen; // Update
+
+ // TLS Properties
+ property UseTLS: Boolean read GetUseTLS write SetUseTLS default DefUseTLS;
+ property TlsProvider: TncTlsProvider read GetTlsProvider write SetTlsProvider default DefTlsProvider;
+ property CertificateFile: string read GetCertificateFile write SetCertificateFile;
+ property PrivateKeyFile: string read GetPrivateKeyFile write SetPrivateKeyFile;
+ property PrivateKeyPassword: string read GetPrivateKeyPassword write SetPrivateKeyPassword;
+ property CACertificatesFile: string read GetCACertificatesFile write SetCACertificatesFile;
+ property IgnoreCertificateErrors: Boolean read GetIgnoreCertificateErrors write SetIgnoreCertificateErrors default DefIgnoreCertificateErrors;
published
end;
@@ -190,6 +326,7 @@ TncCustomTCPClient = class(TncTCPBase)
TncTCPClient = class(TncCustomTCPClient)
published
property Active;
+ property Family;
property Port;
property Host;
property ReaderThreadPriority;
@@ -197,12 +334,21 @@ TncTCPClient = class(TncCustomTCPClient)
property UseReaderThread;
property NoDelay;
property KeepAlive;
+ property ReadBufferLen;
property Reconnect;
property ReconnectInterval;
property OnConnected;
property OnDisconnected;
property OnReadData;
property OnReconnected;
+ // TLS Properties
+ property UseTLS;
+ property TlsProvider;
+ property CertificateFile;
+ property PrivateKeyFile;
+ property PrivateKeyPassword;
+ property CACertificatesFile;
+ property IgnoreCertificateErrors;
end;
TncClientProcessor = class(TncReadyThread)
@@ -246,15 +392,25 @@ TncTCPServer = class(TncCustomTCPServer)
public
published
property Active;
+ property Family;
property Port;
property ReaderThreadPriority;
property EventsUseMainThread;
property UseReaderThread;
property NoDelay;
property KeepAlive;
+ property ReadBufferLen; // Update
property OnConnected;
property OnDisconnected;
property OnReadData;
+ // TLS Properties
+ property UseTLS;
+ property TlsProvider;
+ property CertificateFile;
+ property PrivateKeyFile;
+ property PrivateKeyPassword;
+ property CACertificatesFile;
+ property IgnoreCertificateErrors;
end;
TncServerProcessor = class(TncReadyThread)
@@ -269,15 +425,6 @@ TncServerProcessor = class(TncReadyThread)
procedure ProcessEvent; override;
end;
- // We bring in TncLine so that a form that uses our components does
- // not have to reference ncLines unit to get the type
- TncLine = ncLines.TncLine;
-
- // We make a descendant of TncLine so that we can access the API functions.
- // These API functions are not made puclic in TncLine so that the user cannot
- // mangle up the line
- TncLineInternal = class(TncLine);
-
implementation
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -287,7 +434,6 @@ implementation
constructor TThreadLineList.Create;
begin
inherited Create;
- FLock := TCriticalSection.Create;
FList := TSocketList.Create;
FLockCount := 0;
end;
@@ -300,7 +446,6 @@ destructor TThreadLineList.Destroy;
inherited Destroy;
finally
UnlockListNoCopy;
- FLock.Free;
end;
end;
@@ -338,18 +483,18 @@ procedure TThreadLineList.Remove(Item: TncLine);
function TThreadLineList.LockListNoCopy: TSocketList;
begin
- FLock.Acquire;
+ TMonitor.Enter(Self);
Result := FList;
end;
procedure TThreadLineList.UnlockListNoCopy;
begin
- FLock.Release;
+ TMonitor.Exit(Self);
end;
function TThreadLineList.LockList: TSocketList;
begin
- FLock.Acquire;
+ TMonitor.Enter(Self);
try
if FLockCount = 0 then
begin
@@ -360,13 +505,13 @@ function TThreadLineList.LockList: TSocketList;
FLockCount := FLockCount + 1;
finally
- FLock.Release;
+ TMonitor.Exit(Self);
end;
end;
procedure TThreadLineList.UnlockList;
begin
- FLock.Acquire;
+ TMonitor.Enter(Self);
try
if FLockCount = 0 then
raise Exception.Create('Cannot unlock a non-locked list');
@@ -376,10 +521,57 @@ procedure TThreadLineList.UnlockList;
if FLockCount = 0 then
FListCopy.Free;
finally
- FLock.Release;
+ TMonitor.Exit(Self);
end;
end;
+{$IFDEF MSWINDOWS}
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncTlsConnectionContext }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncTlsConnectionContext.Create(aIsServer: Boolean);
+begin
+ inherited Create;
+ FIsServer := aIsServer;
+
+ // Initialize TLS contexts using FillChar and then set public fields
+ FillChar(FClientContext, SizeOf(FClientContext), 0);
+ FClientContext.Initialized := False;
+
+ FillChar(FServerContext, SizeOf(FServerContext), 0);
+ FServerContext.Initialized := False;
+ FServerContext.HandshakeCompleted := False;
+end;
+
+destructor TncTlsConnectionContext.Destroy;
+begin
+ // In a perfect world, FinalizeTLS was already called
+ // and all cleanup is done - destructor should be nearly empty
+
+ {$IFDEF DEBUG}
+ // Debug check - verify cleanup already happened
+ if FIsServer then
+ Assert(not FServerContext.Initialized, 'Server TLS context not cleaned up!')
+ else
+ Assert(not FClientContext.Initialized, 'Client TLS context not cleaned up!');
+ {$ENDIF}
+
+ inherited Destroy;
+end;
+
+function TncTlsConnectionContext.GetClientContext: PSChannelClient;
+begin
+ Result := @FClientContext;
+end;
+
+function TncTlsConnectionContext.GetServerContext: PSChannelServer;
+begin
+ Result := @FServerContext;
+end;
+{$ENDIF}
+
+
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{ TncTCPBase }
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -388,26 +580,61 @@ constructor TncTCPBase.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
- PropertyLock := TCriticalSection.Create;
- ShutDownLock := TCriticalSection.Create;
+ PropertyLock := TObject.Create;
+ ShutDownLock := TObject.Create;
FInitActive := False;
+ FFamily := DefFamily;
FPort := DefPort;
FEventsUseMainThread := DefEventsUseMainThread;
FUseReaderThread := DefUseReaderThread;
FNoDelay := DefNoDelay;
FKeepAlive := DefKeepAlive;
+ FReadBufferLen := DefReadBufferLen; // Update
FOnConnected := nil;
FOnDisconnected := nil;
FOnReadData := nil;
+ // Initialize TLS properties
+ FUseTLS := DefUseTLS;
+ FTlsProvider := DefTlsProvider;
+ FCertificateFile := '';
+ FPrivateKeyFile := '';
+ FPrivateKeyPassword := '';
+ FCACertificatesFile := '';
+ FIgnoreCertificateErrors := DefIgnoreCertificateErrors;
+
+ {$IFDEF MSWINDOWS}
+ // Initialize TLS contexts using FillChar and then set public fields
+ FillChar(FTlsContext, SizeOf(FTlsContext), 0);
+ FTlsContext.Initialized := False;
+
+ FillChar(FTlsServerContext, SizeOf(FTlsServerContext), 0);
+ FTlsServerContext.Initialized := False;
+ FTlsServerContext.HandshakeCompleted := False;
+ {$ENDIF}
+
+ FIsServer := False;
+
SetLength(ReadBuf, DefReadBufferLen);
+
+end;
+
+function TncTCPBase.Kind: TSocketType;
+begin
+ Result := stTCP;
end;
destructor TncTCPBase.Destroy;
begin
- ShutDownLock.Free;
+ Active := False;
+
+ // TLS contexts are now managed per-connection and cleaned up in FinalizeTLS
+ // No global TLS context cleanup needed
+
PropertyLock.Free;
+ ShutDownLock.Free;
+
inherited Destroy;
end;
@@ -422,28 +649,67 @@ procedure TncTCPBase.Loaded;
function TncTCPBase.CreateLineObject: TncLine;
begin
Result := TncLineInternal.Create;
+ TncLineInternal(Result).SetKind(Kind);
+ TncLineInternal(Result).SetFamily(FFamily);
+
+ // Set up TLS callback if TLS is enabled
+ if FUseTLS then
+ TncLineInternal(Result).OnBeforeConnected := HandleTLSHandshake;
end;
procedure TncTCPBase.SetActive(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
if not(csLoading in ComponentState) then
DoActivate(Value);
FInitActive := GetActive; // we only care here for the loaded event
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetFamily: TAddressType;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FFamily;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetFamily(const Value: TAddressType);
+begin
+ if not (csLoading in ComponentState) then
+ begin
+ if Active then
+ raise EPropertySetError.Create(ECannotSetFamilyWhileConnectionIsActiveStr);
+ end;
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Update base class family
+ FFamily := Value;
+
+ // Update the Line's family
+ if FLine <> nil then
+ begin
+ TncLineInternal(FLine).SetFamily(Value);
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncTCPBase.GetPort: Integer;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FPort;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
@@ -453,27 +719,27 @@ procedure TncTCPBase.SetPort(const Value: Integer);
if Active then
raise EPropertySetError.Create(ECannotSetPortWhileConnectionIsActiveStr);
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FPort := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncTCPBase.GetReaderThreadPriority: TncThreadPriority;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := ToNcThreadPriority(LineProcessor.Priority);
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncTCPBase.SetReaderThreadPriority(const Value: TncThreadPriority);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
try
LineProcessor.Priority := FromNcThreadPriority(Value);
@@ -481,27 +747,27 @@ procedure TncTCPBase.SetReaderThreadPriority(const Value: TncThreadPriority);
// Some android devices cannot handle changing priority
end;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncTCPBase.GetEventsUseMainThread: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FEventsUseMainThread;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncTCPBase.SetEventsUseMainThread(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FEventsUseMainThread := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
@@ -511,54 +777,529 @@ procedure TncTCPBase.SetUseReaderThread(const Value: Boolean);
if Active then
raise EPropertySetError.Create(ECannotSetUseReaderThreadWhileActiveStr);
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FUseReaderThread := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncTCPBase.GetNoDelay: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FNoDelay;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncTCPBase.SetNoDelay(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FNoDelay := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncTCPBase.GetKeepAlive: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FKeepAlive;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncTCPBase.SetKeepAlive(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FKeepAlive := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
+// Update
+function TncTCPBase.GetReadBufferLen: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReadBufferLen;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// Update
+procedure TncTCPBase.SetReadBufferLen(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReadBufferLen := Value;
+ SetLength(ReadBuf, FReadBufferLen);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// TLS Property Methods
+function TncTCPBase.GetUseTLS: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FUseTLS;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetUseTLS(const Value: Boolean);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create('Cannot set UseTLS property whilst the connection is active');
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FUseTLS := Value;
+
+ // Add TLS callback assignment when TLS is enabled
+ if Value then
+ begin
+ if FIsServer and (Self is TncCustomTCPServer) then
+ begin
+ // Server callback assignment
+ var Server := TncCustomTCPServer(Self);
+ if Server.Listener <> nil then
+ begin
+ TncLineInternal(Server.Listener).OnBeforeConnected := HandleTLSHandshake;
+ end;
+ end
+ else if not FIsServer and (Self is TncCustomTCPClient) then
+ begin
+ // Client callback assignment
+ var Client := TncCustomTCPClient(Self);
+ if Client.Line <> nil then
+ begin
+ TncLineInternal(Client.Line).OnBeforeConnected := HandleTLSHandshake;
+ end;
+ end;
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetTlsProvider: TncTlsProvider;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FTlsProvider;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetTlsProvider(const Value: TncTlsProvider);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create('Cannot set TlsProvider property whilst the connection is active');
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Validate provider availability
+ case Value of
+ tpSChannel:
+ begin
+ {$IFNDEF MSWINDOWS}
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr);
+ {$ENDIF}
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL validation - for now, not supported
+ raise EOpenSSLNotAvailable.Create(EOpenSSLNotAvailableStr);
+ end;
+ end;
+
+ FTlsProvider := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetCertificateFile: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCertificateFile;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetCertificateFile(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCertificateFile := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetPrivateKeyFile: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPrivateKeyFile;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetPrivateKeyFile(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FPrivateKeyFile := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetPrivateKeyPassword: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPrivateKeyPassword;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetPrivateKeyPassword(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FPrivateKeyPassword := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetCACertificatesFile: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCACertificatesFile;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetCACertificatesFile(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCACertificatesFile := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBase.GetIgnoreCertificateErrors: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FIgnoreCertificateErrors;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBase.SetIgnoreCertificateErrors(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FIgnoreCertificateErrors := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// TLS base implementation
+function TncTCPBase.GetHost: string;
+begin
+ Result := ''; // Default implementation, override in client
+end;
+
+{$IFDEF MSWINDOWS}
+// TLS Functionality Methods
+procedure TncTCPBase.InitializeTLS(aLine: TncLine);
+var
+ TlsContext: TncTlsConnectionContext;
+begin
+ if not FUseTLS then
+ Exit;
+
+ if aLine = nil then
+ Exit;
+
+ // Get or create per-connection TLS context
+ if TncLineInternal(aLine).DataObject = nil then
+ begin
+ TlsContext := TncTlsConnectionContext.Create(FIsServer);
+ TncLineInternal(aLine).DataObject := TlsContext;
+ end
+ else
+ begin
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+ end;
+
+ // Check if TLS is already initialized for this specific connection
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ Exit;
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ Exit;
+ end;
+
+ // Initialize TLS for this specific connection
+ if FIsServer then
+ begin
+ TlsContext.GetServerContext^.AfterConnection(aLine, AnsiString(FCertificateFile), AnsiString(FPrivateKeyPassword));
+ end
+ else
+ begin
+ TlsContext.GetClientContext^.AfterConnection(aLine, AnsiString(GetHost), FIgnoreCertificateErrors);
+ end;
+end;
+{$ELSE}
+// TLS Functionality Methods - Linux stub
+procedure TncTCPBase.InitializeTLS(aLine: TncLine);
+begin
+ // TLS not supported on Linux yet
+ if FUseTLS then
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr);
+end;
+{$ENDIF}
+
+procedure TncTCPBase.HandleTLSHandshake(aLine: TncLine);
+begin
+ // This method is called automatically before OnConnected fires
+ // It performs the TLS handshake synchronously
+ if FUseTLS and (aLine <> nil) then
+ begin
+ InitializeTLS(aLine); // Perform the complete TLS handshake
+ end;
+end;
+
+procedure TncTCPBase.HandleTLSHandshakeComplete(aLine: TncLine);
+begin
+ // Call OnConnected for TLS connections after handshake completes
+ if FUseTLS and Assigned(OnConnected) then
+ begin
+ try
+ OnConnected(Self, aLine);
+ except
+ on E: Exception do
+ // OnConnected failed - could log this if needed
+ end;
+ end;
+end;
+
+{$IFDEF MSWINDOWS}
+procedure TncTCPBase.FinalizeTLS(aLine: TncLine);
+var
+ TlsContext: TncTlsConnectionContext;
+begin
+ if FUseTLS and (aLine <> nil) and (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ try
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+
+ case FTlsProvider of
+ tpSChannel:
+ begin
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ TlsContext.GetServerContext^.BeforeDisconnection(aLine);
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ TlsContext.GetClientContext^.BeforeDisconnection(aLine);
+ end;
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL cleanup
+ end;
+ end;
+
+ // Clean up the TLS context object
+ TncLineInternal(aLine).DataObject := nil;
+ TlsContext.Free;
+ except
+ on E: Exception do
+ // Log error but don't raise exception during cleanup
+ end;
+ end;
+end;
+{$ELSE}
+procedure TncTCPBase.FinalizeTLS(aLine: TncLine);
+begin
+ // TLS not supported on Linux yet - no cleanup needed
+end;
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+function TncTCPBase.SendTLS(aLine: TncLine; const aBuf; aBufSize: Integer): Integer;
+var
+ TlsContext: TncTlsConnectionContext;
+begin
+ if FUseTLS and (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+
+ case FTlsProvider of
+ tpSChannel:
+ begin
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ Result := TlsContext.GetServerContext^.Send(aLine, @aBuf, aBufSize)
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ Result := TlsContext.GetClientContext^.Send(aLine, @aBuf, aBufSize)
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+ end;
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL send implementation
+ raise EOpenSSLNotAvailable.Create(EOpenSSLNotAvailableStr);
+ end;
+ end;
+ end
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+end;
+{$ELSE}
+function TncTCPBase.SendTLS(aLine: TncLine; const aBuf; aBufSize: Integer): Integer;
+begin
+ if FUseTLS then
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr)
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+end;
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+function TncTCPBase.ReceiveTLS(aLine: TncLine; var aBuf; aBufSize: Integer): Integer;
+var
+ TlsContext: TncTlsConnectionContext;
+ WasHandshakeCompleted: Boolean;
+begin
+ if FUseTLS and (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+
+ case FTlsProvider of
+ tpSChannel:
+ begin
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ begin
+ WasHandshakeCompleted := TlsContext.GetServerContext^.HandshakeCompleted;
+
+ Result := TlsContext.GetServerContext^.Receive(aLine, @aBuf, aBufSize);
+
+ // CRITICAL FIX: Detect TLS disconnection when Receive returns 0 after handshake completion
+ if (Result = 0) and WasHandshakeCompleted then
+ begin
+ raise Exception.Create('TLS client disconnected');
+ end;
+
+ // Check if handshake just completed
+ if not WasHandshakeCompleted and TlsContext.GetServerContext^.HandshakeCompleted then
+ begin
+ // Handshake just completed, call OnConnected
+ HandleTLSHandshakeComplete(aLine);
+
+ // CRITICAL FIX: Return -1 to prevent OnReadData from being triggered with empty data
+ // The handshake completion callback has already been called above
+ Result := -1;
+ end;
+ end
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ begin
+ // For client, handshake is complete when Initialized becomes true
+ // But we need to track when it JUST became initialized (not if it was already initialized)
+ // Since the client calls AfterConnection during OnBeforeConnected, we know that
+ // the first call to Receive after OnBeforeConnected is when handshake is complete
+
+ Result := TlsContext.GetClientContext^.Receive(aLine, @aBuf, aBufSize);
+
+ // CRITICAL FIX: Detect TLS disconnection when Receive returns 0 after handshake completion
+ if (Result = 0) and TlsContext.GetClientContext^.Initialized then
+ begin
+ raise Exception.Create('TLS server disconnected');
+ end;
+
+ // Client-side handshake completion detection:
+ // The client TLS handshake is handled in OnBeforeConnected event
+ // So by the time we get here, handshake is already complete
+ // We don't need to do anything special for client handshake completion
+ end
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+ end;
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL receive implementation
+ raise EOpenSSLNotAvailable.Create(EOpenSSLNotAvailableStr);
+ end;
+ end;
+ end
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+end;
+{$ELSE}
+function TncTCPBase.ReceiveTLS(aLine: TncLine; var aBuf; aBufSize: Integer): Integer;
+begin
+ if FUseTLS then
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr)
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+end;
+{$ENDIF}
+
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{ TncCustomTCPClient }
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -567,6 +1308,7 @@ constructor TncCustomTCPClient.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
+ FIsServer := False; // Set client flag for TLS context selection
FHost := DefHost;
FReconnect := True;
FReconnectInterval := DefCntReconnectInterval;
@@ -575,10 +1317,20 @@ constructor TncCustomTCPClient.Create(AOwner: TComponent);
LastConnectAttempt := TStopWatch.GetTimeStamp;
WasConnected := False;
+ // Create Line with correct family
Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
TncLineInternal(Line).OnConnected := DataSocketConnected;
TncLineInternal(Line).OnDisconnected := DataSocketDisconnected;
+ // Set up TLS handshake callback if TLS is enabled
+ if FUseTLS then
+ TncLineInternal(Line).OnBeforeConnected := HandleTLSHandshake;
+
LineProcessor := TncClientProcessor.Create(Self);
try
if LineProcessor.Priority <> FromNcThreadPriority(DefReaderThreadPriority) then
@@ -589,6 +1341,7 @@ constructor TncCustomTCPClient.Create(AOwner: TComponent);
LineProcessor.WaitForReady;
end;
+
destructor TncCustomTCPClient.Destroy;
begin
Active := False;
@@ -605,12 +1358,20 @@ destructor TncCustomTCPClient.Destroy;
procedure TncCustomTCPClient.DoActivate(aActivate: Boolean);
begin
+
if aActivate = GetActive then
Exit;
if aActivate then
begin
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
TncLineInternal(Line).CreateClientHandle(FHost, FPort);
+
// if there were no exceptions, and line is still not active,
// that means the user has deactivated it in the OnConnect handler
if not Line.Active then
@@ -641,12 +1402,15 @@ procedure TncCustomTCPClient.DataSocketConnected(aLine: TncLine);
end;
try
- TncLineInternal(Line).SetReceiveSize(1048576);
- TncLineInternal(Line).SetWriteSize(1048576);
- TncLineInternal(Line).SetReceiveSize(20 * 1048576);
+ TncLineInternal(Line).SetReceiveSize(1048576); // 1MB
+ TncLineInternal(Line).SetWriteSize(1048576); // 1MB
+ //TncLineInternal(Line).SetReceiveSize(20 * 1048576);
+
except
end;
+ // TLS initialization is now handled by OnBeforeConnected event
+
if Assigned(OnConnected) then
try
OnConnected(Self, aLine);
@@ -662,6 +1426,10 @@ procedure TncCustomTCPClient.DataSocketConnected(aLine: TncLine);
procedure TncCustomTCPClient.DataSocketDisconnected(aLine: TncLine);
begin
+ // Finalize TLS if enabled
+ if UseTLS then
+ FinalizeTLS(aLine);
+
if Assigned(OnDisconnected) then
try
OnDisconnected(Self, aLine);
@@ -669,10 +1437,13 @@ procedure TncCustomTCPClient.DataSocketDisconnected(aLine: TncLine);
end;
end;
+
procedure TncCustomTCPClient.Send(const aBuf; aBufSize: Integer);
begin
- Active := True;
- TncLineInternal(Line).SendBuffer(aBuf, aBufSize);
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ SendTLS(Line, aBuf, aBufSize);
end;
procedure TncCustomTCPClient.Send(const aBytes: TBytes);
@@ -701,13 +1472,13 @@ function TncCustomTCPClient.Receive(aTimeout: Cardinal): TBytes;
Exit;
end;
- BufRead := TncLineInternal(Line).RecvBuffer(ReadBuf[0], Length(ReadBuf));
+ BufRead := ReceiveTLS(Line, ReadBuf[0], Length(ReadBuf));
Result := Copy(ReadBuf, 0, BufRead)
end;
function TncCustomTCPClient.ReceiveRaw(var aBytes: TBytes): Integer;
begin
- Result := TncLineInternal(Line).RecvBuffer(aBytes[0], Length(aBytes));
+ Result := ReceiveTLS(Line, aBytes[0], Length(aBytes));
end;
function TncCustomTCPClient.GetActive: Boolean;
@@ -717,11 +1488,11 @@ function TncCustomTCPClient.GetActive: Boolean;
function TncCustomTCPClient.GetHost: string;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FHost;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
@@ -731,51 +1502,51 @@ procedure TncCustomTCPClient.SetHost(const Value: string);
if Active then
raise EPropertySetError.Create(ECannotSetHostWhileConnectionIsActiveStr);
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FHost := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncCustomTCPClient.GetReconnect: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FReconnect;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncCustomTCPClient.SetReconnect(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FReconnect := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncCustomTCPClient.GetReconnectInterval: Cardinal;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FReconnectInterval;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncCustomTCPClient.SetReconnectInterval(const Value: Cardinal);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FReconnectInterval := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
@@ -794,8 +1565,8 @@ procedure TncClientProcessor.SocketProcess;
var
BufRead: Integer;
begin
- BufRead := TncLineInternal(FClientSocket.Line).RecvBuffer(FClientSocket.ReadBuf[0], Length(FClientSocket.ReadBuf));
- if Assigned(FClientSocket.OnReadData) then
+ BufRead := FClientSocket.ReceiveTLS(FClientSocket.Line, FClientSocket.ReadBuf[0], Length(FClientSocket.ReadBuf));
+ if Assigned(FClientSocket.OnReadData) and (BufRead > 0) then
try
FClientSocket.OnReadData(FClientSocket, FClientSocket.Line, FClientSocket.ReadBuf, BufRead);
except
@@ -849,7 +1620,7 @@ procedure TncClientProcessor.ProcessEvent;
FClientSocket.LastConnectAttempt := TStopWatch.GetTimeStamp;
WasReconnected := False;
- FClientSocket.PropertyLock.Acquire;
+ TMonitor.Enter(FClientSocket.PropertyLock);
try
if not FClientSocket.Active then
begin
@@ -864,7 +1635,7 @@ procedure TncClientProcessor.ProcessEvent;
end;
end;
finally
- FClientSocket.PropertyLock.Release;
+ TMonitor.Exit(FClientSocket.PropertyLock);
end;
if WasReconnected then
if FClientSocket.EventsUseMainThread then
@@ -889,17 +1660,32 @@ constructor TncCustomTCPServer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
+ FIsServer := True; // Set server flag for TLS context selection
+
Listener := CreateLineObject;
+ if Listener.Family <> FFamily then
+ begin
+ TncLineInternal(Listener).SetFamily(FFamily);
+ end;
+
TncLineInternal(Listener).OnConnected := DataSocketConnected;
TncLineInternal(Listener).OnDisconnected := DataSocketDisconnected;
- Lines := TThreadLineList.Create;
+ // Set up TLS handshake callback if TLS is enabled
+ if FUseTLS then
+ begin
+ TncLineInternal(Listener).OnBeforeConnected := HandleTLSHandshake;
+ end;
+ Lines := TThreadLineList.Create();
+
LineProcessor := TncServerProcessor.Create(Self);
try
- LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ if LineProcessor.Priority <> FromNcThreadPriority(DefReaderThreadPriority) then
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
except
// Some Android devices do not like this
end;
+ LineProcessor.WaitForReady;
end;
destructor TncCustomTCPServer.Destroy;
@@ -933,23 +1719,31 @@ procedure TncCustomTCPServer.DoActivate(aActivate: Boolean);
if aActivate then
begin
+ // Verify family setting before creating handle
+ if Assigned(Listener) and (Listener.Family <> FFamily) then
+ begin
+ TncLineInternal(Listener).SetFamily(FFamily);
+ end;
TncLineInternal(Listener).CreateServerHandle(FPort);
end
else
begin
- TncLineInternal(Listener).DestroyHandle;
+ if Assigned(Listener) then
+ TncLineInternal(Listener).DestroyHandle;
- // Delphi complains about the free that it does nothing except nil the variable
- // That is under the mostly forgettable and thankgoodness "gotten rid off"
- // ARC compilers...
+ // Cleanup connected sockets
{$HINTS OFF}
DataSockets := Lines.LockListNoCopy;
try
for i := 0 to DataSockets.Count - 1 do
try
- TncLineInternal(DataSockets.Lines[i]).DestroyHandle;
- TncLineInternal(DataSockets.Lines[i]).Free;
+ if Assigned(DataSockets.Lines[i]) then
+ begin
+ TncLineInternal(DataSockets.Lines[i]).DestroyHandle;
+ DataSockets.Lines[i].Free;
+ end;
except
+ //
end;
DataSockets.Clear;
finally
@@ -964,7 +1758,7 @@ procedure TncCustomTCPServer.ShutDownLine(aLine: TncLine);
begin
if UseReaderThread then
begin
- ShutDownLock.Acquire;
+ TMonitor.Enter(ShutDownLock);
try
for i := 0 to High(LinesToShutDown) do
if LinesToShutDown[i] = aLine then
@@ -973,7 +1767,7 @@ procedure TncCustomTCPServer.ShutDownLine(aLine: TncLine);
SetLength(LinesToShutDown, Length(LinesToShutDown) + 1);
LinesToShutDown[High(LinesToShutDown)] := aLine;
finally
- ShutDownLock.Release;
+ TMonitor.Exit(ShutDownLock);
end;
end
else
@@ -1018,14 +1812,27 @@ procedure TncCustomTCPServer.DataSocketConnected(aLine: TncLine);
except
end;
- if Assigned(OnConnected) then
- try
- OnConnected(Self, aLine);
- except
- end;
+ // TLS initialization is now handled by OnBeforeConnected event
+
+ // For TLS connections, delay OnConnected until after handshake completes
+ if not UseTLS then
+ begin
+ if Assigned(OnConnected) then
+ try
+ OnConnected(Self, aLine);
+ except
+ end;
+ end
+ else
+ begin
+ // For TLS connections, OnConnected will be called after handshake completes
+ // This is handled in the first successful TLS receive operation
+ end;
end;
end;
+// Update : Moves the handle removal before the disconnect event handling
+// This prevents other threads from trying to use the handle while the disconnect event is processing.
procedure TncCustomTCPServer.DataSocketDisconnected(aLine: TncLine);
var
i: Integer;
@@ -1034,25 +1841,36 @@ procedure TncCustomTCPServer.DataSocketDisconnected(aLine: TncLine);
SetLength(ReadSocketHandles, 0)
else
begin
+ // Finalize TLS if enabled
+ if UseTLS then
+ FinalizeTLS(aLine);
+
+ // First remove the handle to prevent further processing
+ TMonitor.Enter(PropertyLock);
+ try
+ for i := 0 to High(ReadSocketHandles) do
+ if ReadSocketHandles[i] = aLine.Handle then
+ begin
+ ReadSocketHandles[i] := ReadSocketHandles[High(ReadSocketHandles)];
+ SetLength(ReadSocketHandles, Length(ReadSocketHandles) - 1);
+ Break;
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+
+ // Then handle disconnect event
if Assigned(OnDisconnected) then
try
OnDisconnected(Self, aLine);
except
end;
-
- for i := 0 to High(ReadSocketHandles) do
- if ReadSocketHandles[i] = aLine.Handle then
- begin
- ReadSocketHandles[i] := ReadSocketHandles[High(ReadSocketHandles)];
- SetLength(ReadSocketHandles, Length(ReadSocketHandles) - 1);
- Break;
- end;
end;
end;
procedure TncCustomTCPServer.Send(aLine: TncLine; const aBuf; aBufSize: Integer);
begin
- TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+ SendTLS(aLine, aBuf, aBufSize);
end;
procedure TncCustomTCPServer.Send(aLine: TncLine; const aBytes: TBytes);
@@ -1100,7 +1918,7 @@ function TncCustomTCPServer.Receive(aLine: TncLine; aTimeout: Cardinal): TBytes;
try
if not Line.Active then
Abort;
- BufRead := TncLineInternal(Line).RecvBuffer(ReadBuf[0], Length(ReadBuf));
+ BufRead := ReceiveTLS(Line, ReadBuf[0], Length(ReadBuf));
Result := Copy(ReadBuf, 0, BufRead);
except
// Line has disconnected, destroy the line
@@ -1117,7 +1935,7 @@ function TncCustomTCPServer.Receive(aLine: TncLine; aTimeout: Cardinal): TBytes;
function TncCustomTCPServer.ReceiveRaw(aLine: TncLine; var aBytes: TBytes): Integer;
begin
- Result := TncLineInternal(aLine).RecvBuffer(aBytes[0], Length(aBytes));
+ Result := ReceiveTLS(aLine, aBytes[0], Length(aBytes));
end;
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1137,9 +1955,9 @@ procedure TncServerProcessor.CheckLinesToShutDown;
begin
// The list may be locked from custom code executed in the OnReadData handler
// So we will not delete anything, or lock the list, until this lock is freed
- if FServerSocket.Lines.FLock.TryEnter then
+ if TMonitor.TryEnter(FServerSocket.Lines) then
try
- FServerSocket.ShutDownLock.Acquire;
+ TMonitor.Enter(FServerSocket.ShutDownLock);
try
for i := 0 to High(FServerSocket.LinesToShutDown) do
try
@@ -1150,10 +1968,10 @@ procedure TncServerProcessor.CheckLinesToShutDown;
end;
SetLength(FServerSocket.LinesToShutDown, 0);
finally
- FServerSocket.ShutDownLock.Release;
+ TMonitor.Exit(FServerSocket.ShutDownLock);
end;
finally
- FServerSocket.Lines.FLock.Leave;
+ TMonitor.Exit(FServerSocket.Lines);
end;
end;
@@ -1221,8 +2039,8 @@ procedure TncServerProcessor.SocketProcess;
ReadySocketsChanged := False;
Exit;
end;
- BufRead := TncLineInternal(Line).RecvBuffer(FServerSocket.ReadBuf[0], Length(FServerSocket.ReadBuf));
- if Assigned(FServerSocket.OnReadData) then
+ BufRead := FServerSocket.ReceiveTLS(Line, FServerSocket.ReadBuf[0], Length(FServerSocket.ReadBuf));
+ if Assigned(FServerSocket.OnReadData) and (BufRead > 0) then
FServerSocket.OnReadData(FServerSocket, Line, FServerSocket.ReadBuf, BufRead);
except
// Line has disconnected, destroy the line
diff --git a/Source/ncSocketsDual.pas b/Source/ncSocketsDual.pas
new file mode 100644
index 0000000..d5bdae5
--- /dev/null
+++ b/Source/ncSocketsDual.pas
@@ -0,0 +1,2983 @@
+unit ncSocketsDual;
+
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 ncSocketsDual - Enhanced TCP Components with Dual Protocol Support
+//
+// This unit extends ncSockets with dual protocol capabilities, allowing both
+// raw data (text/binary) and structured command protocols to coexist on the
+// same connection.
+//
+// Key Features:
+// - Automatic protocol detection via magic header ($ACF0FF00)
+// - OnReadData: Handles raw data and custom protocols (like ncSockets)
+// - OnCommand: Handles structured binary commands with guaranteed delivery
+// - Full backward compatibility with ncSockets
+// - Advanced TCP fragmentation handling with state machine
+// - TLS support, IPv6, and all ncSockets features preserved
+// - CRITICAL FIX: Per-connection TLS context storage for multiple concurrent TLS connections
+//
+// Usage:
+// - Drop-in replacement for ncSockets (TncTCPClient -> TncTCPClientDual)
+// - Custom protocols work exactly like ncSockets via OnReadData
+// - Enhanced features available via SendCommand/OnCommand for guaranteed delivery
+//
+// 11/08/2025 - by J.Pauwels
+// - Added original compression and encryption from ncSources
+//
+// 29/07/2025 - by J.Pauwels
+// - CRITICAL FIX: Fixed TLS disconnection crash by changing from event-driven to direct TLS cleanup
+// - Removed OnBeforeDisconnected := FinalizeTLS assignments from constructors and SetUseTLS
+// - Added direct FinalizeTLS(aLine) calls in DataSocketDisconnected methods for better timing
+// - This aligns ncSocketsDual TLS cleanup pattern with the proven ncSockets approach
+//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 15/07/2025 - by J.Pauwels
+// - CRITICAL FIX: Implemented per-connection TLS context storage to support multiple concurrent TLS connections
+// - Fixed TLS multiple client connection issue using TncTlsConnectionContext class
+//
+// 15/07/2025 - by J.Pauwels
+// - Added OnCommand event for guaranteed delivery of commands
+// - Added SendCommand method for sending commands
+// - Added TncCommand type for command handling
+// - Added TncCommandPacking unit for command packing/unpacking
+//
+// 15/07/2025 - by J.Pauwels
+// - Initial creation
+//
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+// To disable as much of RTTI as possible (Delphi 2009/2010),
+// Note: There is a bug if $RTTI is used before the "unit ;" section of a unit, hence the position
+
+{$IF CompilerVersion >= 21.0}
+{$WEAKLINKRTTI ON }
+{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
+{$ENDIF}
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ System.Diagnostics,
+ System.Math,
+ System.TimeSpan,
+ System.SyncObjs,
+ System.ZLib, // For compression support
+ Generics.Collections,
+ {$IFDEF MSWINDOWS}
+ Winapi.Windows,
+ Winapi.Winsock2,
+ ncSChannel,
+ {$ELSE}
+ Posix.SysSocket,
+ Posix.Unistd,
+ {$ENDIF}
+ ncSocketList,
+ ncLines,
+ ncThreads,
+ ncCommandPacking, // For TncCommand type
+ ncCompression, // For compression utilities
+ ncEncryption; // For encryption utilities
+
+type
+ // TLS Provider enumeration (declared early for use in constants)
+ TncTlsProvider = (
+ tpSChannel, // Windows SChannel (Windows only, no external dependencies)
+ tpOpenSSL // OpenSSL (cross-platform, requires OpenSSL DLLs)
+ );
+
+{$IFDEF MSWINDOWS}
+ // Forward declarations for SChannel types
+ PSChannelClient = ^TSChannelClient;
+ PSChannelServer = ^TSChannelServer;
+
+ // Per-connection TLS context storage
+ TncTlsConnectionContext = class
+ private
+ FIsServer: Boolean;
+ FClientContext: TSChannelClient;
+ FServerContext: TSChannelServer;
+ FLock: TObject; // CRITICAL FIX: Thread-safe lock for concurrent Send/Receive
+ public
+ constructor Create(aIsServer: Boolean);
+ destructor Destroy; override;
+ procedure Lock; // Lock before TLS operations
+ procedure Unlock; // Unlock after TLS operations
+ function GetClientContext: PSChannelClient;
+ function GetServerContext: PSChannelServer;
+ property IsServer: Boolean read FIsServer;
+ end;
+{$ENDIF}
+
+ // Protocol magic header type (same as ncSources)
+ TMagicHeaderType = UInt32;
+ PMagicHeaderType = ^TMagicHeaderType;
+
+const
+ DefPort = 16233;
+ DefHost = '';
+ DefReadBufferLen = 1024 * 1024; // 1 MB
+ DefReaderThreadPriority = ntpNormal;
+ DefCntReconnectInterval = 1000;
+ DefEventsUseMainThread = False;
+ DefUseReaderThread = True;
+ DefNoDelay = False;
+ DefKeepAlive = True;
+ DefFamily = afIPv4;
+ DefUseTLS = False;
+ DefTlsProvider = tpSChannel;
+ DefIgnoreCertificateErrors = False;
+
+ // Compression and Encryption defaults (same as ncSources)
+ DefCompression = zcNone;
+ DefEncryption = etNoEncryption;
+ DefEncryptionKey = 'SetEncryptionKey';
+ DefEncryptOnHashedKey = True;
+
+ // Thread Pool Constants (from ncSources)
+ DefCommandProcessorThreadPriority = ntpNormal;
+ DefCommandProcessorThreads = 0;
+ DefCommandProcessorThreadsPerCPU = 4;
+ DefCommandProcessorThreadsGrowUpto = 32;
+
+ // Protocol magic header (same as ncSources)
+ MagicHeader: TMagicHeaderType = $ACF0FF00;
+
+resourcestring
+ ECannotSetPortWhileConnectionIsActiveStr = 'Cannot set Port property whilst the connection is active';
+ ECannotSetHostWhileConnectionIsActiveStr = 'Cannot set Host property whilst the connection is active';
+ ECannotSendWhileSocketInactiveStr = 'Cannot send data while socket is inactive';
+ ECannotSetUseReaderThreadWhileActiveStr = 'Cannot set UseReaderThread property whilst the connection is active';
+ ECannotReceiveIfUseReaderThreadStr =
+ 'Cannot receive data if UseReaderThread is set. Use OnReadData event handler to get the data or set UseReaderThread property to false';
+ ECannotSetFamilyWhileConnectionIsActiveStr = 'Cannot set Family property whilst the connection is active';
+ ETlsProviderNotSupportedStr = 'TLS provider not supported on this platform';
+ EOpenSSLNotAvailableStr = 'OpenSSL libraries not available';
+
+type
+ EPropertySetError = class(Exception);
+ ENonActiveSocket = class(Exception);
+ ECannotReceiveIfUseReaderThread = class(Exception);
+ ETlsProviderNotSupported = class(Exception);
+ EOpenSSLNotAvailable = class(Exception);
+
+ // We bring in TncLine so that a form that uses our components does
+ // not have to reference ncLines unit to get the type
+ TncLine = ncLines.TncLine;
+
+ // We make a descendant of TncLine so that we can access the API functions.
+ // These API functions are not made puclic in TncLine so that the user cannot
+ // mangle up the line
+ TncLineInternal = class(TncLine);
+
+ // Forward declarations
+ TncCustomTCPServerDual = class;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // TThreadLineList
+ // Thread safe object, used by the main components
+
+ TThreadLineList = class
+ private
+ FList: TSocketList;
+ FListCopy: TSocketList;
+ // FLock converted to TMonitor.Enter(Self)
+ FLockCount: Integer;
+ protected
+ procedure Add(const Item: TncLine); inline;
+ procedure Clear; inline;
+ procedure Remove(Item: TncLine); inline;
+ function LockListNoCopy: TSocketList;
+ procedure UnlockListNoCopy;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function LockList: TSocketList;
+ procedure UnlockList;
+ end;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Base object for all TCP Sockets
+ TncOnConnectDisconnect = procedure(Sender: TObject; aLine: TncLine) of object;
+ TncOnReadData = procedure(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer) of object;
+ TncOnReconnected = procedure(Sender: TObject; aLine: TncLine) of object;
+ TncOnCommandReceived = procedure(Sender: TObject; aLine: TncLine;
+ aCmd: Integer; const aData: TBytes) of object; // Binary protocol event
+
+ // Command Processing Thread for Thread Pool (from ncSources)
+ THandleCommandWorkType = (htwtOnCommand);
+
+ THandleCommandThread = class(TncReadyThread)
+ private
+ FWorkType: THandleCommandWorkType;
+ FSource: TComponent;
+ FLine: TncLine;
+ FCmd: Integer;
+ FData: TBytes;
+ FOnCommand: TncOnCommandReceived;
+ FEventsUseMainThread: Boolean;
+
+ procedure CallOnCommandEvent;
+ protected
+ procedure ProcessEvent; override;
+ public
+ property WorkType: THandleCommandWorkType read FWorkType write FWorkType;
+ property Source: TComponent read FSource write FSource;
+ property Line: TncLine read FLine write FLine;
+ property Cmd: Integer read FCmd write FCmd;
+ property Data: TBytes read FData write FData;
+ property OnCommand: TncOnCommandReceived read FOnCommand write FOnCommand;
+ property EventsUseMainThread: Boolean read FEventsUseMainThread write FEventsUseMainThread;
+ end;
+
+ TncTCPBaseDual = class(TComponent)
+ private
+ FInitActive: Boolean;
+ FFamily: TAddressType;
+ FPort: Integer;
+ FEventsUseMainThread: Boolean;
+ FNoDelay: Boolean;
+ FKeepAlive: Boolean;
+ FReadBufferLen: Integer;
+ FOnConnected: TncOnConnectDisconnect;
+ FOnDisconnected: TncOnConnectDisconnect;
+ FOnReadData: TncOnReadData;
+ FLine: TncLine;
+
+ // Thread Pool Properties (from ncSources)
+ FCommandProcessorThreadPriority: TncThreadPriority;
+ FCommandProcessorThreads: Integer;
+ FCommandProcessorThreadsPerCPU: Integer;
+ FCommandProcessorThreadsGrowUpto: Integer;
+
+ // TLS Properties
+ FUseTLS: Boolean;
+ FTlsProvider: TncTlsProvider;
+ FCertificateFile: string;
+ FPrivateKeyFile: string;
+ FPrivateKeyPassword: string;
+ FCACertificatesFile: string;
+ FIgnoreCertificateErrors: Boolean;
+ FIsServer: Boolean;
+
+ // Compression and Encryption Properties (same as ncSources)
+ FCompression: TZCompressionLevel;
+ FEncryption: TEncryptorType;
+ FEncryptionKey: AnsiString;
+ FEncryptOnHashedKey: Boolean;
+
+ function GetReadBufferLen: Integer;
+ procedure SetReadBufferLen(const Value: Integer);
+ function GetActive: Boolean; virtual; abstract;
+ procedure SetActive(const Value: Boolean);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+
+ function GetPort: Integer;
+ procedure SetPort(const Value: Integer);
+ function GetReaderThreadPriority: TncThreadPriority;
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority);
+ function GetEventsUseMainThread: Boolean;
+ procedure SetEventsUseMainThread(const Value: Boolean);
+ function GetNoDelay: Boolean;
+ procedure SetNoDelay(const Value: Boolean);
+ function GetKeepAlive: Boolean;
+ procedure SetKeepAlive(const Value: Boolean);
+
+ // TLS Property Methods
+ function GetUseTLS: Boolean;
+ procedure SetUseTLS(const Value: Boolean);
+ function GetTlsProvider: TncTlsProvider;
+ procedure SetTlsProvider(const Value: TncTlsProvider);
+ function GetCertificateFile: string;
+ procedure SetCertificateFile(const Value: string);
+ function GetPrivateKeyFile: string;
+ procedure SetPrivateKeyFile(const Value: string);
+ function GetPrivateKeyPassword: string;
+ procedure SetPrivateKeyPassword(const Value: string);
+ function GetCACertificatesFile: string;
+ procedure SetCACertificatesFile(const Value: string);
+ function GetIgnoreCertificateErrors: Boolean;
+ procedure SetIgnoreCertificateErrors(const Value: Boolean);
+
+ // Compression and Encryption Property Methods (same as ncSources)
+ function GetCompression: TZCompressionLevel;
+ procedure SetCompression(const Value: TZCompressionLevel);
+ function GetEncryption: TEncryptorType;
+ procedure SetEncryption(const Value: TEncryptorType);
+ function GetEncryptionKey: AnsiString;
+ procedure SetEncryptionKey(const Value: AnsiString);
+ function GetEncryptOnHashedKey: Boolean;
+ procedure SetEncryptOnHashedKey(const Value: Boolean);
+
+ // Thread Pool Property Methods (from ncSources)
+ function GetCommandProcessorThreadPriority: TncThreadPriority;
+ procedure SetCommandProcessorThreadPriority(const Value: TncThreadPriority);
+ function GetCommandProcessorThreads: Integer;
+ procedure SetCommandProcessorThreads(const Value: Integer);
+ function GetCommandProcessorThreadsPerCPU: Integer;
+ procedure SetCommandProcessorThreadsPerCPU(const Value: Integer);
+ function GetCommandProcessorThreadsGrowUpto: Integer;
+ procedure SetCommandProcessorThreadsGrowUpto(const Value: Integer);
+
+ private
+ FUseReaderThread: Boolean;
+ procedure DoActivate(aActivate: Boolean); virtual; abstract;
+ procedure SetUseReaderThread(const Value: Boolean);
+ protected
+ PropertyLock, ShutDownLock: TObject; // TMonitor synchronization objects
+ ReadBuf: TBytes;
+
+ // Thread Pool Infrastructure (from ncSources)
+ HandleCommandThreadPool: TncThreadPool;
+
+ procedure Loaded; override;
+ function CreateLineObject: TncLine; virtual;
+ function GetHost: string; virtual; // Virtual method for TLS
+ procedure InitializeTLS(aLine: TncLine); virtual;
+ procedure FinalizeTLS(aLine: TncLine); virtual;
+ function SendTLS(aLine: TncLine; const aBuf; aBufSize: Integer): Integer; virtual;
+ function ReceiveTLS(aLine: TncLine; var aBuf; aBufSize: Integer): Integer; virtual;
+ procedure HandleTLSHandshake(aLine: TncLine); virtual;
+ procedure HandleTLSHandshakeComplete(aLine: TncLine); virtual;
+ property Line: TncLine read FLine;
+ public
+ LineProcessor: TncReadyThread;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ function Kind: TSocketType; virtual;
+
+ property Active: Boolean read GetActive write SetActive default False;
+ property Family: TAddressType read GetFamily write SetFamily default afIPv4;
+ property Port: Integer read GetPort write SetPort default DefPort;
+ property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
+ property EventsUseMainThread: Boolean read GetEventsUseMainThread write SetEventsUseMainThread default DefEventsUseMainThread;
+ property UseReaderThread: Boolean read FUseReaderThread write SetUseReaderThread default DefUseReaderThread;
+ property NoDelay: Boolean read GetNoDelay write SetNoDelay default DefNoDelay;
+ property KeepAlive: Boolean read GetKeepAlive write SetKeepAlive default DefKeepAlive;
+ property OnConnected: TncOnConnectDisconnect read FOnConnected write FOnConnected;
+ property OnDisconnected: TncOnConnectDisconnect read FOnDisconnected write FOnDisconnected;
+ property OnReadData: TncOnReadData read FOnReadData write FOnReadData;
+ property ReadBufferLen: Integer read GetReadBufferLen write SetReadBufferLen default DefReadBufferLen;
+
+ // Thread Pool Properties (from ncSources)
+ property CommandProcessorThreadPriority: TncThreadPriority read GetCommandProcessorThreadPriority write SetCommandProcessorThreadPriority default DefCommandProcessorThreadPriority;
+ property CommandProcessorThreads: Integer read GetCommandProcessorThreads write SetCommandProcessorThreads default DefCommandProcessorThreads;
+ property CommandProcessorThreadsPerCPU: Integer read GetCommandProcessorThreadsPerCPU write SetCommandProcessorThreadsPerCPU default DefCommandProcessorThreadsPerCPU;
+ property CommandProcessorThreadsGrowUpto: Integer read GetCommandProcessorThreadsGrowUpto write SetCommandProcessorThreadsGrowUpto default DefCommandProcessorThreadsGrowUpto;
+
+ // TLS Properties
+ property UseTLS: Boolean read GetUseTLS write SetUseTLS default DefUseTLS;
+ property TlsProvider: TncTlsProvider read GetTlsProvider write SetTlsProvider default DefTlsProvider;
+ property CertificateFile: string read GetCertificateFile write SetCertificateFile;
+ property PrivateKeyFile: string read GetPrivateKeyFile write SetPrivateKeyFile;
+ property PrivateKeyPassword: string read GetPrivateKeyPassword write SetPrivateKeyPassword;
+ property CACertificatesFile: string read GetCACertificatesFile write SetCACertificatesFile;
+ property IgnoreCertificateErrors: Boolean read GetIgnoreCertificateErrors write SetIgnoreCertificateErrors default DefIgnoreCertificateErrors;
+
+ // Compression and Encryption Properties (same as ncSources)
+ property Compression: TZCompressionLevel read GetCompression write SetCompression default DefCompression;
+ property Encryption: TEncryptorType read GetEncryption write SetEncryption default DefEncryption;
+ property EncryptionKey: AnsiString read GetEncryptionKey write SetEncryptionKey;
+ property EncryptOnHashedKey: Boolean read GetEncryptOnHashedKey write SetEncryptOnHashedKey default DefEncryptOnHashedKey;
+ published
+ end;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Client Socket
+ TncClientProcessor = class;
+
+ // Connection state for efficient message handling (ncSources-style)
+ TConnectionState = record
+ MessageBuffer: TBytes; // Accumulated message data
+ BytesToEndOfMessage: UInt64; // How many bytes still needed
+ MessageType: (mtUnknown, mtBinary, mtText); // Protocol type
+ ExpectedMessageLength: UInt64; // Total expected message length
+ HeaderComplete: Boolean; // Have we read the complete header?
+ procedure Reset;
+ end;
+
+ TncCustomTCPClientDual = class(TncTCPBaseDual)
+ private
+ FHost: string;
+ FReconnect: Boolean;
+ FReconnectInterval: Cardinal;
+ FOnReconnected: TncOnReconnected;
+ FOnCommand: TncOnCommandReceived; // Binary protocol event
+ OriginalOnReadData: TncOnReadData; // Store original handler for protocol detection
+ FConnectionState: TConnectionState; // State-based message handling
+ function GetActive: Boolean; override;
+ // Override OnReadData property to preserve protocol detection
+ procedure SetOnReadData(const Value: TncOnReadData);
+ procedure SetHost(const Value: string);
+ function GetHost: string;
+ function GetReconnect: Boolean;
+ procedure SetReconnect(const Value: Boolean);
+ function GetReconnectInterval: Cardinal;
+ procedure SetReconnectInterval(const Value: Cardinal);
+ protected
+ WasConnected: Boolean;
+ LastConnectAttempt: Int64;
+ procedure DoActivate(aActivate: Boolean); override;
+ procedure DataSocketConnected(aLine: TncLine);
+ procedure DataSocketDisconnected(aLine: TncLine);
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure Send(const aBuf; aBufSize: Integer); overload; inline;
+ procedure Send(const aBytes: TBytes); overload; inline;
+ procedure Send(const aStr: string); overload; inline;
+ procedure SendCommand(aCmd: Integer; const aData: TBytes = nil); // Binary protocol method
+ function Receive(aTimeout: Cardinal = 2000): TBytes; inline;
+ function ReceiveRaw(var aBytes: TBytes): Integer; inline;
+ procedure InternalReadDataHandler(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer); // Protocol detection handler
+ property Host: string read GetHost write SetHost;
+ property Reconnect: Boolean read GetReconnect write SetReconnect default True;
+ property ReconnectInterval: Cardinal read GetReconnectInterval write SetReconnectInterval default DefCntReconnectInterval;
+ property OnReconnected: TncOnReconnected read FOnReconnected write FOnReconnected;
+ property OnCommand: TncOnCommandReceived read FOnCommand write FOnCommand;
+ // Override OnReadData to preserve protocol detection
+ property OnReadData: TncOnReadData read FOnReadData write SetOnReadData;
+ end;
+
+ TncTCPClientDual = class(TncCustomTCPClientDual)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property Host;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property NoDelay;
+ property KeepAlive;
+ property ReadBufferLen;
+ property Reconnect;
+ property ReconnectInterval;
+ property OnConnected;
+ property OnDisconnected;
+ property OnReadData;
+ property OnReconnected;
+ property OnCommand;
+
+ // Thread Pool Properties (from ncSources)
+ property CommandProcessorThreadPriority;
+ property CommandProcessorThreads;
+ property CommandProcessorThreadsPerCPU;
+ property CommandProcessorThreadsGrowUpto;
+
+ // TLS Properties
+ property UseTLS;
+ property TlsProvider;
+ property CertificateFile;
+ property PrivateKeyFile;
+ property PrivateKeyPassword;
+ property CACertificatesFile;
+ property IgnoreCertificateErrors;
+
+ // Compression and Encryption Properties
+ property Compression;
+ property Encryption;
+ property EncryptionKey;
+ property EncryptOnHashedKey;
+ end;
+
+ TncClientProcessor = class(TncReadyThread)
+ private
+ FClientSocket: TncCustomTCPClientDual;
+ public
+ ReadySocketsChanged: Boolean;
+ constructor Create(aClientSocket: TncCustomTCPClientDual);
+ procedure SocketWasReconnected;
+ procedure SocketProcess; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Server Socket
+ TncServerProcessor = class;
+
+ TncCustomTCPServerDual = class(TncTCPBaseDual)
+ private
+ FOnCommand: TncOnCommandReceived; // Binary protocol event
+ OriginalOnReadData: TncOnReadData; // Store original handler for protocol detection
+ FConnectionStates: TDictionary; // Per-connection state tracking
+ function GetActive: Boolean; override;
+ // Override OnReadData property to preserve protocol detection
+ procedure SetOnReadData(const Value: TncOnReadData);
+ protected
+ Listener: TncLine;
+ LinesToShutDown: array of TncLine;
+ procedure DataSocketConnected(aLine: TncLine);
+ procedure DataSocketDisconnected(aLine: TncLine);
+ procedure DoActivate(aActivate: Boolean); override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Lines: TThreadLineList;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure ShutDownLine(aLine: TncLine);
+ procedure Send(aLine: TncLine; const aBuf; aBufSize: Integer); overload; inline;
+ procedure Send(aLine: TncLine; const aBytes: TBytes); overload; inline;
+ procedure Send(aLine: TncLine; const aStr: string); overload; inline;
+ function Receive(aLine: TncLine; aTimeout: Cardinal = 2000): TBytes; inline;
+ function ReceiveRaw(aLine: TncLine; var aBytes: TBytes): Integer; inline;
+ procedure SendCommand(aLine: TncLine; aCmd: Integer; const aData: TBytes = nil); // Binary protocol method
+ procedure InternalReadDataHandler(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer); // Protocol detection handler
+ property OnCommand: TncOnCommandReceived read FOnCommand write FOnCommand;
+ // Override OnReadData to preserve protocol detection
+ property OnReadData: TncOnReadData read FOnReadData write SetOnReadData;
+ end;
+
+ TncTCPServerDual = class(TncCustomTCPServerDual)
+ public
+ published
+ property Active;
+ property Family;
+ property Port;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property NoDelay;
+ property KeepAlive;
+ property ReadBufferLen;
+ property OnConnected;
+ property OnDisconnected;
+ property OnReadData;
+ property OnCommand;
+
+ // Thread Pool Properties (from ncSources)
+ property CommandProcessorThreadPriority;
+ property CommandProcessorThreads;
+ property CommandProcessorThreadsPerCPU;
+ property CommandProcessorThreadsGrowUpto;
+
+ // TLS Properties
+ property UseTLS;
+ property TlsProvider;
+ property CertificateFile;
+ property PrivateKeyFile;
+ property PrivateKeyPassword;
+ property CACertificatesFile;
+ property IgnoreCertificateErrors;
+
+ // Compression and Encryption Properties
+ property Compression;
+ property Encryption;
+ property EncryptionKey;
+ property EncryptOnHashedKey;
+ end;
+
+ TncServerProcessor = class(TncReadyThread)
+ private
+ FServerSocket: TncCustomTCPServerDual;
+ procedure CheckLinesToShutDown;
+ public
+ ReadySockets: TSocketHandleArray;
+ ReadySocketsChanged: Boolean;
+ constructor Create(aServerSocket: TncCustomTCPServerDual);
+ procedure SocketProcess; inline;
+ procedure ProcessEvent; override;
+ end;
+
+implementation
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TConnectionState }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+procedure TConnectionState.Reset;
+begin
+ SetLength(MessageBuffer, 0);
+ BytesToEndOfMessage := 0;
+ MessageType := mtUnknown;
+ ExpectedMessageLength := 0;
+ HeaderComplete := False;
+end;
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TThreadLineList }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TThreadLineList.Create;
+begin
+ inherited Create;
+ FList := TSocketList.Create;
+ FLockCount := 0;
+end;
+
+destructor TThreadLineList.Destroy;
+begin
+ LockListNoCopy;
+ try
+ FList.Free;
+ inherited Destroy;
+ finally
+ UnlockListNoCopy;
+ end;
+end;
+
+procedure TThreadLineList.Add(const Item: TncLine);
+begin
+ LockListNoCopy;
+ try
+ // FList has Duplicates to dupError, so we know if this is already in the
+ // list it will not be accepted
+ FList.Add(Item.Handle, Item);
+ finally
+ UnlockListNoCopy;
+ end;
+end;
+
+procedure TThreadLineList.Clear;
+begin
+ LockListNoCopy;
+ try
+ FList.Clear;
+ finally
+ UnlockListNoCopy;
+ end;
+end;
+
+procedure TThreadLineList.Remove(Item: TncLine);
+begin
+ LockListNoCopy;
+ try
+ FList.Delete(FList.IndexOf(Item.Handle));
+ finally
+ UnlockListNoCopy;
+ end;
+end;
+
+function TThreadLineList.LockListNoCopy: TSocketList;
+begin
+ TMonitor.Enter(Self);
+ Result := FList;
+end;
+
+procedure TThreadLineList.UnlockListNoCopy;
+begin
+ TMonitor.Exit(Self);
+end;
+
+function TThreadLineList.LockList: TSocketList;
+begin
+ TMonitor.Enter(Self);
+ try
+ if FLockCount = 0 then
+ begin
+ FListCopy := TSocketList.Create;
+ FListCopy.Assign(FList);
+ end;
+ Result := FListCopy;
+
+ FLockCount := FLockCount + 1;
+ finally
+ TMonitor.Exit(Self);
+ end;
+end;
+
+procedure TThreadLineList.UnlockList;
+begin
+ TMonitor.Enter(Self);
+ try
+ if FLockCount = 0 then
+ raise Exception.Create('Cannot unlock a non-locked list');
+
+ FLockCount := FLockCount - 1;
+
+ if FLockCount = 0 then
+ FListCopy.Free;
+ finally
+ TMonitor.Exit(Self);
+ end;
+end;
+
+{$IFDEF MSWINDOWS}
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncTlsConnectionContext }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncTlsConnectionContext.Create(aIsServer: Boolean);
+begin
+ inherited Create;
+ FIsServer := aIsServer;
+
+ // CRITICAL FIX: Create lock for thread-safe TLS operations
+ // SChannel is NOT thread-safe for concurrent encrypt/decrypt on the same context
+ FLock := TObject.Create;
+
+ // Initialize TLS contexts using FillChar and then set public fields
+ FillChar(FClientContext, SizeOf(FClientContext), 0);
+ FClientContext.Initialized := False;
+
+ FillChar(FServerContext, SizeOf(FServerContext), 0);
+ FServerContext.Initialized := False;
+ FServerContext.HandshakeCompleted := False;
+end;
+
+destructor TncTlsConnectionContext.Destroy;
+begin
+ // In a perfect world, FinalizeTLS was already called
+ // and all cleanup is done - destructor should be nearly empty
+
+ {$IFDEF DEBUG}
+ // Debug check - verify cleanup already happened
+ if FIsServer then
+ Assert(not FServerContext.Initialized, 'Server TLS context not cleaned up!')
+ else
+ Assert(not FClientContext.Initialized, 'Client TLS context not cleaned up!');
+ {$ENDIF}
+
+ // Free the lock object
+ FLock.Free;
+
+ inherited Destroy;
+end;
+
+procedure TncTlsConnectionContext.Lock;
+begin
+ TMonitor.Enter(FLock);
+end;
+
+procedure TncTlsConnectionContext.Unlock;
+begin
+ TMonitor.Exit(FLock);
+end;
+
+function TncTlsConnectionContext.GetClientContext: PSChannelClient;
+begin
+ Result := @FClientContext;
+end;
+
+function TncTlsConnectionContext.GetServerContext: PSChannelServer;
+begin
+ Result := @FServerContext;
+end;
+{$ENDIF}
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncTCPBaseDual }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncTCPBaseDual.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ PropertyLock := TObject.Create;
+ ShutDownLock := TObject.Create;
+
+ FInitActive := False;
+ FFamily := DefFamily;
+ FPort := DefPort;
+ FEventsUseMainThread := DefEventsUseMainThread;
+ FUseReaderThread := DefUseReaderThread;
+ FNoDelay := DefNoDelay;
+ FKeepAlive := DefKeepAlive;
+ FReadBufferLen := DefReadBufferLen;
+ FOnConnected := nil;
+ FOnDisconnected := nil;
+ FOnReadData := nil;
+
+ // Initialize Thread Pool Properties (from ncSources)
+ FCommandProcessorThreadPriority := DefCommandProcessorThreadPriority;
+ FCommandProcessorThreads := DefCommandProcessorThreads;
+ FCommandProcessorThreadsPerCPU := DefCommandProcessorThreadsPerCPU;
+ FCommandProcessorThreadsGrowUpto := DefCommandProcessorThreadsGrowUpto;
+
+ // Initialize TLS properties
+ FUseTLS := DefUseTLS;
+ FTlsProvider := DefTlsProvider;
+ FCertificateFile := '';
+ FPrivateKeyFile := '';
+ FPrivateKeyPassword := '';
+ FCACertificatesFile := '';
+ FIgnoreCertificateErrors := DefIgnoreCertificateErrors;
+
+ // Initialize Compression and Encryption properties (same as ncSources)
+ FCompression := DefCompression;
+ FEncryption := DefEncryption;
+ FEncryptionKey := DefEncryptionKey;
+ FEncryptOnHashedKey := DefEncryptOnHashedKey;
+
+ FIsServer := False;
+
+ SetLength(ReadBuf, DefReadBufferLen);
+
+ // Create Thread Pool for Command Processing (from ncSources)
+ HandleCommandThreadPool := TncThreadPool.Create(THandleCommandThread);
+
+end;
+
+function TncTCPBaseDual.Kind: TSocketType;
+begin
+ Result := stTCP;
+end;
+
+destructor TncTCPBaseDual.Destroy;
+begin
+ Active := False;
+ // Clean up Thread Pool (from ncSources)
+ HandleCommandThreadPool.Free;
+
+ PropertyLock.Free;
+ ShutDownLock.Free;
+ inherited Destroy;
+end;
+
+procedure TncTCPBaseDual.Loaded;
+begin
+ inherited Loaded;
+
+ // Configure Thread Pool (from ncSources)
+ HandleCommandThreadPool.SetThreadPriority(FCommandProcessorThreadPriority);
+ HandleCommandThreadPool.SetExecThreads(
+ Max(1, Max(FCommandProcessorThreads, GetNumberOfProcessors * FCommandProcessorThreadsPerCPU)),
+ FCommandProcessorThreadPriority);
+ HandleCommandThreadPool.GrowUpto := FCommandProcessorThreadsGrowUpto;
+
+ if FInitActive then
+ DoActivate(True);
+end;
+
+function TncTCPBaseDual.CreateLineObject: TncLine;
+begin
+ Result := TncLineInternal.Create;
+ TncLineInternal(Result).SetKind(Kind);
+ TncLineInternal(Result).SetFamily(FFamily);
+
+ // Set up TLS callbacks if TLS is enabled
+ if FUseTLS then
+ begin
+ TncLineInternal(Result).OnBeforeConnected := HandleTLSHandshake;
+ TncLineInternal(Result).OnBeforeDisconnected := FinalizeTLS;
+ end;
+end;
+
+procedure TncTCPBaseDual.SetActive(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ if not(csLoading in ComponentState) then
+ DoActivate(Value);
+
+ FInitActive := GetActive; // we only care here for the loaded event
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetFamily: TAddressType;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FFamily;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetFamily(const Value: TAddressType);
+begin
+ if not (csLoading in ComponentState) then
+ begin
+ if Active then
+ raise EPropertySetError.Create(ECannotSetFamilyWhileConnectionIsActiveStr);
+ end;
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Update base class family
+ FFamily := Value;
+
+ // Update the Line's family
+ if FLine <> nil then
+ begin
+ TncLineInternal(FLine).SetFamily(Value);
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetPort: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPort;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetPort(const Value: Integer);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetPortWhileConnectionIsActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FPort := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetReaderThreadPriority: TncThreadPriority;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := ToNcThreadPriority(LineProcessor.Priority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ try
+ LineProcessor.Priority := FromNcThreadPriority(Value);
+ except
+ // Some android devices cannot handle changing priority
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetEventsUseMainThread: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FEventsUseMainThread;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetEventsUseMainThread(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FEventsUseMainThread := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetUseReaderThread(const Value: Boolean);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetUseReaderThreadWhileActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FUseReaderThread := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetNoDelay: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FNoDelay;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetNoDelay(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FNoDelay := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetKeepAlive: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FKeepAlive;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetKeepAlive(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FKeepAlive := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// Update
+function TncTCPBaseDual.GetReadBufferLen: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReadBufferLen;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// Update
+procedure TncTCPBaseDual.SetReadBufferLen(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReadBufferLen := Value;
+ SetLength(ReadBuf, FReadBufferLen);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// TLS Property Methods
+function TncTCPBaseDual.GetUseTLS: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FUseTLS;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetUseTLS(const Value: Boolean);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create('Cannot set UseTLS property whilst the connection is active');
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FUseTLS := Value;
+
+ // Add TLS callback assignment when TLS is enabled
+ if Value then
+ begin
+ if FIsServer and (Self is TncCustomTCPServerDual) then
+ begin
+ // Server callback assignment
+ var Server := TncCustomTCPServerDual(Self);
+ if Server.Listener <> nil then
+ begin
+ TncLineInternal(Server.Listener).OnBeforeConnected := HandleTLSHandshake;
+ end;
+ end
+ else if not FIsServer and (Self is TncCustomTCPClientDual) then
+ begin
+ // Client callback assignment
+ var Client := TncCustomTCPClientDual(Self);
+ if Client.Line <> nil then
+ begin
+ TncLineInternal(Client.Line).OnBeforeConnected := HandleTLSHandshake;
+ end;
+ end;
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetTlsProvider: TncTlsProvider;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FTlsProvider;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetTlsProvider(const Value: TncTlsProvider);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create('Cannot set TlsProvider property whilst the connection is active');
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Validate provider availability
+ case Value of
+ tpSChannel:
+ begin
+ {$IFNDEF MSWINDOWS}
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr);
+ {$ENDIF}
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL validation - for now, not supported
+ raise EOpenSSLNotAvailable.Create(EOpenSSLNotAvailableStr);
+ end;
+ end;
+
+ FTlsProvider := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetCertificateFile: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCertificateFile;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCertificateFile(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCertificateFile := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetPrivateKeyFile: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPrivateKeyFile;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetPrivateKeyFile(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FPrivateKeyFile := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetPrivateKeyPassword: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPrivateKeyPassword;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetPrivateKeyPassword(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FPrivateKeyPassword := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetCACertificatesFile: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCACertificatesFile;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCACertificatesFile(const Value: string);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCACertificatesFile := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetIgnoreCertificateErrors: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FIgnoreCertificateErrors;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetIgnoreCertificateErrors(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FIgnoreCertificateErrors := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// Compression and Encryption Property Implementations (same as ncSources)
+
+function TncTCPBaseDual.GetCompression: TZCompressionLevel;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCompression;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCompression(const Value: TZCompressionLevel);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCompression := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetEncryption: TEncryptorType;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FEncryption;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetEncryption(const Value: TEncryptorType);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FEncryption := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetEncryptionKey: AnsiString;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FEncryptionKey;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetEncryptionKey(const Value: AnsiString);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FEncryptionKey := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetEncryptOnHashedKey: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FEncryptOnHashedKey;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetEncryptOnHashedKey(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FEncryptOnHashedKey := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// TLS base implementation
+
+function TncTCPBaseDual.GetHost: string;
+begin
+ Result := ''; // Default implementation, override in client
+end;
+
+{$IFDEF MSWINDOWS}
+// TLS Functionality Methods
+procedure TncTCPBaseDual.InitializeTLS(aLine: TncLine);
+var
+ TlsContext: TncTlsConnectionContext;
+begin
+ if not FUseTLS then
+ Exit;
+
+ if aLine = nil then
+ Exit;
+
+ // Get or create per-connection TLS context
+ if TncLineInternal(aLine).DataObject = nil then
+ begin
+ TlsContext := TncTlsConnectionContext.Create(FIsServer);
+ TncLineInternal(aLine).DataObject := TlsContext;
+ end
+ else
+ begin
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+ end;
+
+ // Check if TLS is already initialized for this specific connection
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ Exit;
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ Exit;
+ end;
+
+ // Initialize TLS for this specific connection
+ if FIsServer then
+ begin
+ TlsContext.GetServerContext^.AfterConnection(aLine, AnsiString(FCertificateFile), AnsiString(FPrivateKeyPassword));
+ end
+ else
+ begin
+ TlsContext.GetClientContext^.AfterConnection(aLine, AnsiString(GetHost), FIgnoreCertificateErrors);
+ end;
+end;
+{$ELSE}
+// TLS Functionality Methods - Linux stub
+procedure TncTCPBaseDual.InitializeTLS(aLine: TncLine);
+begin
+ // TLS not supported on Linux yet
+ if FUseTLS then
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr);
+end;
+{$ENDIF}
+
+procedure TncTCPBaseDual.HandleTLSHandshake(aLine: TncLine);
+begin
+ // This method is called automatically before OnConnected fires
+ // It performs the TLS handshake synchronously
+ if FUseTLS and (aLine <> nil) then
+ begin
+ InitializeTLS(aLine); // Perform the complete TLS handshake
+ end;
+end;
+
+procedure TncTCPBaseDual.HandleTLSHandshakeComplete(aLine: TncLine);
+begin
+ // Call OnConnected for TLS connections after handshake completes
+ if FUseTLS and Assigned(OnConnected) then
+ begin
+ try
+ OnConnected(Self, aLine);
+ except
+ on E: Exception do
+ // OnConnected failed - could log this if needed
+ end;
+ end;
+end;
+
+{$IFDEF MSWINDOWS}
+procedure TncTCPBaseDual.FinalizeTLS(aLine: TncLine);
+var
+ TlsContext: TncTlsConnectionContext;
+begin
+ if FUseTLS and (aLine <> nil) and (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ try
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+
+ case FTlsProvider of
+ tpSChannel:
+ begin
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ TlsContext.GetServerContext^.BeforeDisconnection(aLine);
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ TlsContext.GetClientContext^.BeforeDisconnection(aLine);
+ end;
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL cleanup
+ end;
+ end;
+
+ // Clean up the TLS context object
+ TncLineInternal(aLine).DataObject := nil;
+ TlsContext.Free;
+ except
+ on E: Exception do
+ // Log error but don't raise exception during cleanup
+ end;
+ end;
+end;
+{$ELSE}
+procedure TncTCPBaseDual.FinalizeTLS(aLine: TncLine);
+begin
+ // TLS not supported on Linux yet - no cleanup needed
+end;
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+function TncTCPBaseDual.SendTLS(aLine: TncLine; const aBuf; aBufSize: Integer): Integer;
+var
+ TlsContext: TncTlsConnectionContext;
+begin
+ if FUseTLS and (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+
+ case FTlsProvider of
+ tpSChannel:
+ begin
+ // CRITICAL FIX: Lock the TLS context during Send
+ // SChannel is NOT thread-safe for concurrent encrypt/decrypt
+ TlsContext.Lock;
+ try
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ Result := TlsContext.GetServerContext^.Send(aLine, @aBuf, aBufSize)
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ Result := TlsContext.GetClientContext^.Send(aLine, @aBuf, aBufSize)
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+ end;
+ finally
+ TlsContext.Unlock;
+ end;
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL send implementation
+ raise EOpenSSLNotAvailable.Create(EOpenSSLNotAvailableStr);
+ end;
+ end;
+ end
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+end;
+{$ELSE}
+function TncTCPBaseDual.SendTLS(aLine: TncLine; const aBuf; aBufSize: Integer): Integer;
+begin
+ if FUseTLS then
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr)
+ else
+ Result := TncLineInternal(aLine).SendBuffer(aBuf, aBufSize);
+end;
+{$ENDIF}
+
+{$IFDEF MSWINDOWS}
+function TncTCPBaseDual.ReceiveTLS(aLine: TncLine; var aBuf; aBufSize: Integer): Integer;
+var
+ TlsContext: TncTlsConnectionContext;
+ WasHandshakeCompleted: Boolean;
+ HandshakeJustCompleted: Boolean;
+ SessionClosed: Boolean;
+begin
+ if FUseTLS and (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+
+ case FTlsProvider of
+ tpSChannel:
+ begin
+ if FIsServer then
+ begin
+ if TlsContext.GetServerContext^.Initialized then
+ begin
+ // CRITICAL FIX: Lock the TLS context during Receive
+ // SChannel is NOT thread-safe for concurrent encrypt/decrypt
+ TlsContext.Lock;
+ try
+ WasHandshakeCompleted := TlsContext.GetServerContext^.HandshakeCompleted;
+
+ Result := TlsContext.GetServerContext^.Receive(aLine, @aBuf, aBufSize);
+
+ // Capture state while still locked
+ SessionClosed := TlsContext.GetServerContext^.SessionClosed;
+ HandshakeJustCompleted := not WasHandshakeCompleted and TlsContext.GetServerContext^.HandshakeCompleted;
+ finally
+ TlsContext.Unlock;
+ end;
+
+ // CRITICAL FIX: Detect TLS disconnection when Receive returns 0 after handshake completion
+ // BUT only if SessionClosed is also true (indicating actual disconnection)
+ if (Result = 0) and WasHandshakeCompleted and SessionClosed then
+ raise Exception.Create('TLS client disconnected');
+
+ // Check if handshake just completed
+ if HandshakeJustCompleted then
+ begin
+ // Handshake just completed, call OnConnected
+ HandleTLSHandshakeComplete(aLine);
+
+ // CRITICAL FIX: Return -1 to prevent OnReadData from being triggered with empty data
+ // The handshake completion callback has already been called above
+ Result := -1;
+ end;
+ end
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+ end
+ else
+ begin
+ if TlsContext.GetClientContext^.Initialized then
+ begin
+ // For client, handshake is complete when Initialized becomes true
+ // But we need to track when it JUST became initialized (not if it was already initialized)
+ // Since the client calls AfterConnection during OnBeforeConnected, we know that
+ // the first call to Receive after OnBeforeConnected is when handshake is complete
+
+ // CRITICAL FIX: Lock the TLS context during Receive
+ // SChannel is NOT thread-safe for concurrent encrypt/decrypt
+ TlsContext.Lock;
+ try
+ Result := TlsContext.GetClientContext^.Receive(aLine, @aBuf, aBufSize);
+ SessionClosed := TlsContext.GetClientContext^.SessionClosed;
+ finally
+ TlsContext.Unlock;
+ end;
+
+ // CRITICAL FIX: Detect TLS disconnection when Receive returns 0 after handshake completion
+ // BUT only if SessionClosed is also true (indicating actual disconnection)
+ if (Result = 0) and TlsContext.GetClientContext^.Initialized and SessionClosed then
+ raise Exception.Create('TLS server disconnected');
+
+ // Client-side handshake completion detection:
+ // The client TLS handshake is handled in OnBeforeConnected event
+ // So by the time we get here, handshake is already complete
+ // We don't need to do anything special for client handshake completion
+ end
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+ end;
+ end;
+ tpOpenSSL:
+ begin
+ // Future OpenSSL receive implementation
+ raise EOpenSSLNotAvailable.Create(EOpenSSLNotAvailableStr);
+ end;
+ end;
+ end
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+end;
+{$ELSE}
+function TncTCPBaseDual.ReceiveTLS(aLine: TncLine; var aBuf; aBufSize: Integer): Integer;
+begin
+ if FUseTLS then
+ raise ETlsProviderNotSupported.Create(ETlsProviderNotSupportedStr)
+ else
+ Result := TncLineInternal(aLine).RecvBuffer(aBuf, aBufSize);
+end;
+{$ENDIF}
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncCustomTCPClientDual }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncCustomTCPClientDual.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FIsServer := False; // Set client flag for TLS context selection
+ FHost := DefHost;
+ FReconnect := True;
+ FReconnectInterval := DefCntReconnectInterval;
+ FOnReconnected := nil;
+ FOnCommand := nil; // Initialize the new field
+ OriginalOnReadData := OnReadData; // Store original handler
+ OnReadData := InternalReadDataHandler; // Set up protocol detection handler
+ FConnectionState.Reset; // Initialize connection state
+
+ LastConnectAttempt := TStopWatch.GetTimeStamp;
+ WasConnected := False;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ TncLineInternal(Line).OnConnected := DataSocketConnected;
+ TncLineInternal(Line).OnDisconnected := DataSocketDisconnected;
+
+ // Set up TLS callbacks if TLS is enabled
+ if FUseTLS then
+ begin
+ TncLineInternal(Line).OnBeforeConnected := HandleTLSHandshake;
+ // REMOVED: OnBeforeDisconnected - now using direct FinalizeTLS call like ncSockets.pas
+ end;
+
+ LineProcessor := TncClientProcessor.Create(Self);
+ try
+ if LineProcessor.Priority <> FromNcThreadPriority(DefReaderThreadPriority) then
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+ LineProcessor.WaitForReady;
+end;
+
+
+destructor TncCustomTCPClientDual.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+procedure TncCustomTCPClientDual.DoActivate(aActivate: Boolean);
+begin
+
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ TncLineInternal(Line).CreateClientHandle(FHost, FPort);
+
+ // if there were no exceptions, and line is still not active,
+ // that means the user has deactivated it in the OnConnect handler
+ if not Line.Active then
+ WasConnected := False;
+ end
+ else
+ begin
+ WasConnected := False;
+ TncLineInternal(Line).DestroyHandle;
+ end;
+end;
+
+procedure TncCustomTCPClientDual.DataSocketConnected(aLine: TncLine);
+begin
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ if NoDelay then
+ try
+ TncLineInternal(Line).EnableNoDelay;
+ except
+ end;
+
+ if KeepAlive then
+ try
+ TncLineInternal(Line).EnableKeepAlive;
+ except
+ end;
+
+ try
+ TncLineInternal(Line).SetReceiveSize(1048576); // 1MB
+ TncLineInternal(Line).SetWriteSize(1048576); // 1MB
+ //TncLineInternal(Line).SetReceiveSize(20 * 1048576);
+
+ except
+ end;
+
+ // TLS initialization is now handled by OnBeforeConnected event
+
+ if Assigned(OnConnected) then
+ try
+ OnConnected(Self, aLine);
+ except
+ end;
+
+ LastConnectAttempt := TStopWatch.GetTimeStamp;
+ WasConnected := True;
+
+ if UseReaderThread then
+ LineProcessor.Run; // Will just set events, this does not wait
+end;
+
+procedure TncCustomTCPClientDual.DataSocketDisconnected(aLine: TncLine);
+begin
+ // FIXED: Use same pattern as ncSockets.pas - direct TLS cleanup call
+ if UseTLS then
+ FinalizeTLS(aLine);
+
+ if Assigned(OnDisconnected) then
+ try
+ OnDisconnected(Self, aLine);
+ except
+ end;
+end;
+
+
+procedure TncCustomTCPClientDual.Send(const aBuf; aBufSize: Integer);
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ SendTLS(Line, aBuf, aBufSize);
+end;
+
+procedure TncCustomTCPClientDual.Send(const aBytes: TBytes);
+begin
+ if Length(aBytes) > 0 then
+ Send(aBytes[0], Length(aBytes));
+end;
+
+procedure TncCustomTCPClientDual.Send(const aStr: string);
+begin
+ Send(BytesOf(aStr));
+end;
+
+procedure TncCustomTCPClientDual.SendCommand(aCmd: Integer; const aData: TBytes = nil);
+var
+ Command: TncCommand;
+ MessageBytes, FinalBuf: TBytes;
+ MsgByteCount, HeaderBytes: UInt64;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ // Create command like ncSources does
+ Command.CommandType := ctInitiator;
+ Command.UniqueID := 0; // Simplified for now
+ Command.Cmd := aCmd;
+ Command.Data := aData;
+ Command.RequiresResult := False;
+ Command.AsyncExecute := False;
+ Command.ResultIsErrorString := False;
+ Command.SourceComponentHandler := '';
+ Command.PeerComponentHandler := '';
+
+ // Convert to bytes like ncSources
+ MessageBytes := Command.ToBytes;
+
+ // Apply compression and encryption (same order as ncSources)
+ // Step 1: Encrypt first (if enabled)
+ if Encryption <> etNoEncryption then
+ MessageBytes := EncryptBytes(MessageBytes, EncryptionKey, Encryption, EncryptOnHashedKey, False);
+
+ // Step 2: Compress second (if enabled)
+ if Compression <> zcNone then
+ MessageBytes := CompressBytes(MessageBytes, Compression);
+
+ MsgByteCount := Length(MessageBytes);
+
+ // Use ncSources protocol format: [Magic: 4][MessageLength: 8][Data: variable]
+ HeaderBytes := SizeOf(TMagicHeaderType) + SizeOf(MsgByteCount);
+ SetLength(FinalBuf, HeaderBytes + MsgByteCount);
+
+ // Write protocol header (same as ncSources)
+ PMagicHeaderType(@FinalBuf[0])^ := MagicHeader; // Magic: 4 bytes
+ PUInt64(@FinalBuf[SizeOf(MagicHeader)])^ := MsgByteCount; // MessageLength: 8 bytes
+ Move(MessageBytes[0], FinalBuf[HeaderBytes], MsgByteCount); // Data: variable
+
+ Send(FinalBuf);
+end;
+
+procedure TncCustomTCPClientDual.InternalReadDataHandler(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ Command: TncCommand;
+ Ofs: Integer;
+ BytesToRead: Integer;
+ OldLen: Integer;
+ TextData: TBytes;
+begin
+ // CRITICAL FIX: When TLS is enabled, bypass protocol detection during handshake
+ // TLS handshake data should never reach the application layer
+ if UseTLS then
+ begin
+ {$IFDEF MSWINDOWS}
+ // Check if TLS handshake is still in progress using per-connection context
+ if (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ var TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+ if not TlsContext.GetClientContext^.Initialized then
+ begin
+ // During handshake, pass all data directly to original handler (TLS layer)
+ // Protocol detection should only happen AFTER TLS handshake completes
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, aBuf, aBufCount);
+ Exit; // Don't process for protocol detection during handshake
+ end;
+ end;
+ {$ENDIF}
+ // If we reach here, TLS handshake is complete and data is decrypted application data
+ // Continue with normal protocol detection below
+ end;
+
+ Ofs := 0;
+
+ // Process incoming data using ncSources-style state machine
+ while Ofs < aBufCount do
+ begin
+ // Are we in the middle of accumulating a message?
+ if FConnectionState.BytesToEndOfMessage > 0 then
+ begin
+ // ncSources approach: We know exactly how many bytes we need
+ BytesToRead := Min(FConnectionState.BytesToEndOfMessage, aBufCount - Ofs);
+
+ // Accumulate data efficiently
+ OldLen := Length(FConnectionState.MessageBuffer);
+ SetLength(FConnectionState.MessageBuffer, OldLen + BytesToRead);
+ Move(aBuf[Ofs], FConnectionState.MessageBuffer[OldLen], BytesToRead);
+
+ Ofs := Ofs + BytesToRead;
+ FConnectionState.BytesToEndOfMessage := FConnectionState.BytesToEndOfMessage - BytesToRead;
+ end;
+
+ // Do we have a complete message?
+ if FConnectionState.BytesToEndOfMessage = 0 then
+ begin
+ if Length(FConnectionState.MessageBuffer) > 0 then
+ begin
+ // Process complete message based on detected protocol
+ case FConnectionState.MessageType of
+ mtBinary:
+ begin
+ // Process binary command - Route to Thread Pool (from ncSources)
+ try
+ // Apply decompression and decryption (reverse order of sending)
+ var ProcessedData := FConnectionState.MessageBuffer;
+
+ // Step 1: Decompress first (reverse order)
+ if Compression <> zcNone then
+ ProcessedData := DecompressBytes(ProcessedData);
+
+ // Step 2: Decrypt second
+ if Encryption <> etNoEncryption then
+ ProcessedData := DecryptBytes(ProcessedData, EncryptionKey, Encryption, EncryptOnHashedKey, False);
+
+ // Parse the processed data
+ Command.FromBytes(ProcessedData);
+
+ // Route to thread pool for processing like ncSources
+ TMonitor.Enter(HandleCommandThreadPool);
+ try
+ var HandleCommandThread := THandleCommandThread(HandleCommandThreadPool.RequestReadyThread);
+ HandleCommandThread.WorkType := htwtOnCommand;
+ HandleCommandThread.Source := Self;
+ HandleCommandThread.Line := aLine;
+ HandleCommandThread.Cmd := Command.Cmd;
+ HandleCommandThread.Data := Command.Data;
+ HandleCommandThread.OnCommand := FOnCommand;
+ HandleCommandThread.EventsUseMainThread := EventsUseMainThread;
+ HandleCommandThreadPool.RunRequestedThread(HandleCommandThread);
+ finally
+ TMonitor.Exit(HandleCommandThreadPool);
+ end;
+ except
+ // If decompression/decryption/parsing fails, treat as text
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, FConnectionState.MessageBuffer, Length(FConnectionState.MessageBuffer));
+ end;
+ end;
+ mtText:
+ begin
+ // Process text data
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, FConnectionState.MessageBuffer, Length(FConnectionState.MessageBuffer));
+ end;
+ end;
+
+ // Reset for next message
+ FConnectionState.Reset;
+ end;
+
+ // Start new message detection if we have more data
+ if Ofs < aBufCount then
+ begin
+ // Protocol detection: Check for magic header
+ if (aBufCount - Ofs) >= SizeOf(TMagicHeaderType) then
+ begin
+ if PMagicHeaderType(@aBuf[Ofs])^ = MagicHeader then
+ begin
+ // Binary protocol detected
+ FConnectionState.MessageType := mtBinary;
+
+ // Do we have the complete header?
+ if (aBufCount - Ofs) >= (SizeOf(TMagicHeaderType) + SizeOf(UInt64)) then
+ begin
+ // Read message length and set up state
+ FConnectionState.ExpectedMessageLength := PUInt64(@aBuf[Ofs + SizeOf(TMagicHeaderType)])^;
+ FConnectionState.BytesToEndOfMessage := FConnectionState.ExpectedMessageLength;
+ FConnectionState.HeaderComplete := True;
+
+ // Skip past header
+ Ofs := Ofs + SizeOf(TMagicHeaderType) + SizeOf(UInt64);
+
+ // Continue to accumulate message data
+ Continue;
+ end
+ else
+ begin
+ // Incomplete header - buffer remaining data and wait
+ SetLength(TextData, aBufCount - Ofs);
+ Move(aBuf[Ofs], TextData[0], aBufCount - Ofs);
+ FConnectionState.MessageBuffer := TextData;
+ FConnectionState.BytesToEndOfMessage := (SizeOf(TMagicHeaderType) + SizeOf(UInt64)) - (aBufCount - Ofs);
+ FConnectionState.MessageType := mtUnknown; // Still detecting
+ Break;
+ end;
+ end
+ else
+ begin
+ // Unknown protocol - pass through directly like ncSockets
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, Copy(aBuf, Ofs, aBufCount - Ofs), aBufCount - Ofs);
+ Break; // Exit processing, don't accumulate
+ end;
+ end
+ else
+ begin
+ // Not enough data for magic header check - pass through directly like ncSockets
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, Copy(aBuf, Ofs, aBufCount - Ofs), aBufCount - Ofs);
+ Break; // Exit processing
+ end;
+ end;
+ end;
+ end;
+end;
+
+procedure TncCustomTCPClientDual.SetOnReadData(const Value: TncOnReadData);
+begin
+ // Store the user's handler and keep protocol detection active
+ OriginalOnReadData := Value;
+ inherited OnReadData := InternalReadDataHandler;
+end;
+
+function TncCustomTCPClientDual.Receive(aTimeout: Cardinal): TBytes;
+var
+ BufRead: Integer;
+begin
+ if UseReaderThread then
+ raise ECannotReceiveIfUseReaderThread.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ BufRead := ReceiveTLS(Line, ReadBuf[0], Length(ReadBuf));
+ Result := Copy(ReadBuf, 0, BufRead)
+end;
+
+function TncCustomTCPClientDual.ReceiveRaw(var aBytes: TBytes): Integer;
+begin
+ Result := ReceiveTLS(Line, aBytes[0], Length(aBytes));
+end;
+
+function TncCustomTCPClientDual.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+function TncCustomTCPClientDual.GetHost: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FHost;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomTCPClientDual.SetHost(const Value: string);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetHostWhileConnectionIsActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FHost := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncCustomTCPClientDual.GetReconnect: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReconnect;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomTCPClientDual.SetReconnect(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReconnect := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncCustomTCPClientDual.GetReconnectInterval: Cardinal;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReconnectInterval;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomTCPClientDual.SetReconnectInterval(const Value: Cardinal);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReconnectInterval := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncClientProcessor }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncClientProcessor.Create(aClientSocket: TncCustomTCPClientDual);
+begin
+ FClientSocket := aClientSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+procedure TncClientProcessor.SocketProcess;
+var
+ BufRead: Integer;
+begin
+ BufRead := FClientSocket.ReceiveTLS(FClientSocket.Line, FClientSocket.ReadBuf[0], Length(FClientSocket.ReadBuf));
+ if Assigned(FClientSocket.OnReadData) and (BufRead > 0) then
+ try
+ FClientSocket.OnReadData(FClientSocket, FClientSocket.Line, FClientSocket.ReadBuf, BufRead);
+ except
+ end;
+end;
+
+procedure TncClientProcessor.SocketWasReconnected;
+begin
+ if Assigned(FClientSocket.FOnReconnected) then
+ FClientSocket.FOnReconnected(FClientSocket, FClientSocket.Line);
+ if Assigned(FClientSocket.FOnConnected) then
+ FClientSocket.FOnConnected(FClientSocket, FClientSocket.Line);
+end;
+
+procedure TncClientProcessor.ProcessEvent;
+var
+ PrevOnConnect: TncOnConnectDisconnect;
+ WasReconnected: Boolean;
+begin
+ while (not Terminated) do // Repeat handling until terminated
+ try
+ if FClientSocket.Line.Active then // Repeat reading socket until disconnected
+ begin
+ if ReadableAnySocket(FClientSocket.ReadSocketHandles, 100) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ if FClientSocket.EventsUseMainThread then
+ Synchronize(SocketProcess) // for synchronize
+ else
+ SocketProcess;
+ end;
+ end
+ else
+ // Is not Active, try reconnecting if was connected
+ begin
+ // Logic for reconnect mode
+ if FClientSocket.Reconnect and FClientSocket.WasConnected then
+ begin
+ // A minimal sleep time of 30 msec is required in Android before
+ // reattempting to connect on a recently deactivated network connection.
+ // We have put it to 60 for safety
+ Sleep(60);
+ if Terminated then
+ Break;
+ if TStopWatch.GetTimeStamp - FClientSocket.LastConnectAttempt > FClientSocket.ReconnectInterval * TTimeSpan.TicksPerMillisecond then
+ begin
+ FClientSocket.LastConnectAttempt := TStopWatch.GetTimeStamp;
+
+ WasReconnected := False;
+ TMonitor.Enter(FClientSocket.PropertyLock);
+ try
+ if not FClientSocket.Active then
+ begin
+ PrevOnConnect := FClientSocket.OnConnected;
+ try
+ // Disable firing the event in the wrong thread in case it gets connected
+ FClientSocket.OnConnected := nil;
+ FClientSocket.Active := True;
+ WasReconnected := True;
+ finally
+ FClientSocket.OnConnected := PrevOnConnect;
+ end;
+ end;
+ finally
+ TMonitor.Exit(FClientSocket.PropertyLock);
+ end;
+ if WasReconnected then
+ if FClientSocket.EventsUseMainThread then
+ Synchronize(SocketWasReconnected)
+ else
+ SocketWasReconnected;
+ end;
+ end
+ else
+ Exit;
+ end;
+ except
+ // Something was disconnected, continue processing
+ end;
+end;
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncCustomTCPServerDual }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncCustomTCPServerDual.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FIsServer := True; // Set server flag for TLS context selection
+ FOnCommand := nil; // Initialize the new field
+ OriginalOnReadData := OnReadData; // Store original handler
+ OnReadData := InternalReadDataHandler; // Set up protocol detection handler
+ FConnectionStates := TDictionary.Create; // Initialize state tracking dictionary
+
+ Listener := CreateLineObject;
+ if Listener.Family <> FFamily then
+ begin
+ TncLineInternal(Listener).SetFamily(FFamily);
+ end;
+
+ TncLineInternal(Listener).OnConnected := DataSocketConnected;
+ TncLineInternal(Listener).OnDisconnected := DataSocketDisconnected;
+
+ // Set up TLS callbacks if TLS is enabled
+ if FUseTLS then
+ begin
+ TncLineInternal(Listener).OnBeforeConnected := HandleTLSHandshake;
+ // REMOVED: OnBeforeDisconnected - now using direct FinalizeTLS call like ncSockets.pas
+ end;
+ Lines := TThreadLineList.Create();
+
+ LineProcessor := TncServerProcessor.Create(Self);
+ try
+ if LineProcessor.Priority <> FromNcThreadPriority(DefReaderThreadPriority) then
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+ LineProcessor.WaitForReady;
+end;
+
+destructor TncCustomTCPServerDual.Destroy;
+begin
+ // Will get Sockets.Lines disposed off
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Lines.Free;
+ Listener.Free;
+
+ FConnectionStates.Free; // Cleanup state tracking dictionary
+
+ inherited Destroy;
+end;
+
+function TncCustomTCPServerDual.GetActive: Boolean;
+begin
+ Result := Listener.Active;
+end;
+
+procedure TncCustomTCPServerDual.DoActivate(aActivate: Boolean);
+var
+ DataSockets: TSocketList;
+ i: Integer;
+begin
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+ // Verify family setting before creating handle
+ if Assigned(Listener) and (Listener.Family <> FFamily) then
+ begin
+ TncLineInternal(Listener).SetFamily(FFamily);
+ end;
+ TncLineInternal(Listener).CreateServerHandle(FPort);
+ end
+ else
+ begin
+ if Assigned(Listener) then
+ TncLineInternal(Listener).DestroyHandle;
+
+ // Cleanup connected sockets
+ DataSockets := Lines.LockListNoCopy;
+ try
+ for i := 0 to DataSockets.Count - 1 do
+ try
+ if Assigned(DataSockets.Lines[i]) then
+ begin
+ TncLineInternal(DataSockets.Lines[i]).DestroyHandle;
+ DataSockets.Lines[i].Free;
+ end;
+ except
+ //
+ end;
+ DataSockets.Clear;
+ finally
+ Lines.UnlockListNoCopy;
+ end;
+ end;
+end;
+
+procedure TncCustomTCPServerDual.ShutDownLine(aLine: TncLine);
+var
+ i: Integer;
+begin
+ if UseReaderThread then
+ begin
+ TMonitor.Enter(ShutDownLock);
+ try
+ for i := 0 to High(LinesToShutDown) do
+ if LinesToShutDown[i] = aLine then
+ Exit;
+
+ SetLength(LinesToShutDown, Length(LinesToShutDown) + 1);
+ LinesToShutDown[High(LinesToShutDown)] := aLine;
+ finally
+ TMonitor.Exit(ShutDownLock);
+ end;
+ end
+ else
+ begin
+ Lines.Remove(aLine);
+ aLine.Free;
+ end;
+end;
+
+procedure TncCustomTCPServerDual.DataSocketConnected(aLine: TncLine);
+begin
+ if aLine = Listener then
+ begin
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Listener.Handle;
+ if UseReaderThread then
+ begin
+ LineProcessor.WaitForReady;
+ LineProcessor.Run;
+ end;
+ end
+ else
+ begin
+ SetLength(ReadSocketHandles, Length(ReadSocketHandles) + 1);
+ ReadSocketHandles[High(ReadSocketHandles)] := aLine.Handle;
+
+ if NoDelay then
+ try
+ TncLineInternal(aLine).EnableNoDelay;
+ except
+ end;
+
+ if KeepAlive then
+ try
+ TncLineInternal(aLine).EnableKeepAlive;
+ except
+ end;
+
+ try
+ TncLineInternal(aLine).SetReceiveSize(1048576);
+ TncLineInternal(aLine).SetWriteSize(1048576);
+ except
+ end;
+
+ // TLS initialization is now handled by OnBeforeConnected event
+
+ // For TLS connections, delay OnConnected until after handshake completes
+ if not UseTLS then
+ begin
+ if Assigned(OnConnected) then
+ try
+ OnConnected(Self, aLine);
+ except
+ end;
+ end
+ else
+ begin
+ // For TLS connections, OnConnected will be called after handshake completes
+ // This is handled in the first successful TLS receive operation
+ end;
+ end;
+end;
+
+// Update : Moves the handle removal before the disconnect event handling
+// This prevents other threads from trying to use the handle while the disconnect event is processing.
+procedure TncCustomTCPServerDual.DataSocketDisconnected(aLine: TncLine);
+var
+ i: Integer;
+begin
+ if aLine = Listener then
+ SetLength(ReadSocketHandles, 0)
+ else
+ begin
+ // FIXED: Use same pattern as ncSockets.pas - direct TLS cleanup call
+ if UseTLS then
+ FinalizeTLS(aLine);
+
+ // Clean up connection state
+ FConnectionStates.Remove(aLine);
+
+ // First remove the handle to prevent further processing
+ TMonitor.Enter(PropertyLock);
+ try
+ for i := 0 to High(ReadSocketHandles) do
+ if ReadSocketHandles[i] = aLine.Handle then
+ begin
+ ReadSocketHandles[i] := ReadSocketHandles[High(ReadSocketHandles)];
+ SetLength(ReadSocketHandles, Length(ReadSocketHandles) - 1);
+ Break;
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+
+ // Then handle disconnect event
+ if Assigned(OnDisconnected) then
+ try
+ OnDisconnected(Self, aLine);
+ except
+ end;
+ end;
+end;
+
+procedure TncCustomTCPServerDual.Send(aLine: TncLine; const aBuf; aBufSize: Integer);
+begin
+ SendTLS(aLine, aBuf, aBufSize);
+end;
+
+procedure TncCustomTCPServerDual.Send(aLine: TncLine; const aBytes: TBytes);
+begin
+ if Length(aBytes) > 0 then
+ Send(aLine, aBytes[0], Length(aBytes));
+end;
+
+procedure TncCustomTCPServerDual.Send(aLine: TncLine; const aStr: string);
+begin
+ Send(aLine, BytesOf(aStr));
+end;
+
+function TncCustomTCPServerDual.Receive(aLine: TncLine; aTimeout: Cardinal): TBytes;
+var
+ i, BufRead, LineNdx: Integer;
+ DataSockets: TSocketList;
+ Line: TncLine;
+ ReadySockets: TSocketHandleArray;
+begin
+ if UseReaderThread then
+ raise ECannotReceiveIfUseReaderThread.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ SetLength(Result, 0);
+ ReadySockets := Readable(ReadSocketHandles, aTimeout);
+
+ for i := 0 to High(ReadySockets) do
+ try
+ if ReadySockets[i] = Listener.Handle then
+ // New line is here, accept it and create a new TncLine object
+ Lines.Add(TncLineInternal(Listener).AcceptLine);
+ except
+ end;
+
+ DataSockets := Lines.LockListNoCopy;
+ try
+ for i := 0 to High(ReadySockets) do
+ try
+ if aLine.Handle = ReadySockets[i] then
+ begin
+ LineNdx := DataSockets.IndexOf(ReadySockets[i]);
+ if LineNdx = -1 then
+ Continue;
+ Line := DataSockets.Lines[LineNdx];
+ try
+ if not Line.Active then
+ Abort;
+ BufRead := ReceiveTLS(Line, ReadBuf[0], Length(ReadBuf));
+ Result := Copy(ReadBuf, 0, BufRead);
+ except
+ // Line has disconnected, destroy the line
+ DataSockets.Delete(LineNdx);
+ Line.Free;
+ end;
+ end;
+ except
+ end;
+ finally
+ Lines.UnlockListNoCopy;
+ end;
+end;
+
+function TncCustomTCPServerDual.ReceiveRaw(aLine: TncLine; var aBytes: TBytes): Integer;
+begin
+ Result := ReceiveTLS(aLine, aBytes[0], Length(aBytes));
+end;
+
+procedure TncCustomTCPServerDual.SendCommand(aLine: TncLine; aCmd: Integer; const aData: TBytes = nil);
+var
+ Command: TncCommand;
+ MessageBytes, FinalBuf: TBytes;
+ MsgByteCount, HeaderBytes: UInt64;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ // Create command like ncSources does
+ Command.CommandType := ctInitiator;
+ Command.UniqueID := 0; // Simplified for now
+ Command.Cmd := aCmd;
+ Command.Data := aData;
+ Command.RequiresResult := False;
+ Command.AsyncExecute := False;
+ Command.ResultIsErrorString := False;
+ Command.SourceComponentHandler := '';
+ Command.PeerComponentHandler := '';
+
+ // Convert to bytes like ncSources
+ MessageBytes := Command.ToBytes;
+
+ // Apply compression and encryption (same order as ncSources)
+ // Step 1: Encrypt first (if enabled)
+ if Encryption <> etNoEncryption then
+ MessageBytes := EncryptBytes(MessageBytes, EncryptionKey, Encryption, EncryptOnHashedKey, False);
+
+ // Step 2: Compress second (if enabled)
+ if Compression <> zcNone then
+ MessageBytes := CompressBytes(MessageBytes, Compression);
+
+ MsgByteCount := Length(MessageBytes);
+
+ // Use ncSources protocol format: [Magic: 4][MessageLength: 8][Data: variable]
+ HeaderBytes := SizeOf(TMagicHeaderType) + SizeOf(MsgByteCount);
+ SetLength(FinalBuf, HeaderBytes + MsgByteCount);
+
+ // Write protocol header (same as ncSources)
+ PMagicHeaderType(@FinalBuf[0])^ := MagicHeader; // Magic: 4 bytes
+ PUInt64(@FinalBuf[SizeOf(MagicHeader)])^ := MsgByteCount; // MessageLength: 8 bytes
+ Move(MessageBytes[0], FinalBuf[HeaderBytes], MsgByteCount); // Data: variable
+
+ Send(aLine, FinalBuf);
+end;
+
+procedure TncCustomTCPServerDual.InternalReadDataHandler(Sender: TObject; aLine: TncLine;
+ const aBuf: TBytes; aBufCount: Integer);
+var
+ Command: TncCommand;
+ ConnectionState: TConnectionState;
+ Ofs: Integer;
+ BytesToRead: Integer;
+ OldLen: Integer;
+ TextData: TBytes;
+begin
+ // CRITICAL FIX: When TLS is enabled, bypass protocol detection during handshake
+ // TLS handshake data should never reach the application layer
+ if UseTLS then
+ begin
+ {$IFDEF MSWINDOWS}
+ // Check if TLS handshake is still in progress using per-connection context
+ if (TncLineInternal(aLine).DataObject <> nil) then
+ begin
+ var TlsContext := TncTlsConnectionContext(TncLineInternal(aLine).DataObject);
+ if not TlsContext.GetServerContext^.HandshakeCompleted then
+ begin
+ // During handshake, pass all data directly to original handler (TLS layer)
+ // Protocol detection should only happen AFTER TLS handshake completes
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, aBuf, aBufCount);
+ Exit; // Don't process for protocol detection during handshake
+ end;
+ end;
+ {$ENDIF}
+ // If we reach here, TLS handshake is complete and data is decrypted application data
+ // Continue with normal protocol detection below
+ end;
+
+ // Get or create connection state
+ if not FConnectionStates.TryGetValue(aLine, ConnectionState) then
+ begin
+ ConnectionState.Reset;
+ FConnectionStates.Add(aLine, ConnectionState);
+ end;
+
+ Ofs := 0;
+
+ // Process incoming data using ncSources-style state machine
+ while Ofs < aBufCount do
+ begin
+ // Are we in the middle of accumulating a message?
+ if ConnectionState.BytesToEndOfMessage > 0 then
+ begin
+ // ncSources approach: We know exactly how many bytes we need
+ BytesToRead := Min(ConnectionState.BytesToEndOfMessage, aBufCount - Ofs);
+
+ // Accumulate data efficiently
+ OldLen := Length(ConnectionState.MessageBuffer);
+ SetLength(ConnectionState.MessageBuffer, OldLen + BytesToRead);
+ Move(aBuf[Ofs], ConnectionState.MessageBuffer[OldLen], BytesToRead);
+
+ Ofs := Ofs + BytesToRead;
+ ConnectionState.BytesToEndOfMessage := ConnectionState.BytesToEndOfMessage - BytesToRead;
+ end;
+
+ // Do we have a complete message?
+ if ConnectionState.BytesToEndOfMessage = 0 then
+ begin
+ if Length(ConnectionState.MessageBuffer) > 0 then
+ begin
+ // Process complete message based on detected protocol
+ case ConnectionState.MessageType of
+ mtBinary:
+ begin
+ // Process binary command - Route to Thread Pool (from ncSources)
+ try
+ // Apply decompression and decryption (reverse order of sending)
+ var ProcessedData := ConnectionState.MessageBuffer;
+
+ // Step 1: Decompress first (reverse order)
+ if Compression <> zcNone then
+ ProcessedData := DecompressBytes(ProcessedData);
+
+ // Step 2: Decrypt second
+ if Encryption <> etNoEncryption then
+ ProcessedData := DecryptBytes(ProcessedData, EncryptionKey, Encryption, EncryptOnHashedKey, False);
+
+ // Parse the processed data
+ Command.FromBytes(ProcessedData);
+
+ // Route to thread pool for processing like ncSources
+ TMonitor.Enter(HandleCommandThreadPool);
+ try
+ var HandleCommandThread := THandleCommandThread(HandleCommandThreadPool.RequestReadyThread);
+ HandleCommandThread.WorkType := htwtOnCommand;
+ HandleCommandThread.Source := Self;
+ HandleCommandThread.Line := aLine;
+ HandleCommandThread.Cmd := Command.Cmd;
+ HandleCommandThread.Data := Command.Data;
+ HandleCommandThread.OnCommand := FOnCommand;
+ HandleCommandThread.EventsUseMainThread := EventsUseMainThread;
+ HandleCommandThreadPool.RunRequestedThread(HandleCommandThread);
+ finally
+ TMonitor.Exit(HandleCommandThreadPool);
+ end;
+ except
+ // If decompression/decryption/parsing fails, treat as text
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, ConnectionState.MessageBuffer, Length(ConnectionState.MessageBuffer));
+ end;
+ end;
+ mtText:
+ begin
+ // Process text data
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, ConnectionState.MessageBuffer, Length(ConnectionState.MessageBuffer));
+ end;
+ end;
+
+ // Reset for next message
+ ConnectionState.Reset;
+ end;
+
+ // Start new message detection if we have more data
+ if Ofs < aBufCount then
+ begin
+ // Protocol detection: Check for magic header
+ if (aBufCount - Ofs) >= SizeOf(TMagicHeaderType) then
+ begin
+ if PMagicHeaderType(@aBuf[Ofs])^ = MagicHeader then
+ begin
+ // Binary protocol detected
+ ConnectionState.MessageType := mtBinary;
+
+ // Do we have the complete header?
+ if (aBufCount - Ofs) >= (SizeOf(TMagicHeaderType) + SizeOf(UInt64)) then
+ begin
+ // Read message length and set up state
+ ConnectionState.ExpectedMessageLength := PUInt64(@aBuf[Ofs + SizeOf(TMagicHeaderType)])^;
+ ConnectionState.BytesToEndOfMessage := ConnectionState.ExpectedMessageLength;
+ ConnectionState.HeaderComplete := True;
+
+ // Skip past header
+ Ofs := Ofs + SizeOf(TMagicHeaderType) + SizeOf(UInt64);
+
+ // Continue to accumulate message data
+ Continue;
+ end
+ else
+ begin
+ // Incomplete header - buffer remaining data and wait
+ SetLength(TextData, aBufCount - Ofs);
+ Move(aBuf[Ofs], TextData[0], aBufCount - Ofs);
+ ConnectionState.MessageBuffer := TextData;
+ ConnectionState.BytesToEndOfMessage := (SizeOf(TMagicHeaderType) + SizeOf(UInt64)) - (aBufCount - Ofs);
+ ConnectionState.MessageType := mtUnknown; // Still detecting
+ Break;
+ end;
+ end
+ else
+ begin
+ // Unknown protocol - pass through directly like ncSockets
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, Copy(aBuf, Ofs, aBufCount - Ofs), aBufCount - Ofs);
+ Break; // Exit processing, don't accumulate
+ end;
+ end
+ else
+ begin
+ // Not enough data for magic header check - pass through directly like ncSockets
+ if Assigned(OriginalOnReadData) then
+ OriginalOnReadData(Self, aLine, Copy(aBuf, Ofs, aBufCount - Ofs), aBufCount - Ofs);
+ Break; // Exit processing
+ end;
+ end;
+ end;
+ end;
+
+ // Update connection state
+ FConnectionStates.AddOrSetValue(aLine, ConnectionState);
+end;
+
+procedure TncCustomTCPServerDual.SetOnReadData(const Value: TncOnReadData);
+begin
+ // Store the user's handler and keep protocol detection active
+ OriginalOnReadData := Value;
+ inherited OnReadData := InternalReadDataHandler;
+end;
+
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncServerProcessor }
+// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncServerProcessor.Create(aServerSocket: TncCustomTCPServerDual);
+begin
+ FServerSocket := aServerSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+procedure TncServerProcessor.CheckLinesToShutDown;
+var
+ i: Integer;
+begin
+ // The list may be locked from custom code executed in the OnReadData handler
+ // So we will not delete anything, or lock the list, until this lock is freed
+ if TMonitor.TryEnter(FServerSocket.Lines) then
+ try
+ TMonitor.Enter(FServerSocket.ShutDownLock);
+ try
+ for i := 0 to High(FServerSocket.LinesToShutDown) do
+ try
+ FServerSocket.Lines.Remove(FServerSocket.LinesToShutDown[i]);
+ TncLineInternal(FServerSocket.LinesToShutDown[i]).DestroyHandle;
+ TncLineInternal(FServerSocket.LinesToShutDown[i]).Free;
+ except
+ end;
+ SetLength(FServerSocket.LinesToShutDown, 0);
+ finally
+ TMonitor.Exit(FServerSocket.ShutDownLock);
+ end;
+ finally
+ TMonitor.Exit(FServerSocket.Lines);
+ end;
+end;
+
+procedure TncServerProcessor.SocketProcess;
+var
+ i, LineNdx, BufRead, ReadySocketsHigh: Integer;
+ DataSockets: TSocketList;
+ Line: TncLine;
+ j: Integer;
+begin
+ ReadySocketsHigh := High(ReadySockets);
+
+ // First accept new lines
+ i := 0;
+ while i <= ReadySocketsHigh do
+ begin
+ try
+ if ReadySockets[i] = FServerSocket.Listener.Handle then
+ begin
+ // New line is here, accept it and create a new TncLine object
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Exit;
+ end;
+ FServerSocket.Lines.Add(TncLineInternal(FServerSocket.Listener).AcceptLine);
+
+ Delete(ReadySockets, i, 1);
+ ReadySocketsHigh := ReadySocketsHigh - 1;
+ i := i - 1;
+ end;
+ except
+ end;
+ i := i + 1;
+ end;
+
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Exit;
+ end;
+
+ // Check for new data
+ DataSockets := FServerSocket.Lines.FList;
+ for i := 0 to ReadySocketsHigh do
+ try
+ LineNdx := DataSockets.IndexOf(ReadySockets[i]);
+ if LineNdx = -1 then
+ begin
+ for j := 0 to High(FServerSocket.ReadSocketHandles) do
+ if FServerSocket.ReadSocketHandles[j] = ReadySockets[i] then
+ begin
+ FServerSocket.ReadSocketHandles[j] := FServerSocket.ReadSocketHandles[High(FServerSocket.ReadSocketHandles)];
+ SetLength(FServerSocket.ReadSocketHandles, Length(FServerSocket.ReadSocketHandles) - 1);
+ Break;
+ end;
+ Continue;
+ end;
+ Line := DataSockets.Lines[LineNdx];
+ try
+ if not Line.Active then
+ Abort;
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Exit;
+ end;
+ BufRead := FServerSocket.ReceiveTLS(Line, FServerSocket.ReadBuf[0], Length(FServerSocket.ReadBuf));
+ if Assigned(FServerSocket.OnReadData) and (BufRead > 0) then
+ FServerSocket.OnReadData(FServerSocket, Line, FServerSocket.ReadBuf, BufRead);
+ except
+ // Line has disconnected, destroy the line
+ DataSockets.Delete(LineNdx);
+ Line.Free;
+ end;
+
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Exit;
+ end;
+ except
+ end;
+end;
+
+procedure TncServerProcessor.ProcessEvent;
+begin
+ if FServerSocket.EventsUseMainThread then
+ while FServerSocket.Listener.Active and (not Terminated) do
+ try
+ ReadySockets := Readable(FServerSocket.ReadSocketHandles, 500);
+ Synchronize(SocketProcess);
+ CheckLinesToShutDown;
+ except
+ end
+ else
+ while FServerSocket.Listener.Active and (not Terminated) do
+ try
+ ReadySockets := Readable(FServerSocket.ReadSocketHandles, 500);
+ SocketProcess;
+ CheckLinesToShutDown;
+ except
+ end;
+end;
+
+// Thread Pool Property Implementations (from ncSources)
+function TncTCPBaseDual.GetCommandProcessorThreadPriority: TncThreadPriority;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCommandProcessorThreadPriority;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCommandProcessorThreadPriority(const Value: TncThreadPriority);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCommandProcessorThreadPriority := Value;
+ if not(csLoading in ComponentState) then
+ HandleCommandThreadPool.SetThreadPriority(Value);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetCommandProcessorThreads: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCommandProcessorThreads;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCommandProcessorThreads(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCommandProcessorThreads := Value;
+ if Value <> 0 then
+ FCommandProcessorThreadsPerCPU := 0;
+
+ if not(csLoading in ComponentState) then
+ HandleCommandThreadPool.SetExecThreads(Max(1, Max(FCommandProcessorThreads, GetNumberOfProcessors * FCommandProcessorThreadsPerCPU)),
+ FCommandProcessorThreadPriority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetCommandProcessorThreadsPerCPU: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCommandProcessorThreadsPerCPU;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCommandProcessorThreadsPerCPU(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCommandProcessorThreadsPerCPU := Value;
+ if Value <> 0 then
+ FCommandProcessorThreads := 0;
+
+ if not(csLoading in ComponentState) then
+ HandleCommandThreadPool.SetExecThreads(Max(1, Max(FCommandProcessorThreads, GetNumberOfProcessors * FCommandProcessorThreadsPerCPU)),
+ FCommandProcessorThreadPriority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncTCPBaseDual.GetCommandProcessorThreadsGrowUpto: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FCommandProcessorThreadsGrowUpto;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncTCPBaseDual.SetCommandProcessorThreadsGrowUpto(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FCommandProcessorThreadsGrowUpto := Value;
+ if not(csLoading in ComponentState) then
+ HandleCommandThreadPool.GrowUpto := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+{ THandleCommandThread }
+
+procedure THandleCommandThread.CallOnCommandEvent;
+begin
+ if Assigned(FOnCommand) then
+ try
+ FOnCommand(FSource, FLine, FCmd, FData);
+ except
+ // Swallow exceptions in worker thread to prevent thread termination
+ end;
+end;
+
+procedure THandleCommandThread.ProcessEvent;
+begin
+ if FEventsUseMainThread then
+ Synchronize(CallOnCommandEvent)
+ else
+ CallOnCommandEvent;
+end;
+
+
+end.
+
+
+
diff --git a/Source/ncSocketsThd.pas b/Source/ncSocketsThd.pas
new file mode 100644
index 0000000..b04c60b
--- /dev/null
+++ b/Source/ncSocketsThd.pas
@@ -0,0 +1,942 @@
+unit ncSocketsThd;
+
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 Package - Threaded Socket Components
+//
+// This unit creates TncTCPServerThd and TncTCPClientThd components that provide
+// raw socket functionality with thread pool processing for received data.
+//
+// Unlike TncSourceBase which is limited to command protocol processing,
+// these components allow custom protocol handling while still benefiting
+// from the thread pool architecture for performance.
+//
+// Component Architecture:
+// - TncTCPServerThd: Raw TCP server with thread pool data processing
+// - TncTCPClientThd: Raw TCP client with thread pool data processing
+// - TncSocketBase: Base class with common thread pool functionality
+// - TDataProcessingThread: Worker thread for processing raw data
+//
+// Key Features:
+// - Raw socket data processing with thread pool
+// - Reader threads for network I/O (non-blocking)
+// - Processing threads for data handling (OnReadData event)
+// - Component composition pattern wrapping TncTCPServer/TncTCPClient
+// - All socket properties delegated to underlying components
+// - TLS/SSL support through SChannel integration (Windows)
+//
+// Architecture:
+// Network Data -> Reader Thread -> Processing Thread Pool -> OnReadData Event
+//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 13/07/2025 - by J.Pauwels
+// - Added TLS/SSL support through SChannel integration
+// - Added TLS properties (UseTLS, TlsProvider, CertificateFile)
+// - Integrated secure communication capabilities for both server and client
+//
+// 12/07/2025 - by J.Pauwels
+// - Initial creation
+//
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+// To disable as much of RTTI as possible (Delphi 2009/2010),
+// Note: There is a bug if $RTTI is used before the "unit ;" section of a unit, hence the position
+{$IF CompilerVersion >= 21.0}
+{$WEAKLINKRTTI ON}
+{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
+{$ENDIF}
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ Winapi.Windows, Winapi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, System.SyncObjs, System.Math,
+ System.Diagnostics, System.TimeSpan, System.RTLConsts, System.Types,
+ ncLines, ncSocketList, ncThreads, ncSockets;
+
+type
+ // Event type for raw data processing
+ TncOnServerReadData = procedure(
+ Sender: TObject;
+ aLine: TncLine;
+ const aBuf: TBytes;
+ aBufCount: Integer) of object;
+
+ TncOnServerConnectDisconnect = procedure(
+ Sender: TObject;
+ aLine: TncLine) of object;
+
+ TncOnServerReconnected = procedure(
+ Sender: TObject;
+ aLine: TncLine) of object;
+
+const
+ DefDataProcessorThreadPriority = ntpNormal;
+ DefDataProcessorThreads = 0;
+ DefDataProcessorThreadsPerCPU = 4;
+ DefDataProcessorThreadsGrowUpto = 32;
+ DefServerEventsUseMainThread = False;
+
+type
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // TncSocketBase
+ // Base class for TncTCPServerThd and TncTCPClientThd providing thread pool data processing
+ // Copies the TncSourceBase pattern but for raw data instead of commands
+
+ TncSocketBase = class(TComponent)
+ private
+ FDataProcessorThreadPriority: TncThreadPriority;
+ FDataProcessorThreads: Integer;
+ FDataProcessorThreadsPerCPU: Integer;
+ FDataProcessorThreadsGrowUpto: Integer;
+ FEventsUseMainThread: Boolean;
+
+ FOnConnected: TncOnServerConnectDisconnect;
+ FOnDisconnected: TncOnServerConnectDisconnect;
+ FOnReconnected: TncOnServerReconnected;
+ FOnReadData: TncOnServerReadData;
+
+ // Socket property delegation getters/setters
+ function GetActive: Boolean;
+ procedure SetActive(const Value: Boolean);
+ function GetKeepAlive: Boolean;
+ procedure SetKeepAlive(const Value: Boolean);
+ function GetNoDelay: Boolean;
+ procedure SetNoDelay(const Value: Boolean);
+ function GetPort: Integer;
+ procedure SetPort(const Value: Integer);
+ function GetReaderThreadPriority: TncThreadPriority;
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+ function GetReadBufferLen: Integer;
+ procedure SetReadBufferLen(const Value: Integer);
+ function GetUseReaderThread: Boolean;
+ procedure SetUseReaderThread(const Value: Boolean);
+ function GetUseTLS: Boolean;
+ procedure SetUseTLS(const Value: Boolean);
+ function GetTlsProvider: TncTlsProvider;
+ procedure SetTlsProvider(const Value: TncTlsProvider);
+ function GetCertificateFile: string;
+ procedure SetCertificateFile(const Value: string);
+ function GetIgnoreCertificateErrors: Boolean;
+ procedure SetIgnoreCertificateErrors(const Value: Boolean);
+ function GetPrivateKeyPassword: string;
+ procedure SetPrivateKeyPassword(const Value: string);
+
+ // Thread pool property getters/setters
+ function GetDataProcessorThreadPriority: TncThreadPriority;
+ procedure SetDataProcessorThreadPriority(const Value: TncThreadPriority);
+ function GetDataProcessorThreads: Integer;
+ procedure SetDataProcessorThreads(const Value: Integer);
+ function GetDataProcessorThreadsPerCPU: Integer;
+ procedure SetDataProcessorThreadsPerCPU(const Value: Integer);
+ function GetDataProcessorThreadsGrowUpto: Integer;
+ procedure SetDataProcessorThreadsGrowUpto(const Value: Integer);
+ function GetEventsUseMainThread: Boolean;
+ procedure SetEventsUseMainThread(const Value: Boolean);
+ private
+ // To set the component active on loaded if was set at design time
+ WasSetActive: Boolean;
+ WithinConnectionHandler: Boolean;
+ protected
+ PropertyLock: TObject; // TMonitor synchronization object
+ DataProcessorThreadPool: TncThreadPool;
+ Socket: TncTCPBase;
+
+ LastConnectedLine, LastDisconnectedLine, LastReconnectedLine: TncLine;
+
+ procedure Loaded; override;
+ procedure TLSHandshakeWrapper(aLine: TncLine);
+ procedure CallConnectedEvents;
+ procedure SocketConnected(Sender: TObject; aLine: TncLine);
+ procedure CallDisconnectedEvents;
+ procedure SocketDisconnected(Sender: TObject; aLine: TncLine);
+ procedure CallReconnectedEvents;
+ procedure SocketReconnected(Sender: TObject; aLine: TncLine);
+ procedure SocketReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ function GetThreadPoolThreadCount: Integer;
+ function GetThreadPoolActiveThreadCount: Integer;
+ published
+ // Socket properties (delegated to underlying socket)
+ property Active: Boolean read GetActive write SetActive default False;
+ property Port: Integer read GetPort write SetPort default DefPort;
+ property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
+ property NoDelay: Boolean read GetNoDelay write SetNoDelay default DefNoDelay;
+ property KeepAlive: Boolean read GetKeepAlive write SetKeepAlive default DefKeepAlive;
+ property Family: TAddressType read GetFamily write SetFamily default DefFamily;
+ property ReadBufferLen: Integer read GetReadBufferLen write SetReadBufferLen default DefReadBufferLen;
+ property UseReaderThread: Boolean read GetUseReaderThread write SetUseReaderThread default DefUseReaderThread;
+ property UseTLS: Boolean read GetUseTLS write SetUseTLS default False;
+ property TlsProvider: TncTlsProvider read GetTlsProvider write SetTlsProvider default DefTlsProvider;
+ property CertificateFile: string read GetCertificateFile write SetCertificateFile;
+ property IgnoreCertificateErrors: Boolean read GetIgnoreCertificateErrors write SetIgnoreCertificateErrors default DefIgnoreCertificateErrors;
+ property PrivateKeyPassword: string read GetPrivateKeyPassword write SetPrivateKeyPassword;
+
+ // Thread pool properties
+ property DataProcessorThreadPriority: TncThreadPriority read GetDataProcessorThreadPriority write SetDataProcessorThreadPriority default DefDataProcessorThreadPriority;
+ property DataProcessorThreads: Integer read GetDataProcessorThreads write SetDataProcessorThreads default DefDataProcessorThreads;
+ property DataProcessorThreadsPerCPU: Integer read GetDataProcessorThreadsPerCPU write SetDataProcessorThreadsPerCPU default DefDataProcessorThreadsPerCPU;
+ property DataProcessorThreadsGrowUpto: Integer read GetDataProcessorThreadsGrowUpto write SetDataProcessorThreadsGrowUpto default DefDataProcessorThreadsGrowUpto;
+ property EventsUseMainThread: Boolean read GetEventsUseMainThread write SetEventsUseMainThread default DefServerEventsUseMainThread;
+
+ // Events
+ property OnConnected: TncOnServerConnectDisconnect read FOnConnected write FOnConnected;
+ property OnDisconnected: TncOnServerConnectDisconnect read FOnDisconnected write FOnDisconnected;
+ property OnReadData: TncOnServerReadData read FOnReadData write FOnReadData;
+ end;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // TDataProcessingThread
+ // Worker thread that processes raw data from the thread pool
+ // Copies the THandleCommandThread pattern for consistency
+
+ TDataProcessingThread = class(TncReadyThread)
+ public
+ OnReadData: TncOnServerReadData;
+ Server: TncSocketBase;
+ Line: TncLine;
+ Buffer: TBytes;
+ BufferCount: Integer;
+
+ procedure CallOnReadDataEvent;
+ procedure ProcessEvent; override;
+ end;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // TncTCPServerThd
+ // Server component providing raw socket functionality with thread pool processing
+
+ TncTCPServerThd = class(TncSocketBase)
+ private
+ function GetLines: TThreadLineList;
+ protected
+ function GetReaderThreadPriority: TncThreadPriority; // Override to access server-specific property
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority); // Override to access server-specific property
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ procedure Send(aLine: TncLine; const aBuf; aBufSize: Integer); overload; inline;
+ procedure Send(aLine: TncLine; const aBytes: TBytes); overload; inline;
+ procedure Send(aLine: TncLine; const aStr: string); overload; inline;
+ procedure ShutDownLine(aLine: TncLine);
+ property Lines: TThreadLineList read GetLines;
+ published
+ // Inherited properties from TncSocketBase
+ property Active;
+ property Port;
+ property ReaderThreadPriority;
+ property NoDelay;
+ property KeepAlive;
+ property Family;
+ property ReadBufferLen;
+ property UseReaderThread;
+ property UseTLS;
+ property TlsProvider;
+ property CertificateFile;
+ property IgnoreCertificateErrors;
+ property PrivateKeyPassword;
+ property DataProcessorThreadPriority;
+ property DataProcessorThreads;
+ property DataProcessorThreadsPerCPU;
+ property DataProcessorThreadsGrowUpto;
+ property EventsUseMainThread;
+ property OnConnected;
+ property OnDisconnected;
+ property OnReadData;
+ end;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // TncTCPClientThd
+ // Client component providing raw socket functionality with thread pool processing
+
+ TncTCPClientThd = class(TncSocketBase)
+ private
+ FOnReconnected: TncOnServerReconnected;
+ function GetHost: string;
+ procedure SetHost(const Value: string);
+ function GetReconnect: Boolean;
+ procedure SetReconnect(const Value: Boolean);
+ function GetReconnectInterval: Cardinal;
+ procedure SetReconnectInterval(const Value: Cardinal);
+ function GetLine: TncLine;
+ protected
+ function GetReaderThreadPriority: TncThreadPriority; // Override to access client-specific property
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority); // Override to access client-specific property
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ procedure Send(const aBuf; aBufSize: Integer); overload; inline;
+ procedure Send(const aBytes: TBytes); overload; inline;
+ procedure Send(const aStr: string); overload; inline;
+ function Receive(aTimeout: Cardinal = 2000): TBytes; inline;
+ function ReceiveRaw(var aBytes: TBytes): Integer; inline;
+
+ property Line: TncLine read GetLine;
+ published
+ // Inherited properties from TncSocketBase
+ property Active;
+ property Port;
+ property ReaderThreadPriority;
+ property NoDelay;
+ property KeepAlive;
+ property Family;
+ property ReadBufferLen;
+ property UseReaderThread;
+ property UseTLS;
+ property TlsProvider;
+ property CertificateFile;
+ property IgnoreCertificateErrors;
+ property PrivateKeyPassword;
+ property DataProcessorThreadPriority;
+ property DataProcessorThreads;
+ property DataProcessorThreadsPerCPU;
+ property DataProcessorThreadsGrowUpto;
+ property EventsUseMainThread;
+ property OnConnected;
+ property OnDisconnected;
+ property OnReadData;
+
+ // Client-specific properties
+ property Host: string read GetHost write SetHost;
+ property Reconnect: Boolean read GetReconnect write SetReconnect default True;
+ property ReconnectInterval: Cardinal read GetReconnectInterval write SetReconnectInterval default DefCntReconnectInterval;
+ property OnReconnected: TncOnServerReconnected read FOnReconnected write FOnReconnected;
+ end;
+
+implementation
+
+uses
+ System.TypInfo;
+
+type
+ // Friend class declarations to access protected members
+ TncLineInternal = class(TncLine);
+ TncTCPBaseInternal = class(TncTCPBase);
+ TncCustomTCPServerInternal = class(TncCustomTCPServer);
+ TncTCPServerInternal = class(TncTCPServer);
+
+{ TncDataProcessingThread }
+
+procedure TDataProcessingThread.CallOnReadDataEvent;
+begin
+ if Assigned(OnReadData) then
+ try
+ OnReadData(Server, Line, Buffer, BufferCount);
+ except
+ // Swallow exceptions to prevent thread termination
+ end;
+end;
+
+procedure TDataProcessingThread.ProcessEvent;
+begin
+ if Server.EventsUseMainThread then
+ Synchronize(CallOnReadDataEvent)
+ else
+ CallOnReadDataEvent;
+end;
+
+// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncSocketBase }
+// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncSocketBase.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ PropertyLock := TObject.Create;
+
+ Socket := nil;
+ WasSetActive := False;
+ WithinConnectionHandler := False;
+
+ FDataProcessorThreadPriority := DefDataProcessorThreadPriority;
+ FDataProcessorThreads := DefDataProcessorThreads;
+ FDataProcessorThreadsPerCPU := DefDataProcessorThreadsPerCPU;
+ FDataProcessorThreadsGrowUpto := DefDataProcessorThreadsGrowUpto;
+ FEventsUseMainThread := DefServerEventsUseMainThread;
+
+ FOnConnected := nil;
+ FOnDisconnected := nil;
+ FOnReconnected := nil;
+ FOnReadData := nil;
+
+ DataProcessorThreadPool := TncThreadPool.Create(TDataProcessingThread);
+end;
+
+destructor TncSocketBase.Destroy;
+begin
+ DataProcessorThreadPool.Free;
+ PropertyLock.Free;
+ inherited Destroy;
+end;
+
+function TncSocketBase.GetThreadPoolThreadCount: Integer;
+begin
+ Result := DataProcessorThreadPool.GetThreadCount;
+end;
+
+function TncSocketBase.GetThreadPoolActiveThreadCount: Integer;
+begin
+ Result := DataProcessorThreadPool.GetActiveThreadCount;
+end;
+
+procedure TncSocketBase.Loaded;
+begin
+ inherited Loaded;
+
+ DataProcessorThreadPool.SetThreadPriority(FDataProcessorThreadPriority);
+ DataProcessorThreadPool.SetExecThreads(
+ Max(1, Max(FDataProcessorThreads, GetNumberOfProcessors * FDataProcessorThreadsPerCPU)),
+ FDataProcessorThreadPriority);
+
+ if WasSetActive then
+ Socket.Active := True;
+end;
+
+procedure TncSocketBase.CallConnectedEvents;
+begin
+ WithinConnectionHandler := True;
+ try
+ if Assigned(OnConnected) then
+ OnConnected(Self, LastConnectedLine);
+ finally
+ WithinConnectionHandler := False;
+ end;
+end;
+
+procedure TncSocketBase.SocketConnected(Sender: TObject; aLine: TncLine);
+begin
+ LastConnectedLine := aLine;
+ if EventsUseMainThread then
+ Socket.LineProcessor.Synchronize(Socket.LineProcessor, CallConnectedEvents)
+ else
+ CallConnectedEvents;
+end;
+
+procedure TncSocketBase.CallDisconnectedEvents;
+begin
+ WithinConnectionHandler := True;
+ try
+ if Assigned(OnDisconnected) then
+ try
+ OnDisconnected(Self, LastDisconnectedLine);
+ except
+ end;
+ finally
+ WithinConnectionHandler := False;
+ end;
+end;
+
+procedure TncSocketBase.SocketDisconnected(Sender: TObject; aLine: TncLine);
+begin
+ LastDisconnectedLine := aLine;
+ if EventsUseMainThread then
+ Socket.LineProcessor.Synchronize(Socket.LineProcessor, CallDisconnectedEvents)
+ else
+ CallDisconnectedEvents;
+end;
+
+procedure TncSocketBase.CallReconnectedEvents;
+begin
+ WithinConnectionHandler := True;
+ try
+ if Assigned(TncTCPClientThd(Self).OnReconnected) then
+ try
+ TncTCPClientThd(Self).OnReconnected(Self, LastReconnectedLine);
+ except
+ end;
+ finally
+ WithinConnectionHandler := False;
+ end;
+end;
+
+procedure TncSocketBase.SocketReconnected(Sender: TObject; aLine: TncLine);
+begin
+ LastReconnectedLine := aLine;
+ if EventsUseMainThread then
+ Socket.LineProcessor.Synchronize(Socket.LineProcessor, CallReconnectedEvents)
+ else
+ CallReconnectedEvents;
+end;
+
+// This is the key method - it queues raw data processing to the thread pool
+procedure TncSocketBase.SocketReadData(Sender: TObject; aLine: TncLine; const aBuf: TBytes; aBufCount: Integer);
+var
+ DataProcessingThread: TDataProcessingThread;
+begin
+ // The base socket handles TLS handshake internally and only fires OnReadData for application data
+ // So we can safely queue all data to the thread pool
+ if Assigned(OnReadData) then
+ begin
+ TMonitor.Enter(DataProcessorThreadPool);
+ try
+ DataProcessingThread := TDataProcessingThread(DataProcessorThreadPool.RequestReadyThread);
+ DataProcessingThread.OnReadData := OnReadData;
+ DataProcessingThread.Server := Self;
+ DataProcessingThread.Line := aLine;
+ DataProcessingThread.Buffer := Copy(aBuf, 0, aBufCount); // Copy the buffer to avoid race conditions
+ DataProcessingThread.BufferCount := aBufCount;
+ DataProcessorThreadPool.RunRequestedThread(DataProcessingThread);
+ finally
+ TMonitor.Exit(DataProcessorThreadPool);
+ end;
+ end;
+end;
+
+// Socket property delegation methods
+function TncSocketBase.GetActive: Boolean;
+begin
+ Result := Socket.Active;
+end;
+
+procedure TncSocketBase.SetActive(const Value: Boolean);
+begin
+ if csLoading in ComponentState then
+ WasSetActive := Value
+ else
+ Socket.Active := Value;
+end;
+
+function TncSocketBase.GetFamily: TAddressType;
+begin
+ Result := Socket.Family;
+end;
+
+procedure TncSocketBase.SetFamily(const Value: TAddressType);
+begin
+ Socket.Family := Value;
+end;
+
+function TncSocketBase.GetKeepAlive: Boolean;
+begin
+ Result := Socket.KeepAlive;
+end;
+
+procedure TncSocketBase.SetKeepAlive(const Value: Boolean);
+begin
+ Socket.KeepAlive := Value;
+end;
+
+function TncSocketBase.GetNoDelay: Boolean;
+begin
+ Result := Socket.NoDelay;
+end;
+
+procedure TncSocketBase.SetNoDelay(const Value: Boolean);
+begin
+ Socket.NoDelay := Value;
+end;
+
+function TncSocketBase.GetPort: Integer;
+begin
+ Result := Socket.Port;
+end;
+
+procedure TncSocketBase.SetPort(const Value: Integer);
+begin
+ Socket.Port := Value;
+end;
+
+function TncSocketBase.GetReaderThreadPriority: TncThreadPriority;
+begin
+ Result := Socket.ReaderThreadPriority;
+end;
+
+procedure TncSocketBase.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ Socket.ReaderThreadPriority := Value;
+end;
+
+function TncSocketBase.GetReadBufferLen: Integer;
+begin
+ Result := Socket.ReadBufferLen;
+end;
+
+procedure TncSocketBase.SetReadBufferLen(const Value: Integer);
+begin
+ Socket.ReadBufferLen := Value;
+end;
+
+function TncSocketBase.GetUseReaderThread: Boolean;
+begin
+ Result := Socket.UseReaderThread;
+end;
+
+procedure TncSocketBase.SetUseReaderThread(const Value: Boolean);
+begin
+ Socket.UseReaderThread := Value;
+end;
+
+function TncSocketBase.GetUseTLS: Boolean;
+begin
+ Result := Socket.UseTLS;
+end;
+
+procedure TncSocketBase.SetUseTLS(const Value: Boolean);
+begin
+ Socket.UseTLS := Value;
+
+ // Set up TLS handshake callback if Line objects already exist
+ // The underlying ncSockets components will handle TLS setup during Line creation
+ if Value then
+ begin
+ if Socket is TncTCPClient then
+ begin
+ var Client := TncTCPClient(Socket);
+ if Client.Line <> nil then
+ begin
+ TncLineInternal(Client.Line).OnBeforeConnected := TLSHandshakeWrapper;
+ end;
+ // If Line doesn't exist yet, it will be set up automatically when Line is created
+ end
+ else if Socket is TncTCPServer then
+ begin
+ var Server := TncTCPServer(Socket);
+ if TncTCPServerInternal(Server).Listener <> nil then
+ begin
+ TncLineInternal(TncTCPServerInternal(Server).Listener).OnBeforeConnected := TLSHandshakeWrapper;
+ end;
+ end;
+ end;
+end;
+
+function TncSocketBase.GetTlsProvider: TncTlsProvider;
+begin
+ Result := Socket.TlsProvider;
+end;
+
+procedure TncSocketBase.SetTlsProvider(const Value: TncTlsProvider);
+begin
+ Socket.TlsProvider := Value;
+end;
+
+function TncSocketBase.GetCertificateFile: string;
+begin
+ Result := Socket.CertificateFile;
+end;
+
+procedure TncSocketBase.SetCertificateFile(const Value: string);
+begin
+ Socket.CertificateFile := Value;
+end;
+
+function TncSocketBase.GetIgnoreCertificateErrors: Boolean;
+begin
+ Result := Socket.IgnoreCertificateErrors;
+end;
+
+procedure TncSocketBase.SetIgnoreCertificateErrors(const Value: Boolean);
+begin
+ Socket.IgnoreCertificateErrors := Value;
+end;
+
+function TncSocketBase.GetPrivateKeyPassword: string;
+begin
+ Result := Socket.PrivateKeyPassword;
+end;
+
+procedure TncSocketBase.SetPrivateKeyPassword(const Value: string);
+begin
+ Socket.PrivateKeyPassword := Value;
+end;
+
+// Thread pool property methods
+function TncSocketBase.GetDataProcessorThreadPriority: TncThreadPriority;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FDataProcessorThreadPriority;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncSocketBase.SetDataProcessorThreadPriority(const Value: TncThreadPriority);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FDataProcessorThreadPriority := Value;
+ if not (csLoading in ComponentState) then
+ DataProcessorThreadPool.SetThreadPriority(Value);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncSocketBase.GetDataProcessorThreads: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FDataProcessorThreads;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncSocketBase.SetDataProcessorThreads(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FDataProcessorThreads := Value;
+ if Value <> 0 then
+ FDataProcessorThreadsPerCPU := 0;
+
+ if not (csLoading in ComponentState) then
+ DataProcessorThreadPool.SetExecThreads(
+ Max(1, Max(FDataProcessorThreads, GetNumberOfProcessors * FDataProcessorThreadsPerCPU)),
+ FDataProcessorThreadPriority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncSocketBase.GetDataProcessorThreadsPerCPU: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FDataProcessorThreadsPerCPU;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncSocketBase.SetDataProcessorThreadsPerCPU(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FDataProcessorThreadsPerCPU := Value;
+ if Value <> 0 then
+ FDataProcessorThreads := 0;
+
+ if not (csLoading in ComponentState) then
+ DataProcessorThreadPool.SetExecThreads(
+ Max(1, Max(FDataProcessorThreads, GetNumberOfProcessors * FDataProcessorThreadsPerCPU)),
+ FDataProcessorThreadPriority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncSocketBase.GetDataProcessorThreadsGrowUpto: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FDataProcessorThreadsGrowUpto;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncSocketBase.SetDataProcessorThreadsGrowUpto(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FDataProcessorThreadsGrowUpto := Value;
+ if not (csLoading in ComponentState) then
+ DataProcessorThreadPool.GrowUpto := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncSocketBase.GetEventsUseMainThread: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FEventsUseMainThread;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncSocketBase.SetEventsUseMainThread(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FEventsUseMainThread := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncSocketBase.TLSHandshakeWrapper(aLine: TncLine);
+begin
+ TncTCPBaseInternal(Socket).HandleTLSHandshake(aLine);
+end;
+
+
+// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncTCPServerThd }
+// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncTCPServerThd.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ // Create the underlying TCP server socket
+ Socket := TncTCPServer.Create(Self);
+ Socket.Family := afIPv4;
+ Socket.Port := DefPort;
+ Socket.NoDelay := DefNoDelay;
+ Socket.EventsUseMainThread := False;
+ Socket.OnConnected := SocketConnected;
+ Socket.OnDisconnected := SocketDisconnected;
+ Socket.OnReadData := SocketReadData;
+end;
+
+destructor TncTCPServerThd.Destroy;
+begin
+ Socket.Free;
+ inherited Destroy;
+end;
+
+function TncTCPServerThd.GetLines: TThreadLineList;
+begin
+ Result := TncTCPServer(Socket).Lines;
+end;
+
+procedure TncTCPServerThd.Send(aLine: TncLine; const aBuf; aBufSize: Integer);
+begin
+ TncTCPServer(Socket).Send(aLine, aBuf, aBufSize);
+end;
+
+procedure TncTCPServerThd.Send(aLine: TncLine; const aBytes: TBytes);
+begin
+ TncTCPServer(Socket).Send(aLine, aBytes);
+end;
+
+procedure TncTCPServerThd.Send(aLine: TncLine; const aStr: string);
+begin
+ TncTCPServer(Socket).Send(aLine, aStr);
+end;
+
+procedure TncTCPServerThd.ShutDownLine(aLine: TncLine);
+begin
+ TncTCPServer(Socket).ShutDownLine(aLine);
+end;
+
+// Override to access server-specific property
+function TncTCPServerThd.GetReaderThreadPriority: TncThreadPriority;
+begin
+ Result := TncTCPServer(Socket).ReaderThreadPriority;
+end;
+
+procedure TncTCPServerThd.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ TncTCPServer(Socket).ReaderThreadPriority := Value;
+end;
+
+// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{ TncTCPClientThd }
+// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+constructor TncTCPClientThd.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ Socket := TncTCPClient.Create(Self);
+ Socket.Family := afIPv4;
+ Socket.Port := DefPort;
+ Socket.NoDelay := DefNoDelay;
+ Socket.EventsUseMainThread := False;
+ Socket.OnConnected := SocketConnected;
+ Socket.OnDisconnected := SocketDisconnected;
+ Socket.OnReadData := SocketReadData;
+ TncTCPClient(Socket).OnReconnected := SocketReconnected;
+end;
+
+destructor TncTCPClientThd.Destroy;
+begin
+ Socket.Free;
+ inherited Destroy;
+end;
+
+function TncTCPClientThd.GetLine: TncLine;
+begin
+ Result := TncTCPClient(Socket).Line;
+end;
+
+procedure TncTCPClientThd.Send(const aBuf; aBufSize: Integer);
+begin
+ TncTCPClient(Socket).Send(aBuf, aBufSize);
+end;
+
+procedure TncTCPClientThd.Send(const aBytes: TBytes);
+begin
+ TncTCPClient(Socket).Send(aBytes);
+end;
+
+procedure TncTCPClientThd.Send(const aStr: string);
+begin
+ TncTCPClient(Socket).Send(aStr);
+end;
+
+function TncTCPClientThd.Receive(aTimeout: Cardinal = 2000): TBytes;
+begin
+ Result := TncTCPClient(Socket).Receive(aTimeout);
+end;
+
+function TncTCPClientThd.ReceiveRaw(var aBytes: TBytes): Integer;
+begin
+ Result := TncTCPClient(Socket).ReceiveRaw(aBytes);
+end;
+
+function TncTCPClientThd.GetHost: string;
+begin
+ Result := TncTCPClient(Socket).Host;
+end;
+
+procedure TncTCPClientThd.SetHost(const Value: string);
+begin
+ TncTCPClient(Socket).Host := Value;
+end;
+
+function TncTCPClientThd.GetReconnect: Boolean;
+begin
+ Result := TncTCPClient(Socket).Reconnect;
+end;
+
+procedure TncTCPClientThd.SetReconnect(const Value: Boolean);
+begin
+ TncTCPClient(Socket).Reconnect := Value;
+end;
+
+function TncTCPClientThd.GetReconnectInterval: Cardinal;
+begin
+ Result := TncTCPClient(Socket).ReconnectInterval;
+end;
+
+procedure TncTCPClientThd.SetReconnectInterval(const Value: Cardinal);
+begin
+ TncTCPClient(Socket).ReconnectInterval := Value;
+end;
+
+// Override to access client-specific property
+function TncTCPClientThd.GetReaderThreadPriority: TncThreadPriority;
+begin
+ Result := TncTCPClient(Socket).ReaderThreadPriority;
+end;
+
+procedure TncTCPClientThd.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ TncTCPClient(Socket).ReaderThreadPriority := Value;
+end;
+
+end.
+
diff --git a/Source/ncSources.pas b/Source/ncSources.pas
index 4029540..c96509a 100644
--- a/Source/ncSources.pas
+++ b/Source/ncSources.pas
@@ -25,6 +25,13 @@
// These components have built in encryption and compression, set by the
// corresponding properties.
//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 14/01/2025 - by J.Pauwels
+// - Explicitly set this unit to use TCP
+// - Added IPV6 support
+//
// 12/8/2020
// - Complete re-engineering of the base component
//
@@ -184,6 +191,9 @@ TncSourceBase = class(TComponent, IncCommandHandler)
function GetReaderThreadPriority: TncThreadPriority;
procedure SetReaderThreadPriority(const Value: TncThreadPriority);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+
// For implementing the IncCommandHandler interface
function GetComponentName: string;
function GetOnConnected: TncOnSourceConnectDisconnect;
@@ -221,12 +231,12 @@ TncSourceBase = class(TComponent, IncCommandHandler)
WasSetActive: Boolean;
WithinConnectionHandler: Boolean;
protected
- PropertyLock: TCriticalSection;
+ PropertyLock: TObject; // TMonitor synchronization object
CommandHandlers: array of IncCommandHandler;
UniqueSentID: TncCommandUniqueID;
HandleCommandThreadPool: TncThreadPool;
Socket: TncTCPBase;
- ExecuteSerialiser: TCriticalSection;
+ ExecuteSerialiser: TObject; // TMonitor synchronization object
LastConnectedLine, LastDisconnectedLine, LastReconnectedLine: TncLine;
@@ -264,6 +274,7 @@ TncSourceBase = class(TComponent, IncCommandHandler)
property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
property NoDelay: Boolean read GetNoDelay write SetNoDelay default True;
property KeepAlive: Boolean read GetKeepAlive write SetKeepAlive default True;
+ property Family: TAddressType read GetFamily write SetFamily default afIPv4;
// New properties for sources
property CommandProcessorThreadPriority: TncThreadPriority read GetCommandProcessorThreadPriority write SetCommandProcessorThreadPriority
@@ -365,6 +376,7 @@ constructor TncSourceLine.Create;
function TncSourceLine.CreateLineObject: TncLine;
begin
Result := TncSourceLine.Create; // Create its own kind of objects
+ TncSourceLine(Result).SetKind(stTCP); // Explicitly set to TCP
end;
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -375,8 +387,8 @@ constructor TncSourceBase.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
- PropertyLock := TCriticalSection.Create;
- ExecuteSerialiser := TCriticalSection.Create;
+ PropertyLock := TObject.Create;
+ ExecuteSerialiser := TObject.Create;
Socket := nil;
WasSetActive := False;
@@ -596,7 +608,7 @@ function TncSourceBase.ExecCommand(
PendingNdx: Integer;
WaitForEventTimeout: Integer;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
IDSent := UniqueSentID;
@@ -636,7 +648,7 @@ function TncSourceBase.ExecCommand(
Exit; // Nothing more to do
end;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
// We are here because we require a result and this is not an AsyncExecute
@@ -657,7 +669,7 @@ function TncSourceBase.ExecCommand(
// the socket reading is paused, so we need to process it here
if WithinConnectionHandler then
begin
- ExecuteSerialiser.Acquire;
+ TMonitor.Enter(ExecuteSerialiser);
try
if (Socket is TncTCPClient) then
begin
@@ -675,7 +687,7 @@ function TncSourceBase.ExecCommand(
TncServerProcessor(TncTCPServer(Socket).LineProcessor).ReadySocketsChanged := True;
end;
finally
- ExecuteSerialiser.Release;
+ TMonitor.Exit(ExecuteSerialiser);
end;
end;
@@ -683,18 +695,18 @@ function TncSourceBase.ExecCommand(
raise ENetComCommandExecutionTimeout.Create(ENetComCommandExecutionTimeoutMessage);
end;
except
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
PendingCommandsList.Delete(PendingCommandsList.IndexOf(IDSent));
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
raise;
end;
// We are here because we got the result
// Get the result of the command into the result of this function
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
PendingNdx := PendingCommandsList.IndexOf(IDSent);
try
@@ -707,7 +719,7 @@ function TncSourceBase.ExecCommand(
PendingCommandsList.Delete(PendingNdx);
end;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
finally
ReceivedResultEvent.Free; // Event not needed any more
@@ -726,7 +738,7 @@ procedure TncSourceBase.HandleReceivedCommand(aLine: TncSourceLine; const aComma
ctInitiator:
begin
// Handle the command from the thread pool
- HandleCommandThreadPool.Serialiser.Acquire;
+ TMonitor.Enter(HandleCommandThreadPool);
try
HandleCommandThread := THandleCommandThread(HandleCommandThreadPool.RequestReadyThread);
HandleCommandThread.WorkType := htwtOnHandleCommand;
@@ -736,14 +748,14 @@ procedure TncSourceBase.HandleReceivedCommand(aLine: TncSourceLine; const aComma
HandleCommandThread.Command := Command;
HandleCommandThreadPool.RunRequestedThread(HandleCommandThread);
finally
- HandleCommandThreadPool.Serialiser.Release;
+ TMonitor.Exit(HandleCommandThreadPool);
end;
end;
ctResponse:
if Command.AsyncExecute then
begin
// Handle the command from the thread pool
- HandleCommandThreadPool.Serialiser.Acquire;
+ TMonitor.Enter(HandleCommandThreadPool);
try
HandleCommandThread := THandleCommandThread(HandleCommandThreadPool.RequestReadyThread);
HandleCommandThread.WorkType := htwtAsyncResponse;
@@ -753,12 +765,12 @@ procedure TncSourceBase.HandleReceivedCommand(aLine: TncSourceLine; const aComma
HandleCommandThread.Command := Command;
HandleCommandThreadPool.RunRequestedThread(HandleCommandThread);
finally
- HandleCommandThreadPool.Serialiser.Release;
+ TMonitor.Exit(HandleCommandThreadPool);
end;
end
else
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
// Find the event to set from the PendingCommandsList
PendingNdx := PendingCommandsList.IndexOf(Command.UniqueID);
@@ -770,7 +782,7 @@ procedure TncSourceBase.HandleReceivedCommand(aLine: TncSourceLine; const aComma
PendingCommandsList.ReceivedResultEvents[PendingNdx].SetEvent;
end;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
end;
@@ -865,6 +877,16 @@ procedure TncSourceBase.SetActive(const Value: Boolean);
Socket.Active := Value;
end;
+function TncSourceBase.GetFamily: TAddressType;
+begin
+ Result := Socket.Family;
+end;
+
+procedure TncSourceBase.SetFamily(const Value: TAddressType);
+begin
+ Socket.Family := Value;
+end;
+
function TncSourceBase.GetKeepAlive: Boolean;
begin
Result := Socket.KeepAlive;
@@ -907,59 +929,59 @@ procedure TncSourceBase.SetReaderThreadPriority(const Value: TncThreadPriority);
function TncSourceBase.GetExecCommandTimeout: Cardinal;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCommandExecTimeout;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetExecCommandTimeout(const Value: Cardinal);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCommandExecTimeout := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetCommandProcessorThreadPriority: TncThreadPriority;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCommandProcessorThreadPriority;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetCommandProcessorThreadPriority(const Value: TncThreadPriority);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCommandProcessorThreadPriority := Value;
if not(csLoading in ComponentState) then
HandleCommandThreadPool.SetThreadPriority(Value);
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetCommandProcessorThreads: Integer;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCommandProcessorThreads;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetCommandProcessorThreads(const Value: Integer);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCommandProcessorThreads := Value;
if Value <> 0 then
@@ -969,23 +991,23 @@ procedure TncSourceBase.SetCommandProcessorThreads(const Value: Integer);
HandleCommandThreadPool.SetExecThreads(Max(1, Max(FCommandProcessorThreads, GetNumberOfProcessors * FCommandProcessorThreadsPerCPU)),
FCommandProcessorThreadPriority);
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetCommandProcessorThreadsPerCPU: Integer;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCommandProcessorThreadsPerCPU;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetCommandProcessorThreadsPerCPU(const Value: Integer);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCommandProcessorThreadsPerCPU := Value;
if Value <> 0 then
@@ -995,128 +1017,128 @@ procedure TncSourceBase.SetCommandProcessorThreadsPerCPU(const Value: Integer);
HandleCommandThreadPool.SetExecThreads(Max(1, Max(FCommandProcessorThreads, GetNumberOfProcessors * FCommandProcessorThreadsPerCPU)),
FCommandProcessorThreadPriority);
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetCommandProcessorThreadsGrowUpto: Integer;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCommandProcessorThreadsGrowUpto;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetCommandProcessorThreadsGrowUpto(const Value: Integer);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCommandProcessorThreadsGrowUpto := Value;
HandleCommandThreadPool.GrowUpto := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetEventsUseMainThread: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FEventsUseMainThread;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetEventsUseMainThread(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FEventsUseMainThread := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetCompression: TZCompressionLevel;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FCompression;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetCompression(const Value: TZCompressionLevel);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FCompression := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetEncryption: TEncryptorType;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FEncryption;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetEncryption(const Value: TEncryptorType);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FEncryption := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetEncryptionKey: AnsiString;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FEncryptionKey;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetEncryptionKey(const Value: AnsiString);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FEncryptionKey := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
function TncSourceBase.GetEncryptOnHashedKey: Boolean;
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
Result := FEncryptOnHashedKey;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
procedure TncSourceBase.SetEncryptOnHashedKey(const Value: Boolean);
begin
- PropertyLock.Acquire;
+ TMonitor.Enter(PropertyLock);
try
FEncryptOnHashedKey := Value;
finally
- PropertyLock.Release;
+ TMonitor.Exit(PropertyLock);
end;
end;
@@ -1259,6 +1281,7 @@ TncTCPClientSourceSocket = class(TncTCPClient)
function TncTCPClientSourceSocket.CreateLineObject: TncLine;
begin
Result := TncSourceLine.Create;
+ TncSourceLine(Result).SetKind(stTCP);
end;
constructor TncClientSource.Create(AOwner: TComponent);
@@ -1268,6 +1291,7 @@ constructor TncClientSource.Create(AOwner: TComponent);
FOnReconnected := nil;
Socket := TncTCPClientSourceSocket.Create(nil);
+ Socket.Family := afIPv4; // Set default family
Socket.Port := DefPort;
Socket.NoDelay := DefNoDelay;
Socket.EventsUseMainThread := False;
@@ -1351,6 +1375,7 @@ TncTCPServerSourceSocket = class(TncTCPServer)
function TncTCPServerSourceSocket.CreateLineObject: TncLine;
begin
Result := TncSourceLine.Create;
+ TncSourceLine(Result).SetKind(stTCP);
end;
constructor TncServerSource.Create(AOwner: TComponent);
@@ -1358,6 +1383,7 @@ constructor TncServerSource.Create(AOwner: TComponent);
inherited Create(AOwner);
Socket := TncTCPServerSourceSocket.Create(nil);
+ Socket.Family := afIPv4; // Set default family
Socket.NoDelay := DefNoDelay;
Socket.Port := DefPort;
Socket.EventsUseMainThread := False;
@@ -1383,3 +1409,5 @@ procedure TncServerSource.ShutDownLine(aLine: TncLine);
end;
end.
+
+
diff --git a/Source/ncThreads.pas b/Source/ncThreads.pas
index e733b5c..938feea 100644
--- a/Source/ncThreads.pas
+++ b/Source/ncThreads.pas
@@ -3,6 +3,10 @@
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// NetCom7 Package
+//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
// Written by Demos Bill, 17 Nov 2009
//
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -63,7 +67,6 @@ TncThreadPool = class
protected
Threads: array of TncReadyThread;
public
- Serialiser: TCriticalSection;
constructor Create(aWorkerThreadClass: TncReadyThreadClass);
destructor Destroy; override;
function RequestReadyThread: TncReadyThread;
@@ -71,6 +74,9 @@ TncThreadPool = class
procedure SetExecThreads(aThreadCount: Integer; aThreadPriority: TncThreadPriority);
procedure SetThreadPriority(aPriority: TncThreadPriority);
+
+ function GetThreadCount: Integer;
+ function GetActiveThreadCount: Integer;
property GrowUpto: Integer read GetGrowUpto write SetGrowUpto;
end;
@@ -266,7 +272,6 @@ procedure TncReadyThread.Run;
constructor TncThreadPool.Create(aWorkerThreadClass: TncReadyThreadClass);
begin
- Serialiser := TCriticalSection.Create;
ThreadClass := aWorkerThreadClass;
FGrowUpto := 500; // can reach up to 500 threads by default
end;
@@ -274,7 +279,6 @@ constructor TncThreadPool.Create(aWorkerThreadClass: TncReadyThreadClass);
destructor TncThreadPool.Destroy;
begin
ShutDown;
- Serialiser.Free;
inherited;
end;
@@ -395,21 +399,48 @@ procedure TncThreadPool.ShutDown;
function TncThreadPool.GetGrowUpto: Integer;
begin
- Serialiser.Acquire;
+ TMonitor.Enter(Self);
try
Result := FGrowUpto;
finally
- Serialiser.Release;
+ TMonitor.Exit(Self);
end;
end;
procedure TncThreadPool.SetGrowUpto(const Value: Integer);
begin
- Serialiser.Acquire;
+ TMonitor.Enter(Self);
try
FGrowUpto := Value;
finally
- Serialiser.Release;
+ TMonitor.Exit(Self);
+ end;
+end;
+
+function TncThreadPool.GetThreadCount: Integer;
+begin
+ TMonitor.Enter(Self);
+ try
+ Result := Length(Threads);
+ finally
+ TMonitor.Exit(Self);
+ end;
+end;
+
+function TncThreadPool.GetActiveThreadCount: Integer;
+var
+ i: Integer;
+begin
+ TMonitor.Enter(Self);
+ try
+ Result := 0;
+ for i := 0 to High(Threads) do
+ begin
+ if Assigned(Threads[i]) and (Threads[i].ReadyEvent.WaitFor(0) <> wrSignaled) then
+ Inc(Result);
+ end;
+ finally
+ TMonitor.Exit(Self);
end;
end;
diff --git a/Source/ncUDPSockets.pas b/Source/ncUDPSockets.pas
new file mode 100644
index 0000000..2dd9da9
--- /dev/null
+++ b/Source/ncUDPSockets.pas
@@ -0,0 +1,1098 @@
+unit ncUDPSockets;
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 Package - UDP Socket Components
+//
+// This unit implements UDP Server and UDP Client components
+//
+// 14/1/2025
+// - Initial creation
+// Currently implemented :
+// - Broadcast
+//
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+{$IF CompilerVersion >= 21.0}
+{$WEAKLINKRTTI ON}
+{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
+{$ENDIF}
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ Winapi.Windows, Winapi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, System.SyncObjs, System.Math, System.Diagnostics, System.TimeSpan,
+ ncLines, ncSocketList, ncThreads, ncIPUtils;
+
+const
+ DefPort = 16233;
+ DefHost = '';
+ DefReadBufferLen = 64 * 1024; // 64KB default for UDP
+ DefReaderThreadPriority = ntpNormal;
+ DefEventsUseMainThread = False;
+ DefUseReaderThread = True;
+ DefBroadcast = False;
+ DefFamily = afIPv4;
+
+resourcestring
+ ECannotSetPortWhileSocketActiveStr = 'Cannot set Port property while socket is active';
+ ECannotSetHostWhileSocketActiveStr = 'Cannot set Host property while socket is active';
+ ECannotSendWhileSocketInactiveStr = 'Cannot send data while socket is inactive';
+ ECannotSetUseReaderThreadWhileSocketActiveStr = 'Cannot set UseReaderThread property while socket is active';
+ ECannotReceiveIfUseReaderThreadStr = 'Cannot receive data if UseReaderThread is set. Use OnReadDatagram event handler to get the data or set UseReaderThread property to false';
+ ECannotSetFamilyWhileConnectionIsActiveStr = 'Cannot set Family property whilst the connection is active';
+type
+ EPropertySetError = class(Exception);
+
+ // Event types for UDP
+ TncOnDatagramEvent = procedure(Sender: TObject; aLine: TncLine;const aBuf: TBytes; aBufCount: Integer;const SenderAddr: TSockAddrStorage) of object;
+
+
+ // Base UDP Socket class
+ TncUDPBase = class(TComponent)
+ private
+ FInitActive: Boolean;
+ FFamily: TAddressType;
+ FPort: Integer;
+ FEventsUseMainThread: Boolean;
+ FBroadcast: Boolean;
+ FLine: TncLine;
+ FReadBufferLen: Integer;
+ FOnReadDatagram: TncOnDatagramEvent;
+ function GetReadBufferLen: Integer;
+ procedure SetReadBufferLen(const Value: Integer);
+ function GetActive: Boolean; virtual; abstract;
+ procedure SetActive(const Value: Boolean);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+ function GetPort: Integer;
+ procedure SetPort(const Value: Integer);
+ function GetReaderThreadPriority: TncThreadPriority;
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority);
+ function GetBroadcast: Boolean;
+ procedure SetBroadcast(const Value: Boolean);
+
+ private
+ FUseReaderThread: Boolean;
+ procedure DoActivate(aActivate: Boolean); virtual; abstract;
+ procedure SetUseReaderThread(const Value: Boolean);
+ protected
+ PropertyLock: TObject; // TMonitor synchronization object
+ ReadBuf: TBytes;
+ procedure Loaded; override;
+ function CreateLineObject: TncLine; virtual;
+ function GetLine: TncLine; virtual; abstract;
+ public
+ LineProcessor: TncReadyThread;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ function Kind: TSocketType; virtual;
+
+ property Active: Boolean read GetActive write SetActive default False;
+ property Family: TAddressType read GetFamily write SetFamily default afIPv4;
+ property Port: Integer read GetPort write SetPort default DefPort;
+ property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
+ property EventsUseMainThread: Boolean read FEventsUseMainThread write FEventsUseMainThread default DefEventsUseMainThread;
+ property UseReaderThread: Boolean read FUseReaderThread write SetUseReaderThread default DefUseReaderThread;
+ property Broadcast: Boolean read GetBroadcast write SetBroadcast default DefBroadcast;
+ property OnReadDatagram: TncOnDatagramEvent read FOnReadDatagram write FOnReadDatagram;
+ property ReadBufferLen: Integer read GetReadBufferLen write SetReadBufferLen default DefReadBufferLen;
+ published
+ end;
+
+ // UDP Client implementation
+ TncUDPClientProcessor = class;
+
+ TncCustomUDPClient = class(TncUDPBase)
+ private
+ FHost: string;
+ function GetActive: Boolean; override;
+ procedure SetHost(const Value: string);
+ function GetHost: string;
+ protected
+ procedure DoActivate(aActivate: Boolean); override;
+ function GetLine: TncLine; override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aBytes: TBytes;const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aStr: string; const DestAddr: TSockAddrStorage); overload;
+ procedure Send(const aBuf; aBufSize: Integer); overload;
+ procedure Send(const aBytes: TBytes); overload;
+ procedure Send(const aStr: string); overload;
+ function Receive(aTimeout: Cardinal = 2000): TBytes;
+ property Host: string read GetHost write SetHost;
+ end;
+
+ TncUDPClient = class(TncCustomUDPClient)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property Host;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property Broadcast;
+ property ReadBufferLen;
+ property OnReadDatagram;
+ end;
+
+ TncUDPClientProcessor = class(TncReadyThread)
+ private
+ FClientSocket: TncCustomUDPClient;
+ public
+ ReadySocketsChanged: Boolean;
+ constructor Create(aClientSocket: TncCustomUDPClient);
+ procedure ProcessDatagram; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // UDP Server implementation
+ TncUDPServerProcessor = class;
+
+ TncCustomUDPServer = class(TncUDPBase)
+ private
+ function GetActive: Boolean; override;
+ protected
+ procedure DoActivate(aActivate: Boolean); override;
+ function GetLine: TncLine; override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aBytes: TBytes;const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aStr: string; const DestAddr: TSockAddrStorage); overload;
+ function Receive(aTimeout: Cardinal = 2000): TBytes;
+ end;
+
+ TncUDPServer = class(TncCustomUDPServer)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property Broadcast;
+ property ReadBufferLen;
+ property OnReadDatagram;
+ end;
+
+ TncUDPServerProcessor = class(TncReadyThread)
+ private
+ FServerSocket: TncCustomUDPServer;
+ public
+ ReadySockets: TSocketHandleArray;
+ ReadySocketsChanged: Boolean;
+ constructor Create(aServerSocket: TncCustomUDPServer);
+ procedure ProcessDatagram; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // We bring in TncLine so that a form that uses our components does
+ // not have to reference ncLines unit to get the type
+ TncLine = ncLines.TncLine;
+
+ // We make a descendant of TncLine so that we can access the API functions.
+ // These API functions are not made puclic in TncLine so that the user cannot
+ // mangle up the line
+ TncLineInternal = class(TncLine);
+
+implementation
+
+{ TncUDPBase }
+
+constructor TncUDPBase.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ PropertyLock := TObject.Create;
+
+ FInitActive := False;
+ FFamily := DefFamily;
+ FPort := DefPort;
+ FEventsUseMainThread := DefEventsUseMainThread;
+ FUseReaderThread := DefUseReaderThread;
+ FBroadcast := DefBroadcast;
+ FReadBufferLen := DefReadBufferLen;
+ FOnReadDatagram := nil;
+
+ SetLength(ReadBuf, DefReadBufferLen);
+
+end;
+
+function TncUDPBase.Kind: TSocketType;
+begin
+ Result := stUDP;
+end;
+
+destructor TncUDPBase.Destroy;
+begin
+ PropertyLock.Free;
+ inherited Destroy;
+end;
+
+procedure TncUDPBase.Loaded;
+begin
+ inherited Loaded;
+ if FInitActive then
+ DoActivate(True);
+end;
+
+function TncUDPBase.CreateLineObject: TncLine;
+begin
+ Result := TncLine.Create;
+ TncLineInternal(Result).SetKind(Kind);
+ TncLineInternal(Result).SetFamily(FFamily);
+end;
+
+procedure TncUDPBase.SetActive(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ if not(csLoading in ComponentState) then
+ DoActivate(Value);
+ FInitActive := GetActive;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBase.GetFamily: TAddressType;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FFamily;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBase.SetFamily(const Value: TAddressType);
+begin
+ if not(csLoading in ComponentState) then
+ begin
+ if Active then
+ raise EPropertySetError.Create
+ (ECannotSetFamilyWhileConnectionIsActiveStr);
+ end;
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Update base class family
+ FFamily := Value;
+
+ // Update the Line's family
+ if FLine <> nil then
+ begin
+ TncLineInternal(FLine).SetFamily(Value);
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBase.GetPort: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPort;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBase.SetPort(const Value: Integer);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetPortWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FPort := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBase.GetReaderThreadPriority: TncThreadPriority;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := ToNcThreadPriority(LineProcessor.Priority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBase.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ try
+ LineProcessor.Priority := FromNcThreadPriority(Value);
+ except
+ // Some android devices cannot handle changing priority
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBase.GetBroadcast: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FBroadcast;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBase.SetBroadcast(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FBroadcast := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBase.SetUseReaderThread(const Value: Boolean);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetUseReaderThreadWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FUseReaderThread := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBase.GetReadBufferLen: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReadBufferLen;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBase.SetReadBufferLen(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReadBufferLen := Value;
+ SetLength(ReadBuf, FReadBufferLen);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+{ TncCustomUDPClient }
+
+constructor TncCustomUDPClient.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FHost := DefHost;
+
+ Line := CreateLineObject;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ LineProcessor := TncUDPClientProcessor.Create(Self);
+ try
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+end;
+
+destructor TncCustomUDPClient.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+function TncCustomUDPClient.GetLine: TncLine;
+begin
+ Result := Line;
+end;
+
+procedure TncCustomUDPClient.DoActivate(aActivate: Boolean);
+begin
+ // Exit if socket is already in requested state
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+ try
+
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ // Create socket handle and establish connection
+ TncLineInternal(Line).CreateClientHandle(FHost, FPort, GetBroadcast);
+
+ // Enable broadcast mode if requested
+ if GetBroadcast then
+ TncLineInternal(Line).EnableBroadcast;
+
+ // Configure socket buffer sizes for optimal performance
+ try
+ TncLineInternal(Line).SetReceiveSize(GetReadBufferLen);
+ TncLineInternal(Line).SetWriteSize(GetReadBufferLen);
+ except
+ on E: Exception do
+ begin
+ TncLineInternal(Line).DestroyHandle;
+ raise;
+ end;
+ end;
+
+ // Initialize socket handle array for reading
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ // Start reader thread if enabled
+ if UseReaderThread then
+ LineProcessor.Run;
+ except
+ on E: Exception do
+ begin
+ // Clean up on activation failure
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ raise;
+ end;
+ end;
+ end
+ else
+ begin
+ // Clean up when deactivating
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ end;
+end;
+
+function TncCustomUDPClient.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+function TncCustomUDPClient.GetHost: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FHost;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomUDPClient.SetHost(const Value: string);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetHostWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FHost := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomUDPClient.Send(const aBuf; aBufSize: Integer);
+var
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ case Family of
+ afIPv4:
+ begin
+ if GetBroadcast then
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(FPort);
+
+ // Use Winsock API directly for IPv4 broadcast
+ var addr := inet_addr(PAnsiChar(AnsiString(FHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+
+ SendTo(aBuf, aBufSize, storage);
+ end
+ else
+ TncLineInternal(Line).SendBuffer(aBuf, aBufSize);
+ end;
+
+ afIPv6:
+ begin
+ if GetBroadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.')
+ else if FHost = '' then
+ raise Exception.Create('Host address cannot be empty for IPv6')
+ else
+ begin
+ // Validate IPv6 address format
+ if not TncIPUtils.IsIPv6ValidAddress(FHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(FPort);
+
+ // Handle link-local address with scope ID
+ if TncIPUtils.IsLinkLocal(FHost) then
+ begin
+ var scopePos := Pos('%', FHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(FHost, 1, scopePos - 1);
+ var scope := Copy(FHost, scopePos + 1, Length(FHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ // Convert the address part without scope ID
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(FHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(FHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ SendTo(aBuf, aBufSize, storage);
+ end;
+ end;
+ end;
+end;
+
+procedure TncCustomUDPClient.Send(const aBytes: TBytes);
+begin
+ if Length(aBytes) > 0 then
+ Send(aBytes[0], Length(aBytes));
+end;
+
+procedure TncCustomUDPClient.Send(const aStr: string);
+begin
+ Send(BytesOf(aStr));
+end;
+
+// 1. Base SendTo that does the actual sending
+procedure TncCustomUDPClient.SendTo(const aBuf; aBufSize: Integer;
+ const DestAddr: TSockAddrStorage);
+var
+ AddrLen: Integer;
+ {$IFDEF MSWINDOWS}
+ BytesSent: Integer;
+ {$ELSE}
+ BytesSent: ssize_t;
+ {$ENDIF}
+ DestIP: string;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ try
+ // Get destination address for logging/error reporting
+ DestIP := TncIPUtils.GetIPFromStorage(DestAddr);
+
+ // Set proper address length based on family
+ case DestAddr.ss_family of
+ AF_INET: AddrLen := SizeOf(TSockAddr);
+ AF_INET6: AddrLen := SizeOf(TSockAddrIn6);
+ else
+ AddrLen := SizeOf(TSockAddrStorage);
+ end;
+
+ {$IFDEF MSWINDOWS}
+ BytesSent := Winapi.Winsock2.sendto(Line.Handle, aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent = SOCKET_ERROR then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(WSAGetLastError)]);
+ {$ELSE}
+ BytesSent := Posix.SysSocket.sendto(Line.Handle, @aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent < 0 then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(GetLastError)]);
+ {$ENDIF}
+ except
+ on E: EIPError do
+ raise Exception.Create('Invalid destination address: ' + E.Message);
+ end;
+end;
+
+// 2. SendTo for byte arrays
+procedure TncCustomUDPClient.SendTo(const aBytes: TBytes;
+ const DestAddr: TSockAddrStorage);
+begin
+ if Length(aBytes) > 0 then
+ SendTo(aBytes[0], Length(aBytes), DestAddr);
+end;
+
+// 3. SendTo for strings
+procedure TncCustomUDPClient.SendTo(const aStr: string; const DestAddr: TSockAddrStorage);
+var
+ bytes: TBytes;
+ len: Integer;
+begin
+ bytes := BytesOf(aStr);
+ len := Length(bytes);
+ if len > 0 then
+ SendTo(bytes[0], len, DestAddr);
+end;
+
+function TncCustomUDPClient.Receive(aTimeout: Cardinal = 2000): TBytes;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ SenderIP: string;
+begin
+ if UseReaderThread then
+ raise Exception.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(Line.Handle, ReadBuf[0], Length(ReadBuf), 0,
+ PSockAddr(@SenderAddr)^, SenderAddrLen);
+
+ try
+ if BufRead > 0 then
+ begin
+ // Get sender IP for logging if needed
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ Result := Copy(ReadBuf, 0, BufRead);
+ end
+ else if BufRead = 0 then
+ begin
+ SetLength(Result, 0);
+ // Optional: raise Exception.Create('Connection closed by peer');
+ end
+ else
+ begin
+ SetLength(Result, 0);
+ {$IFDEF MSWINDOWS}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(GetLastError));
+ {$ENDIF}
+ end;
+ except
+ on E: EIPError do
+ begin
+ SetLength(Result, 0);
+ raise Exception.Create('Invalid sender address: ' + E.Message);
+ end;
+ end;
+end;
+
+{ TncUDPClientProcessor }
+
+constructor TncUDPClientProcessor.Create(aClientSocket: TncCustomUDPClient);
+begin
+ FClientSocket := aClientSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+procedure TncUDPClientProcessor.ProcessDatagram;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+begin
+ // Initialize sender address structure
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ // Receive datagram with proper address structure
+ BufRead := recvfrom(FClientSocket.Line.Handle,
+ FClientSocket.ReadBuf[0],
+ Length(FClientSocket.ReadBuf),
+ 0,
+ PSockAddr(@SenderAddr)^,
+ SenderAddrLen);
+
+ if (BufRead > 0) and Assigned(FClientSocket.OnReadDatagram) then
+ try
+ FClientSocket.OnReadDatagram(FClientSocket,
+ FClientSocket.Line,
+ FClientSocket.ReadBuf,
+ BufRead,
+ SenderAddr);
+ except
+ end;
+end;
+
+procedure TncUDPClientProcessor.ProcessEvent;
+begin
+ while (not Terminated) do
+ try
+ if FClientSocket.Line.Active then
+ begin
+ if ReadableAnySocket(FClientSocket.ReadSocketHandles, 100) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ if FClientSocket.EventsUseMainThread then
+ Synchronize(ProcessDatagram)
+ else
+ ProcessDatagram;
+ end;
+ end
+ else
+ Exit;
+ except
+ // Continue processing even after errors
+ end;
+end;
+
+{ TncCustomUDPServer }
+
+constructor TncCustomUDPServer.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ Line := CreateLineObject;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ LineProcessor := TncUDPServerProcessor.Create(Self);
+ try
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+end;
+
+destructor TncCustomUDPServer.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+function TncCustomUDPServer.GetLine: TncLine;
+begin
+ Result := Line;
+end;
+
+function TncCustomUDPServer.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+procedure TncCustomUDPServer.DoActivate(aActivate: Boolean);
+begin
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ // CreateServerHandle will bind to all interfaces (0.0.0.0)
+ // through the AI_PASSIVE flag in ncLines.CreateServerHandle
+ TncLineInternal(Line).CreateServerHandle(FPort);
+
+ // Enable broadcast if needed
+ if Broadcast then
+ TncLineInternal(Line).EnableBroadcast;
+
+ // Set socket buffer sizes for better performance
+ try
+ TncLineInternal(Line).SetReceiveSize(ReadBufferLen);
+ TncLineInternal(Line).SetWriteSize(ReadBufferLen);
+ except
+ // Ignore buffer size errors
+ end;
+
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ if UseReaderThread then
+ begin
+ LineProcessor.WaitForReady;
+ LineProcessor.Run;
+ end;
+ end
+ else
+ begin
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ end;
+end;
+
+// 1. Base SendTo that does the actual sending
+procedure TncCustomUDPServer.SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage);
+var
+ AddrLen: Integer;
+ {$IFDEF MSWINDOWS}
+ BytesSent: Integer;
+ {$ELSE}
+ BytesSent: ssize_t;
+ {$ENDIF}
+ DestIP: string;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+ try
+ // Get destination address for logging/error reporting
+ DestIP := TncIPUtils.GetIPFromStorage(DestAddr);
+ // Set proper address length based on family
+ case DestAddr.ss_family of
+ AF_INET: AddrLen := SizeOf(TSockAddr);
+ AF_INET6: AddrLen := SizeOf(TSockAddrIn6);
+ else
+ AddrLen := SizeOf(TSockAddrStorage);
+ end;
+ {$IFDEF MSWINDOWS}
+ BytesSent := Winapi.Winsock2.sendto(Line.Handle, aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent = SOCKET_ERROR then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(WSAGetLastError)]);
+ {$ELSE}
+ BytesSent := Posix.SysSocket.sendto(Line.Handle, @aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent < 0 then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(GetLastError)]);
+ {$ENDIF}
+ except
+ on E: EIPError do
+ raise Exception.Create('Invalid destination address: ' + E.Message);
+ end;
+end;
+
+// 2. SendTo for byte arrays
+procedure TncCustomUDPServer.SendTo(const aBytes: TBytes; const DestAddr: TSockAddrStorage);
+begin
+ if Length(aBytes) > 0 then
+ SendTo(aBytes[0], Length(aBytes), DestAddr);
+end;
+
+// 3. SendTo for strings
+procedure TncCustomUDPServer.SendTo(const aStr: string; const DestAddr: TSockAddrStorage);
+var
+ bytes: TBytes;
+ len: Integer;
+begin
+ bytes := BytesOf(aStr);
+ len := Length(bytes);
+ if len > 0 then
+ SendTo(bytes[0], len, DestAddr);
+end;
+
+function TncCustomUDPServer.Receive(aTimeout: Cardinal = 2000): TBytes;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ SenderIP: string;
+begin
+ if UseReaderThread then
+ raise Exception.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(Line.Handle, ReadBuf[0], Length(ReadBuf), 0,
+ PSockAddr(@SenderAddr)^, SenderAddrLen);
+
+ try
+ if BufRead > 0 then
+ begin
+ // Get sender IP for logging if needed
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ Result := Copy(ReadBuf, 0, BufRead);
+ end
+ else if BufRead = 0 then
+ begin
+ SetLength(Result, 0);
+ // Optional: raise Exception.Create('Connection closed by peer');
+ end
+ else
+ begin
+ SetLength(Result, 0);
+ {$IFDEF MSWINDOWS}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(GetLastError));
+ {$ENDIF}
+ end;
+ except
+ on E: EIPError do
+ begin
+ SetLength(Result, 0);
+ raise Exception.Create('Invalid sender address: ' + E.Message);
+ end;
+ end;
+end;
+
+{ TncUDPServerProcessor }
+
+constructor TncUDPServerProcessor.Create(aServerSocket: TncCustomUDPServer);
+begin
+ FServerSocket := aServerSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+
+procedure TncUDPServerProcessor.ProcessDatagram;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+begin
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(FServerSocket.Line.Handle,
+ FServerSocket.ReadBuf[0],
+ Length(FServerSocket.ReadBuf),
+ 0,
+ PSockAddr(@SenderAddr)^,
+ SenderAddrLen);
+
+ if (BufRead > 0) and Assigned(FServerSocket.OnReadDatagram) then
+ try
+ FServerSocket.OnReadDatagram(FServerSocket, FServerSocket.Line,
+ FServerSocket.ReadBuf, BufRead, SenderAddr);
+ except
+ end;
+end;
+
+procedure TncUDPServerProcessor.ProcessEvent;
+begin
+ if FServerSocket.EventsUseMainThread then
+ while FServerSocket.Active and (not Terminated) do
+ try
+ if ReadableAnySocket(FServerSocket.ReadSocketHandles, 500) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ Synchronize(ProcessDatagram);
+ end;
+ except
+ end
+ else
+ while FServerSocket.Active and (not Terminated) do
+ try
+ if ReadableAnySocket(FServerSocket.ReadSocketHandles, 500) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ ProcessDatagram;
+ end;
+ except
+ end;
+end;
+
+end.
+
diff --git a/Source/ncUDPSocketsDual.pas b/Source/ncUDPSocketsDual.pas
new file mode 100644
index 0000000..1d28e43
--- /dev/null
+++ b/Source/ncUDPSocketsDual.pas
@@ -0,0 +1,1999 @@
+unit ncUDPSocketsDual;
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 Package - UDP Socket Components (Dual Mode - Raw + Protocol)
+//
+// This unit implements UDP Server and UDP Client components with both
+// raw UDP support and lightweight command protocol support
+//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 23/07/2025
+// - Lightweight Command Protocol (LCP)
+// - Auto-chunking for large data
+// 14/1/2025
+// - Initial creation
+// Currently implemented :
+// - Broadcast
+// - Raw UDP communication
+//
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+{$IF CompilerVersion >= 21.0}
+{$WEAKLINKRTTI ON}
+{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
+{$ENDIF}
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ Winapi.Windows, Winapi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, System.SyncObjs, System.Math, System.Diagnostics, System.TimeSpan, System.DateUtils,
+ ncLines, ncSocketList, ncThreads, ncIPUtils, System.Generics.Collections;
+
+const
+ DefPort = 16233;
+ DefHost = '';
+ DefReadBufferLen = 64 * 1024; // 64KB default for UDP
+ DefReaderThreadPriority = ntpNormal;
+ DefEventsUseMainThread = False;
+ DefUseReaderThread = True;
+ DefBroadcast = False;
+ DefFamily = afIPv4;
+
+ // UDP Performance constants
+ UDP_COMMAND_MAGIC = $4E43; // 'NC'
+ UDP_CHUNK_MAGIC = $4E44; // 'ND' signature for chunk packets
+ UDP_MAX_SAFE_PAYLOAD = 1392; // Optimal MTU (avoids fragmentation)
+ UDP_CHUNK_TIMEOUT = 5000; // 5 seconds timeout for incomplete transfers
+
+type
+ // UDP Command Header Structure
+ TUdpCommandHeader = packed record
+ Cmd: Integer; // Command ID (matches ncSocketsPro)
+ Flags: Byte; // Command flags for future extensibility
+ Sequence: UInt16; // Sequence number for tracking/ordering
+ end;
+
+ // Complete UDP Command Packet Structure
+ TUdpCommandPacket = packed record
+ Magic: UInt16; // Protocol detection signature
+ Header: TUdpCommandHeader; // Command header
+ // Variable data follows after this structure
+ end;
+
+ // UDP Chunk Header Structure (for auto-chunking large commands)
+ TUdpChunkHeader = packed record
+ Magic: UInt16; // Chunk magic signature ($4E44 = 'ND')
+ TransferID: UInt32; // Unique transfer identifier
+ ChunkIndex: UInt16; // Current chunk number (0-based)
+ TotalChunks: UInt16; // Total number of chunks
+ OriginalCmd: Integer; // Original command ID
+ OriginalFlags: Byte; // Original command flags
+ OriginalSequence: UInt16; // Original sequence number
+ end;
+
+ // Pointer type for zero-copy operations
+ PUdpChunkHeader = ^TUdpChunkHeader;
+
+ // Chunk reassembly tracking
+ TChunkTransfer = record
+ TransferID: UInt32;
+ OriginalCmd: Integer;
+ OriginalFlags: Byte;
+ OriginalSequence: UInt16;
+ TotalChunks: UInt16;
+ FragmentsRemaining: UInt16;
+ LastActivity: TDateTime;
+ CompleteData: TBytes; // Pre-allocated full buffer
+ Fragments: array of UInt32; // Bitwise tracking
+ ActualDataSize: UInt32; // Real size of the complete data (calculated when complete)
+ LastChunkSize: UInt16; // Size of the last chunk (for accurate total calculation)
+
+ // Helper methods for bitwise operations
+ function IsFragmentReceived(FragmentIndex: UInt16): Boolean;
+ procedure SetFragmentReceived(FragmentIndex: UInt16);
+ end;
+
+ // Chunk transfer manager
+ TncChunkManager = class
+ private
+ FTransfers: TDictionary; // Hash table for O(1) lookup
+ FLock: TObject; // TMonitor synchronization object
+ function GenerateTransferID: UInt32;
+ procedure CleanupExpiredTransfers;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function StartTransfer(ACmd: Integer; AFlags: Byte; ASequence: UInt16; ATotalChunks: UInt16; AActualDataSize: UInt32): UInt32;
+ function CreateTransferFromChunk(ATransferID: UInt32; ATotalChunks: UInt16; AOriginalCmd: Integer; AOriginalFlags: Byte; AOriginalSequence: UInt16): Boolean;
+ function AddChunk(ATransferID: UInt32; AChunkIndex: UInt16; const AChunkData: TBytes): Boolean;
+ function CompleteTransfer(ATransferID: UInt32; out ACmd: Integer; out AFlags: Byte;
+ out ASequence: UInt16; out ACompleteData: TBytes): Boolean;
+ end;
+
+resourcestring
+ ECannotSetPortWhileSocketActiveStr = 'Cannot set Port property while socket is active';
+ ECannotSetHostWhileSocketActiveStr = 'Cannot set Host property while socket is active';
+ ECannotSendWhileSocketInactiveStr = 'Cannot send data while socket is inactive';
+ ECannotSetUseReaderThreadWhileSocketActiveStr = 'Cannot set UseReaderThread property while socket is active';
+ ECannotReceiveIfUseReaderThreadStr = 'Cannot receive data if UseReaderThread is set. Use OnReadDatagram event handler to get the data or set UseReaderThread property to false';
+ ECannotSetFamilyWhileConnectionIsActiveStr = 'Cannot set Family property whilst the connection is active';
+type
+ EPropertySetError = class(Exception);
+
+ // Event types for UDP
+ TncOnDatagramEvent = procedure(Sender: TObject; aLine: TncLine;const aBuf: TBytes; aBufCount: Integer;const SenderAddr: TSockAddrStorage) of object;
+
+ // UDP Command Protocol Event
+ TncOnUDPCommandEvent = procedure(Sender: TObject; aLine: TncLine; const aSenderAddr: TSockAddrStorage;
+ aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16) of object;
+
+
+ // Base UDP Socket class
+ TncUDPBaseDual = class(TComponent)
+ private
+ FInitActive: Boolean;
+ FFamily: TAddressType;
+ FPort: Integer;
+ FEventsUseMainThread: Boolean;
+ FBroadcast: Boolean;
+ FLine: TncLine;
+ FReadBufferLen: Integer;
+ FOnReadDatagram: TncOnDatagramEvent;
+ FOnCommand: TncOnUDPCommandEvent;
+ FChunkManager: TncChunkManager; // For auto-chunking large commands
+ function GetReadBufferLen: Integer;
+ procedure SetReadBufferLen(const Value: Integer);
+ function GetActive: Boolean; virtual; abstract;
+ procedure SetActive(const Value: Boolean);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+ function GetPort: Integer;
+ procedure SetPort(const Value: Integer);
+ function GetReaderThreadPriority: TncThreadPriority;
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority);
+ function GetBroadcast: Boolean;
+ procedure SetBroadcast(const Value: Boolean);
+
+ private
+ FUseReaderThread: Boolean;
+ procedure DoActivate(aActivate: Boolean); virtual; abstract;
+ procedure SetUseReaderThread(const Value: Boolean);
+ protected
+ PropertyLock: TObject; // TMonitor synchronization object
+ ReadBuf: TBytes;
+ procedure Loaded; override;
+ function CreateLineObject: TncLine; virtual;
+ function GetLine: TncLine; virtual; abstract;
+ public
+ LineProcessor: TncReadyThread;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ function Kind: TSocketType; virtual;
+
+ property Active: Boolean read GetActive write SetActive default False;
+ property Family: TAddressType read GetFamily write SetFamily default afIPv4;
+ property Port: Integer read GetPort write SetPort default DefPort;
+ property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
+ property EventsUseMainThread: Boolean read FEventsUseMainThread write FEventsUseMainThread default DefEventsUseMainThread;
+ property UseReaderThread: Boolean read FUseReaderThread write SetUseReaderThread default DefUseReaderThread;
+ property Broadcast: Boolean read GetBroadcast write SetBroadcast default DefBroadcast;
+ property OnReadDatagram: TncOnDatagramEvent read FOnReadDatagram write FOnReadDatagram;
+ property OnCommand: TncOnUDPCommandEvent read FOnCommand write FOnCommand;
+ property ReadBufferLen: Integer read GetReadBufferLen write SetReadBufferLen default DefReadBufferLen;
+ published
+ end;
+
+ // UDP Client implementation
+ TncUDPClientProcessor = class;
+
+ TncCustomUDPClientDual = class(TncUDPBaseDual)
+ private
+ FHost: string;
+ function GetActive: Boolean; override;
+ procedure SetHost(const Value: string);
+ function GetHost: string;
+ protected
+ procedure DoActivate(aActivate: Boolean); override;
+ function GetLine: TncLine; override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aBytes: TBytes;const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aStr: string; const DestAddr: TSockAddrStorage); overload;
+ procedure Send(const aBuf; aBufSize: Integer); overload;
+ procedure Send(const aBytes: TBytes); overload;
+ procedure Send(const aStr: string); overload;
+
+ // UDP Command Protocol Methods
+ procedure SendCommand(aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+ procedure SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+
+ function Receive(aTimeout: Cardinal = 2000): TBytes;
+ property Host: string read GetHost write SetHost;
+ end;
+
+ TncUDPClientDual = class(TncCustomUDPClientDual)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property Host;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property Broadcast;
+ property ReadBufferLen;
+ property OnReadDatagram;
+ property OnCommand;
+ end;
+
+ TncUDPClientProcessor = class(TncReadyThread)
+ private
+ FClientSocket: TncCustomUDPClientDual;
+ public
+ ReadySocketsChanged: Boolean;
+ constructor Create(aClientSocket: TncCustomUDPClientDual);
+ procedure ProcessDatagram; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // UDP Server implementation
+ TncUDPServerProcessor = class;
+
+ TncCustomUDPServerDual = class(TncUDPBaseDual)
+ private
+ function GetActive: Boolean; override;
+ protected
+ procedure DoActivate(aActivate: Boolean); override;
+ function GetLine: TncLine; override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aBytes: TBytes;const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aStr: string; const DestAddr: TSockAddrStorage); overload;
+
+ // UDP Command Protocol Methods
+ procedure SendCommand(const DestAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+ procedure SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+
+ function Receive(aTimeout: Cardinal = 2000): TBytes;
+ end;
+
+ TncUDPServerDual = class(TncCustomUDPServerDual)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property Broadcast;
+ property ReadBufferLen;
+ property OnReadDatagram;
+ property OnCommand;
+ end;
+
+ TncUDPServerProcessor = class(TncReadyThread)
+ private
+ FServerSocket: TncCustomUDPServerDual;
+ public
+ ReadySockets: TSocketHandleArray;
+ ReadySocketsChanged: Boolean;
+ constructor Create(aServerSocket: TncCustomUDPServerDual);
+ procedure ProcessDatagram; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // We bring in TncLine so that a form that uses our components does
+ // not have to reference ncLines unit to get the type
+ TncLine = ncLines.TncLine;
+
+ // We make a descendant of TncLine so that we can access the API functions.
+ // These API functions are not made puclic in TncLine so that the user cannot
+ // mangle up the line
+ TncLineInternal = class(TncLine);
+
+implementation
+
+{ TncUDPBaseDual }
+
+constructor TncUDPBaseDual.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ PropertyLock := TObject.Create;
+
+ FInitActive := False;
+ FFamily := DefFamily;
+ FPort := DefPort;
+ FEventsUseMainThread := DefEventsUseMainThread;
+ FUseReaderThread := DefUseReaderThread;
+ FBroadcast := DefBroadcast;
+ FReadBufferLen := DefReadBufferLen;
+ FOnReadDatagram := nil;
+ FOnCommand := nil;
+ FChunkManager := TncChunkManager.Create; // Initialize the chunk manager
+
+ SetLength(ReadBuf, DefReadBufferLen);
+
+end;
+
+function TncUDPBaseDual.Kind: TSocketType;
+begin
+ Result := stUDP;
+end;
+
+destructor TncUDPBaseDual.Destroy;
+begin
+ PropertyLock.Free;
+ FChunkManager.Free; // Free the chunk manager
+ inherited Destroy;
+end;
+
+procedure TncUDPBaseDual.Loaded;
+begin
+ inherited Loaded;
+ if FInitActive then
+ DoActivate(True);
+end;
+
+function TncUDPBaseDual.CreateLineObject: TncLine;
+begin
+ Result := TncLine.Create;
+ TncLineInternal(Result).SetKind(Kind);
+ TncLineInternal(Result).SetFamily(FFamily);
+end;
+
+procedure TncUDPBaseDual.SetActive(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ if not(csLoading in ComponentState) then
+ DoActivate(Value);
+ FInitActive := GetActive;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseDual.GetFamily: TAddressType;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FFamily;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseDual.SetFamily(const Value: TAddressType);
+begin
+ if not(csLoading in ComponentState) then
+ begin
+ if Active then
+ raise EPropertySetError.Create
+ (ECannotSetFamilyWhileConnectionIsActiveStr);
+ end;
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Update base class family
+ FFamily := Value;
+
+ // Update the Line's family
+ if FLine <> nil then
+ begin
+ TncLineInternal(FLine).SetFamily(Value);
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseDual.GetPort: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPort;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseDual.SetPort(const Value: Integer);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetPortWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FPort := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseDual.GetReaderThreadPriority: TncThreadPriority;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := ToNcThreadPriority(LineProcessor.Priority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseDual.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ try
+ LineProcessor.Priority := FromNcThreadPriority(Value);
+ except
+ // Some android devices cannot handle changing priority
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseDual.GetBroadcast: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FBroadcast;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseDual.SetBroadcast(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FBroadcast := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseDual.SetUseReaderThread(const Value: Boolean);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetUseReaderThreadWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FUseReaderThread := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseDual.GetReadBufferLen: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReadBufferLen;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseDual.SetReadBufferLen(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReadBufferLen := Value;
+ SetLength(ReadBuf, FReadBufferLen);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+{ TncCustomUDPClientDual }
+
+constructor TncCustomUDPClientDual.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FHost := DefHost;
+
+ Line := CreateLineObject;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ LineProcessor := TncUDPClientProcessor.Create(Self);
+ try
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+end;
+
+destructor TncCustomUDPClientDual.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+function TncCustomUDPClientDual.GetLine: TncLine;
+begin
+ Result := Line;
+end;
+
+procedure TncCustomUDPClientDual.DoActivate(aActivate: Boolean);
+begin
+ // Exit if socket is already in requested state
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+ try
+
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ // Create socket handle and establish connection
+ TncLineInternal(Line).CreateClientHandle(FHost, FPort, GetBroadcast);
+
+ // Enable broadcast mode if requested
+ if GetBroadcast then
+ TncLineInternal(Line).EnableBroadcast;
+
+ // Configure socket buffer sizes for optimal performance
+ try
+ TncLineInternal(Line).SetReceiveSize(GetReadBufferLen);
+ TncLineInternal(Line).SetWriteSize(GetReadBufferLen);
+ except
+ on E: Exception do
+ begin
+ TncLineInternal(Line).DestroyHandle;
+ raise;
+ end;
+ end;
+
+ // Initialize socket handle array for reading
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ // Start reader thread if enabled
+ if UseReaderThread then
+ LineProcessor.Run;
+ except
+ on E: Exception do
+ begin
+ // Clean up on activation failure
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ raise;
+ end;
+ end;
+ end
+ else
+ begin
+ // Clean up when deactivating
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ end;
+end;
+
+function TncCustomUDPClientDual.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+function TncCustomUDPClientDual.GetHost: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FHost;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomUDPClientDual.SetHost(const Value: string);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetHostWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FHost := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomUDPClientDual.Send(const aBuf; aBufSize: Integer);
+var
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ case Family of
+ afIPv4:
+ begin
+ if GetBroadcast then
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(FPort);
+
+ // Use Winsock API directly for IPv4 broadcast
+ var addr := inet_addr(PAnsiChar(AnsiString(FHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+
+ SendTo(aBuf, aBufSize, storage);
+ end
+ else
+ TncLineInternal(Line).SendBuffer(aBuf, aBufSize);
+ end;
+
+ afIPv6:
+ begin
+ if GetBroadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.')
+ else if FHost = '' then
+ raise Exception.Create('Host address cannot be empty for IPv6')
+ else
+ begin
+ // Validate IPv6 address format
+ if not TncIPUtils.IsIPv6ValidAddress(FHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(FPort);
+
+ // Handle link-local address with scope ID
+ if TncIPUtils.IsLinkLocal(FHost) then
+ begin
+ var scopePos := Pos('%', FHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(FHost, 1, scopePos - 1);
+ var scope := Copy(FHost, scopePos + 1, Length(FHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ // Convert the address part without scope ID
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(FHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(FHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ SendTo(aBuf, aBufSize, storage);
+ end;
+ end;
+ end;
+end;
+
+procedure TncCustomUDPClientDual.Send(const aBytes: TBytes);
+begin
+ if Length(aBytes) > 0 then
+ Send(aBytes[0], Length(aBytes));
+end;
+
+procedure TncCustomUDPClientDual.Send(const aStr: string);
+begin
+ Send(BytesOf(aStr));
+end;
+
+// UDP Command Protocol Methods for TncCustomUDPClientDual
+
+procedure TncCustomUDPClientDual.SendCommand(aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+begin
+ SendCommand(FHost, FPort, aCmd, aData, aFlags, aSequence);
+end;
+
+procedure TncCustomUDPClientDual.SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ HeaderSize, DataSize, TotalSize: Integer;
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+
+ // For normal sending
+ Packet: TBytes;
+ PacketHeader: TUdpCommandPacket;
+
+ // For chunking
+ ChunkHeader: TUdpChunkHeader;
+ ChunkPacket: TBytes;
+ TransferID: UInt32;
+ TotalChunks: UInt16;
+ ChunkIndex: UInt16;
+ CurrentPos: Integer;
+ ChunkDataSize: Integer;
+ MaxChunkDataSize: Integer;
+
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ // IPv6 broadcast validation
+ if (Family = afIPv6) and GetBroadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.');
+
+ // Calculate total command packet size
+ HeaderSize := SizeOf(TUdpCommandPacket);
+ DataSize := Length(aData);
+ TotalSize := HeaderSize + DataSize;
+
+ // Build destination address first (common for both paths)
+ case Family of
+ afIPv4:
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(aRemotePort);
+ var addr := inet_addr(PAnsiChar(AnsiString(aRemoteHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+ end;
+
+ afIPv6:
+ begin
+ if not TncIPUtils.IsIPv6ValidAddress(aRemoteHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(aRemotePort);
+ if TncIPUtils.IsLinkLocal(aRemoteHost) then
+ begin
+ var scopePos := Pos('%', aRemoteHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(aRemoteHost, 1, scopePos - 1);
+ var scope := Copy(aRemoteHost, scopePos + 1, Length(aRemoteHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end;
+ end;
+
+ // Check if auto-chunking is needed
+ if TotalSize <= UDP_MAX_SAFE_PAYLOAD then
+ begin
+ // ===============================================
+ // NORMAL SEND - Single packet
+ // ===============================================
+
+ PacketHeader.Magic := UDP_COMMAND_MAGIC;
+ PacketHeader.Header.Cmd := aCmd;
+ PacketHeader.Header.Flags := aFlags;
+ PacketHeader.Header.Sequence := aSequence;
+
+ SetLength(Packet, TotalSize);
+ Move(PacketHeader, Packet[0], HeaderSize);
+ if DataSize > 0 then
+ Move(aData[0], Packet[HeaderSize], DataSize);
+
+ SendTo(Packet, storage);
+ end
+ else
+ begin
+ // ===============================================
+ // AUTO-CHUNKING - Multiple packets
+ // ===============================================
+
+ MaxChunkDataSize := UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader);
+ TotalChunks := (DataSize + MaxChunkDataSize - 1) div MaxChunkDataSize;
+ TransferID := FChunkManager.StartTransfer(aCmd, aFlags, aSequence, TotalChunks, DataSize);
+
+ // Immediate packet sending for maximum speed
+ SetLength(ChunkPacket, UDP_MAX_SAFE_PAYLOAD);
+
+ ChunkHeader.Magic := UDP_CHUNK_MAGIC;
+ ChunkHeader.TransferID := TransferID;
+ ChunkHeader.TotalChunks := TotalChunks;
+ ChunkHeader.OriginalCmd := aCmd;
+ ChunkHeader.OriginalFlags := aFlags;
+ ChunkHeader.OriginalSequence := aSequence;
+
+ CurrentPos := 0;
+
+ // Send packets immediately without preparation overhead
+ for ChunkIndex := 0 to TotalChunks - 1 do
+ begin
+ ChunkDataSize := MaxChunkDataSize;
+ if ChunkIndex = TotalChunks - 1 then
+ ChunkDataSize := DataSize - CurrentPos;
+
+ ChunkHeader.ChunkIndex := ChunkIndex;
+
+ // Build and send packet immediately (zero overhead)
+ Move(ChunkHeader, ChunkPacket[0], SizeOf(TUdpChunkHeader));
+ if ChunkDataSize > 0 then
+ Move(aData[CurrentPos], ChunkPacket[SizeOf(TUdpChunkHeader)], ChunkDataSize);
+
+ // Send immediately at maximum speed (no delays, no burst preparation)
+ SendTo(ChunkPacket[0], SizeOf(TUdpChunkHeader) + ChunkDataSize, storage);
+
+ Inc(CurrentPos, ChunkDataSize);
+ end;
+ end;
+end;
+
+// 1. Base SendTo that does the actual sending
+procedure TncCustomUDPClientDual.SendTo(const aBuf; aBufSize: Integer;
+ const DestAddr: TSockAddrStorage);
+var
+ AddrLen: Integer;
+ {$IFDEF MSWINDOWS}
+ BytesSent: Integer;
+ {$ELSE}
+ BytesSent: ssize_t;
+ {$ENDIF}
+ DestIP: string;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ try
+ // Get destination address for logging/error reporting
+ DestIP := TncIPUtils.GetIPFromStorage(DestAddr);
+
+ // Set proper address length based on family
+ case DestAddr.ss_family of
+ AF_INET: AddrLen := SizeOf(TSockAddr);
+ AF_INET6: AddrLen := SizeOf(TSockAddrIn6);
+ else
+ AddrLen := SizeOf(TSockAddrStorage);
+ end;
+
+ {$IFDEF MSWINDOWS}
+ BytesSent := Winapi.Winsock2.sendto(Line.Handle, aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent = SOCKET_ERROR then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(WSAGetLastError)]);
+ {$ELSE}
+ BytesSent := Posix.SysSocket.sendto(Line.Handle, @aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent < 0 then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(GetLastError)]);
+ {$ENDIF}
+ except
+ on E: EIPError do
+ raise Exception.Create('Invalid destination address: ' + E.Message);
+ end;
+end;
+
+// 2. SendTo for byte arrays
+procedure TncCustomUDPClientDual.SendTo(const aBytes: TBytes;
+ const DestAddr: TSockAddrStorage);
+begin
+ if Length(aBytes) > 0 then
+ SendTo(aBytes[0], Length(aBytes), DestAddr);
+end;
+
+// 3. SendTo for strings
+procedure TncCustomUDPClientDual.SendTo(const aStr: string; const DestAddr: TSockAddrStorage);
+var
+ bytes: TBytes;
+ len: Integer;
+begin
+ bytes := BytesOf(aStr);
+ len := Length(bytes);
+ if len > 0 then
+ SendTo(bytes[0], len, DestAddr);
+end;
+
+function TncCustomUDPClientDual.Receive(aTimeout: Cardinal = 2000): TBytes;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ SenderIP: string;
+begin
+ if UseReaderThread then
+ raise Exception.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(Line.Handle, ReadBuf[0], Length(ReadBuf), 0,
+ PSockAddr(@SenderAddr)^, SenderAddrLen);
+
+ try
+ if BufRead > 0 then
+ begin
+ // Get sender IP for logging if needed
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ Result := Copy(ReadBuf, 0, BufRead);
+ end
+ else if BufRead = 0 then
+ begin
+ SetLength(Result, 0);
+ // Optional: raise Exception.Create('Connection closed by peer');
+ end
+ else
+ begin
+ SetLength(Result, 0);
+ {$IFDEF MSWINDOWS}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(GetLastError));
+ {$ENDIF}
+ end;
+ except
+ on E: EIPError do
+ begin
+ SetLength(Result, 0);
+ raise Exception.Create('Invalid sender address: ' + E.Message);
+ end;
+ end;
+end;
+
+{ TncUDPClientProcessor }
+
+constructor TncUDPClientProcessor.Create(aClientSocket: TncCustomUDPClientDual);
+begin
+ FClientSocket := aClientSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+procedure TncUDPClientProcessor.ProcessDatagram;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ Magic: UInt16;
+ CommandHeader: TUdpCommandHeader;
+ CommandData: TBytes;
+ PacketSize: Integer;
+
+ // For chunk handling
+ ChunkHeader: TUdpChunkHeader;
+ ChunkData: TBytes;
+ CompleteCmd: Integer;
+ CompleteFlags: Byte;
+ CompleteSequence: UInt16;
+ CompleteData: TBytes;
+begin
+ // Initialize sender address structure
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ // Receive datagram with proper address structure
+ BufRead := recvfrom(FClientSocket.Line.Handle,
+ FClientSocket.ReadBuf[0],
+ Length(FClientSocket.ReadBuf),
+ 0,
+ PSockAddr(@SenderAddr)^,
+ SenderAddrLen);
+
+ if BufRead > 0 then
+ begin
+ // Check minimum size for any structured packet
+ if (BufRead >= SizeOf(UInt16)) then
+ begin
+ // Extract magic number to check protocol type
+ Move(FClientSocket.ReadBuf[0], Magic, SizeOf(Magic));
+
+ if Magic = UDP_COMMAND_MAGIC then
+ begin
+ // ===============================================
+ // NORMAL COMMAND PACKET
+ // ===============================================
+ if BufRead >= SizeOf(TUdpCommandPacket) then
+ begin
+ Move(FClientSocket.ReadBuf[SizeOf(UInt16)], CommandHeader, SizeOf(CommandHeader));
+
+ PacketSize := SizeOf(TUdpCommandPacket);
+ if BufRead > PacketSize then
+ begin
+ SetLength(CommandData, BufRead - PacketSize);
+ Move(FClientSocket.ReadBuf[PacketSize], CommandData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(CommandData, 0);
+
+ if Assigned(FClientSocket.OnCommand) then
+ try
+ FClientSocket.OnCommand(FClientSocket,
+ FClientSocket.Line,
+ SenderAddr,
+ CommandHeader.Cmd,
+ CommandData,
+ CommandHeader.Flags,
+ CommandHeader.Sequence);
+ except
+ end;
+ end;
+ end
+ else if Magic = UDP_CHUNK_MAGIC then
+ begin
+ // ===============================================
+ // CHUNK PACKET - Auto-reassembly
+ // ===============================================
+
+ if BufRead >= SizeOf(TUdpChunkHeader) then
+ begin
+ // Direct header access
+ Move(FClientSocket.ReadBuf[0], ChunkHeader, SizeOf(ChunkHeader));
+
+ // Direct chunk data extraction
+ PacketSize := SizeOf(TUdpChunkHeader);
+ if BufRead > PacketSize then
+ begin
+ // Use buffer slice directly instead of copying
+ SetLength(ChunkData, BufRead - PacketSize);
+ Move(FClientSocket.ReadBuf[PacketSize], ChunkData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(ChunkData, 0);
+
+ // Ensure transfer exists (create if first chunk)
+ FClientSocket.FChunkManager.CreateTransferFromChunk(ChunkHeader.TransferID, ChunkHeader.TotalChunks,
+ ChunkHeader.OriginalCmd, ChunkHeader.OriginalFlags, ChunkHeader.OriginalSequence);
+
+ // Add chunk to manager
+ if FClientSocket.FChunkManager.AddChunk(ChunkHeader.TransferID, ChunkHeader.ChunkIndex, ChunkData) then
+ begin
+ // Only check completion if chunk was successfully added
+ if FClientSocket.FChunkManager.CompleteTransfer(ChunkHeader.TransferID, CompleteCmd, CompleteFlags, CompleteSequence, CompleteData) then
+ begin
+ // Transfer complete - fire OnCommand with reassembled data
+ if Assigned(FClientSocket.OnCommand) then
+ try
+ FClientSocket.OnCommand(FClientSocket,
+ FClientSocket.Line,
+ SenderAddr,
+ CompleteCmd,
+ CompleteData,
+ CompleteFlags,
+ CompleteSequence);
+ except
+ end;
+ end;
+ end;
+ end;
+ end
+ else
+ begin
+ // ===============================================
+ // RAW DATA PACKET
+ // ===============================================
+ if Assigned(FClientSocket.OnReadDatagram) then
+ try
+ FClientSocket.OnReadDatagram(FClientSocket,
+ FClientSocket.Line,
+ FClientSocket.ReadBuf,
+ BufRead,
+ SenderAddr);
+ except
+ end;
+ end;
+ end
+ else
+ begin
+ // ===============================================
+ // TOO SMALL - Raw data
+ // ===============================================
+ if Assigned(FClientSocket.OnReadDatagram) then
+ try
+ FClientSocket.OnReadDatagram(FClientSocket,
+ FClientSocket.Line,
+ FClientSocket.ReadBuf,
+ BufRead,
+ SenderAddr);
+ except
+ end;
+ end;
+ end;
+end;
+
+procedure TncUDPClientProcessor.ProcessEvent;
+begin
+ while (not Terminated) do
+ try
+ if FClientSocket.Line.Active then
+ begin
+ if ReadableAnySocket(FClientSocket.ReadSocketHandles, 100) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ if FClientSocket.EventsUseMainThread then
+ Synchronize(ProcessDatagram)
+ else
+ ProcessDatagram;
+ end;
+ end
+ else
+ Exit;
+ except
+ // Continue processing even after errors
+ end;
+end;
+
+{ TncChunkManager }
+
+constructor TncChunkManager.Create;
+begin
+ inherited Create;
+ FLock := TObject.Create;
+ FTransfers := TDictionary.Create;
+end;
+
+destructor TncChunkManager.Destroy;
+begin
+ FLock.Free;
+ FTransfers.Free;
+ inherited Destroy;
+end;
+
+function TncChunkManager.GenerateTransferID: UInt32;
+begin
+ // Simple transfer ID generation (timestamp + random)
+ Result := UInt32(GetTickCount) xor UInt32(Random(65536));
+end;
+
+procedure TncChunkManager.CleanupExpiredTransfers;
+var
+ Now: TDateTime;
+ TransferID: UInt32;
+ Transfer: TChunkTransfer;
+ ExpiredIDs: TArray;
+ I: Integer;
+begin
+ Now := System.SysUtils.Now;
+ SetLength(ExpiredIDs, 0);
+
+ // First pass: identify expired transfers
+ for Transfer in FTransfers.Values do
+ begin
+ if MilliSecondsBetween(Now, Transfer.LastActivity) > UDP_CHUNK_TIMEOUT then
+ begin
+ SetLength(ExpiredIDs, Length(ExpiredIDs) + 1);
+ ExpiredIDs[High(ExpiredIDs)] := Transfer.TransferID;
+ end;
+ end;
+
+ // Second pass: remove expired transfers
+ for I := 0 to High(ExpiredIDs) do
+ FTransfers.Remove(ExpiredIDs[I]);
+end;
+
+function TncChunkManager.StartTransfer(ACmd: Integer; AFlags: Byte; ASequence: UInt16; ATotalChunks: UInt16; AActualDataSize: UInt32): UInt32;
+var
+ Transfer: TChunkTransfer;
+ MaxDataSize: Integer;
+ BitArraySize: Integer;
+begin
+ TMonitor.Enter(FLock);
+ try
+ CleanupExpiredTransfers;
+
+ Transfer.TransferID := GenerateTransferID;
+ Transfer.OriginalCmd := ACmd;
+ Transfer.OriginalFlags := AFlags;
+ Transfer.OriginalSequence := ASequence;
+ Transfer.TotalChunks := ATotalChunks;
+ Transfer.FragmentsRemaining := ATotalChunks; // Initialize FragmentsRemaining
+ Transfer.LastActivity := System.SysUtils.Now;
+ Transfer.ActualDataSize := AActualDataSize; // Store the actual data size
+ Transfer.LastChunkSize := 0; // Will be set when last chunk is received
+
+ // Pre-allocate only maximum needed size (not over-allocate)
+ MaxDataSize := ATotalChunks * (UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader));
+ SetLength(Transfer.CompleteData, MaxDataSize);
+
+ // Calculate bit array size (32 fragments per UInt32)
+ BitArraySize := (ATotalChunks + 31) div 32;
+ SetLength(Transfer.Fragments, BitArraySize);
+ // Initialize all bits to 0
+ if BitArraySize > 0 then
+ FillChar(Transfer.Fragments[0], BitArraySize * SizeOf(UInt32), 0);
+
+ FTransfers.Add(Transfer.TransferID, Transfer);
+
+ Result := Transfer.TransferID;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+function TncChunkManager.CreateTransferFromChunk(ATransferID: UInt32; ATotalChunks: UInt16; AOriginalCmd: Integer; AOriginalFlags: Byte; AOriginalSequence: UInt16): Boolean;
+var
+ Transfer: TChunkTransfer;
+ MaxDataSize: Integer;
+ BitArraySize: Integer;
+begin
+ Result := False;
+ TMonitor.Enter(FLock);
+ try
+ // Check if transfer already exists
+ if FTransfers.TryGetValue(ATransferID, Transfer) then
+ begin
+ Result := True; // Already exists
+ Exit;
+ end;
+
+ // Create new transfer
+ Transfer.TransferID := ATransferID;
+ Transfer.OriginalCmd := AOriginalCmd;
+ Transfer.OriginalFlags := AOriginalFlags;
+ Transfer.OriginalSequence := AOriginalSequence;
+ Transfer.TotalChunks := ATotalChunks;
+ Transfer.FragmentsRemaining := ATotalChunks; // Initialize FragmentsRemaining
+ Transfer.LastActivity := System.SysUtils.Now;
+ Transfer.ActualDataSize := 0; // Will be calculated when all chunks received
+ Transfer.LastChunkSize := 0; // Will be set when last chunk is received
+
+ // Pre-allocate buffer for maximum possible data size
+ MaxDataSize := ATotalChunks * (UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader));
+ SetLength(Transfer.CompleteData, MaxDataSize);
+
+ // Calculate bit array size (32 fragments per UInt32)
+ BitArraySize := (ATotalChunks + 31) div 32;
+ SetLength(Transfer.Fragments, BitArraySize);
+ // Initialize all bits to 0
+ if BitArraySize > 0 then
+ FillChar(Transfer.Fragments[0], BitArraySize * SizeOf(UInt32), 0);
+
+ FTransfers.Add(Transfer.TransferID, Transfer);
+
+ Result := True;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+function TncChunkManager.AddChunk(ATransferID: UInt32; AChunkIndex: UInt16; const AChunkData: TBytes): Boolean;
+var
+ Transfer: TChunkTransfer;
+ ChunkOffset: Integer;
+ DataSize: Integer;
+ MaxChunkSize: Integer;
+begin
+ Result := False;
+ DataSize := Length(AChunkData);
+
+ // Quick validation before lock
+ if DataSize = 0 then Exit;
+
+ // Single lock operation only
+ TMonitor.Enter(FLock);
+ try
+ if FTransfers.TryGetValue(ATransferID, Transfer) then
+ begin
+ // Transfer exists - add chunk
+ if (AChunkIndex < Transfer.TotalChunks) and (not Transfer.IsFragmentReceived(AChunkIndex)) then
+ begin
+ // Calculate offset once and copy directly
+ MaxChunkSize := UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader);
+ ChunkOffset := AChunkIndex * MaxChunkSize;
+
+ // Direct memory operation
+ if ChunkOffset + DataSize <= Length(Transfer.CompleteData) then
+ begin
+ Move(AChunkData[0], Transfer.CompleteData[ChunkOffset], DataSize);
+
+ // Update tracking
+ Transfer.SetFragmentReceived(AChunkIndex);
+ Dec(Transfer.FragmentsRemaining);
+ Transfer.LastActivity := System.SysUtils.Now;
+
+ // Track last chunk size for accurate total calculation
+ if AChunkIndex = Transfer.TotalChunks - 1 then
+ Transfer.LastChunkSize := DataSize;
+
+ // If all chunks received, calculate actual data size
+ if Transfer.FragmentsRemaining = 0 then
+ Transfer.ActualDataSize := (Transfer.TotalChunks - 1) * MaxChunkSize + Transfer.LastChunkSize;
+
+ // Update the transfer back to dictionary once
+ FTransfers.AddOrSetValue(ATransferID, Transfer);
+ Result := True;
+ end;
+ end;
+ end;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+function TncChunkManager.CompleteTransfer(ATransferID: UInt32; out ACmd: Integer; out AFlags: Byte;
+ out ASequence: UInt16; out ACompleteData: TBytes): Boolean;
+var
+ Transfer: TChunkTransfer;
+begin
+ Result := False;
+ TMonitor.Enter(FLock);
+ try
+ if FTransfers.TryGetValue(ATransferID, Transfer) and (Transfer.FragmentsRemaining = 0) then
+ begin
+ // All chunks received - prepare output
+ ACmd := Transfer.OriginalCmd;
+ AFlags := Transfer.OriginalFlags;
+ ASequence := Transfer.OriginalSequence;
+
+ // Use the stored actual data size (from sender)
+ if Transfer.ActualDataSize > 0 then
+ begin
+ SetLength(ACompleteData, Transfer.ActualDataSize);
+ Move(Transfer.CompleteData[0], ACompleteData[0], Transfer.ActualDataSize);
+ end
+ else
+ SetLength(ACompleteData, 0);
+
+ // Remove completed transfer
+ FTransfers.Remove(ATransferID);
+ Result := True;
+ end;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+{ TChunkTransfer - bitwise fragment tracking }
+
+function TChunkTransfer.IsFragmentReceived(FragmentIndex: UInt16): Boolean;
+begin
+ if FragmentIndex >= TotalChunks then
+ begin
+ Result := False;
+ Exit;
+ end;
+ // Bitwise check: (fragments[fragmentNumber / 32] & (1u << (fragmentNumber % 32))) == 0
+ Result := (Fragments[FragmentIndex div 32] and (UInt32(1) shl (FragmentIndex mod 32))) <> 0;
+end;
+
+procedure TChunkTransfer.SetFragmentReceived(FragmentIndex: UInt16);
+begin
+ if FragmentIndex < TotalChunks then
+ // Bitwise set: fragments[fragmentNumber / 32] |= (1u << (fragmentNumber % 32))
+ Fragments[FragmentIndex div 32] := Fragments[FragmentIndex div 32] or (UInt32(1) shl (FragmentIndex mod 32));
+end;
+
+{ TncCustomUDPServerDual }
+
+constructor TncCustomUDPServerDual.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ Line := CreateLineObject;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ LineProcessor := TncUDPServerProcessor.Create(Self);
+ try
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+end;
+
+destructor TncCustomUDPServerDual.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+function TncCustomUDPServerDual.GetLine: TncLine;
+begin
+ Result := Line;
+end;
+
+function TncCustomUDPServerDual.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+procedure TncCustomUDPServerDual.DoActivate(aActivate: Boolean);
+begin
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ // CreateServerHandle will bind to all interfaces (0.0.0.0)
+ // through the AI_PASSIVE flag in ncLines.CreateServerHandle
+ TncLineInternal(Line).CreateServerHandle(FPort);
+
+ // Enable broadcast if needed
+ if Broadcast then
+ TncLineInternal(Line).EnableBroadcast;
+
+ // Set socket buffer sizes for better performance
+ try
+ TncLineInternal(Line).SetReceiveSize(ReadBufferLen);
+ TncLineInternal(Line).SetWriteSize(ReadBufferLen);
+ except
+ // Ignore buffer size errors
+ end;
+
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ if UseReaderThread then
+ begin
+ LineProcessor.WaitForReady;
+ LineProcessor.Run;
+ end;
+ end
+ else
+ begin
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ end;
+end;
+
+// 1. Base SendTo that does the actual sending
+procedure TncCustomUDPServerDual.SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage);
+var
+ AddrLen: Integer;
+ {$IFDEF MSWINDOWS}
+ BytesSent: Integer;
+ {$ELSE}
+ BytesSent: ssize_t;
+ {$ENDIF}
+ DestIP: string;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+ try
+ // Get destination address for logging/error reporting
+ DestIP := TncIPUtils.GetIPFromStorage(DestAddr);
+ // Set proper address length based on family
+ case DestAddr.ss_family of
+ AF_INET: AddrLen := SizeOf(TSockAddr);
+ AF_INET6: AddrLen := SizeOf(TSockAddrIn6);
+ else
+ AddrLen := SizeOf(TSockAddrStorage);
+ end;
+ {$IFDEF MSWINDOWS}
+ BytesSent := Winapi.Winsock2.sendto(Line.Handle, aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent = SOCKET_ERROR then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(WSAGetLastError)]);
+ {$ELSE}
+ BytesSent := Posix.SysSocket.sendto(Line.Handle, @aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent < 0 then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(GetLastError)]);
+ {$ENDIF}
+ except
+ on E: EIPError do
+ raise Exception.Create('Invalid destination address: ' + E.Message);
+ end;
+end;
+
+// 2. SendTo for byte arrays
+procedure TncCustomUDPServerDual.SendTo(const aBytes: TBytes; const DestAddr: TSockAddrStorage);
+begin
+ if Length(aBytes) > 0 then
+ SendTo(aBytes[0], Length(aBytes), DestAddr);
+end;
+
+// 3. SendTo for strings
+procedure TncCustomUDPServerDual.SendTo(const aStr: string; const DestAddr: TSockAddrStorage);
+var
+ bytes: TBytes;
+ len: Integer;
+begin
+ bytes := BytesOf(aStr);
+ len := Length(bytes);
+ if len > 0 then
+ SendTo(bytes[0], len, DestAddr);
+end;
+
+// UDP Command Protocol Methods for TncCustomUDPServerDual
+
+procedure TncCustomUDPServerDual.SendCommand(const DestAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ HeaderSize, DataSize, TotalSize: Integer;
+
+ // For normal sending
+ Packet: TBytes;
+ PacketHeader: TUdpCommandPacket;
+
+ // For chunking
+ ChunkHeader: TUdpChunkHeader;
+ ChunkPacket: TBytes;
+ TransferID: UInt32;
+ TotalChunks: UInt16;
+ ChunkIndex: UInt16;
+ CurrentPos: Integer;
+ ChunkDataSize: Integer;
+ MaxChunkDataSize: Integer;
+
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ // Calculate total command packet size
+ HeaderSize := SizeOf(TUdpCommandPacket);
+ DataSize := Length(aData);
+ TotalSize := HeaderSize + DataSize;
+
+ // Check if auto-chunking is needed
+ if TotalSize <= UDP_MAX_SAFE_PAYLOAD then
+ begin
+ // ===============================================
+ // NORMAL SEND - Single packet
+ // ===============================================
+ PacketHeader.Magic := UDP_COMMAND_MAGIC;
+ PacketHeader.Header.Cmd := aCmd;
+ PacketHeader.Header.Flags := aFlags;
+ PacketHeader.Header.Sequence := aSequence;
+
+ SetLength(Packet, TotalSize);
+ Move(PacketHeader, Packet[0], HeaderSize);
+ if DataSize > 0 then
+ Move(aData[0], Packet[HeaderSize], DataSize);
+
+ SendTo(Packet, DestAddr);
+ end
+ else
+ begin
+ // ===============================================
+ // AUTO-CHUNKING - Multiple packets
+ // ===============================================
+
+ MaxChunkDataSize := UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader);
+ TotalChunks := (DataSize + MaxChunkDataSize - 1) div MaxChunkDataSize;
+ TransferID := FChunkManager.StartTransfer(aCmd, aFlags, aSequence, TotalChunks, DataSize);
+
+ // Immediate packet sending for maximum speed
+ SetLength(ChunkPacket, UDP_MAX_SAFE_PAYLOAD);
+
+ ChunkHeader.Magic := UDP_CHUNK_MAGIC;
+ ChunkHeader.TransferID := TransferID;
+ ChunkHeader.TotalChunks := TotalChunks;
+ ChunkHeader.OriginalCmd := aCmd;
+ ChunkHeader.OriginalFlags := aFlags;
+ ChunkHeader.OriginalSequence := aSequence;
+
+ CurrentPos := 0;
+
+ // Send packets immediately without preparation overhead
+ for ChunkIndex := 0 to TotalChunks - 1 do
+ begin
+ ChunkDataSize := MaxChunkDataSize;
+ if ChunkIndex = TotalChunks - 1 then
+ ChunkDataSize := DataSize - CurrentPos;
+
+ ChunkHeader.ChunkIndex := ChunkIndex;
+
+ // Build and send packet immediately (zero overhead)
+ Move(ChunkHeader, ChunkPacket[0], SizeOf(TUdpChunkHeader));
+ if ChunkDataSize > 0 then
+ Move(aData[CurrentPos], ChunkPacket[SizeOf(TUdpChunkHeader)], ChunkDataSize);
+
+ // Send immediately at maximum speed (no delays, no burst preparation)
+ SendTo(ChunkPacket[0], SizeOf(TUdpChunkHeader) + ChunkDataSize, DestAddr);
+
+ Inc(CurrentPos, ChunkDataSize);
+ end;
+ end;
+end;
+
+procedure TncCustomUDPServerDual.SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+begin
+ // IPv6 broadcast validation
+ if (Family = afIPv6) and Broadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.');
+
+ // Build destination address based on family
+ case Family of
+ afIPv4:
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(aRemotePort);
+
+ var addr := inet_addr(PAnsiChar(AnsiString(aRemoteHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+
+ SendCommand(storage, aCmd, aData, aFlags, aSequence);
+ end;
+
+ afIPv6:
+ begin
+ if not TncIPUtils.IsIPv6ValidAddress(aRemoteHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(aRemotePort);
+
+ // Handle link-local address with scope ID
+ if TncIPUtils.IsLinkLocal(aRemoteHost) then
+ begin
+ var scopePos := Pos('%', aRemoteHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(aRemoteHost, 1, scopePos - 1);
+ var scope := Copy(aRemoteHost, scopePos + 1, Length(aRemoteHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ SendCommand(storage, aCmd, aData, aFlags, aSequence);
+ end;
+ end;
+end;
+
+function TncCustomUDPServerDual.Receive(aTimeout: Cardinal = 2000): TBytes;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ SenderIP: string;
+begin
+ if UseReaderThread then
+ raise Exception.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(Line.Handle, ReadBuf[0], Length(ReadBuf), 0,
+ PSockAddr(@SenderAddr)^, SenderAddrLen);
+
+ try
+ if BufRead > 0 then
+ begin
+ // Get sender IP for logging if needed
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ Result := Copy(ReadBuf, 0, BufRead);
+ end
+ else if BufRead = 0 then
+ begin
+ SetLength(Result, 0);
+ // Optional: raise Exception.Create('Connection closed by peer');
+ end
+ else
+ begin
+ SetLength(Result, 0);
+ {$IFDEF MSWINDOWS}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(GetLastError));
+ {$ENDIF}
+ end;
+ except
+ on E: EIPError do
+ begin
+ SetLength(Result, 0);
+ raise Exception.Create('Invalid sender address: ' + E.Message);
+ end;
+ end;
+end;
+
+{ TncUDPServerProcessor }
+
+constructor TncUDPServerProcessor.Create(aServerSocket: TncCustomUDPServerDual);
+begin
+ FServerSocket := aServerSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+
+procedure TncUDPServerProcessor.ProcessDatagram;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ Magic: UInt16;
+ CommandHeader: TUdpCommandHeader;
+ CommandData: TBytes;
+ PacketSize: Integer;
+
+ // For chunk handling
+ ChunkHeader: TUdpChunkHeader;
+ ChunkData: TBytes;
+ CompleteCmd: Integer;
+ CompleteFlags: Byte;
+ CompleteSequence: UInt16;
+ CompleteData: TBytes;
+begin
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(FServerSocket.Line.Handle,
+ FServerSocket.ReadBuf[0],
+ Length(FServerSocket.ReadBuf),
+ 0,
+ PSockAddr(@SenderAddr)^,
+ SenderAddrLen);
+
+ if BufRead > 0 then
+ begin
+ // Check minimum size for any structured packet
+ if (BufRead >= SizeOf(UInt16)) then
+ begin
+ // Extract magic number to check protocol type
+ Move(FServerSocket.ReadBuf[0], Magic, SizeOf(Magic));
+
+ if Magic = UDP_COMMAND_MAGIC then
+ begin
+ // ===============================================
+ // NORMAL COMMAND PACKET
+ // ===============================================
+ if BufRead >= SizeOf(TUdpCommandPacket) then
+ begin
+ Move(FServerSocket.ReadBuf[SizeOf(UInt16)], CommandHeader, SizeOf(CommandHeader));
+
+ PacketSize := SizeOf(TUdpCommandPacket);
+ if BufRead > PacketSize then
+ begin
+ SetLength(CommandData, BufRead - PacketSize);
+ Move(FServerSocket.ReadBuf[PacketSize], CommandData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(CommandData, 0);
+
+ if Assigned(FServerSocket.OnCommand) then
+ try
+ FServerSocket.OnCommand(FServerSocket,
+ FServerSocket.Line,
+ SenderAddr,
+ CommandHeader.Cmd,
+ CommandData,
+ CommandHeader.Flags,
+ CommandHeader.Sequence);
+ except
+ end;
+ end;
+ end
+ else if Magic = UDP_CHUNK_MAGIC then
+ begin
+ // ===============================================
+ // CHUNK PACKET - Auto-reassembly
+ // ===============================================
+
+ if BufRead >= SizeOf(TUdpChunkHeader) then
+ begin
+ // Direct header access
+ Move(FServerSocket.ReadBuf[0], ChunkHeader, SizeOf(ChunkHeader));
+
+ // Direct chunk data extraction
+ PacketSize := SizeOf(TUdpChunkHeader);
+ if BufRead > PacketSize then
+ begin
+ // Use buffer slice directly instead of copying
+ SetLength(ChunkData, BufRead - PacketSize);
+ Move(FServerSocket.ReadBuf[PacketSize], ChunkData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(ChunkData, 0);
+
+ // Ensure transfer exists (create if first chunk)
+ FServerSocket.FChunkManager.CreateTransferFromChunk(ChunkHeader.TransferID, ChunkHeader.TotalChunks,
+ ChunkHeader.OriginalCmd, ChunkHeader.OriginalFlags, ChunkHeader.OriginalSequence);
+
+ // Add chunk to manager
+ if FServerSocket.FChunkManager.AddChunk(ChunkHeader.TransferID, ChunkHeader.ChunkIndex, ChunkData) then
+ begin
+ // Only check completion if chunk was successfully added
+ if FServerSocket.FChunkManager.CompleteTransfer(ChunkHeader.TransferID, CompleteCmd, CompleteFlags, CompleteSequence, CompleteData) then
+ begin
+ // Transfer complete - fire OnCommand with reassembled data
+ if Assigned(FServerSocket.OnCommand) then
+ try
+ FServerSocket.OnCommand(FServerSocket,
+ FServerSocket.Line,
+ SenderAddr,
+ CompleteCmd,
+ CompleteData,
+ CompleteFlags,
+ CompleteSequence);
+ except
+ end;
+ end;
+ end;
+ end;
+ end
+ else
+ begin
+ // ===============================================
+ // RAW DATA PACKET
+ // ===============================================
+ if Assigned(FServerSocket.OnReadDatagram) then
+ try
+ FServerSocket.OnReadDatagram(FServerSocket, FServerSocket.Line,
+ FServerSocket.ReadBuf, BufRead, SenderAddr);
+ except
+ end;
+ end;
+ end
+ else
+ begin
+ // ===============================================
+ // TOO SMALL - Raw data
+ // ===============================================
+ if Assigned(FServerSocket.OnReadDatagram) then
+ try
+ FServerSocket.OnReadDatagram(FServerSocket, FServerSocket.Line,
+ FServerSocket.ReadBuf, BufRead, SenderAddr);
+ except
+ end;
+ end;
+ end;
+end;
+
+procedure TncUDPServerProcessor.ProcessEvent;
+begin
+ if FServerSocket.EventsUseMainThread then
+ while FServerSocket.Active and (not Terminated) do
+ try
+ if ReadableAnySocket(FServerSocket.ReadSocketHandles, 500) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ Synchronize(ProcessDatagram);
+ end;
+ except
+ end
+ else
+ while FServerSocket.Active and (not Terminated) do
+ try
+ if ReadableAnySocket(FServerSocket.ReadSocketHandles, 500) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ ProcessDatagram;
+ end;
+ except
+ end;
+end;
+
+end.
+
+
+
+
diff --git a/Source/ncUDPSocketsLCP.pas b/Source/ncUDPSocketsLCP.pas
new file mode 100644
index 0000000..48b35d0
--- /dev/null
+++ b/Source/ncUDPSocketsLCP.pas
@@ -0,0 +1,1941 @@
+unit ncUDPSocketsLCP;
+// /////////////////////////////////////////////////////////////////////////////
+//
+// NetCom7 Package - UDP Socket Components (LCP Only - Protocol Only)
+//
+// This unit implements UDP Server and UDP Client components with
+// lightweight command protocol support ONLY (no raw UDP support)
+//
+// 25/07/2025- by J.Pauwels
+// - Replace TCriticalSection to TMonitor
+//
+// 23/07/2025
+// - Removed raw UDP support (OnReadData)
+// - Protocol-only implementation
+// Currently implemented :
+// - Broadcast
+// - Lightweight Command Protocol (LCP) ONLY
+// - Auto-chunking for large data
+//
+// Written by J.Pauwels
+//
+// /////////////////////////////////////////////////////////////////////////////
+
+
+{$IF CompilerVersion >= 21.0}
+{$WEAKLINKRTTI ON}
+{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}
+{$ENDIF}
+
+interface
+
+uses
+{$IFDEF MSWINDOWS}
+ Winapi.Windows, Winapi.Winsock2,
+{$ELSE}
+ Posix.SysSocket, Posix.Unistd,
+{$ENDIF}
+ System.Classes, System.SysUtils, System.SyncObjs, System.Math, System.Diagnostics, System.TimeSpan, System.DateUtils,
+ ncLines, ncSocketList, ncThreads, ncIPUtils, System.Generics.Collections;
+
+const
+ DefPort = 16233;
+ DefHost = '';
+ DefReadBufferLen = 64 * 1024; // 64KB default for UDP
+ DefReaderThreadPriority = ntpNormal;
+ DefEventsUseMainThread = False;
+ DefUseReaderThread = True;
+ DefBroadcast = False;
+ DefFamily = afIPv4;
+
+ // UDP Performance constants
+ UDP_COMMAND_MAGIC = $4E43; // 'NC'
+ UDP_CHUNK_MAGIC = $4E44; // 'ND' signature for chunk packets
+ UDP_MAX_SAFE_PAYLOAD = 1392; // Optimal MTU (avoids fragmentation)
+ UDP_CHUNK_TIMEOUT = 5000; // 5 seconds timeout for incomplete transfers
+
+type
+ // UDP Command Header Structure
+ TUdpCommandHeader = packed record
+ Cmd: Integer; // Command ID (matches ncSocketsPro)
+ Flags: Byte; // Command flags for future extensibility
+ Sequence: UInt16; // Sequence number for tracking/ordering
+ end;
+
+ // Complete UDP Command Packet Structure
+ TUdpCommandPacket = packed record
+ Magic: UInt16; // Protocol detection signature
+ Header: TUdpCommandHeader; // Command header
+ // Variable data follows after this structure
+ end;
+
+ // UDP Chunk Header Structure (for auto-chunking large commands)
+ TUdpChunkHeader = packed record
+ Magic: UInt16; // Chunk magic signature ($4E44 = 'ND')
+ TransferID: UInt32; // Unique transfer identifier
+ ChunkIndex: UInt16; // Current chunk number (0-based)
+ TotalChunks: UInt16; // Total number of chunks
+ OriginalCmd: Integer; // Original command ID
+ OriginalFlags: Byte; // Original command flags
+ OriginalSequence: UInt16; // Original sequence number
+ end;
+
+ // Pointer type for zero-copy operations
+ PUdpChunkHeader = ^TUdpChunkHeader;
+
+ // Chunk reassembly tracking
+ TChunkTransfer = record
+ TransferID: UInt32;
+ OriginalCmd: Integer;
+ OriginalFlags: Byte;
+ OriginalSequence: UInt16;
+ TotalChunks: UInt16;
+ FragmentsRemaining: UInt16;
+ LastActivity: TDateTime;
+ CompleteData: TBytes; // Pre-allocated full buffer
+ Fragments: array of UInt32; // Bitwise tracking
+ ActualDataSize: UInt32; // Real size of the complete data (calculated when complete)
+ LastChunkSize: UInt16; // Size of the last chunk (for accurate total calculation)
+
+ // Helper methods for bitwise operations
+ function IsFragmentReceived(FragmentIndex: UInt16): Boolean;
+ procedure SetFragmentReceived(FragmentIndex: UInt16);
+ end;
+
+ // Chunk transfer manager
+ TncChunkManager = class
+ private
+ FTransfers: TDictionary; // Hash table for O(1) lookup
+ FLock: TObject; // TMonitor synchronization object
+ function GenerateTransferID: UInt32;
+ procedure CleanupExpiredTransfers;
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function StartTransfer(ACmd: Integer; AFlags: Byte; ASequence: UInt16; ATotalChunks: UInt16; AActualDataSize: UInt32): UInt32;
+ function CreateTransferFromChunk(ATransferID: UInt32; ATotalChunks: UInt16; AOriginalCmd: Integer; AOriginalFlags: Byte; AOriginalSequence: UInt16): Boolean;
+ function AddChunk(ATransferID: UInt32; AChunkIndex: UInt16; const AChunkData: TBytes): Boolean;
+ function CompleteTransfer(ATransferID: UInt32; out ACmd: Integer; out AFlags: Byte;
+ out ASequence: UInt16; out ACompleteData: TBytes): Boolean;
+ end;
+
+resourcestring
+ ECannotSetPortWhileSocketActiveStr = 'Cannot set Port property while socket is active';
+ ECannotSetHostWhileSocketActiveStr = 'Cannot set Host property while socket is active';
+ ECannotSendWhileSocketInactiveStr = 'Cannot send data while socket is inactive';
+ ECannotSetUseReaderThreadWhileSocketActiveStr = 'Cannot set UseReaderThread property while socket is active';
+ ECannotReceiveIfUseReaderThreadStr = 'Cannot receive data if UseReaderThread is set. Use OnCommand event handler to get protocol data or set UseReaderThread property to false';
+ ECannotSetFamilyWhileConnectionIsActiveStr = 'Cannot set Family property whilst the connection is active';
+type
+ EPropertySetError = class(Exception);
+
+ // Event types for UDP
+ TncOnDatagramEvent = procedure(Sender: TObject; aLine: TncLine;const aBuf: TBytes; aBufCount: Integer;const SenderAddr: TSockAddrStorage) of object;
+
+ // UDP Command Protocol Event
+ TncOnUDPCommandEvent = procedure(Sender: TObject; aLine: TncLine; const aSenderAddr: TSockAddrStorage;
+ aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16) of object;
+
+
+ // Base UDP Socket class
+ TncUDPBaseLCP = class(TComponent)
+ private
+ FInitActive: Boolean;
+ FFamily: TAddressType;
+ FPort: Integer;
+ FEventsUseMainThread: Boolean;
+ FBroadcast: Boolean;
+ FLine: TncLine;
+ FReadBufferLen: Integer;
+ FOnCommand: TncOnUDPCommandEvent;
+ FChunkManager: TncChunkManager; // For auto-chunking large commands
+ function GetReadBufferLen: Integer;
+ procedure SetReadBufferLen(const Value: Integer);
+ function GetActive: Boolean; virtual; abstract;
+ procedure SetActive(const Value: Boolean);
+ function GetFamily: TAddressType;
+ procedure SetFamily(const Value: TAddressType);
+ function GetPort: Integer;
+ procedure SetPort(const Value: Integer);
+ function GetReaderThreadPriority: TncThreadPriority;
+ procedure SetReaderThreadPriority(const Value: TncThreadPriority);
+ function GetBroadcast: Boolean;
+ procedure SetBroadcast(const Value: Boolean);
+
+ private
+ FUseReaderThread: Boolean;
+ procedure DoActivate(aActivate: Boolean); virtual; abstract;
+ procedure SetUseReaderThread(const Value: Boolean);
+ protected
+ PropertyLock: TObject; // TMonitor synchronization object
+ ReadBuf: TBytes;
+ procedure Loaded; override;
+ function CreateLineObject: TncLine; virtual;
+ function GetLine: TncLine; virtual; abstract;
+ public
+ LineProcessor: TncReadyThread;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ function Kind: TSocketType; virtual;
+
+ property Active: Boolean read GetActive write SetActive default False;
+ property Family: TAddressType read GetFamily write SetFamily default afIPv4;
+ property Port: Integer read GetPort write SetPort default DefPort;
+ property ReaderThreadPriority: TncThreadPriority read GetReaderThreadPriority write SetReaderThreadPriority default DefReaderThreadPriority;
+ property EventsUseMainThread: Boolean read FEventsUseMainThread write FEventsUseMainThread default DefEventsUseMainThread;
+ property UseReaderThread: Boolean read FUseReaderThread write SetUseReaderThread default DefUseReaderThread;
+ property Broadcast: Boolean read GetBroadcast write SetBroadcast default DefBroadcast;
+ property OnCommand: TncOnUDPCommandEvent read FOnCommand write FOnCommand;
+ property ReadBufferLen: Integer read GetReadBufferLen write SetReadBufferLen default DefReadBufferLen;
+ published
+ end;
+
+ // UDP Client implementation
+ TncUDPClientProcessor = class;
+
+ TncCustomUDPClientLCP = class(TncUDPBaseLCP)
+ private
+ FHost: string;
+ function GetActive: Boolean; override;
+ procedure SetHost(const Value: string);
+ function GetHost: string;
+ protected
+ procedure DoActivate(aActivate: Boolean); override;
+ function GetLine: TncLine; override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aBytes: TBytes;const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aStr: string; const DestAddr: TSockAddrStorage); overload;
+ procedure Send(const aBuf; aBufSize: Integer); overload;
+ procedure Send(const aBytes: TBytes); overload;
+ procedure Send(const aStr: string); overload;
+
+ // UDP Command Protocol Methods
+ procedure SendCommand(aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+ procedure SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+
+ function Receive(aTimeout: Cardinal = 2000): TBytes;
+ property Host: string read GetHost write SetHost;
+ end;
+
+ TncUDPClientLCP = class(TncCustomUDPClientLCP)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property Host;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property Broadcast;
+ property ReadBufferLen;
+ property OnCommand;
+ end;
+
+ TncUDPClientProcessor = class(TncReadyThread)
+ private
+ FClientSocket: TncCustomUDPClientLCP;
+ public
+ ReadySocketsChanged: Boolean;
+ constructor Create(aClientSocket: TncCustomUDPClientLCP);
+ procedure ProcessDatagram; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // UDP Server implementation
+ TncUDPServerProcessor = class;
+
+ TncCustomUDPServerLCP = class(TncUDPBaseLCP)
+ private
+ function GetActive: Boolean; override;
+ protected
+ procedure DoActivate(aActivate: Boolean); override;
+ function GetLine: TncLine; override;
+ public
+ ReadSocketHandles: TSocketHandleArray;
+ Line: TncLine;
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aBytes: TBytes;const DestAddr: TSockAddrStorage); overload;
+ procedure SendTo(const aStr: string; const DestAddr: TSockAddrStorage); overload;
+
+ // UDP Command Protocol Methods
+ procedure SendCommand(const DestAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+ procedure SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte = 0; aSequence: UInt16 = 0); overload;
+
+ function Receive(aTimeout: Cardinal = 2000): TBytes;
+ end;
+
+ TncUDPServerLCP = class(TncCustomUDPServerLCP)
+ published
+ property Active;
+ property Family;
+ property Port;
+ property ReaderThreadPriority;
+ property EventsUseMainThread;
+ property UseReaderThread;
+ property Broadcast;
+ property ReadBufferLen;
+ property OnCommand;
+ end;
+
+ TncUDPServerProcessor = class(TncReadyThread)
+ private
+ FServerSocket: TncCustomUDPServerLCP;
+ public
+ ReadySocketsChanged: Boolean;
+ constructor Create(aServerSocket: TncCustomUDPServerLCP);
+ procedure ProcessDatagram; inline;
+ procedure ProcessEvent; override;
+ end;
+
+ // We bring in TncLine so that a form that uses our components does
+ // not have to reference ncLines unit to get the type
+ TncLine = ncLines.TncLine;
+
+ // We make a descendant of TncLine so that we can access the API functions.
+ // These API functions are not made puclic in TncLine so that the user cannot
+ // mangle up the line
+ TncLineInternal = class(TncLine);
+
+implementation
+
+{ TncUDPBaseLCP }
+
+constructor TncUDPBaseLCP.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ PropertyLock := TObject.Create;
+
+ FInitActive := False;
+ FFamily := DefFamily;
+ FPort := DefPort;
+ FEventsUseMainThread := DefEventsUseMainThread;
+ FUseReaderThread := DefUseReaderThread;
+ FBroadcast := DefBroadcast;
+ FReadBufferLen := DefReadBufferLen;
+ FOnCommand := nil;
+ FChunkManager := TncChunkManager.Create; // Initialize the chunk manager
+
+ SetLength(ReadBuf, DefReadBufferLen);
+
+end;
+
+function TncUDPBaseLCP.Kind: TSocketType;
+begin
+ Result := stUDP;
+end;
+
+destructor TncUDPBaseLCP.Destroy;
+begin
+ PropertyLock.Free;
+ FChunkManager.Free; // Free the chunk manager
+ inherited Destroy;
+end;
+
+procedure TncUDPBaseLCP.Loaded;
+begin
+ inherited Loaded;
+ if FInitActive then
+ DoActivate(True);
+end;
+
+function TncUDPBaseLCP.CreateLineObject: TncLine;
+begin
+ Result := TncLine.Create;
+ TncLineInternal(Result).SetKind(Kind);
+ TncLineInternal(Result).SetFamily(FFamily);
+end;
+
+procedure TncUDPBaseLCP.SetActive(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ if not(csLoading in ComponentState) then
+ DoActivate(Value);
+ FInitActive := GetActive;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseLCP.GetFamily: TAddressType;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FFamily;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseLCP.SetFamily(const Value: TAddressType);
+begin
+ if not(csLoading in ComponentState) then
+ begin
+ if Active then
+ raise EPropertySetError.Create
+ (ECannotSetFamilyWhileConnectionIsActiveStr);
+ end;
+
+ TMonitor.Enter(PropertyLock);
+ try
+ // Update base class family
+ FFamily := Value;
+
+ // Update the Line's family
+ if FLine <> nil then
+ begin
+ TncLineInternal(FLine).SetFamily(Value);
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseLCP.GetPort: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FPort;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseLCP.SetPort(const Value: Integer);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetPortWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FPort := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseLCP.GetReaderThreadPriority: TncThreadPriority;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := ToNcThreadPriority(LineProcessor.Priority);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseLCP.SetReaderThreadPriority(const Value: TncThreadPriority);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ try
+ LineProcessor.Priority := FromNcThreadPriority(Value);
+ except
+ // Some android devices cannot handle changing priority
+ end;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseLCP.GetBroadcast: Boolean;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FBroadcast;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseLCP.SetBroadcast(const Value: Boolean);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FBroadcast := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseLCP.SetUseReaderThread(const Value: Boolean);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetUseReaderThreadWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FUseReaderThread := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+function TncUDPBaseLCP.GetReadBufferLen: Integer;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FReadBufferLen;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncUDPBaseLCP.SetReadBufferLen(const Value: Integer);
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ FReadBufferLen := Value;
+ SetLength(ReadBuf, FReadBufferLen);
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+{ TncCustomUDPClientLCP }
+
+constructor TncCustomUDPClientLCP.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FHost := DefHost;
+
+ Line := CreateLineObject;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ LineProcessor := TncUDPClientProcessor.Create(Self);
+ try
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+end;
+
+destructor TncCustomUDPClientLCP.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+function TncCustomUDPClientLCP.GetLine: TncLine;
+begin
+ Result := Line;
+end;
+
+procedure TncCustomUDPClientLCP.DoActivate(aActivate: Boolean);
+begin
+ // Exit if socket is already in requested state
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+ try
+
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ // Create socket handle and establish connection
+ TncLineInternal(Line).CreateClientHandle(FHost, FPort, GetBroadcast);
+
+ // Enable broadcast mode if requested
+ if GetBroadcast then
+ TncLineInternal(Line).EnableBroadcast;
+
+ // Configure socket buffer sizes for optimal performance
+ try
+ TncLineInternal(Line).SetReceiveSize(GetReadBufferLen);
+ TncLineInternal(Line).SetWriteSize(GetReadBufferLen);
+ except
+ on E: Exception do
+ begin
+ TncLineInternal(Line).DestroyHandle;
+ raise;
+ end;
+ end;
+
+ // Initialize socket handle array for reading
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ // Start reader thread if enabled
+ if UseReaderThread then
+ LineProcessor.Run;
+ except
+ on E: Exception do
+ begin
+ // Clean up on activation failure
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ raise;
+ end;
+ end;
+ end
+ else
+ begin
+ // Clean up when deactivating
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ end;
+end;
+
+function TncCustomUDPClientLCP.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+function TncCustomUDPClientLCP.GetHost: string;
+begin
+ TMonitor.Enter(PropertyLock);
+ try
+ Result := FHost;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomUDPClientLCP.SetHost(const Value: string);
+begin
+ if not(csLoading in ComponentState) then
+ if Active then
+ raise EPropertySetError.Create(ECannotSetHostWhileSocketActiveStr);
+
+ TMonitor.Enter(PropertyLock);
+ try
+ FHost := Value;
+ finally
+ TMonitor.Exit(PropertyLock);
+ end;
+end;
+
+procedure TncCustomUDPClientLCP.Send(const aBuf; aBufSize: Integer);
+var
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ case Family of
+ afIPv4:
+ begin
+ if GetBroadcast then
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(FPort);
+
+ // Use Winsock API directly for IPv4 broadcast
+ var addr := inet_addr(PAnsiChar(AnsiString(FHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+
+ SendTo(aBuf, aBufSize, storage);
+ end
+ else
+ TncLineInternal(Line).SendBuffer(aBuf, aBufSize);
+ end;
+
+ afIPv6:
+ begin
+ if GetBroadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.')
+ else if FHost = '' then
+ raise Exception.Create('Host address cannot be empty for IPv6')
+ else
+ begin
+ // Validate IPv6 address format
+ if not TncIPUtils.IsIPv6ValidAddress(FHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(FPort);
+
+ // Handle link-local address with scope ID
+ if TncIPUtils.IsLinkLocal(FHost) then
+ begin
+ var scopePos := Pos('%', FHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(FHost, 1, scopePos - 1);
+ var scope := Copy(FHost, scopePos + 1, Length(FHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ // Convert the address part without scope ID
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(FHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(FHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ SendTo(aBuf, aBufSize, storage);
+ end;
+ end;
+ end;
+end;
+
+procedure TncCustomUDPClientLCP.Send(const aBytes: TBytes);
+begin
+ if Length(aBytes) > 0 then
+ Send(aBytes[0], Length(aBytes));
+end;
+
+procedure TncCustomUDPClientLCP.Send(const aStr: string);
+begin
+ Send(BytesOf(aStr));
+end;
+
+// UDP Command Protocol Methods for TncCustomUDPClientLCP
+
+procedure TncCustomUDPClientLCP.SendCommand(aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+begin
+ SendCommand(FHost, FPort, aCmd, aData, aFlags, aSequence);
+end;
+
+procedure TncCustomUDPClientLCP.SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ HeaderSize, DataSize, TotalSize: Integer;
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+
+ // For normal sending
+ Packet: TBytes;
+ PacketHeader: TUdpCommandPacket;
+
+ // For chunking
+ ChunkHeader: TUdpChunkHeader;
+ ChunkPacket: TBytes;
+ TransferID: UInt32;
+ TotalChunks: UInt16;
+ ChunkIndex: UInt16;
+ CurrentPos: Integer;
+ ChunkDataSize: Integer;
+ MaxChunkDataSize: Integer;
+
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ // IPv6 broadcast validation
+ if (Family = afIPv6) and GetBroadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.');
+
+ // Calculate total command packet size
+ HeaderSize := SizeOf(TUdpCommandPacket);
+ DataSize := Length(aData);
+ TotalSize := HeaderSize + DataSize;
+
+ // Build destination address first (common for both paths)
+ case Family of
+ afIPv4:
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(aRemotePort);
+ var addr := inet_addr(PAnsiChar(AnsiString(aRemoteHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+ end;
+
+ afIPv6:
+ begin
+ if not TncIPUtils.IsIPv6ValidAddress(aRemoteHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(aRemotePort);
+ if TncIPUtils.IsLinkLocal(aRemoteHost) then
+ begin
+ var scopePos := Pos('%', aRemoteHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(aRemoteHost, 1, scopePos - 1);
+ var scope := Copy(aRemoteHost, scopePos + 1, Length(aRemoteHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end;
+ end;
+
+ // Check if auto-chunking is needed
+ if TotalSize <= UDP_MAX_SAFE_PAYLOAD then
+ begin
+ // ===============================================
+ // NORMAL SEND - Single packet
+ // ===============================================
+
+ PacketHeader.Magic := UDP_COMMAND_MAGIC;
+ PacketHeader.Header.Cmd := aCmd;
+ PacketHeader.Header.Flags := aFlags;
+ PacketHeader.Header.Sequence := aSequence;
+
+ SetLength(Packet, TotalSize);
+ Move(PacketHeader, Packet[0], HeaderSize);
+ if DataSize > 0 then
+ Move(aData[0], Packet[HeaderSize], DataSize);
+
+ SendTo(Packet, storage);
+ end
+ else
+ begin
+ // ===============================================
+ // AUTO-CHUNKING - Multiple packets
+ // ===============================================
+
+ MaxChunkDataSize := UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader);
+ TotalChunks := (DataSize + MaxChunkDataSize - 1) div MaxChunkDataSize;
+ TransferID := FChunkManager.StartTransfer(aCmd, aFlags, aSequence, TotalChunks, DataSize);
+
+ // Immediate packet sending for maximum speed
+ SetLength(ChunkPacket, UDP_MAX_SAFE_PAYLOAD);
+
+ ChunkHeader.Magic := UDP_CHUNK_MAGIC;
+ ChunkHeader.TransferID := TransferID;
+ ChunkHeader.TotalChunks := TotalChunks;
+ ChunkHeader.OriginalCmd := aCmd;
+ ChunkHeader.OriginalFlags := aFlags;
+ ChunkHeader.OriginalSequence := aSequence;
+
+ CurrentPos := 0;
+
+ // Send packets immediately without preparation overhead
+ for ChunkIndex := 0 to TotalChunks - 1 do
+ begin
+ ChunkDataSize := MaxChunkDataSize;
+ if ChunkIndex = TotalChunks - 1 then
+ ChunkDataSize := DataSize - CurrentPos;
+
+ ChunkHeader.ChunkIndex := ChunkIndex;
+
+ // Build and send packet immediately (zero overhead)
+ Move(ChunkHeader, ChunkPacket[0], SizeOf(TUdpChunkHeader));
+ if ChunkDataSize > 0 then
+ Move(aData[CurrentPos], ChunkPacket[SizeOf(TUdpChunkHeader)], ChunkDataSize);
+
+ // Send immediately at maximum speed (no delays, no burst preparation)
+ SendTo(ChunkPacket[0], SizeOf(TUdpChunkHeader) + ChunkDataSize, storage);
+
+ Inc(CurrentPos, ChunkDataSize);
+ end;
+ end;
+end;
+
+// 1. Base SendTo that does the actual sending
+procedure TncCustomUDPClientLCP.SendTo(const aBuf; aBufSize: Integer;
+ const DestAddr: TSockAddrStorage);
+var
+ AddrLen: Integer;
+ {$IFDEF MSWINDOWS}
+ BytesSent: Integer;
+ {$ELSE}
+ BytesSent: ssize_t;
+ {$ENDIF}
+ DestIP: string;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ try
+ // Get destination address for logging/error reporting
+ DestIP := TncIPUtils.GetIPFromStorage(DestAddr);
+
+ // Set proper address length based on family
+ case DestAddr.ss_family of
+ AF_INET: AddrLen := SizeOf(TSockAddr);
+ AF_INET6: AddrLen := SizeOf(TSockAddrIn6);
+ else
+ AddrLen := SizeOf(TSockAddrStorage);
+ end;
+
+ {$IFDEF MSWINDOWS}
+ BytesSent := Winapi.Winsock2.sendto(Line.Handle, aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent = SOCKET_ERROR then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(WSAGetLastError)]);
+ {$ELSE}
+ BytesSent := Posix.SysSocket.sendto(Line.Handle, @aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent < 0 then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(GetLastError)]);
+ {$ENDIF}
+ except
+ on E: EIPError do
+ raise Exception.Create('Invalid destination address: ' + E.Message);
+ end;
+end;
+
+// 2. SendTo for byte arrays
+procedure TncCustomUDPClientLCP.SendTo(const aBytes: TBytes;
+ const DestAddr: TSockAddrStorage);
+begin
+ if Length(aBytes) > 0 then
+ SendTo(aBytes[0], Length(aBytes), DestAddr);
+end;
+
+// 3. SendTo for strings
+procedure TncCustomUDPClientLCP.SendTo(const aStr: string; const DestAddr: TSockAddrStorage);
+var
+ bytes: TBytes;
+ len: Integer;
+begin
+ bytes := BytesOf(aStr);
+ len := Length(bytes);
+ if len > 0 then
+ SendTo(bytes[0], len, DestAddr);
+end;
+
+function TncCustomUDPClientLCP.Receive(aTimeout: Cardinal = 2000): TBytes;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ SenderIP: string;
+begin
+ if UseReaderThread then
+ raise Exception.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(Line.Handle, ReadBuf[0], Length(ReadBuf), 0,
+ PSockAddr(@SenderAddr)^, SenderAddrLen);
+
+ try
+ if BufRead > 0 then
+ begin
+ // Get sender IP for logging if needed
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ Result := Copy(ReadBuf, 0, BufRead);
+ end
+ else if BufRead = 0 then
+ begin
+ SetLength(Result, 0);
+ // Optional: raise Exception.Create('Connection closed by peer');
+ end
+ else
+ begin
+ SetLength(Result, 0);
+ {$IFDEF MSWINDOWS}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(GetLastError));
+ {$ENDIF}
+ end;
+ except
+ on E: EIPError do
+ begin
+ SetLength(Result, 0);
+ raise Exception.Create('Invalid sender address: ' + E.Message);
+ end;
+ end;
+end;
+
+{ TncUDPClientProcessor }
+
+constructor TncUDPClientProcessor.Create(aClientSocket: TncCustomUDPClientLCP);
+begin
+ FClientSocket := aClientSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+procedure TncUDPClientProcessor.ProcessDatagram;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ Magic: UInt16;
+ CommandHeader: TUdpCommandHeader;
+ CommandData: TBytes;
+ PacketSize: Integer;
+
+ // For chunk handling
+ ChunkHeader: TUdpChunkHeader;
+ ChunkData: TBytes;
+ CompleteCmd: Integer;
+ CompleteFlags: Byte;
+ CompleteSequence: UInt16;
+ CompleteData: TBytes;
+begin
+ // Initialize sender address structure
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ // Receive datagram with proper address structure
+ BufRead := recvfrom(FClientSocket.Line.Handle,
+ FClientSocket.ReadBuf[0],
+ Length(FClientSocket.ReadBuf),
+ 0,
+ PSockAddr(@SenderAddr)^,
+ SenderAddrLen);
+
+ if BufRead > 0 then
+ begin
+ // Check minimum size for any structured packet
+ if (BufRead >= SizeOf(UInt16)) then
+ begin
+ // Extract magic number to check protocol type
+ Move(FClientSocket.ReadBuf[0], Magic, SizeOf(Magic));
+
+ if Magic = UDP_COMMAND_MAGIC then
+ begin
+ // ===============================================
+ // NORMAL COMMAND PACKET
+ // ===============================================
+ if BufRead >= SizeOf(TUdpCommandPacket) then
+ begin
+ Move(FClientSocket.ReadBuf[SizeOf(UInt16)], CommandHeader, SizeOf(CommandHeader));
+
+ PacketSize := SizeOf(TUdpCommandPacket);
+ if BufRead > PacketSize then
+ begin
+ SetLength(CommandData, BufRead - PacketSize);
+ Move(FClientSocket.ReadBuf[PacketSize], CommandData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(CommandData, 0);
+
+ if Assigned(FClientSocket.OnCommand) then
+ try
+ FClientSocket.OnCommand(FClientSocket,
+ FClientSocket.Line,
+ SenderAddr,
+ CommandHeader.Cmd,
+ CommandData,
+ CommandHeader.Flags,
+ CommandHeader.Sequence);
+ except
+ end;
+ end;
+ end
+ else if Magic = UDP_CHUNK_MAGIC then
+ begin
+ // ===============================================
+ // CHUNK PACKET - Auto-reassembly
+ // ===============================================
+
+ if BufRead >= SizeOf(TUdpChunkHeader) then
+ begin
+ // Direct header access
+ Move(FClientSocket.ReadBuf[0], ChunkHeader, SizeOf(ChunkHeader));
+
+ // Direct chunk data extraction
+ PacketSize := SizeOf(TUdpChunkHeader);
+ if BufRead > PacketSize then
+ begin
+ // Use buffer slice directly instead of copying
+ SetLength(ChunkData, BufRead - PacketSize);
+ Move(FClientSocket.ReadBuf[PacketSize], ChunkData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(ChunkData, 0);
+
+ // Ensure transfer exists (create if first chunk)
+ FClientSocket.FChunkManager.CreateTransferFromChunk(ChunkHeader.TransferID, ChunkHeader.TotalChunks,
+ ChunkHeader.OriginalCmd, ChunkHeader.OriginalFlags, ChunkHeader.OriginalSequence);
+
+ // Add chunk to manager
+ if FClientSocket.FChunkManager.AddChunk(ChunkHeader.TransferID, ChunkHeader.ChunkIndex, ChunkData) then
+ begin
+ // Only check completion if chunk was successfully added
+ if FClientSocket.FChunkManager.CompleteTransfer(ChunkHeader.TransferID, CompleteCmd, CompleteFlags, CompleteSequence, CompleteData) then
+ begin
+ // Transfer complete - fire OnCommand with reassembled data
+ if Assigned(FClientSocket.OnCommand) then
+ try
+ FClientSocket.OnCommand(FClientSocket,
+ FClientSocket.Line,
+ SenderAddr,
+ CompleteCmd,
+ CompleteData,
+ CompleteFlags,
+ CompleteSequence);
+ except
+ end;
+ end;
+ end;
+ end;
+ end;
+ // NOTE: LCP ONLY - No else clause for raw data
+ // Any non-protocol packets are silently ignored
+ end;
+ // NOTE: LCP ONLY - Packets too small for protocol headers are silently ignored
+ end;
+end;
+
+procedure TncUDPClientProcessor.ProcessEvent;
+begin
+ while (not Terminated) do
+ try
+ if FClientSocket.Line.Active then
+ begin
+ if ReadableAnySocket(FClientSocket.ReadSocketHandles, 100) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ if FClientSocket.EventsUseMainThread then
+ Synchronize(ProcessDatagram)
+ else
+ ProcessDatagram;
+ end;
+ end
+ else
+ Exit;
+ except
+ // Continue processing even after errors
+ end;
+end;
+
+{ TncChunkManager }
+
+constructor TncChunkManager.Create;
+begin
+ inherited Create;
+ FLock := TObject.Create;
+ FTransfers := TDictionary.Create;
+end;
+
+destructor TncChunkManager.Destroy;
+begin
+ FLock.Free;
+ FTransfers.Free;
+ inherited Destroy;
+end;
+
+function TncChunkManager.GenerateTransferID: UInt32;
+begin
+ // Simple transfer ID generation (timestamp + random)
+ Result := UInt32(GetTickCount) xor UInt32(Random(65536));
+end;
+
+procedure TncChunkManager.CleanupExpiredTransfers;
+var
+ Now: TDateTime;
+ TransferID: UInt32;
+ Transfer: TChunkTransfer;
+ ExpiredIDs: TArray;
+ I: Integer;
+begin
+ Now := System.SysUtils.Now;
+ SetLength(ExpiredIDs, 0);
+
+ // First pass: identify expired transfers
+ for Transfer in FTransfers.Values do
+ begin
+ if MilliSecondsBetween(Now, Transfer.LastActivity) > UDP_CHUNK_TIMEOUT then
+ begin
+ SetLength(ExpiredIDs, Length(ExpiredIDs) + 1);
+ ExpiredIDs[High(ExpiredIDs)] := Transfer.TransferID;
+ end;
+ end;
+
+ // Second pass: remove expired transfers
+ for I := 0 to High(ExpiredIDs) do
+ FTransfers.Remove(ExpiredIDs[I]);
+end;
+
+function TncChunkManager.StartTransfer(ACmd: Integer; AFlags: Byte; ASequence: UInt16; ATotalChunks: UInt16; AActualDataSize: UInt32): UInt32;
+var
+ Transfer: TChunkTransfer;
+ MaxDataSize: Integer;
+ BitArraySize: Integer;
+begin
+ TMonitor.Enter(FLock);
+ try
+ CleanupExpiredTransfers;
+
+ Transfer.TransferID := GenerateTransferID;
+ Transfer.OriginalCmd := ACmd;
+ Transfer.OriginalFlags := AFlags;
+ Transfer.OriginalSequence := ASequence;
+ Transfer.TotalChunks := ATotalChunks;
+ Transfer.FragmentsRemaining := ATotalChunks; // Initialize FragmentsRemaining
+ Transfer.LastActivity := System.SysUtils.Now;
+ Transfer.ActualDataSize := AActualDataSize; // Store the actual data size
+ Transfer.LastChunkSize := 0; // Will be set when last chunk is received
+
+ // Pre-allocate only maximum needed size (not over-allocate)
+ MaxDataSize := ATotalChunks * (UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader));
+ SetLength(Transfer.CompleteData, MaxDataSize);
+
+ // Calculate bit array size (32 fragments per UInt32)
+ BitArraySize := (ATotalChunks + 31) div 32;
+ SetLength(Transfer.Fragments, BitArraySize);
+ // Initialize all bits to 0
+ if BitArraySize > 0 then
+ FillChar(Transfer.Fragments[0], BitArraySize * SizeOf(UInt32), 0);
+
+ FTransfers.Add(Transfer.TransferID, Transfer);
+
+ Result := Transfer.TransferID;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+function TncChunkManager.CreateTransferFromChunk(ATransferID: UInt32; ATotalChunks: UInt16; AOriginalCmd: Integer; AOriginalFlags: Byte; AOriginalSequence: UInt16): Boolean;
+var
+ Transfer: TChunkTransfer;
+ MaxDataSize: Integer;
+ BitArraySize: Integer;
+begin
+ Result := False;
+ TMonitor.Enter(FLock);
+ try
+ // Check if transfer already exists
+ if FTransfers.TryGetValue(ATransferID, Transfer) then
+ begin
+ Result := True; // Already exists
+ Exit;
+ end;
+
+ // Create new transfer
+ Transfer.TransferID := ATransferID;
+ Transfer.OriginalCmd := AOriginalCmd;
+ Transfer.OriginalFlags := AOriginalFlags;
+ Transfer.OriginalSequence := AOriginalSequence;
+ Transfer.TotalChunks := ATotalChunks;
+ Transfer.FragmentsRemaining := ATotalChunks; // Initialize FragmentsRemaining
+ Transfer.LastActivity := System.SysUtils.Now;
+ Transfer.ActualDataSize := 0; // Will be calculated when all chunks received
+ Transfer.LastChunkSize := 0; // Will be set when last chunk is received
+
+ // Pre-allocate buffer for maximum possible data size
+ MaxDataSize := ATotalChunks * (UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader));
+ SetLength(Transfer.CompleteData, MaxDataSize);
+
+ // Calculate bit array size (32 fragments per UInt32)
+ BitArraySize := (ATotalChunks + 31) div 32;
+ SetLength(Transfer.Fragments, BitArraySize);
+ // Initialize all bits to 0
+ if BitArraySize > 0 then
+ FillChar(Transfer.Fragments[0], BitArraySize * SizeOf(UInt32), 0);
+
+ FTransfers.Add(Transfer.TransferID, Transfer);
+
+ Result := True;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+function TncChunkManager.AddChunk(ATransferID: UInt32; AChunkIndex: UInt16; const AChunkData: TBytes): Boolean;
+var
+ Transfer: TChunkTransfer;
+ ChunkOffset: Integer;
+ DataSize: Integer;
+ MaxChunkSize: Integer;
+begin
+ Result := False;
+ DataSize := Length(AChunkData);
+
+ // Quick validation before lock
+ if DataSize = 0 then Exit;
+
+ // Single lock operation only
+ TMonitor.Enter(FLock);
+ try
+ if FTransfers.TryGetValue(ATransferID, Transfer) then
+ begin
+ // Transfer exists - add chunk
+ if (AChunkIndex < Transfer.TotalChunks) and (not Transfer.IsFragmentReceived(AChunkIndex)) then
+ begin
+ // Calculate offset once and copy directly
+ MaxChunkSize := UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader);
+ ChunkOffset := AChunkIndex * MaxChunkSize;
+
+ // Direct memory operation
+ if ChunkOffset + DataSize <= Length(Transfer.CompleteData) then
+ begin
+ Move(AChunkData[0], Transfer.CompleteData[ChunkOffset], DataSize);
+
+ // Update tracking
+ Transfer.SetFragmentReceived(AChunkIndex);
+ Dec(Transfer.FragmentsRemaining);
+ Transfer.LastActivity := System.SysUtils.Now;
+
+ // Track last chunk size for accurate total calculation
+ if AChunkIndex = Transfer.TotalChunks - 1 then
+ Transfer.LastChunkSize := DataSize;
+
+ // If all chunks received, calculate actual data size
+ if Transfer.FragmentsRemaining = 0 then
+ Transfer.ActualDataSize := (Transfer.TotalChunks - 1) * MaxChunkSize + Transfer.LastChunkSize;
+
+ // Update the transfer back to dictionary once
+ FTransfers.AddOrSetValue(ATransferID, Transfer);
+ Result := True;
+ end;
+ end;
+ end;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+function TncChunkManager.CompleteTransfer(ATransferID: UInt32; out ACmd: Integer; out AFlags: Byte;
+ out ASequence: UInt16; out ACompleteData: TBytes): Boolean;
+var
+ Transfer: TChunkTransfer;
+begin
+ Result := False;
+ TMonitor.Enter(FLock);
+ try
+ if FTransfers.TryGetValue(ATransferID, Transfer) and (Transfer.FragmentsRemaining = 0) then
+ begin
+ // All chunks received - prepare output
+ ACmd := Transfer.OriginalCmd;
+ AFlags := Transfer.OriginalFlags;
+ ASequence := Transfer.OriginalSequence;
+
+ // Use the stored actual data size (from sender)
+ if Transfer.ActualDataSize > 0 then
+ begin
+ SetLength(ACompleteData, Transfer.ActualDataSize);
+ Move(Transfer.CompleteData[0], ACompleteData[0], Transfer.ActualDataSize);
+ end
+ else
+ SetLength(ACompleteData, 0);
+
+ // Remove completed transfer
+ FTransfers.Remove(ATransferID);
+ Result := True;
+ end;
+ finally
+ TMonitor.Exit(FLock);
+ end;
+end;
+
+{ TChunkTransfer - bitwise fragment tracking }
+
+function TChunkTransfer.IsFragmentReceived(FragmentIndex: UInt16): Boolean;
+begin
+ if FragmentIndex >= TotalChunks then
+ begin
+ Result := False;
+ Exit;
+ end;
+ // Bitwise check: (fragments[fragmentNumber / 32] & (1u << (fragmentNumber % 32))) == 0
+ Result := (Fragments[FragmentIndex div 32] and (UInt32(1) shl (FragmentIndex mod 32))) <> 0;
+end;
+
+procedure TChunkTransfer.SetFragmentReceived(FragmentIndex: UInt16);
+begin
+ if FragmentIndex < TotalChunks then
+ // Bitwise set: fragments[fragmentNumber / 32] |= (1u << (fragmentNumber % 32))
+ Fragments[FragmentIndex div 32] := Fragments[FragmentIndex div 32] or (UInt32(1) shl (FragmentIndex mod 32));
+end;
+
+{ TncCustomUDPServerLCP }
+
+constructor TncCustomUDPServerLCP.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ Line := CreateLineObject;
+
+ // Create Line with correct family
+ Line := CreateLineObject;
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ LineProcessor := TncUDPServerProcessor.Create(Self);
+ try
+ LineProcessor.Priority := FromNcThreadPriority(DefReaderThreadPriority);
+ except
+ // Some Android devices do not like this
+ end;
+end;
+
+destructor TncCustomUDPServerLCP.Destroy;
+begin
+ Active := False;
+
+ LineProcessor.Terminate;
+ LineProcessor.WakeupEvent.SetEvent;
+ LineProcessor.WaitFor;
+ LineProcessor.Free;
+
+ Line.Free;
+
+ inherited Destroy;
+end;
+
+function TncCustomUDPServerLCP.GetLine: TncLine;
+begin
+ Result := Line;
+end;
+
+function TncCustomUDPServerLCP.GetActive: Boolean;
+begin
+ Result := Line.Active;
+end;
+
+procedure TncCustomUDPServerLCP.DoActivate(aActivate: Boolean);
+begin
+ if aActivate = GetActive then
+ Exit;
+
+ if aActivate then
+ begin
+
+ // Verify family setting before creating handle
+ if Line.Family <> FFamily then
+ begin
+ TncLineInternal(Line).SetFamily(FFamily);
+ end;
+
+ // CreateServerHandle will bind to all interfaces (0.0.0.0)
+ // through the AI_PASSIVE flag in ncLines.CreateServerHandle
+ TncLineInternal(Line).CreateServerHandle(FPort);
+
+ // Enable broadcast if needed
+ if Broadcast then
+ TncLineInternal(Line).EnableBroadcast;
+
+ // Set socket buffer sizes for better performance
+ try
+ TncLineInternal(Line).SetReceiveSize(ReadBufferLen);
+ TncLineInternal(Line).SetWriteSize(ReadBufferLen);
+ except
+ // Ignore buffer size errors
+ end;
+
+ SetLength(ReadSocketHandles, 1);
+ ReadSocketHandles[0] := Line.Handle;
+
+ if UseReaderThread then
+ begin
+ LineProcessor.WaitForReady;
+ LineProcessor.Run;
+ end;
+ end
+ else
+ begin
+ TncLineInternal(Line).DestroyHandle;
+ SetLength(ReadSocketHandles, 0);
+ end;
+end;
+
+// 1. Base SendTo that does the actual sending
+procedure TncCustomUDPServerLCP.SendTo(const aBuf; aBufSize: Integer; const DestAddr: TSockAddrStorage);
+var
+ AddrLen: Integer;
+ {$IFDEF MSWINDOWS}
+ BytesSent: Integer;
+ {$ELSE}
+ BytesSent: ssize_t;
+ {$ENDIF}
+ DestIP: string;
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+ try
+ // Get destination address for logging/error reporting
+ DestIP := TncIPUtils.GetIPFromStorage(DestAddr);
+ // Set proper address length based on family
+ case DestAddr.ss_family of
+ AF_INET: AddrLen := SizeOf(TSockAddr);
+ AF_INET6: AddrLen := SizeOf(TSockAddrIn6);
+ else
+ AddrLen := SizeOf(TSockAddrStorage);
+ end;
+ {$IFDEF MSWINDOWS}
+ BytesSent := Winapi.Winsock2.sendto(Line.Handle, aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent = SOCKET_ERROR then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(WSAGetLastError)]);
+ {$ELSE}
+ BytesSent := Posix.SysSocket.sendto(Line.Handle, @aBuf, aBufSize, 0,
+ Psockaddr(@DestAddr), AddrLen);
+ if BytesSent < 0 then
+ raise Exception.CreateFmt('Failed to send to %s: %s',
+ [DestIP, SysErrorMessage(GetLastError)]);
+ {$ENDIF}
+ except
+ on E: EIPError do
+ raise Exception.Create('Invalid destination address: ' + E.Message);
+ end;
+end;
+
+// 2. SendTo for byte arrays
+procedure TncCustomUDPServerLCP.SendTo(const aBytes: TBytes; const DestAddr: TSockAddrStorage);
+begin
+ if Length(aBytes) > 0 then
+ SendTo(aBytes[0], Length(aBytes), DestAddr);
+end;
+
+// 3. SendTo for strings
+procedure TncCustomUDPServerLCP.SendTo(const aStr: string; const DestAddr: TSockAddrStorage);
+var
+ bytes: TBytes;
+ len: Integer;
+begin
+ bytes := BytesOf(aStr);
+ len := Length(bytes);
+ if len > 0 then
+ SendTo(bytes[0], len, DestAddr);
+end;
+
+// UDP Command Protocol Methods for TncCustomUDPServerLCP
+
+procedure TncCustomUDPServerLCP.SendCommand(const DestAddr: TSockAddrStorage; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ HeaderSize, DataSize, TotalSize: Integer;
+
+ // For normal sending
+ Packet: TBytes;
+ PacketHeader: TUdpCommandPacket;
+
+ // For chunking
+ ChunkHeader: TUdpChunkHeader;
+ ChunkPacket: TBytes;
+ TransferID: UInt32;
+ TotalChunks: UInt16;
+ ChunkIndex: UInt16;
+ CurrentPos: Integer;
+ ChunkDataSize: Integer;
+ MaxChunkDataSize: Integer;
+
+begin
+ if not Active then
+ raise EPropertySetError.Create(ECannotSendWhileSocketInactiveStr);
+
+ // Calculate total command packet size
+ HeaderSize := SizeOf(TUdpCommandPacket);
+ DataSize := Length(aData);
+ TotalSize := HeaderSize + DataSize;
+
+ // Check if auto-chunking is needed
+ if TotalSize <= UDP_MAX_SAFE_PAYLOAD then
+ begin
+ // ===============================================
+ // NORMAL SEND - Single packet
+ // ===============================================
+ PacketHeader.Magic := UDP_COMMAND_MAGIC;
+ PacketHeader.Header.Cmd := aCmd;
+ PacketHeader.Header.Flags := aFlags;
+ PacketHeader.Header.Sequence := aSequence;
+
+ SetLength(Packet, TotalSize);
+ Move(PacketHeader, Packet[0], HeaderSize);
+ if DataSize > 0 then
+ Move(aData[0], Packet[HeaderSize], DataSize);
+
+ SendTo(Packet, DestAddr);
+ end
+ else
+ begin
+ // ===============================================
+ // AUTO-CHUNKING - Multiple packets
+ // ===============================================
+
+ MaxChunkDataSize := UDP_MAX_SAFE_PAYLOAD - SizeOf(TUdpChunkHeader);
+ TotalChunks := (DataSize + MaxChunkDataSize - 1) div MaxChunkDataSize;
+ TransferID := FChunkManager.StartTransfer(aCmd, aFlags, aSequence, TotalChunks, DataSize);
+
+ // Immediate packet sending for maximum speed
+ SetLength(ChunkPacket, UDP_MAX_SAFE_PAYLOAD);
+
+ ChunkHeader.Magic := UDP_CHUNK_MAGIC;
+ ChunkHeader.TransferID := TransferID;
+ ChunkHeader.TotalChunks := TotalChunks;
+ ChunkHeader.OriginalCmd := aCmd;
+ ChunkHeader.OriginalFlags := aFlags;
+ ChunkHeader.OriginalSequence := aSequence;
+
+ CurrentPos := 0;
+
+ // Send packets immediately without preparation overhead
+ for ChunkIndex := 0 to TotalChunks - 1 do
+ begin
+ ChunkDataSize := MaxChunkDataSize;
+ if ChunkIndex = TotalChunks - 1 then
+ ChunkDataSize := DataSize - CurrentPos;
+
+ ChunkHeader.ChunkIndex := ChunkIndex;
+
+ // Build and send packet immediately (zero overhead)
+ Move(ChunkHeader, ChunkPacket[0], SizeOf(TUdpChunkHeader));
+ if ChunkDataSize > 0 then
+ Move(aData[CurrentPos], ChunkPacket[SizeOf(TUdpChunkHeader)], ChunkDataSize);
+
+ // Send immediately at maximum speed (no delays, no burst preparation)
+ SendTo(ChunkPacket[0], SizeOf(TUdpChunkHeader) + ChunkDataSize, DestAddr);
+
+ Inc(CurrentPos, ChunkDataSize);
+ end;
+ end;
+end;
+
+procedure TncCustomUDPServerLCP.SendCommand(const aRemoteHost: string; aRemotePort: Integer; aCmd: Integer; const aData: TBytes; aFlags: Byte; aSequence: UInt16);
+var
+ storage: TSockAddrStorage;
+ addrV4: PSockAddrIn;
+ addrV6: PSockAddrIn6;
+begin
+ // IPv6 broadcast validation
+ if (Family = afIPv6) and Broadcast then
+ raise Exception.Create('Broadcast is not supported in IPv6. Use multicast instead.');
+
+ // Build destination address based on family
+ case Family of
+ afIPv4:
+ begin
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET;
+
+ addrV4 := PSockAddrIn(@storage);
+ addrV4^.sin_family := AF_INET;
+ addrV4^.sin_port := htons(aRemotePort);
+
+ var addr := inet_addr(PAnsiChar(AnsiString(aRemoteHost)));
+ if addr <> INADDR_NONE then
+ addrV4^.sin_addr.S_addr := addr
+ else
+ raise Exception.Create('Invalid IPv4 address format');
+
+ SendCommand(storage, aCmd, aData, aFlags, aSequence);
+ end;
+
+ afIPv6:
+ begin
+ if not TncIPUtils.IsIPv6ValidAddress(aRemoteHost) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ FillChar(storage, SizeOf(storage), 0);
+ storage.ss_family := AF_INET6;
+
+ addrV6 := PSockAddrIn6(@storage);
+ addrV6^.sin6_family := AF_INET6;
+ addrV6^.sin6_port := htons(aRemotePort);
+
+ // Handle link-local address with scope ID
+ if TncIPUtils.IsLinkLocal(aRemoteHost) then
+ begin
+ var scopePos := Pos('%', aRemoteHost);
+ if scopePos > 0 then
+ begin
+ var hostAddr := Copy(aRemoteHost, 1, scopePos - 1);
+ var scope := Copy(aRemoteHost, scopePos + 1, Length(aRemoteHost));
+ var scopeID: Cardinal;
+ if TryStrToUInt(scope, scopeID) then
+ begin
+ addrV6^.sin6_scope_id := scopeID;
+ if not TncIPUtils.StringToAddress(hostAddr, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else
+ raise Exception.Create('Invalid IPv6 scope ID');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+ end
+ else if not TncIPUtils.StringToAddress(aRemoteHost, addrV6^.sin6_addr) then
+ raise Exception.Create('Invalid IPv6 address format');
+
+ SendCommand(storage, aCmd, aData, aFlags, aSequence);
+ end;
+ end;
+end;
+
+function TncCustomUDPServerLCP.Receive(aTimeout: Cardinal = 2000): TBytes;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ SenderIP: string;
+begin
+ if UseReaderThread then
+ raise Exception.Create(ECannotReceiveIfUseReaderThreadStr);
+
+ Active := True;
+
+ if not ReadableAnySocket([Line.Handle], aTimeout) then
+ begin
+ SetLength(Result, 0);
+ Exit;
+ end;
+
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(Line.Handle, ReadBuf[0], Length(ReadBuf), 0,
+ PSockAddr(@SenderAddr)^, SenderAddrLen);
+
+ try
+ if BufRead > 0 then
+ begin
+ // Get sender IP for logging if needed
+ SenderIP := TncIPUtils.GetIPFromStorage(SenderAddr);
+ Result := Copy(ReadBuf, 0, BufRead);
+ end
+ else if BufRead = 0 then
+ begin
+ SetLength(Result, 0);
+ // Optional: raise Exception.Create('Connection closed by peer');
+ end
+ else
+ begin
+ SetLength(Result, 0);
+ {$IFDEF MSWINDOWS}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(WSAGetLastError));
+ {$ELSE}
+ raise Exception.Create('Receive error: ' + SysErrorMessage(GetLastError));
+ {$ENDIF}
+ end;
+ except
+ on E: EIPError do
+ begin
+ SetLength(Result, 0);
+ raise Exception.Create('Invalid sender address: ' + E.Message);
+ end;
+ end;
+end;
+
+{ TncUDPServerProcessor }
+
+constructor TncUDPServerProcessor.Create(aServerSocket: TncCustomUDPServerLCP);
+begin
+ FServerSocket := aServerSocket;
+ ReadySocketsChanged := False;
+ inherited Create;
+end;
+
+
+procedure TncUDPServerProcessor.ProcessDatagram;
+var
+ BufRead: Integer;
+ SenderAddr: TSockAddrStorage;
+ SenderAddrLen: Integer;
+ Magic: UInt16;
+ CommandHeader: TUdpCommandHeader;
+ CommandData: TBytes;
+ PacketSize: Integer;
+
+ // For chunk handling
+ ChunkHeader: TUdpChunkHeader;
+ ChunkData: TBytes;
+ CompleteCmd: Integer;
+ CompleteFlags: Byte;
+ CompleteSequence: UInt16;
+ CompleteData: TBytes;
+begin
+ SenderAddrLen := SizeOf(TSockAddrStorage);
+ FillChar(SenderAddr, SenderAddrLen, 0);
+
+ BufRead := recvfrom(FServerSocket.Line.Handle,
+ FServerSocket.ReadBuf[0],
+ Length(FServerSocket.ReadBuf),
+ 0,
+ PSockAddr(@SenderAddr)^,
+ SenderAddrLen);
+
+ if BufRead > 0 then
+ begin
+ // Check minimum size for any structured packet
+ if (BufRead >= SizeOf(UInt16)) then
+ begin
+ // Extract magic number to check protocol type
+ Move(FServerSocket.ReadBuf[0], Magic, SizeOf(Magic));
+
+ if Magic = UDP_COMMAND_MAGIC then
+ begin
+ // ===============================================
+ // NORMAL COMMAND PACKET
+ // ===============================================
+ if BufRead >= SizeOf(TUdpCommandPacket) then
+ begin
+ Move(FServerSocket.ReadBuf[SizeOf(UInt16)], CommandHeader, SizeOf(CommandHeader));
+
+ PacketSize := SizeOf(TUdpCommandPacket);
+ if BufRead > PacketSize then
+ begin
+ SetLength(CommandData, BufRead - PacketSize);
+ Move(FServerSocket.ReadBuf[PacketSize], CommandData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(CommandData, 0);
+
+ if Assigned(FServerSocket.OnCommand) then
+ try
+ FServerSocket.OnCommand(FServerSocket,
+ FServerSocket.Line,
+ SenderAddr,
+ CommandHeader.Cmd,
+ CommandData,
+ CommandHeader.Flags,
+ CommandHeader.Sequence);
+ except
+ end;
+ end;
+ end
+ else if Magic = UDP_CHUNK_MAGIC then
+ begin
+ // ===============================================
+ // CHUNK PACKET - Auto-reassembly
+ // ===============================================
+
+ if BufRead >= SizeOf(TUdpChunkHeader) then
+ begin
+ // Direct header access
+ Move(FServerSocket.ReadBuf[0], ChunkHeader, SizeOf(ChunkHeader));
+
+ // Direct chunk data extraction
+ PacketSize := SizeOf(TUdpChunkHeader);
+ if BufRead > PacketSize then
+ begin
+ // Use buffer slice directly instead of copying
+ SetLength(ChunkData, BufRead - PacketSize);
+ Move(FServerSocket.ReadBuf[PacketSize], ChunkData[0], BufRead - PacketSize);
+ end
+ else
+ SetLength(ChunkData, 0);
+
+ // Ensure transfer exists (create if first chunk)
+ FServerSocket.FChunkManager.CreateTransferFromChunk(ChunkHeader.TransferID, ChunkHeader.TotalChunks,
+ ChunkHeader.OriginalCmd, ChunkHeader.OriginalFlags, ChunkHeader.OriginalSequence);
+
+ // Add chunk to manager
+ if FServerSocket.FChunkManager.AddChunk(ChunkHeader.TransferID, ChunkHeader.ChunkIndex, ChunkData) then
+ begin
+ // Only check completion if chunk was successfully added
+ if FServerSocket.FChunkManager.CompleteTransfer(ChunkHeader.TransferID, CompleteCmd, CompleteFlags, CompleteSequence, CompleteData) then
+ begin
+ // Transfer complete - fire OnCommand with reassembled data
+ if Assigned(FServerSocket.OnCommand) then
+ try
+ FServerSocket.OnCommand(FServerSocket,
+ FServerSocket.Line,
+ SenderAddr,
+ CompleteCmd,
+ CompleteData,
+ CompleteFlags,
+ CompleteSequence);
+ except
+ end;
+ end;
+ end;
+ end;
+ end;
+ // NOTE: LCP ONLY - No else clause for raw data
+ // Any non-protocol packets are silently ignored
+ end;
+ // NOTE: LCP ONLY - Packets too small for protocol headers are silently ignored
+ end;
+end;
+
+procedure TncUDPServerProcessor.ProcessEvent;
+begin
+ if FServerSocket.EventsUseMainThread then
+ while FServerSocket.Active and (not Terminated) do
+ try
+ if ReadableAnySocket(FServerSocket.ReadSocketHandles, 500) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ Synchronize(ProcessDatagram);
+ end;
+ except
+ end
+ else
+ while FServerSocket.Active and (not Terminated) do
+ try
+ if ReadableAnySocket(FServerSocket.ReadSocketHandles, 500) then
+ begin
+ if ReadySocketsChanged then
+ begin
+ ReadySocketsChanged := False;
+ Continue;
+ end;
+ ProcessDatagram;
+ end;
+ except
+ end;
+end;
+
+end.
\ No newline at end of file